cc-devflow 4.5.1 → 4.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +14 -0
  2. package/.claude/skills/cc-act/PLAYBOOK.md +26 -1
  3. package/.claude/skills/cc-act/SKILL.md +36 -7
  4. package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +20 -0
  5. package/.claude/skills/cc-act/references/closure-contract.md +8 -0
  6. package/.claude/skills/cc-act/scripts/cc-act-common.sh +6 -1
  7. package/.claude/skills/cc-act/scripts/render-pr-brief.sh +99 -0
  8. package/.claude/skills/cc-act/scripts/verify-act-gate.sh +17 -1
  9. package/.claude/skills/cc-check/CHANGELOG.md +14 -0
  10. package/.claude/skills/cc-check/PLAYBOOK.md +101 -1
  11. package/.claude/skills/cc-check/SKILL.md +128 -7
  12. package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +121 -1
  13. package/.claude/skills/cc-check/references/review-contract.md +88 -0
  14. package/.claude/skills/cc-check/scripts/render-report-card.js +172 -5
  15. package/.claude/skills/cc-check/scripts/verify-gate.sh +21 -0
  16. package/.claude/skills/cc-investigate/CHANGELOG.md +13 -0
  17. package/.claude/skills/cc-investigate/PLAYBOOK.md +105 -4
  18. package/.claude/skills/cc-investigate/SKILL.md +185 -8
  19. package/.claude/skills/cc-investigate/assets/ANALYSIS_TEMPLATE.md +77 -3
  20. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +10 -3
  21. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +102 -1
  22. package/.claude/skills/cc-investigate/references/investigation-contract.md +146 -0
  23. package/.claude/skills/cc-simplify/CHANGELOG.md +15 -0
  24. package/.claude/skills/cc-simplify/SKILL.md +255 -35
  25. package/CHANGELOG.md +16 -0
  26. package/docs/examples/example-bindings.json +3 -3
  27. package/docs/examples/full-design-blocked/README.md +1 -1
  28. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/review/report-card.json +140 -3
  29. package/docs/examples/local-handoff/README.md +1 -1
  30. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/review/report-card.json +92 -0
  31. package/docs/examples/pdca-loop/README.md +1 -1
  32. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/pr-brief.md +20 -0
  33. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/review/report-card.json +92 -0
  34. package/lib/skill-runtime/review.js +64 -1
  35. package/lib/skill-runtime/schemas.js +150 -3
  36. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cc-check
3
- version: 1.8.2
3
+ version: 1.8.4
4
4
  description: Use when a planned or investigated change needs fresh verification evidence, layered gate proof, review truth, and an honest pass fail blocked verdict before entering cc-act.
5
5
  triggers:
6
6
  - 验收这个需求
@@ -25,7 +25,7 @@ entry_gate:
25
25
  - Re-run fresh commands instead of inheriting cc-do narration.
26
26
  - If evidence is stale or missing, reset context and rebuild the verdict from canonical artifacts.
27
27
  exit_criteria:
28
- - review/report-card.json records pass, fail, or blocked using fresh evidence, plus spec alignment and sync readiness.
28
+ - review/report-card.json records pass, fail, or blocked using fresh evidence, review freshness, claim evidence, QA coverage and browser evidence, failure ownership, plus spec alignment and sync readiness.
29
29
  - Task-level review and requirement-level diff review are separated clearly.
30
30
  - 'The next step is unambiguous: cc-act, cc-do, cc-investigate, or cc-plan.'
31
31
  reroutes:
@@ -119,6 +119,8 @@ NO PASS WITHOUT FRESH EVIDENCE
119
119
  - runtime gate
120
120
  - task-level review proof
121
121
  - requirement-level diff review
122
+ - claim evidence matrix
123
+ - QA regression / test-quality proof
122
124
  - spec alignment / sync readiness
123
125
  4. **Freeze Verdict**
124
126
  - 只允许 `pass` / `fail` / `blocked`
@@ -131,12 +133,12 @@ NO PASS WITHOUT FRESH EVIDENCE
131
133
 
132
134
  - Allowed actions: rerun gates, inspect review proof, record a verdict, and route the requirement honestly.
