cc-devflow 4.5.11 → 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 (185) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +18 -0
  2. package/.claude/skills/cc-act/PLAYBOOK.md +17 -269
  3. package/.claude/skills/cc-act/SKILL.md +38 -425
  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 +18 -0
  15. package/.claude/skills/cc-check/PLAYBOOK.md +19 -273
  16. package/.claude/skills/cc-check/SKILL.md +33 -456
  17. package/.claude/skills/cc-check/references/review-contract.md +12 -147
  18. package/.claude/skills/cc-dev/CHANGELOG.md +15 -0
  19. package/.claude/skills/cc-dev/PLAYBOOK.md +1 -1
  20. package/.claude/skills/cc-dev/SKILL.md +52 -137
  21. package/.claude/skills/cc-dev/scripts/resolve-cc-devflow.sh +181 -0
  22. package/.claude/skills/cc-do/CHANGELOG.md +11 -0
  23. package/.claude/skills/cc-do/PLAYBOOK.md +19 -113
  24. package/.claude/skills/cc-do/SKILL.md +39 -245
  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 +16 -0
  31. package/.claude/skills/cc-investigate/PLAYBOOK.md +20 -180
  32. package/.claude/skills/cc-investigate/SKILL.md +64 -246
  33. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +48 -98
  34. package/.claude/skills/cc-investigate/references/investigation-contract.md +14 -218
  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 +16 -0
  39. package/.claude/skills/cc-plan/PLAYBOOK.md +22 -161
  40. package/.claude/skills/cc-plan/SKILL.md +45 -295
  41. package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +30 -228
  42. package/.claude/skills/cc-plan/references/planning-contract.md +24 -161
  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 +13 -0
  65. package/bin/cc-devflow-cli.js +20 -260
  66. package/bin/cc-devflow.js +44 -7
  67. package/docs/commands/README.md +1 -1
  68. package/docs/commands/README.zh-CN.md +1 -1
  69. package/docs/examples/README.md +1 -1
  70. package/docs/examples/START-HERE.md +14 -15
  71. package/docs/examples/example-bindings.json +11 -11
  72. package/docs/examples/full-design-blocked/README.md +4 -6
  73. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/{planning/tasks.md → task.md} +20 -15
  74. package/docs/examples/local-handoff/README.md +8 -11
  75. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/pr-brief.md +31 -0
  76. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/{planning/tasks.md → task.md} +18 -13
  77. package/docs/examples/pdca-loop/README.md +6 -9
  78. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/pr-brief.md +9 -11
  79. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/{planning/tasks.md → task.md} +18 -13
  80. package/docs/examples/scripts/check-example-bindings.sh +11 -62
  81. package/docs/guides/artifact-contract.md +10 -40
  82. package/docs/guides/getting-started.md +8 -8
  83. package/docs/guides/getting-started.zh-CN.md +8 -8
  84. package/docs/guides/minimize-artifacts.md +16 -130
  85. package/docs/guides/project-postmortem.md +14 -71
  86. package/lib/compiler/__tests__/skills-registry.test.js +9 -8
  87. package/lib/compiler/resource-copier.js +29 -0
  88. package/lib/skill-runtime/__tests__/archive-change.test.js +2 -2
  89. package/lib/skill-runtime/__tests__/benchmark-skills.test.js +3 -3
  90. package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +14 -4
  91. package/lib/skill-runtime/errors.js +3 -3
  92. package/lib/skill-runtime/index.js +5 -23
  93. package/lib/skill-runtime/paths.js +5 -52
  94. package/lib/skill-runtime/query-registry.js +4 -4
  95. package/lib/skill-runtime/query.js +89 -201
  96. package/lib/skill-runtime/store.js +4 -40
  97. package/lib/skill-runtime/trace.js +2 -2
  98. package/package.json +2 -5
  99. package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_PRINCIPLES_TEMPLATE.md +0 -29
  100. package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +0 -54
  101. package/.claude/skills/cc-act/scripts/generate-status-report.sh +0 -92
  102. package/.claude/skills/cc-act/scripts/sync-act-docs.sh +0 -355
  103. package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +0 -234
  104. package/.claude/skills/cc-check/scripts/render-report-card.js +0 -438
  105. package/.claude/skills/cc-check/scripts/verify-gate.sh +0 -85
  106. package/.claude/skills/cc-do/scripts/build-task-context.sh +0 -175
  107. package/.claude/skills/cc-do/scripts/record-review-decision.sh +0 -88
  108. package/.claude/skills/cc-do/scripts/recover-workflow.sh +0 -82
  109. package/.claude/skills/cc-do/scripts/run-problem-analysis.sh +0 -70
  110. package/.claude/skills/cc-do/scripts/verify-task-gates.sh +0 -109
  111. package/.claude/skills/cc-do/scripts/write-task-checkpoint.sh +0 -92
  112. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +0 -224
  113. package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +0 -178
  114. package/.claude/skills/cc-spec-init/assets/CHANGE_META_TEMPLATE.json +0 -28
  115. package/.claude/skills/cc-spec-init/scripts/validate-spec-links.sh +0 -45
  116. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +0 -234
  117. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +0 -488
  118. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/review/report-card.json +0 -189
  119. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/resume-index.md +0 -39
  120. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/status.md +0 -29
  121. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +0 -123
  122. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +0 -292
  123. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/review/report-card.json +0 -136
  124. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/status.md +0 -29
  125. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +0 -124
  126. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +0 -292
  127. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/review/report-card.json +0 -136
  128. package/docs/get-shit-done-strategy-audit.md +0 -518
  129. package/docs/skill-runtime-migration.md +0 -46
  130. package/lib/skill-runtime/__tests__/approve.test.js +0 -92
  131. package/lib/skill-runtime/__tests__/autopilot.test.js +0 -253
  132. package/lib/skill-runtime/__tests__/benchmark-artifacts.test.js +0 -165
  133. package/lib/skill-runtime/__tests__/delegation.test.js +0 -97
  134. package/lib/skill-runtime/__tests__/dispatch.test.js +0 -237
  135. package/lib/skill-runtime/__tests__/intent.test.js +0 -203
  136. package/lib/skill-runtime/__tests__/lifecycle.test.js +0 -169
  137. package/lib/skill-runtime/__tests__/planner.tdd.test.js +0 -331
  138. package/lib/skill-runtime/__tests__/prepare-pr.test.js +0 -126
  139. package/lib/skill-runtime/__tests__/query.test.js +0 -860
  140. package/lib/skill-runtime/__tests__/readiness.test.js +0 -53
  141. package/lib/skill-runtime/__tests__/release.test.js +0 -85
  142. package/lib/skill-runtime/__tests__/review-check-integration.test.js +0 -148
  143. package/lib/skill-runtime/__tests__/review-records.test.js +0 -619
  144. package/lib/skill-runtime/__tests__/runtime.integration.test.js +0 -351
  145. package/lib/skill-runtime/__tests__/schemas.test.js +0 -337
  146. package/lib/skill-runtime/__tests__/task-contract-migrate.test.js +0 -137
  147. package/lib/skill-runtime/__tests__/task-contract.test.js +0 -874
  148. package/lib/skill-runtime/__tests__/team-state.test.js +0 -51
  149. package/lib/skill-runtime/__tests__/verify-artifacts.test.js +0 -203
  150. package/lib/skill-runtime/__tests__/worker-run.test.js +0 -275
  151. package/lib/skill-runtime/__tests__/worker.test.js +0 -56
  152. package/lib/skill-runtime/__tests__/workflow-context-legacy-fallback.test.js +0 -31
  153. package/lib/skill-runtime/__tests__/workflow-context.test.js +0 -98
  154. package/lib/skill-runtime/artifacts.js +0 -88
  155. package/lib/skill-runtime/context-index.js +0 -545
  156. package/lib/skill-runtime/delegation.js +0 -533
  157. package/lib/skill-runtime/intent.js +0 -309
  158. package/lib/skill-runtime/lifecycle.js +0 -294
  159. package/lib/skill-runtime/operations/CLAUDE.md +0 -19
  160. package/lib/skill-runtime/operations/approve.js +0 -81
  161. package/lib/skill-runtime/operations/autopilot-core.js +0 -337
  162. package/lib/skill-runtime/operations/autopilot-execution.js +0 -307
  163. package/lib/skill-runtime/operations/autopilot-shared.js +0 -48
  164. package/lib/skill-runtime/operations/autopilot.js +0 -163
  165. package/lib/skill-runtime/operations/dispatch.js +0 -416
  166. package/lib/skill-runtime/operations/init.js +0 -60
  167. package/lib/skill-runtime/operations/janitor.js +0 -61
  168. package/lib/skill-runtime/operations/plan.js +0 -59
  169. package/lib/skill-runtime/operations/prepare-pr.js +0 -25
  170. package/lib/skill-runtime/operations/release.js +0 -99
  171. package/lib/skill-runtime/operations/resume.js +0 -126
  172. package/lib/skill-runtime/operations/review-records.js +0 -265
  173. package/lib/skill-runtime/operations/snapshot.js +0 -45
  174. package/lib/skill-runtime/operations/task-contract.js +0 -593
  175. package/lib/skill-runtime/operations/verify.js +0 -170
  176. package/lib/skill-runtime/operations/worker-run.js +0 -531
  177. package/lib/skill-runtime/operations/worker.js +0 -33
  178. package/lib/skill-runtime/planner.js +0 -539
  179. package/lib/skill-runtime/readiness.js +0 -84
  180. package/lib/skill-runtime/review-records.js +0 -123
  181. package/lib/skill-runtime/review.js +0 -855
  182. package/lib/skill-runtime/schemas.js +0 -746
  183. package/lib/skill-runtime/task-contract.js +0 -188
  184. package/lib/skill-runtime/team-state.js +0 -122
  185. 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
- };