cc-devflow 4.5.2 → 4.5.4

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 (100) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +19 -0
  2. package/.claude/skills/cc-act/PLAYBOOK.md +14 -1
  3. package/.claude/skills/cc-act/SKILL.md +46 -6
  4. package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +44 -1
  5. package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +18 -1
  6. package/.claude/skills/cc-act/references/closure-contract.md +3 -0
  7. package/.claude/skills/cc-act/scripts/cc-act-common.sh +27 -1
  8. package/.claude/skills/cc-act/scripts/render-pr-brief.sh +31 -0
  9. package/.claude/skills/cc-act/scripts/verify-act-gate.sh +6 -0
  10. package/.claude/skills/cc-check/CHANGELOG.md +18 -0
  11. package/.claude/skills/cc-check/PLAYBOOK.md +38 -7
  12. package/.claude/skills/cc-check/SKILL.md +39 -7
  13. package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +61 -0
  14. package/.claude/skills/cc-check/references/gate-contract.md +11 -0
  15. package/.claude/skills/cc-check/references/review-contract.md +17 -1
  16. package/.claude/skills/cc-check/scripts/render-report-card.js +37 -0
  17. package/.claude/skills/cc-check/scripts/verify-gate.sh +7 -0
  18. package/.claude/skills/cc-do/CHANGELOG.md +18 -0
  19. package/.claude/skills/cc-do/PLAYBOOK.md +20 -13
  20. package/.claude/skills/cc-do/SKILL.md +37 -17
  21. package/.claude/skills/cc-do/references/execution-recovery.md +19 -5
  22. package/.claude/skills/cc-do/references/parallel-dispatch.md +6 -4
  23. package/.claude/skills/cc-do/scripts/detect-file-conflicts.sh +49 -3
  24. package/.claude/skills/cc-do/scripts/verify-task-gates.sh +19 -6
  25. package/.claude/skills/cc-do/scripts/write-task-checkpoint.sh +14 -2
  26. package/.claude/skills/cc-investigate/CHANGELOG.md +24 -0
  27. package/.claude/skills/cc-investigate/PLAYBOOK.md +35 -13
  28. package/.claude/skills/cc-investigate/SKILL.md +87 -20
  29. package/.claude/skills/cc-investigate/assets/ANALYSIS_TEMPLATE.md +68 -3
  30. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +9 -4
  31. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +41 -2
  32. package/.claude/skills/cc-investigate/references/investigation-contract.md +46 -0
  33. package/.claude/skills/cc-plan/CHANGELOG.md +32 -0
  34. package/.claude/skills/cc-plan/PLAYBOOK.md +26 -8
  35. package/.claude/skills/cc-plan/SKILL.md +79 -34
  36. package/.claude/skills/cc-plan/assets/DESIGN_TEMPLATE.md +71 -3
  37. package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +32 -0
  38. package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +76 -2
  39. package/.claude/skills/cc-plan/assets/TINY_DESIGN_TEMPLATE.md +58 -0
  40. package/.claude/skills/cc-plan/references/planning-contract.md +26 -4
  41. package/.claude/skills/cc-roadmap/CHANGELOG.md +14 -0
  42. package/.claude/skills/cc-roadmap/PLAYBOOK.md +10 -7
  43. package/.claude/skills/cc-roadmap/SKILL.md +43 -23
  44. package/.claude/skills/cc-roadmap/assets/BACKLOG_TEMPLATE.md +10 -0
  45. package/.claude/skills/cc-roadmap/assets/ROADMAP_TEMPLATE.md +15 -0
  46. package/.claude/skills/cc-roadmap/assets/TRACKING_TEMPLATE.json +1 -1
  47. package/.claude/skills/cc-roadmap/references/roadmap-dialogue.md +11 -7
  48. package/.claude/skills/cc-simplify/CHANGELOG.md +6 -0
  49. package/.claude/skills/cc-simplify/SKILL.md +10 -1
  50. package/.claude/skills/cc-spec-init/CHANGELOG.md +6 -0
  51. package/.claude/skills/cc-spec-init/SKILL.md +14 -1
  52. package/CHANGELOG.md +29 -0
  53. package/README.md +10 -2
  54. package/README.zh-CN.md +10 -2
  55. package/bin/cc-devflow-cli.js +93 -2
  56. package/docs/examples/example-bindings.json +7 -7
  57. package/docs/examples/full-design-blocked/BACKLOG.md +1 -1
  58. package/docs/examples/full-design-blocked/README.md +1 -1
  59. package/docs/examples/full-design-blocked/ROADMAP.md +1 -1
  60. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +1 -1
  61. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +1 -1
  62. package/docs/examples/full-design-blocked/roadmap-tracking.json +1 -1
  63. package/docs/examples/local-handoff/BACKLOG.md +1 -1
  64. package/docs/examples/local-handoff/README.md +1 -1
  65. package/docs/examples/local-handoff/ROADMAP.md +1 -1
  66. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +1 -1
  67. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +1 -1
  68. package/docs/examples/local-handoff/roadmap-tracking.json +1 -1
  69. package/docs/examples/pdca-loop/BACKLOG.md +1 -1
  70. package/docs/examples/pdca-loop/README.md +1 -1
  71. package/docs/examples/pdca-loop/ROADMAP.md +1 -1
  72. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +1 -1
  73. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +2 -2
  74. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +1 -1
  75. package/docs/examples/pdca-loop/roadmap-tracking.json +1 -1
  76. package/docs/get-shit-done-strategy-audit.md +518 -0
  77. package/docs/skill-strategy-audit.md +48 -0
  78. package/lib/compiler/__tests__/inventory.test.js +51 -0
  79. package/lib/compiler/inventory.js +78 -0
  80. package/lib/skill-runtime/__tests__/approve.test.js +92 -0
  81. package/lib/skill-runtime/__tests__/autopilot.test.js +4 -0
  82. package/lib/skill-runtime/__tests__/planner.tdd.test.js +20 -0
  83. package/lib/skill-runtime/__tests__/query.test.js +147 -1
  84. package/lib/skill-runtime/__tests__/readiness.test.js +53 -0
  85. package/lib/skill-runtime/__tests__/release.test.js +85 -0
  86. package/lib/skill-runtime/__tests__/runtime.integration.test.js +30 -1
  87. package/lib/skill-runtime/__tests__/schemas.test.js +56 -0
  88. package/lib/skill-runtime/__tests__/worker-run.test.js +29 -0
  89. package/lib/skill-runtime/errors.js +39 -0
  90. package/lib/skill-runtime/index.js +8 -0
  91. package/lib/skill-runtime/operations/approve.js +17 -2
  92. package/lib/skill-runtime/operations/release.js +6 -3
  93. package/lib/skill-runtime/operations/worker-run.js +30 -0
  94. package/lib/skill-runtime/planner.js +10 -2
  95. package/lib/skill-runtime/query-registry.js +101 -0
  96. package/lib/skill-runtime/query.js +159 -91
  97. package/lib/skill-runtime/readiness.js +84 -0
  98. package/lib/skill-runtime/schemas.js +39 -4
  99. package/lib/skill-runtime/trace.js +22 -0
  100. package/package.json +1 -1