133
135
  - Forbidden actions: continuing development, inheriting old execution claims without fresh proof, or masking blocked work as pass.
134
- - Required evidence: every passing statement must cite fresh command output, exit status, and key observation.
136
+ - Required evidence: every passing statement must cite fresh command output, exit status, key observation, and the claim it proves.
135
137
  - Reroute rule: code and review fixes return to `cc-do`; root-cause drift returns to `cc-investigate`; scope or design invalidation returns to `cc-plan`.
136
138
 
137
139
  ## Verification Layers
138
140
 
139
- `cc-check` 不是只看“测试是不是绿的”,而是至少看 4 层:
141
+ `cc-check` 不是只看“测试是不是绿的”,而是至少看 9 层:
140
142
 
141
143
  1. **Runtime Layer**
142
144
  - 测试、lint、typecheck、build、脚本 gate
@@ -147,9 +149,61 @@ NO PASS WITHOUT FRESH EVIDENCE
147
149
  - 当前改动是否真的兑现 requirement,而不是只让局部测试通过
148
150
  4. **Spec Sync Layer**
149
151
  - capability truth、expected spec delta、handoff readiness 是否仍然一致
152
+ 5. **Claim Evidence Layer**
153
+ - 测试通过、build 成功、bug 修复、需求完成、agent 完成等声明,是否各自有对应证据
154
+ 6. **QA Test Layer**
155
+ - 回归测试是否有 red/green 证据
156
+ - 测试是否验证真实行为,而不是 mock 或 test-only production API
157
+ 7. **Review Freshness Layer**
158
+ - review 是否绑定当前 `headSha`
159
+ - 从 review 到当前 HEAD 是否还有新增 commit
160
+ - 质量分、置信度、finding 去噪是否可复盘
161
+ 8. **QA Coverage / Browser Layer**
162
+ - 行为链路、错误态、边界条件是否被测试映射覆盖
163
+ - UI / 用户路径变更是否有浏览器证据、截图、console 结果或明确 skip 理由
164
+ 9. **Failure Ownership Layer**
165
+ - 失败是本分支引入、基线已存在、环境阻塞,还是归属不明
166
+ - 归属不明默认不能支撑 `pass`
150
167
 
151
168
  任何一层失真,都不能写 `pass`。
152
169
 
170
+ ## Claim Evidence Matrix
171
+
172
+ 不要把所有绿色都写成“测试过了”。`cc-check` 必须把声明拆成证据:
173
+
174
+ | Claim | Required proof | Not enough |
175
+ | --- | --- | --- |
176
+ | Tests pass | 本轮 test command、exit 0、0 failures | 旧输出、局部日志、应该会过 |
177
+ | Lint clean | 本轮 lint command、0 errors | 只跑 formatter、只看 touched file 且声明全仓 clean |
178
+ | Build succeeds | build command exit 0 | test / lint 通过 |
179
+ | Bug fixed | 原始症状或回归测试通过 | 代码改了、推测已修 |
180
+ | Regression test works | red -> green 证据 | 测试只绿过一次 |
181
+ | Agent completed | VCS diff / artifact 证明实际变化 | agent 自报 success |
182
+ | Requirements met | 逐项 plan / manifest checklist | 测试通过 |
183
+
184
+ 这些事实写入 `claimEvidence[]`。缺少关键 claim 的证据时,结论至少是 `blocked`。
185
+
186
+ ## QA Test Review
187
+
188
+ `cc-check` 必须区分“有测试”和“测试证明了正确行为”:
189
+
190
+ 1. 回归测试必须记录 red/green 证据;red 要因为目标行为缺失而失败,不是语法、fixture 或 mock 写错。
191
+ 2. 测试应验证真实行为;如果依赖 mock,必须说明 mock 的边界和为什么不会测试 mock 本身。
192
+ 3. 生产代码里新增仅测试使用的 API,默认是坏味道,必须 blocking,除非有明确生产生命周期理由。
193
+ 4. 复杂 mock setup 超过测试主体时,优先要求 integration / contract test 解释。
194
+
195
+ 这些事实写入 `qa.regressionProof` 和 `qa.testQuality`。如果本需求没有行为测试空间,必须记录 `tddException` 或替代验证命令。
196
+
197
+ ## QA Coverage And Browser Evidence
198
+
199
+ 测试不是数量游戏。`cc-check` 必须判断测试覆盖了哪条真实路径:
200
+
201
+ 1. `qa.coverageAudit` 记录 `coveragePct`、`pathMap`、`gaps`、`testsAdded`、`e2eRequired`、`evalRequired`、`qualityStars`。
202
+ 2. UI、路由、端到端用户路径、可视状态、交互状态变化时,必须记录 `qa.browserEvidence`。
203
+ 3. `qa.browserEvidence` 至少说明 `mode`、`affectedRoutes`、`screenshots`、`consoleErrors`、`healthScore`、`issues`、`skipReason`。
204
+ 4. 前端变更没有浏览器证据也没有 skip reason,不能写 `pass`。
205
+ 5. 非前端或纯内部变更可以把 `browserEvidence.status` 写成 `skipped`,但必须说明为什么不需要浏览器 QA。
206
+
153
207
  ## Diff Review Pipeline
