cc-devflow 4.5.8 → 4.5.10

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 (149) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +33 -0
  2. package/.claude/skills/cc-act/PLAYBOOK.md +9 -4
  3. package/.claude/skills/cc-act/SKILL.md +73 -12
  4. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_INDEX_TEMPLATE.md +30 -0
  5. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_PRINCIPLES_TEMPLATE.md +29 -0
  6. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_TEMPLATE.md +103 -0
  7. package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +61 -5
  8. package/.claude/skills/cc-act/references/closure-contract.md +4 -1
  9. package/.claude/skills/cc-act/references/git-commit-guidelines.md +342 -37
  10. package/.claude/skills/cc-act/scripts/cc-act-common.sh +29 -1
  11. package/.claude/skills/cc-act/scripts/render-pr-brief.sh +164 -0
  12. package/.claude/skills/cc-act/scripts/sync-act-docs.sh +1 -1
  13. package/.claude/skills/cc-check/CHANGELOG.md +17 -0
  14. package/.claude/skills/cc-check/PLAYBOOK.md +1 -0
  15. package/.claude/skills/cc-check/SKILL.md +9 -5
  16. package/.claude/skills/cc-check/references/review-contract.md +7 -0
  17. package/.claude/skills/cc-check/scripts/render-report-card.js +6 -1
  18. package/.claude/skills/cc-dev/CHANGELOG.md +5 -0
  19. package/.claude/skills/cc-dev/SKILL.md +26 -1
  20. package/.claude/skills/cc-do/CHANGELOG.md +23 -0
  21. package/.claude/skills/cc-do/PLAYBOOK.md +7 -7
  22. package/.claude/skills/cc-do/SKILL.md +49 -45
  23. package/.claude/skills/cc-do/references/execution-recovery.md +18 -13
  24. package/.claude/skills/cc-do/scripts/build-task-context.sh +13 -22
  25. package/.claude/skills/cc-do/scripts/mark-task-complete.sh +0 -6
  26. package/.claude/skills/cc-do/scripts/record-review-decision.sh +4 -5
  27. package/.claude/skills/cc-do/scripts/recover-workflow.sh +9 -11
  28. package/.claude/skills/cc-do/scripts/verify-task-gates.sh +12 -10
  29. package/.claude/skills/cc-do/scripts/write-task-checkpoint.sh +7 -29
  30. package/.claude/skills/cc-investigate/CHANGELOG.md +34 -0
  31. package/.claude/skills/cc-investigate/PLAYBOOK.md +21 -5
  32. package/.claude/skills/cc-investigate/SKILL.md +97 -40
  33. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +66 -4
  34. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +30 -59
  35. package/.claude/skills/cc-investigate/assets/{ANALYSIS_TEMPLATE.md → legacy/ANALYSIS_TEMPLATE.md} +48 -0
  36. package/.claude/skills/cc-investigate/references/investigation-contract.md +16 -2
  37. package/.claude/skills/cc-investigate/scripts/bootstrap-analysis.sh +1 -1
  38. package/.claude/skills/cc-next/CHANGELOG.md +6 -0
  39. package/.claude/skills/cc-next/PLAYBOOK.md +26 -4
  40. package/.claude/skills/cc-next/SKILL.md +39 -4
  41. package/.claude/skills/cc-plan/CHANGELOG.md +38 -0
  42. package/.claude/skills/cc-plan/PLAYBOOK.md +60 -53
  43. package/.claude/skills/cc-plan/SKILL.md +164 -87
  44. package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +101 -9
  45. package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +58 -229
  46. package/.claude/skills/cc-plan/assets/{DESIGN_TEMPLATE.md → legacy/DESIGN_TEMPLATE.md} +68 -0
  47. package/.claude/skills/cc-plan/assets/{TINY_DESIGN_TEMPLATE.md → legacy/TINY_DESIGN_TEMPLATE.md} +47 -1
  48. package/.claude/skills/cc-plan/references/planning-contract.md +48 -33
  49. package/.claude/skills/cc-review/CHANGELOG.md +6 -0
  50. package/.claude/skills/cc-review/PLAYBOOK.md +9 -11
  51. package/.claude/skills/cc-review/SKILL.md +37 -61
  52. package/.claude/skills/cc-review/references/e2e-and-plugin-verification.md +1 -1
  53. package/.claude/skills/cc-review/references/implementation-review-branch.md +5 -5
  54. package/.claude/skills/cc-review/references/plan-review-branch.md +1 -1
  55. package/.claude/skills/cc-review/references/review-methods.md +4 -4
  56. package/.claude/skills/cc-review/scripts/collect-review-context.sh +14 -7
  57. package/.claude/skills/cc-roadmap/CHANGELOG.md +6 -0
  58. package/.claude/skills/cc-roadmap/PLAYBOOK.md +30 -0
  59. package/.claude/skills/cc-roadmap/SKILL.md +45 -8
  60. package/.claude/skills/cc-roadmap/assets/BACKLOG_TEMPLATE.md +8 -0
  61. package/.claude/skills/cc-roadmap/assets/ROADMAP_TEMPLATE.md +22 -0
  62. package/.claude/skills/cc-roadmap/assets/TRACKING_TEMPLATE.json +32 -1
  63. package/.claude/skills/cc-roadmap/references/roadmap-dialogue.md +14 -14
  64. package/CHANGELOG.md +28 -0
  65. package/CONTRIBUTING.md +40 -4
  66. package/CONTRIBUTING.zh-CN.md +40 -4
  67. package/README.md +57 -43
  68. package/README.zh-CN.md +57 -43
  69. package/bin/cc-devflow-cli.js +293 -36
  70. package/docs/examples/START-HERE.md +5 -4
  71. package/docs/examples/example-bindings.json +10 -10
  72. package/docs/examples/full-design-blocked/BACKLOG.md +1 -1
  73. package/docs/examples/full-design-blocked/README.md +2 -2
  74. package/docs/examples/full-design-blocked/ROADMAP.md +1 -1
  75. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +2 -1
  76. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +29 -312
  77. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +11 -8
  78. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/review/report-card.json +4 -4
  79. package/docs/examples/full-design-blocked/roadmap.json +1 -1
  80. package/docs/examples/local-handoff/BACKLOG.md +1 -1
  81. package/docs/examples/local-handoff/README.md +2 -2
  82. package/docs/examples/local-handoff/ROADMAP.md +1 -1
  83. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +2 -1
  84. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +27 -210
  85. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +9 -6
  86. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/review/report-card.json +1 -1
  87. package/docs/examples/local-handoff/roadmap.json +1 -1
  88. package/docs/examples/pdca-loop/BACKLOG.md +1 -1
  89. package/docs/examples/pdca-loop/README.md +2 -2
  90. package/docs/examples/pdca-loop/ROADMAP.md +1 -1
  91. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/pr-brief.md +65 -1
  92. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +2 -1
  93. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +26 -228
  94. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +9 -6
  95. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/review/report-card.json +1 -1
  96. package/docs/examples/pdca-loop/roadmap.json +1 -1
  97. package/docs/examples/scripts/check-example-bindings.sh +11 -5
  98. package/docs/get-shit-done-strategy-audit.md +22 -22
  99. package/docs/guides/artifact-contract.md +44 -0
  100. package/docs/guides/getting-started.md +10 -8
  101. package/docs/guides/getting-started.zh-CN.md +10 -8
  102. package/docs/guides/minimize-artifacts.md +123 -0
  103. package/docs/guides/project-postmortem.md +78 -0
  104. package/lib/compiler/__tests__/skills-registry.test.js +2 -2
  105. package/lib/skill-runtime/CLAUDE.md +1 -1
  106. package/lib/skill-runtime/__tests__/autopilot.test.js +42 -6
  107. package/lib/skill-runtime/__tests__/benchmark-artifacts.test.js +165 -0
  108. package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +2 -2
  109. package/lib/skill-runtime/__tests__/dispatch.test.js +8 -38
  110. package/lib/skill-runtime/__tests__/intent.test.js +4 -20
  111. package/lib/skill-runtime/__tests__/lifecycle.test.js +1 -1
  112. package/lib/skill-runtime/__tests__/paths.test.js +7 -1
  113. package/lib/skill-runtime/__tests__/planner.tdd.test.js +63 -2
  114. package/lib/skill-runtime/__tests__/prepare-pr.test.js +3 -16
  115. package/lib/skill-runtime/__tests__/query.test.js +388 -7
  116. package/lib/skill-runtime/__tests__/review-check-integration.test.js +148 -0
  117. package/lib/skill-runtime/__tests__/review-records.test.js +619 -0
  118. package/lib/skill-runtime/__tests__/runtime.integration.test.js +64 -23
  119. package/lib/skill-runtime/__tests__/schemas.test.js +76 -2
  120. package/lib/skill-runtime/__tests__/task-contract-migrate.test.js +137 -0
  121. package/lib/skill-runtime/__tests__/task-contract.test.js +783 -0
  122. package/lib/skill-runtime/__tests__/verify-artifacts.test.js +203 -0
  123. package/lib/skill-runtime/__tests__/worker-run.test.js +4 -11
  124. package/lib/skill-runtime/__tests__/workflow-context-legacy-fallback.test.js +31 -0
  125. package/lib/skill-runtime/__tests__/workflow-context.test.js +98 -0
  126. package/lib/skill-runtime/artifacts.js +0 -5
  127. package/lib/skill-runtime/context-index.js +545 -0
  128. package/lib/skill-runtime/intent.js +9 -33
  129. package/lib/skill-runtime/lifecycle.js +1 -1
  130. package/lib/skill-runtime/operations/CLAUDE.md +2 -2
  131. package/lib/skill-runtime/operations/dispatch.js +4 -42
  132. package/lib/skill-runtime/operations/init.js +2 -6
  133. package/lib/skill-runtime/operations/janitor.js +2 -18
  134. package/lib/skill-runtime/operations/resume.js +21 -38
  135. package/lib/skill-runtime/operations/review-records.js +265 -0
  136. package/lib/skill-runtime/operations/snapshot.js +1 -1
  137. package/lib/skill-runtime/operations/task-contract.js +524 -0
  138. package/lib/skill-runtime/operations/worker-run.js +2 -30
  139. package/lib/skill-runtime/paths.js +4 -4
  140. package/lib/skill-runtime/planner.js +25 -13
  141. package/lib/skill-runtime/query-registry.js +2 -2
  142. package/lib/skill-runtime/query.js +16 -3
  143. package/lib/skill-runtime/review-records.js +123 -0
  144. package/lib/skill-runtime/review.js +246 -11
  145. package/lib/skill-runtime/schemas.js +179 -15
  146. package/lib/skill-runtime/store.js +0 -10
  147. package/lib/skill-runtime/task-contract.js +187 -0
  148. package/lib/skill-runtime/workflow-context.js +748 -0
  149. package/package.json +7 -4
