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,746 +0,0 @@
1
- /**
2
- * [INPUT]: 依赖 zod 进行运行时 schema 校验,依赖调用方提供 manifest/report/runtime 原始对象。
3
- * [OUTPUT]: 对外提供 Manifest/Task/ReportCard/Runtime approval schema 与 parse 校验函数。
4
- * [POS]: skill runtime 的类型边界层,被 planner/dispatcher/verifier/release 复用。
5
- * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
- */
7
-
8
- const { z } = require('zod');
9
- const { isTaskCompletedStatus } = require('./lifecycle');
10
- const { CHANGE_ID_PATTERN } = require('./paths');
11
-
12
- const TASK_ID_PATTERN = /^[A-Z][A-Z0-9_-]{1,31}$/;
13
-
14
- const ChangeIdSchema = z.string().regex(CHANGE_ID_PATTERN, 'Invalid changeId format');
15
-
16
- const TaskStatusSchema = z.enum(['pending', 'running', 'passed', 'failed', 'skipped']);
17
- const ReviewDecisionStatusSchema = z.enum(['pending', 'pass', 'fail', 'blocked', 'skipped']);
18
-
19
- function normalizeTouch(value) {
20
- return String(value)
21
- .replace(/\\/g, '/')
22
- .replace(/\/+/g, '/')
23
- .replace(/^\.\//, '')
24
- .replace(/\/$/, '');
25
- }
26
-
27
- function overlappingTouch(left, right) {
28
- if (left === right) return left;
29
- if (left && right.startsWith(`${left}/`)) return left;
30
- if (right && left.startsWith(`${right}/`)) return right;
31
- return '';
32
- }
33
-
34
- function taskTouches(task) {
35
- return [...new Set([...(task.touches || []), ...(task.files || [])].map(normalizeTouch).filter(Boolean))];
36
- }
37
-
38
- const RuntimeStatusSchema = z.enum(['initialized', 'planned', 'in_progress', 'verified', 'released']);
39
- const ApprovalStatusSchema = z.enum(['pending', 'approved']);
40
- const ExecutionModeSchema = z.enum(['direct', 'delegate', 'team']);
41
-
42
- const RuntimeApprovalSchema = z.object({
43
- status: ApprovalStatusSchema.default('pending'),
44
- executionMode: ExecutionModeSchema.default('delegate'),
45
- planVersion: z.number().int().min(1).optional(),
46
- approvedAt: z.string().datetime().optional()
47
- });
48
-
49
- const RuntimeStateSchema = z.object({
50
- changeId: ChangeIdSchema,
51
- changeKey: z.string().min(1).optional(),
52
- slug: z.string().min(1).optional(),
53
- createdAt: z.string().datetime().optional(),
54
- goal: z.string().min(1),
55
- status: RuntimeStatusSchema,
56
- initializedAt: z.string().datetime(),
57
- plannedAt: z.string().datetime().optional(),
58
- verifiedAt: z.string().datetime().optional(),
59
- releasedAt: z.string().datetime().optional(),
60
- approval: RuntimeApprovalSchema.optional(),
61
- updatedAt: z.string().datetime()
62
- });
63
-
64
- const TaskContextSchema = z.object({
65
- readFiles: z.array(z.string().min(1)).default([]),
66
- commands: z.array(z.string().min(1)).default([]),
67
- notes: z.array(z.string().min(1)).default([])
68
- }).default({
69
- readFiles: [],
70
- commands: [],
71
- notes: []
72
- });
73
-
74
- const TaskReviewStateSchema = z.object({
75
- spec: ReviewDecisionStatusSchema.default('pending'),
76
- code: ReviewDecisionStatusSchema.default('pending')
77
- }).default({
78
- spec: 'pending',
79
- code: 'pending'
80
- });
81
-
82
- const TaskSchema = z.object({
83
- id: z.string().regex(TASK_ID_PATTERN, 'Invalid task id'),
84
- title: z.string().min(1, 'Task title is required'),
85
- type: z.enum(['TEST', 'IMPL', 'OTHER', 'REFACTOR', 'VERIFY']).default('OTHER'),
86
- phase: z.number().int().min(1).default(1),
87
- parallel: z.boolean().default(false),
88
- dependsOn: z.array(z.string().regex(TASK_ID_PATTERN)).default([]),
89
- touches: z.array(z.string().min(1)).default([]),
90
- files: z.array(z.string().min(1)).default([]),
91
- run: z.array(z.string().min(1)).min(1, 'At least one run command is required'),
92
- checks: z.array(z.string().min(1)).default([]),
93
- acceptance: z.array(z.string().min(1)).default([]),
94
- verification: z.array(z.string().min(1)).default([]),
95
- evidence: z.array(z.string().min(1)).default([]),
96
- context: TaskContextSchema,
97
- reviews: TaskReviewStateSchema,
98
- status: TaskStatusSchema.default('pending'),
99
- attempts: z.number().int().min(0).default(0),
100
- maxRetries: z.number().int().min(0).default(1),
101
- lastError: z.string().optional()
102
- });
103
-
104
- const ManifestSchema = z.object({
105
- changeId: ChangeIdSchema,
106
- goal: z.string().min(1).default('Deliver planned requirement changes safely.'),
107
- createdAt: z.string().datetime(),
108
- updatedAt: z.string().datetime(),
109
- currentTaskId: z.string().regex(TASK_ID_PATTERN).nullable().default(null),
110
- activePhase: z.number().int().min(1).nullable().optional(),
111
- tasks: z.array(TaskSchema),
112
- metadata: z.object({
113
- source: z.enum(['tasks.md', 'planning/tasks.md', 'default']).default('default'),
114
- generatedBy: z.string().min(1).default('skill:cc-plan'),
115
- planVersion: z.number().int().min(1).default(1)
116
- }).default({ source: 'default', generatedBy: 'skill:cc-plan', planVersion: 1 })
117
- }).superRefine((manifest, ctx) => {
118
- const taskIds = new Set();
119
- const taskMap = new Map();
120
-
121
- for (let index = 0; index < manifest.tasks.length; index += 1) {
122
- const task = manifest.tasks[index];
123
-
124
- if (taskIds.has(task.id)) {
125
- ctx.addIssue({
126
- code: z.ZodIssueCode.custom,
127
- path: ['tasks', index, 'id'],
128
- message: `Duplicate task id: ${task.id}`
129
- });
130
- continue;
131
- }
132
-
133
- taskIds.add(task.id);
134
- taskMap.set(task.id, task);
135
- }
136
-
137
- for (let index = 0; index < manifest.tasks.length; index += 1) {
138
- const task = manifest.tasks[index];
139
-
140
- for (const depId of task.dependsOn) {
141
- if (!taskMap.has(depId)) {
142
- ctx.addIssue({
143
- code: z.ZodIssueCode.custom,
144
- path: ['tasks', index, 'dependsOn'],
145
- message: `Task ${task.id} depends on missing task ${depId}`
146
- });
147
- }
148
-
149
- if (depId === task.id) {
150
- ctx.addIssue({
151
- code: z.ZodIssueCode.custom,
152
- path: ['tasks', index, 'dependsOn'],
153
- message: `Task ${task.id} cannot depend on itself`
154
- });
155
- }
156
- }
157
- }
158
-
159
- const unfinished = manifest.tasks.filter((task) => !isTaskCompletedStatus(task.status));
160
- const derivedActivePhase = unfinished.length > 0
161
- ? Math.min(...unfinished.map((task) => task.phase || 1))
162
- : null;
163
-
164
- if (manifest.activePhase !== undefined && manifest.activePhase !== null && manifest.activePhase !== derivedActivePhase) {
165
- ctx.addIssue({
166
- code: z.ZodIssueCode.custom,
167
- path: ['activePhase'],
168
- message: `activePhase ${manifest.activePhase} does not match derived active phase ${derivedActivePhase}`
169
- });
170
- }
171
-
172
- if (manifest.currentTaskId !== null) {
173
- const currentTask = taskMap.get(manifest.currentTaskId);
174
- if (!currentTask) {
175
- ctx.addIssue({
176
- code: z.ZodIssueCode.custom,
177
- path: ['currentTaskId'],
178
- message: `currentTaskId ${manifest.currentTaskId} is not present in tasks`
179
- });
180
- } else if (derivedActivePhase !== null && currentTask.phase !== derivedActivePhase) {
181
- ctx.addIssue({
182
- code: z.ZodIssueCode.custom,
183
- path: ['currentTaskId'],
184
- message: `currentTaskId ${manifest.currentTaskId} is not in active phase ${derivedActivePhase}`
185
- });
186
- }
187
- }
188
-
189
- const taskSourceIsTasksMarkdown = manifest.metadata?.source === 'tasks.md';
190
-
191
- for (let index = 0; index < manifest.tasks.length; index += 1) {
192
- const task = manifest.tasks[index];
193
-
194
- if (taskSourceIsTasksMarkdown && task.type !== 'OTHER') {
195
- if (task.acceptance.length === 0) {
196
- ctx.addIssue({
197
- code: z.ZodIssueCode.custom,
198
- path: ['tasks', index, 'acceptance'],
199
- message: `${task.id} must include acceptance criteria`
200
- });
201
- }
202
-
203
- if (task.verification.length === 0) {
204
- ctx.addIssue({
205
- code: z.ZodIssueCode.custom,
206
- path: ['tasks', index, 'verification'],
207
- message: `${task.id} must include verification commands`
208
- });
209
- }
210
-
211
- if (task.evidence.length === 0) {
212
- ctx.addIssue({
213
- code: z.ZodIssueCode.custom,
214
- path: ['tasks', index, 'evidence'],
215
- message: `${task.id} must include evidence expectations`
216
- });
217
- }
218
-
219
- if (task.context.readFiles.length === 0) {
220
- ctx.addIssue({
221
- code: z.ZodIssueCode.custom,
222
- path: ['tasks', index, 'context', 'readFiles'],
223
- message: `${task.id} must include readFiles for context injection`
224
- });
225
- }
226
- }
227
- }
228
-
229
- for (let leftIndex = 0; leftIndex < manifest.tasks.length; leftIndex += 1) {
230
- const left = manifest.tasks[leftIndex];
231
- if (!left.parallel) {
232
- continue;
233
- }
234
-
235
- const leftTouches = taskTouches(left);
236
-
237
- for (let rightIndex = leftIndex + 1; rightIndex < manifest.tasks.length; rightIndex += 1) {
238
- const right = manifest.tasks[rightIndex];
239
-
240
- if (!right.parallel || left.phase !== right.phase) {
241
- continue;
242
- }
243
-
244
- const dependsOnEachOther =
245
- left.dependsOn.includes(right.id) || right.dependsOn.includes(left.id);
246
-
247
- if (dependsOnEachOther) {
248
- ctx.addIssue({
249
- code: z.ZodIssueCode.custom,
250
- path: ['tasks', rightIndex, 'parallel'],
251
- message: `Tasks ${left.id} and ${right.id} cannot both be parallel when one depends on the other`
252
- });
253
- }
254
-
255
- const rightTouches = taskTouches(right);
256
- const sharedTouches = [
257
- ...new Set(
258
- leftTouches.flatMap((leftTouch) =>
259
- rightTouches.map((rightTouch) => overlappingTouch(leftTouch, rightTouch)).filter(Boolean)
260
- )
261
- )
262
- ];
263
-
264
- if (sharedTouches.length > 0) {
265
- ctx.addIssue({
266
- code: z.ZodIssueCode.custom,
267
- path: ['tasks', rightIndex, 'touches'],
268
- message: `Parallel tasks ${left.id} and ${right.id} share touches: ${sharedTouches.join(', ')}`
269
- });
270
- }
271
- }
272
- }
273
- });
274
-
275
- const TddCheckpointEvidenceSchema = z.object({
276
- red: z.record(z.any()).optional(),
277
- green: z.record(z.any()).optional(),
278
- refactor: z.record(z.any()).optional(),
279
- feedbackLoop: z.record(z.any()).optional(),
280
- testQuality: z.record(z.any()).optional()
281
- }).passthrough();
282
-
283
- const CheckpointSchema = z.object({
284
- changeId: ChangeIdSchema,
285
- taskId: z.string().regex(TASK_ID_PATTERN),
286
- sessionId: z.string().min(1),
287
- planVersion: z.number().int().min(1).default(1),
288
- status: TaskStatusSchema,
289
- summary: z.string().min(1),
290
- error: z.string().default(''),
291
- outputExcerpt: z.string().default(''),
292
- timestamp: z.string().datetime(),
293
- attempt: z.number().int().min(0).default(0),
294
- tdd: TddCheckpointEvidenceSchema.optional(),
295
- tddException: z.record(z.any()).optional()
296
- });
297
-
298
- const GateResultSchema = z.object({
299
- name: z.string().min(1),
300
- status: z.enum(['pass', 'fail', 'skipped']),
301
- command: z.string().min(1),
302
- durationMs: z.number().int().min(0),
303
- details: z.string().default('')
304
- });
305
-
306
- const ReviewSeveritySchema = z.enum(['critical', 'important', 'minor', 'info']);
307
- const ReviewActionSchema = z.enum([
308
- 'fix_now',
309
- 'follow_up',
310
- 'cc-investigate',
311
- 'reroute-cc-do',
312
- 'reroute-cc-plan',
313
- 'reroute-cc-investigate',
314
- 'document-follow-up',
315
- 'none'
316
- ]);
317
- const ReviewFindingStatusSchema = z.enum([
318
- 'open',
319
- 'resolved',
320
- 'accepted',
321
- 'informational',
322
- 'accepted-fixed',
323
- 'rejected-with-evidence',
324
- 'deferred-minor',
325
- 'clarification-needed'
326
- ]);
327
-
328
- const ReviewEvidenceSchema = z.object({
329
- kind: z.enum(['command', 'file', 'note']),
330
- label: z.string().min(1),
331
- ref: z.string().default(''),
332
- observation: z.string().default('')
333
- });
334
-
335
- const ReviewFindingSchema = z.object({
336
- id: z.string().min(1),
337
- source: z.string().min(1),
338
- scope: z.enum(['task', 'requirement']),
339
- category: z.string().min(1),
340
- severity: ReviewSeveritySchema,
341
- summary: z.string().min(1),
342
- details: z.string().default(''),
343
- file: z.string().optional(),
344
- line: z.number().int().min(1).optional(),
345
- action: ReviewActionSchema.default('none'),
346
- status: ReviewFindingStatusSchema.default('open'),
347
- fingerprint: z.string().optional(),
348
- confidence: z.enum(['high', 'medium', 'low']).optional(),
349
- confidenceScore: z.number().min(1).max(10).optional(),
350
- displayTier: z.enum(['blocking', 'warning', 'info', 'suppressed']).optional(),
351
- suppressionReason: z.string().nullable().optional()
352
- });
353
-
354
- const ReviewerResultSchema = z.object({
355
- key: z.string().min(1),
356
- scope: z.enum(['task', 'requirement']),
357
- mode: z.enum(['spec', 'code', 'coverage', 'structured', 'adversarial']),
358
- source: z.enum(['manifest', 'runtime', 'codex', 'shell']),
359
- status: ReviewDecisionStatusSchema,
360
- summary: z.string().default(''),
361
- evidence: z.array(ReviewEvidenceSchema).default([]),
362
- findings: z.array(ReviewFindingSchema).default([])
363
- });
364
-
365
- const ReviewSectionSchema = z.object({
366
- status: ReviewDecisionStatusSchema.default('skipped'),
367
- required: z.boolean().default(false),
368
- summary: z.string().default(''),
369
- reviewers: z.array(ReviewerResultSchema).default([]),
370
- findings: z.array(ReviewFindingSchema).default([])
371
- });
372
-
373
- const ReviewFreshnessSchema = z.object({
374
- status: z.enum(['fresh', 'stale', 'unknown', 'not-applicable']).default('unknown'),
375
- reviewedCommit: z.string().default(''),
376
- currentCommit: z.string().default(''),
377
- commitsSinceReview: z.number().int().min(0).nullable().default(null),
378
- staleReason: z.string().default('')
379
- });
380
-
381
- const RecordReviewSchema = ReviewSectionSchema.extend({
382
- source: z.string().min(1).default('review-records'),
383
- freshness: ReviewFreshnessSchema.default({
384
- status: 'unknown',
385
- reviewedCommit: '',
386
- currentCommit: '',
387
- commitsSinceReview: null,
388
- staleReason: ''
389
- }),
390
- errors: z.array(z.string()).default([])
391
- });
392
-
393
- const ReportReviewSchema = z.object({
394
- status: ReviewDecisionStatusSchema.default('skipped'),
395
- summary: z.string().default(''),
396
- details: z.string().default(''),
397
- freshness: ReviewFreshnessSchema.default({
398
- status: 'unknown',
399
- reviewedCommit: '',
400
- currentCommit: '',
401
- commitsSinceReview: null,
402
- staleReason: ''
403
- }),
404
- qualityScore: z.number().min(0).max(10).nullable().default(null),
405
- specialistReviews: z.array(z.object({
406
- name: z.string().min(1),
407
- status: ReviewDecisionStatusSchema,
408
- required: z.boolean().default(false),
409
- summary: z.string().default(''),
410
- skipReason: z.string().default(''),
411
- findings: z.array(ReviewFindingSchema).default([])
412
- })).default([]),
413
- taskReviews: ReviewSectionSchema.default({
414
- status: 'skipped',
415
- required: false,
416
- summary: '',
417
- reviewers: [],
418
- findings: []
419
- }),
420
- recordReview: RecordReviewSchema.default({
421
- source: 'review-records',
422
- status: 'skipped',
423
- required: false,
424
- summary: '',
425
- reviewers: [],
426
- findings: [],
427
- freshness: {
428
- status: 'unknown',
429
- reviewedCommit: '',
430
- currentCommit: '',
431
- commitsSinceReview: null,
432
- staleReason: ''
433
- },
434
- errors: []
435
- }),
436
- diffReview: ReviewSectionSchema.default({
437
- status: 'skipped',
438
- required: false,
439
- summary: '',
440
- reviewers: [],
441
- findings: []
442
- }),
443
- findings: z.array(ReviewFindingSchema).default([])
444
- });
445
-
446
- const ClaimEvidenceSchema = z.object({
447
- claim: z.string().min(1),
448
- requiredProof: z.string().min(1),
449
- commandOrArtifact: z.string().min(1),
450
- exitStatus: z.number().int().nullable().optional(),
451
- keyObservation: z.string().default(''),
452
- status: ReviewDecisionStatusSchema
453
- });
454
-
455
- const RuntimeFailureOwnershipSchema = z.object({
456
- failure: z.string().min(1),
457
- classification: z.enum(['in-branch', 'pre-existing', 'environment', 'ambiguous']),
458
- touchedByDiff: z.boolean().optional(),
459
- evidence: z.string().default(''),
460
- action: z.string().default(''),
461
- status: z.string().default('open')
462
- });
463
-
464
- const ReportRuntimeSchema = z.object({
465
- status: ReviewDecisionStatusSchema.default('skipped'),
466
- failureOwnership: z.array(RuntimeFailureOwnershipSchema).default([])
467
- }).default({
468
- status: 'skipped',
469
- failureOwnership: []
470
- });
471
-
472
- const QaSchema = z.object({
473
- status: ReviewDecisionStatusSchema.default('skipped'),
474
- regressionProof: z.array(z.record(z.any())).default([]),
475
- testQuality: z.array(z.record(z.any())).default([]),
476
- coverageAudit: z.object({
477
- status: ReviewDecisionStatusSchema.default('skipped'),
478
- coveragePct: z.number().nullable().default(null),
479
- pathMap: z.array(z.string()).default([]),
480
- gaps: z.array(z.string()).default([]),
481
- testsAdded: z.array(z.string()).default([]),
482
- e2eRequired: z.boolean().default(false),
483
- evalRequired: z.boolean().default(false),
484
- qualityStars: z.string().default('')
485
- }).default({
486
- status: 'skipped',
487
- coveragePct: null,
488
- pathMap: [],
489
- gaps: [],
490
- testsAdded: [],
491
- e2eRequired: false,
492
- evalRequired: false,
493
- qualityStars: ''
494
- }),
495
- browserEvidence: z.object({
496
- status: ReviewDecisionStatusSchema.default('skipped'),
497
- mode: z.string().default('not-applicable'),
498
- affectedRoutes: z.array(z.string()).default([]),
499
- screenshots: z.array(z.string()).default([]),
500
- consoleErrors: z.array(z.string()).default([]),
501
- healthScore: z.number().nullable().default(null),
502
- issues: z.array(z.record(z.any())).default([]),
503
- skipReason: z.string().default('')
504
- }).default({
505
- status: 'skipped',
506
- mode: 'not-applicable',
507
- affectedRoutes: [],
508
- screenshots: [],
509
- consoleErrors: [],
510
- healthScore: null,
511
- issues: [],
512
- skipReason: ''
513
- }),
514
- tddException: z.string().nullable().default(null)
515
- }).default({
516
- status: 'skipped',
517
- regressionProof: [],
518
- testQuality: [],
519
- coverageAudit: {
520
- status: 'skipped',
521
- coveragePct: null,
522
- pathMap: [],
523
- gaps: [],
524
- testsAdded: [],
525
- e2eRequired: false,
526
- evalRequired: false,
527
- qualityStars: ''
528
- },
529
- browserEvidence: {
530
- status: 'skipped',
531
- mode: 'not-applicable',
532
- affectedRoutes: [],
533
- screenshots: [],
534
- consoleErrors: [],
535
- healthScore: null,
536
- issues: [],
537
- skipReason: ''
538
- },
539
- tddException: null
540
- });
541
-
542
- const ReportCardSchema = z.object({
543
- changeId: ChangeIdSchema,
544
- verdict: z.enum(['pass', 'fail', 'blocked']).optional(),
545
- overall: z.enum(['pass', 'fail']),
546
- summary: z.string().default(''),
547
- specAlignment: z.enum(['pass', 'fail', 'blocked']).default('blocked'),
548
- specDeltaVerified: z.boolean().default(false),
549
- specSyncReady: z.boolean().default(false),
550
- runtime: ReportRuntimeSchema,
551
- claimEvidence: z.array(ClaimEvidenceSchema).default([]),
552
- qa: QaSchema,
553
- quickGates: z.array(GateResultSchema),
554
- strictGates: z.array(GateResultSchema),
555
- review: ReportReviewSchema,
556
- blockingFindings: z.array(z.string()),
557
- gaps: z.array(z.string()).default([]),
558
- reroute: z.enum(['none', 'cc-do', 'cc-investigate', 'cc-plan']).default('none'),
559
- timestamp: z.string().datetime()
560
- });
561
-
562
- /* ============================================================
563
- * Review-ledger event schemas (REQ-003 minimize-workflow-artifacts)
564
- * Source: devflow/changes/REQ-003-minimize-workflow-artifacts/
565
- * planning/design.md §Interface & Data Contract
566
- * ============================================================ */
567
-
568
- const REVIEW_LEDGER_SCHEMA = z.literal('review-ledger.v2');
569
- const REVIEW_FINDINGS_SCHEMA = z.literal('review-findings.v2');
570
- const ReviewLedgerRouteSchema = z.enum(['cc-do', 'cc-check', 'cc-plan', 'cc-act', 'no-op']);
571
- const ReviewLedgerModeSchema = z.enum(['plan', 'implementation', 'mixed']);
572
- const ReviewLedgerSeveritySchema = z.enum(['critical', 'important', 'advisory']);
573
- const ReviewLedgerDisplayTierSchema = z.enum(['blocking', 'warning', 'info', 'suppressed']);
574
- const ReviewLedgerFreshnessStatusSchema = z.enum(['fresh', 'stale', 'unknown']);
575
- const ReviewLedgerSummaryStatusSchema = z.enum(['clean', 'findings', 'blocked']);
576
-
577
- const reviewLedgerEventCommon = {
578
- schema: REVIEW_LEDGER_SCHEMA,
579
- change: z.string().min(1),
580
- reviewId: z.string().min(1),
581
- createdAt: z.string().datetime(),
582
- createdBy: z.string().min(1)
583
- };
584
-
585
- const ReviewLedgerStartedEventSchema = z.object({
586
- ...reviewLedgerEventCommon,
587
- event: z.literal('review-started'),
588
- mode: ReviewLedgerModeSchema,
589
- scope: z.string().min(1),
590
- baseSha: z.string().min(1),
591
- headSha: z.string().min(1),
592
- selectedNodes: z.array(z.string().min(1)).default([]),
593
- skippedNodes: z.array(z.object({
594
- node: z.string().min(1),
595
- reason: z.string().default('')
596
- })).default([]),
597
- riskLanes: z.array(z.string().min(1)).default([])
598
- });
599
-
600
- const ReviewLedgerNodeCheckedEventSchema = z.object({
601
- ...reviewLedgerEventCommon,
602
- event: z.literal('review-node-checked'),
603
- nodeId: z.string().min(1),
604
- mode: ReviewLedgerModeSchema,
605
- target: z.string().min(1),
606
- status: z.enum(['checked', 'skipped', 'blocked']),
607
- coverage: z.array(z.string().min(1)).default([]),
608
- evidenceRefs: z.array(z.string().min(1)).default([]),
609
- findings: z.array(z.string().min(1)).default([]),
610
- next: ReviewLedgerRouteSchema
611
- });
612
-
613
- const ReviewLedgerFindingAddedEventSchema = z.object({
614
- ...reviewLedgerEventCommon,
615
- event: z.literal('review-finding-added'),
616
- findingId: z.string().min(1),
617
- severity: ReviewLedgerSeveritySchema,
618
- confidence: z.number().min(0).max(10),
619
- displayTier: ReviewLedgerDisplayTierSchema,
620
- fingerprint: z.string().min(1),
621
- scope: z.string().min(1),
622
- path: z.string().min(1),
623
- evidence: z.string().min(1),
624
- recommendation: z.string().min(1),
625
- route: ReviewLedgerRouteSchema
626
- });
627
-
628
- const ReviewLedgerClosedEventSchema = z.object({
629
- ...reviewLedgerEventCommon,
630
- event: z.literal('review-closed'),
631
- status: ReviewLedgerSummaryStatusSchema,
632
- blockingCount: z.number().int().min(0),
633
- warningCount: z.number().int().min(0),
634
- next: ReviewLedgerRouteSchema
635
- });
636
-
637
- const ReviewLedgerEventSchema = z.discriminatedUnion('event', [
638
- ReviewLedgerStartedEventSchema,
639
- ReviewLedgerNodeCheckedEventSchema,
640
- ReviewLedgerFindingAddedEventSchema,
641
- ReviewLedgerClosedEventSchema
642
- ]);
643
-
644
- const ReviewLedgerFindingEntrySchema = z.object({
645
- id: z.string().min(1),
646
- severity: ReviewLedgerSeveritySchema,
647
- confidence: z.number().min(0).max(10),
648
- displayTier: ReviewLedgerDisplayTierSchema,
649
- fingerprint: z.string().min(1),
650
- scope: z.string().min(1),
651
- path: z.string().min(1),
652
- evidence: z.string().min(1),
653
- recommendation: z.string().min(1),
654
- route: ReviewLedgerRouteSchema
655
- });
656
-
657
- const ReviewFindingsDocSchema = z.object({
658
- schema: REVIEW_FINDINGS_SCHEMA,
659
- change: z.string().min(1),
660
- reviewId: z.string().min(1),
661
- headSha: z.string().min(1),
662
- freshness: z.object({
663
- status: ReviewLedgerFreshnessStatusSchema,
664
- reviewedCommit: z.string().min(1),
665
- currentCommit: z.string().min(1),
666
- commitsSinceReview: z.number().int().min(0)
667
- }),
668
- summary: z.object({
669
- status: ReviewLedgerSummaryStatusSchema,
670
- blockingCount: z.number().int().min(0),
671
- warningCount: z.number().int().min(0),
672
- next: ReviewLedgerRouteSchema
673
- }),
674
- findings: z.array(ReviewLedgerFindingEntrySchema).default([])
675
- });
676
-
677
- function parseWithSchema(schema, input, label) {
678
- const parsed = schema.safeParse(input);
679
- if (parsed.success) {
680
- return parsed.data;
681
- }
682
-
683
- const issues = parsed.error.issues
684
- .map((issue) => `${issue.path.join('.') || '<root>'}: ${issue.message}`)
685
- .join('; ');
686
- throw new Error(`${label} validation failed: ${issues}`);
687
- }
688
-
689
- function parseManifest(input) {
690
- const manifest = parseWithSchema(ManifestSchema, input, 'Manifest');
691
- delete manifest.activePhase;
692
- return manifest;
693
- }
694
-
695
- function parseCheckpoint(input) {
696
- return parseWithSchema(CheckpointSchema, input, 'Checkpoint');
697
- }
698
-
699
- function parseReportCard(input) {
700
- return parseWithSchema(ReportCardSchema, input, 'ReportCard');
701
- }
702
-
703
- function parseRuntimeState(input) {
704
- return parseWithSchema(RuntimeStateSchema, input, 'RuntimeState');
705
- }
706
-
707
- function parseReviewLedgerEvent(input) {
708
- return parseWithSchema(ReviewLedgerEventSchema, input, 'ReviewLedgerEvent');
709
- }
710
-
711
- function parseReviewFindingsDoc(input) {
712
- return parseWithSchema(ReviewFindingsDocSchema, input, 'ReviewFindingsDoc');
713
- }
714
-
715
- module.exports = {
716
- ChangeIdSchema,
717
- TaskSchema,
718
- TaskStatusSchema,
719
- RuntimeStatusSchema,
720
- ApprovalStatusSchema,
721
- ExecutionModeSchema,
722
- RuntimeApprovalSchema,
723
- RuntimeStateSchema,
724
- ManifestSchema,
725
- CheckpointSchema,
726
- GateResultSchema,
727
- ReviewDecisionStatusSchema,
728
- ReviewFindingSchema,
729
- ReviewerResultSchema,
730
- ReviewSectionSchema,
731
- ReportReviewSchema,
732
- ReportCardSchema,
733
- ReviewLedgerEventSchema,
734
- ReviewLedgerStartedEventSchema,
735
- ReviewLedgerNodeCheckedEventSchema,
736
- ReviewLedgerFindingAddedEventSchema,
737
- ReviewLedgerClosedEventSchema,
738
- ReviewLedgerFindingEntrySchema,
739
- ReviewFindingsDocSchema,
740
- parseManifest,
741
- parseCheckpoint,
742
- parseReportCard,
743
- parseRuntimeState,
744
- parseReviewLedgerEvent,
745
- parseReviewFindingsDoc
746
- };