perses-code-review

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Perses Code Review

Perses代码审查

Review code changes in Perses repositories for domain-specific patterns, API conventions, plugin system compliance, and dashboard correctness. This is not a general-purpose code reviewer — it enforces Perses-specific invariants across Go backend, React frontend, CUE schemas, and dashboard definitions.
审查Perses代码仓库中的代码变更,确保其符合领域特定模式、API规范、插件系统合规性以及仪表板正确性。这不是通用代码审查工具——它会针对Go后端、React前端、CUE模式和仪表板定义,强制执行Perses特有的约束规则。

Operator Context

技能执行上下文

This skill operates as a Perses-domain code reviewer. It understands the project layout (
/cmd
,
/pkg
,
/internal
), the plugin system (
@perses-dev/*
), CUE schema conventions, and dashboard definition structure. It dispatches sub-reviewers per file type and aggregates findings.
本技能作为Perses领域专属的代码审查工具运行。它了解项目布局(
/cmd
/pkg
/internal
)、插件系统(
@perses-dev/*
)、CUE模式规范以及仪表板定义结构。它会根据文件类型分配对应的子审查器,并汇总审查结果。

Hardcoded Behaviors (Always Apply)

硬编码行为(始终适用)

  • Perses-specific focus: Review against Perses patterns, not generic Go/React/CUE style guides. A passing
    golangci-lint
    does not mean the code follows Perses conventions.
  • CUE schema validation: Every CUE schema must be in
    package model
    , use
    close({})
    for specs, and include a JSON example alongside the schema definition.
  • Dashboard definition validation: Validate
    $ref
    panel references resolve, variable chains are acyclic, and datasource scopes (
    global
    ,
    project
    ,
    dashboard
    ) are correct.
  • Project-scoped API compliance: All CRUD API handlers must be project-scoped at
    /api/v1/projects/{project}/...
    unless the resource is explicitly global (e.g.,
    GlobalDatasource
    ,
    GlobalSecret
    ).
  • percli lint gate: Run
    percli lint
    on any dashboard JSON/YAML definitions touched in the PR. Lint failures are blockers.
  • Perses专属聚焦:仅依据Perses模式进行审查,而非通用的Go/React/CUE风格指南。即使
    golangci-lint
    检查通过,也不代表代码符合Perses规范。
  • CUE模式验证:所有CUE模式必须声明为
    package model
    ,规格定义需使用
    close({})
    ,且模式文件旁必须附带JSON示例。
  • 仪表板定义验证:验证
    $ref
    面板引用是否可解析、变量链是否无环,以及数据源范围(
    global
    project
    dashboard
    )是否正确。
  • 项目范围API合规性:所有CRUD API处理器必须以
    /api/v1/projects/{project}/...
    为项目范围,除非资源明确为全局资源(如
    GlobalDatasource
    GlobalSecret
    )。
  • percli lint关卡:对PR中修改的所有仪表板JSON/YAML定义运行
    percli lint
    。Lint失败将作为阻塞问题处理。

Default Behaviors (ON unless disabled)

默认行为(默认开启,可关闭)

  • Multi-domain dispatch: Route
    .go
    files to Go sub-reviewer,
    .tsx
    /
    .ts
    to React sub-reviewer,
    .cue
    to CUE sub-reviewer, dashboard JSON/YAML to dashboard sub-reviewer.
  • Cross-domain correlation: When a PR touches both CUE schemas and plugin code, verify the schema changes match the plugin's expected input/output types.
  • Storage interface check: Verify new resources implement the storage interface (
    dao.go
    ) with all required CRUD methods including
    List
    with pagination support.
  • 多领域分配:将
    .go
    文件路由至Go子审查器,
    .tsx
    /
    .ts
    文件路由至React子审查器,
    .cue
    文件路由至CUE子审查器,仪表板JSON/YAML文件路由至仪表板子审查器。
  • 跨领域关联检查:当PR同时修改CUE模式和插件代码时,验证模式变更是否与插件的预期输入/输出类型匹配。
  • 存储接口检查:验证新资源是否实现了存储接口(
    dao.go
    ),并包含所有必需的CRUD方法,包括支持分页的
    List
    方法。

Optional Behaviors (OFF unless enabled)

可选行为(默认关闭,需开启)

  • Migration review: Check
    migrate/migrate.cue
    for backward-compatible schema evolution when CUE schemas change.
  • E2E test coverage: Verify that new API endpoints have corresponding E2E tests in the test suite.
  • Performance review: Flag N+1 queries in storage implementations and unbounded list operations.
  • 迁移审查:当CUE模式变更时,检查
    migrate/migrate.cue
    是否包含向后兼容的模式演进方案。
  • E2E测试覆盖:验证新API端点在测试套件中是否有对应的E2E测试。
  • 性能审查:标记存储实现中的N+1查询以及无边界列表操作。

What This Skill CAN Do

本技能可执行的操作

  • Review Go backend code for Perses API patterns, storage interface compliance, and auth middleware usage
  • Review React frontend code for
    @perses-dev/plugin-system
    hook usage and component conventions
  • Review CUE schemas for
    package model
    compliance, closed specs, and JSON examples
  • Validate dashboard definitions for panel references, variable chains, and datasource scoping
  • Run
    percli lint
    on dashboard definitions and report failures
  • Correlate cross-domain changes (schema + plugin, API + frontend)
  • 审查Go后端代码是否符合Perses API模式、存储接口合规性以及认证中间件使用规范
  • 审查React前端代码是否正确使用
    @perses-dev/plugin-system
    钩子和组件规范
  • 审查CUE模式是否符合
    package model
    要求、闭合规格定义以及是否附带JSON示例
  • 验证仪表板定义的面板引用、变量链和数据源范围是否正确
  • 对仪表板定义运行
    percli lint
    并报告失败结果
  • 关联跨领域变更(模式+插件、API+前端)

What This Skill CANNOT Do

本技能不可执行的操作

  • Deploy Perses instances (use
    perses-deploy
    )
  • Create dashboards from scratch (use
    perses-dashboard-create
    )
  • Develop new plugins (use
    perses-plugin-create
    )
  • Perform general Go or React code review without Perses context (use
    golang-general-engineer
    or
    typescript-frontend-engineer
    )
  • Run the full Perses test suite (use CI/CD)

  • 部署Perses实例(请使用
    perses-deploy
  • 从头创建仪表板(请使用
    perses-dashboard-create
  • 开发新插件(请使用
    perses-plugin-create
  • 在无Perses上下文的情况下执行通用Go或React代码审查(请使用
    golang-general-engineer
    typescript-frontend-engineer
  • 运行完整的Perses测试套件(请使用CI/CD)

Error Handling

错误处理

CauseSymptomSolution
Go API handler doesn't follow Perses CRUD patternsMissing pagination on
List
endpoint, wrong HTTP status codes (e.g., 200 instead of 201 on create), no project-scoping
Flag as blocker. Perses
List
handlers must accept
?page=N&size=M
query params and return paginated results. Create returns 201, Update returns 200, Delete returns 204. All non-global resources must be under
/api/v1/projects/{project}/
.
React component doesn't use
@perses-dev/plugin-system
hooks
Component uses raw
fetch()
or direct state for time range instead of
usePlugin
,
useTimeRange
,
useDataQueries
from the plugin system
Flag as blocker. Perses plugins MUST use the plugin system hooks to participate in the dashboard lifecycle (time range sync, variable interpolation, refresh). Direct data fetching bypasses the plugin contract.
CUE schema not in
package model
or spec not closed
Schema declares
package foo
instead of
package model
, uses open struct
{}
instead of
close({})
, no JSON example file alongside
Flag as blocker. All Perses CUE schemas must be
package model
to be discoverable by the schema registry. Specs must use
close({})
to prevent unexpected fields. A
_example.json
must accompany each schema for documentation and validation.
Dashboard definition has invalid
$ref
panel references
Layout references
$ref: #/spec/panels/myPanel
but panel key is
my-panel
or doesn't exist, causing render failures
Flag as blocker. Panel keys in
$ref
must exactly match keys in
spec.panels
. Run
percli lint
to catch these. Check for typos and naming convention mismatches (camelCase vs kebab-case).
Broken variable chains in dashboardVariable B depends on variable A via
$A
in its query, but A is defined after B in the variables list, or A doesn't exist
Flag as blocker. Variable evaluation order follows list order. Dependees must appear before dependents. Missing variables cause silent empty interpolation.
Wrong datasource scopeDashboard uses
datasource: {name: "prom"}
without specifying scope, or references a project datasource from a different project
Flag as warning. Datasources have three scopes:
global
(cluster-wide),
project
(project-level),
dashboard
(inline). The scope must be explicit. Cross-project references are invalid.

原因症状解决方案
Go API处理器未遵循Perses CRUD模式
List
端点缺少分页、HTTP状态码错误(如创建操作返回200而非201)、无项目范围限制
标记为阻塞问题。Perses的
List
处理器必须接受
?page=N&size=M
查询参数并返回分页结果。创建操作返回201,更新操作返回200,删除操作返回204。所有非全局资源必须置于
/api/v1/projects/{project}/
路径下。
React组件未使用
@perses-dev/plugin-system
钩子
组件使用原生
fetch()
或直接状态管理时间范围,而非插件系统提供的
usePlugin
useTimeRange
useDataQueries
标记为阻塞问题。Perses插件必须使用插件系统钩子以参与仪表板生命周期(时间范围同步、变量插值、刷新)。直接数据获取会违反插件契约。
CUE模式未声明为
package model
或规格未闭合
模式声明为
package foo
而非
package model
、使用开放结构体
{}
而非
close({})
、未附带JSON示例文件
标记为阻塞问题。所有Perses CUE模式必须声明为
package model
才能被模式注册表发现。规格定义必须使用
close({})
以防止意外字段。每个模式必须附带
_example.json
文件用于文档和验证。
仪表板定义中的
$ref
面板引用无效
布局引用
$ref: #/spec/panels/myPanel
但面板键为
my-panel
或不存在,导致渲染失败
标记为阻塞问题。
$ref
中的面板键必须与
spec.panels
中的键完全匹配。运行
percli lint
可捕获此类问题。检查拼写错误和命名规范不匹配(驼峰式 vs 短横线式)。
仪表板中的变量链断裂变量B通过查询中的
$A
依赖变量A,但A在变量列表中定义于B之后,或A不存在
标记为阻塞问题。变量评估顺序遵循列表顺序。被依赖的变量必须出现在依赖变量之前。缺失变量会导致静默的空插值。
数据源范围错误仪表板使用
datasource: {name: "prom"}
但未指定范围,或引用了其他项目的项目级数据源
标记为警告。数据源有三个范围:
global
(集群级)、
project
(项目级)、
dashboard
(内联)。范围必须明确。跨项目引用无效。

Anti-Patterns

反模式

1. Reviewing Perses code with a general Go/React reviewer

1. 使用通用Go/React审查工具审查Perses代码

Why it fails: A general Go reviewer will approve an API handler that returns a flat list without pagination, uses generic error responses, or doesn't enforce project-scoping. These are all Perses-specific requirements that generic linters and reviewers miss entirely. What to do instead: Always route through this skill when the changed code lives in a Perses repository.
失败原因:通用Go审查工具会批准未实现分页的API处理器、使用通用错误响应或未强制项目范围的代码。这些都是Perses特有的要求,通用检查器和审查工具完全无法识别。 正确做法:当变更代码位于Perses仓库时,始终通过本技能进行路由审查。

2. Not running
percli lint
on dashboard definitions in the PR

2. 未对PR中的仪表板定义运行
percli lint

Why it fails: Dashboard JSON can have structurally valid YAML/JSON but semantically broken panel references, invalid plugin kinds, or malformed variable expressions. Manual review catches some of these, but
percli lint
catches all of them deterministically. What to do instead: Run
percli lint
on every dashboard file changed in the PR. Treat lint failures as blockers.
失败原因:仪表板JSON可能结构上是有效的YAML/JSON,但存在语义上的面板引用错误、无效插件类型或格式错误的变量表达式。手动审查只能发现部分问题,而
percli lint
可以确定性地发现所有此类问题。 正确做法:对PR中修改的每个仪表板文件运行
percli lint
。将Lint失败视为阻塞问题。

3. Ignoring CUE schema changes when reviewing plugin PRs

3. 审查插件PR时忽略CUE模式变更

Why it fails: A plugin PR that adds new configuration options without updating the corresponding CUE schema means the schema registry is out of sync. Users will be able to set options in the UI that fail CUE validation, or the UI won't expose options that the backend accepts. What to do instead: When a plugin PR touches TypeScript types or Go structs, check that the corresponding
.cue
schema file is also updated and that the JSON example reflects the new fields.
失败原因:插件PR添加新配置选项但未更新对应的CUE模式,会导致模式注册表不同步。用户将能够在UI中设置会触发CUE验证失败的选项,或者UI不会展示后端接受的选项。 正确做法:当插件PR修改TypeScript类型或Go结构体时,检查对应的
.cue
模式文件是否也已更新,且JSON示例是否反映了新字段。

4. Approving storage implementations without pagination

4. 批准未实现分页的存储实现

Why it fails: Perses projects can contain hundreds of dashboards. A
List
endpoint that returns all results without pagination will cause memory issues and slow API responses at scale. The frontend
useListResource
hook expects paginated responses. What to do instead: Verify every
List
method in the storage layer accepts
page
and
size
parameters and returns a paginated response with total count.

失败原因:Perses项目可能包含数百个仪表板。无分页的
List
端点在规模扩大时会导致内存问题和缓慢的API响应。前端
useListResource
钩子期望分页响应。 正确做法:验证存储层中的每个
List
方法是否接受
page
size
参数,并返回包含总计数的分页响应。

Anti-Rationalization

错误辩解与真相

RationalizationRealityRequired Action
"It's just a small dashboard JSON change, no need to lint"Small JSON changes are where typos in
$ref
paths hide. A single wrong character breaks panel rendering silently.
Run
percli lint
. Always.
"The Go handler works, it just doesn't paginate yet""Yet" means never once it ships. Unpaginated list endpoints are tech debt that causes production incidents at scale.Block the PR until pagination is implemented.
"The CUE schema is fine without
close()
, it still validates"
Open schemas accept any field, defeating the purpose of schema validation. Users will send garbage fields that silently pass validation.Require
close({})
on all spec structs.
"This React component doesn't need
useTimeRange
, it manages its own time"
Components that manage their own time range break dashboard-level time sync. Users change the time picker and this panel doesn't update.Use
useTimeRange
from
@perses-dev/plugin-system
.
"The variable ordering doesn't matter, the engine resolves dependencies"The Perses variable engine evaluates in list order, not dependency order. Out-of-order variables produce empty interpolation with no error.Verify variable dependency order matches list order.

辩解理由实际情况要求操作
"这只是一个小的仪表板JSON变更,不需要Lint"小型JSON变更正是
$ref
路径拼写错误的隐藏之处。一个字符错误就会导致面板静默渲染失败。
必须运行
percli lint
,无一例外。
"Go处理器可以正常工作,只是还没实现分页""还没实现"意味着一旦发布就永远不会实现。无分页的列表端点是技术债务,会在规模扩大时导致生产事故。阻止PR,直到分页功能实现。
"CUE模式没有
close()
也没问题,仍然可以验证"
开放模式会接受任何字段,违背了模式验证的目的。用户将能够发送会静默通过验证的无效字段。要求所有规格结构体使用
close({})
"这个React组件不需要
useTimeRange
,它自己管理时间"
自行管理时间范围的组件会破坏仪表板级别的时间同步。用户更改时间选择器时,该面板不会更新。使用
@perses-dev/plugin-system
提供的
useTimeRange
"变量顺序无关紧要,引擎会解析依赖关系"Perses变量引擎按列表顺序评估,而非依赖顺序。顺序错误的变量会产生无错误的空插值。验证变量依赖顺序与列表顺序一致。

FORBIDDEN Patterns

禁止模式

These are hard stops. If encountered, block the PR immediately.
  • Hardcoded datasource URLs in dashboard definitions — Datasources must be referenced by name and scope, never by direct URL. Hardcoded URLs break when Perses is deployed in different environments.
  • package main
    in CUE schema files
    — CUE schemas must be
    package model
    . Using
    package main
    makes the schema invisible to the Perses schema registry.
  • Raw HTTP calls in plugin React components — Plugins must use the Perses plugin system (
    useDataQueries
    ,
    usePlugin
    ) for data fetching. Raw
    fetch()
    or
    axios
    calls bypass caching, auth token injection, and datasource proxy routing.
  • Global resource endpoints without admin auth middleware
    GlobalDatasource
    ,
    GlobalSecret
    , and
    GlobalVariable
    endpoints must enforce admin-level authorization. Missing auth middleware is a security vulnerability.
  • Dashboard definitions without a
    kind
    field
    — Every Perses resource must have a
    kind
    field. Dashboard definitions without
    kind: Dashboard
    will fail API validation on import.

这些是硬性禁止项。如果遇到,立即阻止PR。
  • 仪表板定义中硬编码数据源URL — 数据源必须通过名称和范围引用,绝不能直接使用URL。硬编码URL会导致Perses在不同环境部署时失效。
  • CUE模式文件中使用
    package main
    — CUE模式必须声明为
    package model
    。使用
    package main
    会导致模式对Perses模式注册表不可见。
  • 插件React组件中使用原生HTTP调用 — 插件必须使用Perses插件系统(
    useDataQueries
    usePlugin
    )进行数据获取。原生
    fetch()
    axios
    调用会绕过缓存、认证令牌注入和数据源代理路由。
  • 全局资源端点未添加管理员认证中间件
    GlobalDatasource
    GlobalSecret
    GlobalVariable
    端点必须强制执行管理员级别的授权。缺失认证中间件是安全漏洞。
  • 仪表板定义中缺少
    kind
    字段
    — 每个Perses资源必须有
    kind
    字段。缺少
    kind: Dashboard
    的仪表板定义在导入时会触发API验证失败。

Blocker Criteria

阻塞性问题判定标准

A finding is a blocker (must fix before merge) if any of these apply:
  1. percli lint
    fails on any dashboard definition in the PR
  2. CUE schema is not in
    package model
    or uses open structs for spec types
  3. API handler is missing project-scoping for a non-global resource
  4. Plugin component uses raw HTTP instead of plugin system hooks
  5. $ref
    panel references don't resolve to existing panel keys
  6. Variable dependency chain is circular or out of order
  7. Any FORBIDDEN pattern is present
A finding is a warning (should fix, not blocking) if:
  1. Missing JSON example alongside new CUE schema (documentation gap)
  2. Datasource scope is implicit rather than explicit
  3. Missing error handling for specific edge cases
  4. Test coverage gaps for new functionality

如果发现以下任何情况,该问题将被判定为阻塞性问题(必须在合并前修复):
  1. PR中任何仪表板定义的
    percli lint
    失败
  2. CUE模式未声明为
    package model
    或规格类型使用开放结构体
  3. API处理器对非全局资源未设置项目范围
  4. 插件组件使用原生HTTP调用而非插件系统钩子
  5. $ref
    面板引用无法解析为现有面板键
  6. 变量依赖链存在循环或顺序错误
  7. 存在任何禁止模式
如果发现以下情况,该问题将被判定为警告(建议修复,但不阻塞):
  1. 新CUE模式旁缺少JSON示例(文档缺口)
  2. 数据源范围隐式而非显式
  3. 特定边缘情况缺失错误处理
  4. 新功能的测试覆盖缺口

Instructions

操作步骤

Phase 1: CLASSIFY

阶段1:分类

Goal: Determine the review domains for this PR.
  1. List all changed files and categorize: Go backend (
    .go
    ), React frontend (
    .ts
    ,
    .tsx
    ), CUE schemas (
    .cue
    ), dashboard definitions (
    .json
    ,
    .yaml
    with
    kind: Dashboard
    )
  2. Identify cross-domain changes — does the PR touch both schema and plugin? Both API and frontend?
  3. Check for dashboard definition files that need
    percli lint
Gate: File classification complete. Domains identified.
目标:确定本次PR的审查领域。
  1. 列出所有变更文件并分类:Go后端(
    .go
    )、React前端(
    .ts
    .tsx
    )、CUE模式(
    .cue
    )、仪表板定义(
    .json
    .yaml
    且包含
    kind: Dashboard
  2. 识别跨领域变更 — PR是否同时修改了模式和插件?是否同时修改了API和前端?
  3. 检查是否有需要运行
    percli lint
    的仪表板定义文件
关卡:文件分类完成,领域已识别。

Phase 2: REVIEW

阶段2:审查

Goal: Apply Perses-specific review checks per domain.
Go backend (
/cmd
,
/pkg
,
/internal
):
  • API handlers at
    /api/v1/*
    follow RESTful CRUD with project scoping
  • Storage interfaces implement all required methods including paginated
    List
  • Auth middleware is applied to global resource endpoints
  • Error responses use Perses error types, not raw HTTP status codes
React frontend (
@perses-dev/*
packages):
  • Components use
    usePlugin
    ,
    useTimeRange
    ,
    useDataQueries
    from
    @perses-dev/plugin-system
  • No raw
    fetch()
    or
    axios
    calls in plugin components
  • Component props follow
    @perses-dev/dashboards
    type conventions
  • UI components use
    @perses-dev/components
    rather than raw MUI
CUE schemas:
  • Schema is
    package model
  • Spec structs use
    close({})
  • JSON example file exists alongside schema
  • If schema changed, check
    migrate/migrate.cue
    for migration path
Dashboard definitions:
  • Run
    percli lint
    on all dashboard files
  • Validate
    $ref
    panel references resolve
  • Check variable chains for circular dependencies and ordering
  • Verify datasource references use name + explicit scope
Gate: All domains reviewed. Findings collected.
目标:针对每个领域应用Perses特定的审查检查。
Go后端
/cmd
/pkg
/internal
):
  • /api/v1/*
    路径下的API处理器遵循RESTful CRUD并设置项目范围
  • 存储接口实现了所有必需的方法,包括分页
    List
    方法
  • 全局资源端点已应用认证中间件
  • 错误响应使用Perses错误类型,而非原生HTTP状态码
React前端
@perses-dev/*
包):
  • 组件使用
    @perses-dev/plugin-system
    提供的
    usePlugin
    useTimeRange
    useDataQueries
  • 插件组件中无原生
    fetch()
    axios
    调用
  • 组件属性遵循
    @perses-dev/dashboards
    类型规范
  • UI组件使用
    @perses-dev/components
    而非原生MUI
CUE模式
  • 模式声明为
    package model
  • 规格结构体使用
    close({})
  • 模式旁存在JSON示例文件
  • 如果模式已变更,检查
    migrate/migrate.cue
    是否包含迁移路径
仪表板定义
  • 对所有仪表板文件运行
    percli lint
  • 验证
    $ref
    面板引用是否可解析
  • 检查变量链是否存在循环依赖和顺序错误
  • 验证数据源引用是否使用名称+显式范围
关卡:所有领域审查完成,已收集审查结果。

Phase 3: REPORT

阶段3:报告

Goal: Deliver structured review findings.
Report format:
  1. Summary: One-line verdict (approve, request changes, blocker found)
  2. Blockers: Issues that must be fixed before merge (with file path and line)
  3. Warnings: Issues that should be fixed but are not blocking
  4. Notes: Observations and suggestions for improvement
  5. percli lint output: Raw output if dashboard definitions were linted
Gate: Review report delivered. Task complete.

目标:交付结构化的审查结果。
报告格式:
  1. 摘要:一行结论(批准、要求变更、发现阻塞问题)
  2. 阻塞性问题:必须在合并前修复的问题(包含文件路径和行号)
  3. 警告:建议修复但不阻塞的问题
  4. 说明:观察结果和改进建议
  5. percli lint输出:如果审查了仪表板定义,附上原始Lint输出
关卡:审查报告已交付,任务完成。

References

参考资料