@abelxiaoxing/cadence 1.8.4 → 2.0.1

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 (202) hide show
  1. package/README.md +324 -117
  2. package/THIRD_PARTY_NOTICES.md +15 -0
  3. package/agents/design-explorer.md +14 -18
  4. package/agents/diagnosis-worker.md +14 -14
  5. package/agents/implementation-worker.md +16 -17
  6. package/config/workflow-task.example.json +7 -0
  7. package/docs/remote-access.md +60 -0
  8. package/docs/reuse-and-distribution.md +44 -0
  9. package/docs/service-management.md +108 -0
  10. package/licenses/bundled-web.txt +6245 -0
  11. package/licenses/pi-web-ui-MIT.txt +21 -0
  12. package/licenses/pi-web-ui-reuse.md +22 -0
  13. package/package.json +92 -20
  14. package/src/index.ts +21 -1802
  15. package/src/native-build.ts +6 -0
  16. package/src/native-client.ts +103 -0
  17. package/src/native-export.ts +58 -0
  18. package/src/native-history.ts +359 -0
  19. package/src/operator-cli.mjs +453 -1937
  20. package/src/plan-proposal.ts +87 -0
  21. package/src/sdk-worker.mjs +549 -0
  22. package/src/service/contracts/active.ts +82 -0
  23. package/src/service/contracts/budget.ts +148 -0
  24. package/src/service/contracts/build.ts +67 -0
  25. package/src/service/contracts/capture.ts +48 -0
  26. package/src/service/contracts/core.ts +33 -0
  27. package/src/service/contracts/current.ts +261 -0
  28. package/src/service/contracts/domain.ts +68 -0
  29. package/src/service/contracts/history.ts +2245 -0
  30. package/src/service/contracts/models.ts +139 -0
  31. package/src/service/coordination.ts +862 -0
  32. package/src/service/private-files.ts +204 -0
  33. package/src/service-cli.mjs +5592 -0
  34. package/src/service-client.ts +747 -0
  35. package/src/service-contract.ts +245 -0
  36. package/src/service-host.mjs +22382 -0
  37. package/src/service-http-client.ts +425 -0
  38. package/src/service-wire.ts +372 -0
  39. package/src/task-shell.ts +1045 -0
  40. package/src/task-store.ts +479 -0
  41. package/src/task-types.ts +184 -0
  42. package/src/verification-diagnostics.ts +29 -72
  43. package/src/worker-capture.mjs +1197 -0
  44. package/src/worker-public.mjs +1753 -0
  45. package/src/worker-redaction.mjs +608 -0
  46. package/src/worker-tools.mjs +202 -0
  47. package/web/dist/assets/KaTeX_AMS-Regular.ttf +0 -0
  48. package/web/dist/assets/KaTeX_AMS-Regular.woff +0 -0
  49. package/web/dist/assets/KaTeX_AMS-Regular.woff2 +0 -0
  50. package/web/dist/assets/KaTeX_Caligraphic-Bold.ttf +0 -0
  51. package/web/dist/assets/KaTeX_Caligraphic-Bold.woff +0 -0
  52. package/web/dist/assets/KaTeX_Caligraphic-Bold.woff2 +0 -0
  53. package/web/dist/assets/KaTeX_Caligraphic-Regular.ttf +0 -0
  54. package/web/dist/assets/KaTeX_Caligraphic-Regular.woff +0 -0
  55. package/web/dist/assets/KaTeX_Caligraphic-Regular.woff2 +0 -0
  56. package/web/dist/assets/KaTeX_Fraktur-Bold.ttf +0 -0
  57. package/web/dist/assets/KaTeX_Fraktur-Bold.woff +0 -0
  58. package/web/dist/assets/KaTeX_Fraktur-Bold.woff2 +0 -0
  59. package/web/dist/assets/KaTeX_Fraktur-Regular.ttf +0 -0
  60. package/web/dist/assets/KaTeX_Fraktur-Regular.woff +0 -0
  61. package/web/dist/assets/KaTeX_Fraktur-Regular.woff2 +0 -0
  62. package/web/dist/assets/KaTeX_Main-Bold.ttf +0 -0
  63. package/web/dist/assets/KaTeX_Main-Bold.woff +0 -0
  64. package/web/dist/assets/KaTeX_Main-Bold.woff2 +0 -0
  65. package/web/dist/assets/KaTeX_Main-BoldItalic.ttf +0 -0
  66. package/web/dist/assets/KaTeX_Main-BoldItalic.woff +0 -0
  67. package/web/dist/assets/KaTeX_Main-BoldItalic.woff2 +0 -0
  68. package/web/dist/assets/KaTeX_Main-Italic.ttf +0 -0
  69. package/web/dist/assets/KaTeX_Main-Italic.woff +0 -0
  70. package/web/dist/assets/KaTeX_Main-Italic.woff2 +0 -0
  71. package/web/dist/assets/KaTeX_Main-Regular.ttf +0 -0
  72. package/web/dist/assets/KaTeX_Main-Regular.woff +0 -0
  73. package/web/dist/assets/KaTeX_Main-Regular.woff2 +0 -0
  74. package/web/dist/assets/KaTeX_Math-BoldItalic.ttf +0 -0
  75. package/web/dist/assets/KaTeX_Math-BoldItalic.woff +0 -0
  76. package/web/dist/assets/KaTeX_Math-BoldItalic.woff2 +0 -0
  77. package/web/dist/assets/KaTeX_Math-Italic.ttf +0 -0
  78. package/web/dist/assets/KaTeX_Math-Italic.woff +0 -0
  79. package/web/dist/assets/KaTeX_Math-Italic.woff2 +0 -0
  80. package/web/dist/assets/KaTeX_SansSerif-Bold.ttf +0 -0
  81. package/web/dist/assets/KaTeX_SansSerif-Bold.woff +0 -0
  82. package/web/dist/assets/KaTeX_SansSerif-Bold.woff2 +0 -0
  83. package/web/dist/assets/KaTeX_SansSerif-Italic.ttf +0 -0
  84. package/web/dist/assets/KaTeX_SansSerif-Italic.woff +0 -0
  85. package/web/dist/assets/KaTeX_SansSerif-Italic.woff2 +0 -0
  86. package/web/dist/assets/KaTeX_SansSerif-Regular.ttf +0 -0
  87. package/web/dist/assets/KaTeX_SansSerif-Regular.woff +0 -0
  88. package/web/dist/assets/KaTeX_SansSerif-Regular.woff2 +0 -0
  89. package/web/dist/assets/KaTeX_Script-Regular.ttf +0 -0
  90. package/web/dist/assets/KaTeX_Script-Regular.woff +0 -0
  91. package/web/dist/assets/KaTeX_Script-Regular.woff2 +0 -0
  92. package/web/dist/assets/KaTeX_Size1-Regular.ttf +0 -0
  93. package/web/dist/assets/KaTeX_Size1-Regular.woff +0 -0
  94. package/web/dist/assets/KaTeX_Size1-Regular.woff2 +0 -0
  95. package/web/dist/assets/KaTeX_Size2-Regular.ttf +0 -0
  96. package/web/dist/assets/KaTeX_Size2-Regular.woff +0 -0
  97. package/web/dist/assets/KaTeX_Size2-Regular.woff2 +0 -0
  98. package/web/dist/assets/KaTeX_Size3-Regular.ttf +0 -0
  99. package/web/dist/assets/KaTeX_Size3-Regular.woff +0 -0
  100. package/web/dist/assets/KaTeX_Size3-Regular.woff2 +0 -0
  101. package/web/dist/assets/KaTeX_Size4-Regular.ttf +0 -0
  102. package/web/dist/assets/KaTeX_Size4-Regular.woff +0 -0
  103. package/web/dist/assets/KaTeX_Size4-Regular.woff2 +0 -0
  104. package/web/dist/assets/KaTeX_Typewriter-Regular.ttf +0 -0
  105. package/web/dist/assets/KaTeX_Typewriter-Regular.woff +0 -0
  106. package/web/dist/assets/KaTeX_Typewriter-Regular.woff2 +0 -0
  107. package/web/dist/assets/cadence.css +2 -0
  108. package/web/dist/assets/cadence.js +7 -0
  109. package/web/dist/assets/markdown.js +296 -0
  110. package/web/dist/assets/react.js +9 -0
  111. package/web/dist/assets/rolldown-runtime.js +1 -0
  112. package/web/dist/assets/timeline-client.js +41 -0
  113. package/web/dist/assets/vis-timeline.css +1274 -0
  114. package/web/dist/assets/vis-timeline.js +32 -0
  115. package/web/dist/index.html +18 -0
  116. package/web/dist/manifest.json +505 -0
  117. package/config/plan-draft.example.json +0 -125
  118. package/config/plan-draft.multiple-tasks.example.json +0 -375
  119. package/config/plan-draft.quick.example.json +0 -78
  120. package/prompts/abel-design.md +0 -382
  121. package/prompts/abel-diagnose.md +0 -71
  122. package/prompts/abel-implement.md +0 -284
  123. package/prompts/abel-init.md +0 -52
  124. package/src/activation.ts +0 -44
  125. package/src/activity-contracts.ts +0 -82
  126. package/src/agent-registry.ts +0 -53
  127. package/src/apply-transaction.ts +0 -1437
  128. package/src/artifact-store.ts +0 -213
  129. package/src/build-windows-job.mjs +0 -95
  130. package/src/candidate-artifact.ts +0 -143
  131. package/src/candidate-context.ts +0 -289
  132. package/src/candidate-patch.ts +0 -271
  133. package/src/candidate-workspace.ts +0 -80
  134. package/src/canonical.ts +0 -16
  135. package/src/change-contract-schema.ts +0 -191
  136. package/src/change-contract.ts +0 -324
  137. package/src/change-verification.ts +0 -1617
  138. package/src/contracts.ts +0 -2466
  139. package/src/control-contracts.ts +0 -382
  140. package/src/delivery-compiler.ts +0 -1805
  141. package/src/delivery-revision.ts +0 -42
  142. package/src/design-control.ts +0 -1299
  143. package/src/design-diagnostics.ts +0 -181
  144. package/src/design-journal.ts +0 -1773
  145. package/src/directory-sync.ts +0 -36
  146. package/src/durable-contracts.ts +0 -227
  147. package/src/durable-workflow.ts +0 -822
  148. package/src/evidence-draft.ts +0 -122
  149. package/src/execution-profile.ts +0 -64
  150. package/src/execution-retention.ts +0 -77
  151. package/src/file-snapshot.ts +0 -163
  152. package/src/implement-continuation.ts +0 -559
  153. package/src/implement-graph.ts +0 -690
  154. package/src/implement-plan.ts +0 -72
  155. package/src/install-config.d.mts +0 -6
  156. package/src/isolation-backend.ts +0 -353
  157. package/src/model-source.ts +0 -22
  158. package/src/openspec-cli.ts +0 -494
  159. package/src/operator-cli-entry.mjs +0 -24
  160. package/src/operator-tools.ts +0 -309
  161. package/src/package-candidate-process.ts +0 -206
  162. package/src/package-candidate.ts +0 -24
  163. package/src/package-delivery.ts +0 -486
  164. package/src/package-state.ts +0 -320
  165. package/src/package-verification.ts +0 -635
  166. package/src/package-workflow.ts +0 -305
  167. package/src/packet-runtime.ts +0 -459
  168. package/src/phase-execution.ts +0 -2163
  169. package/src/pi-adapter.ts +0 -19
  170. package/src/plan-draft-summary.ts +0 -527
  171. package/src/plan-draft.ts +0 -502
  172. package/src/remove-path.ts +0 -32
  173. package/src/run-state.ts +0 -420
  174. package/src/run-store.ts +0 -1179
  175. package/src/safe-path.ts +0 -77
  176. package/src/scoped-grep-worker.mjs +0 -23
  177. package/src/scoped-tools.ts +0 -775
  178. package/src/single-task-draft.ts +0 -142
  179. package/src/sqlite-schema.ts +0 -171
  180. package/src/state-root.ts +0 -215
  181. package/src/storage-schema.ts +0 -360
  182. package/src/subagent-activity.ts +0 -1417
  183. package/src/subagent-process.ts +0 -476
  184. package/src/task-ledger.ts +0 -1338
  185. package/src/transport-budget.ts +0 -50
  186. package/src/verification-capability.ts +0 -1191
  187. package/src/verification-environment-io.ts +0 -389
  188. package/src/verification-environment.ts +0 -162
  189. package/src/verification-identity.ts +0 -77
  190. package/src/verification-scan.ts +0 -64
  191. package/src/windows-job-backend.ts +0 -419
  192. package/src/windows-job.c +0 -149
  193. package/src/workflow-engine.ts +0 -28
  194. package/src/workflow-policy.ts +0 -1670
  195. package/src/workflow-recovery-policy.ts +0 -97
  196. package/src/workflow-scheduling.ts +0 -105
  197. package/src/workflow-state-machine.ts +0 -4341
  198. package/src/workflow-status.ts +0 -576
  199. package/src/workspace-io-entry.mjs +0 -76
  200. package/src/workspace-io-worker.mjs +0 -1312
  201. package/src/workspace-io.ts +0 -89
  202. package/src/workspace-store.ts +0 -634