154
208
 
155
209
  `cc-check` 的 requirement-level review 不能只写“diff 看过了”。至少要形成这些事实:
@@ -161,9 +215,56 @@ NO PASS WITHOUT FRESH EVIDENCE
161
215
  5. Outside-diff lookup:新增枚举值、状态、路由、artifact 类型时,必须搜索 sibling references,不能只读 diff 内文件。
162
216
  6. Documentation staleness:代码行为、入口、命令、结构变化时,检查 README / CLAUDE / architecture docs 是否漂移。
163
217
  7. Adversarial synthesis:如果有 codex review、subagent review、人工 review,多视角 finding 要去重并标出高置信重叠项。
218
+ 8. Specialist facets:按实际风险记录 `testing`、`security`、`performance`、`api-contract`、`data-migration`、`design` 等 review facet;没有派发也要写 skip reason,避免 reviewer 误以为已经覆盖。
219
+ 9. Confidence calibration:每条 finding 必须有可比较的置信度和指纹,低置信 finding 不准伪装成 blocker。
164
220
 
165
221
  这些事实写入 `review.diffReview.details` 或 `review.findings`。`pass` 只在 scope、completion、critical pass、doc staleness 都没有 blocking finding 时成立。
166
222
 
223
+ ## Review Packet And Triage
224
+
225
+ 每次 task-level 或 requirement-level review 都必须能脱离聊天记录复盘:
226
+
227
+ 1. `reviewPacket.baseSha`
228
+ 2. `reviewPacket.headSha`
229
+ 3. `reviewPacket.requirements`
230
+ 4. `reviewPacket.implemented`
231
+ 5. `reviewPacket.reviewerContext`
232
+
233
+ 每次 review 还必须记录 freshness:
234
+
235
+ 1. `review.freshness.status`:`fresh` / `stale` / `unknown` / `not-applicable`
236
+ 2. `review.freshness.reviewedCommit`
237
+ 3. `review.freshness.currentCommit`
238
+ 4. `review.freshness.commitsSinceReview`
239
+ 5. `review.freshness.staleReason`
240
+ 6. `review.qualityScore`:0-10,缺失时不能当成高置信审查
241
+
242
+ 每条 finding 必须有 triage:
243
+
244
+ - `accepted-fixed`:已修并有验证
245
+ - `rejected-with-evidence`:经代码 / 测试证明不适用
246
+ - `deferred-minor`:非阻塞,已写入 follow-up
247
+ - `clarification-needed`:不清楚,当前 verdict 不能是 `pass`
248
+
249
+ `critical` / `important` finding 未 triage 或未闭环,不能进入 `cc-act`。
250
+
251
+ 每条 finding 还必须带去噪字段:
252
+
253
+ - `confidenceScore`:1-10,低于 7 的 finding 只能作为 warning 或待验证 gap
254
+ - `fingerprint`:稳定去重键,避免多路 review 重复报同一件事
255
+ - `displayTier`:`blocking` / `warning` / `info` / `suppressed`
256
+ - `suppressionReason`:只有 `displayTier=suppressed` 时允许非空
257
+
258
+ ## Failure Ownership
259
+
260
+ 失败不能只写“测试红了”。`cc-check` 必须把失败归属写入 `runtime.failureOwnership[]`:
261
+
262
+ 1. `classification` 只能是 `in-branch`、`pre-existing`、`environment`、`ambiguous`。
263
+ 2. `ambiguous` 默认按 `in-branch` 处理,除非有 base branch 复验证据。
264
+ 3. `pre-existing` 必须有 base branch 或历史证据,不能靠猜。
265
+ 4. `environment` 必须记录缺失依赖、权限、服务、密钥或平台约束。
266
+ 5. `pass` 不能带未解释的 `in-branch` 或 `ambiguous` 失败。
267
+
167
268
  ## Entry Gate
