sapcc-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSAPCC Comprehensive Code Review v1
SAPCC 全面代码审查 v1
10-agent domain-specialist review. Each agent masters one rule domain and scans every package for violations against the comprehensive patterns reference.
How this differs from /sapcc-audit: sapcc-audit segments by package (generalist per package). sapcc-review segments by rule domain (specialist per concern, cross-package). Both are useful; this one catches more because specialists find issues generalists miss.
由10个领域专家Agent执行审查。每个Agent精通一个规则领域,扫描所有包以检查是否违反综合模式参考规范。
与/sapcc-audit的区别:sapcc-audit按包划分(每个包由通用型Agent审查),而sapcc-review按规则领域划分(每个关注点由专家型Agent审查,跨包扫描)。两者各有用处;本工具能发现更多问题,因为专家型Agent能捕捉到通用型Agent遗漏的问题。
Operator Context
操作方上下文
Hardcoded Behaviors (Always Apply)
硬编码行为(始终生效)
- Domain-Scoped References: Each agent loads ONLY its domain-specific reference file (see Reference Loading Strategy). The essential rules are inline in each agent's dispatch prompt.
- Domain Specialist Model: Agents are assigned by rule domain (testing, errors, types, etc.), NOT by package. Each agent scans ALL packages for their domain's violations.
- Code-Level Findings Only: Every finding must include actual code from the repo and a concrete CORRECT version. Abstract suggestions are forbidden.
- Cite Rule Source: Every finding must cite the section number from sapcc-code-patterns.md (e.g., "§30.1: httptest.Handler migration").
- Directive Review Voice: Frame findings as the lead reviewer would state them in a PR comment. Use the project's established review phrases where applicable.
- Audit Only By Default: READ and REPORT. Do NOT modify code unless is specified.
--fix - Skip Generic Go: Do NOT report generic Go best practices. Only report patterns that are specifically sapcc/project-convention divergences.
- 领域范围参考资料:每个Agent仅加载其特定领域的参考文件(参见参考资料加载策略)。核心规则内联在每个Agent的调度提示中。
- 领域专家模型:Agent按规则领域(测试、错误处理、类型等)分配,而非按包分配。每个Agent扫描所有包以检查其领域内的违规情况。
- 仅包含代码层面的发现:每个发现必须包含仓库中的实际代码以及具体的正确版本。禁止抽象建议。
- 引用规则来源:每个发现必须引用sapcc-code-patterns.md中的章节编号(例如“§30.1: httptest.Handler迁移”)。
- 指令式审查语气:发现内容需以首席审查者在PR评论中的表述方式呈现。适用时使用项目既定的审查用语。
- 默认仅审计:仅读取并报告。除非指定参数,否则不得修改代码。
--fix - 跳过通用Go规范:不得报告通用Go最佳实践。仅报告与sapcc/项目约定存在差异的模式。
Default Behaviors (ON unless disabled)
默认行为(默认开启,可禁用)
- gopls MCP Integration: All review agents MUST use gopls MCP tools when available — at start,
go_workspacefor dependency analysis,go_file_contextfor cross-package impact tracing,go_symbol_referencesfor build verification. This gives type-aware analysis instead of text-only grep.go_diagnostics - Save Report: Write findings to in repo root
sapcc-review-report.md - Quick Wins Section: Identify the 5 easiest fixes with highest impact
- Cross-Repository Reinforcement: Weight findings higher when the violated rule appears in 4+ repos per §35
- gopls MCP集成:所有审查Agent在可用时必须使用gopls MCP工具——启动时使用,依赖分析使用
go_workspace,跨包影响追踪使用go_file_context,构建验证使用go_symbol_references。这提供了类型感知分析,而非纯文本 grep。go_diagnostics - 保存报告:将发现结果写入仓库根目录的文件
sapcc-review-report.md - 快速修复章节:识别5个最容易修复且影响最大的问题
- 跨仓库强化:当被违反的规则在4个以上仓库中出现时(参见§35),提高该发现的优先级
Optional Behaviors (OFF unless enabled)
可选行为(默认关闭,需启用)
- --fix: Create worktree, apply fixes, run tests, create branch
- --focus [package]: Audit only one package (runs 3 agents instead of 10)
- --severity [critical|high|medium|all]: Only report findings at or above severity
- --fix:创建工作树,应用修复,运行测试,创建分支
- --focus [package]:仅审计指定的一个包(仅运行3个Agent而非10个)
- --severity [critical|high|medium|all]:仅报告指定严重程度及以上的发现
Reference Loading Strategy
参考资料加载策略
Reference files live at (or globally).
skills/go-sapcc-conventions/references/~/.claude/skills/go-sapcc-conventions/references/Key change from v0: Agents load ONLY their domain-specific reference, NOT the full patterns file. The essential rules are already embedded in each agent's dispatch prompt below. Reference files provide supplementary depth.
Per-agent reference loading (included in each agent's dispatch prompt):
| Agent | Domain Reference to Load |
|---|---|
| 1 (Signatures/Config) | |
| 2 (Types/Option[T]) | |
| 3 (HTTP/API) | |
| 4 (Error Handling) | |
| 5 (Database/SQL) | (none — rules inline) |
| 6 (Testing) | |
| 7 (Pkg Org/Imports) | |
| 8 (Modern Go/Stdlib) | (none — rules inline) |
| 9 (Observability/Jobs) | (none — rules inline) |
| 10 (Anti-Patterns/LLM) | |
Optional deep-dive (load only when findings need calibration):
- — Comprehensive 36-section reference. Only load specific sections, not the entire file.
sapcc-code-patterns.md - — Review severity calibration
pr-mining-insights.md - — Approved/forbidden dependency table
library-reference.md
Anti-pattern: Loading ALL reference files into EVERY agent wastes context and dilutes focus. Each agent should load only what it needs.
参考文件位于(或全局路径)。
skills/go-sapcc-conventions/references/~/.claude/skills/go-sapcc-conventions/references/与v0版本的关键变化:Agent仅加载其特定领域的参考资料,而非完整的模式文件。核心规则已嵌入下方每个Agent的调度提示中。参考文件提供补充性的深度内容。
每个Agent的参考资料加载(包含在每个Agent的调度提示中):
| Agent | 需加载的领域参考资料 |
|---|---|
| 1(签名/配置) | |
| 2(类型/Option[T]) | |
| 3(HTTP/API) | |
| 4(错误处理) | |
| 5(数据库/SQL) | 无——规则内联 |
| 6(测试) | |
| 7(包组织/导入) | |
| 8(现代Go/标准库) | 无——规则内联 |
| 9(可观测性/任务) | 无——规则内联 |
| 10(反模式/LLM) | |
可选深度调研(仅在需要校准发现结果时加载):
- — 包含36个章节的综合参考资料。仅加载特定章节,而非整个文件。
sapcc-code-patterns.md - — 审查严重程度校准参考
pr-mining-insights.md - — 已批准/禁用的依赖表
library-reference.md
反模式:将所有参考文件加载到每个Agent中会浪费上下文并分散注意力。每个Agent应仅加载其所需的内容。
Instructions
操作步骤
Phase 1: DISCOVER
阶段1:发现
Goal: Map the repository, verify it's an sapcc project, plan the review.
Step 1: Verify sapcc project
bash
cat go.mod | head -5
grep -c "sapcc" go.modIf the module path doesn't contain "sapcc" AND go.mod doesn't import any sapcc packages, warn the user but continue (they may want to check a non-sapcc repo against the project's standards).
Step 2: Map all Go packages and files
bash
undefined目标:映射仓库结构,验证其为sapcc项目,规划审查流程。
步骤1:验证sapcc项目
bash
cat go.mod | head -5
grep -c "sapcc" go.mod如果模块路径不包含"sapcc"且go.mod未导入任何sapcc包,需向用户发出警告但继续执行(用户可能希望针对非sapcc仓库检查项目标准)。
步骤2:映射所有Go包和文件
bash
undefinedCount .go files (excluding vendor)
统计.go文件数量(排除vendor目录)
find . -name ".go" -not -path "/vendor/*" | wc -l
find . -name ".go" -not -path "/vendor/*" | wc -l
List packages with file counts
列出包及对应的文件数量
find . -name ".go" -not -path "/vendor/" | sed 's|/[^/]$||' | sort | uniq -c | sort -rn
find . -name ".go" -not -path "/vendor/" | sed 's|/[^/]$||' | sort | uniq -c | sort -rn
Check for test files separately
单独统计测试文件数量
find . -name "_test.go" -not -path "/vendor/*" | wc -l
**Step 3: Check for key imports** (determines which rules are most relevant)
```bash
grep -r "go-bits" go.mod # Uses go-bits?
grep -r "go-api-declarations" go.mod # Uses API declarations?
grep -r "gophercloud" go.mod # Uses OpenStack?
grep -r "gorilla/mux" go.mod # HTTP routing?
grep -r "database/sql" go.mod # Database?Step 4: Create task_plan.md
markdown
undefinedfind . -name "_test.go" -not -path "/vendor/*" | wc -l
**步骤3:检查关键导入**(确定哪些规则最相关)
```bash
grep -r "go-bits" go.mod # 是否使用go-bits?
grep -r "go-api-declarations" go.mod # 是否使用API声明?
grep -r "gophercloud" go.mod # 是否使用OpenStack?
grep -r "gorilla/mux" go.mod # 是否使用HTTP路由?
grep -r "database/sql" go.mod # 是否使用数据库?步骤4:创建task_plan.md
markdown
undefinedTask Plan: SAPCC Review — [repo name]
任务计划:SAPCC审查 — [仓库名称]
Goal
目标
Comprehensive code review of [repo] against project standards, dispatching 10 domain-specialist agents.
针对[仓库]进行全面代码审查,符合项目标准,调度10个领域专家Agent。
Phases
阶段
- Phase 1: Discover repo structure
- Phase 2: Dispatch 10 specialist agents
- Phase 3: Aggregate findings
- Phase 4: Write report
- 阶段1:发现仓库结构
- 阶段2:调度10个专家Agent
- 阶段3:汇总发现结果
- 阶段4:撰写报告
Repo Profile
仓库概况
- Module: [module path]
- Packages: [N]
- Go files: [M] (excluding vendor)
- Test files: [T]
- Key imports: [list]
- 模块:[模块路径]
- 包数量:[N]
- Go文件数量:[M](排除vendor)
- 测试文件数量:[T]
- 关键导入:[列表]
Status
状态
Currently in Phase 2 - Dispatching agents
**Gate**: Repo mapped, plan created. Proceed to Phase 2.
---当前处于阶段2 - 正在调度Agent
**检查点**:已完成仓库映射和计划创建。进入阶段2。
---Phase 2: DISPATCH
阶段2:调度
Goal: Launch 10 domain-specialist agents in a SINGLE message for true parallel execution.
CRITICAL: All 10 agents must be dispatched in ONE message using the Agent tool. Do NOT serialize them.
Each agent receives:
- The path to sapcc-code-patterns.md to read
- Their assigned sections to focus on
- Their domain-specific reference file(s) to read
- Instructions to scan ALL .go files in the repo
- The exact output format for findings
All agents share this preamble (include in each prompt):
REFERENCE FILES TO READ FIRST (mandatory):
1. Read ~/.claude/skills/go-sapcc-conventions/references/sapcc-code-patterns.md
(Focus on sections listed below, but skim all for context)
2. Read [domain-specific reference file]
REPO TO REVIEW: [current working directory]
SCAN METHOD:
- Use Glob to find all .go files: **/*.go (excluding vendor/)
- Use Read to examine each file
- Use Grep to search for specific patterns across all files
OUTPUT FORMAT for each finding:目标:在单个消息中启动10个领域专家Agent,实现真正的并行执行。
关键要求:必须使用Agent工具在单个消息中调度所有10个Agent。不得串行执行。
每个Agent将收到:
- sapcc-code-patterns.md的读取路径
- 需重点关注的指定章节
- 需读取的特定领域参考文件
- 扫描仓库中所有.go文件的指令
- 发现结果的精确输出格式
所有Agent共享以下前置内容(包含在每个提示中):
需优先读取的参考文件(必填):
1. 读取~/.claude/skills/go-sapcc-conventions/references/sapcc-code-patterns.md
(重点关注以下列出的章节,但需通读全文以获取上下文)
2. 读取[特定领域参考文件]
待审查的仓库:[当前工作目录]
扫描方法:
- 使用Glob查找所有.go文件:**/*.go(排除vendor/目录)
- 使用Read检查每个文件
- 使用Grep在所有文件中搜索特定模式
每个发现结果的输出格式:[CRITICAL|HIGH|MEDIUM|LOW]: [One-line summary]
[CRITICAL|HIGH|MEDIUM|LOW]: [单行摘要]
File:
Rule: §[section].[subsection]: [rule name]
Convention: "[What the lead reviewer would write in a PR comment]"
path/to/file.go:LINEREJECTED (current code):
go
[actual code, 3-10 lines]CORRECT (what it should be):
go
[fixed code]Why: [One sentence]
Write ALL findings to: [output file path]
---文件:
规则:§[章节].[小节]: [规则名称]
约定:"[首席审查者在PR评论中会写的内容]"
path/to/file.go:LINE错误代码(当前代码):
go
[实际代码,3-10行]正确代码(应修改为):
go
[修复后的代码]原因:[一句话说明]
将所有发现结果写入:[输出文件路径]
---Agent 1: Function Signatures, Constructors, Configuration
Agent 1:函数签名、构造函数、配置
Sections: §1 (Function Signatures), §2 (Configuration), §3 (Constructor Patterns)
Extra Reference:
review-standards-lead.mdWhat to check across ALL packages:
- Constructor taking option struct or functional options instead of positional params
- Functions with >8 params (should they be split?)
- context.Context in wrong position (should be first only for external calls)
- Config loaded from files/viper instead of env vars via osext.MustGetenv
- Constructors that return errors (should be infallible)
- Missing Override methods for test doubles
- Missing time.Now / ID-generator injection in constructors
章节:§1(函数签名)、§2(配置)、§3(构造函数模式)
额外参考:
review-standards-lead.md需在所有包中检查的内容:
- 构造函数是否使用选项结构体或函数式选项,而非位置参数
- 参数数量>8的函数(是否应拆分?)
- context.Context位置错误(仅外部调用应将其作为第一个参数)
- 配置是否从文件/viper加载,而非通过osext.MustGetenv从环境变量加载
- 返回错误的构造函数(应确保不会出错)
- 测试替身缺少Override方法
- 构造函数中缺少time.Now / ID生成器注入
Agent 2: Interfaces, Types, Option[T]
Agent 2:接口、类型、Option[T]
Sections: §4 (Interface Patterns), §8 (Type Definitions), §32 (Option[T] Complete Guide), §36 (Contract Cohesion)
Extra Reference:
architecture-patterns.mdWhat to check across ALL packages:
- Interfaces with only one implementation (should be concrete type)
- Interfaces defined in implementation package instead of consumer package
- used for optional fields instead of
*Tfrom majewsky/gg/optionOption[T] - Missing dot-import for option package ()
import . "github.com/majewsky/gg/option" - used for enums instead of typed string constants
iota - Named types for domain concepts missing (raw where
stringtype should exist)AccountName - Pointer receivers where value receiver is appropriate (or vice versa)
- Type exported when only constructor needs to be public
- Contract cohesion (§36): Constants, error sentinels, or validation functions in a different file from the interface/type they belong to. If is returned by
ErrFoomethods, both must live inFooDriver. MEDIUM for new violations, LOW for pre-existing.foo_driver.go - Interface consumer audit: When a sentinel value or special parameter is introduced on an interface method, grep for ALL implementations AND all callers of that interface method across the entire repo. Use gopls when available. Verify every caller validates the sentinel before passing it. Do not rely on the PR description's claim about authorization — verify the call chain independently.
go_symbol_references
章节:§4(接口模式)、§8(类型定义)、§32(Option[T]完整指南)、§36(契约内聚)
额外参考:
architecture-patterns.md需在所有包中检查的内容:
- 仅有一种实现的接口(应改为具体类型)
- 在实现包而非消费包中定义的接口
- 使用作为可选字段,而非majewsky/gg/option中的
*TOption[T] - 缺少option包的点导入()
import . "github.com/majewsky/gg/option" - 使用定义枚举,而非类型化字符串常量
iota - 缺少领域概念的命名类型(应使用类型的位置使用了原始
AccountName)string - 值接收器适用时使用了指针接收器(反之亦然)
- 仅构造函数需要公开时导出了类型
- 契约内聚(§36):常量、错误哨兵或验证函数与所属的接口/类型不在同一文件中。如果由
ErrFoo方法返回,则两者必须位于FooDriver中。新违规为MEDIUM级别,已有违规为LOW级别。foo_driver.go - 接口消费者审计:当接口方法引入哨兵值或特殊参数时,需在整个仓库中grep所有实现以及该接口方法的所有调用者。可用时使用gopls的。验证每个调用者在传递前是否验证了哨兵值。不得依赖PR描述中的授权声明——需独立验证调用链。
go_symbol_references
Agent 3: HTTP/API Design
Agent 3:HTTP/API设计
Sections: §5 (HTTP/API Patterns), §34 (Architectural Opinions Feb 2026)
Extra Reference:
api-design-detailed.mdWhat to check across ALL packages:
- Auth done as middleware instead of inline at top of handler
- JSON responses not using respondwith.JSON
- Error responses using JSON instead of text/plain (http.Error for 4xx, respondwith.ErrorText for 500)
- Missing DisallowUnknownFields on json.NewDecoder
- Route registration not using httpapi.Compose pattern
- Handler not a method on *API struct
- Handler signature not
handleVerbResource(w, r) - Request structs not parsed into purpose-specific types
- API docs in Markdown instead of Go types on pkg.go.dev
章节:§5(HTTP/API模式)、§34(2026年2月架构意见)
额外参考:
api-design-detailed.md需在所有包中检查的内容:
- 认证作为中间件实现,而非在处理函数顶部内联
- JSON响应未使用respondwith.JSON
- 错误响应使用JSON而非text/plain(4xx错误使用http.Error,500错误使用respondwith.ErrorText)
- json.NewDecoder缺少DisallowUnknownFields
- 路由注册未使用httpapi.Compose模式
- 处理函数不是*API结构体的方法
- 处理函数签名不是
handleVerbResource(w, r) - 请求结构体未解析为特定用途的类型
- API文档使用Markdown而非pkg.go.dev上的Go类型
Agent 4: Error Handling
Agent 4:错误处理
Sections: §6 (Error Handling), §26.13 (Error message naming)
Extra Reference:
error-handling-detailed.mdWhat to check across ALL packages:
- Error messages not following "cannot <verb>: %w" format
- "failed to" instead of "cannot" in error messages
- Logging AND returning the same error (must choose one)
- Missing error wrapping (bare without context)
return err - Generic error messages ("internal error", "something went wrong")
- logg.Fatal used outside cmd/ packages
- Swallowed errors (err checked but not returned or logged)
- fmt.Errorf with %s when %w is needed (or vice versa)
- Validation functions returning (bool, string) instead of error
章节:§6(错误处理)、§26.13(错误消息命名)
额外参考:
error-handling-detailed.md需在所有包中检查的内容:
- 错误消息未遵循"cannot <verb>: %w"格式
- 错误消息中使用"failed to"而非"cannot"
- 同时记录并返回同一错误(必须二选一)
- 缺少错误包装(直接而无上下文)
return err - 通用错误消息("internal error"、"something went wrong")
- 在cmd/包外使用logg.Fatal
- 错误被吞没(检查了err但未返回或记录)
- 使用fmt.Errorf时错误使用%s而非%w(反之亦然)
- 验证函数返回(bool, string)而非error
Agent 5: Database and SQL
Agent 5:数据库和SQL
Sections: §7 (Database Patterns), §27 (Database Deep Dive)
Extra Reference: (use sapcc-code-patterns.md §7 + §27)
What to check across ALL packages:
- SQL queries not declared as package-level with
varsqlext.SimplifyWhitespace() - Using placeholders instead of
?(PostgreSQL style)$1, $2 - Missing after
defer sqlext.RollbackUnlessCommitted(tx)db.Begin() - TIMESTAMP used instead of TIMESTAMPTZ
- NULL columns that should be NOT NULL
- Migrations that modify existing migrations (immutable rule)
- Missing down migrations
- App-level validation that should be DB constraints
- Using explicit transaction for single statements
- Not using for row iteration
sqlext.ForeachRow
章节:§7(数据库模式)、§27(数据库深度解析)
额外参考:(使用sapcc-code-patterns.md §7 + §27)
需在所有包中检查的内容:
- SQL查询未声明为包级并使用
varsqlext.SimplifyWhitespace() - 使用占位符而非
?(PostgreSQL风格)$1, $2 - 后缺少
db.Begin()defer sqlext.RollbackUnlessCommitted(tx) - 使用TIMESTAMP而非TIMESTAMPTZ
- 应为NOT NULL的NULL列
- 修改现有迁移的迁移操作(不可变规则)
- 缺少回滚迁移
- 应作为DB约束的应用级验证
- 单条语句使用显式事务
- 未使用进行行迭代
sqlext.ForeachRow
Agent 6: Testing Patterns
Agent 6:测试模式
Sections: §9 (Testing Patterns), §30 (go-bits Testing API Evolution)
Extra Reference:
testing-patterns-detailed.md*What to check across ALL _test.go files AND test helpers:
- Using deprecated instead of
assert.HTTPRequesthttptest.Handler.RespondTo() - Using where generic
assert.DeepEqualworksassert.Equal - Table-driven tests (project convention prefers sequential scenario-driven narrative)
- Missing in test helper functions
t.Helper() - Using reflect.DeepEqual instead of assert.DeepEqual
- Test fixtures as large JSON files instead of programmatic builders
- Duplicated test setup across test functions (should extract)
- Using package instead of
requirefrom go-bitsmust - Not using /
must.SucceedTfor error-checked returnsmust.ReturnT - Not using for flexible error matching
assert.ErrEqual - Assertion depth check: For security-sensitive code (auth, filtering, tenant isolation), presence-only assertions (,
NotEmpty,NotNil) are INSUFFICIENT. Tests must verify the actual VALUE matches the expected input (e.g.,assert.True(t, ok))assert.Equal(t, expectedID, filters[0]["term"]["tenant_ids"])
章节:§9(测试模式)、§30(go-bits测试API演进)
额外参考:
testing-patterns-detailed.md需在所有*_test.go文件和测试辅助工具中检查的内容:
- 使用已弃用的而非
assert.HTTPRequesthttptest.Handler.RespondTo() - 在通用可用时使用
assert.Equalassert.DeepEqual - 表驱动测试(项目约定更倾向于顺序场景驱动的叙述式测试)
- 测试辅助函数中缺少
t.Helper() - 使用reflect.DeepEqual而非assert.DeepEqual
- 测试 fixtures 为大型JSON文件而非程序化构建器
- 测试函数之间重复的测试设置(应提取为公共代码)
- 使用require包而非go-bits中的must
- 未使用/
must.SucceedT处理带错误检查的返回值must.ReturnT - 未使用进行灵活的错误匹配
assert.ErrEqual - 断言深度检查:对于安全敏感代码(认证、过滤、租户隔离),仅存在性断言(、
NotEmpty、NotNil)是不够的。测试必须验证实际值与预期输入匹配(例如assert.True(t, ok))assert.Equal(t, expectedID, filters[0]["term"]["tenant_ids"])
Agent 7: Package Organization, Imports, Comments
Agent 7:包组织、导入、注释
Sections: §10 (Package Org), §11 (Import Org), §13 (Comment Style), §28 (CLI Patterns), §36 (Contract Cohesion)
Extra Reference:
architecture-patterns.mdWhat to check across ALL packages:
- Import groups not in stdlib / external / internal order (3 groups)
- Dot-import used for anything other than
majewsky/gg/option - Missing SPDX license header
- Comments using instead of
/* */for doc comments// - Missing 80-slash separator comments () between type groups
////////////////... - markers missing for non-obvious logic
//NOTE: - Exported symbols without godoc comments
- cmd/ packages using wrong CLI patterns (if CLI repo)
- Package names not reading as English ("package utils" instead of meaningful name)
- Contract cohesion (§36): Files named generically (,
interface.go,types.go) when they should be named for the domain concept (constants.go,storage_driver.go). Constants/sentinels inrbac_policy.gothat belong to a specific interface's file. The test: if you can name the owning interface, the artifact must live in that interface's file.util.go
章节:§10(包组织)、§11(导入组织)、§13(注释风格)、§28(CLI模式)、§36(契约内聚)
额外参考:
architecture-patterns.md需在所有包中检查的内容:
- 导入组未按标准库/外部/内部顺序排列(3个组)
- 除外使用点导入
majewsky/gg/option - 缺少SPDX许可证头
- 文档注释使用而非
/* */// - 类型组之间缺少80个斜杠的分隔注释()
////////////////... - 非明显逻辑缺少标记
//NOTE: - 导出的符号没有godoc注释
- cmd/包使用错误的CLI模式(如果是CLI仓库)
- 包名不符合英文语义(例如使用"package utils"而非有意义的名称)
- 契约内聚(§36):文件命名过于通用(、
interface.go、types.go),而应按领域概念命名(constants.go、storage_driver.go)。rbac_policy.go中的常量/哨兵值属于特定接口的文件。测试方法:如果能确定所属接口,则该元素必须位于该接口的文件中。util.go
Agent 8: Modern Go, Standard Library, Concurrency
Agent 8:现代Go、标准库、并发
Sections: §14 (Concurrency), §15 (Startup/Shutdown), §29 (Modern Go Stdlib)
Extra Reference: (use sapcc-code-patterns.md §14, §15, §29)
What to check across ALL packages:
- Using instead of
sort.Slice(Go 1.21+)slices.SortFunc - Using manual instead of
keys := make([]K, 0, len(m)); for k := range m { ... }slices.Sorted(maps.Keys(m)) - Using instead of
strings.HasPrefix + strings.TrimPrefix(Go 1.20+)strings.CutPrefix - Using manual instead of
if a < b { return a }(Go 1.21+)min(a, b) - Loop variable capture workaround () in Go 1.22+ code
v := v - Goroutines without proper context cancellation
- Missing SIGINT context handling in main()
- used instead of proper shutdown sequence
os.Exit - on struct value instead of per-resource
sync.Mutex - Missing syntax where applicable (Go 1.22+)
for range N
章节:§14(并发)、§15(启动/关闭)、§29(现代Go标准库)
额外参考:(使用sapcc-code-patterns.md §14、§15、§29)
需在所有包中检查的内容:
- 使用而非
sort.Slice(Go 1.21+)slices.SortFunc - 使用手动实现而非
keys := make([]K, 0, len(m)); for k := range m { ... }slices.Sorted(maps.Keys(m)) - 使用而非
strings.HasPrefix + strings.TrimPrefix(Go 1.20+)strings.CutPrefix - 使用手动实现而非
if a < b { return a }(Go 1.21+)min(a, b) - 在Go 1.22+代码中使用循环变量捕获的变通方法()
v := v - Goroutine缺少适当的上下文取消机制
- main()中缺少SIGINT上下文处理
- 使用而非正确的关闭序列
os.Exit - 在结构体值上使用而非按资源使用
sync.Mutex - 适用时未使用语法(Go 1.22+)
for range N
Agent 9: Observability, Metrics, Background Jobs
Agent 9:可观测性、指标、后台任务
Sections: §16 (Background Jobs), §17 (HTTP Client), §18 (String Formatting), §20 (Observability)
Extra Reference: (use sapcc-code-patterns.md §16-18, §20)
What to check across ALL packages:
- Prometheus metrics missing application prefix (e.g., or
keppel_)logrouter_ - Counter metrics not initialized to zero
- Counter metric names not plural
- Gauge used where Counter is appropriate (or vice versa)
- Background jobs not using pattern
jobloop.ProducerConsumerJob - HTTP client creating new per request instead of using
http.Clienthttp.DefaultClient - Custom HTTP transport instead of
http.DefaultTransport - Missing jitter in polling/retry loops
- for simple string concatenation (use
fmt.Sprintf)+ - for complex multi-part string building (use
+)fmt.Sprintf
章节:§16(后台任务)、§17(HTTP客户端)、§18(字符串格式化)、§20(可观测性)
额外参考:(使用sapcc-code-patterns.md §16-18、§20)
需在所有包中检查的内容:
- Prometheus指标缺少应用前缀(例如或
keppel_)logrouter_ - 计数器指标未初始化为零
- 计数器指标名称未使用复数形式
- 在应使用Counter的地方使用了Gauge(反之亦然)
- 后台任务未使用模式
jobloop.ProducerConsumerJob - HTTP客户端每次请求创建新的而非使用
http.Clienthttp.DefaultClient - 使用自定义HTTP传输而非
http.DefaultTransport - 轮询/重试循环中缺少抖动
- 简单字符串拼接使用(应使用
fmt.Sprintf)+ - 复杂多部分字符串构建使用(应使用
+)fmt.Sprintf
Agent 10: Anti-Patterns, LLM Tells, Community Divergences
Agent 10:反模式、LLM特征、社区差异
Sections: §22 (Divergences), §24 (Anti-Patterns), §25 (LLM Code Feedback), §33 (Portunus Architecture), §35 (Reinforcement Table)
Extra Reference:
anti-patterns.mdThis is the highest-value agent. It checks for patterns that LLMs generate by default but the project explicitly rejects:
- Functional options pattern (project convention: positional params)
- Table-driven tests (project convention: sequential scenario narrative)
- Interface segregation / many small interfaces (project convention: 1-2 interfaces max per domain)
- Middleware-based auth (project convention: inline at handler top)
- Config validation layer (project convention: no separate validation)
- for optional fields (project convention:
*T)Option[T] - Config files / viper (project convention: pure env vars)
- Error messages starting with capital letter
- Error messages using "failed to" (project convention: "cannot")
- Helper functions extracted for cyclomatic complexity (project convention: "contrived edit to satisfy silly metrics")
- Exported types when only constructor is public
- Plugin creating its own DB connection (project convention: receive dependencies)
- +
errors.Newinstead offmt.Sprintffmt.Errorf - Manual row scanning instead of
sqlext.ForeachRow - Test setup in instead of per-test
TestMain - Verbose error checking instead of /
assert.ErrEqualmust.SucceedT - Extraction without guard transfer: When inline code is extracted into a named helper, ALL defensive checks that relied on "the caller handles it" must be re-evaluated. A missing guard rated LOW as inline code becomes MEDIUM as a reusable function. Flag extracted helpers that lack self-contained validation.
Gate: All 10 agents dispatched in single message. Wait for all to complete. Proceed to Phase 3.
章节:§22(差异)、§24(反模式)、§25(LLM代码反馈)、§33(Portunus架构)、§35(强化表)
额外参考:
anti-patterns.md这是价值最高的Agent。它检查LLM默认生成但项目明确拒绝的模式:
- 函数式选项模式(项目约定:位置参数)
- 表驱动测试(项目约定:顺序场景叙述式测试)
- 接口隔离/多个小接口(项目约定:每个领域最多1-2个接口)
- 基于中间件的认证(项目约定:在处理函数顶部内联)
- 配置验证层(项目约定:无单独验证层)
- 使用作为可选字段(项目约定:
*T)Option[T] - 配置文件/viper(项目约定:纯环境变量)
- 错误消息以大写字母开头
- 错误消息使用"failed to"(项目约定:"cannot")
- 为降低圈复杂度而提取的辅助函数(项目约定:“为满足愚蠢指标而刻意修改”)
- 仅构造函数需公开时导出类型
- 插件创建自己的数据库连接(项目约定:接收依赖)
- 使用+
errors.New而非fmt.Sprintffmt.Errorf - 手动行扫描而非
sqlext.ForeachRow - 测试设置在中而非每个测试用例中
TestMain - 冗长的错误检查而非/
assert.ErrEqualmust.SucceedT - 提取但未转移防护逻辑:当内联代码被提取为命名辅助函数时,所有依赖于“调用者处理”的防御性检查必须重新评估。内联时为LOW级别的缺失防护,在变为可重用函数后会升级为MEDIUM级别。标记缺少自包含验证的提取辅助函数。
检查点:已在单个消息中调度所有10个Agent。等待所有Agent完成。进入阶段3。
Phase 3: AGGREGATE
阶段3:汇总
Goal: Compile all agent findings into a single prioritized report.
Step 0: Full file inventory
Run (not just ) to capture both modified AND untracked (new) files. This ensures new files created during the review session are not missed in the report.
git status --shortgit diff --statStep 1: Collect all findings
Read each agent's output. Extract all findings with their severity, file, rule, and code.
Step 2: Deduplicate
If two agents flagged the same file:line, keep the higher-severity finding with the more specific rule citation.
Step 3: Prioritize
Apply cross-repository reinforcement from §35:
| Pattern Strength | Severity Boost |
|---|---|
| NON-NEGOTIABLE (4+ repos) | +1 severity level (MEDIUM->HIGH) |
| Strong Signal (2-3 repos) | No change |
| Context-Specific (1 repo) | -1 severity level (HIGH->MEDIUM) |
Step 4: Identify Quick Wins
Mark findings that are:
- Single-line changes (regex replace, import reorder)
- No behavioral change (pure style/naming)
- Low risk of breaking tests
These go in a "Quick Wins" section at the top of the report.
Step 5: Write report
Create :
sapcc-review-report.mdmarkdown
undefined目标:将所有Agent的发现结果编译为单个优先级报告。
步骤0:完整文件清单
运行(不仅是)以捕获已修改和未跟踪(新)的文件。确保审查会话期间创建的新文件不会在报告中遗漏。
git status --shortgit diff --stat步骤1:收集所有发现结果
读取每个Agent的输出。提取所有发现结果及其严重程度、文件、规则和代码。
步骤2:去重
如果两个Agent标记了同一文件的同一行,保留严重程度更高且规则引用更具体的发现结果。
步骤3:优先级排序
应用§35中的跨仓库强化规则:
| 模式强度 | 严重程度提升 |
|---|---|
| 不可协商(4+仓库) | +1级严重程度(MEDIUM->HIGH) |
| 强信号(2-3仓库) | 无变化 |
| 特定上下文(1仓库) | -1级严重程度(HIGH->MEDIUM) |
步骤4:识别快速修复
标记符合以下条件的发现结果:
- 单行修改(正则替换、导入重排)
- 无行为变化(纯样式/命名修改)
- 破坏测试的风险低
这些内容将放入报告顶部的“快速修复”章节。
步骤5:撰写报告
创建:
sapcc-review-report.mdmarkdown
undefinedSAPCC Code Review: [repo name]
SAPCC代码审查:[仓库名称]
Module: [go module path]
Date: [date]
Packages reviewed: [N] packages, [M] Go files, [T] test files
Agents dispatched: 10 domain specialists
Reference version: sapcc-code-patterns.md (comprehensive patterns reference, 36 sections)
模块:[go模块路径]
日期:[日期]
已审查的包:[N]个包,[M]个Go文件,[T]个测试文件
已调度的Agent:10个领域专家
参考版本:sapcc-code-patterns.md(综合模式参考,36个章节)
Verdict
verdict
[2-3 sentences: Would this codebase pass lead review? What are the systemic issues?
Not just "there are problems" — identify the PATTERN of problems.]
[2-3句话:该代码库能否通过首席审查?存在哪些系统性问题?
不仅要说明“存在问题”——需识别问题的模式。]
Score Card
评分卡
| Domain | Agent | Findings | Critical | High | Medium | Low |
|---|---|---|---|---|---|---|
| Signatures/Config | 1 | N | ... | ... | ... | ... |
| Types/Option[T] | 2 | N | ... | ... | ... | ... |
| HTTP/API | 3 | N | ... | ... | ... | ... |
| Error Handling | 4 | N | ... | ... | ... | ... |
| Database/SQL | 5 | N | ... | ... | ... | ... |
| Testing | 6 | N | ... | ... | ... | ... |
| Pkg Org/Imports | 7 | N | ... | ... | ... | ... |
| Modern Go/Stdlib | 8 | N | ... | ... | ... | ... |
| Observability/Jobs | 9 | N | ... | ... | ... | ... |
| Anti-Patterns/LLM | 10 | N | ... | ... | ... | ... |
| TOTAL | N | X | Y | Z | W |
| 领域 | Agent | 发现数量 | 严重 | 高 | 中 | 低 |
|---|---|---|---|---|---|---|
| 签名/配置 | 1 | N | ... | ... | ... | ... |
| 类型/Option[T] | 2 | N | ... | ... | ... | ... |
| HTTP/API | 3 | N | ... | ... | ... | ... |
| 错误处理 | 4 | N | ... | ... | ... | ... |
| 数据库/SQL | 5 | N | ... | ... | ... | ... |
| 测试 | 6 | N | ... | ... | ... | ... |
| 包组织/导入 | 7 | N | ... | ... | ... | ... |
| 现代Go/标准库 | 8 | N | ... | ... | ... | ... |
| 可观测性/任务 | 9 | N | ... | ... | ... | ... |
| 反模式/LLM | 10 | N | ... | ... | ... | ... |
| 总计 | N | X | Y | Z | W |
Quick Wins (Easy Fixes, High Impact)
快速修复(易修复、高影响)
[5-10 findings that can be fixed with minimal effort]
[5-10个可通过最小努力修复的发现结果]
Critical Findings
严重发现
[Each finding with full REJECTED/CORRECT code]
[每个发现结果包含完整的错误代码/正确代码]
High Findings
高优先级发现
[Each finding with full REJECTED/CORRECT code]
[每个发现结果包含完整的错误代码/正确代码]
Medium Findings
中优先级发现
[Each finding]
[每个发现结果]
Low Findings
低优先级发现
[Brief list]
[简要列表]
What's Done Well
做得好的地方
[Genuine positives the lead reviewer would note approvingly. This is important for morale
and to show the review isn't blindly negative.]
[首席审查者会认可的真正积极点。这对士气很重要,也能表明审查并非盲目负面。]
Systemic Recommendations
系统性建议
[2-3 big-picture recommendations based on patterns across findings.
E.g., "This repo consistently uses *T for optionals — a bulk migration
to Option[T] would address 15 findings at once."]
**Gate**: Report written. Display summary to user. Proceed to Phase 4 if `--fix` specified.
---[2-3个基于发现结果模式的宏观建议。
例如:“该仓库一致使用*T作为可选字段——批量迁移到Option[T]可一次性解决15个发现结果。”]
**检查点**:报告已撰写。向用户显示摘要。如果指定了`--fix`参数,进入阶段4。
---Phase 4: FIX (Optional — only with --fix
flag)
--fix阶段4:修复(可选——仅在指定--fix标志时执行)
Goal: Apply fixes on an isolated branch.
Step 1: Create worktree
Use to create an isolated copy. Name it .
EnterWorktreesapcc-review-fixesStep 2: Apply Quick Wins first
Start with Quick Wins (lowest risk). After each group of fixes:
bash
go build ./... # Must still compile
go vet ./... # Must pass vet
make check 2>/dev/null || go test ./... # Must pass testsStep 3: Apply Critical and High fixes
Apply in order. Run tests between each fix. If a fix breaks tests, revert it and note in the report.
Step 4: Create commit
bash
git add -A
git commit -m "fix: apply sapcc-review findings (N fixes across M files)"Step 5: Report results
Update with:
sapcc-review-report.md- Which findings were fixed
- Which findings were skipped (and why)
- Test results after fixes
目标:在隔离分支上应用修复。
步骤1:创建工作树
使用创建隔离副本。命名为。
EnterWorktreesapcc-review-fixes步骤2:优先应用快速修复
从快速修复开始(风险最低)。每组修复完成后:
bash
go build ./... # 必须仍能编译
go vet ./... # 必须通过vet检查
make check 2>/dev/null || go test ./... # 必须通过测试步骤3:应用严重和高优先级修复
按顺序应用。每次修复后运行测试。如果修复破坏了测试,回滚并在报告中说明。
步骤4:创建提交
bash
git add -A
git commit -m "fix: apply sapcc-review findings (N fixes across M files)"步骤5:报告结果
更新,包含:
sapcc-review-report.md- 已修复的发现结果
- 已跳过的发现结果及原因
- 修复后的测试结果
Calibration: What Makes This Gold Standard
校准:何为黄金标准
Why 10 Domain Specialists > N Package Generalists
为何10个领域专家优于N个包通用型Agent
| Approach | Strength | Weakness |
|---|---|---|
| Package generalist (sapcc-audit) | Understands file-level context | Must remember ALL rules for every file |
| Domain specialist (sapcc-review) | Deep expertise in one rule domain | May miss cross-concern interactions |
Combination is ideal: Run for comprehensive rule coverage, then for holistic package-level review.
/sapcc-review/sapcc-audit| 方法 | 优势 | 劣势 |
|---|---|---|
| 包通用型(sapcc-audit) | 理解文件级上下文 | 必须记住每个文件的所有规则 |
| 领域专家型(sapcc-review) | 深入掌握一个规则领域 | 可能遗漏跨关注点的交互 |
理想组合:运行以获得全面的规则覆盖,然后运行以获得整体的包级审查。
/sapcc-review/sapcc-auditWhy Read sapcc-code-patterns.md First
为何要先阅读sapcc-code-patterns.md
The comprehensive reference is the single source of truth. Without reading it, agents default to community Go conventions — which are WRONG for 12+ patterns the project explicitly diverges from (§22). The reference file IS the competitive advantage.
综合参考资料是唯一的事实来源。如果不阅读,Agent会默认采用社区Go约定——而项目明确偏离的12+种模式(参见§22)中,这些约定是错误的。参考文件是核心竞争优势。
What "Gold Standard" Means
“黄金标准”的含义
- Complete coverage: Every section in sapcc-code-patterns.md has a specialist agent checking for it
- Low false positives: Agents skip generic Go advice and only report sapcc-specific divergences
- Actionable findings: Every finding has REJECTED code and CORRECT code
- Prioritized output: Cross-repo reinforcement weights findings by importance
- Reproducible: Same repo + same reference = same findings
- Quick Wins first: Operator can fix 10 easy things immediately for rapid improvement
- 完整覆盖:sapcc-code-patterns.md中的每个章节都有专家Agent负责检查
- 低误报率:Agent跳过通用Go建议,仅报告sapcc特定的差异
- 可操作的发现结果:每个发现结果都包含错误代码和正确代码
- 优先级输出:跨仓库强化根据重要性对发现结果加权
- 可重现:相同仓库+相同参考资料=相同发现结果
- 优先快速修复:操作方可立即修复10个简单问题,实现快速改进
Anti-Patterns
反模式
AP-1: Not Reading the References
AP-1:未阅读参考资料
What it looks like: Agent starts reviewing without reading sapcc-code-patterns.md
Why wrong: Without the reference, agents generate findings based on community Go advice, which diverges from the project's preferences in 12+ areas
Do instead: ALWAYS read sapcc-code-patterns.md FIRST. This is hardcoded behavior.
表现:Agent在未阅读sapcc-code-patterns.md的情况下开始审查
错误原因:没有参考资料,Agent会基于社区Go建议生成发现结果,而这些建议在12+个领域与项目偏好存在差异
正确做法:始终优先阅读sapcc-code-patterns.md。这是硬编码行为。
AP-2: Reporting Generic Go Issues
AP-2:报告通用Go问题
What it looks like: "Add t.Parallel()", "Use context.Context as first param"
Why wrong: The lead reviewer doesn't care about these. The focus is on over-engineering, dead code, and error quality.
Do instead: Only report patterns that match rules in sapcc-code-patterns.md
表现:“添加t.Parallel()”、“使用context.Context作为第一个参数”
错误原因:首席审查者不关心这些。重点是过度工程、死代码和错误质量。
正确做法:仅报告与sapcc-code-patterns.md中规则匹配的模式。
AP-3: Suggesting More Complexity
AP-3:建议增加复杂度
What it looks like: "Add a config validation layer", "Create an error registry"
Why wrong: The #1 concern in lead review is over-engineering. Never suggest adding abstraction.
Do instead: Suggest REMOVING complexity. "Delete this wrapper" > "Add this wrapper"
表现:“添加配置验证层”、“创建错误注册表”
错误原因:首席审查的首要关注点是过度工程。绝不要建议添加抽象层。
正确做法:建议移除复杂度。“删除此包装器”优于“添加此包装器”。
AP-4: Abstract Findings Without Code
AP-4:无代码的抽象发现结果
What it looks like: "Error handling could be improved in package X"
Why wrong: Not actionable. Lead reviews always show exact code.
Do instead: Show the actual line, the actual code, and the actual fix.
表现:“包X中的错误处理可改进”
错误原因:不具备可操作性。首席审查始终会展示精确代码。
正确做法:展示实际行、实际代码和实际修复方案。
Integration
集成
- Router: routes via "sapcc review", "sapcc lead review", "comprehensive sapcc audit"
/do - Complements: (package-level generalist) — use both for maximum coverage
/sapcc-audit - Prerequisite: go-sapcc-conventions skill must be installed at
~/.claude/skills/go-sapcc-conventions/ - Sync: After creating, run for global access
cp -r skills/sapcc-review ~/.claude/skills/sapcc-review
- 路由:路由通过"sapcc review"、"sapcc lead review"、"comprehensive sapcc audit"触发
/do - 补充工具:(包级通用型审查)——结合使用可获得最大覆盖范围
/sapcc-audit - 前提条件:go-sapcc-conventions技能必须安装在
~/.claude/skills/go-sapcc-conventions/ - 同步:创建后,运行以实现全局访问",
cp -r skills/sapcc-review ~/.claude/skills/sapcc-review