cool-workflow 0.1.80 → 0.1.82

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 (122) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +42 -2
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/end-to-end-golden-path/app.json +1 -1
  7. package/apps/pr-review-fix-ci/app.json +1 -1
  8. package/apps/release-cut/app.json +1 -1
  9. package/apps/research-synthesis/app.json +1 -1
  10. package/dist/agent-config.js +21 -7
  11. package/dist/candidate-scoring.js +62 -48
  12. package/dist/capability-core.js +152 -96
  13. package/dist/capability-registry.js +160 -174
  14. package/dist/cli.js +90 -100
  15. package/dist/collaboration.js +5 -6
  16. package/dist/commit.js +232 -209
  17. package/dist/compare.js +18 -0
  18. package/dist/coordinator/classify.js +45 -0
  19. package/dist/coordinator/paths.js +42 -0
  20. package/dist/coordinator/util.js +126 -0
  21. package/dist/coordinator.js +127 -300
  22. package/dist/dispatch.js +46 -3
  23. package/dist/drive.js +7 -7
  24. package/dist/error-feedback.js +8 -4
  25. package/dist/evidence-reasoning.js +5 -2
  26. package/dist/execution-backend/agent.js +294 -0
  27. package/dist/execution-backend/probes.js +96 -0
  28. package/dist/execution-backend/util.js +47 -0
  29. package/dist/execution-backend.js +77 -450
  30. package/dist/gates.js +48 -0
  31. package/dist/mcp-server.js +34 -173
  32. package/dist/multi-agent/graph.js +84 -0
  33. package/dist/multi-agent/helpers.js +141 -0
  34. package/dist/multi-agent/ids.js +20 -0
  35. package/dist/multi-agent/paths.js +22 -0
  36. package/dist/multi-agent-eval/format.js +194 -0
  37. package/dist/multi-agent-eval/normalize.js +51 -0
  38. package/dist/multi-agent-eval.js +63 -242
  39. package/dist/multi-agent-host.js +53 -40
  40. package/dist/multi-agent-operator-ux.js +2 -1
  41. package/dist/multi-agent-trust.js +5 -5
  42. package/dist/multi-agent.js +125 -314
  43. package/dist/node-projection.js +59 -0
  44. package/dist/node-snapshot.js +11 -21
  45. package/dist/observability/format.js +61 -0
  46. package/dist/observability/intake.js +98 -0
  47. package/dist/observability.js +14 -160
  48. package/dist/operator-ux/format.js +364 -0
  49. package/dist/operator-ux.js +22 -363
  50. package/dist/orchestrator/lifecycle-operations.js +22 -1
  51. package/dist/orchestrator/report.js +8 -0
  52. package/dist/orchestrator.js +41 -10
  53. package/dist/reclamation.js +32 -55
  54. package/dist/run-export.js +138 -14
  55. package/dist/run-registry/derive.js +172 -0
  56. package/dist/run-registry/format.js +124 -0
  57. package/dist/run-registry/gc.js +251 -0
  58. package/dist/run-registry/policy.js +16 -0
  59. package/dist/run-registry/queue.js +116 -0
  60. package/dist/run-registry.js +78 -593
  61. package/dist/run-state-schema.js +1 -0
  62. package/dist/sandbox-profile.js +43 -2
  63. package/dist/scheduler.js +34 -4
  64. package/dist/state-explosion/format.js +159 -0
  65. package/dist/state-explosion/helpers.js +82 -0
  66. package/dist/state-explosion.js +65 -283
  67. package/dist/state-node.js +19 -4
  68. package/dist/telemetry-attestation.js +55 -0
  69. package/dist/telemetry-demo.js +15 -3
  70. package/dist/telemetry-ledger.js +60 -15
  71. package/dist/topology.js +50 -12
  72. package/dist/triggers.js +33 -14
  73. package/dist/trust-audit.js +215 -71
  74. package/dist/validation.js +328 -0
  75. package/dist/version.js +1 -1
  76. package/dist/worker-isolation/helpers.js +51 -0
  77. package/dist/worker-isolation/paths.js +46 -0
  78. package/dist/worker-isolation.js +182 -173
  79. package/docs/agent-delegation-drive.7.md +14 -0
  80. package/docs/cli-mcp-parity.7.md +5 -0
  81. package/docs/contract-migration-tooling.7.md +3 -0
  82. package/docs/control-plane-scheduling.7.md +3 -0
  83. package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
  84. package/docs/durable-state-and-locking.7.md +5 -0
  85. package/docs/evidence-adoption-reasoning-chain.7.md +3 -0
  86. package/docs/execution-backends.7.md +3 -0
  87. package/docs/index.md +1 -0
  88. package/docs/launch/launch-kit.md +46 -23
  89. package/docs/launch/pre-launch-checklist.md +14 -14
  90. package/docs/multi-agent-cli-mcp-surface.7.md +5 -0
  91. package/docs/multi-agent-eval-replay-harness.7.md +3 -0
  92. package/docs/multi-agent-operator-ux.7.md +3 -0
  93. package/docs/multi-agent-trust-policy-audit.7.md +27 -0
  94. package/docs/node-snapshot-diff-replay.7.md +3 -0
  95. package/docs/observability-cost-accounting.7.md +3 -0
  96. package/docs/project-index.md +23 -6
  97. package/docs/real-execution-backends.7.md +3 -0
  98. package/docs/release-and-migration.7.md +5 -0
  99. package/docs/release-tooling.7.md +35 -2
  100. package/docs/run-registry-control-plane.7.md +55 -8
  101. package/docs/run-retention-reclamation.7.md +5 -0
  102. package/docs/state-explosion-management.7.md +3 -0
  103. package/docs/team-collaboration.7.md +3 -0
  104. package/docs/trust-model.md +267 -0
  105. package/docs/vendor-manifest-loadability.7.md +43 -0
  106. package/docs/web-desktop-workbench.7.md +3 -0
  107. package/manifest/plugin.manifest.json +1 -1
  108. package/manifest/source-context-profiles.json +1 -1
  109. package/package.json +4 -2
  110. package/scripts/agents/builtin-templates.json +7 -0
  111. package/scripts/bump-version.js +5 -11
  112. package/scripts/canonical-apps-list.js +64 -0
  113. package/scripts/canonical-apps.js +19 -4
  114. package/scripts/children/batch-delegate-child.js +58 -0
  115. package/scripts/children/http-delegate-child.js +39 -0
  116. package/scripts/dogfood-release.js +1 -1
  117. package/scripts/golden-path.js +4 -4
  118. package/scripts/parity-check.js +5 -0
  119. package/scripts/release-check.js +5 -1
  120. package/scripts/release-flow.js +181 -5
  121. package/scripts/version-sync-check.js +5 -8
  122. package/dist/capability-dispatcher.js +0 -86
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.BackendError = exports.SANDBOX_DIMENSIONS = exports.DEFAULT_BACKEND_ID = exports.EXECUTION_BACKEND_SCHEMA_VERSION = void 0;
29
+ exports.BackendError = exports.SANDBOX_DIMENSIONS = exports.DEFAULT_BACKEND_ID = exports.EXECUTION_BACKEND_SCHEMA_VERSION = exports.runAgentBatchOutcomes = exports.prepareAgentSpawn = exports.stripSecretArgs = exports.sha256 = void 0;
30
30
  exports.registerBackend = registerBackend;
