@abelxiaoxing/cadence 1.4.0 → 1.5.0

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 (66) hide show
  1. package/README.md +130 -8
  2. package/agents/design-explorer.md +17 -11
  3. package/agents/diagnosis-worker.md +9 -1
  4. package/agents/implementation-worker.md +3 -1
  5. package/config/plan-draft.example.json +122 -0
  6. package/config/plan-draft.multiple-tasks.example.json +345 -0
  7. package/config/plan-draft.quick.example.json +78 -0
  8. package/package.json +10 -4
  9. package/prompts/abel-design.md +101 -44
  10. package/prompts/abel-implement.md +9 -0
  11. package/src/activity-contracts.ts +82 -0
  12. package/src/candidate-artifact.ts +143 -0
  13. package/src/candidate-patch.ts +31 -11
  14. package/src/candidate-workspace.ts +74 -0
  15. package/src/change-contract-schema.ts +191 -0
  16. package/src/change-contract.ts +5 -0
  17. package/src/change-verification.ts +920 -0
  18. package/src/child-budget.ts +58 -0
  19. package/src/child-model.ts +142 -0
  20. package/src/child-session.ts +289 -326
  21. package/src/contracts.ts +200 -76
  22. package/src/delivery-compiler.ts +105 -120
  23. package/src/delivery-revision.ts +42 -0
  24. package/src/design-control.ts +113 -4
  25. package/src/design-diagnostics.ts +150 -0
  26. package/src/durable-contracts.ts +213 -0
  27. package/src/durable-workflow.ts +148 -3570
  28. package/src/evidence-draft.ts +122 -0
  29. package/src/execution-profile.ts +38 -0
  30. package/src/implement-graph.ts +3 -0
  31. package/src/implement-plan.ts +70 -0
  32. package/src/index.ts +59 -522
  33. package/src/isolation-backend.ts +62 -40
  34. package/src/model-source.ts +22 -0
  35. package/src/operator-cli-entry.mjs +24 -0
  36. package/src/operator-cli.mjs +1421 -0
  37. package/src/operator-tools.ts +249 -0
  38. package/src/package-candidate.ts +227 -0
  39. package/src/package-verification.ts +86 -8
  40. package/src/package-workflow.ts +291 -0
  41. package/src/packet-runtime.ts +27 -48
  42. package/src/parent-provider.ts +86 -198
  43. package/src/phase-execution.ts +2248 -0
  44. package/src/pi-adapter.ts +19 -0
  45. package/src/plan-draft-summary.ts +149 -0
  46. package/src/plan-draft.ts +493 -0
  47. package/src/single-task-draft.ts +142 -0
  48. package/src/subagent-activity.ts +32 -66
  49. package/src/submit-tool.ts +20 -59
  50. package/src/transport-budget.ts +52 -0
  51. package/src/verification-capability.ts +5 -3
  52. package/src/verification-diagnostics.ts +76 -0
  53. package/src/verification-environment-io.ts +280 -0
  54. package/src/verification-environment.ts +56 -154
  55. package/src/verification-scan.ts +64 -0
  56. package/src/worker-broker.ts +39 -57
  57. package/src/workflow-policy.ts +14 -53
  58. package/src/workflow-recovery-policy.ts +95 -0
  59. package/src/workflow-scheduling.ts +105 -0
  60. package/src/workflow-state-machine.ts +105 -497
  61. package/src/workflow-status.ts +384 -0
  62. package/src/workspace-io-entry.mjs +19 -1
  63. package/src/workspace-io-worker.mjs +275 -50
  64. package/src/workspace-io.ts +6 -1
  65. package/src/empty-resource-loader.ts +0 -38
  66. package/src/parent-payload-bridge.ts +0 -523