168
269
 
169
270
  1. 先读 `planning/design.md` 或 `planning/analysis.md`,再读 `planning/tasks.md`、`planning/task-manifest.json`。
@@ -181,6 +282,7 @@ NO PASS WITHOUT FRESH EVIDENCE
181
282
  - 运行真实命令
182
283
  - 记录 exit status
183
284
  - 识别 failure 还是 blocked
285
+ - 记录 failure ownership,而不是把所有红灯混成一个失败摘要
184
286
  3. **Compare against the contract**
185
287
  - 对照 `planning/design.md` 或 `planning/analysis.md`
186
288
  - 对照 `planning/tasks.md`、`planning/task-manifest.json`
@@ -265,9 +367,12 @@ NO PASS WITHOUT FRESH EVIDENCE
265
367
 
266
368
  1. severity:`critical` / `important` / `info`
267
369
  2. confidence:`high` / `medium` / `low`,低置信不要伪装成 blocker
370
+ - 同时写 `confidenceScore`,用 1-10 数字表达可比较置信度
268
371
  3. source:`runtime` / `task-review` / `diff-review` / `adversarial` / `docs`
269
372
  4. evidence:文件、命令、退出码、manifest path、或具体观察
270
373
  5. action:`fix-now` / `reroute-cc-do` / `reroute-cc-plan` / `reroute-cc-investigate` / `document-follow-up`
374
+ 6. fingerprint:稳定去重键
375
+ 7. displayTier:`blocking` / `warning` / `info` / `suppressed`
271
376
 
272
377
  不能写“可能有问题”然后让接手者猜。要么证明,要么标成待验证 gap。
273
378
 
@@ -281,15 +386,31 @@ NO PASS WITHOUT FRESH EVIDENCE
281
386
  "verdict": "pass",
282
387
  "overall": "pass",
283
388
  "summary": "verdict=pass quick=3/3 strict=0/0 review=pass",
389
+ "claimEvidence": [
390
+ { "claim": "tests-pass", "requiredProof": "fresh test command", "commandOrArtifact": "npm test", "exitStatus": 0, "keyObservation": "0 failures", "status": "pass" },
391
+ { "claim": "requirements-met", "requiredProof": "plan checklist", "commandOrArtifact": "planning/tasks.md", "exitStatus": null, "keyObservation": "all tasks complete", "status": "pass" }
392
+ ],
393
+ "runtime": { "status": "pass", "failureOwnership": [] },
394
+ "qa": {
395
+ "status": "pass",
396
+ "regressionProof": [],
397
+ "testQuality": [],
398
+ "coverageAudit": { "status": "pass", "coveragePct": 80, "pathMap": [], "gaps": [], "testsAdded": [], "e2eRequired": false, "evalRequired": false, "qualityStars": "★★" },
399
+ "browserEvidence": { "status": "skipped", "mode": "not-applicable", "affectedRoutes": [], "screenshots": [], "consoleErrors": [], "healthScore": null, "issues": [], "skipReason": "not a UI or user-path change" },
400
+ "tddException": null
401
+ },
284
402
  "quickGates": [],
285
403
  "strictGates": [],
