@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,635 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { closeSync, constants, fstatSync, openSync, readSync } from "node:fs";
3
- import path from "node:path";
4
- import {
5
- type AtomicVerificationContract,
6
- type StructuredVerificationContract,
7
- type VerificationInputObservation,
8
- type VerificationObservation,
9
- verificationSteps,
10
- } from "./contracts.ts";
11
- import { executionProfile } from "./execution-profile.ts";
12
- import { retainExecution } from "./execution-retention.ts";
13
- import { canonicalJson } from "./implement-graph.ts";
14
- import { BubblewrapIsolationBackend } from "./isolation-backend.ts";
15
- import { observeSafePath } from "./safe-path.ts";
16
- import {
17
- bindCurrentVerificationCapability,
18
- isVerificationCapabilityCurrent,
19
- type VerificationRunnerBinding,
20
- } from "./verification-capability.ts";
21
- import { diagnosticText } from "./verification-diagnostics.ts";
22
- import { prepareVerificationEnvironment } from "./verification-environment.ts";
23
- import { WindowsJobBackend } from "./windows-job-backend.ts";
24
-
25
- function sha256(value: Uint8Array | string): string {
26
- return createHash("sha256").update(value).digest("hex");
27
- }
28
-
29
- function packageScriptInvocation(
30
- packageManager: string,
31
- script: string,
32
- args: string[],
33
- ): string[] {
34
- return packageManager === "npm"
35
- ? ["run", script, "--", ...args]
36
- : ["run", script, ...args];
37
- }
38
-
39
- function bindingFor(
40
- bindings: readonly VerificationRunnerBinding[],
41
- command: string,
42
- ): VerificationRunnerBinding | undefined {
43
- return bindings.find((binding) => binding.command === command);
44
- }
45
-
46
- function verificationInvocation(
47
- step: AtomicVerificationContract,
48
- bindings: readonly VerificationRunnerBinding[],
49
- reportFile: string,
50
- ): { executable: string; args: string[] } | undefined {
51
- const reporter =
52
- step.kind === "vitest"
53
- ? ["--reporter=json", `--outputFile.json=${reportFile}`]
54
- : [];
55
- if (step.kind === "package-script") {
56
- const binding = bindingFor(bindings, step.packageManager);
57
- return binding
58
- ? {
59
- executable: binding.executablePath,
60
- args: [
61
- ...(binding.fixedArgs ?? []),
62
- ...packageScriptInvocation(
63
- step.packageManager,
64
- step.script,
65
- step.args,
66
- ),
67
- ],
68
- }
69
- : undefined;
70
- }
71
- const runner = step.runner;
72
- if (runner.kind === "package-script") {
73
- const binding = bindingFor(bindings, runner.packageManager);
74
- const args =
75
- step.kind === "vitest"
76
- ? [...step.testFiles, ...step.args, ...reporter]
77
- : step.args;
78
- return binding
79
- ? {
80
- executable: binding.executablePath,
81
- args: [
82
- ...(binding.fixedArgs ?? []),
83
- ...packageScriptInvocation(
84
- runner.packageManager,
85
- runner.script,
86
- args,
87
- ),
88
- ],
89
- }
90
- : undefined;
91
- }
92
- if (runner.kind === "local-binary") {
93
- const binding = bindingFor(bindings, runner.executable);
94
- return {
95
- executable:
96
- binding?.executablePath ??
97
- `/workspace/node_modules/.bin/${runner.executable}`,
98
- args: [
99
- ...(binding?.fixedArgs ?? []),
100
- ...(step.kind === "vitest"
101
- ? [...step.testFiles, ...step.args, ...reporter]
102
- : step.args),
103
- ],
104
- };
105
- }
106
- const command = runner.kind === "node" ? "node" : "npx";
107
- const binding = bindingFor(bindings, command);
108
- if (!binding) return undefined;
109
- return {
110
- executable: binding.executablePath,
111
- args:
112
- runner.kind === "node"
113
- ? [...(binding.fixedArgs ?? []), runner.script, ...step.args]
114
- : [
115
- ...(binding.fixedArgs ?? []),
116
- "--no-install",
117
- runner.executable,
118
- ...(step.kind === "vitest" ? step.testFiles : []),
119
- ...step.args,
120
- ...reporter,
121
- ],
122
- };
123
- }
124
-
125
- function vitestReport(json: string):
126
- | {
127
- total: number;
128
- failed: number;
129
- success: boolean;
130
- failures: string[];
131
- failedText: string[];
132
- }
133
- | undefined {
134
- let value: unknown;
135
- try {
136
- value = JSON.parse(json);
137
- } catch {
138
- return undefined;
139
- }
140
- if (!value || typeof value !== "object" || Array.isArray(value)) {
141
- return undefined;
142
- }
143
- const report = value as Record<string, unknown>;
144
- if (
145
- !Number.isSafeInteger(report.numTotalTests) ||
146
- !Number.isSafeInteger(report.numFailedTests) ||
147
- typeof report.success !== "boolean" ||
148
- (report.numTotalTests as number) < 0 ||
149
- (report.numFailedTests as number) < 0 ||
150
- (report.numFailedTests as number) > (report.numTotalTests as number) ||
151
- !Array.isArray(report.testResults) ||
152
- (report.numRuntimeErrorTestSuites !== undefined &&
153
- report.numRuntimeErrorTestSuites !== 0) ||
154
- (Array.isArray(report.unhandledErrors) && report.unhandledErrors.length > 0)
155
- ) {
156
- return undefined;
157
- }
158
- let assertionCount = 0;
159
- for (const suite of report.testResults) {
160
- if (
161
- !suite ||
162
- typeof suite !== "object" ||
163
- !Array.isArray(suite.assertionResults)
164
- )
165
- return undefined;
166
- for (const assertion of suite.assertionResults) {
167
- if (
168
- !assertion ||
169
- typeof assertion !== "object" ||
170
- ![
171
- "passed",
172
- "failed",
173
- "pending",
174
- "skipped",
175
- "todo",
176
- "disabled",
177
- ].includes(assertion.status)
178
- )
179
- return undefined;
180
- assertionCount++;
181
- }
182
- }
183
- if (assertionCount !== report.numTotalTests) return undefined;
184
- const failedAssertions = (
185
- Array.isArray(report.testResults) ? report.testResults : []
186
- ).flatMap((suite): Array<{ identity: string; text: string[] }> => {
187
- if (!suite || typeof suite !== "object" || Array.isArray(suite)) return [];
188
- const record = suite as Record<string, unknown>;
189
- const suiteName =
190
- typeof record.name === "string"
191
- ? record.name.replace(/^\/workspace\//u, "")
192
- : "unknown-suite";
193
- if (!Array.isArray(record.assertionResults)) return [];
194
- return record.assertionResults.flatMap(
195
- (assertion): Array<{ identity: string; text: string[] }> => {
196
- if (
197
- !assertion ||
198
- typeof assertion !== "object" ||
199
- Array.isArray(assertion)
200
- ) {
201
- return [];
202
- }
203
- const entry = assertion as Record<string, unknown>;
204
- if (entry.status !== "failed") return [];
205
- const title =
206
- typeof entry.fullName === "string"
207
- ? entry.fullName
208
- : typeof entry.title === "string"
209
- ? entry.title
210
- : "unknown-assertion";
211
- const diagnostics = Array.isArray(entry.failureMessages)
212
- ? entry.failureMessages.filter(
213
- (message): message is string => typeof message === "string",
214
- )
215
- : [];
216
- return [
217
- {
218
- identity: `${suiteName}\0${title}`,
219
- text: [title, ...diagnostics],
220
- },
221
- ];
222
- },
223
- );
224
- });
225
- if (
226
- failedAssertions.length !== report.numFailedTests ||
227
- report.success !== (report.numFailedTests === 0)
228
- )
229
- return undefined;
230
- return {
231
- total: report.numTotalTests as number,
232
- failed: report.numFailedTests as number,
233
- success: report.success,
234
- failures: failedAssertions.map((failure) => failure.identity),
235
- failedText: failedAssertions.flatMap((failure) => failure.text),
236
- };
237
- }
238
-
239
- function normalizedFailureIdentities(input: {
240
- step: AtomicVerificationContract;
241
- report?: ReturnType<typeof vitestReport>;
242
- output: string;
243
- exitCode: number;
244
- }): string[] {
245
- const vitestFailures = input.report?.failures ?? [];
246
- if (vitestFailures.length > 0) {
247
- return [...new Set(vitestFailures)]
248
- .sort()
249
- .map((failure) => sha256(`vitest-failure\0${failure}`));
250
- }
251
- const normalizedOutput = input.output
252
- .replace(new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "gu"), "")
253
- .replace(/\r\n?/gu, "\n")
254
- .replace(/\b\d+(?:\.\d+)?(?:ms|s)\b/gu, "<duration>")
255
- .replace(/\b\d{4}-\d{2}-\d{2}T[\d:.]+Z\b/gu, "<timestamp>");
256
- return [
257
- sha256(
258
- canonicalJson({
259
- obligation:
260
- input.step.kind === "package-script"
261
- ? {
262
- kind: "package-script",
263
- packageManager: input.step.packageManager,
264
- script: input.step.script,
265
- command: input.step.command,
266
- args: input.step.args,
267
- }
268
- : {
269
- kind: input.step.kind,
270
- runner: input.step.runner,
271
- args: input.step.args,
272
- },
273
- exitCode: input.exitCode,
274
- output: normalizedOutput,
275
- }),
276
- ),
277
- ];
278
- }
279
-
280
- export const VERIFICATION_REPORT_LIMIT = 64 * 1024 * 1024;
281
-
282
- function readReport(root: string, relative: string, maximum: number): string {
283
- if (observeSafePath(root, relative).kind !== "file")
284
- throw new Error("verification-report-unavailable");
285
- const descriptor = openSync(
286
- path.join(root, relative),
287
- constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,
288
- );
289
- try {
290
- const stat = fstatSync(descriptor);
291
- if (!stat.isFile()) throw new Error("verification-report-unavailable");
292
- if (stat.size > maximum) throw new Error("verification-report-too-large");
293
- const bytes = Buffer.alloc(stat.size + 1);
294
- let offset = 0;
295
- while (offset < bytes.length) {
296
- const count = readSync(
297
- descriptor,
298
- bytes,
299
- offset,
300
- bytes.length - offset,
301
- null,
302
- );
303
- if (count === 0) break;
304
- offset += count;
305
- }
306
- if (offset !== stat.size) throw new Error("verification-report-invalid");
307
- return bytes.subarray(0, offset).toString("utf8");
308
- } finally {
309
- closeSync(descriptor);
310
- }
311
- }
312
-
313
- export async function executePackageVerification(input: {
314
- root: string;
315
- dependencyOwner: string;
316
- executionOwnerRoot?: string;
317
- verification: StructuredVerificationContract;
318
- signal: AbortSignal;
319
- maxReportBytes?: number;
320
- executionWritePaths?: readonly string[];
321
- }): Promise<VerificationObservation> {
322
- let executionDiagnostic:
323
- | import("./contracts.ts").VerificationFailureSummary
324
- | undefined;
325
- const unavailable = (
326
- code: string,
327
- category: "environment" | "adapter" | "resource" = "adapter",
328
- inputObservation?: VerificationInputObservation,
329
- ): VerificationObservation => ({
330
- kind: "unavailable",
331
- category,
332
- code,
333
- verificationId: input.verification.id,
334
- ...(inputObservation ? { inputObservation } : {}),
335
- ...(executionDiagnostic
336
- ? {
337
- diagnostic: {
338
- ...executionDiagnostic,
339
- code,
340
- nextStep:
341
- "Repair the runner, environment or report adapter; do not treat missing evidence as a product failure.",
342
- },
343
- }
344
- : {}),
345
- });
346
- if (input.signal.aborted) return { kind: "cancelled" };
347
- const maxReportBytes = input.maxReportBytes ?? VERIFICATION_REPORT_LIMIT;
348
- if (!Number.isSafeInteger(maxReportBytes) || maxReportBytes < 1)
349
- return unavailable("verification-report-limit-invalid", "resource");
350
- const capability = bindCurrentVerificationCapability(
351
- input.root,
352
- input.verification,
353
- {
354
- dependencyOwner: input.dependencyOwner,
355
- executionWritePaths: input.executionWritePaths,
356
- },
357
- );
358
- if (!capability.ok)
359
- return unavailable(
360
- capability.diagnostic.code,
361
- "adapter",
362
- capability.diagnostic.kind === "verification-adapter"
363
- ? capability.diagnostic.inputObservation
364
- : undefined,
365
- );
366
- let environment: Awaited<ReturnType<typeof prepareVerificationEnvironment>>;
367
- try {
368
- environment = await prepareVerificationEnvironment(
369
- input.root,
370
- input.dependencyOwner,
371
- capability.value.runnerBindings,
372
- input.signal,
373
- );
374
- } catch (error) {
375
- if (input.signal.aborted) return { kind: "cancelled" };
376
- const code =
377
- error instanceof Error &&
378
- [
379
- "workspace-dependency-missing",
380
- "dependency-path-unsafe",
381
- "execution-mode-invalid",
382
- "windows-job-helper-path-invalid",
383
- "verification-timeout-invalid",
384
- "verification-environment-names-invalid",
385
- "verification-environment-requires-trusted-mode",
386
- ].includes(error.message)
387
- ? error.message
388
- : "verification-environment-unavailable";
389
- return unavailable(code, "environment");
390
- }
391
- let retained = false;
392
- try {
393
- const profile = executionProfile();
394
- const isolation =
395
- profile.mode === "host-trusted"
396
- ? new WindowsJobBackend({
397
- helperPath: profile.windowsHelperPath ?? "",
398
- timeoutMs: profile.timeoutMs,
399
- })
400
- : new BubblewrapIsolationBackend({
401
- bwrapPath: profile.bwrapPath,
402
- timeoutMs: profile.timeoutMs,
403
- localTrusted: profile.mode === "local-trusted",
404
- });
405
- let final: VerificationObservation | undefined;
406
- let sequence = 0;
407
- for (const step of verificationSteps(input.verification)) {
408
- const relative = `reports/${sequence++}.json`;
409
- const invocation = verificationInvocation(
410
- step,
411
- environment.bindings,
412
- `${environment.reportRoot}/${relative}`,
413
- );
414
- if (!invocation) return unavailable("runner-missing");
415
- if (profile.mode !== "isolated") {
416
- const translate = (value: string) =>
417
- value.startsWith("/workspace/")
418
- ? path.join(input.root, value.slice(11))
419
- : value;
420
- invocation.executable = translate(invocation.executable);
421
- invocation.args = invocation.args.map(translate);
422
- }
423
- const lease =
424
- profile.mode === "host-trusted"
425
- ? retainExecution(
426
- input.executionOwnerRoot ?? path.dirname(input.root),
427
- [input.root, environment.privateRoot],
428
- )
429
- : undefined;
430
- let executed: Awaited<ReturnType<typeof isolation.run>>;
431
- try {
432
- executed = await isolation.run({
433
- root: input.root,
434
- ...invocation,
435
- mounts: profile.mode === "host-trusted" ? [] : environment.mounts,
436
- environment: environment.environment,
437
- ...(step.kind !== "vitest" && step.classification === "expected-red"
438
- ? { outputWitness: step.expectedFailure }
439
- : {}),
440
- signal: input.signal,
441
- });
442
- if (
443
- !executed.ok &&
444
- executed.code === "isolation-termination-unconfirmed"
445
- ) {
446
- retained = true;
447
- lease?.uncertain();
448
- } else lease?.settled();
449
- } catch (error) {
450
- retained = !!lease;
451
- lease?.uncertain();
452
- throw error;
453
- }
454
- if (!executed.ok) {
455
- if (executed.state === "cancelled") return { kind: "cancelled" };
456
- return unavailable(
457
- executed.code,
458
- executed.code === "isolation-execution-timeout"
459
- ? "resource"
460
- : "environment",
461
- );
462
- }
463
- executionDiagnostic = {
464
- verificationId: step.id,
465
- code: "verification-rejected",
466
- exitCode: executed.exitCode,
467
- failures: [],
468
- stdout: diagnosticText(executed.stdout),
469
- stderr: diagnosticText(executed.stderr),
470
- truncated:
471
- executed.logs.stdout.truncated ||
472
- executed.logs.stderr.truncated ||
473
- executed.stdout.length > 4096 ||
474
- executed.stderr.length > 4096,
475
- nextStep: "Inspect the reported verification failure.",
476
- };
477
- let report: ReturnType<typeof vitestReport>;
478
- if (step.kind === "vitest") {
479
- try {
480
- report = vitestReport(
481
- readReport(environment.privateRoot, relative, maxReportBytes),
482
- );
483
- } catch (error) {
484
- const large =
485
- error instanceof Error &&
486
- error.message === "verification-report-too-large";
487
- return unavailable(
488
- large
489
- ? "verification-report-too-large"
490
- : "verification-report-unavailable",
491
- large ? "resource" : "adapter",
492
- );
493
- }
494
- if (!report || (executed.exitCode === 0) !== report.success)
495
- return unavailable("verification-report-invalid");
496
- }
497
- // A shell could not start its program; this is not evidence about the product.
498
- if ([126, 127].includes(executed.exitCode))
499
- return unavailable("verification-runner-launch-failed", "environment");
500
- if (!isVerificationCapabilityCurrent(input.root, capability.value))
501
- return unavailable("verification-input-unavailable");
502
- const output = `${executed.stdout}\n${executed.stderr}`;
503
- const identity =
504
- step.classification !== "expected-red" ||
505
- (step.kind === "vitest"
506
- ? report?.failedText.some((text) =>
507
- text.includes(step.expectedFailure ?? ""),
508
- ) === true
509
- : executed.outputWitnessMatched === true);
510
- const accepted =
511
- step.classification === "expected-red"
512
- ? executed.exitCode !== 0 &&
513
- identity &&
514
- (step.kind !== "vitest" ||
515
- (report !== undefined &&
516
- report.failed > 0 &&
517
- report.total >= step.minTests))
518
- : executed.exitCode === 0 &&
519
- (step.kind !== "vitest" ||
520
- (report?.success === true && report.total >= step.minTests));
521
- const evidence = {
522
- id: step.id,
523
- exitCode: executed.exitCode,
524
- classification: step.classification,
525
- policy: "report-file-v3" as const,
526
- ...(report ? { tests: report.total } : {}),
527
- attributionReliable: step.kind === "vitest",
528
- failureIdentities: accepted
529
- ? []
530
- : normalizedFailureIdentities({
531
- step,
532
- report,
533
- output,
534
- exitCode: executed.exitCode,
535
- }),
536
- };
537
- if (!accepted)
538
- return {
539
- kind: "rejected",
540
- code:
541
- step.classification === "expected-red" && executed.exitCode === 0
542
- ? "red-not-witnessed"
543
- : "verification-rejected",
544
- evidence,
545
- diagnostic: {
546
- verificationId: step.id,
547
- code: "verification-rejected",
548
- exitCode: executed.exitCode,
549
- failures: (report?.failedText ?? [])
550
- .slice(0, 16)
551
- .map((text) => diagnosticText(text, 1024)),
552
- stdout: diagnosticText(executed.stdout),
553
- stderr: diagnosticText(executed.stderr),
554
- truncated:
555
- executed.logs.stdout.truncated ||
556
- executed.logs.stderr.truncated ||
557
- executed.stdout.length > 4096 ||
558
- executed.stderr.length > 4096,
559
- nextStep:
560
- step.classification === "expected-red"
561
- ? "Make the approved regression fail for the expected assertion, not an environment error."
562
- : "Fix the reported failure in the candidate; preserve the accepted verification contract.",
563
- },
564
- };
565
- final = { kind: "accepted", evidence };
566
- }
567
- return final ?? unavailable("verification-contract-unsupported");
568
- } finally {
569
- if (!retained) await environment.cleanup();
570
- }
571
- }
572
-
573
- /** Compatibility at the execution service boundary, without guessing from error strings. */
574
- export function phaseVerificationResult(result: VerificationObservation) {
575
- if (result.kind === "cancelled")
576
- throw new DOMException("cancelled", "AbortError");
577
- if (result.kind === "accepted")
578
- return {
579
- ok: true as const,
580
- exitCode: result.evidence.exitCode,
581
- classification: result.evidence.classification,
582
- diagnostic: { kind: "assertion" as const, id: result.evidence.id },
583
- };
584
- if (result.kind === "rejected")
585
- return {
586
- ok: false as const,
587
- kind: "retryable" as const,
588
- code: result.code,
589
- failureIdentities: result.evidence.failureIdentities,
590
- attributionReliable: result.evidence.attributionReliable,
591
- };
592
- return {
593
- ok: false as const,
594
- kind: "paused" as const,
595
- code: result.code,
596
- category: result.category,
597
- ...(result.inputObservation
598
- ? { inputObservation: result.inputObservation }
599
- : {}),
600
- };
601
- }
602
-
603
- export function changeVerificationResult(result: VerificationObservation) {
604
- if (result.kind === "accepted")
605
- return {
606
- ok: true as const,
607
- exitCode: 0 as const,
608
- classification: result.evidence.classification,
609
- };
610
- if (result.kind === "cancelled")
611
- return {
612
- ok: false as const,
613
- kind: "cancelled" as const,
614
- code: "cancelled",
615
- };
616
- if (result.kind === "rejected")
617
- return {
618
- ok: false as const,
619
- kind: "verification" as const,
620
- code: result.code,
621
- failureIdentities: result.evidence.failureIdentities,
622
- attributionReliable: result.evidence.attributionReliable,
623
- };
624
- return {
625
- ok: false as const,
626
- kind:
627
- result.category === "adapter"
628
- ? ("verification-adapter" as const)
629
- : ("environment" as const),
630
- code: result.code,
631
- ...(result.inputObservation
632
- ? { inputObservation: result.inputObservation }
633
- : {}),
634
- };
635
- }