@@ -1,690 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { canonicalJson } from "./canonical.ts";
3
- import {
4
- type ImplementationPhase,
5
- type ImplementGraphBoundary,
6
- type ImplementGraphOutput,
7
- type ImplementGraphReadinessCode,
8
- type ImplementGraphReadinessDiagnostic,
9
- type ImplementTaskBoundary,
10
- type VerificationInputBinding,
11
- validateImplementGraphBoundary,
12
- verificationInputPaths,
13
- } from "./contracts.ts";
14
- import { isSafeRegularFile } from "./safe-path.ts";
15
- import {
16
- type VerificationRunnerEnvironment,
17
- validateVerificationAdapterCapability,
18
- } from "./verification-capability.ts";
19
-
20
- export function hashCanonicalValue(value: unknown): string {
21
- return createHash("sha256").update(canonicalJson(value)).digest("hex");
22
- }
23
-
24
- export interface ImplementExecutionFacts {
25
- completedTasks: readonly string[];
26
- blockedTasks?: readonly string[];
27
- appliedPhases?: ReadonlyArray<{
28
- taskId: string;
29
- phase: ImplementationPhase;
30
- }>;
31
- candidate?: { taskId: string; phase: ImplementationPhase };
32
- dependencyOwner?: string;
33
- verificationRunnerEnvironment?: VerificationRunnerEnvironment;
34
- }
35
-
36
- export interface ImplementPhaseReadiness {
37
- taskId: string;
38
- phase: ImplementationPhase;
39
- ready: boolean;
40
- completed?: true;
41
- diagnostics: ImplementGraphReadinessDiagnostic[];
42
- }
43
-
44
- export interface ImplementGraphReadiness {
45
- closure: {
46
- executable: boolean;
47
- diagnostics: ImplementGraphReadinessDiagnostic[];
48
- };
49
- phases: ImplementPhaseReadiness[];
50
- outputs: ImplementOutputReadiness[];
51
- }
52
-
53
- export interface ImplementOutputReadiness {
54
- outputId: string;
55
- producerTaskId: string;
56
- producerPhase: ImplementationPhase;
57
- status: "pending" | "available" | "unavailable";
58
- diagnostic?: ImplementGraphReadinessDiagnostic;
59
- }
60
-
61
- const IMPLEMENT_PHASE_INDEX: Record<ImplementationPhase, number> = {
62
- red: 0,
63
- green: 1,
64
- refactor: 2,
65
- };
66
-
67
- function graphDiagnostic(
68
- code: ImplementGraphReadinessCode,
69
- details: Omit<
70
- Extract<ImplementGraphReadinessDiagnostic, { kind: "graph-readiness" }>,
71
- "kind" | "code"
72
- > = {},
73
- ): ImplementGraphReadinessDiagnostic {
74
- return { kind: "graph-readiness", code, ...details };
75
- }
76
-
77
- function taskPhases(
78
- task: ImplementTaskBoundary,
79
- ): Array<[ImplementationPhase, ImplementTaskBoundary["phases"]["red"]]> {
80
- return [
81
- ...(!task.verificationMode || task.verificationMode === "behavior"
82
- ? [
83
- ["red", task.phases.red] as [
84
- ImplementationPhase,
85
- ImplementTaskBoundary["phases"]["red"],
86
- ],
87
- ]
88
- : []),
89
- ["green", task.phases.green],
90
- ...(task.phases.refactor
91
- ? ([["refactor", task.phases.refactor]] as Array<
92
- [ImplementationPhase, ImplementTaskBoundary["phases"]["red"]]
93
- >)
94
- : []),
95
- ];
96
- }
97
-
98
- function withinTaskRoots(
99
- task: ImplementTaskBoundary,
100
- candidate: string,
101
- ): boolean {
102
- return task.roots.some(
103
- (root) =>
104
- root === "." || candidate === root || candidate.startsWith(`${root}/`),
105
- );
106
- }
107
-
108
- function dependencyAncestors(
109
- taskId: string,
110
- tasks: ReadonlyMap<string, ImplementTaskBoundary>,
111
- ): Set<string> {
112
- const ancestors = new Set<string>();
113
- const pending = [...(tasks.get(taskId)?.dependsOn ?? [])];
114
- while (pending.length > 0) {
115
- const dependency = pending.pop() as string;
116
- if (ancestors.has(dependency)) continue;
117
- ancestors.add(dependency);
118
- pending.push(...(tasks.get(dependency)?.dependsOn ?? []));
119
- }
120
- return ancestors;
121
- }
122
-
123
- type PathOperation = {
124
- taskId: string;
125
- phase: ImplementationPhase;
126
- kind: "write" | "delete";
127
- };
128
-
129
- function operationsBeforePhase(
130
- tasks: ReadonlyMap<string, ImplementTaskBoundary>,
131
- ancestors: ReadonlySet<string>,
132
- consumerTaskId: string,
133
- consumerPhase: ImplementationPhase,
134
- candidatePath: string,
135
- ): PathOperation[] {
136
- return [...tasks.values()].flatMap((task) => {
137
- if (task.taskId !== consumerTaskId && !ancestors.has(task.taskId)) {
138
- return [];
139
- }
140
- return taskPhases(task).flatMap(([phase, boundary]) => {
141
- if (
142
- task.taskId === consumerTaskId &&
143
- IMPLEMENT_PHASE_INDEX[phase] > IMPLEMENT_PHASE_INDEX[consumerPhase]
144
- ) {
145
- return [];
146
- }
147
- return [
148
- ...(boundary.write.includes(candidatePath)
149
- ? [{ taskId: task.taskId, phase, kind: "write" as const }]
150
- : []),
151
- ...(boundary.delete.includes(candidatePath)
152
- ? [{ taskId: task.taskId, phase, kind: "delete" as const }]
153
- : []),
154
- ];
155
- });
156
- });
157
- }
158
-
159
- function operationBefore(
160
- left: PathOperation,
161
- right: PathOperation,
162
- tasks: ReadonlyMap<string, ImplementTaskBoundary>,
163
- ): boolean {
164
- return left.taskId === right.taskId
165
- ? IMPLEMENT_PHASE_INDEX[left.phase] < IMPLEMENT_PHASE_INDEX[right.phase]
166
- : dependencyAncestors(right.taskId, tasks).has(left.taskId);
167
- }
168
-
169
- function survivesDeclaredOperations(
170
- operations: readonly PathOperation[],
171
- tasks: ReadonlyMap<string, ImplementTaskBoundary>,
172
- ): boolean {
173
- return operations
174
- .filter((operation) => operation.kind === "delete")
175
- .every((deletion) =>
176
- operations.some(
177
- (operation) =>
178
- operation.kind === "write" &&
179
- operationBefore(deletion, operation, tasks),
180
- ),
181
- );
182
- }
183
-
184
- function bindingPath(
185
- binding: VerificationInputBinding,
186
- outputs: ReadonlyMap<string, ImplementGraphOutput>,
187
- ): string | undefined {
188
- return binding.kind === "workspace"
189
- ? binding.path
190
- : outputs.get(binding.outputId)?.path;
191
- }
192
-
193
- function sameStringSet(
194
- left: readonly string[],
195
- right: readonly string[],
196
- ): boolean {
197
- return (
198
- left.length === right.length && left.every((entry) => right.includes(entry))
199
- );
200
- }
201
-
202
- function appendDistinct(
203
- diagnostics: ImplementGraphReadinessDiagnostic[],
204
- diagnostic: ImplementGraphReadinessDiagnostic,
205
- ): void {
206
- if (
207
- !diagnostics.some(
208
- (candidate) => JSON.stringify(candidate) === JSON.stringify(diagnostic),
209
- )
210
- ) {
211
- diagnostics.push(diagnostic);
212
- }
213
- }
214
-
215
- export function assessImplementGraphReadiness(
216
- root: string,
217
- value: unknown,
218
- facts: ImplementExecutionFacts,
219
- ): ImplementGraphReadiness {
220
- const validation = validateImplementGraphBoundary(value);
221
- if (!validation.ok) {
222
- const diagnostic = graphDiagnostic(validation.diagnostic.code, {
223
- ...(validation.diagnostic.code === "invalid-output-path" &&
224
- validation.diagnostic.outputId
225
- ? { outputId: validation.diagnostic.outputId }
226
- : {}),
227
- });
228
- return {
229
- closure: { executable: false, diagnostics: [diagnostic] },
230
- phases: [],
231
- outputs: [],
232
- };
233
- }
234
-
235
- const graph: ImplementGraphBoundary = validation.value;
236
- const diagnostics: ImplementGraphReadinessDiagnostic[] = [];
237
- const tasks = new Map<string, ImplementTaskBoundary>();
238
- for (const task of graph.tasks) {
239
- if (tasks.has(task.taskId)) {
240
- diagnostics.push(
241
- graphDiagnostic("duplicate-task-id", { taskId: task.taskId }),
242
- );
243
- } else {
244
- tasks.set(task.taskId, task);
245
- }
246
- }
247
-
248
- for (const task of graph.tasks) {
249
- for (const dependencyTaskId of task.dependsOn) {
250
- if (!tasks.has(dependencyTaskId) || dependencyTaskId === task.taskId) {
251
- diagnostics.push(
252
- graphDiagnostic("unknown-dependency", {
253
- taskId: task.taskId,
254
- dependencyTaskId,
255
- }),
256
- );
257
- }
258
- }
259
- if (dependencyAncestors(task.taskId, tasks).has(task.taskId)) {
260
- diagnostics.push(
261
- graphDiagnostic("dependency-cycle", { taskId: task.taskId }),
262
- );
263
- }
264
- }
265
-
266
- const outputs = new Map<string, ImplementGraphOutput>();
267
- const outputPaths = new Map<string, ImplementGraphOutput>();
268
- for (const output of graph.outputs) {
269
- if (outputs.has(output.id)) {
270
- diagnostics.push(
271
- graphDiagnostic("duplicate-output-id", { outputId: output.id }),
272
- );
273
- } else {
274
- outputs.set(output.id, output);
275
- }
276
- const prior = outputPaths.get(output.path);
277
- if (prior) {
278
- diagnostics.push(
279
- graphDiagnostic("multiple-output-producers", {
280
- outputId: output.id,
281
- path: output.path,
282
- producerTaskId: output.producer.taskId,
283
- producerPhase: output.producer.phase,
284
- }),
285
- );
286
- } else {
287
- outputPaths.set(output.path, output);
288
- }
289
-
290
- const producer = tasks.get(output.producer.taskId);
291
- const producerPhase = producer?.phases[output.producer.phase];
292
- if (
293
- !producer ||
294
- !producerPhase ||
295
- !withinTaskRoots(producer, output.path)
296
- ) {
297
- diagnostics.push(
298
- graphDiagnostic("output-producer-invalid", {
299
- outputId: output.id,
300
- producerTaskId: output.producer.taskId,
301
- producerPhase: output.producer.phase,
302
- }),
303
- );
304
- } else if (!producerPhase.write.includes(output.path)) {
305
- diagnostics.push(
306
- graphDiagnostic("output-write-not-approved", {
307
- outputId: output.id,
308
- producerTaskId: output.producer.taskId,
309
- producerPhase: output.producer.phase,
310
- }),
311
- );
312
- }
313
- }
314
-
315
- const phaseStaticDiagnostics = new Map<
316
- string,
317
- ImplementGraphReadinessDiagnostic[]
318
- >();
319
- for (const task of graph.tasks) {
320
- const ancestors = dependencyAncestors(task.taskId, tasks);
321
- for (const [phase, boundary] of taskPhases(task)) {
322
- const key = `${task.taskId}\0${phase}`;
323
- const current: ImplementGraphReadinessDiagnostic[] = [];
324
- phaseStaticDiagnostics.set(key, current);
325
- const verificationId = boundary.verification.id;
326
- const requiredPaths = verificationInputPaths(boundary.verification);
327
- const boundPaths = boundary.verificationInputs
328
- .map((binding) => bindingPath(binding, outputs))
329
- .filter((entry): entry is string => entry !== undefined);
330
-
331
- for (const binding of boundary.verificationInputs) {
332
- if (binding.kind === "workspace") {
333
- const graphOutput = outputPaths.get(binding.path);
334
- if (graphOutput) {
335
- appendDistinct(
336
- current,
337
- graphDiagnostic("workspace-input-has-producer", {
338
- taskId: task.taskId,
339
- phase,
340
- verificationId,
341
- outputId: graphOutput.id,
342
- path: binding.path,
343
- }),
344
- );
345
- }
346
- if (!isSafeRegularFile(root, binding.path)) {
347
- appendDistinct(
348
- current,
349
- graphDiagnostic("workspace-input-unavailable", {
350
- taskId: task.taskId,
351
- phase,
352
- verificationId,
353
- path: binding.path,
354
- }),
355
- );
356
- }
357
- if (
358
- !survivesDeclaredOperations(
359
- operationsBeforePhase(
360
- tasks,
361
- ancestors,
362
- task.taskId,
363
- phase,
364
- binding.path,
365
- ),
366
- tasks,
367
- )
368
- ) {
369
- appendDistinct(
370
- current,
371
- graphDiagnostic("workspace-input-unavailable", {
372
- taskId: task.taskId,
373
- phase,
374
- verificationId,
375
- path: binding.path,
376
- }),
377
- );
378
- }
379
- continue;
380
- }
381
-
382
- const output = outputs.get(binding.outputId);
383
- if (!output) {
384
- appendDistinct(
385
- current,
386
- graphDiagnostic("output-not-declared", {
387
- taskId: task.taskId,
388
- phase,
389
- verificationId,
390
- outputId: binding.outputId,
391
- }),
392
- );
393
- continue;
394
- }
395
- if (output.producer.taskId === task.taskId) {
396
- if (
397
- IMPLEMENT_PHASE_INDEX[output.producer.phase] >
398
- IMPLEMENT_PHASE_INDEX[phase]
399
- ) {
400
- appendDistinct(
401
- current,
402
- graphDiagnostic("producer-phase-after-consumer", {
403
- taskId: task.taskId,
404
- phase,
405
- verificationId,
406
- outputId: output.id,
407
- producerTaskId: output.producer.taskId,
408
- producerPhase: output.producer.phase,
409
- }),
410
- );
411
- }
412
- } else if (!ancestors.has(output.producer.taskId)) {
413
- appendDistinct(
414
- current,
415
- graphDiagnostic("producer-not-dependency", {
416
- taskId: task.taskId,
417
- phase,
418
- verificationId,
419
- outputId: output.id,
420
- producerTaskId: output.producer.taskId,
421
- producerPhase: output.producer.phase,
422
- }),
423
- );
424
- }
425
- if (
426
- (output.producer.taskId === task.taskId ||
427
- ancestors.has(output.producer.taskId)) &&
428
- IMPLEMENT_PHASE_INDEX[output.producer.phase] <=
429
- (output.producer.taskId === task.taskId
430
- ? IMPLEMENT_PHASE_INDEX[phase]
431
- : IMPLEMENT_PHASE_INDEX.refactor) &&
432
- !survivesDeclaredOperations(
433
- operationsBeforePhase(
434
- tasks,
435
- ancestors,
436
- task.taskId,
437
- phase,
438
- output.path,
439
- ),
440
- tasks,
441
- )
442
- ) {
443
- appendDistinct(
444
- current,
445
- graphDiagnostic("producer-output-unavailable", {
446
- taskId: task.taskId,
447
- phase,
448
- verificationId,
449
- outputId: output.id,
450
- path: output.path,
451
- producerTaskId: output.producer.taskId,
452
- producerPhase: output.producer.phase,
453
- }),
454
- );
455
- }
456
- }
457
-
458
- if (!sameStringSet(requiredPaths, boundPaths)) {
459
- appendDistinct(
460
- current,
461
- graphDiagnostic("verification-input-binding-mismatch", {
462
- taskId: task.taskId,
463
- phase,
464
- verificationId,
465
- field: `phases.${phase}.verificationInputs`,
466
- expectedPaths: [...requiredPaths].sort(),
467
- actualPaths: [...boundPaths].sort(),
468
- }),
469
- );
470
- }
471
-
472
- const capability = validateVerificationAdapterCapability(
473
- root,
474
- boundary.verification,
475
- {
476
- dependencyOwner: facts.dependencyOwner ?? root,
477
- runnerEnvironment: facts.verificationRunnerEnvironment,
478
- },
479
- );
480
- if (!capability.ok) {
481
- const { message: _message, ...diagnostic } = capability.diagnostic;
482
- appendDistinct(current, {
483
- ...diagnostic,
484
- taskId: task.taskId,
485
- phase,
486
- });
487
- }
488
- diagnostics.push(...current);
489
- }
490
- }
491
-
492
- const closure = {
493
- executable: diagnostics.length === 0,
494
- diagnostics,
495
- };
496
- const completedTasks = new Set(facts.completedTasks);
497
- const blockedTasks = new Set(facts.blockedTasks ?? []);
498
- const appliedPhases = new Set(
499
- (facts.appliedPhases ?? []).map(
500
- (entry) => `${entry.taskId}\0${entry.phase}`,
501
- ),
502
- );
503
- const outputReadiness: ImplementOutputReadiness[] = graph.outputs.map(
504
- (output) => {
505
- const observed =
506
- completedTasks.has(output.producer.taskId) ||
507
- appliedPhases.has(
508
- `${output.producer.taskId}\0${output.producer.phase}`,
509
- ) ||
510
- (facts.candidate?.taskId === output.producer.taskId &&
511
- facts.candidate.phase === output.producer.phase);
512
- if (!observed) {
513
- return {
514
- outputId: output.id,
515
- producerTaskId: output.producer.taskId,
516
- producerPhase: output.producer.phase,
517
- status: "pending" as const,
518
- };
519
- }
520
- if (isSafeRegularFile(root, output.path)) {
521
- return {
522
- outputId: output.id,
523
- producerTaskId: output.producer.taskId,
524
- producerPhase: output.producer.phase,
525
- status: "available" as const,
526
- };
527
- }
528
- return {
529
- outputId: output.id,
530
- producerTaskId: output.producer.taskId,
531
- producerPhase: output.producer.phase,
532
- status: "unavailable" as const,
533
- diagnostic: graphDiagnostic("producer-output-unavailable", {
534
- outputId: output.id,
535
- producerTaskId: output.producer.taskId,
536
- producerPhase: output.producer.phase,
537
- }),
538
- };
539
- },
540
- );
541
- const outputStatus = new Map(
542
- outputReadiness.map((entry) => [entry.outputId, entry]),
543
- );
544
- const phases: ImplementPhaseReadiness[] = [];
545
-
546
- for (const task of graph.tasks) {
547
- for (const [phase, boundary] of taskPhases(task)) {
548
- const staticDiagnostics = phaseStaticDiagnostics.get(
549
- `${task.taskId}\0${phase}`,
550
- ) as ImplementGraphReadinessDiagnostic[];
551
- if (!closure.executable) {
552
- phases.push({
553
- taskId: task.taskId,
554
- phase,
555
- ready: false,
556
- diagnostics:
557
- staticDiagnostics.length > 0 ? staticDiagnostics : diagnostics,
558
- });
559
- continue;
560
- }
561
- if (completedTasks.has(task.taskId)) {
562
- phases.push({
563
- taskId: task.taskId,
564
- phase,
565
- ready: false,
566
- completed: true,
567
- diagnostics: [],
568
- });
569
- continue;
570
- }
571
-
572
- const current: ImplementGraphReadinessDiagnostic[] = [];
573
- if (blockedTasks.has(task.taskId)) {
574
- current.push(
575
- graphDiagnostic("dependency-blocked", {
576
- taskId: task.taskId,
577
- phase,
578
- dependencyTaskId: task.taskId,
579
- }),
580
- );
581
- }
582
- for (const dependencyTaskId of task.dependsOn) {
583
- if (!completedTasks.has(dependencyTaskId)) {
584
- appendDistinct(
585
- current,
586
- graphDiagnostic("dependency-blocked", {
587
- taskId: task.taskId,
588
- phase,
589
- dependencyTaskId,
590
- }),
591
- );
592
- }
593
- }
594
-
595
- const earlierPhases = taskPhases(task)
596
- .map(([candidate]) => candidate)
597
- .filter(
598
- (candidate) =>
599
- IMPLEMENT_PHASE_INDEX[candidate] < IMPLEMENT_PHASE_INDEX[phase],
600
- );
601
- if (
602
- earlierPhases.some(
603
- (candidate) => !appliedPhases.has(`${task.taskId}\0${candidate}`),
604
- )
605
- ) {
606
- appendDistinct(
607
- current,
608
- graphDiagnostic("phase-blocked", { taskId: task.taskId, phase }),
609
- );
610
- }
611
-
612
- if (current.length === 0) {
613
- for (const binding of boundary.verificationInputs) {
614
- if (binding.kind !== "output") continue;
615
- const output = outputs.get(binding.outputId);
616
- if (!output) continue;
617
- const sameTask = output.producer.taskId === task.taskId;
618
- const samePhase = sameTask && output.producer.phase === phase;
619
- const readiness = outputStatus.get(output.id);
620
- const published =
621
- !sameTask && completedTasks.has(output.producer.taskId);
622
- if (readiness?.status === "unavailable") {
623
- appendDistinct(
624
- current,
625
- graphDiagnostic("producer-output-unavailable", {
626
- taskId: task.taskId,
627
- phase,
628
- outputId: output.id,
629
- producerTaskId: output.producer.taskId,
630
- producerPhase: output.producer.phase,
631
- }),
632
- );
633
- } else if (
634
- (!sameTask && !published) ||
635
- (sameTask && !samePhase && readiness?.status !== "available")
636
- ) {
637
- appendDistinct(
638
- current,
639
- sameTask
640
- ? graphDiagnostic("phase-blocked", {
641
- taskId: task.taskId,
642
- phase,
643
- })
644
- : graphDiagnostic("dependency-blocked", {
645
- taskId: task.taskId,
646
- phase,
647
- dependencyTaskId: output.producer.taskId,
648
- }),
649
- );
650
- }
651
- }
652
-
653
- if (
654
- facts.candidate?.taskId === task.taskId &&
655
- facts.candidate.phase === phase
656
- ) {
657
- for (const output of graph.outputs.filter(
658
- (entry) =>
659
- entry.producer.taskId === task.taskId &&
660
- entry.producer.phase === phase,
661
- )) {
662
- if (outputStatus.get(output.id)?.status !== "available") {
663
- appendDistinct(
664
- current,
665
- graphDiagnostic("producer-output-unavailable", {
666
- taskId: task.taskId,
667
- phase,
668
- outputId: output.id,
669
- producerTaskId: output.producer.taskId,
670
- producerPhase: output.producer.phase,
671
- }),
672
- );
673
- }
674
- }
675
- }
676
- }
677
-
678
- phases.push({
679
- taskId: task.taskId,
680
- phase,
681
- ready: current.length === 0,
682
- diagnostics: current,
683
- });
684
- }
685
- }
686
-
687
- return { closure, phases, outputs: outputReadiness };
688
- }
689
-
690
- export { canonicalJson } from "./canonical.ts";