@@ -0,0 +1,1421 @@
1
+ // Generated by scripts/build-workspace-io.mjs; edit operator-cli-entry.mjs and its source modules.
2
+ // src/operator-cli-entry.mjs
3
+ import path6 from "node:path";
4
+
5
+ // src/operator-tools.ts
6
+ import { spawnSync } from "node:child_process";
7
+ import { lstatSync as lstatSync6, readdirSync as readdirSync4, readFileSync as readFileSync4, realpathSync as realpathSync4 } from "node:fs";
8
+ import path5 from "node:path";
9
+ import { DatabaseSync } from "node:sqlite";
10
+
11
+ // src/execution-profile.ts
12
+ function executionProfile(env = process.env) {
13
+ const mode = env.ABEL_EXECUTION_MODE ?? "isolated";
14
+ if (mode !== "isolated" && mode !== "local-trusted")
15
+ throw new Error("execution-mode-invalid");
16
+ const timeoutMs = Number(env.ABEL_VERIFICATION_TIMEOUT_MS ?? 600000);
17
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 86400000)
18
+ throw new Error("verification-timeout-invalid");
19
+ const inheritEnvironment = (env.ABEL_VERIFICATION_ENV ?? "").split(",").map((name) => name.trim()).filter(Boolean);
20
+ if (inheritEnvironment.some((name) => !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)))
21
+ throw new Error("verification-environment-names-invalid");
22
+ if (mode === "isolated" && inheritEnvironment.length)
23
+ throw new Error("verification-environment-requires-trusted-mode");
24
+ return {
25
+ mode,
26
+ timeoutMs,
27
+ bwrapPath: env.ABEL_BWRAP_PATH ?? "/usr/bin/bwrap",
28
+ inheritEnvironment
29
+ };
30
+ }
31
+
32
+ // src/openspec-cli.ts
33
+ import { lstatSync, readdirSync, readFileSync, realpathSync } from "node:fs";
34
+ import path from "node:path";
35
+ var PACKAGE_NAME = "@fission-ai/openspec";
36
+ var OPENSPEC_LIMITS = Object.freeze({
37
+ timeoutMs: 30000,
38
+ maxBuffer: 4 * 1024 * 1024
39
+ });
40
+
41
+ class OpenSpecCliError extends Error {
42
+ diagnostic;
43
+ constructor(command, phase, reason, detail = {}) {
44
+ super("design-openspec-unavailable");
45
+ this.name = "OpenSpecCliError";
46
+ this.diagnostic = Object.freeze({
47
+ code: "design-openspec-unavailable",
48
+ command,
49
+ phase,
50
+ reason,
51
+ ...["ENOENT", "EINVAL", "EACCES", "EPERM", "ENOEXEC", "E2BIG"].includes(detail.systemCode ?? "") ? { systemCode: detail.systemCode } : {},
52
+ ...Number.isSafeInteger(detail.exitCode) && (detail.exitCode ?? -1) >= 0 ? { exitCode: String(detail.exitCode) } : {}
53
+ });
54
+ }
55
+ }
56
+ function record(value) {
57
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
58
+ }
59
+ function inside(root, target) {
60
+ const relative = path.relative(root, target);
61
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
62
+ }
63
+ function envValue(environment, name) {
64
+ const key = Object.keys(environment).sort().find((candidate) => process.platform === "win32" ? candidate.toUpperCase() === name.toUpperCase() : candidate === name);
65
+ return key === undefined ? undefined : environment[key];
66
+ }
67
+ function packageEntry(root) {
68
+ const canonicalRoot = realpathSync(root);
69
+ const manifestPath = realpathSync(path.join(canonicalRoot, "package.json"));
70
+ const manifestStat = lstatSync(manifestPath);
71
+ if (!inside(canonicalRoot, manifestPath) || !manifestStat.isFile() || manifestStat.size > 1024 * 1024)
72
+ throw new Error("manifest-limit");
73
+ const manifest = record(JSON.parse(readFileSync(manifestPath, "utf8")));
74
+ const bin = typeof manifest?.bin === "string" ? manifest.bin : record(manifest?.bin)?.openspec;
75
+ if (manifest?.name !== PACKAGE_NAME || typeof bin !== "string" || path.isAbsolute(bin))
76
+ throw new Error("manifest-invalid");
77
+ const entry = realpathSync(path.resolve(canonicalRoot, bin));
78
+ if (!inside(canonicalRoot, entry) || !/\.(?:cjs|mjs|js)$/iu.test(entry) || !lstatSync(entry).isFile())
79
+ throw new Error("entry-invalid");
80
+ return entry;
81
+ }
82
+ function canonicalConsumerRoot(consumerRoot) {
83
+ try {
84
+ const root = realpathSync(consumerRoot);
85
+ if (!lstatSync(root).isDirectory())
86
+ throw new Error("cwd-invalid");
87
+ return root;
88
+ } catch (error) {
89
+ throw new OpenSpecCliError("resolve", "resolution", "cwd-unavailable", {
90
+ systemCode: error.code
91
+ });
92
+ }
93
+ }
94
+ function commandIn(directory) {
95
+ const names = process.platform === "win32" ? ["openspec.exe", "openspec.cmd", "openspec"] : ["openspec"];
96
+ const entries = process.platform === "win32" ? readdirSync(directory) : names;
97
+ for (const name of names) {
98
+ const matches = entries.filter((entry) => entry.toLowerCase() === name);
99
+ if (matches.length > 1)
100
+ throw new Error("ambiguous-command");
101
+ if (matches.length === 1) {
102
+ const candidate = path.join(directory, matches[0]);
103
+ if (lstatSync(candidate, { throwIfNoEntry: false }))
104
+ return candidate;
105
+ }
106
+ }
107
+ return;
108
+ }
109
+ function resolveOpenSpecInvocation(consumerRoot, environment = process.env) {
110
+ const configuredRoot = envValue(environment, "ABEL_OPENSPEC_PACKAGE_ROOT");
111
+ const configuredNode = envValue(environment, "ABEL_OPENSPEC_NODE");
112
+ const node = configuredNode ?? (process.release.name === "node" && !process.versions.bun ? process.execPath : undefined);
113
+ let executable;
114
+ try {
115
+ if (!node || !path.isAbsolute(node) || /\.(?:cmd|bat|ps1)$/iu.test(node)) {
116
+ throw new Error("runtime-invalid");
117
+ }
118
+ executable = realpathSync(node);
119
+ if (!lstatSync(executable).isFile())
120
+ throw new Error("runtime-invalid");
121
+ } catch {
122
+ throw new OpenSpecCliError("resolve", "resolution", "runtime-unavailable");
123
+ }
124
+ if (configuredRoot !== undefined) {
125
+ try {
126
+ if (!path.isAbsolute(configuredRoot))
127
+ throw new Error("root-invalid");
128
+ return { executable, entry: packageEntry(configuredRoot) };
129
+ } catch {
130
+ throw new OpenSpecCliError("resolve", "resolution", "installation-invalid");
131
+ }
132
+ }
133
+ const consumer = canonicalConsumerRoot(consumerRoot);
134
+ const directories = (envValue(environment, "PATH") ?? "").split(path.delimiter);
135
+ for (const directory of directories) {
136
+ if (!path.isAbsolute(directory))
137
+ continue;
138
+ let command;
139
+ let canonicalDirectory;
140
+ try {
141
+ canonicalDirectory = realpathSync(directory);
142
+ if (inside(consumer, canonicalDirectory))
143
+ continue;
144
+ command = commandIn(canonicalDirectory);
145
+ } catch {
146
+ continue;
147
+ }
148
+ if (!command)
149
+ continue;
150
+ try {
151
+ const target = realpathSync(command);
152
+ if (inside(consumer, target)) {
153
+ throw new OpenSpecCliError("resolve", "resolution", "unsafe-installation");
154
+ }
155
+ const layoutRoots = [
156
+ path.join(canonicalDirectory, "node_modules", PACKAGE_NAME),
157
+ path.resolve(canonicalDirectory, "../lib/node_modules", PACKAGE_NAME)
158
+ ];
159
+ const roots = [];
160
+ let ancestor = path.dirname(target);
161
+ for (let depth = 0;depth < 8; depth++) {
162
+ roots.push(ancestor);
163
+ const parent = path.dirname(ancestor);
164
+ if (parent === ancestor)
165
+ break;
166
+ ancestor = parent;
167
+ }
168
+ const linked = lstatSync(command).isSymbolicLink();
169
+ const candidates = linked ? roots : layoutRoots;
170
+ for (const root of candidates) {
171
+ let entry;
172
+ try {
173
+ entry = packageEntry(root);
174
+ if (linked && entry !== target)
175
+ continue;
176
+ } catch {
177
+ continue;
178
+ }
179
+ if (inside(consumer, entry)) {
180
+ throw new OpenSpecCliError("resolve", "resolution", "unsafe-installation");
181
+ }
182
+ return { executable, entry };
183
+ }
184
+ } catch (error) {
185
+ if (error instanceof OpenSpecCliError)
186
+ throw error;
187
+ }
188
+ throw new OpenSpecCliError("resolve", "resolution", "installation-invalid");
189
+ }
190
+ throw new OpenSpecCliError("resolve", "resolution", "installation-not-found");
191
+ }
192
+
193
+ // src/state-root.ts
194
+ import { createHash } from "node:crypto";
195
+ import { chmodSync, lstatSync as lstatSync2, mkdirSync, realpathSync as realpathSync2 } from "node:fs";
196
+ import os from "node:os";
197
+ import path2 from "node:path";
198
+ class StateRootError extends Error {
199
+ code;
200
+ constructor(code) {
201
+ super(code);
202
+ this.name = "StateRootError";
203
+ this.code = code;
204
+ }
205
+ }
206
+ function isContainedBy(parent, candidate) {
207
+ const relative = path2.relative(parent, candidate);
208
+ return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
209
+ }
210
+ function inspectExistingComponents(absolutePath) {
211
+ const parsed = path2.parse(absolutePath);
212
+ const relativeParts = absolutePath.slice(parsed.root.length).split(path2.sep).filter(Boolean);
213
+ let current = parsed.root;
214
+ for (const part of relativeParts) {
215
+ current = path2.join(current, part);
216
+ let stat;
217
+ try {
218
+ stat = lstatSync2(current);
219
+ } catch (error) {
220
+ if (error.code === "ENOENT")
221
+ return;
222
+ throw error;
223
+ }
224
+ if (stat.isSymbolicLink()) {
225
+ throw new StateRootError("state-component-symlink");
226
+ }
227
+ if (!stat.isDirectory() && current !== absolutePath) {
228
+ throw new StateRootError("state-component-type");
229
+ }
230
+ }
231
+ }
232
+ function canonicalFuturePath(input) {
233
+ const absolute = path2.resolve(input);
234
+ inspectExistingComponents(absolute);
235
+ let cursor = absolute;
236
+ const missing = [];
237
+ for (;; ) {
238
+ try {
239
+ return path2.join(realpathSync2.native(cursor), ...missing.reverse());
240
+ } catch (error) {
241
+ if (error.code !== "ENOENT")
242
+ throw error;
243
+ const parent = path2.dirname(cursor);
244
+ if (parent === cursor)
245
+ throw error;
246
+ missing.push(path2.basename(cursor));
247
+ cursor = parent;
248
+ }
249
+ }
250
+ }
251
+ function requireAbsoluteDirectoryBase(xdgStateHome, homeDir) {
252
+ if (xdgStateHome && path2.isAbsolute(xdgStateHome)) {
253
+ return canonicalFuturePath(xdgStateHome);
254
+ }
255
+ if (!path2.isAbsolute(homeDir)) {
256
+ throw new StateRootError("invalid-state-base");
257
+ }
258
+ return canonicalFuturePath(path2.join(homeDir, ".local", "state"));
259
+ }
260
+ function resolveStateRoot(options) {
261
+ let consumerRoot;
262
+ try {
263
+ consumerRoot = realpathSync2.native(path2.resolve(options.consumerRoot));
264
+ if (!lstatSync2(consumerRoot).isDirectory()) {
265
+ throw new StateRootError("consumer-root-unavailable");
266
+ }
267
+ } catch (error) {
268
+ if (error instanceof StateRootError)
269
+ throw error;
270
+ throw new StateRootError("consumer-root-unavailable");
271
+ }
272
+ const stateBase = requireAbsoluteDirectoryBase(options.xdgStateHome, options.homeDir ?? os.homedir());
273
+ const consumerRootHash = createHash("sha256").update(consumerRoot).digest("hex");
274
+ const productRoot = canonicalFuturePath(path2.join(stateBase, "abel-cadence"));
275
+ const rootsDir = canonicalFuturePath(path2.join(productRoot, "roots"));
276
+ const rootDir = canonicalFuturePath(path2.join(rootsDir, consumerRootHash));
277
+ if (isContainedBy(consumerRoot, rootDir)) {
278
+ throw new StateRootError("state-root-inside-consumer");
279
+ }
280
+ return {
281
+ consumerRoot,
282
+ consumerRootHash,
283
+ stateBase,
284
+ productRoot,
285
+ rootsDir,
286
+ rootDir,
287
+ databasePath: path2.join(rootDir, "control.sqlite3"),
288
+ artifactsDir: path2.join(rootDir, "artifacts"),
289
+ workspacesDir: path2.join(rootDir, "workspaces"),
290
+ transactionsDir: path2.join(rootDir, "transactions")
291
+ };
292
+ }
293
+
294
+ // src/transport-budget.ts
295
+ var REQUEST_BOUNDS = Object.freeze({
296
+ firstProgressMs: 90000,
297
+ streamIdleMs: 180000,
298
+ cancellationDrainMs: 250
299
+ });
300
+ function requestBounds(env = process.env) {
301
+ const read = (name, fallback) => {
302
+ const value = Number(env[name] ?? fallback);
303
+ if (!Number.isSafeInteger(value) || value < 1 || value > 1200000)
304
+ throw new Error("request-budget-invalid");
305
+ return value;
306
+ };
307
+ return {
308
+ ...REQUEST_BOUNDS,
309
+ firstProgressMs: read("ABEL_FIRST_PROGRESS_MS", REQUEST_BOUNDS.firstProgressMs),
310
+ streamIdleMs: read("ABEL_STREAM_IDLE_MS", REQUEST_BOUNDS.streamIdleMs)
311
+ };
312
+ }
313
+
314
+ // src/verification-capability.ts
315
+ import {
316
+ lstatSync as lstatSync5,
317
+ readdirSync as readdirSync3,
318
+ readFileSync as readFileSync3,
319
+ realpathSync as realpathSync3
320
+ } from "node:fs";
321
+ import path4 from "node:path";
322
+
323
+ // src/control-contracts.ts
324
+ var CONTROL_SCHEMA_PROPERTIES = {
325
+ command: {
326
+ type: "string",
327
+ enum: ["start", "status", "resume", "rebind", "cancel", "discard"]
328
+ },
329
+ stage: { type: "string", enum: ["abel-implement"] },
330
+ change: { type: "string" },
331
+ operationId: { type: "string" },
332
+ deliveryRevision: { type: "integer", minimum: 1 },
333
+ receiptHash: { type: "string" },
334
+ routeId: { type: "string" },
335
+ recovery: {
336
+ type: "object",
337
+ additionalProperties: false,
338
+ properties: {
339
+ incidentKey: { type: "string", pattern: "^[a-f0-9]{64}$" },
340
+ failureSequence: { type: "integer", minimum: 1 },
341
+ reason: {
342
+ type: "string",
343
+ enum: ["parent-directed-retry", "route-changed", "context-extended"]
344
+ }
345
+ },
346
+ required: ["incidentKey", "failureSequence", "reason"]
347
+ }
348
+ };
349
+ var commandSchema = (command, fields) => ({
350
+ type: "object",
351
+ properties: {
352
+ command: { type: "string", enum: [command] },
353
+ ...Object.fromEntries(fields.map((field) => [field, CONTROL_SCHEMA_PROPERTIES[field]]))
354
+ },
355
+ required: ["command", ...fields],
356
+ additionalProperties: false
357
+ });
358
+ var CONTROL_COMMAND_PARAMETERS = {
359
+ type: "object",
360
+ properties: CONTROL_SCHEMA_PROPERTIES,
361
+ required: ["command", "stage", "change"],
362
+ anyOf: [
363
+ commandSchema("start", ["stage", "change", "operationId"]),
364
+ commandSchema("status", ["stage", "change"]),
365
+ commandSchema("resume", ["stage", "change", "operationId"]),
366
+ commandSchema("resume", ["stage", "change", "operationId", "recovery"]),
367
+ commandSchema("resume", [
368
+ "stage",
369
+ "change",
370
+ "operationId",
371
+ "deliveryRevision",
372
+ "receiptHash",
373
+ "recovery"
374
+ ]),
375
+ commandSchema("resume", [
376
+ "stage",
377
+ "change",
378
+ "operationId",
379
+ "deliveryRevision",
380
+ "receiptHash"
381
+ ]),
382
+ commandSchema("rebind", ["stage", "change", "operationId", "routeId"]),
383
+ commandSchema("cancel", ["stage", "change", "operationId"]),
384
+ commandSchema("discard", ["stage", "change", "operationId"])
385
+ ],
386
+ additionalProperties: false
387
+ };
388
+ var CONTROL_TOOL_FIELDS = new Set([
389
+ "command",
390
+ "stage",
391
+ "change",
392
+ "operationId",
393
+ "deliveryRevision",
394
+ "receiptHash",
395
+ "routeId",
396
+ "recovery"
397
+ ]);
398
+ var COMMAND_FIELDS = Object.freeze({
399
+ start: new Set(["command", "stage", "change", "operationId"]),
400
+ status: new Set(["command", "stage", "change"]),
401
+ resume: new Set([
402
+ "command",
403
+ "stage",
404
+ "change",
405
+ "operationId",
406
+ "deliveryRevision",
407
+ "receiptHash",
408
+ "recovery"
409
+ ]),
410
+ rebind: new Set(["command", "stage", "change", "operationId", "routeId"]),
411
+ cancel: new Set(["command", "stage", "change", "operationId"]),
412
+ discard: new Set(["command", "stage", "change", "operationId"])
413
+ });
414
+ // src/contracts.ts
415
+ var LIMITS = {
416
+ maxActiveChildSessions: 4,
417
+ maxEnvelopeBytes: 64 * 1024,
418
+ phaseTimeoutMs: 20 * 60 * 1000,
419
+ maxCompleteResultBytes: 64 * 1024
420
+ };
421
+ var VERIFICATION_LIMITS = Object.freeze({
422
+ minSteps: 1,
423
+ maxSteps: 8,
424
+ minTestFiles: 1,
425
+ maxTestFiles: 64
426
+ });
427
+ var NONCANONICAL = /(^|\/)\.\.(\/|$)|(^|\/)\/|^\//;
428
+ var RELATIVE_PATH_PATTERN = String.raw`^(?:\.|(?!/)(?![a-zA-Z]:/)(?!\./)(?![\s\S]*\.\.)(?![\s\S]*[\\\u0000])(?![\s\S]*//)(?![\s\S]*/\.(?:/|$))(?![\s\S]*/$)[\s\S]+)$`;
429
+ function isValidRelativePath(p) {
430
+ return typeof p === "string" && p.length > 0 && p.length <= 512 && !NONCANONICAL.test(p) && !p.startsWith("/") && !/^[a-z]:\//iu.test(p) && (p === "." || !p.startsWith("./") && !p.endsWith("/") && !p.split("/").includes(".")) && !p.includes("..") && !p.includes("\\") && !p.includes("\x00");
431
+ }
432
+ var UNSAFE_VERIFICATION_TOKEN = /[;&|`$<>\n\r\0]/u;
433
+ var VERIFICATION_NAME = /^[a-z0-9][a-z0-9._:@/-]*$/iu;
434
+ var EXECUTABLE_NAME = /^[a-z0-9][a-z0-9._-]*$/iu;
435
+ var IDENTIFIER = /^[a-z0-9](?:[a-z0-9._:-]{0,126}[a-z0-9])?$/iu;
436
+ function validVerificationToken(value) {
437
+ const optionValue = typeof value === "string" && value.includes("=") ? value.slice(value.indexOf("=") + 1) : value;
438
+ return typeof value === "string" && value.length > 0 && value.length <= 512 && value.trim() === value && !UNSAFE_VERIFICATION_TOKEN.test(value) && !value.includes("\\") && !value.startsWith("/") && !/^[a-z]:\//iu.test(value) && !/(^|\/)\.\.(\/|$)/u.test(value) && typeof optionValue === "string" && !optionValue.startsWith("/") && !/^[a-z]:\//iu.test(optionValue) && !/(^|\/)\.\.(\/|$)/u.test(optionValue);
439
+ }
440
+ function validVerificationArgs(value) {
441
+ return Array.isArray(value) && value.length <= 128 && value.every(validVerificationToken);
442
+ }
443
+ function validScriptCommand(value) {
444
+ return typeof value === "string" && value.length > 0 && value.length <= 1024 && value.trim() === value && !value.includes("\x00");
445
+ }
446
+ function validVerificationIdentity(contract) {
447
+ if (!validIdentifier(contract.id) || !["expected-red", "expected-green", "expected-refactor"].includes(String(contract.classification))) {
448
+ return false;
449
+ }
450
+ return contract.classification === "expected-red" ? typeof contract.expectedFailure === "string" && contract.expectedFailure.length > 0 && contract.expectedFailure.length <= 512 : contract.expectedFailure === undefined;
451
+ }
452
+ function validatePackageScriptRunner(value) {
453
+ if (!hasExactKeys(value, ["kind", "packageManager", "script", "command"]) || value.kind !== "package-script" || !["bun", "npm", "pnpm", "yarn"].includes(String(value.packageManager)) || typeof value.script !== "string" || !VERIFICATION_NAME.test(value.script) || value.script.includes("/") || !validScriptCommand(value.command)) {
454
+ return false;
455
+ }
456
+ return true;
457
+ }
458
+ function validateExecutableRunner(value) {
459
+ if (!value || typeof value !== "object" || Array.isArray(value))
460
+ return false;
461
+ const runner = value;
462
+ if (runner.kind === "package-script") {
463
+ return validatePackageScriptRunner(runner);
464
+ }
465
+ if (runner.kind === "local-binary" && hasExactKeys(runner, ["kind", "executable"])) {
466
+ return typeof runner.executable === "string" && EXECUTABLE_NAME.test(runner.executable);
467
+ }
468
+ return runner.kind === "npx" && hasExactKeys(runner, ["kind", "executable", "noInstall"]) && typeof runner.executable === "string" && EXECUTABLE_NAME.test(runner.executable) && runner.noInstall === true;
469
+ }
470
+ function validateVitestRunner(value) {
471
+ if (value.kind === "package-script") {
472
+ if (UNSAFE_VERIFICATION_TOKEN.test(value.command))
473
+ return false;
474
+ const tokens = value.command.split(/\s+/u);
475
+ return tokens[0] === "vitest" || tokens[0] === "npx" && tokens[1] === "--no-install" && tokens[2] === "vitest";
476
+ }
477
+ return value.executable === "vitest";
478
+ }
479
+ function validateAtomicVerification(value) {
480
+ if (!value || typeof value !== "object" || Array.isArray(value))
481
+ return false;
482
+ const contract = value;
483
+ if (contract.executionBindings !== undefined && (!contract.executionBindings || typeof contract.executionBindings !== "object" || Array.isArray(contract.executionBindings) || Object.entries(contract.executionBindings).some(([key, hash]) => !VERIFICATION_CONFIGURATION_PATHS.includes(key) || hash !== null && (typeof hash !== "string" || !/^[a-f0-9]{64}$/u.test(hash)))))
484
+ return false;
485
+ const expectedFailure = [
486
+ ...contract.classification === "expected-red" ? ["expectedFailure"] : [],
487
+ ...contract.executionBindings === undefined ? [] : ["executionBindings"]
488
+ ];
489
+ if (contract.kind === "vitest") {
490
+ const executableRunner = contract.runner;
491
+ return hasExactKeys(contract, [
492
+ "kind",
493
+ "id",
494
+ "runner",
495
+ "testFiles",
496
+ "args",
497
+ "classification",
498
+ ...expectedFailure,
499
+ "minTests"
500
+ ]) && validVerificationIdentity(contract) && validateExecutableRunner(contract.runner) && validateVitestRunner(executableRunner) && Array.isArray(contract.testFiles) && contract.testFiles.length >= VERIFICATION_LIMITS.minTestFiles && contract.testFiles.length <= VERIFICATION_LIMITS.maxTestFiles && contract.testFiles.every(isValidRelativePath) && new Set(contract.testFiles).size === contract.testFiles.length && validVerificationArgs(contract.args) && Number.isSafeInteger(contract.minTests) && contract.minTests >= 1;
501
+ }
502
+ if (contract.kind === "package-script") {
503
+ const runner2 = {
504
+ kind: "package-script",
505
+ packageManager: contract.packageManager,
506
+ script: contract.script,
507
+ command: contract.command
508
+ };
509
+ return hasExactKeys(contract, [
510
+ "kind",
511
+ "id",
512
+ "packageManager",
513
+ "script",
514
+ "command",
515
+ "args",
516
+ "classification",
517
+ ...expectedFailure
518
+ ]) && validVerificationIdentity(contract) && validatePackageScriptRunner(runner2) && validVerificationArgs(contract.args);
519
+ }
520
+ if (contract.kind !== "static-check")
521
+ return false;
522
+ const runner = contract.runner;
523
+ const validRunner = validateExecutableRunner(runner) || hasExactKeys(runner, ["kind", "script"]) && runner.kind === "node" && isValidRelativePath(runner.script);
524
+ return hasExactKeys(contract, [
525
+ "kind",
526
+ "id",
527
+ "runner",
528
+ "args",
529
+ "classification",
530
+ ...expectedFailure
531
+ ]) && validVerificationIdentity(contract) && validRunner && validVerificationArgs(contract.args);
532
+ }
533
+ function validateStructuredVerification(value) {
534
+ if (!value || typeof value !== "object" || Array.isArray(value))
535
+ return false;
536
+ const contract = value;
537
+ if (contract.kind !== "steps") {
538
+ return validateAtomicVerification(contract);
539
+ }
540
+ if (!hasExactKeys(contract, ["kind", "id", "classification", "steps"]) || !validIdentifier(contract.id) || !["expected-red", "expected-green", "expected-refactor"].includes(String(contract.classification)) || !Array.isArray(contract.steps) || contract.steps.length < VERIFICATION_LIMITS.minSteps || contract.steps.length > VERIFICATION_LIMITS.maxSteps || !contract.steps.every((step) => validateAtomicVerification(step))) {
541
+ return false;
542
+ }
543
+ const steps = contract.steps;
544
+ return steps.slice(0, -1).every((step) => step.classification === "expected-green") && steps.at(-1)?.classification === contract.classification && new Set(steps.map((step) => step.id)).size === steps.length;
545
+ }
546
+ function validateVerificationContract(value) {
547
+ if (validateStructuredVerification(value)) {
548
+ return { ok: true, value: structuredClone(value) };
549
+ }
550
+ return {
551
+ ok: false,
552
+ reason: "verification contract is unsupported by the Implement runtime"
553
+ };
554
+ }
555
+ function verificationSteps(verification) {
556
+ const normalized = validateVerificationContract(verification);
557
+ if (!normalized.ok)
558
+ return [];
559
+ return normalized.value.kind === "steps" ? structuredClone(normalized.value.steps) : [structuredClone(normalized.value)];
560
+ }
561
+ var VERIFICATION_CONFIGURATION_PATHS = [
562
+ "package.json",
563
+ "package-lock.json",
564
+ "npm-shrinkwrap.json",
565
+ "bun.lock",
566
+ "bun.lockb",
567
+ "pnpm-lock.yaml",
568
+ "yarn.lock",
569
+ ".npmrc",
570
+ ".yarnrc",
571
+ ".yarnrc.yml",
572
+ "bunfig.toml",
573
+ "pnpm-workspace.yaml"
574
+ ];
575
+ function verificationBoundInputPaths(verification) {
576
+ return [
577
+ ...new Set([
578
+ ...verificationInputPaths(verification),
579
+ ...verificationSteps(verification).flatMap((step) => step.kind === "vitest" || step.kind === "package-script" || ("runner" in step) && step.runner.kind === "package-script" ? VERIFICATION_CONFIGURATION_PATHS : [])
580
+ ])
581
+ ];
582
+ }
583
+ function verificationInputPaths(verification) {
584
+ return [
585
+ ...new Set(verificationSteps(verification).flatMap((step) => {
586
+ const paths = step.kind === "vitest" ? [...step.testFiles] : step.kind === "static-check" && step.runner.kind === "node" ? [step.runner.script] : [];
587
+ if (step.kind === "package-script" || "runner" in step && step.runner.kind === "package-script") {
588
+ paths.push("package.json");
589
+ }
590
+ return paths;
591
+ }))
592
+ ];
593
+ }
594
+ function hasExactKeys(value, required, optional = []) {
595
+ if (!value || typeof value !== "object" || Array.isArray(value))
596
+ return false;
597
+ const record2 = value;
598
+ const allowed = new Set([...required, ...optional]);
599
+ return required.every((key) => Object.hasOwn(record2, key)) && Object.keys(record2).every((key) => allowed.has(key));
600
+ }
601
+ function validIdentifier(value) {
602
+ return typeof value === "string" && IDENTIFIER.test(value);
603
+ }
604
+
605
+ // src/file-snapshot.ts
606
+ import { createHash as createHash2 } from "node:crypto";
607
+ import { lstatSync as lstatSync4, readdirSync as readdirSync2, readFileSync as readFileSync2, readlinkSync } from "node:fs";
608
+ import { join, resolve } from "node:path";
609
+
610
+ // src/safe-path.ts
611
+ import { lstatSync as lstatSync3 } from "node:fs";
612
+ import path3 from "node:path";
613
+ function observeSafePath(root, relative) {
614
+ if (!isValidRelativePath(relative)) {
615
+ return { kind: "unsafe", reason: "invalid-path" };
616
+ }
617
+ try {
618
+ const resolvedRoot = path3.resolve(root);
619
+ const rootStat = lstatSync3(resolvedRoot, { throwIfNoEntry: false });
620
+ if (!rootStat?.isDirectory() || rootStat.isSymbolicLink()) {
621
+ return { kind: "unsafe", reason: "root-unavailable" };
622
+ }
623
+ if (relative === ".")
624
+ return { kind: "directory" };
625
+ let current = resolvedRoot;
626
+ const parts = relative.split("/");
627
+ for (const [index, part] of parts.entries()) {
628
+ current = path3.join(current, part);
629
+ if (!current.startsWith(`${resolvedRoot}${path3.sep}`)) {
630
+ return { kind: "unsafe", reason: "invalid-path" };
631
+ }
632
+ const stat = lstatSync3(current, { throwIfNoEntry: false });
633
+ if (!stat)
634
+ return { kind: "absent" };
635
+ if (stat.isSymbolicLink()) {
636
+ return { kind: "unsafe", reason: "symlink" };
637
+ }
638
+ if (index < parts.length - 1) {
639
+ if (!stat.isDirectory()) {
640
+ return { kind: "unsafe", reason: "parent-not-directory" };
641
+ }
642
+ continue;
643
+ }
644
+ if (stat.isFile())
645
+ return { kind: "file" };
646
+ if (stat.isDirectory())
647
+ return { kind: "directory" };
648
+ return { kind: "unsafe", reason: "special-file" };
649
+ }
650
+ } catch {
651
+ return { kind: "unsafe", reason: "path-unavailable" };
652
+ }
653
+ return { kind: "unsafe", reason: "invalid-path" };
654
+ }
655
+ function isSafeRegularFile(root, relative) {
656
+ return observeSafePath(root, relative).kind === "file";
657
+ }
658
+
659
+ // src/file-snapshot.ts
660
+ function sha256(bytes) {
661
+ return createHash2("sha256").update(bytes).digest("hex");
662
+ }
663
+ function snapshotFile(root, relPath) {
664
+ if (observeSafePath(root, relPath).kind !== "file")
665
+ return null;
666
+ const abs = resolve(root, relPath);
667
+ const bytes = readFileSync2(abs);
668
+ return { sha256: sha256(bytes), bytes: bytes.length, kind: "file" };
669
+ }
670
+
671
+ // src/verification-capability.ts
672
+ var WINDOWS_EXECUTABLE_EXTENSIONS = new Set([".exe", ".cmd"]);
673
+ var DEFAULT_WINDOWS_PATH_EXT = ".COM;.EXE;.BAT;.CMD";
674
+ var SYSTEM_MOUNT_ROOTS = ["/usr", "/bin", "/lib", "/lib64", "/etc"];
675
+ var BROAD_MOUNT_ROOTS = new Set([
676
+ "/",
677
+ "/home",
678
+ "/root",
679
+ "/tmp",
680
+ "/var",
681
+ "/var/tmp"
682
+ ]);
683
+ function capabilitySuccess(verificationId, runnerBindings = []) {
684
+ const seen = new Set;
685
+ return {
686
+ ok: true,
687
+ verificationId,
688
+ runnerBindings: runnerBindings.filter((binding) => {
689
+ const key = `${binding.command}\x00${binding.executablePath}\x00${JSON.stringify(binding.fixedArgs ?? [])}\x00${binding.mountSource ?? ""}`;
690
+ if (seen.has(key))
691
+ return false;
692
+ seen.add(key);
693
+ return true;
694
+ }).map((binding) => ({
695
+ ...binding,
696
+ ...binding.fixedArgs ? { fixedArgs: [...binding.fixedArgs] } : {}
697
+ }))
698
+ };
699
+ }
700
+ function adapterFailure(verificationId, code, message) {
701
+ return {
702
+ ok: false,
703
+ diagnostic: { kind: "verification-adapter", code, verificationId, message }
704
+ };
705
+ }
706
+ function fileStatus(root, relative) {
707
+ const observation = observeSafePath(root, relative);
708
+ if (observation.kind === "file")
709
+ return "regular";
710
+ return observation.kind === "absent" ? "absent" : "unsafe";
711
+ }
712
+ function regularFile(root, relative) {
713
+ return fileStatus(root, relative) === "regular";
714
+ }
715
+ function localExecutable(root, executable, dependencyOwner = root, environment = {}) {
716
+ const dependencyRoot = path4.resolve(dependencyOwner, "node_modules");
717
+ try {
718
+ const canonicalDependencyRoot = realpathSync3(dependencyRoot);
719
+ for (const name of localExecutableNames(executable, environment)) {
720
+ const unresolved = resolveCandidateName(path4.resolve(dependencyRoot, ".bin"), name, environment.platform ?? process.platform);
721
+ if (!unresolved)
722
+ continue;
723
+ const canonical = realpathSync3(unresolved);
724
+ const stat = lstatSync5(canonical);
725
+ if (canonical !== canonicalDependencyRoot && pathWithin(canonicalDependencyRoot, canonical, environment.platform ?? process.platform) && regularExecutableFile(stat, environment.platform ?? process.platform)) {
726
+ return true;
727
+ }
728
+ }
729
+ return false;
730
+ } catch {
731
+ return false;
732
+ }
733
+ }
734
+ function pathApi(platform, ...values) {
735
+ if (platform !== "win32")
736
+ return path4.posix;
737
+ if (process.platform === "win32" || values.some((value) => /^[a-z]:[\\/]/iu.test(value) || value.startsWith("\\\\"))) {
738
+ return path4.win32;
739
+ }
740
+ return path4.posix;
741
+ }
742
+ function pathWithin(root, candidate, platform) {
743
+ const platformPath = pathApi(platform, root, candidate);
744
+ const normalizedRoot = platformPath.resolve(root);
745
+ const relative = platformPath.relative(normalizedRoot, platformPath.resolve(candidate));
746
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${platformPath.sep}`) && !platformPath.isAbsolute(relative);
747
+ }
748
+ function regularExecutableFile(stat, platform) {
749
+ return stat.isFile() && (platform === "win32" || (stat.mode & 73) !== 0);
750
+ }
751
+ function windowsPathExtensions(pathExt) {
752
+ const seen = new Set;
753
+ const extensions = [];
754
+ for (const entry of (pathExt ?? DEFAULT_WINDOWS_PATH_EXT).split(";")) {
755
+ const extension = entry.trim().toLowerCase();
756
+ if (!WINDOWS_EXECUTABLE_EXTENSIONS.has(extension) || seen.has(extension)) {
757
+ continue;
758
+ }
759
+ seen.add(extension);
760
+ extensions.push(extension);
761
+ }
762
+ return extensions;
763
+ }
764
+ function runnerNames(command, environment) {
765
+ if (!/^[a-z0-9][a-z0-9._-]*$/iu.test(command))
766
+ return [];
767
+ if ((environment.platform ?? process.platform) !== "win32") {
768
+ return [command];
769
+ }
770
+ const extension = path4.extname(command).toLowerCase();
771
+ if (extension) {
772
+ return WINDOWS_EXECUTABLE_EXTENSIONS.has(extension) ? [command] : [];
773
+ }
774
+ return windowsPathExtensions(environment.pathExt).map((candidateExtension) => `${command}${candidateExtension}`);
775
+ }
776
+ function localExecutableNames(executable, environment) {
777
+ if (!/^[a-z0-9][a-z0-9._-]*$/iu.test(executable))
778
+ return [];
779
+ if ((environment.platform ?? process.platform) !== "win32") {
780
+ return [executable];
781
+ }
782
+ const extension = path4.extname(executable).toLowerCase();
783
+ if (extension) {
784
+ return WINDOWS_EXECUTABLE_EXTENSIONS.has(extension) ? [executable] : [];
785
+ }
786
+ return [
787
+ executable,
788
+ ...windowsPathExtensions(environment.pathExt).map((candidateExtension) => `${executable}${candidateExtension}`)
789
+ ];
790
+ }
791
+ function resolveCandidateName(directory, name, platform) {
792
+ const exact = path4.join(directory, name);
793
+ if (platform !== "win32")
794
+ return exact;
795
+ try {
796
+ const matches = readdirSync3(directory).filter((entry) => entry.toLowerCase() === name.toLowerCase());
797
+ return matches.length === 1 ? path4.join(directory, matches[0]) : null;
798
+ } catch {
799
+ return null;
800
+ }
801
+ }
802
+ function within(root, candidate) {
803
+ return candidate === root || candidate.startsWith(`${root}${path4.sep}`);
804
+ }
805
+ function commonDirectory(left, right, platform = process.platform) {
806
+ const platformPath = pathApi(platform, left, right);
807
+ const leftResolved = platformPath.resolve(left);
808
+ const rightResolved = platformPath.resolve(right);
809
+ const leftRoot = platformPath.parse(leftResolved).root;
810
+ const rightRoot = platformPath.parse(rightResolved).root;
811
+ const comparable = (value) => platform === "win32" ? value.toLowerCase() : value;
812
+ if (comparable(leftRoot) !== comparable(rightRoot))
813
+ return leftRoot;
814
+ const parts = (value, root) => platformPath.relative(root, value).split(platformPath.sep).filter(Boolean);
815
+ const leftParts = parts(leftResolved, leftRoot);
816
+ const rightParts = parts(rightResolved, rightRoot);
817
+ const common = [];
818
+ for (let index = 0;index < Math.min(leftParts.length, rightParts.length); index++) {
819
+ const leftPart = leftParts[index];
820
+ const rightPart = rightParts[index];
821
+ if (comparable(leftPart) !== comparable(rightPart))
822
+ break;
823
+ common.push(leftPart);
824
+ }
825
+ return platformPath.join(leftRoot, ...common);
826
+ }
827
+ function unsafeMountSource(source) {
828
+ if (BROAD_MOUNT_ROOTS.has(source))
829
+ return true;
830
+ if (path4.resolve(source) === path4.parse(path4.resolve(source)).root)
831
+ return true;
832
+ const parts = path4.relative(path4.parse(path4.resolve(source)).root, path4.resolve(source)).split(path4.sep).filter(Boolean).map((part) => part.toLowerCase());
833
+ return parts[0] === "home" && parts.length <= 2 || parts[0] === "users" && parts.length <= 2 || parts[0] === "root" && parts.length <= 1;
834
+ }
835
+ function safeRunnerSource(paths, platform) {
836
+ let source = path4.dirname(paths[0]);
837
+ for (const candidate of paths.slice(1)) {
838
+ source = commonDirectory(source, path4.dirname(candidate), platform);
839
+ }
840
+ if (unsafeMountSource(source))
841
+ return null;
842
+ try {
843
+ const stat = lstatSync5(source);
844
+ if (!stat.isDirectory() || stat.isSymbolicLink())
845
+ return null;
846
+ } catch {
847
+ return null;
848
+ }
849
+ return paths.every((candidate) => pathWithin(source, candidate, platform)) ? source : null;
850
+ }
851
+ function resolvedRunnerEnvironment(environment) {
852
+ return {
853
+ platform: environment.platform ?? process.platform,
854
+ path: environment.path ?? process.env.PATH ?? "",
855
+ pathExt: environment.pathExt ?? process.env.PATHEXT ?? DEFAULT_WINDOWS_PATH_EXT,
856
+ pathDelimiter: environment.pathDelimiter ?? path4.delimiter
857
+ };
858
+ }
859
+ function windowsShimBinding(command, launcherPath, environment) {
860
+ const name = path4.basename(command, path4.extname(command)).toLowerCase();
861
+ if (name !== "npm" && name !== "npx")
862
+ return null;
863
+ const node = resolveVerificationRunner("node", environment);
864
+ if (!node || node.fixedArgs || path4.extname(node.executablePath).toLowerCase() !== ".exe") {
865
+ return null;
866
+ }
867
+ const cli = path4.join(path4.dirname(launcherPath), "node_modules", "npm", "bin", `${name}-cli.js`);
868
+ try {
869
+ const canonicalLauncher = realpathSync3(launcherPath);
870
+ const canonicalCli = realpathSync3(cli);
871
+ const cliStat = lstatSync5(canonicalCli);
872
+ if (!cliStat.isFile())
873
+ return null;
874
+ const source = safeRunnerSource([node.executablePath, canonicalLauncher, canonicalCli], environment.platform);
875
+ if (!source)
876
+ return null;
877
+ return {
878
+ command,
879
+ executablePath: node.executablePath,
880
+ fixedArgs: [canonicalCli]
881
+ };
882
+ } catch {
883
+ return null;
884
+ }
885
+ }
886
+ function localPackageDirectories(dependencyRoot) {
887
+ const packages = [];
888
+ try {
889
+ for (const entry of readdirSync3(dependencyRoot, { withFileTypes: true })) {
890
+ if (!entry.isDirectory() || entry.name.startsWith("."))
891
+ continue;
892
+ const candidate = path4.join(dependencyRoot, entry.name);
893
+ if (!entry.name.startsWith("@")) {
894
+ packages.push(candidate);
895
+ continue;
896
+ }
897
+ for (const scoped of readdirSync3(candidate, { withFileTypes: true })) {
898
+ if (scoped.isDirectory() && !scoped.name.startsWith(".")) {
899
+ packages.push(path4.join(candidate, scoped.name));
900
+ }
901
+ }
902
+ }
903
+ } catch {
904
+ return [];
905
+ }
906
+ return packages;
907
+ }
908
+ function localPackageBinTargets(dependencyOwner, executable, platform) {
909
+ const dependencyRoot = path4.resolve(dependencyOwner, "node_modules");
910
+ let canonicalDependencyRoot;
911
+ try {
912
+ canonicalDependencyRoot = realpathSync3(dependencyRoot);
913
+ } catch {
914
+ return [];
915
+ }
916
+ const targets = [];
917
+ for (const packageDirectory of localPackageDirectories(dependencyRoot)) {
918
+ try {
919
+ const directoryStat = lstatSync5(packageDirectory);
920
+ if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) {
921
+ continue;
922
+ }
923
+ const canonicalPackage = realpathSync3(packageDirectory);
924
+ if (!pathWithin(canonicalDependencyRoot, canonicalPackage, platform) || canonicalPackage === canonicalDependencyRoot) {
925
+ continue;
926
+ }
927
+ const manifestPath = path4.join(canonicalPackage, "package.json");
928
+ const manifestStat = lstatSync5(manifestPath);
929
+ if (!manifestStat.isFile() || manifestStat.isSymbolicLink())
930
+ continue;
931
+ const manifest = JSON.parse(readFileSync3(manifestPath, "utf8"));
932
+ if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
933
+ continue;
934
+ }
935
+ const record2 = manifest;
936
+ const packageName = typeof record2.name === "string" ? record2.name.split("/").pop() ?? "" : "";
937
+ const bin = record2.bin;
938
+ let relative;
939
+ if (typeof bin === "string" && (platform === "win32" ? packageName.toLowerCase() === executable.toLowerCase() : packageName === executable)) {
940
+ relative = bin;
941
+ } else if (bin && typeof bin === "object" && !Array.isArray(bin)) {
942
+ const entries = Object.entries(bin).filter(([name]) => platform === "win32" ? name.toLowerCase() === executable.toLowerCase() : name === executable);
943
+ if (entries.length === 1)
944
+ relative = entries[0]?.[1];
945
+ }
946
+ if (typeof relative !== "string" || relative.length === 0 || relative.includes("\x00")) {
947
+ continue;
948
+ }
949
+ const unresolved = path4.resolve(canonicalPackage, relative);
950
+ if (!pathWithin(canonicalPackage, unresolved, platform))
951
+ continue;
952
+ const canonical = realpathSync3(unresolved);
953
+ const stat = lstatSync5(canonical);
954
+ if (stat.isFile() && pathWithin(canonicalPackage, canonical, platform) && pathWithin(canonicalDependencyRoot, canonical, platform)) {
955
+ targets.push(canonical);
956
+ }
957
+ } catch {}
958
+ }
959
+ return [...new Set(targets)];
960
+ }
961
+ function resolveLocalVerificationRunner(dependencyOwner, executable, runnerEnvironment) {
962
+ const environment = resolvedRunnerEnvironment(runnerEnvironment);
963
+ if (environment.platform !== "win32")
964
+ return null;
965
+ const targets = localPackageBinTargets(dependencyOwner, executable, environment.platform);
966
+ if (targets.length !== 1)
967
+ return null;
968
+ const target = targets[0];
969
+ const extension = path4.extname(target).toLowerCase();
970
+ if (extension === ".exe") {
971
+ return { command: executable, executablePath: target };
972
+ }
973
+ if (![".js", ".cjs", ".mjs"].includes(extension))
974
+ return null;
975
+ const node = resolveVerificationRunner("node", environment);
976
+ if (!node || node.fixedArgs)
977
+ return null;
978
+ return {
979
+ command: executable,
980
+ executablePath: node.executablePath,
981
+ fixedArgs: [target]
982
+ };
983
+ }
984
+ function resolveVerificationRunner(command, runnerEnvironment = {}) {
985
+ const environment = resolvedRunnerEnvironment(runnerEnvironment);
986
+ const directories = environment.path.split(environment.pathDelimiter).filter(Boolean);
987
+ const seenDirectories = new Set;
988
+ const candidates = [
989
+ ...command === "bun" && process.versions.bun && environment.platform === process.platform ? [process.execPath] : [],
990
+ ...directories.flatMap((directory) => {
991
+ const resolvedDirectory = path4.resolve(directory);
992
+ const key = environment.platform === "win32" ? resolvedDirectory.toLowerCase() : resolvedDirectory;
993
+ if (seenDirectories.has(key))
994
+ return [];
995
+ seenDirectories.add(key);
996
+ return runnerNames(command, environment).flatMap((name) => {
997
+ const candidate = resolveCandidateName(resolvedDirectory, name, environment.platform);
998
+ return candidate ? [candidate] : [];
999
+ });
1000
+ })
1001
+ ];
1002
+ const seenCandidates = new Set;
1003
+ for (const candidate of candidates) {
1004
+ try {
1005
+ const executablePath = path4.resolve(candidate);
1006
+ const candidateKey = environment.platform === "win32" ? executablePath.toLowerCase() : executablePath;
1007
+ if (seenCandidates.has(candidateKey))
1008
+ continue;
1009
+ seenCandidates.add(candidateKey);
1010
+ const canonical = realpathSync3(executablePath);
1011
+ const stat = lstatSync5(canonical);
1012
+ if (!regularExecutableFile(stat, environment.platform))
1013
+ continue;
1014
+ if (environment.platform === "win32") {
1015
+ const extension = path4.extname(executablePath).toLowerCase();
1016
+ if (extension === ".cmd") {
1017
+ const shim = windowsShimBinding(command, executablePath, environment);
1018
+ if (shim)
1019
+ return shim;
1020
+ continue;
1021
+ }
1022
+ if (extension !== ".exe")
1023
+ continue;
1024
+ if (!safeRunnerSource([executablePath, canonical], environment.platform)) {
1025
+ continue;
1026
+ }
1027
+ return { command, executablePath };
1028
+ }
1029
+ const systemVisible = SYSTEM_MOUNT_ROOTS.some((root) => within(root, executablePath) && within(root, canonical));
1030
+ if (systemVisible)
1031
+ return { command, executablePath };
1032
+ const mountSource = commonDirectory(path4.dirname(executablePath), path4.dirname(canonical), environment.platform);
1033
+ if (unsafeMountSource(mountSource))
1034
+ continue;
1035
+ const sourceStat = lstatSync5(mountSource);
1036
+ if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink())
1037
+ continue;
1038
+ return { command, executablePath, mountSource };
1039
+ } catch {}
1040
+ }
1041
+ return null;
1042
+ }
1043
+ function packageManifest(root) {
1044
+ if (!regularFile(root, "package.json"))
1045
+ return null;
1046
+ try {
1047
+ const value = JSON.parse(readFileSync3(path4.join(root, "package.json"), "utf8"));
1048
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1049
+ } catch {
1050
+ return null;
1051
+ }
1052
+ }
1053
+ function validatePackageScript(root, verificationId, packageManager, script, approvedCommand, _dependencyOwner = root, runnerEnvironment = {}) {
1054
+ const packageRunner = resolveVerificationRunner(packageManager, runnerEnvironment);
1055
+ if (!packageRunner) {
1056
+ return adapterFailure(verificationId, "runner-missing", `approved package manager ${packageManager} is unavailable or cannot be mounted safely`);
1057
+ }
1058
+ const manifest = packageManifest(root);
1059
+ const scripts = manifest?.scripts;
1060
+ const actual = scripts && typeof scripts === "object" && !Array.isArray(scripts) ? scripts[script] : undefined;
1061
+ if (typeof actual !== "string") {
1062
+ return adapterFailure(verificationId, "script-missing", `package.json script ${script} is missing`);
1063
+ }
1064
+ if (actual !== approvedCommand) {
1065
+ return adapterFailure(verificationId, "script-command-mismatch", `package.json script ${script} differs from the Gate B contract`);
1066
+ }
1067
+ const runtimes = ["node", "bun", "npm", "npx", "pnpm", "yarn"].flatMap((command) => {
1068
+ const binding = resolveVerificationRunner(command, runnerEnvironment);
1069
+ return binding ? [binding] : [];
1070
+ });
1071
+ return capabilitySuccess(verificationId, [packageRunner, ...runtimes]);
1072
+ }
1073
+ function unsupportedExecutionConfiguration(source) {
1074
+ const restricted = new Set([
1075
+ "scriptshell",
1076
+ "userconfig",
1077
+ "globalconfig",
1078
+ "yarnpath",
1079
+ "plugins",
1080
+ "auth",
1081
+ "authtoken",
1082
+ "password",
1083
+ "token",
1084
+ "npmauthtoken",
1085
+ "npmauthident"
1086
+ ]);
1087
+ for (const line of source.split(/\r?\n/u)) {
1088
+ let quote = "";
1089
+ let escaped = false;
1090
+ let active = "";
1091
+ const parts = [];
1092
+ let flowDepth = 0;
1093
+ for (const character of line) {
1094
+ if (escaped) {
1095
+ active += character;
1096
+ escaped = false;
1097
+ continue;
1098
+ }
1099
+ if (character === "\\" && quote === '"') {
1100
+ active += character;
1101
+ escaped = true;
1102
+ continue;
1103
+ }
1104
+ if (quote) {
1105
+ active += character;
1106
+ if (character === quote)
1107
+ quote = "";
1108
+ } else if (character === '"' || character === "'") {
1109
+ quote = character;
1110
+ active += character;
1111
+ } else if (character === "#" || character === ";" && active.trim() === "") {
1112
+ break;
1113
+ } else if (character === "{" || character === "}" || character === "," && flowDepth > 0) {
1114
+ if (character === "{")
1115
+ flowDepth++;
1116
+ if (character === "}")
1117
+ flowDepth = Math.max(0, flowDepth - 1);
1118
+ parts.push(active);
1119
+ active = "";
1120
+ } else
1121
+ active += character;
1122
+ }
1123
+ parts.push(active);
1124
+ for (const part of parts) {
1125
+ if (part.includes("${"))
1126
+ return true;
1127
+ const directive = part.match(/^\s*(?:"((?:\\.|[^"\\])*)"|'([^']*)'|([^\s=]+))\s*(.*)$/u);
1128
+ if (!directive)
1129
+ continue;
1130
+ const rawKey = directive[1] ?? directive[2] ?? directive[3];
1131
+ if (!rawKey.endsWith(":") && !directive[4])
1132
+ continue;
1133
+ const key = rawKey.replace(/:$/u, "").split(":").at(-1)?.replace(/[-_]/gu, "").toLowerCase();
1134
+ if (key && restricted.has(key))
1135
+ return true;
1136
+ }
1137
+ }
1138
+ return false;
1139
+ }
1140
+ function validateAtomicCapability(root, step, dependencyOwner, runnerEnvironment, executionWritePaths) {
1141
+ if (step.kind === "vitest" && [
1142
+ ...step.args,
1143
+ ...step.runner.kind === "package-script" ? step.runner.command.split(/\s+/u) : []
1144
+ ].some((arg) => /^--(?:reporters?|outputFile)(?:[.=]|$)/u.test(arg))) {
1145
+ return adapterFailure(step.id, "report-arguments-conflict", "Vitest report arguments are owned by the adapter");
1146
+ }
1147
+ if (step.executionBindings) {
1148
+ for (const [relative, expected] of Object.entries(step.executionBindings)) {
1149
+ if (executionWritePaths.includes(relative))
1150
+ continue;
1151
+ const observation = observeSafePath(root, relative);
1152
+ if (expected === null && observation.kind !== "absent" || expected !== null && snapshotFile(root, relative)?.sha256 !== expected) {
1153
+ return adapterFailure(step.id, "verification-config-mismatch", "Bound execution inputs changed; recompile the verification contract");
1154
+ }
1155
+ }
1156
+ }
1157
+ for (const relative of verificationBoundInputPaths(step).filter((file) => VERIFICATION_CONFIGURATION_PATHS.includes(file))) {
1158
+ const observation = observeSafePath(root, relative);
1159
+ if (!["file", "absent"].includes(observation.kind))
1160
+ return adapterFailure(step.id, "verification-config-unsafe", "Execution configuration must be a regular file");
1161
+ if (observation.kind !== "file" || ![
1162
+ ".npmrc",
1163
+ ".yarnrc",
1164
+ ".yarnrc.yml",
1165
+ "bunfig.toml",
1166
+ "pnpm-workspace.yaml"
1167
+ ].includes(relative))
1168
+ continue;
1169
+ if (lstatSync5(path4.join(root, relative)).size > 64 * 1024 || executionProfile().mode !== "local-trusted" && unsupportedExecutionConfiguration(readFileSync3(path4.join(root, relative), "utf8"))) {
1170
+ return adapterFailure(step.id, "verification-config-unsafe", "Execution configuration requires unsupported credentials or host configuration");
1171
+ }
1172
+ }
1173
+ if (step.kind === "package-script") {
1174
+ return validatePackageScript(root, step.id, step.packageManager, step.script, step.command, dependencyOwner, runnerEnvironment);
1175
+ }
1176
+ const runner = step.runner;
1177
+ if (runner.kind === "package-script") {
1178
+ const script = validatePackageScript(root, step.id, runner.packageManager, runner.script, runner.command, dependencyOwner, runnerEnvironment);
1179
+ if (!script.ok)
1180
+ return script;
1181
+ if (step.kind === "vitest" && !localExecutable(root, "vitest", dependencyOwner, runnerEnvironment)) {
1182
+ return adapterFailure(step.id, "local-executable-missing", "Vitest is not installed in consumer node_modules");
1183
+ }
1184
+ return script;
1185
+ }
1186
+ if (runner.kind === "node") {
1187
+ const node = resolveVerificationRunner("node", runnerEnvironment);
1188
+ return node ? capabilitySuccess(step.id, [node]) : adapterFailure(step.id, "runner-missing", "Node is unavailable or cannot be mounted safely");
1189
+ }
1190
+ if (!localExecutable(root, runner.executable, dependencyOwner, runnerEnvironment)) {
1191
+ return adapterFailure(step.id, "local-executable-missing", `local executable ${runner.executable} is unavailable`);
1192
+ }
1193
+ if (runner.kind === "npx") {
1194
+ const npx = resolveVerificationRunner("npx", runnerEnvironment);
1195
+ return npx ? capabilitySuccess(step.id, [npx]) : adapterFailure(step.id, "runner-missing", "npx is unavailable or cannot be mounted safely");
1196
+ }
1197
+ if ((runnerEnvironment.platform ?? process.platform) === "win32") {
1198
+ const binding = resolveLocalVerificationRunner(dependencyOwner, runner.executable, runnerEnvironment);
1199
+ return binding ? capabilitySuccess(step.id, [binding]) : adapterFailure(step.id, "local-executable-missing", `local executable ${runner.executable} has no safe direct Windows binding`);
1200
+ }
1201
+ return capabilitySuccess(step.id);
1202
+ }
1203
+ function validateVerificationAdapterCapability(root, value, options = {}) {
1204
+ return validateCapability(root, value, options, false);
1205
+ }
1206
+ function validateCapability(root, value, options, requireInputAvailability) {
1207
+ const validation = validateVerificationContract(value);
1208
+ if (!validation.ok) {
1209
+ const id = value && typeof value === "object" && !Array.isArray(value) && typeof value.id === "string" ? String(value.id) : undefined;
1210
+ return {
1211
+ ok: false,
1212
+ diagnostic: {
1213
+ kind: "design-readiness",
1214
+ code: "verification-contract-unsupported",
1215
+ ...id ? { verificationId: id } : {},
1216
+ message: validation.reason
1217
+ }
1218
+ };
1219
+ }
1220
+ const dependencyOwner = options.dependencyOwner ?? root;
1221
+ return validateAcceptedVerificationCapability(root, validation.value, dependencyOwner, options.runnerEnvironment ?? {}, requireInputAvailability, options.executionWritePaths ?? []);
1222
+ }
1223
+ function validateAcceptedVerificationCapability(root, verification, dependencyOwner, runnerEnvironment, requireInputAvailability, executionWritePaths) {
1224
+ if (requireInputAvailability) {
1225
+ for (const input of verificationInputPaths(verification)) {
1226
+ if (!isSafeRegularFile(root, input)) {
1227
+ return adapterFailure(verification.id, "input-missing", `verification input ${input} is missing or unsafe`);
1228
+ }
1229
+ }
1230
+ }
1231
+ const runnerBindings = [];
1232
+ for (const step of verificationSteps(verification)) {
1233
+ const capability = validateAtomicCapability(root, step, dependencyOwner, runnerEnvironment, executionWritePaths);
1234
+ if (!capability.ok)
1235
+ return capability;
1236
+ runnerBindings.push(...capability.runnerBindings);
1237
+ }
1238
+ return capabilitySuccess(verification.id, runnerBindings);
1239
+ }
1240
+
1241
+ // src/operator-tools.ts
1242
+ function inspectConsumer(root) {
1243
+ root = realpathSync4(root);
1244
+ const checks = [];
1245
+ const check = (name, action, nextStep) => {
1246
+ try {
1247
+ checks.push({ name, ok: true, detail: action() });
1248
+ } catch (error) {
1249
+ checks.push({
1250
+ name,
1251
+ ok: false,
1252
+ detail: error instanceof Error ? error.message : "unavailable",
1253
+ nextStep
1254
+ });
1255
+ }
1256
+ };
1257
+ check("node", () => {
1258
+ if (Number(process.versions.node.split(".")[0]) < 22 || Number(process.versions.node.split(".")[0]) === 22 && Number(process.versions.node.split(".")[1]) < 13)
1259
+ throw new Error("Node 22.13+ required");
1260
+ return process.versions.node;
1261
+ }, "Install Node >=22.13.");
1262
+ check("git", () => {
1263
+ const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
1264
+ cwd: root,
1265
+ encoding: "utf8",
1266
+ timeout: 5000,
1267
+ maxBuffer: 65536
1268
+ });
1269
+ if (result.status !== 0)
1270
+ throw new Error("git-repository-unavailable");
1271
+ return result.stdout.trim();
1272
+ }, "Install Git and initialize the consumer repository.");
1273
+ check("openspec", () => {
1274
+ resolveOpenSpecInvocation(root);
1275
+ return "resolved (protocol not executed)";
1276
+ }, "Install @fission-ai/openspec@1.5.0, or configure ABEL_OPENSPEC_PACKAGE_ROOT / ABEL_OPENSPEC_NODE before launching the host.");
1277
+ check("execution", () => {
1278
+ const profile = executionProfile();
1279
+ if (process.platform !== "linux")
1280
+ throw new Error("linux-pid-isolation-required");
1281
+ const result = spawnSync(profile.bwrapPath, [
1282
+ "--ro-bind",
1283
+ "/",
1284
+ "/",
1285
+ profile.mode === "local-trusted" ? "--unshare-pid" : "--unshare-all",
1286
+ "--",
1287
+ "/bin/true"
1288
+ ], { timeout: 5000, encoding: "utf8", maxBuffer: 65536 });
1289
+ if (result.status !== 0)
1290
+ throw new Error("bubblewrap-probe-failed");
1291
+ return `${profile.mode}: Bubblewrap PID namespace probe passed`;
1292
+ }, "On Linux install/enable Bubblewrap; set ABEL_BWRAP_PATH for a custom install. Trusted Linux projects may explicitly set ABEL_EXECUTION_MODE=local-trusted; Windows should use WSL.");
1293
+ check("request-budgets", () => JSON.stringify(requestBounds()), "Set ABEL_FIRST_PROGRESS_MS and ABEL_STREAM_IDLE_MS to positive milliseconds <=1200000.");
1294
+ check("state-root", () => resolveStateRoot({
1295
+ consumerRoot: root,
1296
+ xdgStateHome: process.env.XDG_STATE_HOME
1297
+ }).rootDir, "Use an absolute repository-external XDG_STATE_HOME.");
1298
+ check("workspace-dependencies", () => {
1299
+ const dependencies = path5.join(root, "node_modules");
1300
+ if (!lstatSync6(dependencies, { throwIfNoEntry: false }))
1301
+ return "no node_modules; prepare dependencies before verification";
1302
+ const names = readdirSync4(dependencies).flatMap((name) => name.startsWith("@") && lstatSync6(path5.join(dependencies, name)).isDirectory() ? readdirSync4(path5.join(dependencies, name)).map((child) => `${name}/${child}`) : [name]);
1303
+ if (names.length > 20000)
1304
+ throw new Error("dependency-view-too-large");
1305
+ let links = 0;
1306
+ for (const name of names) {
1307
+ const file = path5.join(dependencies, name);
1308
+ if (!lstatSync6(file).isSymbolicLink())
1309
+ continue;
1310
+ const resolved = realpathSync4(file);
1311
+ const relative = path5.relative(root, resolved);
1312
+ if (relative === ".." || relative.startsWith(`..${path5.sep}`) || path5.isAbsolute(relative))
1313
+ throw new Error("dependency-link-outside-consumer");
1314
+ if (!resolved.startsWith(`${dependencies}${path5.sep}`))
1315
+ links++;
1316
+ }
1317
+ return `${links} repository workspace link(s); their targets must be included in the candidate baseline`;
1318
+ }, "Repair dangling/external workspace links and ensure local package sources are tracked or admitted in the candidate.");
1319
+ const manifest = path5.join(root, "package.json");
1320
+ if (lstatSync6(manifest, { throwIfNoEntry: false })?.isFile()) {
1321
+ check("manifest", () => {
1322
+ const parsed2 = JSON.parse(readFileSync4(manifest, "utf8"));
1323
+ if (!parsed2 || typeof parsed2 !== "object")
1324
+ throw new Error("manifest-invalid");
1325
+ return Object.keys(parsed2.scripts ?? {}).join(", ") || "no package scripts";
1326
+ }, "Repair package.json.");
1327
+ const parsed = (() => {
1328
+ try {
1329
+ return JSON.parse(readFileSync4(manifest, "utf8"));
1330
+ } catch {
1331
+ return {};
1332
+ }
1333
+ })();
1334
+ for (const script of ["test", "check", "build"].filter((name) => typeof parsed.scripts?.[name] === "string")) {
1335
+ check(`script:${script}`, () => {
1336
+ const manager = ["bun", "pnpm", "yarn", "npm"].find((name) => lstatSync6(path5.join(root, {
1337
+ bun: "bun.lock",
1338
+ pnpm: "pnpm-lock.yaml",
1339
+ yarn: "yarn.lock",
1340
+ npm: "package-lock.json"
1341
+ }[name]), { throwIfNoEntry: false })) ?? "npm";
1342
+ const result = validateVerificationAdapterCapability(root, {
1343
+ kind: "package-script",
1344
+ id: `doctor-${script}`,
1345
+ packageManager: manager,
1346
+ script,
1347
+ command: parsed.scripts[script],
1348
+ args: [],
1349
+ classification: "expected-green"
1350
+ });
1351
+ if (!result.ok)
1352
+ throw new Error(result.diagnostic.code);
1353
+ return "statically admitted; tests not executed";
1354
+ }, "Check the runner, installed dependencies and execution configuration; this probe does not execute your tests.");
1355
+ }
1356
+ }
1357
+ return { root, ok: checks.every((entry) => entry.ok), checks };
1358
+ }
1359
+ function storageUsage(root, maximum = 1e5) {
1360
+ let entries = 0;
1361
+ let bytes = 0;
1362
+ let truncated = false;
1363
+ const visit = (file) => {
1364
+ if (entries >= maximum) {
1365
+ truncated = true;
1366
+ return;
1367
+ }
1368
+ const stat = lstatSync6(file, { throwIfNoEntry: false });
1369
+ if (!stat)
1370
+ return;
1371
+ entries++;
1372
+ if (stat.isFile())
1373
+ bytes += stat.size;
1374
+ else if (stat.isDirectory())
1375
+ for (const name of readdirSync4(file)) {
1376
+ visit(path5.join(file, name));
1377
+ if (truncated)
1378
+ break;
1379
+ }
1380
+ };
1381
+ visit(root);
1382
+ return { entries, bytes, truncated };
1383
+ }
1384
+ function inspectRuns(root) {
1385
+ const state = resolveStateRoot({
1386
+ consumerRoot: root,
1387
+ xdgStateHome: process.env.XDG_STATE_HOME
1388
+ });
1389
+ const usage = storageUsage(state.rootDir);
1390
+ if (!lstatSync6(state.databasePath, { throwIfNoEntry: false }))
1391
+ return { stateRoot: state.rootDir, usage, runs: [], truncated: false };
1392
+ const db = new DatabaseSync(state.databasePath, { readOnly: true });
1393
+ try {
1394
+ const rows = db.prepare("SELECT run_id, stage, change_name, state, sequence FROM runs ORDER BY run_id LIMIT 1001").all();
1395
+ return {
1396
+ stateRoot: state.rootDir,
1397
+ usage,
1398
+ runs: rows.slice(0, 1000),
1399
+ truncated: rows.length > 1000
1400
+ };
1401
+ } finally {
1402
+ db.close();
1403
+ }
1404
+ }
1405
+
1406
+ // src/operator-cli-entry.mjs
1407
+ var [command = "doctor", root = process.cwd()] = process.argv.slice(2);
1408
+ try {
1409
+ if (!["doctor", "runs"].includes(command))
1410
+ throw new Error("Usage: node --experimental-strip-types <cadence>/src/operator-cli.mjs doctor|runs [consumer-root]");
1411
+ const result = command === "doctor" ? inspectConsumer(path6.resolve(root)) : inspectRuns(path6.resolve(root));
1412
+ console.log(JSON.stringify(result, null, 2));
1413
+ if (command === "doctor" && !result.ok)
1414
+ process.exitCode = 1;
1415
+ } catch (error) {
1416
+ console.error(JSON.stringify({
1417
+ ok: false,
1418
+ error: error instanceof Error ? error.message : "operator-command-failed"
1419
+ }));
1420
+ process.exitCode = 1;
1421
+ }