cc-devflow 4.5.10 → 4.5.12

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 (187) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +23 -0
  2. package/.claude/skills/cc-act/PLAYBOOK.md +17 -269
  3. package/.claude/skills/cc-act/SKILL.md +38 -418
  4. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_INDEX_TEMPLATE.md +2 -13
  5. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_TEMPLATE.md +1 -9
  6. package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +21 -177
  7. package/.claude/skills/cc-act/references/closure-contract.md +12 -63
  8. package/.claude/skills/cc-act/references/git-commit-guidelines.md +5 -5
  9. package/.claude/skills/cc-act/scripts/cc-act-common.sh +5 -322
  10. package/.claude/skills/cc-act/scripts/detect-ship-target.sh +11 -2
  11. package/.claude/skills/cc-act/scripts/inspect-git-index.sh +58 -0
  12. package/.claude/skills/cc-act/scripts/render-pr-brief.sh +40 -440
  13. package/.claude/skills/cc-act/scripts/verify-act-gate.sh +10 -50
  14. package/.claude/skills/cc-check/CHANGELOG.md +24 -0
  15. package/.claude/skills/cc-check/PLAYBOOK.md +19 -273
  16. package/.claude/skills/cc-check/SKILL.md +33 -454
  17. package/.claude/skills/cc-check/references/review-contract.md +12 -147
  18. package/.claude/skills/cc-dev/CHANGELOG.md +20 -0
  19. package/.claude/skills/cc-dev/PLAYBOOK.md +1 -1
  20. package/.claude/skills/cc-dev/SKILL.md +52 -130
  21. package/.claude/skills/cc-dev/scripts/resolve-cc-devflow.sh +181 -0
  22. package/.claude/skills/cc-do/CHANGELOG.md +17 -0
  23. package/.claude/skills/cc-do/PLAYBOOK.md +19 -113
  24. package/.claude/skills/cc-do/SKILL.md +39 -236
  25. package/.claude/skills/cc-do/references/execution-recovery.md +15 -109
  26. package/.claude/skills/cc-do/scripts/cc-do-common.sh +5 -57
  27. package/.claude/skills/cc-do/scripts/check-task-status.sh +35 -65
  28. package/.claude/skills/cc-do/scripts/mark-task-complete.sh +9 -46
  29. package/.claude/skills/cc-do/scripts/select-ready-tasks.sh +29 -97
  30. package/.claude/skills/cc-investigate/CHANGELOG.md +23 -0
  31. package/.claude/skills/cc-investigate/PLAYBOOK.md +20 -180
  32. package/.claude/skills/cc-investigate/SKILL.md +65 -513
  33. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +48 -95
  34. package/.claude/skills/cc-investigate/references/investigation-contract.md +14 -217
  35. package/.claude/skills/cc-next/CHANGELOG.md +6 -0
  36. package/.claude/skills/cc-next/PLAYBOOK.md +12 -8
  37. package/.claude/skills/cc-next/SKILL.md +34 -140
  38. package/.claude/skills/cc-plan/CHANGELOG.md +29 -0
  39. package/.claude/skills/cc-plan/PLAYBOOK.md +22 -161
  40. package/.claude/skills/cc-plan/SKILL.md +47 -640
  41. package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +30 -225
  42. package/.claude/skills/cc-plan/references/planning-contract.md +24 -160
  43. package/.claude/skills/cc-plan/scripts/next-change-key.sh +8 -44
  44. package/.claude/skills/cc-plan/scripts/parse-task-dependencies.js +2 -2
  45. package/.claude/skills/cc-plan/scripts/validate-scope.sh +1 -1
  46. package/.claude/skills/cc-pr-land/SKILL.md +14 -114
  47. package/.claude/skills/cc-pr-review/CHANGELOG.md +4 -0
  48. package/.claude/skills/cc-pr-review/SKILL.md +20 -103
  49. package/.claude/skills/cc-review/CHANGELOG.md +17 -0
  50. package/.claude/skills/cc-review/PLAYBOOK.md +13 -86
  51. package/.claude/skills/cc-review/SKILL.md +53 -241
  52. package/.claude/skills/cc-review/references/e2e-and-plugin-verification.md +2 -2
  53. package/.claude/skills/cc-review/references/implementation-review-branch.md +7 -147
  54. package/.claude/skills/cc-review/references/plan-review-branch.md +5 -147
  55. package/.claude/skills/cc-review/references/review-methods.md +10 -218
  56. package/.claude/skills/cc-review/scripts/collect-review-context.sh +4 -63
  57. package/.claude/skills/cc-roadmap/PLAYBOOK.md +1 -1
  58. package/.claude/skills/cc-roadmap/SKILL.md +3 -3
  59. package/.claude/skills/cc-simplify/CHANGELOG.md +7 -0
  60. package/.claude/skills/cc-simplify/SKILL.md +26 -21
  61. package/.claude/skills/cc-spec-init/PLAYBOOK.md +12 -48
  62. package/.claude/skills/cc-spec-init/SKILL.md +29 -132
  63. package/.claude/skills/cc-spec-init/references/spec-contract.md +8 -17
  64. package/CHANGELOG.md +27 -0
  65. package/README.md +5 -3
  66. package/README.zh-CN.md +5 -3
  67. package/bin/cc-devflow-cli.js +20 -260
  68. package/bin/cc-devflow.js +44 -7
  69. package/docs/commands/README.md +1 -1
  70. package/docs/commands/README.zh-CN.md +1 -1
  71. package/docs/examples/README.md +1 -1
  72. package/docs/examples/START-HERE.md +14 -14
  73. package/docs/examples/example-bindings.json +11 -11
  74. package/docs/examples/full-design-blocked/README.md +4 -6
  75. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/{planning/tasks.md → task.md} +20 -15
  76. package/docs/examples/local-handoff/README.md +8 -11
  77. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/pr-brief.md +31 -0
  78. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/{planning/tasks.md → task.md} +18 -13
  79. package/docs/examples/pdca-loop/README.md +6 -9
  80. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/pr-brief.md +9 -11
  81. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/{planning/tasks.md → task.md} +18 -13
  82. package/docs/examples/scripts/check-example-bindings.sh +11 -62
  83. package/docs/guides/artifact-contract.md +10 -36
  84. package/docs/guides/getting-started.md +8 -7
  85. package/docs/guides/getting-started.zh-CN.md +8 -7
  86. package/docs/guides/minimize-artifacts.md +16 -116
  87. package/docs/guides/project-postmortem.md +14 -71
  88. package/lib/compiler/__tests__/skills-registry.test.js +9 -8
  89. package/lib/compiler/resource-copier.js +29 -0
  90. package/lib/skill-runtime/__tests__/archive-change.test.js +2 -2
  91. package/lib/skill-runtime/__tests__/benchmark-skills.test.js +109 -0
  92. package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +14 -4
  93. package/lib/skill-runtime/errors.js +3 -3
  94. package/lib/skill-runtime/index.js +5 -23
  95. package/lib/skill-runtime/paths.js +5 -52
  96. package/lib/skill-runtime/query-registry.js +4 -4
  97. package/lib/skill-runtime/query.js +89 -201
  98. package/lib/skill-runtime/store.js +4 -40
  99. package/lib/skill-runtime/trace.js +2 -2
  100. package/package.json +5 -7
  101. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_PRINCIPLES_TEMPLATE.md +0 -29
  102. package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +0 -54
  103. package/.claude/skills/cc-act/scripts/generate-status-report.sh +0 -92
  104. package/.claude/skills/cc-act/scripts/sync-act-docs.sh +0 -355
  105. package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +0 -234
  106. package/.claude/skills/cc-check/scripts/render-report-card.js +0 -438
  107. package/.claude/skills/cc-check/scripts/verify-gate.sh +0 -85
  108. package/.claude/skills/cc-do/scripts/build-task-context.sh +0 -175
  109. package/.claude/skills/cc-do/scripts/record-review-decision.sh +0 -88
  110. package/.claude/skills/cc-do/scripts/recover-workflow.sh +0 -82
  111. package/.claude/skills/cc-do/scripts/run-problem-analysis.sh +0 -70
  112. package/.claude/skills/cc-do/scripts/verify-task-gates.sh +0 -109
  113. package/.claude/skills/cc-do/scripts/write-task-checkpoint.sh +0 -92
  114. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +0 -225
  115. package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +0 -179
  116. package/.claude/skills/cc-spec-init/assets/CHANGE_META_TEMPLATE.json +0 -28
  117. package/.claude/skills/cc-spec-init/scripts/validate-spec-links.sh +0 -45
  118. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +0 -234
  119. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +0 -488
  120. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/review/report-card.json +0 -189
  121. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/resume-index.md +0 -39
  122. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/status.md +0 -29
  123. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +0 -123
  124. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +0 -292
  125. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/review/report-card.json +0 -136
  126. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/status.md +0 -29
  127. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +0 -124
  128. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +0 -292
  129. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/review/report-card.json +0 -136
  130. package/docs/get-shit-done-strategy-audit.md +0 -518
  131. package/docs/skill-runtime-migration.md +0 -46
  132. package/lib/skill-runtime/__tests__/approve.test.js +0 -92
  133. package/lib/skill-runtime/__tests__/autopilot.test.js +0 -253
  134. package/lib/skill-runtime/__tests__/benchmark-artifacts.test.js +0 -165
  135. package/lib/skill-runtime/__tests__/delegation.test.js +0 -97
  136. package/lib/skill-runtime/__tests__/dispatch.test.js +0 -237
  137. package/lib/skill-runtime/__tests__/intent.test.js +0 -203
  138. package/lib/skill-runtime/__tests__/lifecycle.test.js +0 -169
  139. package/lib/skill-runtime/__tests__/planner.tdd.test.js +0 -331
  140. package/lib/skill-runtime/__tests__/prepare-pr.test.js +0 -126
  141. package/lib/skill-runtime/__tests__/query.test.js +0 -860
  142. package/lib/skill-runtime/__tests__/readiness.test.js +0 -53
  143. package/lib/skill-runtime/__tests__/release.test.js +0 -85
  144. package/lib/skill-runtime/__tests__/review-check-integration.test.js +0 -148
  145. package/lib/skill-runtime/__tests__/review-records.test.js +0 -619
  146. package/lib/skill-runtime/__tests__/runtime.integration.test.js +0 -351
  147. package/lib/skill-runtime/__tests__/schemas.test.js +0 -337
  148. package/lib/skill-runtime/__tests__/task-contract-migrate.test.js +0 -137
  149. package/lib/skill-runtime/__tests__/task-contract.test.js +0 -783
  150. package/lib/skill-runtime/__tests__/team-state.test.js +0 -51
  151. package/lib/skill-runtime/__tests__/verify-artifacts.test.js +0 -203
  152. package/lib/skill-runtime/__tests__/worker-run.test.js +0 -275
  153. package/lib/skill-runtime/__tests__/worker.test.js +0 -56
  154. package/lib/skill-runtime/__tests__/workflow-context-legacy-fallback.test.js +0 -31
  155. package/lib/skill-runtime/__tests__/workflow-context.test.js +0 -98
  156. package/lib/skill-runtime/artifacts.js +0 -88
  157. package/lib/skill-runtime/context-index.js +0 -545
  158. package/lib/skill-runtime/delegation.js +0 -533
  159. package/lib/skill-runtime/intent.js +0 -309
  160. package/lib/skill-runtime/lifecycle.js +0 -294
  161. package/lib/skill-runtime/operations/CLAUDE.md +0 -19
  162. package/lib/skill-runtime/operations/approve.js +0 -81
  163. package/lib/skill-runtime/operations/autopilot-core.js +0 -337
  164. package/lib/skill-runtime/operations/autopilot-execution.js +0 -307
  165. package/lib/skill-runtime/operations/autopilot-shared.js +0 -48
  166. package/lib/skill-runtime/operations/autopilot.js +0 -163
  167. package/lib/skill-runtime/operations/dispatch.js +0 -416
  168. package/lib/skill-runtime/operations/init.js +0 -60
  169. package/lib/skill-runtime/operations/janitor.js +0 -61
  170. package/lib/skill-runtime/operations/plan.js +0 -59
  171. package/lib/skill-runtime/operations/prepare-pr.js +0 -25
  172. package/lib/skill-runtime/operations/release.js +0 -99
  173. package/lib/skill-runtime/operations/resume.js +0 -126
  174. package/lib/skill-runtime/operations/review-records.js +0 -265
  175. package/lib/skill-runtime/operations/snapshot.js +0 -45
  176. package/lib/skill-runtime/operations/task-contract.js +0 -524
  177. package/lib/skill-runtime/operations/verify.js +0 -170
  178. package/lib/skill-runtime/operations/worker-run.js +0 -531
  179. package/lib/skill-runtime/operations/worker.js +0 -33
  180. package/lib/skill-runtime/planner.js +0 -539
  181. package/lib/skill-runtime/readiness.js +0 -84
  182. package/lib/skill-runtime/review-records.js +0 -123
  183. package/lib/skill-runtime/review.js +0 -855
  184. package/lib/skill-runtime/schemas.js +0 -746
  185. package/lib/skill-runtime/task-contract.js +0 -187
  186. package/lib/skill-runtime/team-state.js +0 -122
  187. package/lib/skill-runtime/workflow-context.js +0 -748
