cool-workflow 0.1.80 → 0.1.81
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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +42 -2
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/agent-config.js +21 -7
- package/dist/candidate-scoring.js +42 -22
- package/dist/capability-core.js +94 -17
- package/dist/capability-registry.js +138 -171
- package/dist/cli.js +90 -100
- package/dist/collaboration.js +5 -6
- package/dist/commit.js +20 -6
- package/dist/compare.js +18 -0
- package/dist/coordinator/classify.js +45 -0
- package/dist/coordinator/paths.js +42 -0
- package/dist/coordinator/util.js +129 -0
- package/dist/coordinator.js +127 -300
- package/dist/dispatch.js +35 -0
- package/dist/drive.js +7 -7
- package/dist/error-feedback.js +8 -4
- package/dist/evidence-reasoning.js +1 -1
- package/dist/execution-backend/agent.js +331 -0
- package/dist/execution-backend/probes.js +96 -0
- package/dist/execution-backend/util.js +47 -0
- package/dist/execution-backend.js +67 -420
- package/dist/mcp-server.js +34 -173
- package/dist/multi-agent/graph.js +84 -0
- package/dist/multi-agent/helpers.js +145 -0
- package/dist/multi-agent/paths.js +22 -0
- package/dist/multi-agent-eval/format.js +194 -0
- package/dist/multi-agent-eval/normalize.js +51 -0
- package/dist/multi-agent-eval.js +39 -244
- package/dist/multi-agent-host.js +0 -19
- package/dist/multi-agent.js +125 -314
- package/dist/node-snapshot.js +3 -3
- package/dist/observability/format.js +61 -0
- package/dist/observability/intake.js +98 -0
- package/dist/observability.js +14 -160
- package/dist/operator-ux/format.js +364 -0
- package/dist/operator-ux.js +22 -363
- package/dist/orchestrator/report.js +8 -0
- package/dist/orchestrator.js +25 -8
- package/dist/reclamation.js +26 -21
- package/dist/run-export.js +138 -14
- package/dist/run-registry/derive.js +172 -0
- package/dist/run-registry/format.js +124 -0
- package/dist/run-registry/gc.js +251 -0
- package/dist/run-registry/policy.js +16 -0
- package/dist/run-registry/queue.js +116 -0
- package/dist/run-registry.js +78 -593
- package/dist/run-state-schema.js +1 -0
- package/dist/sandbox-profile.js +43 -2
- package/dist/state-explosion/format.js +159 -0
- package/dist/state-explosion/helpers.js +82 -0
- package/dist/state-explosion.js +65 -283
- package/dist/state-node.js +19 -4
- package/dist/telemetry-attestation.js +55 -0
- package/dist/telemetry-demo.js +15 -3
- package/dist/telemetry-ledger.js +60 -15
- package/dist/topology.js +25 -8
- package/dist/triggers.js +33 -14
- package/dist/trust-audit.js +145 -33
- package/dist/version.js +1 -1
- package/dist/worker-isolation/helpers.js +51 -0
- package/dist/worker-isolation/paths.js +46 -0
- package/dist/worker-isolation.js +39 -115
- package/docs/agent-delegation-drive.7.md +13 -0
- package/docs/cli-mcp-parity.7.md +4 -0
- package/docs/contract-migration-tooling.7.md +2 -0
- package/docs/control-plane-scheduling.7.md +2 -0
- package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
- package/docs/execution-backends.7.md +2 -0
- package/docs/index.md +1 -0
- package/docs/launch/launch-kit.md +46 -23
- package/docs/launch/pre-launch-checklist.md +14 -14
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +2 -0
- package/docs/multi-agent-operator-ux.7.md +2 -0
- package/docs/multi-agent-trust-policy-audit.7.md +27 -0
- package/docs/node-snapshot-diff-replay.7.md +2 -0
- package/docs/observability-cost-accounting.7.md +2 -0
- package/docs/project-index.md +18 -5
- package/docs/real-execution-backends.7.md +2 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +2 -0
- package/docs/run-registry-control-plane.7.md +54 -8
- package/docs/run-retention-reclamation.7.md +4 -0
- package/docs/state-explosion-management.7.md +2 -0
- package/docs/team-collaboration.7.md +2 -0
- package/docs/trust-model.md +267 -0
- package/docs/vendor-manifest-loadability.7.md +43 -0
- package/docs/web-desktop-workbench.7.md +2 -0
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +4 -2
- package/scripts/agents/builtin-templates.json +7 -0
- package/scripts/bump-version.js +5 -11
- package/scripts/canonical-apps-list.js +64 -0
- package/scripts/canonical-apps.js +19 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/parity-check.js +5 -0
- package/scripts/release-check.js +5 -1
- package/scripts/version-sync-check.js +5 -8
- 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,32 @@ 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
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
56
50
|
const node_child_process_1 = require("node:child_process");
|
|
51
|
+
// Pure leaf helpers — carved into ./execution-backend/util.ts (god-module carve).
|
|
52
|
+
// `sha256` is re-exported below to keep the public surface byte-identical.
|
|
53
|
+
const util_1 = require("./execution-backend/util");
|
|
54
|
+
// Per-backend readiness probe bodies — carved into ./execution-backend/probes.ts.
|
|
55
|
+
const probes_1 = require("./execution-backend/probes");
|
|
56
|
+
// Agent-delegation pure helpers + concurrent batch — carved into
|
|
57
|
+
// ./execution-backend/agent.ts. The public symbols (stripSecretArgs,
|
|
58
|
+
// AgentSpawnJob, prepareAgentSpawn, runAgentBatchOutcomes) are re-exported below.
|
|
59
|
+
const agent_1 = require("./execution-backend/agent");
|
|
60
|
+
// Re-export the carved public surface so every importer of "./execution-backend"
|
|
61
|
+
// is byte-unchanged (no public signature changed; pure code movement).
|
|
62
|
+
var util_2 = require("./execution-backend/util");
|
|
63
|
+
Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return util_2.sha256; } });
|
|
64
|
+
var agent_2 = require("./execution-backend/agent");
|
|
65
|
+
Object.defineProperty(exports, "stripSecretArgs", { enumerable: true, get: function () { return agent_2.stripSecretArgs; } });
|
|
66
|
+
Object.defineProperty(exports, "prepareAgentSpawn", { enumerable: true, get: function () { return agent_2.prepareAgentSpawn; } });
|
|
67
|
+
Object.defineProperty(exports, "runAgentBatchOutcomes", { enumerable: true, get: function () { return agent_2.runAgentBatchOutcomes; } });
|
|
57
68
|
exports.EXECUTION_BACKEND_SCHEMA_VERSION = 1;
|
|
58
69
|
exports.DEFAULT_BACKEND_ID = "node";
|
|
59
70
|
exports.SANDBOX_DIMENSIONS = ["read", "write", "command", "network", "env"];
|
|
@@ -204,21 +215,21 @@ function getBackendDescriptor(id) {
|
|
|
204
215
|
// — no central switch to edit. Function declarations below are hoisted, so the
|
|
205
216
|
// closures resolve at call time.
|
|
206
217
|
const BUILTIN_DRIVER_BEHAVIORS = {
|
|
207
|
-
node: { spawnStyle: "direct", runtimeNote: () => "node", probe: probeNodeBackend },
|
|
218
|
+
node: { spawnStyle: "direct", runtimeNote: () => "node", probe: probes_1.probeNodeBackend },
|
|
208
219
|
bun: {
|
|
209
220
|
spawnStyle: "direct",
|
|
210
|
-
runtimeNote: () => (hasExecutable("bun") ? "bun (node-compatible execution)" : "node-compatible (bun not installed)"),
|
|
211
|
-
probe: probeBunBackend
|
|
221
|
+
runtimeNote: () => ((0, util_1.hasExecutable)("bun") ? "bun (node-compatible execution)" : "node-compatible (bun not installed)"),
|
|
222
|
+
probe: probes_1.probeBunBackend
|
|
212
223
|
},
|
|
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 },
|
|
224
|
+
shell: { spawnStyle: "shell", runtimeNote: () => "posix-shell", probe: probes_1.probeShellBackend },
|
|
225
|
+
container: { delegateRun: ctxDelegate(runContainer), buildHandle: containerHandle, probe: probes_1.probeContainerBackend },
|
|
226
|
+
remote: { delegateRun: ctxDelegate(runHttpDelegation), buildHandle: remoteHandle, probe: probes_1.probeRemoteBackend },
|
|
227
|
+
ci: { delegateRun: ctxDelegate(runHttpDelegation), buildHandle: ciHandle, probe: probes_1.probeCiBackend },
|
|
217
228
|
agent: {
|
|
218
229
|
delegateRun: ctxDelegate(runAgentProcess),
|
|
219
|
-
buildHandle: agentHandle,
|
|
230
|
+
buildHandle: agent_1.agentHandle,
|
|
220
231
|
commandlessDelegate: true,
|
|
221
|
-
probe: probeAgentBackend
|
|
232
|
+
probe: probes_1.probeAgentBackend
|
|
222
233
|
}
|
|
223
234
|
};
|
|
224
235
|
for (const spec of DRIVER_SPECS) {
|
|
@@ -254,7 +265,7 @@ function resolveBackendSelection(requested, env = process.env) {
|
|
|
254
265
|
return { backendId: exports.DEFAULT_BACKEND_ID, source: "default" };
|
|
255
266
|
}
|
|
256
267
|
function backendSelectionFrom(args, env = process.env) {
|
|
257
|
-
const requested = firstString(args.backend, args.backendId, args.executionBackend);
|
|
268
|
+
const requested = (0, util_1.firstString)(args.backend, args.backendId, args.executionBackend);
|
|
258
269
|
return resolveBackendSelection(requested, env);
|
|
259
270
|
}
|
|
260
271
|
// ---------------------------------------------------------------------------
|
|
@@ -340,77 +351,6 @@ function probeBackend(id, context = {}) {
|
|
|
340
351
|
reason: body.reason
|
|
341
352
|
};
|
|
342
353
|
}
|
|
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
354
|
// ---------------------------------------------------------------------------
|
|
415
355
|
// The run entry. Refuses (fail closed) when the sandbox cannot be honored, the
|
|
416
356
|
// command is denied by policy, or the backend is not ready. Local drivers spawn a
|
|
@@ -474,9 +414,9 @@ function executeLocal(descriptor, policy, request, label, attestation) {
|
|
|
474
414
|
? (0, node_child_process_1.spawnSync)([command, ...args].join(" "), { ...options, shell: true })
|
|
475
415
|
: (0, node_child_process_1.spawnSync)(command, args, { ...options, shell: false });
|
|
476
416
|
const exitCode = typeof result.status === "number" ? result.status : null;
|
|
477
|
-
const spawnError = result.error ? messageOf(result.error) : undefined;
|
|
417
|
+
const spawnError = result.error ? (0, util_1.messageOf)(result.error) : undefined;
|
|
478
418
|
const stdout = String(result.stdout || "");
|
|
479
|
-
const digest = sha256(stdout);
|
|
419
|
+
const digest = (0, util_1.sha256)(stdout);
|
|
480
420
|
const status = spawnError ? "failed" : exitCode === 0 ? "completed" : "failed";
|
|
481
421
|
const evidence = [
|
|
482
422
|
`command:${[command, ...args].join(" ")}`,
|
|
@@ -502,7 +442,7 @@ function executeLocal(descriptor, policy, request, label, attestation) {
|
|
|
502
442
|
backendId: descriptor.id,
|
|
503
443
|
locality: descriptor.locality,
|
|
504
444
|
kind: descriptor.kind,
|
|
505
|
-
attestation: { ...attestation, status:
|
|
445
|
+
attestation: { ...attestation, status: attestation.status, notes }
|
|
506
446
|
}
|
|
507
447
|
};
|
|
508
448
|
}
|
|
@@ -544,7 +484,7 @@ function delegate(descriptor, policy, request, label, probe) {
|
|
|
544
484
|
* identical to executeLocal's, so evidence is byte-stable across backends. The
|
|
545
485
|
* handle is recorded in provenance only. */
|
|
546
486
|
function delegatedEnvelope(descriptor, label, handle, attestation, command, args, exitCode, stdout) {
|
|
547
|
-
const digest = sha256(stdout);
|
|
487
|
+
const digest = (0, util_1.sha256)(stdout);
|
|
548
488
|
const status = exitCode === 0 ? "completed" : "failed";
|
|
549
489
|
const evidence = [
|
|
550
490
|
`command:${[command, ...args].join(" ")}`,
|
|
@@ -573,7 +513,7 @@ function delegatedEnvelope(descriptor, label, handle, attestation, command, args
|
|
|
573
513
|
* closed when no runtime is on PATH, the daemon is unreachable, or the runtime
|
|
574
514
|
* itself errors (exit 125) — distinct from the command's own non-zero exit. */
|
|
575
515
|
function runContainer(descriptor, policy, request, label, handle, attestation) {
|
|
576
|
-
const runtime = hasExecutable("docker") ? "docker" : hasExecutable("podman") ? "podman" : undefined;
|
|
516
|
+
const runtime = (0, util_1.hasExecutable)("docker") ? "docker" : (0, util_1.hasExecutable)("podman") ? "podman" : undefined;
|
|
577
517
|
if (!runtime) {
|
|
578
518
|
return refusedEnvelope(descriptor, policy, label, "runtime-unavailable", "no container runtime (docker/podman) on PATH", {
|
|
579
519
|
attestation
|
|
@@ -622,7 +562,7 @@ function runContainer(descriptor, policy, request, label, handle, attestation) {
|
|
|
622
562
|
maxBuffer: 32 * 1024 * 1024
|
|
623
563
|
});
|
|
624
564
|
if (result.error) {
|
|
625
|
-
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${runtime} run failed: ${messageOf(result.error)}`, {
|
|
565
|
+
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${runtime} run failed: ${(0, util_1.messageOf)(result.error)}`, {
|
|
626
566
|
attestation
|
|
627
567
|
});
|
|
628
568
|
}
|
|
@@ -696,7 +636,7 @@ function runHttpDelegation(descriptor, policy, request, label, handle, attestati
|
|
|
696
636
|
maxBuffer: 32 * 1024 * 1024
|
|
697
637
|
});
|
|
698
638
|
if (child.error) {
|
|
699
|
-
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${descriptor.id} delegation failed: ${messageOf(child.error)}`, {
|
|
639
|
+
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `${descriptor.id} delegation failed: ${(0, util_1.messageOf)(child.error)}`, {
|
|
700
640
|
attestation
|
|
701
641
|
});
|
|
702
642
|
}
|
|
@@ -714,168 +654,31 @@ function runHttpDelegation(descriptor, policy, request, label, handle, attestati
|
|
|
714
654
|
}
|
|
715
655
|
return delegatedEnvelope(descriptor, label, handle, attestation, command, args, parsed.exitCode, String(parsed.stdout || ""));
|
|
716
656
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
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
|
-
}
|
|
657
|
+
// ---------------------------------------------------------------------------
|
|
658
|
+
// agent — the v0.1.38 delegating driver. Spawns an EXTERNAL agent process per
|
|
659
|
+
// worker (claude -p / codex exec / …) argv-style (shell:false), or POSTs the
|
|
660
|
+
// manifest to a configured HTTP agent endpoint. The agent reads the worker
|
|
661
|
+
// input/manifest and writes the worker's result.md out-of-process; CW captures
|
|
662
|
+
// the agent CHILD's command + exit + stdout digest as the canonical evidence
|
|
663
|
+
// triple (NEVER the result.md — that is the separate recordWorkerOutput layer)
|
|
664
|
+
// and records the kind:process handle + agent-reported model in provenance.
|
|
665
|
+
//
|
|
666
|
+
// THE RED LINE: CW spawns the agent and records its attested output. It NEVER
|
|
667
|
+
// imports a model SDK, holds an API key, or constructs a model API request. Any
|
|
668
|
+
// API key flows from the agent's OWN inherited env; CW never reads or records it.
|
|
669
|
+
// The operator-chosen CW_AGENT_MODEL is interpolated into `{{model}}` as policy
|
|
670
|
+
// and recorded ONLY in secret-stripped args — it is NEVER the attested model id.
|
|
671
|
+
//
|
|
672
|
+
// The pure agent helpers (resolveAgentInvocation, stripSecretArgs, parseAgentReport,
|
|
673
|
+
// agentSubstitutions, substituteAgentArg, recordedAgentHandle, extractEndpointResult,
|
|
674
|
+
// agentHandle) and the concurrent batch live in ./execution-backend/agent.ts; the
|
|
675
|
+
// stateful runners below build the refusal/delegated envelopes and stay here.
|
|
873
676
|
function runAgentProcess(descriptor, policy, request, label, handle, attestation) {
|
|
874
|
-
const resolved = resolveAgentInvocation(request);
|
|
875
|
-
const subst = agentSubstitutions(request, resolved.model);
|
|
677
|
+
const resolved = (0, agent_1.resolveAgentInvocation)(request);
|
|
678
|
+
const subst = (0, agent_1.agentSubstitutions)(request, resolved.model);
|
|
876
679
|
if (resolved.binary) {
|
|
877
|
-
const realArgs = resolved.rawArgs.map((arg) => substituteAgentArg(arg, subst));
|
|
878
|
-
const recordedArgs = stripSecretArgs(realArgs);
|
|
680
|
+
const realArgs = resolved.rawArgs.map((arg) => (0, agent_1.substituteAgentArg)(arg, subst));
|
|
681
|
+
const recordedArgs = (0, agent_1.stripSecretArgs)(realArgs);
|
|
879
682
|
// Spawn the agent argv-style — shell:false, never a shell-interpreted string.
|
|
880
683
|
// The agent inherits the host env so ITS OWN credentials resolve; CW neither
|
|
881
684
|
// reads nor records them. CW enforces only the exact argv it spawns.
|
|
@@ -901,22 +704,22 @@ function runAgentProcess(descriptor, policy, request, label, handle, attestation
|
|
|
901
704
|
stdio: ["ignore", "pipe", streamStderr ? "inherit" : "pipe"]
|
|
902
705
|
});
|
|
903
706
|
outcome = {
|
|
904
|
-
...(child.error ? { spawnError: messageOf(child.error) } : {}),
|
|
707
|
+
...(child.error ? { spawnError: (0, util_1.messageOf)(child.error) } : {}),
|
|
905
708
|
exitCode: typeof child.status === "number" ? child.status : null,
|
|
906
709
|
stdout: String(child.stdout || "")
|
|
907
710
|
};
|
|
908
711
|
}
|
|
909
712
|
if (outcome.spawnError) {
|
|
910
|
-
const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, "unreported");
|
|
713
|
+
const handleOut = (0, agent_1.recordedAgentHandle)(resolved.binary, undefined, recordedArgs, resolved.model, "unreported");
|
|
911
714
|
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent process failed to spawn: ${outcome.spawnError}`, {
|
|
912
715
|
attestation: { ...attestation, handle: handleOut }
|
|
913
716
|
});
|
|
914
717
|
}
|
|
915
718
|
const exitCode = outcome.exitCode;
|
|
916
719
|
const stdout = outcome.stdout;
|
|
917
|
-
const report = parseAgentReport(stdout);
|
|
720
|
+
const report = (0, agent_1.parseAgentReport)(stdout);
|
|
918
721
|
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);
|
|
722
|
+
const handleOut = (0, agent_1.recordedAgentHandle)(resolved.binary, undefined, recordedArgs, resolved.model, reportedModel, report.usage, report.usageSignature);
|
|
920
723
|
if (exitCode === null) {
|
|
921
724
|
// No exit code (timeout/killed) ⇒ fail closed, never a fabricated completion.
|
|
922
725
|
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent process returned no exit code (timed out or killed)`, {
|
|
@@ -934,94 +737,6 @@ function runAgentProcess(descriptor, policy, request, label, handle, attestation
|
|
|
934
737
|
attestation
|
|
935
738
|
});
|
|
936
739
|
}
|
|
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
740
|
/** Agent HTTP endpoint variant — POSTs the worker manifest/prompt to a configured
|
|
1026
741
|
* agent endpoint via the shared Node delegate child; if the endpoint returns a
|
|
1027
742
|
* `result` body, CW writes it to the worker's result.md (the endpoint agent is the
|
|
@@ -1044,9 +759,9 @@ function runAgentEndpoint(descriptor, policy, request, label, resolved, attestat
|
|
|
1044
759
|
timeout: resolved.timeoutMs || 600000,
|
|
1045
760
|
maxBuffer: 32 * 1024 * 1024
|
|
1046
761
|
});
|
|
1047
|
-
const baseHandle = recordedAgentHandle(undefined, endpoint, [], resolved.model, "unreported");
|
|
762
|
+
const baseHandle = (0, agent_1.recordedAgentHandle)(undefined, endpoint, [], resolved.model, "unreported");
|
|
1048
763
|
if (child.error) {
|
|
1049
|
-
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent endpoint delegation failed: ${messageOf(child.error)}`, {
|
|
764
|
+
return refusedEnvelope(descriptor, policy, label, "delegation-failed", `agent endpoint delegation failed: ${(0, util_1.messageOf)(child.error)}`, {
|
|
1050
765
|
attestation: { ...attestation, handle: baseHandle }
|
|
1051
766
|
});
|
|
1052
767
|
}
|
|
@@ -1067,9 +782,9 @@ function runAgentEndpoint(descriptor, policy, request, label, resolved, attestat
|
|
|
1067
782
|
const stdout = String(parsed.stdout || "");
|
|
1068
783
|
// If the endpoint agent returned the result body, CW (as transport) writes it to
|
|
1069
784
|
// the worker's result.md for the separate recordWorkerOutput layer to accept.
|
|
1070
|
-
const report = parseAgentReport(stdout);
|
|
785
|
+
const report = (0, agent_1.parseAgentReport)(stdout);
|
|
1071
786
|
if (manifest?.resultPath && report.usage === undefined) {
|
|
1072
|
-
const body = extractEndpointResult(stdout);
|
|
787
|
+
const body = (0, agent_1.extractEndpointResult)(stdout);
|
|
1073
788
|
if (body && !node_fs_1.default.existsSync(manifest.resultPath)) {
|
|
1074
789
|
try {
|
|
1075
790
|
node_fs_1.default.writeFileSync(manifest.resultPath, body, "utf8");
|
|
@@ -1080,28 +795,9 @@ function runAgentEndpoint(descriptor, policy, request, label, resolved, attestat
|
|
|
1080
795
|
}
|
|
1081
796
|
}
|
|
1082
797
|
const reportedModel = report.model && report.model.trim() ? report.model.trim() : "unreported";
|
|
1083
|
-
const handleOut = recordedAgentHandle(undefined, endpoint, [], resolved.model, reportedModel, report.usage, report.usageSignature);
|
|
798
|
+
const handleOut = (0, agent_1.recordedAgentHandle)(undefined, endpoint, [], resolved.model, reportedModel, report.usage, report.usageSignature);
|
|
1084
799
|
return delegatedEnvelope(descriptor, label, handleOut, { ...attestation, handle: handleOut }, "agent-endpoint", [endpoint], parsed.exitCode, stdout);
|
|
1085
800
|
}
|
|
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
801
|
function delegationHandle(descriptor, request) {
|
|
1106
802
|
return getBackendDriver(descriptor.id)?.buildHandle?.(request);
|
|
1107
803
|
}
|
|
@@ -1132,28 +828,6 @@ function ciHandle(request) {
|
|
|
1132
828
|
const ref = endpoint && jobId ? `${endpoint}#${jobId}` : jobId || endpoint || "";
|
|
1133
829
|
return { kind: "ci", ref, endpoint, jobId };
|
|
1134
830
|
}
|
|
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
831
|
function refusedEnvelope(descriptor, policy, label, code, reason, options = {}) {
|
|
1158
832
|
const attestation = options.attestation
|
|
1159
833
|
? { ...options.attestation, status: "refused", notes: [...(options.attestation.notes || []), `refused: ${code}`] }
|
|
@@ -1242,33 +916,6 @@ function commandDenied(policy, command) {
|
|
|
1242
916
|
function runtimeNote(descriptor) {
|
|
1243
917
|
return getBackendDriver(descriptor.id)?.runtimeNote?.() ?? "node";
|
|
1244
918
|
}
|
|
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
919
|
// ---- Probe cache (v0.1.60) — mechanism, not policy -----------------------
|
|
1273
920
|
const _probeCache = new Map();
|
|
1274
921
|
const PROBE_CACHE_TTL_MS = 60_000; // 60s
|