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,531 +0,0 @@
1
- /**
2
- * [INPUT]: 依赖 delegation/store 提供的 handoff、workspace 与 shell 执行能力,接收 changeId/workerId/taskId/command/provider 以运行本地 worker。
3
- * [OUTPUT]: 对外提供 worker-run 执行结果,并写入 session.log、state、journal、message bus、目标 assignment 状态与 provider session prompt。
4
- * [POS]: skill runtime 的本地 worker 执行壳,把 Markdown handoff bundle 接到真实本地命令执行,并以最薄 provider launcher 连接 codex/claude。
5
- * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
- */
7
-
8
- const path = require('path');
9
- const {
10
- buildWorkerHandoff,
11
- appendWorkerJournal,
12
- appendMessageBus,
13
- updateWorkerState,
14
- updateAssignmentStatus,
15
- ensureWorkerWorkspace,
16
- getWorkerSessionLogPath
17
- } = require('../delegation');
18
- const {
19
- readText,
20
- readJson,
21
- writeText,
22
- nowIso,
23
- writeJson,
24
- appendJsonl,
25
- runCommand,
26
- getEventsPath,
27
- getTaskManifestPath,
28
- getRuntimeStatePath
29
- } = require('../store');
30
- const { parseManifest, parseRuntimeState } = require('../schemas');
31
- const { applyManifestExecutionState } = require('../planner');
32
- const { syncIntentMemory } = require('../intent');
33
- const { namedError } = require('../errors');
34
-
35
- function quoteShellArg(value) {
36
- return `'${String(value).replace(/'/g, `'\"'\"'`)}'`;
37
- }
38
-
39
- function summarizeOutput(result) {
40
- const combined = [result.stdout, result.stderr]
41
- .filter(Boolean)
42
- .join('\n')
43
- .replace(/\s+/g, ' ')
44
- .trim();
45
-
46
- if (!combined) {
47
- return result.code === 0 ? 'command finished without output' : 'command failed without output';
48
- }
49
-
50
- return combined.slice(0, 240);
51
- }
52
-
53
- function quoteCommandArg(value) {
54
- return `'${String(value).replace(/'/g, `'\"'\"'`)}'`;
55
- }
56
-
57
- async function appendSessionLog(logPath, lines) {
58
- const previous = await readText(logPath, '');
59
- const chunk = `${lines.join('\n')}\n`;
60
- await writeText(logPath, `${previous}${chunk}`);
61
- }
62
-
63
- async function writeWorkerEvent(repoRoot, changeId, taskId, event, debug = false) {
64
- if (!debug && !String(event.type || '').includes('failed')) {
65
- return;
66
- }
67
- await appendJsonl(getEventsPath(repoRoot, changeId, taskId), event);
68
- }
69
-
70
- async function updateAssignments(repoRoot, changeId, handoff, fields) {
71
- for (const taskId of handoff.taskIds) {
72
- await updateAssignmentStatus(repoRoot, changeId, taskId, fields(taskId));
73
- }
74
- }
75
-
76
- function pickTaskId(handoff, requestedTaskId) {
77
- if (!requestedTaskId) {
78
- return handoff.taskIds[0];
79
- }
80
-
81
- if (!handoff.taskIds.includes(requestedTaskId)) {
82
- throw new Error(`Worker ${handoff.workerId} is not assigned to task ${requestedTaskId}`);
83
- }
84
-
85
- return requestedTaskId;
86
- }
87
-
88
- function getProviderPromptPath(handoff, taskId) {
89
- return path.join(handoff.runtimeDir, `session-${taskId}.md`);
90
- }
91
-
92
- function getProviderLastMessagePath(handoff, taskId) {
93
- return path.join(handoff.runtimeDir, `session-${taskId}.last-message.md`);
94
- }
95
-
96
- function getProviderTranscriptPath(handoff, taskId, provider) {
97
- return path.join(handoff.runtimeDir, `session-${taskId}.${provider}.jsonl`);
98
- }
99
-
100
- function formatList(items, empty = '- None') {
101
- if (!items || items.length === 0) {
102
- return empty;
103
- }
104
-
105
- return items.map((item) => `- ${item}`).join('\n');
106
- }
107
-
108
- async function buildTaskBrief(repoRoot, changeId, taskId, planVersion) {
109
- const manifest = parseManifest(await readJson(getTaskManifestPath(repoRoot, changeId)));
110
- const task = manifest.tasks.find((item) => item.id === taskId);
111
-
112
- if (!task) {
113
- throw new Error(`Task ${taskId} not found in manifest`);
114
- }
115
-
116
- return [
117
- `# Task Brief: ${task.id}`,
118
- '',
119
- `- Plan Version: ${planVersion || manifest.metadata?.planVersion || 1}`,
120
- `- Type: \`${task.type}\``,
121
- `- Title: ${task.title}`,
122
- '',
123
- '## Dependencies',
124
- '',
125
- formatList(task.dependsOn.map((item) => `\`${item}\``), '- None'),
126
- '',
127
- '## Touched Files',
128
- '',
129
- formatList(task.touches.map((item) => `\`${item}\``), '- None'),
130
- '',
131
- '## Commands',
132
- '',
133
- formatList([...task.run, ...task.checks].map((item) => `\`${item}\``))
134
- ].join('\n');
135
- }
136
-
137
- async function assertWorkerPlanFresh(repoRoot, changeId, handoff) {
138
- const manifestPath = getTaskManifestPath(repoRoot, changeId);
139
- const manifest = parseManifest(await readJson(manifestPath));
140
- const currentPlanVersion = manifest.metadata?.planVersion || 1;
141
-
142
- if (currentPlanVersion === handoff.planVersion) {
143
- return;
144
- }
145
-
146
- throw namedError(
147
- 'StalePlanVersionError',
148
- `Worker ${handoff.workerId} was assigned to planVersion ${handoff.planVersion}, but current planVersion is ${currentPlanVersion}`,
149
- {
150
- artifactRefs: [
151
- `devflow/changes/<change>/planning/task-manifest.json`,
152
- handoff.assignmentPath
153
- ],
154
- rescueAction: 'rerun delegation sync for current planVersion before worker-run',
155
- details: {
156
- workerId: handoff.workerId,
157
- assignedPlanVersion: handoff.planVersion,
158
- currentPlanVersion,
159
- manifestPath
160
- }
161
- }
162
- );
163
- }
164
-
165
- async function buildProviderPrompt(repoRootOrHandoff, handoffOrTaskId, maybeTaskId) {
166
- const repoRoot = typeof repoRootOrHandoff === 'string' ? repoRootOrHandoff : process.cwd();
167
- const handoff = typeof repoRootOrHandoff === 'string' ? handoffOrTaskId : repoRootOrHandoff;
168
- const taskId = typeof repoRootOrHandoff === 'string' ? maybeTaskId : handoffOrTaskId;
169
- const [assignment, taskBrief] = await Promise.all([
170
- readText(handoff.assignmentPath, ''),
171
- buildTaskBrief(repoRoot, handoff.changeId, taskId, handoff.planVersion)
172
- ]);
173
-
174
- return [
175
- `# Worker Session`,
176
- '',
177
- `- Change: \`${handoff.changeId}\``,
178
- `- Worker: \`${handoff.workerId}\``,
179
- `- Role: \`${handoff.role}\``,
180
- `- Task: \`${taskId}\``,
181
- `- Plan Version: ${handoff.planVersion}`,
182
- '',
183
- '## Operating Rules',
184
- '',
185
- '- 先阅读下面的 assignment 和 task brief,再执行当前任务。',
186
- '- 仅处理当前 task,不要擅自结算同 worker 的其他任务。',
187
- '- 所有关键结论先落到仓库工件,再结束会话。',
188
- '- 如果发现 plan_version 漂移,停止并返回阻塞说明。',
189
- '',
190
- '## Worker Assignment',
191
- '',
192
- assignment.trim(),
193
- '',
194
- '## Selected Task Brief',
195
- '',
196
- taskBrief.trim(),
197
- ''
198
- ].join('\n');
199
- }
200
-
201
- function buildProviderCommand({
202
- provider,
203
- providerPromptPath,
204
- providerLastMessagePath,
205
- providerTranscriptPath,
206
- workspace,
207
- providerArgs
208
- }) {
209
- const extraArgs = providerArgs ? ` ${providerArgs.trim()}` : '';
210
- const stdinPromptArg = provider === 'codex' ? ' -' : '';
211
-
212
- if (provider === 'codex') {
213
- return `cat ${quoteCommandArg(providerPromptPath)} | codex exec --json --dangerously-bypass-approvals-and-sandbox -C ${quoteCommandArg(workspace)} -o ${quoteCommandArg(providerLastMessagePath)}${stdinPromptArg}${extraArgs} | tee ${quoteCommandArg(providerTranscriptPath)}`;
214
- }
215
-
216
- if (provider === 'claude') {
217
- return `cat ${quoteCommandArg(providerPromptPath)} | claude -p --dangerously-skip-permissions --add-dir ${quoteCommandArg(workspace)}${extraArgs}`;
218
- }
219
-
220
- throw new Error(`Unsupported provider: ${provider}`);
221
- }
222
-
223
- function parseCodexTranscript(stdout = '') {
224
- const lines = stdout
225
- .split('\n')
226
- .map((line) => line.trim())
227
- .filter(Boolean);
228
-
229
- const summary = {
230
- threadId: null,
231
- agentMessages: [],
232
- commandExecutions: [],
233
- fileChanges: [],
234
- toolCalls: [],
235
- errors: []
236
- };
237
-
238
- for (const line of lines) {
239
- let event;
240
- try {
241
- event = JSON.parse(line);
242
- } catch {
243
- continue;
244
- }
245
-
246
- if (event.type === 'thread.started' && event.thread_id) {
247
- summary.threadId = event.thread_id;
248
- continue;
249
- }
250
-
251
- if (event.type !== 'item.completed' || !event.item) {
252
- continue;
253
- }
254
-
255
- if (event.item.type === 'agent_message' && event.item.text) {
256
- summary.agentMessages.push(event.item.text);
257
- continue;
258
- }
259
-
260
- if (event.item.type === 'command_execution') {
261
- summary.commandExecutions.push({
262
- command: event.item.command,
263
- status: event.item.status,
264
- exitCode: event.item.exit_code
265
- });
266
- continue;
267
- }
268
-
269
- if (event.item.type === 'file_change') {
270
- summary.fileChanges.push(...(event.item.changes || []).map((change) => `${change.kind}:${change.path}`));
271
- continue;
272
- }
273
-
274
- if (event.item.type === 'mcp_tool_call') {
275
- summary.toolCalls.push(`${event.item.server}:${event.item.tool}:${event.item.status}`);
276
- continue;
277
- }
278
-
279
- if (event.item.type === 'error' && event.item.message) {
280
- summary.errors.push(event.item.message);
281
- }
282
- }
283
-
284
- return summary;
285
- }
286
-
287
- async function updateManifestTaskState(repoRoot, changeId, taskId, fields) {
288
- const manifestPath = getTaskManifestPath(repoRoot, changeId);
289
- const manifest = parseManifest(await readJson(manifestPath));
290
- const task = manifest.tasks.find((item) => item.id === taskId);
291
-
292
- if (!task) {
293
- throw new Error(`Task ${taskId} not found in manifest`);
294
- }
295
-
296
- if (fields.status) {
297
- task.status = fields.status;
298
- }
299
- if (Number.isInteger(fields.attempts)) {
300
- task.attempts = fields.attempts;
301
- }
302
- if (Object.prototype.hasOwnProperty.call(fields, 'lastError')) {
303
- task.lastError = fields.lastError || undefined;
304
- }
305
-
306
- applyManifestExecutionState(manifest, nowIso());
307
- await writeJson(manifestPath, manifest);
308
- return manifest;
309
- }
310
-
311
- async function markRuntimeInProgress(repoRoot, changeId) {
312
- const statePath = getRuntimeStatePath(repoRoot, changeId);
313
- const state = await readJson(statePath, null);
314
- if (!state) {
315
- return;
316
- }
317
-
318
- const parsed = parseRuntimeState(state);
319
- if (parsed.status === 'planned' || parsed.status === 'initialized') {
320
- parsed.status = 'in_progress';
321
- }
322
- parsed.updatedAt = nowIso();
323
- await writeJson(statePath, parsed);
324
- }
325
-
326
- async function runWorkerCommand({
327
- repoRoot,
328
- changeId,
329
- workerId,
330
- taskId,
331
- command,
332
- provider,
333
- providerArgs,
334
- debug = false,
335
- timeoutMs = 15 * 60 * 1000
336
- }) {
337
- if (!command && !provider) {
338
- throw new Error('Missing execution mode: provide --command "<local agent command>" or --provider <codex|claude>');
339
- }
340
-
341
- if (command && provider) {
342
- throw new Error('Use either --command or --provider, not both');
343
- }
344
-
345
- const handoff = await buildWorkerHandoff(repoRoot, changeId, workerId);
346
- await assertWorkerPlanFresh(repoRoot, changeId, handoff);
347
- const primaryTaskId = pickTaskId(handoff, taskId);
348
- const assignment = {
349
- workerId,
350
- role: handoff.role
351
- };
352
- const workspace = await ensureWorkerWorkspace(repoRoot, changeId, assignment);
353
- const sessionId = `${workerId}-${Date.now()}`;
354
- const startedAt = nowIso();
355
- const sessionLogPath = handoff.sessionLogPath || getWorkerSessionLogPath(repoRoot, changeId, workerId);
356
- const providerPromptPath = getProviderPromptPath(handoff, primaryTaskId);
357
- const providerLastMessagePath = getProviderLastMessagePath(handoff, primaryTaskId);
358
- const providerTranscriptPath = provider ? getProviderTranscriptPath(handoff, primaryTaskId, provider) : null;
359
- await markRuntimeInProgress(repoRoot, changeId);
360
- const providerPrompt = provider ? await buildProviderPrompt(repoRoot, handoff, primaryTaskId) : null;
361
- if (providerPrompt) {
362
- await writeText(providerPromptPath, `${providerPrompt}\n`);
363
- }
364
- const resolvedCommand = command || buildProviderCommand({
365
- provider,
366
- providerPromptPath,
367
- providerLastMessagePath,
368
- providerTranscriptPath,
369
- workspace: workspace.workspacePath,
370
- providerArgs
371
- });
372
- const wrappedCommand = [
373
- `export CC_DEVFLOW_CHANGE_ID=${quoteShellArg(changeId)}`,
374
- `export CC_DEVFLOW_WORKER_ID=${quoteShellArg(workerId)}`,
375
- `export CC_DEVFLOW_WORKER_ROLE=${quoteShellArg(handoff.role)}`,
376
- `export CC_DEVFLOW_TASK_ID=${quoteShellArg(primaryTaskId)}`,
377
- `export CC_DEVFLOW_WORKER_STATE=${quoteShellArg(handoff.statePath)}`,
378
- `export CC_DEVFLOW_WORKER_JOURNAL=${quoteShellArg(handoff.journalPath)}`,
379
- `export CC_DEVFLOW_WORKER_SESSION_LOG=${quoteShellArg(sessionLogPath)}`,
380
- providerPrompt ? `export CC_DEVFLOW_PROVIDER_PROMPT=${quoteShellArg(providerPromptPath)}` : '',
381
- providerPrompt ? `export CC_DEVFLOW_PROVIDER_LAST_MESSAGE=${quoteShellArg(providerLastMessagePath)}` : '',
382
- providerTranscriptPath ? `export CC_DEVFLOW_PROVIDER_TRANSCRIPT=${quoteShellArg(providerTranscriptPath)}` : '',
383
- provider ? `export CC_DEVFLOW_PROVIDER=${quoteShellArg(provider)}` : '',
384
- resolvedCommand
385
- ].join('\n');
386
-
387
- await updateWorkerState(repoRoot, changeId, workerId, {
388
- role: handoff.role,
389
- planVersion: handoff.planVersion,
390
- status: 'running',
391
- currentTask: primaryTaskId,
392
- branch: workspace.mode === 'worktree' ? 'detached-worktree' : 'controller',
393
- workspace: workspace.workspacePath
394
- });
395
- await updateManifestTaskState(repoRoot, changeId, primaryTaskId, {
396
- status: 'running',
397
- attempts: 1,
398
- lastError: undefined
399
- });
400
- await updateAssignments(repoRoot, changeId, handoff, (taskId) => ({
401
- status: taskId === primaryTaskId ? 'running' : undefined,
402
- workspace: taskId === primaryTaskId ? workspace.workspacePath : undefined,
403
- sessionId: taskId === primaryTaskId ? sessionId : undefined,
404
- summary: taskId === primaryTaskId
405
- ? `worker ${workerId} started ${provider || 'custom'} execution`
406
- : undefined
407
- }));
408
- await appendWorkerJournal(
409
- repoRoot,
410
- changeId,
411
- workerId,
412
- `${startedAt} started ${sessionId} in ${workspace.mode} workspace for ${primaryTaskId} via ${provider || 'custom-command'}`
413
- );
414
- await appendMessageBus(
415
- repoRoot,
416
- changeId,
417
- `${workerId} started ${primaryTaskId} via ${provider || 'custom-command'} in ${workspace.mode} workspace`
418
- );
419
- await writeWorkerEvent(repoRoot, changeId, primaryTaskId, {
420
- type: 'worker_run_started',
421
- changeId,
422
- taskId: primaryTaskId,
423
- sessionId,
424
- provider: provider || 'custom',
425
- workerId,
426
- timestamp: startedAt
427
- }, debug);
428
- await appendSessionLog(sessionLogPath, [
429
- `# Session ${sessionId}`,
430
- `started_at: ${startedAt}`,
431
- `worker: ${workerId}`,
432
- `role: ${handoff.role}`,
433
- `workspace: ${workspace.workspacePath}`,
434
- `workspace_mode: ${workspace.mode}`,
435
- `workspace_reason: ${workspace.reason}`,
436
- `provider: ${provider || 'custom'}`,
437
- providerPrompt ? `provider_prompt: ${providerPromptPath}` : '',
438
- `command: ${resolvedCommand}`,
439
- '',
440
- '## output'
441
- ].filter(Boolean));
442
-
443
- const result = await runCommand(wrappedCommand, {
444
- cwd: workspace.cwd,
445
- timeoutMs
446
- });
447
- const finishedAt = nowIso();
448
- const finalStatus = result.code === 0 ? 'completed' : 'failed';
449
- const summary = summarizeOutput(result);
450
- const codexTranscript = provider === 'codex' ? parseCodexTranscript(result.stdout) : null;
451
-
452
- await appendSessionLog(sessionLogPath, [
453
- result.stdout ? result.stdout.trimEnd() : '',
454
- result.stderr ? `\n## stderr\n${result.stderr.trimEnd()}` : '',
455
- '',
456
- `exit_code: ${result.code}`,
457
- `finished_at: ${finishedAt}`,
458
- `duration_ms: ${result.durationMs}`,
459
- `timed_out: ${result.killedByTimeout ? 'true' : 'false'}`,
460
- ''
461
- ].filter(Boolean));
462
-
463
- await updateManifestTaskState(repoRoot, changeId, primaryTaskId, {
464
- status: result.code === 0 ? 'passed' : 'failed',
465
- attempts: 1,
466
- lastError: result.code === 0 ? undefined : (result.stderr || result.stdout || '').trim()
467
- });
468
- await writeWorkerEvent(repoRoot, changeId, primaryTaskId, {
469
- type: result.code === 0 ? 'worker_run_passed' : 'worker_run_failed',
470
- changeId,
471
- taskId: primaryTaskId,
472
- sessionId,
473
- provider: provider || 'custom',
474
- workerId,
475
- timestamp: finishedAt,
476
- error: result.code === 0 ? undefined : (result.stderr || result.stdout || '').trim()
477
- }, debug);
478
- await syncIntentMemory(repoRoot, changeId, {
479
- event: result.code === 0 ? 'worker_run_completed' : 'worker_run_failed',
480
- reason: `${workerId} ${result.code === 0 ? 'completed' : 'failed'} ${primaryTaskId} via ${provider || 'custom-command'}`
481
- });
482
-
483
- await updateWorkerState(repoRoot, changeId, workerId, {
484
- role: handoff.role,
485
- planVersion: handoff.planVersion,
486
- status: finalStatus,
487
- currentTask: result.code === 0 ? 'none' : primaryTaskId,
488
- branch: workspace.mode === 'worktree' ? 'detached-worktree' : 'controller',
489
- workspace: workspace.workspacePath
490
- });
491
- await updateAssignments(repoRoot, changeId, handoff, (taskId) => ({
492
- status: taskId === primaryTaskId ? finalStatus : undefined,
493
- workspace: taskId === primaryTaskId ? workspace.workspacePath : undefined,
494
- sessionId: taskId === primaryTaskId ? sessionId : undefined,
495
- summary: taskId === primaryTaskId ? `${workerId} ${finalStatus}: ${summary}` : undefined
496
- }));
497
- await appendWorkerJournal(
498
- repoRoot,
499
- changeId,
500
- workerId,
501
- `${finishedAt} ${sessionId} ${finalStatus} (exit ${result.code})`
502
- );
503
- await appendMessageBus(
504
- repoRoot,
505
- changeId,
506
- `${workerId} ${finalStatus} ${primaryTaskId}: ${summary}`
507
- );
508
-
509
- return {
510
- changeId,
511
- workerId,
512
- role: handoff.role,
513
- sessionId,
514
- status: finalStatus,
515
- taskId: primaryTaskId,
516
- workspace,
517
- provider: provider || null,
518
- providerPromptPath: providerPrompt ? providerPromptPath : null,
519
- providerLastMessagePath: providerPrompt ? providerLastMessagePath : null,
520
- providerTranscriptPath,
521
- command: resolvedCommand,
522
- sessionLogPath,
523
- result
524
- };
525
- }
526
-
527
- module.exports = {
528
- buildProviderCommand,
529
- buildProviderPrompt,
530
- runWorkerCommand
531
- };
@@ -1,33 +0,0 @@
1
- /**
2
- * [INPUT]: 依赖 delegation 层提供 worker handoff 与 journal/state 工件,接收 changeId/workerId 以准备本地 worker 会话。
3
- * [OUTPUT]: 返回 worker launch/prompt/state/assignment 路径,并写入 handoff 准备日志。
4
- * [POS]: skill runtime 的 worker 会话入口,为未来本地 subagent/worker shell 对接提供稳定接口。
5
- * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
- */
7
-
8
- const {
9
- buildWorkerHandoff,
10
- appendWorkerJournal,
11
- appendMessageBus,
12
- updateWorkerState
13
- } = require('../delegation');
14
-
15
- async function runWorkerSession({ repoRoot, changeId, workerId }) {
16
- const handoff = await buildWorkerHandoff(repoRoot, changeId, workerId);
17
-
18
- await updateWorkerState(repoRoot, changeId, workerId, {
19
- role: handoff.role,
20
- planVersion: handoff.planVersion,
21
- status: 'handoff_ready',
22
- currentTask: handoff.currentTask || 'assigned',
23
- workspace: 'pending'
24
- });
25
- await appendWorkerJournal(repoRoot, changeId, workerId, 'handoff prepared for local worker session');
26
- await appendMessageBus(repoRoot, changeId, `${workerId} handoff prepared`);
27
-
28
- return handoff;
29
- }
30
-
31
- module.exports = {
32
- runWorkerSession
33
- };