286
404
  "review": {
287
405
  "status": "pass",
288
406
  "summary": "Task review and diff review both passed",
289
407
  "details": "",
290
- "taskReviews": { "status": "pass", "required": true, "summary": "all completed tasks carry spec/code proof", "reviewers": [], "findings": [] },
291
- "diffReview": { "status": "pass", "required": true, "summary": "plan completion clean, no scope drift, no critical diff findings", "reviewers": [], "findings": [] },
292
- "findings": []
408
+ "freshness": { "status": "fresh", "reviewedCommit": "example-head", "currentCommit": "example-head", "commitsSinceReview": 0, "staleReason": "" },
409
+ "qualityScore": 9,
410
+ "specialistReviews": [],
411
+ "taskReviews": { "status": "pass", "required": true, "summary": "all completed tasks carry spec/code proof", "reviewPacket": {}, "reviewers": [], "findings": [] },
412
+ "diffReview": { "status": "pass", "required": true, "summary": "plan completion clean, no scope drift, no critical diff findings", "reviewPacket": {}, "reviewers": [], "findings": [] },
413
+ "findings": []
293
414
  },
294
415
  "blockingFindings": [],
295
416
  "reroute": "none",
@@ -9,6 +9,80 @@
9
9
  "specAlignment": "blocked",
10
10
  "specDeltaVerified": false,
11
11
  "specSyncReady": false,