@@ -13,10 +13,17 @@
13
13
  "status": "blocked",
14
14
  "failureOwnership": [
15
15
  {
16
+ "errorName": "MissingSpecReviewProof",
16
17
  "failure": "missing spec review proof",
17
18
  "classification": "in-branch",
19
+ "owner": "branch",
18
20
  "touchedByDiff": true,
21
+ "artifactRefs": [
22
+ "planning/task-manifest.json",
23
+ "review/report-card.json"
24
+ ],
19
25
  "evidence": "planning/task-manifest.json tasks[T002].reviews.spec is empty",
26
+ "rescueAction": "record spec review proof for T002 or reroute to cc-do",
20
27
  "action": "reroute-cc-do",
21
28
  "status": "open"
22
29
  }
@@ -42,6 +49,32 @@
42
49
  ],
43
50
  "qa": {
44
51
  "status": "blocked",
52
+ "feedbackLoop": {
53
+ "status": "blocked",
54
+ "mode": "targeted-test",
55
+ "commandOrArtifact": "npm test -- src/feature/feature.test.ts",
56
+ "speed": "fast",
57
+ "determinism": "high",
58
+ "signalSharpness": "targeted failure would indicate the user-visible behavior regressed",
59
+ "reproductionRate": "not recorded",
60
+ "attempts": [
61
+ "targeted unit test"
62
+ ],
63
+ "blockedReason": "red/green reproduction is not recorded yet"
64
+ },
65
+ "behaviorEvidence": {
66
+ "status": "blocked",
67
+ "userFacingBoundary": "feature behavior",
68
+ "expectedBehavior": "target behavior succeeds for the user",
69
+ "actualBehavior": "not proven yet",
70
+ "reproductionSteps": [
71
+ "run the targeted verification command"
72
+ ],
73
+ "consistency": "not recorded",
74
+ "domainLanguage": [
75
+ "feature behavior"
76
+ ]
77
+ },
45
78
  "regressionProof": [
46
79
  {
47
80
  "behavior": "original symptom",
@@ -81,6 +114,33 @@
81
114
  "issues": [],
82
115
  "skipReason": "template example is not a UI browser QA scenario"
83
116
  },
117
+ "humanUat": {
118
+ "status": "skipped",
119
+ "required": false,
120
+ "scenario": "",
121
+ "tester": "",
122
+ "evidence": [],
123
+ "failure": "",
124
+ "reroute": "none",
125
+ "skipReason": "not required for this template scenario"
126
+ },
127
+ "architectureFollowUps": [
128
+ {
129
+ "summary": "Add the missing public test seam before widening coverage",
130
+ "currentBehavior": "review proof depends on task metadata instead of a direct behavior seam",
131
+ "desiredBehavior": "tests verify the behavior through a stable public interface",
132
+ "keyInterfaces": [
133
+ "feature public API"
134
+ ],
135
+ "acceptanceCriteria": [
136
+ "target behavior can be reproduced without private implementation hooks"
137
+ ],
138
+ "outOfScope": [
139
+ "rewriting unrelated modules"
140
+ ],
141
+ "status": "deferred-minor"
142
+ }
143
+ ],
84
144
  "tddException": null
85
145
  },
86
146
  "quickGates": [
@@ -140,6 +200,7 @@
140
200
  "summary": "T002 spec review proof is missing",
141
201
  "evidence": "planning/task-manifest.json tasks[T002].reviews.spec is empty",
142
202
  "action": "reroute-cc-do",
203
+ "rescueAction": "record spec review proof for T002 or return to cc-do",
143
204
  "triageStatus": "clarification-needed",
144
205
  "confidenceScore": 9,
145
206
  "fingerprint": "task-review:T002:missing-spec-review",
@@ -16,6 +16,17 @@
16
16
 
17
17
  所有通过结论都必须来自本次新鲜证据;旧输出只能当线索,不能直接继承 verdict。
18
18
 
19
+ ## QA Feedback Loop
20
+
21
+ 行为变更和 bugfix 的 evidence 还必须说明反馈环:
22
+
23
+ - `mode`:failing test、curl / HTTP、CLI fixture、browser、trace replay、bisect、differential loop 等
24
+ - `determinism`:反馈是否稳定,flaky 时复现率是多少
25
+ - `signalSharpness`:失败是否指向目标行为,而不是语法、fixture 或 mock 问题
26
+ - `blockedReason`:无法建立 loop 时缺少什么 artifact、权限、服务或输入
27
+
28
+ 没有可信 loop 的 bugfix 默认不能 `pass`。
29
+
19
30
  ## Reroute
20
31
 
21
32
  - `none`
@@ -98,15 +98,29 @@ Review finding 不只是“发现过”,必须有处置结果:
98
98
 
99
99
  Review 必须判断测试是否证明行为:
100
100
 
101
+ - 反馈环是否可信:速度、确定性、信号锋利度、复现率是否足够支撑结论
102
+ - bugfix 是否复现并覆盖了用户描述的原始症状,而不是附近的另一个失败
103
+ - expected / actual / reproduction steps 是否能让 reviewer 独立复现或判断缺件
101
104
  - 回归测试是否有 red/green 证据
102
105
  - red 是否因为目标行为缺失而失败
103
106
  - green 是否包含 targeted test 和必要的 broader gate
104
- - mock 是否必要,且没有断言 mock 本身
107
+ - 测试是否通过公共接口覆盖行为
108
+ - mock 是否只停在系统边界,且没有断言 mock 本身或内部调用顺序
105
109
  - 生产代码是否新增 test-only API
106
110
  - integration / contract test 是否比复杂 mock 更直接
111
+ - 如果没有正确测试 seam,是否记录了架构 follow-up,而不是造易碎测试
107
112
  - coverage audit 是否映射真实 codepath / user flow / error state / edge case
108
113
  - UI 或用户路径变更是否有 browser evidence、截图、console 结果,或明确 skip reason
109
114
 
115
+ ## Durable Follow-Up Facts
116
+
117
+ Review 产生的 QA issue 或 follow-up 必须可长期执行:
118
+
119
+ - 用领域语言描述用户或系统行为,不把当前文件路径 / 行号当成唯一真相
120
+ - 写清 current behavior、desired behavior、key interfaces、acceptance criteria、out of scope
121
+ - 独立行为拆成独立条目;有依赖关系时写明顺序
122
+ - `deferred-minor` 只能用于不阻塞本次交付的 minor 项,并且必须进入 `cc-act` follow-up writeback
123
+
110
124
  ## Failure Ownership
111
125
 
112
126
  失败归属必须结构化写入 `runtime.failureOwnership[]`:
@@ -125,6 +139,8 @@ Review 必须判断测试是否证明行为:
125
139
  - `important` / `critical` finding 未处理前,不算通过
126
140
  - `important` / `critical` finding 缺 triageStatus,不算通过
127
141
  - QA test quality 缺失且本次涉及行为变化,至少是 `blocked`
142
+ - 行为变更缺 `qa.feedbackLoop` / `qa.behaviorEvidence` 且没有明确例外,至少是 `blocked`
143
+ - bugfix 没有复现原始症状,也没有解释不可复现原因,不能通过
128
144
  - review freshness 缺失、过期或与当前 head 不一致,不能绿灯
129
145
  - UI / 用户路径变更缺 browser evidence 且无 skip reason,不能绿灯
130
146
  - `runtime.failureOwnership` 仍有 `in-branch` 或 `ambiguous` 未解释失败,不能绿灯
@@ -80,6 +80,22 @@ function deriveVerdict(manifest, quickGates, strictGates, review) {
80
80
  return 'blocked';
81
81
  }
82
82
 
83
+ if (['fail'].includes(review.qa?.feedbackLoop?.status)) {
84
+ return 'fail';
85
+ }
86
+
87
+ if (['blocked', 'pending'].includes(review.qa?.feedbackLoop?.status)) {
88
+ return 'blocked';
89
+ }
90
+
91
+ if (['fail'].includes(review.qa?.behaviorEvidence?.status)) {
92
+ return 'fail';
93
+ }
94
+
95
+ if (['blocked', 'pending'].includes(review.qa?.behaviorEvidence?.status)) {
96
+ return 'blocked';
97
+ }
98
+
83
99
  if (review.status === 'blocked') {
84
100
  return 'blocked';
85
101
  }
@@ -185,6 +201,26 @@ function buildClaimEvidence({ manifest, quickGates, strictGates, review }) {
185
201
  function buildQa(review) {
186
202
  return {
187
203
  status: review.qa?.status || 'skipped',
204
+ feedbackLoop: review.qa?.feedbackLoop || {
205
+ status: 'skipped',
206
+ mode: 'not-applicable',
207
+ commandOrArtifact: '',
208
+ speed: '',
209
+ determinism: '',
210
+ signalSharpness: '',
211
+ reproductionRate: '',
212
+ attempts: [],
213
+ blockedReason: 'not recorded'
214
+ },
215
+ behaviorEvidence: review.qa?.behaviorEvidence || {
216
+ status: 'skipped',
217
+ userFacingBoundary: '',
218
+ expectedBehavior: '',
219
+ actualBehavior: '',
220
+ reproductionSteps: [],
221
+ consistency: '',
222
+ domainLanguage: []
223
+ },
188
224
  regressionProof: review.qa?.regressionProof || [],
189
225
  testQuality: review.qa?.testQuality || [],
190
226
  coverageAudit: review.qa?.coverageAudit || {
@@ -207,6 +243,7 @@ function buildQa(review) {
207
243
  issues: [],
208
244
  skipReason: 'not recorded'
209
245
  },
246
+ architectureFollowUps: review.qa?.architectureFollowUps || [],
210
247
  tddException: review.qa?.tddException || null
211
248
  };
212
249
  }
@@ -63,8 +63,15 @@ jq -e '
63
63
  ((.qa.coverageAudit.status? // "skipped") | IN("pass", "fail", "blocked", "skipped", "pending")) and
64
64
  ((.qa.browserEvidence? // {"status":"skipped"}) | type == "object") and
65
65
  ((.qa.browserEvidence.status? // "skipped") | IN("pass", "fail", "blocked", "skipped", "pending")) and
66
+ ((.qa.feedbackLoop? // {"status":"skipped"}) | type == "object") and
67
+ ((.qa.feedbackLoop.status? // "skipped") | IN("pass", "fail", "blocked", "skipped", "pending")) and
68
+ ((.qa.behaviorEvidence? // {"status":"skipped"}) | type == "object") and
69
+ ((.qa.behaviorEvidence.status? // "skipped") | IN("pass", "fail", "blocked", "skipped", "pending")) and
70
+ ((.qa.architectureFollowUps? // []) | type == "array") and
66
71
  ((.review.findings? // []) | all(.[]; ((.confidenceScore? // 7) | type == "number") and ((.displayTier? // "info") | IN("blocking", "warning", "info", "suppressed")))) and
67
72
  ((.verdict != "pass") or ((.review.freshness.status? // "unknown") | IN("fresh", "not-applicable"))) and
73
+ ((.verdict != "pass") or ((.qa.feedbackLoop.status? // "skipped") | IN("pass", "skipped"))) and
74
+ ((.verdict != "pass") or ((.qa.behaviorEvidence.status? // "skipped") | IN("pass", "skipped"))) and
68
75
  ((.verdict != "pass") or (((.runtime.failureOwnership? // []) | map(select(((.classification? // "") | IN("in-branch", "ambiguous")) and ((.status? // "open") | IN("open", "pending")))) | length) == 0)) and
69
76
  ((.verdict == "pass" and .reroute == "none") or (.verdict != "pass" and .reroute != "none"))
70
77
  ' "$REPORT" >/dev/null
@@ -1,5 +1,23 @@
1
1
  # CC-Do Skill Changelog
2
2
 
3
+ ## v1.6.1 - 2026-04-29
4
+
5
+ - reject parent/child touched-path overlaps when selecting parallel execution surfaces
6
+ - report submodule touches separately so unrelated tasks are not serialized by mere `.gitmodules` presence
7
+ - document quick-lane and wave scheduling gates so small tasks still leave checkpoint, verification, and handoff truth
8
+
9
+ ## v1.6.0 - 2026-04-28
10
+
11
+ - prohibit horizontal TDD execution by requiring one tracer bullet Red/Green/Refactor cycle per observable behavior
12
+ - add test fixture discipline so partial fixtures, type assertions, generated stubs, and mocks must preserve public seam behavior
13
+ - require checkpoints to record fixture risk when test data shortcuts could hide a seam or contract problem
14
+
15
+ ## v1.5.3 - 2026-04-28
16
+
17
+ - require Red evidence to prove behavior through a public seam instead of private methods, internal call counts, or implementation-shaped tests
18
+ - add mock-boundary and test-quality gates to the TDD execution contract so internal collaborators are not mocked as fake proof
19
+ - allow `write-task-checkpoint.sh --tdd-json` and runtime checkpoint schema to preserve structured TDD evidence for recovery and review
20
+
3
21
  ## v1.5.2 - 2026-04-27
4
22
 
5
23
  - require execution evidence that adds human-readable summaries to resolve the runtime output policy first
@@ -23,14 +23,15 @@
23
23
 
24
24
  ## Execution Loop
25
25
 
26
- 1. 读取 `task-manifest.json`,先用 `scripts/select-ready-tasks.sh` 找出当前 ready tasks。
27
- 2. 如果有多于一个 ready task,要先跑 `scripts/detect-file-conflicts.sh`;有共享触点或依赖关系就退回串行。
26
+ 1. 读取 `task-manifest.json`,先用 `scripts/select-ready-tasks.sh` 找出当前 ready tasks 和当前 wave
27
+ 2. 如果有多于一个 ready task,要先跑 `scripts/detect-file-conflicts.sh`;有共享触点、父子路径触点或依赖关系就退回串行。
28
28
  3. 对每个要执行的 task,先用 `scripts/build-task-context.sh` 从 `planning/design.md`、`planning/tasks.md`、`planning/task-manifest.json` 组装上下文,再开始编码。
29
29
  4. 如果当前任务来自 `cc-investigate`,把 `planning/analysis.md` 当成上游合同,不准一边做一边重开调查。
30
30
  5. 进入 TDD 闭环:先红,再绿,再重构。
31
31
  6. 每个关键节点都写 runtime:失败测试、Green 通过、Refactor、Review 结论、阻塞原因。
32
32
  7. 任务实现后,先过 `spec review`,再过 `code review`,review 不通过就回到实现。
33
33
  8. 两道 review 门都通过后,才能把任务标成完成,并把结果留给 `cc-check`。
34
+ 9. quick lane 只允许减少叙事,不允许减少 current task、checkpoint、verification、handoff 和 review gates。
34
35
 
35
36
  ## Local Kit
36
37
 
@@ -50,10 +51,12 @@
50
51
 
51
52
  1. 先写失败测试,再运行到红。
52
53
  2. 确认红灯是预期失败,不是测试写错、fixture 缺失或环境没接上。
53
- 3. 只写让当前测试转绿的最小实现。
54
- 4. 绿后才允许重构。
55
- 5. 重构后必须保持绿。
56
- 6. 测试没先红过,就不能宣称这次变更受 TDD 保护。
54
+ 3. 确认红灯通过公共 seam 证明行为缺失,而不是测私有函数、内部调用次数或临时结构。
55
+ 4. 确认 mock 只发生在系统边界;内部协作者不 mock。
56
+ 5. 只写让当前测试转绿的最小实现。
57
+ 6. 绿后才允许重构。
58
+ 7. 重构后必须保持绿。
59
+ 8. 测试没先红过,或红灯不是公共 seam 上的行为失败,就不能宣称这次变更受 TDD 保护。
57
60
 
58
61
  ## TDD Exception Rule
59
62
 
@@ -78,11 +81,14 @@
78
81
 
79
82
  1. `red_failed`: 已观察到预期失败
80
83
  2. `red_reason_verified`: 红灯原因与目标行为缺失一致
81
- 3. `green_passed`: 当前任务实现转绿
82
- 4. `refactor_done` 或 `refactor_not_needed`
83
- 5. `refactor_green`: 重构后相关测试仍绿
84
- 6. `spec_review_pass`
85
- 7. `code_review_pass`
84
+ 3. `red_seam_verified`: 红灯通过公共接口、调用方流程、CLI/API/UI 或真实边界进入系统
85
+ 4. `red_behavior_verified`: 测试断言用户或调用方可观察行为,不断言内部实现细节
86
+ 5. `mock_boundary_verified`: mock 只在系统边界,内部协作者没有被 mock
87
+ 6. `green_passed`: 当前任务实现转绿
88
+ 7. `refactor_done` 或 `refactor_not_needed`
89
+ 8. `refactor_green`: 重构后相关测试仍绿
90
+ 9. `spec_review_pass`
91
+ 10. `code_review_pass`
86
92
 
87
93
  任何一门失败,都回到实现,不准直接跨过去。
88
94
 
@@ -93,8 +99,9 @@
93
99
  1. 任务处于当前 active phase
94
100
  2. `dependsOn` 已全部满足
95
101
  3. 任务显式允许并行,例如 `[P]`
96
- 4. `touches` / `files` 不冲突
97
- 5. 每个 subagent 都拿到了自己的 task context
102
+ 4. `touches` / `files` 不冲突,且父路径 / 子路径也不重叠
103
+ 5. submodule touches 已被标出;触达 submodule 的任务不能默认拿普通 worktree 隔离
104
+ 6. 每个 subagent 都拿到了自己的 task context
98
105
 
99
106
  少一条,都按顺序执行。
100
107
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cc-do
3
- version: 1.5.2
3
+ version: 1.6.1
4
4
  description: Use when implementing planned tasks, resuming interrupted work, applying a frozen investigation handoff, or landing review feedback after cc-plan or cc-investigate.
5
5
  triggers:
6
6
  - 开始做 T003
@@ -27,16 +27,21 @@ writes:
27
27
  durability: durable
28
28
  required: false
29
29
  when: execution mode uses delegated or team workers
30
+ - path: devflow/changes/<change-key>/meta/change-state.json
31
+ durability: durable
32
+ required: false
33
+ when: pause, resume, dispatch, or quick-lane state changes
30
34
  effects:
31
35
  - code changes
32
36
  - test changes
33
37
  - workspace scratch runtime updates
34
38
  entry_gate:
35
39
  - Read planning/design.md or planning/analysis.md, then planning/tasks.md, planning/task-manifest.json, change-meta.json, related capability specs, and the latest checkpoint before changing code.
36
- - Select only ready tasks whose dependencies and file ownership are clear.
40
+ - Select only ready tasks whose dependencies, wave, touched paths, and file ownership are clear.
41
+ - Reject parallel execution when touched paths overlap by exact path or parent/child path; submodule touches must be isolated unless the task explicitly owns that submodule.
37
42
  - If the current task cannot be restated from canonical artifacts, run a context reset before coding.
38
43
  exit_criteria:
39
- - The current task has red/green evidence, review evidence, and a resumable checkpoint trail.
44
+ - The current task has red/green evidence, public-seam test quality evidence, review evidence, and a resumable checkpoint trail.
40
45
  - Execution leaves the next verifier enough runtime truth to judge the task without chat memory.
41
46
  - The honest next step is cc-check or an explicit reroute.
42
47
  reroutes:
@@ -134,28 +139,38 @@ NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
134
139
  3. Refactor:只有 Green 之后才能清理命名、重复、结构和坏味道。
135
140
  4. Record:每一站都写入 `checkpoint.json`,必要时写入 `events.jsonl`。
136
141
 
142
+ Red 不是形式上的红,而是公共 seam 上的行为缺失证明。测试必须通过公共接口、调用方流程、CLI/API/UI 路径或其它真实边界进入系统;只验证私有函数、内部调用次数、临时数据结构或 mock 自己控制的内部协作者,不算 TDD 证据。
143
+
137
144
  例外只能用于 throwaway prototype、纯生成文件、纯配置改动;例外必须写进 checkpoint 的 `tddException`,包含原因、风险和替代验证命令。测试第一次就绿,说明测试没有证明新行为,必须修测试而不是继续写生产代码。
138
145
 
146
+ 禁止水平切片:不要先写一批测试,再写一批实现。每次只推进一个 tracer bullet:一个可观察行为的 Red -> 让它变绿的最小实现 -> 必要重构 -> 记录证据,然后再进入下一个行为。
147
+
148
+ 测试数据也必须诚实。fixture 只提供当前行为需要的最小输入;partial fixture、类型断言、mock payload 或 generated stub 必须写清哪些字段是真实 contract,哪些只是测试填充。不能用 `as`、`any`、双重 cast、缺字段 partial mock 或 test-only method 掩盖 seam 设计问题。
149
+
139
150
  ## Entry Gate
140
151
 
141
152
  1. 先读 `planning/design.md` 或 `planning/analysis.md`,再读 `planning/tasks.md`、`planning/task-manifest.json`;如果是恢复执行,再补读最近 checkpoint 或已有 `handoff/resume-index.md`。
142
153
  2. 先用 `scripts/select-ready-tasks.sh` 判断现在到底哪几个任务真的 ready。
143
- 3. 只锁定当前 ready task,或一组经依赖与触点校验后可并行的 ready tasks。
154
+ 3. 只锁定当前 ready task,或一组经依赖、wave、精确触点与父子路径触点校验后可并行的 ready tasks。
144
155
  4. 如果这次来自 `cc-investigate`,必须把 `planning/analysis.md` 当成 canonical contract,而不是一边实现一边重新调查。
145
156
  5. 没有任务上下文,不准把任务扔给 subagent;先用 `scripts/build-task-context.sh` 从 `planning/design.md` 或 `planning/analysis.md`、`planning/tasks.md`、`planning/task-manifest.json`、`change-meta.json` 与相关 capability spec 组装上下文。
157
+ 6. 如果 `task-manifest.json.metadata.lane == "quick"`,仍然必须有 current task、verification、checkpoint 和 handoff;quick 只缩短文档密度,不跳过证据。
158
+ 7. 如果仓库含 `.gitmodules` 或 manifest 提供 `submodulePaths`,先用 `scripts/detect-file-conflicts.sh` 标出 `submoduleTouches`;只有触达该 submodule 的任务失去默认 worktree 隔离资格,未触达任务不能被无辜串行化。
146
159
 
147
160
  ## Loop
148
161
 
149
162
  1. 读取当前任务,而不是重新发明任务。
150
- 2. 依赖没满足前,不准提前做下游任务。
151
- 3. 没有明确并行资格,不准把多个实现任务同时推进。
163
+ 2. 依赖没满足前,不准提前做下游任务;不同 wave 之间不允许抢跑。
164
+ 3. 没有明确并行资格,不准把多个实现任务同时推进;`touches` 父子路径重叠也算同一执行表面。
152
165
  4. 先 `fail-first`:先写失败测试,先看见预期红,再写生产代码。
153
166
  5. 如果红灯不是预期失败(语法错、fixture 错、测试没连上),先修测试直到它正确失败。
154
- 6. `Red -> Green -> Refactor` 推进,Green 只允许最小实现。
155
- 7. Refactor 后必须重跑相关测试,保持 Green。
156
- 8. 每次推进都写 task runtime:`events.jsonl` + `checkpoint.json`。
157
- 9. 任务实现后,先过 `spec review`,再过 `code review`,两道门都过才算任务收口;这里只验证 spec delta,不回写长期 spec
158
- 10. 当前任务完成后,把可验证证据留给 `cc-check`。
167
+ 6. 如果红灯通过错误 seam 得到,比如私有方法、内部调用次数、mock 内部协作者,先修测试 seam,不准进入 Green
168
+ 7. 按 `Red -> Green -> Refactor` 推进,Green 只允许最小实现。
169
+ 8. 如果当前 Red 需要新的 fixture 或 mock,先证明它仍从公共 seam 触发真实行为;fixture 缺字段、类型强转或内部 mock 都要写入 `tdd.testQuality.fixtureRisk` 或先修 seam。
170
+ 9. Refactor 后必须重跑相关测试,保持 Green
171
+ 10. 每次推进都写 task runtime:`events.jsonl` + `checkpoint.json`,并记录 `tdd.testQuality` 或 `tddException`。
172
+ 11. 任务实现后,先过 `spec review`,再过 `code review`,两道门都过才算任务收口;这里只验证 spec delta,不回写长期 spec。
173
+ 12. 当前任务完成后,把可验证证据留给 `cc-check`。
159
174
 
160
175
  ## Output
161
176
 
@@ -168,8 +183,11 @@ NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
168
183
  ## Good Output
169
184
 
170
185
  - 当前 task 一眼可见,执行者不用从聊天记录里猜目标
171
- - 至少留下一次明确的 Red/Green/Refactor 证据,且 Red 是预期失败
186
+ - 当前 wave、ready tasks、parallel candidates、touch conflict verdict 和 submoduleTouches 一眼可见
187
+ - 至少留下一次明确的 tracer bullet Red/Green/Refactor 证据,且 Red 是公共 seam 上的预期行为失败
188
+ - 测试 fixture 说明真实 contract 字段和测试填充字段,没有用类型欺骗或内部 mock 制造假绿
172
189
  - runtime / checkpoint 足够让下一位接手者无损恢复
190
+ - quick lane 也有 mini manifest、checkpoint、verification 和唯一 next action,不靠聊天记录继续
173
191
  - reviewer 能顺着 review 记录和验证命令复盘这次实现
174
192
 
175
193
  ## Bundled Resources
@@ -194,11 +212,13 @@ NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
194
212
  3. 没有失败测试,不准写生产代码。
195
213
  4. 测试如果第一次就绿,说明你没证明任何东西,先修测试。
196
214
  5. 红灯原因必须和目标行为缺失一致;红灯如果只是测试写错,不算 TDD 证据。
197
- 6. 先过 `spec review`,再过 `code review`,顺序不能反。
198
- 7. 不在 `cc-do` 里改 capability spec 正文;这里只产出实现证据和 spec 对齐证据。
199
- 8. 失败和阻塞都要留下恢复证据。
200
- 9. subagent 的输入必须包含:当前进度、当前任务全文、依赖状态、必读文件、验收标准、可信命令。
201
- 10. 三次失败修补后必须先质疑调查合同或设计合同,而不是继续堆补丁。
215
+ 6. 红灯必须验证公共接口上的行为;实现细节测试、私有方法测试、内部调用次数断言都要先退回 Red 修正。
216
+ 7. Mock 只能放在系统边界;如果必须 mock 内部协作者才能测试,说明 seam 或设计合同有问题。
217
+ 8. 先过 `spec review`,再过 `code review`,顺序不能反。
218
+ 9. 不在 `cc-do` 里改 capability spec 正文;这里只产出实现证据和 spec 对齐证据。
219
+ 10. 失败和阻塞都要留下恢复证据。
220
+ 11. 给 subagent 的输入必须包含:当前进度、当前任务全文、依赖状态、必读文件、验收标准、可信命令。
221
+ 12. 三次失败修补后必须先质疑调查合同或设计合同,而不是继续堆补丁。
202
222
 
203
223
  ## Exit Criteria
204
224
 
@@ -7,6 +7,8 @@
7
7
  - 当前 task status
8
8
  - 当前 active phase
9
9
  - 当前 ready tasks
10
+ - 当前 wave / parallel candidates / touch conflict verdict
11
+ - submoduleTouches(如适用)
10
12
  - 当前 review gates(spec / code)
11
13
  - 已完成证据
12
14
  - 阻塞点
@@ -37,11 +39,14 @@
37
39
  1. `context_ready`
38
40
  2. `red_failed`
39
41
  3. `red_reason_verified`
40
- 4. `green_passed`
41
- 5. `refactor_done` 或 `refactor_not_needed`
42
- 6. `refactor_green`
43
- 7. `spec_review_pass`
44
- 8. `code_review_pass`
42
+ 4. `red_seam_verified`
43
+ 5. `red_behavior_verified`
44
+ 6. `mock_boundary_verified`
45
+ 7. `green_passed`
46
+ 8. `refactor_done` 或 `refactor_not_needed`
47
+ 9. `refactor_green`
48
+ 10. `spec_review_pass`
49
+ 11. `code_review_pass`
45
50
 
46
51
  如果 `events.jsonl` 没开启,至少仍要有最新 `checkpoint.json` 和 manifest review verdict。
47
52
 
@@ -52,9 +57,17 @@
52
57
  - `red.command`
53
58
  - `red.exitStatus`
54
59
  - `red.expectedFailure`
60
+ - `red.testSeam`
61
+ - `red.behaviorAsserted`
62
+ - `red.allowedMocks`
63
+ - `red.implementationDetailRisk`
55
64
  - `green.command`
56
65
  - `green.exitStatus`
57
66
  - `refactor.status`
67
+ - `testQuality.usesPublicInterface`
68
+ - `testQuality.describesBehavior`
69
+ - `testQuality.survivesInternalRefactor`
70
+ - `testQuality.mocksOnlySystemBoundaries`
58
71
  - `review.spec.status`
59
72
  - `review.code.status`
60
73
 
@@ -84,3 +97,4 @@
84
97
  - 验收标准
85
98
  - 验证命令
86
99
  - 不做项 / 边界
100
+ - quick lane 是否仍有 mini manifest、checkpoint、verification 和唯一 next action
@@ -12,17 +12,18 @@
12
12
 
13
13
  1. 两个任务都在当前 active phase
14
14
  2. `dependsOn` 已满足,且互不依赖
15
- 3. `touches` / `files` 没有交集
15
+ 3. `touches` / `files` 没有交集,且没有父路径 / 子路径重叠
16
16
  4. 不共享同一个可变资源,例如同一 schema、同一公共接口、同一全局状态
17
17
  5. 验证命令可以各自独立运行
18
18
  6. 每个任务都有完整上下文包,不需要靠别人的临场解释补脑
19
+ 7. submodule touches 已经被识别;只有实际触达 submodule 的任务失去普通 worktree 隔离资格
19
20
 
20
21
  ## Must Run Sequentially
21
22
 
22
23
  命中任一条,就必须串行:
23
24
 
24
25
  1. 一个任务依赖另一个任务的输出
25
- 2. 两个任务会改同一个文件或同一抽象边界
26
+ 2. 两个任务会改同一个文件、父子路径或同一抽象边界
26
27
  3. 上游任务在定义契约,下游任务在消费契约
27
28
  4. 一个任务先改 schema / API,另一个任务基于它写实现
28
29
  5. 你还不能清楚说出每个任务各自的验收标准
@@ -50,8 +51,9 @@
50
51
 
51
52
  1. 先选当前 active phase 的 ready tasks
52
53
  2. 在 ready tasks 里优先选 `touches` 不重叠的任务
53
- 3. 在不重叠任务里优先选验证面最小的任务
54
- 4. 如果仍然不确定,退回串行
54
+ 3. 在不重叠任务里排除 submodule-touch 隔离风险
55
+ 4. 在剩余任务里优先选验证面最小的任务
56
+ 5. 如果仍然不确定,退回串行
55
57
 
56
58
  ## Good Example
57
59
 
@@ -30,18 +30,41 @@ const sourceTasks = Array.isArray(parsed)
30
30
  const tasks = sourceTasks.filter((task) => task && task.parallel !== false);
31
31
  const fileConflicts = [];
32
32
  const dependencyConflicts = [];
33
+ const submoduleTouches = [];
33
34
  const conflictedTaskIds = new Set();
34
35
 
35
36
  function touchesOf(task) {
36
- return [...new Set([...(task.touches || []), ...(task.files || [])].filter(Boolean))];
37
+ return [...new Set([...(task.touches || []), ...(task.files || [])].filter(Boolean).map(normalizePath))];
38
+ }
39
+
40
+ function normalizePath(value) {
41
+ return String(value)
42
+ .replace(/\\/g, '/')
43
+ .replace(/\/+/g, '/')
44
+ .replace(/^\.\//, '')
45
+ .replace(/\/$/, '');
46
+ }
47
+
48
+ function overlaps(left, right) {
49
+ if (left === right) return left;
50
+ if (left && right.startsWith(`${left}/`)) return left;
51
+ if (right && left.startsWith(`${right}/`)) return right;
52
+ return '';
37
53
  }
38
54
 
39
55
  for (let index = 0; index < tasks.length; index += 1) {
40
56
  for (let offset = index + 1; offset < tasks.length; offset += 1) {
41
57
  const left = tasks[index];
42
58
  const right = tasks[offset];
43
- const leftTouches = new Set(touchesOf(left));
44
- const sharedTouches = touchesOf(right).filter((touch) => leftTouches.has(touch));
59
+ const leftTouches = touchesOf(left);
60
+ const rightTouches = touchesOf(right);
61
+ const sharedTouches = [
62
+ ...new Set(
63
+ leftTouches.flatMap((leftTouch) =>
64
+ rightTouches.map((rightTouch) => overlaps(leftTouch, rightTouch)).filter(Boolean)
65
+ )
66
+ )
67
+ ];
45
68
 
46
69
  if (sharedTouches.length > 0) {
47
70
  conflictedTaskIds.add(left.id);
@@ -68,6 +91,28 @@ for (let index = 0; index < tasks.length; index += 1) {
68
91
  }
69
92
  }
70
93
 
94
+ const submodulePaths = (parsed.submodulePaths || [])
95
+ .map(normalizePath)
96
+ .filter(Boolean);
97
+
98
+ if (submodulePaths.length > 0) {
99
+ for (const task of tasks) {
100
+ const taskTouches = touchesOf(task);
101
+
102
+ for (const submodulePath of submodulePaths) {
103
+ const matchedTouches = taskTouches.filter((touch) => overlaps(submodulePath, touch));
104
+
105
+ if (matchedTouches.length > 0) {
106
+ submoduleTouches.push({
107
+ task: task.id,
108
+ submodulePath,
109
+ touches: matchedTouches
110
+ });
111
+ }
112
+ }
113
+ }
114
+ }
115
+
71
116
  const safeTaskIds = tasks
72
117
  .map((task) => task.id)
73
118
  .filter((taskId) => !conflictedTaskIds.has(taskId));
@@ -78,6 +123,7 @@ process.stdout.write(
78
123
  hasConflicts: fileConflicts.length > 0 || dependencyConflicts.length > 0,
79
124
  fileConflicts,
80
125
  dependencyConflicts,
126
+ submoduleTouches,
81
127
  safeTaskIds
82
128
  },
83
129
  null,
@@ -82,12 +82,25 @@ if [[ -f "$events_file" ]]; then
82
82
  echo "-1"
83
83
  }
84
84
 
85
- red_idx="$(first_index "red_failed")"
86
- green_idx="$(first_index "green_passed")"
87
- if [[ "$red_idx" != "-1" && "$green_idx" != "-1" && "$red_idx" -ge "$green_idx" ]]; then
88
- echo "Task $TASK_ID gate order is invalid" >&2
89
- exit 1
90
- fi
85
+ assert_before() {
86
+ local before="$1"
87
+ local after="$2"
88
+ local before_idx after_idx
89
+ before_idx="$(first_index "$before")"
90
+ after_idx="$(first_index "$after")"
91
+ if [[ "$before_idx" != "-1" && "$after_idx" != "-1" && "$before_idx" -ge "$after_idx" ]]; then
92
+ echo "Task $TASK_ID gate order is invalid: $before must precede $after" >&2
93
+ exit 1
94
+ fi
95
+ }
96
+
97
+ assert_before "red_failed" "red_reason_verified"
98
+ assert_before "red_reason_verified" "red_seam_verified"
99
+ assert_before "red_seam_verified" "red_behavior_verified"
100
+ assert_before "red_behavior_verified" "mock_boundary_verified"
101
+ assert_before "mock_boundary_verified" "green_passed"
102
+ assert_before "red_failed" "green_passed"
103
+ assert_before "green_passed" "refactor_green"
91
104
  fi
92
105
  fi
93
106