@@ -0,0 +1,203 @@
1
+ /**
2
+ * [INPUT]: 依赖 scripts/verify-artifacts.js 导出的 runVerifyArtifacts 和临时 change fixture。
3
+ * [OUTPUT]: 验证 verify:artifacts 只实现 C1-C10,返回稳定 exit code 和 JSON 报告。
4
+ * [POS]: REQ-003-minimize-workflow-artifacts T016 的 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 { runVerifyArtifacts } = require('../../../scripts/verify-artifacts');
14
+
15
+ const REPO_ROOT = path.resolve(__dirname, '../../..');
16
+ const VERIFY_SCRIPT = path.join(REPO_ROOT, 'scripts', 'verify-artifacts.js');
17
+
18
+ function writeJson(filePath, value) {
19
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
20
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
21
+ }
22
+
23
+ function tasksMarkdown({ profile = 'standard', taskCount = 1, extraBody = '' } = {}) {
24
+ const contract = [
25
+ '# Tasks',
26
+ '',
27
+ '## Contract Summary',
28
+ '',
29
+ 'Change: REQ-900-valid-artifacts',
30
+ 'Mode: plan',
31
+ `Profile: ${profile}`,
32
+ 'Approval: approved',
33
+ '',
34
+ 'Goal:',
35
+ '- Keep artifact verification deterministic.',
36
+ '',
37
+ 'Do Not Do:',
38
+ '- Do not add checks outside C1-C10.',
39
+ '',
40
+ 'Approved Direction:',
41
+ '- Verify the minimized artifact shape.',
42
+ '',
43
+ 'Acceptance:',
44
+ '- The verifier returns stable rule ids and exit codes.',
45
+ '',
46
+ 'Verification:',
47
+ '',
48
+ '```bash',
49
+ 'npm run verify:artifacts',
50
+ '```',
51
+ '',
52
+ 'Risk / Escalate If:',
53
+ '- The rule table drifts from C1-C10.',
54
+ ''
55
+ ];
56
+ const tasks = Array.from({ length: taskCount }, (_, index) => [
57
+ `- [ ] T${String(index + 1).padStart(3, '0')} validate artifacts`,
58
+ ' Goal: Exercise one verifier rule.',
59
+ ' Files: `scripts/verify-artifacts.js`',
60
+ ' Verification: npm run verify:artifacts',
61
+ ` Vertical slice: Slice ${index + 1}`,
62
+ ''
63
+ ].join('\n'));
64
+ return [...contract, extraBody, '## Phase 1', '', ...tasks].join('\n');
65
+ }
66
+
67
+ function seedValidChange(repoRoot, options = {}) {
68
+ const changeKey = options.changeKey || 'REQ-900-valid-artifacts';
69
+ const changeDir = path.join(repoRoot, 'devflow', 'changes', changeKey);
70
+ const planningDir = path.join(changeDir, 'planning');
71
+ fs.mkdirSync(planningDir, { recursive: true });
72
+ fs.writeFileSync(path.join(planningDir, 'tasks.md'), tasksMarkdown(options));
73
+ writeJson(path.join(planningDir, 'task-manifest.json'), {
74
+ changeId: changeKey,
75
+ createdAt: '2026-05-12T00:00:00.000Z',
76
+ updatedAt: '2026-05-12T00:00:00.000Z',
77
+ currentTaskId: null,
78
+ tasks: [],
79
+ metadata: {
80
+ source: 'tasks.md',
81
+ generatedBy: 'cc-devflow task-contract',
82
+ planVersion: 1
83
+ }
84
+ });
85
+ writeJson(path.join(changeDir, 'change-meta.json'), {
86
+ changeId: changeKey,
87
+ requirementId: changeKey,
88
+ goal: ['Verify artifacts'],
89
+ acceptance: ['Verifier passes'],
90
+ specReference: {
91
+ source: 'planning/tasks.md#contract-summary',
92
+ change: changeKey,
93
+ mode: 'plan',
94
+ profile: options.profile || 'standard',
95
+ approval: 'approved'
96
+ },
97
+ _meta: {
98
+ generatedBy: 'cc-devflow task-contract',
99
+ generatedAt: '2026-05-12T00:00:00.000Z'
100
+ }
101
+ });
102
+ return { changeDir, planningDir, changeKey };
103
+ }
104
+
105
+ describe('verify:artifacts', () => {
106
+ let repoRoot;
107
+
108
+ beforeEach(() => {
109
+ repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-verify-artifacts-'));
110
+ writeJson(path.join(repoRoot, 'package.json'), {
111
+ name: 'verify-artifacts-fixture',
112
+ version: '0.0.0',
113
+ scripts: {
114
+ 'verify:artifacts': 'node scripts/verify-artifacts.js'
115
+ }
116
+ });
117
+ });
118
+
119
+ afterEach(() => {
120
+ fs.rmSync(repoRoot, { recursive: true, force: true });
121
+ });
122
+
123
+ const ruleCases = [
124
+ ['C1', 2, (ctx) => fs.writeFileSync(path.join(ctx.planningDir, 'design.md'), '# legacy design\n')],
125
+ ['C2', 2, (ctx) => fs.writeFileSync(path.join(ctx.planningDir, 'analysis.md'), '# legacy analysis\n')],
126
+ ['C3', 2, (ctx) => {
127
+ const reviewDir = path.join(ctx.changeDir, 'review');
128
+ fs.mkdirSync(reviewDir, { recursive: true });
129
+ fs.writeFileSync(path.join(reviewDir, 'cc-review-report.md'), '# legacy review\n');
130
+ }],
131
+ ['C4', 3, (ctx) => fs.writeFileSync(path.join(ctx.planningDir, 'tasks.md'), '# Tasks\n\n- [ ] T001 no contract\n')],
132
+ ['C5', 3, (ctx) => writeJson(path.join(ctx.planningDir, 'task-manifest.json'), {
133
+ changeId: ctx.changeKey,
134
+ createdAt: '2026-05-12T00:00:00.000Z',
135
+ updatedAt: '2026-05-12T00:00:00.000Z',
136
+ currentTaskId: null,
137
+ tasks: [],
138
+ metadata: { source: 'tasks.md', generatedBy: 'manual', planVersion: 1 }
139
+ })],
140
+ ['C6', 3, (ctx) => writeJson(path.join(ctx.changeDir, 'change-meta.json'), {
141
+ _meta: { generatedBy: 'manual' }
142
+ })],
143
+ ['C7', 4, (ctx) => fs.writeFileSync(path.join(ctx.planningDir, 'tasks.md'), tasksMarkdown({
144
+ profile: 'tiny',
145
+ taskCount: 2
146
+ }))],
147
+ ['C8', 5, (ctx) => {
148
+ const reviewDir = path.join(ctx.changeDir, 'review');
149
+ fs.mkdirSync(reviewDir, { recursive: true });
150
+ fs.writeFileSync(path.join(reviewDir, 'review-ledger.jsonl'), '{"event":"review-started"}\n');
151
+ }],
152
+ ['C9', 5, (ctx) => {
153
+ const reviewDir = path.join(ctx.changeDir, 'review');
154
+ fs.mkdirSync(reviewDir, { recursive: true });
155
+ fs.writeFileSync(path.join(reviewDir, 'report-card.json'), '{"overall":"pass"}\n');
156
+ }],
157
+ ['C10', 6, (ctx) => fs.writeFileSync(path.join(ctx.planningDir, 'tasks.md'), tasksMarkdown({
158
+ profile: 'standard',
159
+ extraBody: 'x'.repeat(12000)
160
+ }))]
161
+ ];
162
+
163
+ test.each(ruleCases)('%s returns exit code %i with JSON report', async (ruleId, exitCode, mutate) => {
164
+ const ctx = seedValidChange(repoRoot, { changeKey: `REQ-9${ruleId.slice(1).padStart(2, '0')}-${ruleId.toLowerCase()}` });
165
+ mutate(ctx);
166
+
167
+ const result = await runVerifyArtifacts(repoRoot);
168
+
169
+ expect(result.code).toBe(exitCode);
170
+ expect(result.violations[0]).toMatchObject({ ruleId, exitCode });
171
+ expect(result.checks).toHaveLength(10);
172
+ });
173
+
174
+ test('passes a valid generated change and skips grandfathered legacy directories', async () => {
175
+ seedValidChange(repoRoot);
176
+ const legacy = seedValidChange(repoRoot, { changeKey: 'REQ-001-legacy-fallback' });
177
+ fs.writeFileSync(path.join(legacy.planningDir, 'design.md'), '# grandfathered design\n');
178
+ const manifest = JSON.parse(fs.readFileSync(path.join(legacy.planningDir, 'task-manifest.json'), 'utf8'));
179
+ manifest.metadata.generatedBy = 'skill:cc-plan';
180
+ fs.writeFileSync(path.join(legacy.planningDir, 'task-manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`);
181
+
182
+ const result = await runVerifyArtifacts(repoRoot);
183
+
184
+ expect(result).toMatchObject({ code: 0, ok: true });
185
+ expect(result.skippedLegacy.map((item) => item.changeKey)).toContain('REQ-001-legacy-fallback');
186
+ });
187
+
188
+ test('CLI prints stdout JSON and exits with the first violation code', () => {
189
+ const ctx = seedValidChange(repoRoot);
190
+ fs.writeFileSync(path.join(ctx.planningDir, 'design.md'), '# rogue design\n');
191
+
192
+ const result = spawnSync(process.execPath, [VERIFY_SCRIPT, repoRoot], { encoding: 'utf8' });
193
+ const report = JSON.parse(result.stdout);
194
+
195
+ expect(result.status).toBe(2);
196
+ expect(report.violations[0].ruleId).toBe('C1');
197
+ });
198
+
199
+ test('package.json exposes npm run verify:artifacts', () => {
200
+ const pkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8'));
201
+ expect(pkg.scripts['verify:artifacts']).toBe('node scripts/verify-artifacts.js');
202
+ });
203
+ });
@@ -11,7 +11,6 @@ const {
11
11
  const {
12
12
  getRuntimeStatePath,
13
13
  getTaskManifestPath,
14
- getCheckpointPath,
15
14
  getEventsPath
16
15
  } = require('../store');
17
16
 
@@ -138,7 +137,7 @@ describe('runWorkerCommand', () => {
138
137
  expect(claudeCommand).toContain('--dangerously-skip-permissions');
139
138
  });
140
139
 
141
- test('runs local worker command and records only checkpoint truth by default', async () => {
140
+ test('runs local worker command and records only task status truth by default', async () => {
142
141
  const repoRoot = setupRepoRoot('cc-devflow-worker-run-pass-');
143
142
  const manifest = createManifest();
144
143
  writeManifest(repoRoot, manifest);
@@ -157,7 +156,6 @@ describe('runWorkerCommand', () => {
157
156
  const log = fs.readFileSync(result.sessionLogPath, 'utf8');
158
157
  const bus = fs.readFileSync(getMessageBusPath(repoRoot, 'REQ-123'), 'utf8');
159
158
  const assignment = fs.readFileSync(getWorkerAssignmentPath(repoRoot, 'REQ-123', workerId), 'utf8');
160
- const checkpoint = JSON.parse(fs.readFileSync(getCheckpointPath(repoRoot, 'REQ-123', 'T002'), 'utf8'));
161
159
  const nextManifest = JSON.parse(fs.readFileSync(getTaskManifestPath(repoRoot, 'REQ-123'), 'utf8'));
162
160
  const runtimeState = JSON.parse(fs.readFileSync(getRuntimeStatePath(repoRoot, 'REQ-123'), 'utf8'));
163
161
 
@@ -167,9 +165,6 @@ describe('runWorkerCommand', () => {
167
165
  expect(log).toContain('worker-ok');
168
166
  expect(bus).toContain(`${workerId} completed T002`);
169
167
  expect(assignment).toContain('`T002` status=`completed`');
170
- expect(checkpoint.status).toBe('passed');
171
- expect(checkpoint.outputExcerpt).toContain('worker-ok');
172
- expect(checkpoint.error).toBe('');
173
168
  expect(fs.existsSync(getEventsPath(repoRoot, 'REQ-123', 'T002'))).toBe(false);
174
169
  expect(fs.existsSync(path.join(repoRoot, 'devflow/changes/REQ-123-run-delegated-worker-command/execution/workers'))).toBe(false);
175
170
  expect(nextManifest.tasks[0].status).toBe('passed');
@@ -192,7 +187,7 @@ describe('runWorkerCommand', () => {
192
187
  expect(providerPrompt).toContain('Delegated task');
193
188
  });
194
189
 
195
- test('writes failure events and checkpoint error when local command exits non-zero', async () => {
190
+ test('writes failure events and manifest error when local command exits non-zero', async () => {
196
191
  const repoRoot = setupRepoRoot('cc-devflow-worker-run-fail-');
197
192
  const manifest = createManifest();
198
193
  writeManifest(repoRoot, manifest);
@@ -210,7 +205,6 @@ describe('runWorkerCommand', () => {
210
205
  const log = fs.readFileSync(result.sessionLogPath, 'utf8');
211
206
  const assignment = fs.readFileSync(getWorkerAssignmentPath(repoRoot, 'REQ-123', workerId), 'utf8');
212
207
  const failedManifest = JSON.parse(fs.readFileSync(getTaskManifestPath(repoRoot, 'REQ-123'), 'utf8'));
213
- const checkpoint = JSON.parse(fs.readFileSync(getCheckpointPath(repoRoot, 'REQ-123', 'T002'), 'utf8'));
214
208
  const events = fs.readFileSync(getEventsPath(repoRoot, 'REQ-123', 'T002'), 'utf8');
215
209
 
216
210
  expect(result.status).toBe('failed');
@@ -218,10 +212,9 @@ describe('runWorkerCommand', () => {
218
212
  expect(state).toContain('Status: `failed`');
219
213
  expect(log).toContain('boom');
220
214
  expect(assignment).toContain('`T002` status=`failed`');
221
- expect(checkpoint.status).toBe('failed');
222
- expect(checkpoint.error).toContain('boom');
223
215
  expect(events).toContain('worker_run_failed');
224
216
  expect(failedManifest.tasks[0].status).toBe('failed');
217
+ expect(failedManifest.tasks[0].lastError).toContain('boom');
225
218
  });
226
219
 
227
220
  test('updates only the selected task when a worker owns multiple assignments', async () => {
@@ -277,6 +270,6 @@ describe('runWorkerCommand', () => {
277
270
  });
278
271
 
279
272
  expect(fs.existsSync(path.join(repoRoot, 'blocked.txt'))).toBe(false);
280
- expect(fs.existsSync(getCheckpointPath(repoRoot, 'REQ-123', 'T002'))).toBe(false);
273
+ expect(fs.existsSync(getEventsPath(repoRoot, 'REQ-123', 'T002'))).toBe(false);
281
274
  });
282
275
  });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * [INPUT]: 依赖 getWorkflowContext 查询 seam、仓库内真实 legacy workflow artifacts。
3
+ * [OUTPUT]: 验证 legacy design.md fallback 在 compact context 中仍是一等合同入口。
4
+ * [POS]: REQ-003-minimize-workflow-artifacts T010 的 Red/Green 证据。
5
+ * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
+ */
7
+
8
+ const path = require('path');
9
+
10
+ const { getWorkflowContext } = require('../query');
11
+
12
+ const repoRoot = path.resolve(__dirname, '../../..');
13
+
14
+ describe('workflow-context legacy fallback refs', () => {
15
+ test.each([
16
+ ['REQ-002', 'REQ-002-unified-roadmap-truth']
17
+ ])('%s keeps design.md as the first fallback contract ref', async (changeId, changeKey) => {
18
+ const context = await getWorkflowContext(repoRoot, changeId, { changeKey });
19
+ const designRef = `devflow/changes/${changeKey}/planning/design.md#approved-direction`;
20
+
21
+ expect(context.legacyFallback).toBe(true);
22
+ expect(context.source.contract.path).toBe(`devflow/changes/${changeKey}/planning/design.md`);
23
+ expect(context.progressiveDisclosure.defaultOpen[0]).toEqual(expect.objectContaining({
24
+ ref: designRef,
25
+ reason: 'primary task contract',
26
+ exists: true
27
+ }));
28
+ expect(context.progressiveDisclosure.defaultOpen.every((entry) => entry.exists === true))
29
+ .toBe(true);
30
+ });
31
+ });
@@ -0,0 +1,98 @@
1
+ /**
2
+ * [INPUT]: 依赖 getWorkflowContext 查询 seam、真实临时 workflow artifacts。
3
+ * [OUTPUT]: 验证 workflow-context 对新 tasks.md contract refs 的默认打开顺序。
4
+ * [POS]: REQ-003-minimize-workflow-artifacts T009 的 Red/Green 证据。
5
+ * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const os = require('os');
10
+ const path = require('path');
11
+
12
+ const { getWorkflowContext } = require('../query');
13
+ const { getTaskManifestPath } = require('../store');
14
+
15
+ function writeJson(filePath, value) {
16
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
17
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
18
+ }
19
+
20
+ describe('workflow-context contract refs', () => {
21
+ test.each([
22
+ ['REQ-130', '## Contract Summary', 'contract-summary', 'PDCA'],
23
+ ['FIX-130', '## Root Cause Contract', 'root-cause-contract', 'IDCA']
24
+ ])('primary ref is tasks.md#%s for a new change', async (
25
+ changeId,
26
+ contractHeading,
27
+ fragment,
28
+ route
29
+ ) => {
30
+ const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cc-devflow-workflow-context-'));
31
+ const manifestPath = getTaskManifestPath(repoRoot, changeId);
32
+ const planningDir = path.dirname(manifestPath);
33
+ const relativeTasksPath = path.relative(repoRoot, path.join(planningDir, 'tasks.md'));
34
+
35
+ fs.mkdirSync(planningDir, { recursive: true });
36
+ fs.writeFileSync(
37
+ path.join(planningDir, 'tasks.md'),
38
+ [
39
+ '# TASKS',
40
+ '',
41
+ contractHeading,
42
+ '',
43
+ `Change: ${changeId}`,
44
+ 'Mode: plan',
45
+ 'Profile: standard',
46
+ contractHeading.includes('Root Cause') ? 'Diagnosis: Keep root-cause truth in tasks.md.' : 'Approval: approved',
47
+ '',
48
+ '## Phase 1: Execute',
49
+ '',
50
+ '- [ ] T001 Execute new contract'
51
+ ].join('\n')
52
+ );
53
+ writeJson(manifestPath, {
54
+ changeId,
55
+ goal: 'Expose new contract refs',
56
+ createdAt: '2026-05-12T01:00:00.000Z',
57
+ updatedAt: '2026-05-12T01:05:00.000Z',
58
+ currentTaskId: 'T001',
59
+ tasks: [
60
+ {
61
+ id: 'T001',
62
+ title: 'Execute new contract',
63
+ type: 'OTHER',
64
+ phase: 1,
65
+ dependsOn: [],
66
+ run: ['npm test -- lib/skill-runtime/__tests__/workflow-context.test.js'],
67
+ verification: ['npm test -- lib/skill-runtime/__tests__/workflow-context.test.js'],
68
+ context: {
69
+ readFiles: ['tasks.md'],
70
+ commands: ['npm test -- lib/skill-runtime/__tests__/workflow-context.test.js'],
71
+ notes: []
72
+ },
73
+ status: 'pending',
74
+ attempts: 0,
75
+ maxRetries: 1
76
+ }
77
+ ],
78
+ metadata: {
79
+ source: 'tasks.md',
80
+ generatedBy: 'test',
81
+ planVersion: 1
82
+ }
83
+ });
84
+
85
+ const context = await getWorkflowContext(repoRoot, changeId);
86
+
87
+ expect(context.route).toBe(route);
88
+ expect(context.legacyFallback).toBe(false);
89
+ expect(context.source.contract.path).toBe(relativeTasksPath);
90
+ expect(context.progressiveDisclosure.defaultOpen[0]).toEqual(expect.objectContaining({
91
+ ref: `${relativeTasksPath}#${fragment}`,
92
+ exists: true,
93
+ reason: 'primary task contract'
94
+ }));
95
+
96
+ fs.rmSync(repoRoot, { recursive: true, force: true });
97
+ });
98
+ });
@@ -16,10 +16,6 @@ function getIntentArtifactsDir(repoRoot, goalId, options = {}) {
16
16
  return getChangePaths(repoRoot, goalId, options).executionDir;
17
17
  }
18
18
 
19
- function getIntentCheckpointsDir(repoRoot, goalId, options = {}) {
20
- return getChangePaths(repoRoot, goalId, options).tasksDir;
21
- }
22
-
23
19
  function getIntentResumeIndexPath(repoRoot, goalId, options = {}) {
24
20
  return `${getChangePaths(repoRoot, goalId, options).handoffDir}/resume-index.md`;
25
21
  }
@@ -83,7 +79,6 @@ async function ensureIntentScaffold(repoRoot, goalId, options = {}) {
83
79
  module.exports = {
84
80
  getIntentDir,
85
81
  getIntentArtifactsDir,
86
- getIntentCheckpointsDir,
87
82
  getIntentResumeIndexPath,
88
83
  getIntentPrBriefPath,
89
84
  getIntentStatusPath,