31
31
  exports.getBackendDriver = getBackendDriver;
32
32
  exports.listBackendDescriptors = listBackendDescriptors;
@@ -39,21 +39,33 @@ exports.requiredSandboxDimensions = requiredSandboxDimensions;
39
39
  exports.attestSandbox = attestSandbox;
40
40
  exports.probeBackend = probeBackend;
41
41
  exports.runBackend = runBackend;
42
- exports.stripSecretArgs = stripSecretArgs;
43
- exports.prepareAgentSpawn = prepareAgentSpawn;
44
- exports.runAgentBatchOutcomes = runAgentBatchOutcomes;
45
42
  exports.createExecutionBackend = createExecutionBackend;
46
43
  exports.listExecutionBackends = listExecutionBackends;
47
44
  exports.backendListPayload = backendListPayload;
48
45
  exports.backendShowPayload = backendShowPayload;
49
46
  exports.backendProbePayload = backendProbePayload;
50
47
  exports.buildChildEnv = buildChildEnv;
51
- exports.sha256 = sha256;
52
48
  exports.clearProbeCache = clearProbeCache;
53
- const node_crypto_1 = __importDefault(require("node:crypto"));
54
49
  const node_fs_1 = __importDefault(require("node:fs"));
55
50
  const node_path_1 = __importDefault(require("node:path"));
56
51
  const node_child_process_1 = require("node:child_process");
52
+ // Pure leaf helpers — carved into ./execution-backend/util.ts (god-module carve).
53
+ // `sha256` is re-exported below to keep the public surface byte-identical.
54
+ const util_1 = require("./execution-backend/util");
55
+ // Per-backend readiness probe bodies — carved into ./execution-backend/probes.ts.
56
+ const probes_1 = require("./execution-backend/probes");
57
+ // Agent-delegation pure helpers + concurrent batch — carved into
58
+ // ./execution-backend/agent.ts. The public symbols (stripSecretArgs,
59
+ // AgentSpawnJob, prepareAgentSpawn, runAgentBatchOutcomes) are re-exported below.
60
+ const agent_1 = require("./execution-backend/agent");
61
+ // Re-export the carved public surface so every importer of "./execution-backend"
62
+ // is byte-unchanged (no public signature changed; pure code movement).
63
+ var util_2 = require("./execution-backend/util");
64
+ Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return util_2.sha256; } });
65
+ var agent_2 = require("./execution-backend/agent");
66
+ Object.defineProperty(exports, "stripSecretArgs", { enumerable: true, get: function () { return agent_2.stripSecretArgs; } });
67
+ Object.defineProperty(exports, "prepareAgentSpawn", { enumerable: true, get: function () { return agent_2.prepareAgentSpawn; } });
68
+ Object.defineProperty(exports, "runAgentBatchOutcomes", { enumerable: true, get: function () { return agent_2.runAgentBatchOutcomes; } });
57
69
  exports.EXECUTION_BACKEND_SCHEMA_VERSION = 1;
58
70
  exports.DEFAULT_BACKEND_ID = "node";
59
71
  exports.SANDBOX_DIMENSIONS = ["read", "write", "command", "network", "env"];