12
+ "runtime": {
13
+ "status": "blocked",
14
+ "failureOwnership": [
15
+ {
16
+ "failure": "missing spec review proof",
17
+ "classification": "in-branch",
18
+ "touchedByDiff": true,
19
+ "evidence": "planning/task-manifest.json tasks[T002].reviews.spec is empty",
20
+ "action": "reroute-cc-do",
21
+ "status": "open"
22
+ }
23
+ ]
24
+ },
25
+ "claimEvidence": [
26
+ {
27
+ "claim": "tests-pass",
28
+ "requiredProof": "fresh test command with exit 0 and 0 failures",
29
+ "commandOrArtifact": "npm test -- src/feature/feature.test.ts",
30
+ "exitStatus": 0,
31
+ "keyObservation": "targeted tests passed in this run",
32
+ "status": "pass"
33
+ },
34
+ {
35
+ "claim": "requirements-met",
36
+ "requiredProof": "line-by-line planning/tasks.md and task-manifest.json checklist",
37
+ "commandOrArtifact": "planning/tasks.md + planning/task-manifest.json",
38
+ "exitStatus": null,
39
+ "keyObservation": "T002 still lacks spec review proof",
40
+ "status": "blocked"
41
+ }
42
+ ],
43
+ "qa": {
44
+ "status": "blocked",
45
+ "regressionProof": [
46
+ {
47
+ "behavior": "original symptom",
48
+ "redCommand": "",
49
+ "redFailure": "",
50
+ "greenCommand": "",
51
+ "greenObservation": "",
52
+ "restoredState": false
53
+ }
54
+ ],
55
+ "testQuality": [
56
+ {
57
+ "area": "targeted-tests",
58
+ "checksRealBehavior": true,
59
+ "mockBoundary": "none",
60
+ "testOnlyProductionApi": false,
61
+ "status": "pass"
62
+ }
63
+ ],
64
+ "coverageAudit": {
65
+ "status": "blocked",
66
+ "coveragePct": null,
67
+ "pathMap": ["planning/tasks.md#T002"],
68
+ "gaps": ["T002 has no spec review proof, so the requirement cannot be marked covered"],
69
+ "testsAdded": [],
70
+ "e2eRequired": false,
71
+ "evalRequired": false,
72
+ "qualityStars": "★"
73
+ },
74
+ "browserEvidence": {
75
+ "status": "skipped",
76
+ "mode": "not-applicable",
77
+ "affectedRoutes": [],
78
+ "screenshots": [],
79
+ "consoleErrors": [],
80
+ "healthScore": null,
81
+ "issues": [],
82
+ "skipReason": "template example is not a UI browser QA scenario"
83
+ },
84
+ "tddException": null
85
+ },
12
86
  "quickGates": [
13
87
  {
14
88
  "name": "targeted-tests",
@@ -28,17 +102,63 @@
28
102
  "status": "blocked",
29
103
  "summary": "Task review evidence is incomplete",
30
104
  "details": "T002 is implemented, but the requirement still lacks spec review proof required by the gate.",
105
+ "freshness": {
106
+ "status": "unknown",
107
+ "reviewedCommit": "",
108
+ "currentCommit": "",
109
+ "commitsSinceReview": null,
110
+ "staleReason": "review range is not recorded yet"
111
+ },
112
+ "qualityScore": null,
113
+ "specialistReviews": [
114
+ {
115
+ "name": "testing",
116
+ "status": "blocked",
117
+ "required": true,
118
+ "summary": "testing facet cannot pass while task review proof is missing",
119
+ "skipReason": "",
120
+ "findings": []
121
+ }
122
+ ],
31
123
  "taskReviews": {
32
124
  "status": "blocked",
33
125
  "required": true,
34
126
  "summary": "T002 has no spec review record yet",
127
+ "reviewPacket": {
128
+ "baseSha": "",
129
+ "headSha": "",
130
+ "requirements": "planning/tasks.md#T002",
131
+ "implemented": "implementation report for T002",
132
+ "reviewerContext": "task spec and changed files"
133
+ },
35
134
  "reviewers": [],
36
- "findings": []
135
+ "findings": [
136
+ {
137
+ "severity": "important",
138
+ "confidence": "high",
139
+ "source": "task-review",
140
+ "summary": "T002 spec review proof is missing",
141
+ "evidence": "planning/task-manifest.json tasks[T002].reviews.spec is empty",
142
+ "action": "reroute-cc-do",
143
+ "triageStatus": "clarification-needed",
144
+ "confidenceScore": 9,
145
+ "fingerprint": "task-review:T002:missing-spec-review",
146
+ "displayTier": "blocking",
147
+ "suppressionReason": null
148
+ }
149
+ ]
37
150
  },
38
151
  "diffReview": {
39
152
  "status": "skipped",
40
153
  "required": false,
41
154
  "summary": "",
155
+ "reviewPacket": {
156
+ "baseSha": "",
157
+ "headSha": "",
158
+ "requirements": "planning/design.md",
159
+ "implemented": "",
160
+ "reviewerContext": ""
161
+ },
42
162
  "reviewers": [],
43
163
  "findings": []
44
164
  },
@@ -21,6 +21,7 @@
21
21
 
22
22
  每个 reviewer 结果至少说明:
23
23
 
24
+ - reviewPacket
24
25
  - status
25
26
  - summary
26
27
  - evidence
@@ -30,16 +31,103 @@
30
31
 
31
32
  - severity
32
33
  - confidence
34
+ - confidenceScore
33
35
  - source
34
36
  - summary
35
37
  - evidence
36
38
  - action
39
+ - triageStatus
40
+ - fingerprint
41
+ - displayTier
42
+ - suppressionReason
43
+
44
+ ## Review Packet
45
+
46
+ Review 不能依赖聊天记忆。每个 task-level review 和 requirement-level diff review 至少记录:
47
+
48
+ - `baseSha`:被审查范围的起点
49
+ - `headSha`:被审查范围的终点
50
+ - `requirements`:对应的 plan、task、analysis 或 spec 路径
51
+ - `implemented`:实现者声称完成的内容
52
+ - `reviewerContext`:reviewer 实际拿到的上下文摘要
53
+
54
+ 缺 `baseSha` / `headSha` 时,review 只能算 `blocked` 或 `skipped`,不能支撑 `pass`。
55
+
56
+ ## Review Freshness
57
+
58
+ Review 必须绑定当前被交付的 commit,而不是绑定聊天记忆。
59
+
60
+ 每份 requirement-level review 至少记录:
61
+
62
+ - `review.freshness.status`:`fresh` / `stale` / `unknown` / `not-applicable`
63
+ - `review.freshness.reviewedCommit`
64
+ - `review.freshness.currentCommit`
65
+ - `review.freshness.commitsSinceReview`
66
+ - `review.freshness.staleReason`
67
+ - `review.qualityScore`:0-10,可空但空值不能支撑高置信 pass
68
+
69
+ `status=stale`、`status=unknown` 且没有解释,或 `commitsSinceReview > 0` 且未重审,都会阻塞 `pass`。
70
+
71
+ ## Specialist Facets
72
+
73
+ `review.specialistReviews[]` 用来记录按风险覆盖的审查面,不要求每次都派发独立 reviewer,但要求边界说清:
74
+
75
+ - `testing`:负路径、边界条件、隔离性、flaky 风险、回归测试质量
76
+ - `security`:trust boundary、shell / SQL / secret / auth 风险
77
+ - `performance`:热路径、批量、缓存、N+1、资源泄漏
78
+ - `api-contract`:输入输出、状态枚举、兼容面、错误语义
79
+ - `data-migration`:schema、回滚、幂等、历史数据
80
+ - `design`:UI / UX / visual consistency 和可用性
81
+
82
+ 没有相关风险时写 `status=skipped` 和 `skipReason`;有风险却缺 facet 时,至少是 review gap。
83
+
84
+ ## Finding Triage
85
+
86
+ Review finding 不只是“发现过”,必须有处置结果:
87
+
88
+ | triageStatus | 什么时候用 |
89
+ | --- | --- |
90
+ | `accepted-fixed` | finding 正确,已修复,并有验证证据 |
91
+ | `rejected-with-evidence` | finding 不适用,已有代码 / 测试 / 契约证据支撑 |
92
+ | `deferred-minor` | minor,不阻塞本次交付,已写入 follow-up |
93
+ | `clarification-needed` | finding 不清楚,需要用户或 reviewer 澄清 |
94
+
95
+ `critical` / `important` finding 不能用 `deferred-minor`。任何 `clarification-needed` 都会阻塞 `pass`。
96
+
97
+ ## QA Test Review Facts
98
+
99
+ Review 必须判断测试是否证明行为:
100
+
101
+ - 回归测试是否有 red/green 证据
102
+ - red 是否因为目标行为缺失而失败
103
+ - green 是否包含 targeted test 和必要的 broader gate
104
+ - mock 是否必要,且没有断言 mock 本身
105
+ - 生产代码是否新增 test-only API
106
+ - integration / contract test 是否比复杂 mock 更直接
107
+ - coverage audit 是否映射真实 codepath / user flow / error state / edge case
108
+ - UI 或用户路径变更是否有 browser evidence、截图、console 结果,或明确 skip reason
109
+
110
+ ## Failure Ownership
111
+
112
+ 失败归属必须结构化写入 `runtime.failureOwnership[]`:
113
+
114
+ - `classification=in-branch`:当前分支引入
115
+ - `classification=pre-existing`:base branch 也能复现,必须有证据
116
+ - `classification=environment`:缺依赖、权限、服务、密钥或平台条件
117
+ - `classification=ambiguous`:归属不明,默认不能支撑 `pass`
118
+
119
+ 不要把 pre-existing failure 当成当前分支失败,也不要把 ambiguous failure 当成环境问题。
37
120
 
38
121
  ## Gate Rules
39
122
 
40
123
  - 任务级 review 缺证据,不能绿灯
41
124
  - 需求级 diff review 在 strict 模式下缺失,至少是 `blocked`
42
125
  - `important` / `critical` finding 未处理前,不算通过
126
+ - `important` / `critical` finding 缺 triageStatus,不算通过
127
+ - QA test quality 缺失且本次涉及行为变化,至少是 `blocked`
128
+ - review freshness 缺失、过期或与当前 head 不一致,不能绿灯
129
+ - UI / 用户路径变更缺 browser evidence 且无 skip reason,不能绿灯
130
+ - `runtime.failureOwnership` 仍有 `in-branch` 或 `ambiguous` 未解释失败,不能绿灯
43
131
  - plan item 是 `PARTIAL` / `NOT_DONE` 且影响成功标准时,不能通过
44
132
  - scope drift 没有解释清楚时,不能通过
45
133
  - 文档漂移如果影响 reviewer / maintainer 接手,必须阻塞到 `cc-act` doc sync 或 reroute