@@ -1,253 +0,0 @@
1
- const fs = require('fs');
2
- const os = require('os');
3
- const path = require('path');
4
-
5
- const { runAutopilot } = require('../operations/autopilot');
6
- const { runApprove } = require('../operations/approve');
7
- const {
8
- getTasksMarkdownPath,
9
- getTaskManifestPath,
10
- getReportCardPath,
11
- getReleaseNotePath,
12
- getRuntimeStatePath
13
- } = require('../store');
14
- const {
15
- getIntentResumeIndexPath,
16
- getIntentPrBriefPath
17
- } = require('../artifacts');
18
- const { getChangePaths } = require('../paths');
19
-
20
- jest.setTimeout(20000);
21
-
22
- function writeJson(filePath, value) {
23
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
24
- fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
25
- }
26
-
27
- function markManifestReviewsPassed(repoRoot, changeId) {
28
- const manifestPath = getTaskManifestPath(repoRoot, changeId);
29
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
30
- manifest.tasks = manifest.tasks.map((task) => ({
31
- ...task,
32
- reviews: {
33
- spec: 'pass',
34
- code: 'pass'
35
- }
36
- }));
37
- manifest.spec = manifest.spec || {
38
- primaryCapability: 'autopilot-runtime',
39
- specFiles: ['devflow/specs/autopilot-runtime.md']
40
- };
41
- fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
42
- }
43
-
44
- function writeCleanReviewLedger(repoRoot, changeId) {
45
- const change = getChangePaths(repoRoot, changeId);
46
- const ledgerPath = path.join(change.reviewDir, 'review-ledger.jsonl');
47
- fs.mkdirSync(path.dirname(ledgerPath), { recursive: true });
48
- fs.writeFileSync(ledgerPath, [
49
- JSON.stringify({
50
- schema: 'review-ledger.v2',
51
- change: change.changeKey,
52
- reviewId: 'RVW-20260512-001',
53
- createdAt: '2026-05-12T00:00:00.000Z',
54
- createdBy: 'cc-devflow-cli',
55
- event: 'review-started',
56
- mode: 'implementation',
57
- scope: 'current-diff',
58
- baseSha: 'abc123',
59
- headSha: 'def456',
60
- selectedNodes: [],
61
- skippedNodes: [],
62
- riskLanes: []
63
- }),
64
- JSON.stringify({
65
- schema: 'review-ledger.v2',
66
- change: change.changeKey,
67
- reviewId: 'RVW-20260512-001',
68
- createdAt: '2026-05-12T00:01:00.000Z',
69
- createdBy: 'cc-devflow-cli',
70
- event: 'review-closed',
71
- status: 'clean',
72
- blockingCount: 0,
73
- warningCount: 0,
74
- next: 'cc-check'
75
- })
76
- ].join('\n'));
77
- }
78
-
79
- describe('runAutopilot', () => {
80
- test('stops at the approval gate after planning without writing approval-phase handoff markdown', async () => {
81
- const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-autopilot-'));
82
-
83
- writeJson(path.join(repoRoot, 'package.json'), {
84
- name: 'autopilot-smoke',
85
- version: '1.0.0',
86
- scripts: {
87
- lint: 'node -e "process.exit(0)"',
88
- typecheck: 'node -e "process.exit(0)"',
89
- test: 'node -e "process.exit(0)"'
90
- }
91
- });
92
-
93
- const goal = 'Ship thin autopilot loop';
94
- fs.mkdirSync(path.dirname(getTasksMarkdownPath(repoRoot, 'REQ-123', { goal })), { recursive: true });
95
- fs.writeFileSync(
96
- getTasksMarkdownPath(repoRoot, 'REQ-123', { goal }),
97
- [
98
- '- [ ] T001 启动 autopilot 闭环 (src/a.ts)',
99
- '- [ ] T002 多文件委派任务 [P] (src/a.ts,src/b.ts)'
100
- ].join('\n')
101
- );
102
-
103
- const result = await runAutopilot({
104
- repoRoot,
105
- changeId: 'REQ-123',
106
- goal
107
- });
108
-
109
- const runtimeState = JSON.parse(fs.readFileSync(getRuntimeStatePath(repoRoot, 'REQ-123'), 'utf8'));
110
-
111
- expect(result.executed).toEqual(['init', 'snapshot', 'plan']);
112
- expect(result.currentStage).toBe('approve');
113
- expect(runtimeState.changeKey).toBe('REQ-123-ship-thin-autopilot-loop');
114
- expect(fs.existsSync(getReportCardPath(repoRoot, 'REQ-123'))).toBe(false);
115
- expect(fs.existsSync(getIntentPrBriefPath(repoRoot, 'REQ-123'))).toBe(false);
116
- expect(fs.existsSync(getIntentResumeIndexPath(repoRoot, 'REQ-123'))).toBe(false);
117
- });
118
-
119
- test('resumes after approval, executes delegated work, and prepares a PR from task state', async () => {
120
- const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-autopilot-workers-'));
121
-
122
- writeJson(path.join(repoRoot, 'package.json'), {
123
- name: 'autopilot-worker-smoke',
124
- version: '1.0.0',
125
- scripts: {
126
- lint: 'node -e "process.exit(0)"',
127
- typecheck: 'node -e "process.exit(0)"',
128
- test: 'node -e "process.exit(0)"'
129
- }
130
- });
131
-
132
- const goal = 'Ship thin autopilot loop with delegated workers';
133
- fs.mkdirSync(path.dirname(getTasksMarkdownPath(repoRoot, 'REQ-123', { goal })), { recursive: true });
134
- fs.writeFileSync(
135
- getTasksMarkdownPath(repoRoot, 'REQ-123', { goal }),
136
- [
137
- '- [ ] T001 直接执行任务 (src/a.ts)',
138
- '- [ ] T002 委派实现任务 [P] (src/a.ts,src/b.ts)'
139
- ].join('\n')
140
- );
141
-
142
- await runAutopilot({
143
- repoRoot,
144
- changeId: 'REQ-123',
145
- goal
146
- });
147
-
148
- await runApprove({
149
- repoRoot,
150
- changeId: 'REQ-123',
151
- executionMode: 'delegate'
152
- });
153
-
154
- const firstRun = await runAutopilot({
155
- repoRoot,
156
- changeId: 'REQ-123',
157
- workerCommand: 'printf "delegate-ok"'
158
- });
159
-
160
- const manifest = JSON.parse(fs.readFileSync(getTaskManifestPath(repoRoot, 'REQ-123'), 'utf8'));
161
- const report = JSON.parse(fs.readFileSync(getReportCardPath(repoRoot, 'REQ-123'), 'utf8'));
162
-
163
- expect(firstRun.executed).toEqual(expect.arrayContaining(['delegate', 'worker-run', 'dispatch', 'verify']));
164
- expect(firstRun.currentStage).toBe('verify');
165
- expect(manifest.tasks.find((task) => task.id === 'T002').status).toBe('passed');
166
- expect(report.review.status).toBe('blocked');
167
- expect(fs.existsSync(getIntentPrBriefPath(repoRoot, 'REQ-123'))).toBe(false);
168
-
169
- markManifestReviewsPassed(repoRoot, 'REQ-123');
170
- writeCleanReviewLedger(repoRoot, 'REQ-123');
171
-
172
- const secondRun = await runAutopilot({
173
- repoRoot,
174
- changeId: 'REQ-123',
175
- from: 'verify',
176
- skipReview: true
177
- });
178
-
179
- const prBrief = fs.readFileSync(getIntentPrBriefPath(repoRoot, 'REQ-123'), 'utf8');
180
-
181
- expect(secondRun.executed).toEqual(expect.arrayContaining(['verify', 'prepare-pr']));
182
- expect(secondRun.currentStage).toBe('prepare-pr');
183
- expect(prBrief).toContain('planning/task-manifest.json');
184
- expect(prBrief).not.toContain('checkpoint.json');
185
- });
186
-
187
- test('runs release after prepare-pr when requested for an approved plan', async () => {
188
- const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-autopilot-release-'));
189
-
190
- writeJson(path.join(repoRoot, 'package.json'), {
191
- name: 'autopilot-release-smoke',
192
- version: '1.0.0',
193
- scripts: {
194
- lint: 'node -e "process.exit(0)"',
195
- typecheck: 'node -e "process.exit(0)"',
196
- test: 'node -e "process.exit(0)"'
197
- }
198
- });
199
-
200
- const goal = 'Ship thin autopilot loop and release';
201
- fs.mkdirSync(path.dirname(getTasksMarkdownPath(repoRoot, 'REQ-123', { goal })), { recursive: true });
202
- fs.writeFileSync(
203
- getTasksMarkdownPath(repoRoot, 'REQ-123', { goal }),
204
- '- [ ] T001 发布前收尾 (src/a.ts)'
205
- );
206
-
207
- await runAutopilot({
208
- repoRoot,
209
- changeId: 'REQ-123',
210
- goal
211
- });
212
-
213
- await runApprove({
214
- repoRoot,
215
- changeId: 'REQ-123',
216
- executionMode: 'direct'
217
- });
218
-
219
- const firstRun = await runAutopilot({
220
- repoRoot,
221
- changeId: 'REQ-123',
222
- release: true
223
- });
224
-
225
- const manifest = JSON.parse(fs.readFileSync(getTaskManifestPath(repoRoot, 'REQ-123'), 'utf8'));
226
- const report = JSON.parse(fs.readFileSync(getReportCardPath(repoRoot, 'REQ-123'), 'utf8'));
227
-
228
- expect(firstRun.currentStage).toBe('verify');
229
- expect(report.review.status).toBe('blocked');
230
- expect(fs.existsSync(getReleaseNotePath(repoRoot, 'REQ-123'))).toBe(false);
231
-
232
- markManifestReviewsPassed(repoRoot, 'REQ-123');
233
- writeCleanReviewLedger(repoRoot, 'REQ-123');
234
-
235
- const result = await runAutopilot({
236
- repoRoot,
237
- changeId: 'REQ-123',
238
- from: 'verify',
239
- release: true,
240
- skipReview: true
241
- });
242
-
243
- const runtimeState = JSON.parse(fs.readFileSync(getRuntimeStatePath(repoRoot, 'REQ-123'), 'utf8'));
244
- const releaseNote = fs.readFileSync(getReleaseNotePath(repoRoot, 'REQ-123'), 'utf8');
245
-
246
- expect(result.executed).toEqual(expect.arrayContaining(['verify', 'prepare-pr', 'release']));
247
- expect(result.lifecycleStatus).toBe('released');
248
- expect(runtimeState.status).toBe('released');
249
- expect(releaseNote).toContain('Release Note - REQ-123');
250
- expect(fs.existsSync(getIntentPrBriefPath(repoRoot, 'REQ-123'))).toBe(false);
251
- expect(fs.existsSync(getIntentResumeIndexPath(repoRoot, 'REQ-123'))).toBe(false);
252
- });
253
- });
@@ -1,165 +0,0 @@
1
- /**
2
- * [INPUT]: 依赖 scripts/benchmark-artifacts.js 导出的 runBenchmarkArtifacts 和临时 artifact fixture。
3
- * [OUTPUT]: 验证 benchmark:artifacts 使用 ceil(len/4) 估算并报告 profile 阈值 savings。
4
- * [POS]: REQ-003-minimize-workflow-artifacts T017 的 Red/Green 证据。
5
- * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
- */
7
-
8
- const fs = require('fs');
9
- const os = require('os');
10
- const path = require('path');
11
- const { spawnSync } = require('child_process');
12
-
13
- const { runBenchmarkArtifacts } = require('../../../scripts/benchmark-artifacts');
14
-
15
- const REPO_ROOT = path.resolve(__dirname, '../../..');
16
- const BENCHMARK_SCRIPT = path.join(REPO_ROOT, 'scripts', 'benchmark-artifacts.js');
17
-
18
- function writeText(filePath, text) {
19
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
20
- fs.writeFileSync(filePath, text);
21
- }
22
-
23
- function writeJson(filePath, value) {
24
- writeText(filePath, `${JSON.stringify(value, null, 2)}\n`);
25
- }
26
-
27
- function contractTasks({ changeKey, profile = 'standard', filler = '' }) {
28
- return [
29
- '# Tasks',
30
- '',
31
- '## Contract Summary',
32
- '',
33
- `Change: ${changeKey}`,
34
- 'Mode: plan',
35
- `Profile: ${profile}`,
36
- 'Approval: approved',
37
- '',
38
- 'Goal:',
39
- '- Minimize workflow artifacts.',
40
- '',
41
- 'Do Not Do:',
42
- '- Do not change token estimator math.',
43
- '',
44
- 'Approved Direction:',
45
- '- Use tasks.md plus generated JSON records.',
46
- '',
47
- 'Acceptance:',
48
- '- Benchmark savings stay above threshold.',
49
- '',
50
- 'Verification:',
51
- '',
52
- '```bash',
53
- 'npm run benchmark:artifacts',
54
- '```',
55
- '',
56
- 'Risk / Escalate If:',
57
- '- Savings fall below profile threshold.',
58
- '',
59
- filler,
60
- '## Phase 1',
61
- '',
62
- '- [ ] T001 benchmark minimized artifact surface',
63
- ' Vertical slice: Slice 1',
64
- ''
65
- ].join('\n');
66
- }
67
-
68
- function seedLegacyBaseline(repoRoot, changeKey, size = 6000) {
69
- const changeDir = path.join(repoRoot, 'devflow', 'changes', changeKey);
70
- writeText(path.join(changeDir, 'planning', 'design.md'), `# Design\n\n${'d'.repeat(size)}\n`);
71
- writeText(path.join(changeDir, 'planning', 'analysis.md'), `# Analysis\n\n${'a'.repeat(size / 2)}\n`);
72
- writeText(path.join(changeDir, 'planning', 'tasks.md'), `# Tasks\n\n${'t'.repeat(size / 2)}\n`);
73
- writeJson(path.join(changeDir, 'planning', 'task-manifest.json'), { changeId: changeKey, tasks: [] });
74
- writeJson(path.join(changeDir, 'change-meta.json'), { changeId: changeKey, goal: ['legacy'] });
75
- writeJson(path.join(changeDir, 'review', 'report-card.json'), { overall: 'pass' });
76
- }
77
-
78
- function seedMinimizedChange(repoRoot, changeKey, options = {}) {
79
- const changeDir = path.join(repoRoot, 'devflow', 'changes', changeKey);
80
- writeText(path.join(changeDir, 'planning', 'tasks.md'), contractTasks({ changeKey, ...options }));
81
- writeJson(path.join(changeDir, 'planning', 'task-manifest.json'), {
82
- changeId: changeKey,
83
- metadata: { source: 'tasks.md', generatedBy: 'cc-devflow task-contract', planVersion: 1 },
84
- tasks: []
85
- });
86
- writeJson(path.join(changeDir, 'change-meta.json'), {
87
- changeId: changeKey,
88
- _meta: { generatedBy: 'cc-devflow task-contract' }
89
- });
90
- writeJson(path.join(changeDir, 'review', 'review-ledger.jsonl'), { note: 'counted as text by benchmark' });
91
- writeJson(path.join(changeDir, 'review', 'review-findings.json'), { findings: [] });
92
- writeJson(path.join(changeDir, 'review', 'report-card.json'), { overall: 'pass' });
93
- }
94
-
95
- describe('benchmark:artifacts', () => {
96
- let repoRoot;
97
-
98
- beforeEach(() => {
99
- repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-benchmark-artifacts-'));
100
- seedLegacyBaseline(repoRoot, 'REQ-001-legacy-baseline');
101
- seedLegacyBaseline(repoRoot, 'REQ-002-legacy-baseline');
102
- });
103
-
104
- afterEach(() => {
105
- fs.rmSync(repoRoot, { recursive: true, force: true });
106
- });
107
-
108
- test('reports standard savings >= 30% for REQ-003-example', () => {
109
- seedMinimizedChange(repoRoot, 'REQ-003-example', { profile: 'standard' });
110
-
111
- const result = runBenchmarkArtifacts(repoRoot);
112
- const row = result.rows.find((item) => item.changeKey === 'REQ-003-example');
113
-
114
- expect(result.code).toBe(0);
115
- expect(row).toMatchObject({
116
- profile: 'standard',
117
- threshold_pct: 30,
118
- correctness_pass: true
119
- });
120
- expect(row.savings_vs_baseline_pct).toBeGreaterThanOrEqual(30);
121
- });
122
-
123
- test('reports tiny savings >= 60% for tiny fixture', () => {
124
- seedMinimizedChange(repoRoot, 'REQ-004-tiny-example', { profile: 'tiny' });
125
-
126
- const result = runBenchmarkArtifacts(repoRoot);
127
- const row = result.rows.find((item) => item.changeKey === 'REQ-004-tiny-example');
128
-
129
- expect(result.code).toBe(0);
130
- expect(row).toMatchObject({
131
- profile: 'tiny',
132
- threshold_pct: 60,
133
- correctness_pass: true
134
- });
135
- expect(row.savings_vs_baseline_pct).toBeGreaterThanOrEqual(60);
136
- });
137
-
138
- test('exits 1 when savings are below the profile threshold', () => {
139
- seedMinimizedChange(repoRoot, 'REQ-005-bloated-example', {
140
- profile: 'standard',
141
- filler: 'x'.repeat(20000)
142
- });
143
-
144
- const result = runBenchmarkArtifacts(repoRoot);
145
-
146
- expect(result.code).toBe(1);
147
- expect(result.rows[0]).toMatchObject({ correctness_pass: false });
148
- });
149
-
150
- test('CLI prints stdout JSON array', () => {
151
- seedMinimizedChange(repoRoot, 'REQ-003-example', { profile: 'standard' });
152
-
153
- const result = spawnSync(process.execPath, [BENCHMARK_SCRIPT, repoRoot], { encoding: 'utf8' });
154
- const rows = JSON.parse(result.stdout);
155
-
156
- expect(result.status).toBe(0);
157
- expect(Array.isArray(rows)).toBe(true);
158
- expect(rows[0]).toHaveProperty('savings_vs_baseline_pct');
159
- });
160
-
161
- test('package.json exposes npm run benchmark:artifacts', () => {
162
- const pkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8'));
163
- expect(pkg.scripts['benchmark:artifacts']).toBe('node scripts/benchmark-artifacts.js');
164
- });
165
- });
@@ -1,97 +0,0 @@
1
- const fs = require('fs');
2
- const os = require('os');
3
- const path = require('path');
4
-
5
- const {
6
- syncDelegationRuntime,
7
- ensureWorkerWorkspace,
8
- getWorkerStatePath,
9
- getWorkerJournalPath,
10
- getWorkerAssignmentPath,
11
- getMessageBusPath,
12
- getTeamMemoryPath,
13
- getWorkerWorkspacePath
14
- } = require('../delegation');
15
- const { getTeamStatePath } = require('../team-state');
16
-
17
- describe('syncDelegationRuntime', () => {
18
- test('writes workspace scratch files and team-state truth without polluting devflow/changes', async () => {
19
- const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-delegation-'));
20
- fs.writeFileSync(path.join(repoRoot, 'package.json'), JSON.stringify({ name: 'delegation-smoke', version: '1.0.0' }, null, 2));
21
-
22
- const manifest = {
23
- changeId: 'REQ-123',
24
- goal: 'Delegate selected tasks',
25
- createdAt: '2026-03-25T01:00:00.000Z',
26
- updatedAt: '2026-03-25T01:01:00.000Z',
27
- tasks: [
28
- {
29
- id: 'T001',
30
- title: 'Single file direct task',
31
- type: 'IMPL',
32
- dependsOn: [],
33
- touches: ['src/a.ts'],
34
- run: ['echo direct'],
35
- checks: [],
36
- status: 'pending',
37
- attempts: 0,
38
- maxRetries: 1
39
- },
40
- {
41
- id: 'T002',
42
- title: 'Multi file delegated task',
43
- type: 'IMPL',
44
- dependsOn: [],
45
- touches: ['src/a.ts', 'src/b.ts'],
46
- run: ['echo delegated'],
47
- checks: [],
48
- status: 'pending',
49
- attempts: 0,
50
- maxRetries: 1
51
- }
52
- ],
53
- metadata: {
54
- source: 'default',
55
- generatedBy: 'test',
56
- planVersion: 3
57
- }
58
- };
59
-
60
- const result = await syncDelegationRuntime(repoRoot, 'REQ-123', manifest);
61
-
62
- const teamState = JSON.parse(fs.readFileSync(getTeamStatePath(repoRoot, 'REQ-123'), 'utf8'));
63
- const workerId = teamState.team.taskAssignments.T002;
64
- const assignment = fs.readFileSync(getWorkerAssignmentPath(repoRoot, 'REQ-123', workerId), 'utf8');
65
- const messageBus = fs.readFileSync(getMessageBusPath(repoRoot, 'REQ-123'), 'utf8');
66
- const teamMemory = fs.readFileSync(getTeamMemoryPath(repoRoot, 'REQ-123'), 'utf8');
67
- const workerState = fs.readFileSync(getWorkerStatePath(repoRoot, 'REQ-123', workerId), 'utf8');
68
- const workerJournal = fs.readFileSync(getWorkerJournalPath(repoRoot, 'REQ-123', workerId), 'utf8');
69
- const workerWorkspace = getWorkerWorkspacePath(repoRoot, 'REQ-123', workerId);
70
-
71
- expect(result.delegatedCount).toBe(1);
72
- expect(assignment).toContain(`Assignment: ${workerId}`);
73
- expect(assignment).toContain('`T002` Multi file delegated task');
74
- expect(messageBus).toContain('queued for T002');
75
- expect(teamMemory).toContain('Worker Count: 1');
76
- expect(teamState.planVersion).toBe(3);
77
- expect(workerId).toMatch(/^delegate-/);
78
- expect(workerState).toContain('Status: `idle`');
79
- expect(workerJournal).toContain('Assigned Tasks: T002');
80
- expect(workerWorkspace).toContain('devflow/workspaces');
81
- expect(fs.existsSync(path.join(repoRoot, 'devflow/changes/REQ-123-delegate-selected-tasks/execution/workers'))).toBe(false);
82
- });
83
-
84
- test('falls back to controller workspace when git worktree is unavailable', async () => {
85
- const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-no-git-'));
86
- const worker = await ensureWorkerWorkspace(repoRoot, 'REQ-123', {
87
- taskId: 'T001',
88
- workerId: 'delegate-01',
89
- role: 'dev-implementer',
90
- route: 'delegate'
91
- });
92
-
93
- expect(worker.mode).toBe('fallback');
94
- expect(worker.cwd).toBe(repoRoot);
95
- expect(worker.reason).toBe('git-unavailable');
96
- });
97
- });