@@ -204,21 +216,21 @@ function getBackendDescriptor(id) {
204
216
  // — no central switch to edit. Function declarations below are hoisted, so the
205
217
  // closures resolve at call time.
206
218
  const BUILTIN_DRIVER_BEHAVIORS = {
207
- node: { spawnStyle: "direct", runtimeNote: () => "node", probe: probeNodeBackend },
219
+ node: { spawnStyle: "direct", runtimeNote: () => "node", probe: probes_1.probeNodeBackend },
208
220
  bun: {
209
221
  spawnStyle: "direct",
210
- runtimeNote: () => (hasExecutable("bun") ? "bun (node-compatible execution)" : "node-compatible (bun not installed)"),
211
- probe: probeBunBackend
222
+ runtimeNote: () => ((0, util_1.hasExecutable)("bun") ? "bun (node-compatible execution)" : "node-compatible (bun not installed)"),
223
+ probe: probes_1.probeBunBackend
212
224
  },
213
- shell: { spawnStyle: "shell", runtimeNote: () => "posix-shell", probe: probeShellBackend },
214
- container: { delegateRun: ctxDelegate(runContainer), buildHandle: containerHandle, probe: probeContainerBackend },
215
- remote: { delegateRun: ctxDelegate(runHttpDelegation), buildHandle: remoteHandle, probe: probeRemoteBackend },
216
- ci: { delegateRun: ctxDelegate(runHttpDelegation), buildHandle: ciHandle, probe: probeCiBackend },
225
+ shell: { spawnStyle: "shell", runtimeNote: () => "posix-shell", probe: probes_1.probeShellBackend },
226
+ container: { delegateRun: ctxDelegate(runContainer), buildHandle: containerHandle, probe: probes_1.probeContainerBackend },
227
+ remote: { delegateRun: ctxDelegate(runHttpDelegation), buildHandle: remoteHandle, probe: probes_1.probeRemoteBackend },
228
+ ci: { delegateRun: ctxDelegate(runHttpDelegation), buildHandle: ciHandle, probe: probes_1.probeCiBackend },
217
229
  agent: {
218
230
  delegateRun: ctxDelegate(runAgentProcess),
219
- buildHandle: agentHandle,
231
+ buildHandle: agent_1.agentHandle,
220
232
  commandlessDelegate: true,
221
- probe: probeAgentBackend
233
+ probe: probes_1.probeAgentBackend
222
234
  }
223
235
  };
224
236
  for (const spec of DRIVER_SPECS) {
@@ -254,7 +266,7 @@ function resolveBackendSelection(requested, env = process.env) {
254
266
  return { backendId: exports.DEFAULT_BACKEND_ID, source: "default" };
255
267
  }
256
268
  function backendSelectionFrom(args, env = process.env) {
257
- const requested = firstString(args.backend, args.backendId, args.executionBackend);
269
+ const requested = (0, util_1.firstString)(args.backend, args.backendId, args.executionBackend);
258
270
  return resolveBackendSelection(requested, env);
259
271
  }
260
272
  // ---------------------------------------------------------------------------
@@ -340,77 +352,6 @@ function probeBackend(id, context = {}) {
340
352
  reason: body.reason
341
353
  };
342
354
  }
343
- function probeNodeBackend() {
344
- const ok = hasExecutable("node");
345
- return {
346
- checks: [{ name: "node-runtime", ok, detail: ok ? "node on PATH" : "node not found on PATH" }],
347
- readiness: ok ? "ready" : "unavailable",
348
- reason: ok ? undefined : "node runtime not found on PATH"
349
- };
350
- }
351
- function probeShellBackend() {
352
- const ok = hasExecutable("sh") || node_fs_1.default.existsSync("/bin/sh");
353
- return {
354
- checks: [{ name: "posix-shell", ok, detail: ok ? "sh available" : "no POSIX shell found" }],
355
- readiness: ok ? "ready" : "unavailable",
356
- reason: ok ? undefined : "POSIX shell not found"
357
- };
358
- }
359
- function probeBunBackend() {
360
- const bun = hasExecutable("bun");
361
- const node = hasExecutable("node");
362
- return {
363
- checks: [
364
- { name: "bun-runtime", ok: bun, detail: bun ? "bun on PATH" : "bun not found; node-compatible fallback" },
365
- { name: "node-compatible-fallback", ok: node, detail: node ? "node on PATH" : "node not found on PATH" }
366
- ],
367
- readiness: bun || node ? "ready" : "unavailable",
368
- reason: !bun && node ? "bun not installed; executing via node-compatible runtime" : !bun && !node ? "neither bun nor node found on PATH" : undefined
369
- };
370
- }
371
- function probeContainerBackend() {
372
- const docker = hasExecutable("docker");
373
- const podman = hasExecutable("podman");
374
- return {
375
- checks: [
376
- { name: "docker", ok: docker, detail: docker ? "docker on PATH" : "docker not found" },
377
- { name: "podman", ok: podman, detail: podman ? "podman on PATH" : "podman not found" }
378
- ],
379
- readiness: docker || podman ? "ready" : "unavailable",
380
- reason: docker || podman ? undefined : "no container runtime (docker/podman) found; supply --image to delegate explicitly"
381
- };
382
- }
383
- function probeRemoteBackend() {
384
- const endpoint = (process.env.CW_REMOTE_ENDPOINT || "").trim();
385
- return {
386
- checks: [{ name: "endpoint", ok: Boolean(endpoint), detail: endpoint ? "CW_REMOTE_ENDPOINT configured" : "CW_REMOTE_ENDPOINT not set" }],
387
- readiness: endpoint ? "ready" : "unverified",
388
- reason: endpoint ? undefined : "no remote endpoint configured (set CW_REMOTE_ENDPOINT or pass --endpoint)"
389
- };
390
- }
391
- function probeCiBackend() {
392
- const endpoint = (process.env.CW_CI_ENDPOINT || "").trim();
393
- return {
394
- checks: [{ name: "ci-endpoint", ok: Boolean(endpoint), detail: endpoint ? "CW_CI_ENDPOINT configured" : "CW_CI_ENDPOINT not set" }],
395
- readiness: endpoint ? "ready" : "unverified",
396
- reason: endpoint ? undefined : "no CI job target configured (set CW_CI_ENDPOINT or pass --job)"
397
- };
398
- }
399
- function probeAgentBackend() {
400
- // Mirrors remote/ci EXACTLY: unconfigured ⇒ `unverified` (NOT a hard refusal),
401
- // configured ⇒ `ready`. "Configured" = a command-template or endpoint is set.
402
- const command = (process.env.CW_AGENT_COMMAND || "").trim();
403
- const endpoint = (process.env.CW_AGENT_ENDPOINT || "").trim();
404
- const configured = Boolean(command || endpoint);
405
- return {
406
- checks: [
407
- { name: "agent-command", ok: Boolean(command), detail: command ? "CW_AGENT_COMMAND configured" : "CW_AGENT_COMMAND not set" },
408
- { name: "agent-endpoint", ok: Boolean(endpoint), detail: endpoint ? "CW_AGENT_ENDPOINT configured" : "CW_AGENT_ENDPOINT not set" }
409
- ],
410
- readiness: configured ? "ready" : "unverified",
411
- reason: configured ? undefined : "no agent configured (set CW_AGENT_COMMAND or CW_AGENT_ENDPOINT, or pass --agent-command/--agent-endpoint)"
412
- };
413
- }
414
355
  // ---------------------------------------------------------------------------
415
356
  // The run entry. Refuses (fail closed) when the sandbox cannot be honored, the
416
357
  // command is denied by policy, or the backend is not ready. Local drivers spawn a
@@ -474,9 +415,9 @@ function executeLocal(descriptor, policy, request, label, attestation) {
474
415
  ? (0, node_child_process_1.spawnSync)([command, ...args].join(" "), { ...options, shell: true })
475
416
  : (0, node_child_process_1.spawnSync)(command, args, { ...options, shell: false });
476
417
  const exitCode = typeof result.status === "number" ? result.status : null;
477
- const spawnError = result.error ? messageOf(result.error) : undefined;
418
+ const spawnError = result.error ? (0, util_1.messageOf)(result.error) : undefined;
478
419
  const stdout = String(result.stdout || "");
479
- const digest = sha256(stdout);
420
+ const digest = (0, util_1.sha256)(stdout);
480
421
  const status = spawnError ? "failed" : exitCode === 0 ? "completed" : "failed";
481
422
  const evidence = [
482
423
  `command:${[command, ...args].join(" ")}`,
@@ -502,7 +443,7 @@ function executeLocal(descriptor, policy, request, label, attestation) {
502
443
  backendId: descriptor.id,
503
444
  locality: descriptor.locality,
504
445
  kind: descriptor.kind,
505
- attestation: { ...attestation, status: status === "completed" ? attestation.status : attestation.status, notes }
446
+ attestation: { ...attestation, status: attestation.status, notes }
506
447
  }
507
448
  };
508
449
  }
@@ -544,7 +485,7 @@ function delegate(descriptor, policy, request, label, probe) {
544
485
  * identical to executeLocal's, so evidence is byte-stable across backends. The
545
486
  * handle is recorded in provenance only. */
546
487
  function delegatedEnvelope(descriptor, label, handle, attestation, command, args, exitCode, stdout) {
547
- const digest = sha256(stdout);
488
+ const digest = (0, util_1.sha256)(stdout);
548
489
  const status = exitCode === 0 ? "completed" : "failed";
549
490
  const evidence = [
550
491
  `command:${[command, ...args].join(" ")}`,
@@ -573,7 +514,7 @@ function delegatedEnvelope(descriptor, label, handle, attestation, command, args
573
514
  * closed when no runtime is on PATH, the daemon is unreachable, or the runtime
574
515
  * itself errors (exit 125) — distinct from the command's own non-zero exit. */
575
516
  function runContainer(descriptor, policy, request, label, handle, attestation) {
576
- const runtime = hasExecutable("docker") ? "docker" : hasExecutable("podman") ? "podman" : undefined;
517
+ const runtime = (0, util_1.hasExecutable)("docker") ? "docker" : (0, util_1.hasExecutable)("podman") ? "podman" : undefined;
577
518
  if (!runtime) {
578
519
  return refusedEnvelope(descriptor, policy, label, "runtime-unavailable", "no container runtime (docker/podman) on PATH", {
579
520
  attestation
@@ -622,7 +563,7 @@ function runContainer(descriptor, policy, request, label, handle, attestation) {
622
563
  maxBuffer: 32 * 1024 * 1024
623
564
  });
624
565
  if (result.error) {
625
- return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${runtime} run failed: ${messageOf(result.error)}`, {
566
+ return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${runtime} run failed: ${(0, util_1.messageOf)(result.error)}`, {
626
567
  attestation
627
568
  });
628
569
  }
@@ -638,35 +579,14 @@ function runContainer(descriptor, policy, request, label, handle, attestation) {
638
579
  }
639
580
  return delegatedEnvelope(descriptor, label, handle, attestation, command, args, exitCode, String(result.stdout || ""));
640
581
  }
641
- // A self-contained Node child that performs the remote/CI delegation: it reads a
642
- // JSON job on stdin, POSTs it to the endpoint, optionally polls a returned jobId,
643
- // and prints `{ exitCode, stdout }` (or `{ error }`) on stdout. Node-only (global
644
- // fetch, node >=18), so the driver stays portable and synchronous from CW's view.
645
- const HTTP_DELEGATE_CHILD = `
646
- (async () => {
647
- const read = () => new Promise((res) => { let b = ""; process.stdin.on("data", (c) => (b += c)); process.stdin.on("end", () => res(b)); });
648
- try {
649
- const job = JSON.parse((await read()) || "{}");
650
- const endpoint = process.env.CW_DELEGATE_ENDPOINT;
651
- if (!endpoint) throw new Error("no endpoint");
652
- const post = await fetch(endpoint, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(job) });
653
- if (!post.ok) throw new Error("runner responded " + post.status);
654
- let data = await post.json();
655
- // Poll a returned jobId until the runner reports done.
656
- let guard = 0;
657
- while (data && data.jobId && data.done !== true && guard++ < 600) {
658
- await new Promise((r) => setTimeout(r, 1000));
659
- const poll = await fetch(endpoint + (endpoint.includes("?") ? "&" : "?") + "jobId=" + encodeURIComponent(data.jobId));
660
- if (!poll.ok) throw new Error("poll responded " + poll.status);
661
- data = await poll.json();
662
- }
663
- if (typeof data.exitCode !== "number") throw new Error("runner did not report an exitCode");
664
- process.stdout.write(JSON.stringify({ exitCode: data.exitCode, stdout: String(data.stdout || "") }));
665
- } catch (e) {
666
- process.stdout.write(JSON.stringify({ error: e && e.message ? e.message : String(e) }));
667
- }
668
- })();
669
- `;
582
+ // The remote/CI delegation child is a real, packaged Node script (not an embedded
583
+ // `node -e` string — F11): it reads a JSON job on stdin, POSTs it to the endpoint,
584
+ // optionally polls a returned jobId, and prints `{ exitCode, stdout }` (or
585
+ // `{ error }`) on stdout. Node-only (global fetch, node >=18), so the driver stays
586
+ // portable and synchronous from CW's view. We spawn it BY PATH (shell:false). The
587
+ // path is resolved from this compiled module (dist/execution-backend.js) up to the
588
+ // package's `scripts/children/` dir, which package.json ships in "files".
589
+ const HTTP_DELEGATE_CHILD_SCRIPT = node_path_1.default.resolve(__dirname, "..", "scripts", "children", "http-delegate-child.js");
670
590
  /** remote / ci — real HTTP delegation. POSTs the job to the configured endpoint
671
591
  * (and polls a returned jobId) via a Node child, then records the runner's exit +
672
592
  * stdout digest as canonical evidence. Fails closed when the endpoint is missing,
@@ -688,7 +608,7 @@ function runHttpDelegation(descriptor, policy, request, label, handle, attestati
688
608
  sandboxProfileId: policy.id,
689
609
  jobId: handle.jobId
690
610
  });
691
- const child = (0, node_child_process_1.spawnSync)(process.execPath, ["-e", HTTP_DELEGATE_CHILD], {
611
+ const child = (0, node_child_process_1.spawnSync)(process.execPath, [HTTP_DELEGATE_CHILD_SCRIPT], {
692
612
  input: job,
693
613
  env: { ...process.env, CW_DELEGATE_ENDPOINT: endpoint },
694
614
  encoding: "utf8",
@@ -696,7 +616,7 @@ function runHttpDelegation(descriptor, policy, request, label, handle, attestati
696
616
  maxBuffer: 32 * 1024 * 1024
697
617
  });
698
618
  if (child.error) {
699
- return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${descriptor.id} delegation failed: ${messageOf(child.error)}`, {
619
+ return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${descriptor.id} delegation failed: ${(0, util_1.messageOf)(child.error)}`, {
700
620
  attestation
701
621
  });
702
622
  }
@@ -714,168 +634,31 @@ function runHttpDelegation(descriptor, policy, request, label, handle, attestati
714
634
  }
715
635
  return delegatedEnvelope(descriptor, label, handle, attestation, command, args, parsed.exitCode, String(parsed.stdout || ""));
716
636
  }
717
- /** Resolve the agent invocation from the request delegation > env. Vendor-neutral;
718
- * the durable file config is folded in by the drive layer before this point. */
719
- function resolveAgentInvocation(request) {
720
- const delegation = request.delegation || {};
721
- const envCommand = (process.env.CW_AGENT_COMMAND || "").trim();
722
- const endpoint = delegation.endpoint || (process.env.CW_AGENT_ENDPOINT || "").trim() || undefined;
723
- const model = delegation.model || (process.env.CW_AGENT_MODEL || "").trim() || undefined;
724
- // Accept the invocation via delegation (preferred) OR the top-level command/args.
725
- let binary = delegation.command || request.command || undefined;
726
- let rawArgs = delegation.args ? [...delegation.args] : request.args ? [...request.args] : [];
727
- // An env-string command ("claude -p --output-format json {{manifest}}") is split
728
- // into a binary + discrete argv template NEVER shell-interpreted.
729
- if (!binary && envCommand) {
730
- const parts = envCommand.split(/\s+/).filter(Boolean);
731
- binary = parts[0];
732
- if (!delegation.args)
733
- rawArgs = parts.slice(1);
734
- }
735
- else if (binary && !delegation.args && /\s/.test(binary)) {
736
- const parts = binary.split(/\s+/).filter(Boolean);
737
- binary = parts[0];
738
- rawArgs = parts.slice(1);
739
- }
740
- return { binary, rawArgs, endpoint, model, timeoutMs: request.timeoutMs };
741
- }
742
- const AGENT_SECRET_FLAGS = new Set(["--api-key", "--apikey", "--token", "--key", "--secret", "--password", "--auth", "--bearer"]);
743
- /** Redact secrets from recorded agent args: a value FOLLOWING a known secret flag,
744
- * an `--x-key=...` inline value, or a token that LOOKS like a credential. Never
745
- * record a raw secret in provenance/evidence. Exported so the durable config
746
- * surface strips the SAME way before persisting/showing a command template. */
747
- function stripSecretArgs(args) {
748
- const out = [];
749
- for (let i = 0; i < args.length; i++) {
750
- const arg = String(args[i]);
751
- if (AGENT_SECRET_FLAGS.has(arg.toLowerCase())) {
752
- out.push(arg);
753
- if (i + 1 < args.length) {
754
- out.push("<redacted>");
755
- i++;
756
- }
757
- continue;
758
- }
759
- const inline = arg.match(/^(--?[A-Za-z][\w-]*(?:key|token|secret|password|auth|bearer)[\w-]*)=.*/i);
760
- if (inline) {
761
- out.push(`${inline[1]}=<redacted>`);
762
- continue;
763
- }
764
- // Bare credential-looking token: a known provider prefix, or a long high-entropy
765
- // run with NO path separators (so file paths / {{...}} substitutions survive as
766
- // useful provenance). Over-redaction is safe; leaking a key is not.
767
- if (/^(sk-|ghp_|gho_|github_pat_|xox[abpr]-|Bearer\s)/.test(arg) || (arg.length >= 32 && /^[A-Za-z0-9_\-]{32,}$/.test(arg))) {
768
- out.push("<redacted>");
769
- continue;
770
- }
771
- out.push(arg);
772
- }
773
- return out;
774
- }
775
- /** Best-effort parse of the AGENT-reported model id from its stdout. SOLELY the
776
- * agent's own report — `unreported` when absent. Never CW_AGENT_MODEL. */
777
- function parseAgentReport(stdout) {
778
- const text = String(stdout || "").trim();
779
- if (!text)
780
- return {};
781
- const tryObj = (value) => {
782
- try {
783
- const parsed = JSON.parse(value);
784
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
785
- }
786
- catch {
787
- return undefined;
788
- }
789
- };
790
- let obj = tryObj(text);
791
- if (!obj) {
792
- const line = text
793
- .split(/\r?\n/)
794
- .reverse()
795
- .find((entry) => entry.trim().startsWith("{") && entry.trim().endsWith("}"));
796
- if (line)
797
- obj = tryObj(line.trim());
798
- }
799
- if (!obj)
800
- return {};
801
- const usage = obj.usage && typeof obj.usage === "object" ? obj.usage : undefined;
802
- let model = typeof obj.model === "string"
803
- ? obj.model
804
- : usage && typeof usage.model === "string"
805
- ? usage.model
806
- : typeof obj.modelId === "string"
807
- ? obj.modelId
808
- : undefined;
809
- // Some agents (e.g. `claude -p --output-format json`) report no top-level model;
810
- // the model id(s) appear as KEYS of a `modelUsage` object. Pick the primary model
811
- // (the one with the most input tokens). Still SOLELY the agent's own report.
812
- if (!model && obj.modelUsage && typeof obj.modelUsage === "object" && !Array.isArray(obj.modelUsage)) {
813
- const entries = Object.entries(obj.modelUsage);
814
- if (entries.length) {
815
- const tokensOf = (value) => {
816
- const record = value && typeof value === "object" ? value : {};
817
- const input = Number(record.inputTokens ?? record.input_tokens ?? 0);
818
- return Number.isFinite(input) ? input : 0;
819
- };
820
- entries.sort((left, right) => tokensOf(right[1]) - tokensOf(left[1]));
821
- model = entries[0][0];
822
- }
823
- }
824
- // Track 1: the executor's detached signature over its usage report, if it signs.
825
- // SOLELY the agent's own field — CW verifies it later against the trust key.
826
- const usageSignature = typeof obj.usageSignature === "string"
827
- ? obj.usageSignature
828
- : typeof obj.usage_signature === "string"
829
- ? obj.usage_signature
830
- : undefined;
831
- return { model, usage, usageSignature };
832
- }
833
- function agentSubstitutions(request, model) {
834
- const manifest = request.manifest;
835
- const workerDir = manifest?.workerDir || request.cwd || "";
836
- return {
837
- manifest: manifest?.manifestPath || (workerDir ? node_path_1.default.join(workerDir, "manifest.json") : ""),
838
- input: manifest?.inputPath || "",
839
- result: manifest?.resultPath || "",
840
- workerDir,
841
- model: model || "",
842
- prompt: manifest?.prompt || ""
843
- };
844
- }
845
- function substituteAgentArg(arg, subst) {
846
- return arg.replace(/\{\{(\w+)\}\}/g, (_, key) => (key in subst ? subst[key] : `{{${key}}}`));
847
- }
848
- /** Build the recorded process handle for the envelope — secret-stripped + the
849
- * agent-reported model. Same SHAPE that lands in provenance, never in evidence. */
850
- function recordedAgentHandle(binary, endpoint, recordedArgs, model, reportedModel, reportedUsage, usageSignature) {
851
- const ref = binary ? [binary, ...recordedArgs].join(" ") : endpoint || "";
852
- return {
853
- kind: "process",
854
- ref,
855
- endpoint,
856
- metadata: {
857
- mode: binary ? "command" : "endpoint",
858
- command: binary,
859
- args: recordedArgs,
860
- model,
861
- reportedModel,
862
- // Telemetry thread-back: the agent's OWN self-reported token usage (parsed
863
- // from its stdout by parseAgentReport). ATTESTED, never measured by CW —
864
- // same red-line posture as reportedModel. Lands in provenance, never in the
865
- // byte-stable evidence triple. Absent when the agent reported no usage.
866
- ...(reportedUsage ? { reportedUsage } : {}),
867
- // Track 1: the executor's detached signature over its usage report. CW
868
- // verifies it against the operator trust key at output intake.
869
- ...(usageSignature ? { usageSignature } : {})
870
- }
871
- };
872
- }
637
+ // ---------------------------------------------------------------------------
638
+ // agent the v0.1.38 delegating driver. Spawns an EXTERNAL agent process per
639
+ // worker (claude -p / codex exec / …) argv-style (shell:false), or POSTs the
640
+ // manifest to a configured HTTP agent endpoint. The agent reads the worker
641
+ // input/manifest and writes the worker's result.md out-of-process; CW captures
642
+ // the agent CHILD's command + exit + stdout digest as the canonical evidence
643
+ // triple (NEVER the result.md that is the separate recordWorkerOutput layer)
644
+ // and records the kind:process handle + agent-reported model in provenance.
645
+ //
646
+ // THE RED LINE: CW spawns the agent and records its attested output. It NEVER
647
+ // imports a model SDK, holds an API key, or constructs a model API request. Any
648
+ // API key flows from the agent's OWN inherited env; CW never reads or records it.
649
+ // The operator-chosen CW_AGENT_MODEL is interpolated into `{{model}}` as policy
650
+ // and recorded ONLY in secret-stripped args — it is NEVER the attested model id.
651
+ //
652
+ // The pure agent helpers (resolveAgentInvocation, stripSecretArgs, parseAgentReport,
653
+ // agentSubstitutions, substituteAgentArg, recordedAgentHandle, extractEndpointResult,
654
+ // agentHandle) and the concurrent batch live in ./execution-backend/agent.ts; the
655
+ // stateful runners below build the refusal/delegated envelopes and stay here.
873
656
  function runAgentProcess(descriptor, policy, request, label, handle, attestation) {
874
- const resolved = resolveAgentInvocation(request);
875
- const subst = agentSubstitutions(request, resolved.model);
657
+ const resolved = (0, agent_1.resolveAgentInvocation)(request);
658
+ const subst = (0, agent_1.agentSubstitutions)(request, resolved.model);
876
659
  if (resolved.binary) {
877
- const realArgs = resolved.rawArgs.map((arg) => substituteAgentArg(arg, subst));
878
- const recordedArgs = stripSecretArgs(realArgs);
660
+ const realArgs = resolved.rawArgs.map((arg) => (0, agent_1.substituteAgentArg)(arg, subst));
661
+ const recordedArgs = (0, agent_1.stripSecretArgs)(realArgs);
879
662
  // Spawn the agent argv-style — shell:false, never a shell-interpreted string.
880
663
  // The agent inherits the host env so ITS OWN credentials resolve; CW neither
881
664
  // reads nor records them. CW enforces only the exact argv it spawns.
@@ -901,22 +684,22 @@ function runAgentProcess(descriptor, policy, request, label, handle, attestation
901
684
  stdio: ["ignore", "pipe", streamStderr ? "inherit" : "pipe"]
902
685
  });
903
686
  outcome = {
904
- ...(child.error ? { spawnError: messageOf(child.error) } : {}),
687
+ ...(child.error ? { spawnError: (0, util_1.messageOf)(child.error) } : {}),
905
688
  exitCode: typeof child.status === "number" ? child.status : null,
906
689
  stdout: String(child.stdout || "")
907
690
  };
908
691
  }
909
692
  if (outcome.spawnError) {
910
- const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, "unreported");
693
+ const handleOut = (0, agent_1.recordedAgentHandle)(resolved.binary, undefined, recordedArgs, resolved.model, "unreported");
911
694
  return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent process failed to spawn: ${outcome.spawnError}`, {
912
695
  attestation: { ...attestation, handle: handleOut }
913
696
  });
914
697
  }
915
698
  const exitCode = outcome.exitCode;
916
699
  const stdout = outcome.stdout;
917
- const report = parseAgentReport(stdout);
700
+ const report = (0, agent_1.parseAgentReport)(stdout);
918
701
  const reportedModel = report.model && report.model.trim() ? report.model.trim() : "unreported";
919
- const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, reportedModel, report.usage, report.usageSignature);
702
+ const handleOut = (0, agent_1.recordedAgentHandle)(resolved.binary, undefined, recordedArgs, resolved.model, reportedModel, report.usage, report.usageSignature);
920
703
  if (exitCode === null) {
921
704
  // No exit code (timeout/killed) ⇒ fail closed, never a fabricated completion.
922
705
  return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent process returned no exit code (timed out or killed)`, {
@@ -934,94 +717,6 @@ function runAgentProcess(descriptor, policy, request, label, handle, attestation
934
717
  attestation
935
718
  });
936
719
  }
937
- /** Resolve a request to a spawn-style batch job, or undefined when the agent is
938
- * endpoint-configured/unconfigured (those settle through the serial path). */
939
- function prepareAgentSpawn(request) {
940
- const resolved = resolveAgentInvocation(request);
941
- if (!resolved.binary)
942
- return undefined;
943
- const subst = agentSubstitutions(request, resolved.model);
944
- return {
945
- binary: resolved.binary,
946
- args: resolved.rawArgs.map((arg) => substituteAgentArg(arg, subst)),
947
- cwd: request.cwd,
948
- timeoutMs: resolved.timeoutMs || 600000
949
- };
950
- }
951
- // Reads jobs JSON on stdin, spawns ALL concurrently (shell:false, inherited env —
952
- // the agent's own credentials resolve; CW never reads them), per-job SIGTERM at
953
- // timeoutMs + SIGKILL at +5s, caps each captured stdout at 32MB, and prints the
954
- // outcome array when every job has settled. stderr is drained (a full pipe must
955
- // never wedge a child). A kill yields exitCode null — the no-exit-code refusal.
956
- const BATCH_DELEGATE_CHILD = `
957
- const { spawn } = require("node:child_process");
958
- let raw = "";
959
- process.stdin.setEncoding("utf8");
960
- process.stdin.on("data", (d) => (raw += d));
961
- process.stdin.on("end", () => {
962
- const jobs = JSON.parse(raw);
963
- if (!jobs.length) { process.stdout.write("[]"); return; }
964
- const out = new Array(jobs.length);
965
- let pending = jobs.length;
966
- const CAP = 32 * 1024 * 1024;
967
- jobs.forEach((job, i) => {
968
- let stdout = "";
969
- let settled = false;
970
- const settle = (o) => {
971
- if (settled) return;
972
- settled = true;
973
- out[i] = o;
974
- if (--pending === 0) process.stdout.write(JSON.stringify(out));
975
- };
976
- let child;
977
- try {
978
- child = spawn(job.binary, job.args, { cwd: job.cwd, env: process.env, shell: false });
979
- } catch (error) {
980
- settle({ spawnError: String((error && error.message) || error), exitCode: null, stdout: "" });
981
- return;
982
- }
983
- const term = setTimeout(() => { try { child.kill("SIGTERM"); } catch {} }, job.timeoutMs);
984
- const kill = setTimeout(() => { try { child.kill("SIGKILL"); } catch {} }, job.timeoutMs + 5000);
985
- child.stdout.on("data", (d) => { if (stdout.length < CAP) stdout += d; });
986
- child.stderr.on("data", () => {});
987
- child.on("error", (error) => {
988
- clearTimeout(term); clearTimeout(kill);
989
- settle({ spawnError: String((error && error.message) || error), exitCode: null, stdout });
990
- });
991
- child.on("close", (code) => {
992
- clearTimeout(term); clearTimeout(kill);
993
- settle({ exitCode: typeof code === "number" ? code : null, stdout });
994
- });
995
- });
996
- });
997
- `;
998
- /** Run a batch of agent spawns concurrently; outcomes index-align with jobs. The
999
- * parent backstop timeout (max job timeout + 30s) means even a wedged delegate
1000
- * child cannot deadlock the drive: on any batch-level failure EVERY job settles
1001
- * as a fail-closed spawn refusal — never a fabricated completion, never a hang. */
1002
- function runAgentBatchOutcomes(jobs) {
1003
- if (!jobs.length)
1004
- return [];
1005
- const maxTimeout = Math.max(...jobs.map((job) => job.timeoutMs));
1006
- const child = (0, node_child_process_1.spawnSync)(process.execPath, ["-e", BATCH_DELEGATE_CHILD], {
1007
- input: JSON.stringify(jobs),
1008
- encoding: "utf8",
1009
- maxBuffer: 33 * 1024 * 1024 * jobs.length,
1010
- timeout: maxTimeout + 30000
1011
- });
1012
- if (!child.error && typeof child.status === "number" && child.status === 0) {
1013
- try {
1014
- const parsed = JSON.parse(String(child.stdout || ""));
1015
- if (Array.isArray(parsed) && parsed.length === jobs.length)
1016
- return parsed;
1017
- }
1018
- catch {
1019
- // fall through to the fail-closed mapping below
1020
- }
1021
- }
1022
- const reason = child.error ? messageOf(child.error) : `batch delegate exited ${child.status === null ? "without an exit code (timed out or killed)" : `with ${child.status}`}`;
1023
- return jobs.map(() => ({ spawnError: `batch delegate failed: ${reason}`, exitCode: null, stdout: "" }));
1024
- }
1025
720
  /** Agent HTTP endpoint variant — POSTs the worker manifest/prompt to a configured
1026
721
  * agent endpoint via the shared Node delegate child; if the endpoint returns a
1027
722
  * `result` body, CW writes it to the worker's result.md (the endpoint agent is the
@@ -1037,16 +732,16 @@ function runAgentEndpoint(descriptor, policy, request, label, resolved, attestat
1037
732
  resultPath: manifest?.resultPath,
1038
733
  sandboxProfileId: policy.id
1039
734
  });
1040
- const child = (0, node_child_process_1.spawnSync)(process.execPath, ["-e", HTTP_DELEGATE_CHILD], {
735
+ const child = (0, node_child_process_1.spawnSync)(process.execPath, [HTTP_DELEGATE_CHILD_SCRIPT], {
1041
736
  input: job,
1042
737
  env: { ...process.env, CW_DELEGATE_ENDPOINT: endpoint },
1043
738
  encoding: "utf8",
1044
739
  timeout: resolved.timeoutMs || 600000,
1045
740
  maxBuffer: 32 * 1024 * 1024
1046
741
  });
1047
- const baseHandle = recordedAgentHandle(undefined, endpoint, [], resolved.model, "unreported");
742
+ const baseHandle = (0, agent_1.recordedAgentHandle)(undefined, endpoint, [], resolved.model, "unreported");
1048
743
  if (child.error) {
1049
- return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent endpoint delegation failed: ${messageOf(child.error)}`, {
744
+ return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent endpoint delegation failed: ${(0, util_1.messageOf)(child.error)}`, {
1050
745
  attestation: { ...attestation, handle: baseHandle }
1051
746
  });
1052
747
  }
@@ -1067,9 +762,9 @@ function runAgentEndpoint(descriptor, policy, request, label, resolved, attestat
1067
762
  const stdout = String(parsed.stdout || "");
1068
763
  // If the endpoint agent returned the result body, CW (as transport) writes it to
1069
764
  // the worker's result.md for the separate recordWorkerOutput layer to accept.
1070
- const report = parseAgentReport(stdout);
765
+ const report = (0, agent_1.parseAgentReport)(stdout);
1071
766
  if (manifest?.resultPath && report.usage === undefined) {
1072
- const body = extractEndpointResult(stdout);
767
+ const body = (0, agent_1.extractEndpointResult)(stdout);
1073
768
  if (body && !node_fs_1.default.existsSync(manifest.resultPath)) {
1074
769
  try {
1075
770
  node_fs_1.default.writeFileSync(manifest.resultPath, body, "utf8");
@@ -1080,28 +775,9 @@ function runAgentEndpoint(descriptor, policy, request, label, resolved, attestat
1080
775
  }
1081
776
  }
1082
777
  const reportedModel = report.model && report.model.trim() ? report.model.trim() : "unreported";
1083
- const handleOut = recordedAgentHandle(undefined, endpoint, [], resolved.model, reportedModel, report.usage, report.usageSignature);
778
+ const handleOut = (0, agent_1.recordedAgentHandle)(undefined, endpoint, [], resolved.model, reportedModel, report.usage, report.usageSignature);
1084
779
  return delegatedEnvelope(descriptor, label, handleOut, { ...attestation, handle: handleOut }, "agent-endpoint", [endpoint], parsed.exitCode, stdout);
1085
780
  }
1086
- function extractEndpointResult(stdout) {
1087
- const text = String(stdout || "").trim();
1088
- if (!text)
1089
- return undefined;
1090
- try {
1091
- const parsed = JSON.parse(text);
1092
- if (parsed && typeof parsed === "object") {
1093
- if (typeof parsed.result === "string")
1094
- return parsed.result;
1095
- if (typeof parsed.resultMarkdown === "string")
1096
- return parsed.resultMarkdown;
1097
- }
1098
- }
1099
- catch {
1100
- /* not JSON — treat the raw text as the result body */
1101
- return text;
1102
- }
1103
- return undefined;
1104
- }
1105
781
  function delegationHandle(descriptor, request) {
1106
782
  return getBackendDriver(descriptor.id)?.buildHandle?.(request);
1107
783
  }
@@ -1132,28 +808,6 @@ function ciHandle(request) {
1132
808
  const ref = endpoint && jobId ? `${endpoint}#${jobId}` : jobId || endpoint || "";
1133
809
  return { kind: "ci", ref, endpoint, jobId };
1134
810
  }
1135
- function agentHandle(request) {
1136
- // The agent invocation is POLICY-as-DATA, resolved flags(delegation) > env. The
1137
- // handle records ONLY secret-stripped provenance; the raw template is re-resolved
1138
- // inside runAgentProcess for substitution + spawning so no secret ever lands in
1139
- // a recorded handle/evidence entry.
1140
- const resolved = resolveAgentInvocation(request);
1141
- if (!resolved.binary && !resolved.endpoint)
1142
- return undefined;
1143
- const strippedArgs = stripSecretArgs(resolved.rawArgs);
1144
- const ref = resolved.binary ? [resolved.binary, ...strippedArgs].join(" ") : resolved.endpoint || "";
1145
- return {
1146
- kind: "process",
1147
- ref,
1148
- endpoint: resolved.endpoint,
1149
- metadata: {
1150
- mode: resolved.binary ? "command" : "endpoint",
1151
- command: resolved.binary,
1152
- args: strippedArgs,
1153
- model: resolved.model
1154
- }
1155
- };
1156
- }
1157
811
  function refusedEnvelope(descriptor, policy, label, code, reason, options = {}) {
1158
812
  const attestation = options.attestation
1159
813
  ? { ...options.attestation, status: "refused", notes: [...(options.attestation.notes || []), `refused: ${code}`] }
@@ -1242,33 +896,6 @@ function commandDenied(policy, command) {
1242
896
  function runtimeNote(descriptor) {
1243
897
  return getBackendDriver(descriptor.id)?.runtimeNote?.() ?? "node";
1244
898
  }
1245
- function hasExecutable(name) {
1246
- const dirs = (process.env.PATH || "").split(node_path_1.default.delimiter).filter(Boolean);
1247
- for (const dir of dirs) {
1248
- const candidate = node_path_1.default.join(dir, name);
1249
- try {
1250
- if (node_fs_1.default.existsSync(candidate) && node_fs_1.default.statSync(candidate).isFile())
1251
- return true;
1252
- }
1253
- catch {
1254
- // ignore unreadable PATH entries
1255
- }
1256
- }
1257
- return false;
1258
- }
1259
- function sha256(value) {
1260
- return `sha256:${node_crypto_1.default.createHash("sha256").update(value, "utf8").digest("hex")}`;
1261
- }
1262
- function firstString(...values) {
1263
- for (const value of values) {
1264
- if (typeof value === "string" && value.trim())
1265
- return value.trim();
1266
- }
1267
- return undefined;
1268
- }
1269
- function messageOf(error) {
1270
- return error instanceof Error ? error.message : String(error);
1271
- }
1272
899
  // ---- Probe cache (v0.1.60) — mechanism, not policy -----------------------
1273
900
  const _probeCache = new Map();
1274
901
  const PROBE_CACHE_TTL_MS = 60_000; // 60s