cool-workflow 0.1.97 → 0.2.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +11 -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/cli/dispatch.js +236 -0
- package/dist/cli/entry.js +120 -0
- package/dist/cli/io.js +21 -4
- package/dist/cli/parseargv.js +157 -0
- package/dist/cli.js +6 -33
- package/dist/core/capability-table.js +3534 -0
- package/dist/core/format/help.js +314 -0
- package/dist/{state-explosion/format.js → core/format/state-explosion-text.js} +10 -1
- package/dist/core/hash.js +137 -0
- package/dist/core/multi-agent/candidate-scoring.js +219 -0
- package/dist/core/multi-agent/collaboration.js +481 -0
- package/dist/core/multi-agent/coordinator.js +515 -0
- package/dist/core/multi-agent/eval-replay.js +306 -0
- package/dist/core/multi-agent/runtime.js +929 -0
- package/dist/core/multi-agent/topology.js +298 -0
- package/dist/core/multi-agent/trust-policy.js +197 -0
- package/dist/core/pipeline/commit-gate.js +320 -0
- package/dist/{pipeline-contract.js → core/pipeline/contract.js} +24 -37
- package/dist/core/pipeline/dispatch.js +103 -0
- package/dist/core/pipeline/drive-decide.js +227 -0
- package/dist/core/pipeline/error-feedback.js +161 -0
- package/dist/core/pipeline/loop-expansion.js +124 -0
- package/dist/{result-normalize.js → core/pipeline/result-normalize.js} +14 -37
- package/dist/core/pipeline/runner.js +230 -0
- package/dist/{contract-migration.js → core/state/contract-migration.js} +68 -92
- package/dist/{state-migrations.js → core/state/migrations.js} +103 -96
- package/dist/core/state/node-projection.js +95 -0
- package/dist/core/state/node-snapshot.js +230 -0
- package/dist/core/state/run-paths.js +93 -0
- package/dist/{schema-validate.js → core/state/schema-validate.js} +35 -28
- package/dist/core/state/schema.js +50 -0
- package/dist/core/state/state-explosion/digest.js +243 -0
- package/dist/core/state/state-explosion/graph.js +527 -0
- package/dist/{state-explosion → core/state/state-explosion}/helpers.js +34 -3
- package/dist/core/state/state-explosion/report.js +187 -0
- package/dist/{state-explosion → core/state/state-explosion}/size.js +25 -7
- package/dist/{state-node.js → core/state/state-node.js} +90 -113
- package/dist/core/state/types.js +19 -0
- package/dist/{validation.js → core/state/validation.js} +64 -131
- package/dist/core/trust/evidence-grounding.js +134 -0
- package/dist/core/trust/ledger.js +199 -0
- package/dist/{telemetry-attestation.js → core/trust/telemetry-attestation.js} +94 -68
- package/dist/core/trust/telemetry-ledger.js +127 -0
- package/dist/core/types.js +20 -0
- package/dist/core/version.js +16 -0
- package/dist/{workflow-app-framework.js → core/workflow-apps/app-schema.js} +337 -426
- package/dist/mcp/dispatch.js +104 -0
- package/dist/mcp/server.js +144 -0
- package/dist/mcp-server.js +6 -84
- package/dist/{agent-config.js → shell/agent-config.js} +118 -71
- package/dist/shell/app-run-cli.js +88 -0
- package/dist/shell/audit-cli.js +259 -0
- package/dist/shell/audit-provenance.js +83 -0
- package/dist/shell/candidate-scoring-io.js +459 -0
- package/dist/shell/collaboration-io.js +264 -0
- package/dist/shell/commit-summary.js +104 -0
- package/dist/shell/commit.js +290 -0
- package/dist/shell/coordinator-io.js +476 -0
- package/dist/shell/demo-cli.js +19 -0
- package/dist/shell/dispatch.js +162 -0
- package/dist/{doctor.js → shell/doctor.js} +123 -56
- package/dist/shell/drive.js +873 -0
- package/dist/shell/error-feedback-io.js +305 -0
- package/dist/shell/eval-io.js +473 -0
- package/dist/{multi-agent-eval/format.js → shell/eval-text.js} +78 -49
- package/dist/{evidence-reasoning.js → shell/evidence-reasoning.js} +124 -255
- package/dist/shell/exec-backend-cli.js +88 -0
- package/dist/shell/execution-backend/agent.js +475 -0
- package/dist/shell/execution-backend/ci.js +15 -0
- package/dist/shell/execution-backend/container.js +69 -0
- package/dist/shell/execution-backend/envelopes.js +55 -0
- package/dist/shell/execution-backend/local.js +113 -0
- package/dist/shell/execution-backend/probes.js +175 -0
- package/dist/shell/execution-backend/registry.js +402 -0
- package/dist/shell/execution-backend/remote.js +128 -0
- package/dist/shell/execution-backend/types.js +11 -0
- package/dist/shell/feedback-cli.js +81 -0
- package/dist/shell/feedback-operations.js +48 -0
- package/dist/shell/fs-atomic.js +276 -0
- package/dist/shell/harness.js +98 -0
- package/dist/shell/ledger-cli.js +212 -0
- package/dist/shell/ledger-io.js +169 -0
- package/dist/shell/man-cli.js +89 -0
- package/dist/shell/metrics-cli.js +98 -0
- package/dist/shell/multi-agent-cli.js +1002 -0
- package/dist/shell/multi-agent-host.js +563 -0
- package/dist/shell/multi-agent-io.js +387 -0
- package/dist/{multi-agent-operator-ux.js → shell/multi-agent-operator-ux.js} +234 -191
- package/dist/shell/node-store.js +124 -0
- package/dist/{observability/format.js → shell/observability-format.js} +7 -1
- package/dist/{observability/intake.js → shell/observability-intake.js} +79 -56
- package/dist/{observability.js → shell/observability.js} +159 -332
- package/dist/{onramp.js → shell/onramp.js} +11 -0
- package/dist/{operator-ux/format.js → shell/operator-ux-text.js} +250 -239
- package/dist/shell/operator-ux.js +431 -0
- package/dist/shell/orchestrator.js +231 -0
- package/dist/shell/pipeline-cli.js +667 -0
- package/dist/shell/pipeline.js +217 -0
- package/dist/shell/reclamation-io.js +1366 -0
- package/dist/shell/registry-cli.js +329 -0
- package/dist/{remote-source.js → shell/remote-source.js} +12 -5
- package/dist/shell/report-cli.js +101 -0
- package/dist/shell/report-view-cli.js +117 -0
- package/dist/{orchestrator → shell}/report.js +289 -282
- package/dist/shell/reporter.js +62 -0
- package/dist/shell/run-export-cli.js +106 -0
- package/dist/shell/run-export.js +680 -0
- package/dist/shell/run-registry-io.js +1014 -0
- package/dist/shell/run-store.js +164 -0
- package/dist/{sandbox-profile.js → shell/sandbox-profile.js} +134 -95
- package/dist/{scheduler.js → shell/scheduler-io.js} +248 -48
- package/dist/shell/scheduling-io.js +311 -0
- package/dist/shell/state-cli.js +181 -0
- package/dist/shell/state-explosion-cli.js +197 -0
- package/dist/shell/telemetry-cli.js +85 -0
- package/dist/{telemetry-demo.js → shell/telemetry-demo.js} +149 -119
- package/dist/shell/telemetry-ledger-io.js +132 -0
- package/dist/{term.js → shell/term.js} +36 -46
- package/dist/shell/topology-io.js +361 -0
- package/dist/shell/trust-audit.js +471 -0
- package/dist/{multi-agent-trust.js → shell/trust-policy-io.js} +67 -205
- package/dist/shell/verifier.js +48 -0
- package/dist/shell/workbench-host.js +250 -0
- package/dist/shell/workbench-text.js +18 -0
- package/dist/shell/workbench.js +175 -0
- package/dist/shell/worker-cli.js +124 -0
- package/dist/shell/worker-isolation.js +852 -0
- package/dist/shell/workflow-app-loader.js +650 -0
- package/docs/agent-delegation-drive.7.md +4 -0
- package/docs/cli-mcp-parity.7.md +284 -211
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +4 -0
- package/docs/cross-agent-ledger.7.md +217 -0
- package/docs/designs/handoff-ledger.md +145 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
- package/docs/execution-backends.7.md +4 -0
- package/docs/handoff-setup.md +120 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +4 -0
- package/docs/multi-agent-operator-ux.7.md +4 -0
- package/docs/node-snapshot-diff-replay.7.md +4 -0
- package/docs/observability-cost-accounting.7.md +4 -0
- package/docs/project-index.md +143 -71
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +4 -0
- package/docs/run-registry-control-plane.7.md +4 -0
- package/docs/run-retention-reclamation.7.md +25 -0
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/web-desktop-workbench.7.md +4 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +9 -13
- package/package.json +1 -1
- package/scripts/agents/codex-agent.js +34 -4
- package/scripts/agents/cw-attest-wrap.js +2 -2
- package/scripts/bump-version.js +4 -3
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +30 -10
- package/scripts/dogfood-architecture-review.js +2 -3
- package/scripts/dogfood-release.js +3 -3
- package/scripts/gen-parity-doc.js +15 -2
- package/scripts/golden-path.js +4 -4
- package/scripts/onramp-check.js +1 -1
- package/scripts/parity-check.js +38 -21
- package/scripts/release-flow.js +9 -3
- package/scripts/sync-project-index.js +51 -27
- package/scripts/validate-run-state-schema.js +2 -2
- package/scripts/version-sync-check.js +30 -30
- package/dist/candidate-scoring.js +0 -729
- package/dist/capability-core.js +0 -1186
- package/dist/capability-registry.js +0 -879
- package/dist/cli/command-surface.js +0 -490
- package/dist/cli/format.js +0 -56
- package/dist/cli/handlers/audit.js +0 -82
- package/dist/cli/handlers/blackboard.js +0 -81
- package/dist/cli/handlers/candidate.js +0 -40
- package/dist/cli/handlers/clones.js +0 -34
- package/dist/cli/handlers/collaboration.js +0 -61
- package/dist/cli/handlers/eval.js +0 -40
- package/dist/cli/handlers/maintenance.js +0 -107
- package/dist/cli/handlers/multi-agent.js +0 -165
- package/dist/cli/handlers/node.js +0 -41
- package/dist/cli/handlers/operational.js +0 -155
- package/dist/cli/handlers/operator.js +0 -146
- package/dist/cli/handlers/registry.js +0 -68
- package/dist/cli/handlers/run.js +0 -153
- package/dist/cli/handlers/scheduling.js +0 -132
- package/dist/cli/handlers/workbench.js +0 -41
- package/dist/cli/handlers/worker.js +0 -45
- package/dist/cli/run-summary.js +0 -45
- package/dist/clones.js +0 -162
- package/dist/collaboration.js +0 -726
- package/dist/commit.js +0 -592
- package/dist/compare.js +0 -18
- package/dist/coordinator/classify.js +0 -45
- package/dist/coordinator/paths.js +0 -42
- package/dist/coordinator/util.js +0 -126
- package/dist/coordinator.js +0 -990
- package/dist/daemon.js +0 -44
- package/dist/dispatch.js +0 -250
- package/dist/drive.js +0 -827
- package/dist/error-feedback.js +0 -419
- package/dist/evidence-grounding.js +0 -184
- package/dist/execution-backend/agent.js +0 -294
- package/dist/execution-backend/probes.js +0 -112
- package/dist/execution-backend/util.js +0 -47
- package/dist/execution-backend.js +0 -961
- package/dist/gates.js +0 -48
- package/dist/harness.js +0 -61
- package/dist/loop-expansion.js +0 -60
- package/dist/mcp/tool-call.js +0 -434
- package/dist/mcp/tool-definitions.js +0 -1040
- package/dist/mcp-surface.js +0 -30
- package/dist/multi-agent/graph.js +0 -84
- package/dist/multi-agent/helpers.js +0 -141
- package/dist/multi-agent/ids.js +0 -20
- package/dist/multi-agent/paths.js +0 -22
- package/dist/multi-agent-eval/normalize.js +0 -51
- package/dist/multi-agent-eval.js +0 -678
- package/dist/multi-agent-host.js +0 -777
- package/dist/multi-agent.js +0 -984
- package/dist/node-projection.js +0 -59
- package/dist/node-snapshot.js +0 -260
- package/dist/operator-ux.js +0 -631
- package/dist/orchestrator/app-operations.js +0 -211
- package/dist/orchestrator/audit-operations.js +0 -182
- package/dist/orchestrator/candidate-operations.js +0 -117
- package/dist/orchestrator/cli-options.js +0 -294
- package/dist/orchestrator/collaboration-operations.js +0 -86
- package/dist/orchestrator/feedback-operations.js +0 -81
- package/dist/orchestrator/host-operations.js +0 -78
- package/dist/orchestrator/lifecycle-operations.js +0 -626
- package/dist/orchestrator/migration-operations.js +0 -44
- package/dist/orchestrator/multi-agent-operations.js +0 -362
- package/dist/orchestrator/topology-operations.js +0 -84
- package/dist/orchestrator.js +0 -917
- package/dist/pipeline-runner.js +0 -285
- package/dist/reclamation/hash.js +0 -72
- package/dist/reclamation.js +0 -812
- package/dist/reporter.js +0 -67
- package/dist/run-export.js +0 -784
- package/dist/run-registry/derive.js +0 -175
- package/dist/run-registry/format.js +0 -124
- package/dist/run-registry/gc.js +0 -251
- package/dist/run-registry/policy.js +0 -16
- package/dist/run-registry/queue.js +0 -115
- package/dist/run-registry.js +0 -850
- package/dist/run-state-schema.js +0 -68
- package/dist/scheduling.js +0 -184
- package/dist/state-explosion.js +0 -1014
- package/dist/state.js +0 -367
- package/dist/telemetry-ledger.js +0 -196
- package/dist/topology.js +0 -565
- package/dist/triggers.js +0 -184
- package/dist/trust-audit.js +0 -644
- package/dist/types/blackboard.js +0 -2
- package/dist/types/candidate.js +0 -2
- package/dist/types/collaboration.js +0 -2
- package/dist/types/core.js +0 -2
- package/dist/types/drive.js +0 -10
- package/dist/types/error-feedback.js +0 -2
- package/dist/types/evidence-reasoning.js +0 -2
- package/dist/types/execution-backend.js +0 -2
- package/dist/types/multi-agent.js +0 -2
- package/dist/types/observability.js +0 -2
- package/dist/types/pipeline.js +0 -2
- package/dist/types/reclamation.js +0 -8
- package/dist/types/report-bundle.js +0 -6
- package/dist/types/result.js +0 -2
- package/dist/types/run-registry.js +0 -2
- package/dist/types/run.js +0 -2
- package/dist/types/sandbox.js +0 -2
- package/dist/types/schedule.js +0 -2
- package/dist/types/state-node.js +0 -2
- package/dist/types/topology.js +0 -2
- package/dist/types/trust.js +0 -2
- package/dist/types/workbench.js +0 -2
- package/dist/types/worker.js +0 -2
- package/dist/types/workflow-app.js +0 -2
- package/dist/types.js +0 -44
- package/dist/util/fingerprint.js +0 -19
- package/dist/util/fingerprint.test.js +0 -27
- package/dist/verifier.js +0 -78
- package/dist/version.js +0 -8
- package/dist/workbench-host.js +0 -182
- package/dist/workbench.js +0 -192
- package/dist/worker-accept/acceptance.js +0 -114
- package/dist/worker-accept/blackboard-fanout.js +0 -80
- package/dist/worker-accept/blackboard-linkage.js +0 -19
- package/dist/worker-accept/context.js +0 -2
- package/dist/worker-accept/telemetry-ledger.js +0 -126
- package/dist/worker-accept/validation.js +0 -77
- package/dist/worker-accept/verifier-completion.js +0 -73
- package/dist/worker-isolation/helpers.js +0 -51
- package/dist/worker-isolation/paths.js +0 -46
- package/dist/worker-isolation.js +0 -656
- package/dist/workflow-api.js +0 -131
- /package/dist/{types → core/types}/boundary.js +0 -0
package/dist/worker-isolation.js
DELETED
|
@@ -1,656 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WORKER_ISOLATION_SCHEMA_VERSION = void 0;
|
|
7
|
-
exports.allocateWorkerScope = allocateWorkerScope;
|
|
8
|
-
exports.writeWorkerManifest = writeWorkerManifest;
|
|
9
|
-
exports.syncWorkerScopeFromTask = syncWorkerScopeFromTask;
|
|
10
|
-
exports.listWorkerScopes = listWorkerScopes;
|
|
11
|
-
exports.getWorkerScope = getWorkerScope;
|
|
12
|
-
exports.recordWorkerOutput = recordWorkerOutput;
|
|
13
|
-
exports.recordWorkerFailure = recordWorkerFailure;
|
|
14
|
-
exports.recordWorkerRetryAttempt = recordWorkerRetryAttempt;
|
|
15
|
-
exports.validateWorkerBoundary = validateWorkerBoundary;
|
|
16
|
-
exports.summarizeWorkers = summarizeWorkers;
|
|
17
|
-
exports.reclaimOrphans = reclaimOrphans;
|
|
18
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
19
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
20
|
-
const state_1 = require("./state");
|
|
21
|
-
const pipeline_contract_1 = require("./pipeline-contract");
|
|
22
|
-
const error_feedback_1 = require("./error-feedback");
|
|
23
|
-
const state_node_1 = require("./state-node");
|
|
24
|
-
const sandbox_profile_1 = require("./sandbox-profile");
|
|
25
|
-
const execution_backend_1 = require("./execution-backend");
|
|
26
|
-
const trust_audit_1 = require("./trust-audit");
|
|
27
|
-
const helpers_1 = require("./worker-isolation/helpers");
|
|
28
|
-
const paths_1 = require("./worker-isolation/paths");
|
|
29
|
-
const validation_1 = require("./validation");
|
|
30
|
-
const acceptance_1 = require("./worker-accept/acceptance");
|
|
31
|
-
const blackboard_linkage_1 = require("./worker-accept/blackboard-linkage");
|
|
32
|
-
const blackboard_fanout_1 = require("./worker-accept/blackboard-fanout");
|
|
33
|
-
const telemetry_ledger_1 = require("./worker-accept/telemetry-ledger");
|
|
34
|
-
const validation_2 = require("./worker-accept/validation");
|
|
35
|
-
const verifier_completion_1 = require("./worker-accept/verifier-completion");
|
|
36
|
-
exports.WORKER_ISOLATION_SCHEMA_VERSION = 1;
|
|
37
|
-
function allocateWorkerScope(run, task, options = {}) {
|
|
38
|
-
ensureWorkerState(run);
|
|
39
|
-
const existing = task.workerId ? getWorkerScope(run, task.workerId) : undefined;
|
|
40
|
-
if (existing) {
|
|
41
|
-
// Retry detection: re-allocating a worker for the same task
|
|
42
|
-
if (existing.status === "failed" || existing.status === "orphaned") {
|
|
43
|
-
existing.retryCount = (existing.retryCount || 0) + 1;
|
|
44
|
-
existing.updatedAt = new Date().toISOString();
|
|
45
|
-
existing.status = options.status || "allocated";
|
|
46
|
-
existing.errors = [];
|
|
47
|
-
upsertWorkerScope(run, existing);
|
|
48
|
-
writeWorkerIndex(run);
|
|
49
|
-
}
|
|
50
|
-
return existing;
|
|
51
|
-
}
|
|
52
|
-
const now = new Date().toISOString();
|
|
53
|
-
const workerId = options.workerId || (0, paths_1.createWorkerId)(run, task.id);
|
|
54
|
-
const workerDir = node_path_1.default.join(workerRoot(run), (0, state_1.safeFileName)(workerId));
|
|
55
|
-
const inputPath = node_path_1.default.join(workerDir, "input.md");
|
|
56
|
-
const resultPath = node_path_1.default.join(workerDir, "result.md");
|
|
57
|
-
const artifactsDir = node_path_1.default.join(workerDir, "artifacts");
|
|
58
|
-
const logsDir = node_path_1.default.join(workerDir, "logs");
|
|
59
|
-
const sandboxProfileId = options.sandboxProfileId || options.policy?.sandboxProfileId || sandbox_profile_1.DEFAULT_SANDBOX_PROFILE_ID;
|
|
60
|
-
const sandboxPolicy = (0, sandbox_profile_1.sandboxPolicyForWorker)(sandboxProfileId, {
|
|
61
|
-
cwd: run.cwd,
|
|
62
|
-
runDir: run.paths.runDir,
|
|
63
|
-
workerDir,
|
|
64
|
-
inputPath,
|
|
65
|
-
resultPath,
|
|
66
|
-
artifactsDir,
|
|
67
|
-
logsDir,
|
|
68
|
-
extraReadPaths: options.policy?.readPaths || [],
|
|
69
|
-
extraWritePaths: [...(options.policy?.writePaths || []), ...(options.policy?.allowedPaths || [])],
|
|
70
|
-
allowArtifacts: options.policy?.allowArtifacts,
|
|
71
|
-
allowLogs: options.policy?.allowLogs,
|
|
72
|
-
// H7: persisted custom profile definitions so a custom logical id resolves
|
|
73
|
-
// against THIS worker's context (worker-specific path tokens bind correctly).
|
|
74
|
-
customProfiles: run.customSandboxProfiles
|
|
75
|
-
});
|
|
76
|
-
const allowedPaths = (0, sandbox_profile_1.effectiveSandboxWritePaths)(sandboxPolicy);
|
|
77
|
-
(0, sandbox_profile_1.upsertRunSandboxPolicy)(run, sandboxPolicy);
|
|
78
|
-
// Execution backend selection (mechanism vs policy): the worker scope records
|
|
79
|
-
// WHICH backend was selected + its sandbox attestation. The dispatch path is a
|
|
80
|
-
// delegate-host execution (the host runs the worker), so the backend enforces
|
|
81
|
-
// only CW's own worker-output acceptance and attests the rest — reproducing
|
|
82
|
-
// pre-v0.1.29 behavior exactly for the default (node) backend. Only recorded
|
|
83
|
-
// when a backend was explicitly selected.
|
|
84
|
-
const backendSelection = options.backendSelection || (options.backendId ? (0, execution_backend_1.resolveBackendSelection)(options.backendId) : undefined);
|
|
85
|
-
const backendId = backendSelection?.backendId;
|
|
86
|
-
const backendAttestation = backendId
|
|
87
|
-
? options.backendAttestation || (0, execution_backend_1.attestSandbox)((0, execution_backend_1.getBackendDescriptor)(backendId), sandboxPolicy, { mode: "delegate-host" })
|
|
88
|
-
: undefined;
|
|
89
|
-
node_fs_1.default.mkdirSync(artifactsDir, { recursive: true });
|
|
90
|
-
node_fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
91
|
-
const scope = {
|
|
92
|
-
schemaVersion: exports.WORKER_ISOLATION_SCHEMA_VERSION,
|
|
93
|
-
id: workerId,
|
|
94
|
-
runId: run.id,
|
|
95
|
-
taskId: task.id,
|
|
96
|
-
dispatchId: options.dispatchId || task.dispatchId,
|
|
97
|
-
createdAt: now,
|
|
98
|
-
updatedAt: now,
|
|
99
|
-
status: options.status || "allocated",
|
|
100
|
-
workerDir,
|
|
101
|
-
inputPath,
|
|
102
|
-
resultPath,
|
|
103
|
-
artifactsDir,
|
|
104
|
-
logsDir,
|
|
105
|
-
allowedPaths,
|
|
106
|
-
sandboxProfileId: sandboxPolicy.id,
|
|
107
|
-
sandboxPolicy,
|
|
108
|
-
backendId,
|
|
109
|
-
backendSelection,
|
|
110
|
-
backendAttestation,
|
|
111
|
-
stateNodeId: task.stateNodeId,
|
|
112
|
-
feedbackIds: [],
|
|
113
|
-
errors: [],
|
|
114
|
-
multiAgent: options.multiAgent,
|
|
115
|
-
metadata: (0, helpers_1.compactMetadata)({
|
|
116
|
-
...options.metadata,
|
|
117
|
-
multiAgent: options.multiAgent,
|
|
118
|
-
phase: task.phase,
|
|
119
|
-
kind: task.kind,
|
|
120
|
-
taskPath: task.taskPath
|
|
121
|
-
})
|
|
122
|
-
};
|
|
123
|
-
writeWorkerInput(run, task, scope);
|
|
124
|
-
writeWorkerManifest(run, scope);
|
|
125
|
-
upsertWorkerScope(run, scope);
|
|
126
|
-
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
127
|
-
kind: "worker.sandbox-profile",
|
|
128
|
-
decision: "recorded",
|
|
129
|
-
source: "runtime-derived",
|
|
130
|
-
workerId: scope.id,
|
|
131
|
-
taskId: task.id,
|
|
132
|
-
sandboxProfileId: sandboxPolicy.id,
|
|
133
|
-
policySnapshot: sandboxPolicy,
|
|
134
|
-
metadata: { dispatchId: scope.dispatchId, workerDir: scope.workerDir, allowedPaths }
|
|
135
|
-
});
|
|
136
|
-
if (backendId && backendAttestation) {
|
|
137
|
-
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
138
|
-
kind: "worker.backend",
|
|
139
|
-
decision: backendAttestation.status === "refused" ? "denied" : "recorded",
|
|
140
|
-
source: "runtime-derived",
|
|
141
|
-
workerId: scope.id,
|
|
142
|
-
taskId: task.id,
|
|
143
|
-
sandboxProfileId: sandboxPolicy.id,
|
|
144
|
-
policySnapshot: sandboxPolicy,
|
|
145
|
-
metadata: {
|
|
146
|
-
backendId,
|
|
147
|
-
backendSelection,
|
|
148
|
-
attestationStatus: backendAttestation.status,
|
|
149
|
-
enforced: backendAttestation.enforced,
|
|
150
|
-
attested: backendAttestation.attested,
|
|
151
|
-
unenforceable: backendAttestation.unenforceable,
|
|
152
|
-
dispatchId: scope.dispatchId
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
task.workerId = scope.id;
|
|
157
|
-
task.workerManifestPath = (0, paths_1.manifestPath)(scope);
|
|
158
|
-
task.sandboxProfileId = sandboxPolicy.id;
|
|
159
|
-
task.sandboxPolicy = sandboxPolicy;
|
|
160
|
-
task.backendId = backendId;
|
|
161
|
-
task.backendSelection = backendSelection;
|
|
162
|
-
task.backendAttestation = backendAttestation;
|
|
163
|
-
writeWorkerIndex(run);
|
|
164
|
-
if (options.persist !== false)
|
|
165
|
-
(0, state_1.saveCheckpoint)(run);
|
|
166
|
-
return scope;
|
|
167
|
-
}
|
|
168
|
-
function writeWorkerManifest(run, scope) {
|
|
169
|
-
const task = run.tasks.find((candidate) => candidate.id === scope.taskId);
|
|
170
|
-
const sandboxPolicy = scope.sandboxPolicy || sandboxPolicyForBoundary(run, scope);
|
|
171
|
-
const sandboxProfileId = scope.sandboxProfileId || sandboxPolicy.id;
|
|
172
|
-
const scopePath = (0, paths_1.workerScopePath)(scope);
|
|
173
|
-
const workerManifestPath = (0, paths_1.manifestPath)(scope);
|
|
174
|
-
const manifest = {
|
|
175
|
-
schemaVersion: exports.WORKER_ISOLATION_SCHEMA_VERSION,
|
|
176
|
-
id: scope.id,
|
|
177
|
-
runId: scope.runId,
|
|
178
|
-
taskId: scope.taskId,
|
|
179
|
-
dispatchId: scope.dispatchId,
|
|
180
|
-
createdAt: scope.createdAt,
|
|
181
|
-
updatedAt: scope.updatedAt,
|
|
182
|
-
status: scope.status,
|
|
183
|
-
workerDir: scope.workerDir,
|
|
184
|
-
scopePath,
|
|
185
|
-
manifestPath: workerManifestPath,
|
|
186
|
-
inputPath: scope.inputPath,
|
|
187
|
-
resultPath: scope.resultPath,
|
|
188
|
-
artifactsDir: scope.artifactsDir,
|
|
189
|
-
logsDir: scope.logsDir,
|
|
190
|
-
allowedPaths: scope.allowedPaths,
|
|
191
|
-
sandboxProfileId,
|
|
192
|
-
sandboxPolicy,
|
|
193
|
-
sandbox: sandboxPolicy
|
|
194
|
-
? {
|
|
195
|
-
profileId: sandboxPolicy.id,
|
|
196
|
-
policy: sandboxPolicy,
|
|
197
|
-
enforcedByCW: sandboxPolicy.enforcement.enforcedByCW,
|
|
198
|
-
hostRequired: sandboxPolicy.enforcement.hostRequired
|
|
199
|
-
}
|
|
200
|
-
: undefined,
|
|
201
|
-
backendId: scope.backendId,
|
|
202
|
-
backendSelection: scope.backendSelection,
|
|
203
|
-
backendAttestation: scope.backendAttestation,
|
|
204
|
-
retryCount: scope.retryCount,
|
|
205
|
-
backend: scope.backendId && scope.backendAttestation
|
|
206
|
-
? {
|
|
207
|
-
id: scope.backendId,
|
|
208
|
-
locality: scope.backendAttestation.locality,
|
|
209
|
-
kind: scope.backendAttestation.kind,
|
|
210
|
-
enforces: scope.backendAttestation.enforced,
|
|
211
|
-
attests: scope.backendAttestation.attested,
|
|
212
|
-
attestation: scope.backendAttestation
|
|
213
|
-
}
|
|
214
|
-
: undefined,
|
|
215
|
-
instructions: [
|
|
216
|
-
"Read input.md before doing work.",
|
|
217
|
-
"Write the final Markdown result to result.md.",
|
|
218
|
-
"Write worker-local artifacts under artifacts/ and logs under logs/.",
|
|
219
|
-
`Sandbox profile: ${sandboxProfileId}.`,
|
|
220
|
-
"CW enforces profile validation and worker result acceptance only.",
|
|
221
|
-
"The agent host must enforce OS file access, process execution, network access, and environment filtering.",
|
|
222
|
-
"Do not edit shared run state files directly; CW records accepted results."
|
|
223
|
-
],
|
|
224
|
-
taskPath: task?.taskPath,
|
|
225
|
-
prompt: task?.prompt,
|
|
226
|
-
stateNodeId: scope.stateNodeId,
|
|
227
|
-
resultNodeId: scope.resultNodeId,
|
|
228
|
-
feedbackIds: scope.feedbackIds,
|
|
229
|
-
errors: scope.errors,
|
|
230
|
-
output: scope.output,
|
|
231
|
-
multiAgent: scope.multiAgent,
|
|
232
|
-
blackboard: blackboardManifest(run, scope),
|
|
233
|
-
metadata: scope.metadata
|
|
234
|
-
};
|
|
235
|
-
(0, state_1.writeJson)(workerManifestPath, manifest);
|
|
236
|
-
return manifest;
|
|
237
|
-
}
|
|
238
|
-
function syncWorkerScopeFromTask(run, workerId) {
|
|
239
|
-
const scope = getWorkerScope(run, workerId);
|
|
240
|
-
if (!scope)
|
|
241
|
-
return undefined;
|
|
242
|
-
const task = run.tasks.find((candidate) => candidate.id === scope.taskId);
|
|
243
|
-
if (!task?.multiAgent)
|
|
244
|
-
return scope;
|
|
245
|
-
const updated = {
|
|
246
|
-
...scope,
|
|
247
|
-
updatedAt: new Date().toISOString(),
|
|
248
|
-
multiAgent: task.multiAgent,
|
|
249
|
-
metadata: (0, helpers_1.compactMetadata)({
|
|
250
|
-
...(scope.metadata || {}),
|
|
251
|
-
multiAgent: task.multiAgent
|
|
252
|
-
})
|
|
253
|
-
};
|
|
254
|
-
return updateWorkerScope(run, updated);
|
|
255
|
-
}
|
|
256
|
-
function listWorkerScopes(run, options = {}) {
|
|
257
|
-
ensureWorkerState(run);
|
|
258
|
-
const scopes = loadWorkerScopesFromDisk(run);
|
|
259
|
-
run.workers = (0, helpers_1.mergeScopes)(run.workers || [], scopes);
|
|
260
|
-
const listed = run.workers || [];
|
|
261
|
-
return options.status ? listed.filter((scope) => scope.status === options.status) : listed;
|
|
262
|
-
}
|
|
263
|
-
function getWorkerScope(run, workerId) {
|
|
264
|
-
ensureWorkerState(run);
|
|
265
|
-
const existing = (run.workers || []).find((scope) => scope.id === workerId);
|
|
266
|
-
if (existing)
|
|
267
|
-
return existing;
|
|
268
|
-
const file = node_path_1.default.join(workerRoot(run), (0, state_1.safeFileName)(workerId), paths_1.WORKER_SCOPE_FILE);
|
|
269
|
-
if (!node_fs_1.default.existsSync(file))
|
|
270
|
-
return undefined;
|
|
271
|
-
let scope;
|
|
272
|
-
try {
|
|
273
|
-
scope = (0, validation_1.validateWorkerScope)(JSON.parse(node_fs_1.default.readFileSync(file, "utf8")));
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
// A present-but-corrupt scope fails closed with context, not a raw
|
|
277
|
-
// SyntaxError/validation throw bubbling up from deep in the call stack.
|
|
278
|
-
throw new Error(`Corrupt worker scope ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
279
|
-
}
|
|
280
|
-
upsertWorkerScope(run, scope);
|
|
281
|
-
return scope;
|
|
282
|
-
}
|
|
283
|
-
function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
284
|
-
// Accept-path orchestrator. The recorded order + side effects of these ordered
|
|
285
|
-
// steps are load-bearing (replay determinism + the hash-chained audit/telemetry
|
|
286
|
-
// ledgers cross-link by parent event ids), so each helper runs exactly where it
|
|
287
|
-
// did before and mutates the shared `accept` context in place. Do NOT reorder.
|
|
288
|
-
const accept = (0, validation_2.validateWorkerResult)(run, workerId, resultPath, options, {
|
|
289
|
-
requireWorkerScope,
|
|
290
|
-
requireWorkerTask,
|
|
291
|
-
validateWorkerBoundary,
|
|
292
|
-
recordWorkerFailure
|
|
293
|
-
});
|
|
294
|
-
const delegation = (0, telemetry_ledger_1.attestWorkerDelegation)(accept, { recordWorkerFailure });
|
|
295
|
-
(0, acceptance_1.acceptWorkerResult)(accept, delegation);
|
|
296
|
-
(0, telemetry_ledger_1.recordWorkerDelegationLedger)(accept, delegation);
|
|
297
|
-
(0, verifier_completion_1.runWorkerVerify)(accept);
|
|
298
|
-
(0, verifier_completion_1.recordWorkerCompletion)(accept, delegation, { updateWorkerScope });
|
|
299
|
-
(0, blackboard_fanout_1.fanOutWorkerOutput)(accept);
|
|
300
|
-
if (options.persist !== false)
|
|
301
|
-
(0, state_1.saveCheckpoint)(run);
|
|
302
|
-
return accept.output;
|
|
303
|
-
}
|
|
304
|
-
function recordWorkerFailure(run, workerId, error, options = {}) {
|
|
305
|
-
const scope = requireWorkerScope(run, workerId);
|
|
306
|
-
const task = requireWorkerTask(run, scope);
|
|
307
|
-
const structured = normalizeWorkerError(error, scope, options);
|
|
308
|
-
const failureNodeId = `${run.id}:worker:${(0, state_1.safeFileName)(workerId)}:failure:${scope.errors.length + 1}`;
|
|
309
|
-
let failureNode = (0, state_node_1.recordNodeError)((0, state_node_1.createStateNode)({
|
|
310
|
-
id: failureNodeId,
|
|
311
|
-
kind: "error",
|
|
312
|
-
status: "pending",
|
|
313
|
-
loopStage: "adjust",
|
|
314
|
-
inputs: { workerId, taskId: task.id, dispatchId: scope.dispatchId },
|
|
315
|
-
artifacts: (0, paths_1.workerArtifacts)(scope),
|
|
316
|
-
parents: task.stateNodeId ? [task.stateNodeId] : [],
|
|
317
|
-
contractId: pipeline_contract_1.DEFAULT_PIPELINE_CONTRACT_ID,
|
|
318
|
-
metadata: { workerId, taskId: task.id, dispatchId: scope.dispatchId, workerDir: scope.workerDir, sandboxProfileId: scope.sandboxProfileId }
|
|
319
|
-
}), structured);
|
|
320
|
-
if (task.stateNodeId) {
|
|
321
|
-
const parent = run.nodes?.find((candidate) => candidate.id === task.stateNodeId);
|
|
322
|
-
if (parent) {
|
|
323
|
-
const linked = (0, state_node_1.linkStateNodes)(parent, failureNode);
|
|
324
|
-
(0, state_node_1.appendRunNode)(run, linked[0]);
|
|
325
|
-
failureNode = linked[1];
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
(0, state_node_1.appendRunNode)(run, failureNode);
|
|
329
|
-
task.status = "failed";
|
|
330
|
-
task.loopStage = "adjust";
|
|
331
|
-
const feedback = (0, error_feedback_1.recordFeedback)(run, {
|
|
332
|
-
source: "pipeline-runner",
|
|
333
|
-
error: structured,
|
|
334
|
-
nodeId: failureNode.id,
|
|
335
|
-
taskId: task.id,
|
|
336
|
-
path: structured.path,
|
|
337
|
-
retryable: structured.retryable,
|
|
338
|
-
artifacts: failureNode.artifacts,
|
|
339
|
-
metadata: {
|
|
340
|
-
workerId,
|
|
341
|
-
dispatchId: scope.dispatchId,
|
|
342
|
-
workerDir: scope.workerDir,
|
|
343
|
-
sandboxProfileId: scope.sandboxProfileId,
|
|
344
|
-
sandboxPolicy: scope.sandboxPolicy,
|
|
345
|
-
allowedPaths: scope.allowedPaths,
|
|
346
|
-
details: structured.details
|
|
347
|
-
}
|
|
348
|
-
}, { persist: false });
|
|
349
|
-
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
350
|
-
kind: "worker.failure",
|
|
351
|
-
decision: structured.code === "worker-boundary-violation" || structured.code.startsWith("sandbox-") ? "denied" : "failed",
|
|
352
|
-
source: structured.code.startsWith("sandbox-") || structured.code === "worker-boundary-violation" ? "cw-validated" : "runtime-derived",
|
|
353
|
-
workerId,
|
|
354
|
-
taskId: task.id,
|
|
355
|
-
nodeId: failureNode.id,
|
|
356
|
-
feedbackIds: [feedback.id],
|
|
357
|
-
sandboxProfileId: scope.sandboxProfileId,
|
|
358
|
-
policySnapshot: scope.sandboxPolicy,
|
|
359
|
-
normalizedPath: structured.path,
|
|
360
|
-
metadata: {
|
|
361
|
-
code: structured.code,
|
|
362
|
-
dispatchId: scope.dispatchId
|
|
363
|
-
}
|
|
364
|
-
});
|
|
365
|
-
updateWorkerScope(run, {
|
|
366
|
-
...scope,
|
|
367
|
-
updatedAt: new Date().toISOString(),
|
|
368
|
-
status: structured.code === "worker-boundary-violation" || structured.code.startsWith("sandbox-") ? "rejected" : "failed",
|
|
369
|
-
retryCount: typeof options.retryCount === "number" ? options.retryCount : scope.retryCount,
|
|
370
|
-
feedbackIds: (0, helpers_1.unique)([...(scope.feedbackIds || []), feedback.id]),
|
|
371
|
-
errors: [...(scope.errors || []), structured]
|
|
372
|
-
});
|
|
373
|
-
if (options.persist !== false)
|
|
374
|
-
(0, state_1.saveCheckpoint)(run);
|
|
375
|
-
return requireWorkerScope(run, workerId);
|
|
376
|
-
}
|
|
377
|
-
function recordWorkerRetryAttempt(run, workerId, attempts, reason, options = {}) {
|
|
378
|
-
const scope = requireWorkerScope(run, workerId);
|
|
379
|
-
const updated = updateWorkerScope(run, {
|
|
380
|
-
...scope,
|
|
381
|
-
updatedAt: new Date().toISOString(),
|
|
382
|
-
retryCount: attempts,
|
|
383
|
-
metadata: (0, helpers_1.compactMetadata)({
|
|
384
|
-
...scope.metadata,
|
|
385
|
-
agentDelegationAttempts: attempts,
|
|
386
|
-
agentDelegationLastFailure: reason
|
|
387
|
-
})
|
|
388
|
-
});
|
|
389
|
-
if (options.persist !== false)
|
|
390
|
-
(0, state_1.saveCheckpoint)(run);
|
|
391
|
-
return updated;
|
|
392
|
-
}
|
|
393
|
-
function validateWorkerBoundary(run, workerId, options = {}) {
|
|
394
|
-
const scope = requireWorkerScope(run, workerId);
|
|
395
|
-
const rawPath = String(options.path || scope.resultPath);
|
|
396
|
-
const policy = sandboxPolicyForBoundary(run, scope, options);
|
|
397
|
-
const violation = (0, sandbox_profile_1.validateSandboxWrite)(policy, rawPath, workerId);
|
|
398
|
-
if (!violation) {
|
|
399
|
-
// Write paths are enforced by CW at this boundary. Command and network limits
|
|
400
|
-
// are declared in the sandbox policy but enforced by the execution backend
|
|
401
|
-
// (the host/container runtime). Record the policy split transparently so the
|
|
402
|
-
// audit trail shows what CW checked vs what was delegated to the host.
|
|
403
|
-
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
404
|
-
kind: "worker.sandbox-boundary",
|
|
405
|
-
decision: "allowed",
|
|
406
|
-
source: "cw-validated",
|
|
407
|
-
workerId,
|
|
408
|
-
taskId: scope.taskId,
|
|
409
|
-
sandboxProfileId: policy.id,
|
|
410
|
-
policyRef: `execute=${policy.execute.mode} network=${policy.network.mode} env.inherit=${policy.env.inherit}`,
|
|
411
|
-
command: policy.execute.mode,
|
|
412
|
-
networkTarget: policy.network.mode,
|
|
413
|
-
metadata: {
|
|
414
|
-
enforced_by_cw: ["write-paths"],
|
|
415
|
-
delegated_to_host: ["execute", "network", "env"],
|
|
416
|
-
env_inherit: policy.env.inherit
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
return violation;
|
|
421
|
-
}
|
|
422
|
-
function summarizeWorkers(run) {
|
|
423
|
-
const workers = listWorkerScopes(run);
|
|
424
|
-
return {
|
|
425
|
-
total: workers.length,
|
|
426
|
-
byStatus: (0, helpers_1.countBy)(workers, (scope) => scope.status),
|
|
427
|
-
manifestPaths: workers.map(paths_1.manifestPath),
|
|
428
|
-
failed: workers
|
|
429
|
-
.filter((scope) => scope.status === "failed" || scope.status === "rejected")
|
|
430
|
-
.map((scope) => ({ id: scope.id, status: scope.status, feedbackIds: scope.feedbackIds || [] }))
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
function reclaimOrphans(run, now) {
|
|
434
|
-
const nowMs = now ? Date.parse(now) : Date.now();
|
|
435
|
-
if (!Number.isFinite(nowMs))
|
|
436
|
-
throw new Error("Invalid reclaim 'now': " + String(now));
|
|
437
|
-
const orphans = [];
|
|
438
|
-
const activeStatuses = new Set(["allocated", "running"]);
|
|
439
|
-
for (const scope of run.workers || []) {
|
|
440
|
-
if (!activeStatuses.has(scope.status))
|
|
441
|
-
continue;
|
|
442
|
-
if (!scope.timeoutMs || scope.timeoutMs <= 0)
|
|
443
|
-
continue;
|
|
444
|
-
const createdAtMs = Date.parse(scope.createdAt);
|
|
445
|
-
if (!Number.isFinite(createdAtMs))
|
|
446
|
-
continue;
|
|
447
|
-
const elapsedMs = nowMs - createdAtMs;
|
|
448
|
-
if (elapsedMs < scope.timeoutMs)
|
|
449
|
-
continue;
|
|
450
|
-
scope.status = "orphaned";
|
|
451
|
-
scope.updatedAt = new Date(nowMs).toISOString();
|
|
452
|
-
scope.errors.push({
|
|
453
|
-
code: "worker-orphaned",
|
|
454
|
-
message: `Worker exceeded timeout of ${scope.timeoutMs}ms (elapsed: ${elapsedMs}ms).`,
|
|
455
|
-
at: new Date(nowMs).toISOString(),
|
|
456
|
-
retryable: true
|
|
457
|
-
});
|
|
458
|
-
upsertWorkerScope(run, scope);
|
|
459
|
-
orphans.push({ workerId: scope.id, taskId: scope.taskId, elapsedMs, timeoutMs: scope.timeoutMs });
|
|
460
|
-
}
|
|
461
|
-
if (orphans.length) {
|
|
462
|
-
writeWorkerIndex(run);
|
|
463
|
-
}
|
|
464
|
-
return { runId: run.id, reclaimed: orphans.length, orphans };
|
|
465
|
-
}
|
|
466
|
-
function ensureWorkerState(run) {
|
|
467
|
-
run.paths.workersDir = run.paths.workersDir || node_path_1.default.join(run.paths.runDir, "workers");
|
|
468
|
-
node_fs_1.default.mkdirSync(run.paths.workersDir, { recursive: true });
|
|
469
|
-
run.workers = run.workers || [];
|
|
470
|
-
}
|
|
471
|
-
function writeWorkerInput(run, task, scope) {
|
|
472
|
-
const lines = [
|
|
473
|
-
`# Worker ${scope.id}`,
|
|
474
|
-
"",
|
|
475
|
-
`- Run: ${run.id}`,
|
|
476
|
-
`- Task: ${task.id}`,
|
|
477
|
-
`- Dispatch: ${scope.dispatchId || ""}`,
|
|
478
|
-
`- Result: ${scope.resultPath}`,
|
|
479
|
-
`- Artifacts: ${scope.artifactsDir}`,
|
|
480
|
-
`- Logs: ${scope.logsDir}`,
|
|
481
|
-
`- Sandbox Profile: ${scope.sandboxProfileId || sandbox_profile_1.DEFAULT_SANDBOX_PROFILE_ID}`,
|
|
482
|
-
...(scope.multiAgent
|
|
483
|
-
? [
|
|
484
|
-
`- Multi-Agent Run: ${scope.multiAgent.runId}`,
|
|
485
|
-
`- Agent Group: ${scope.multiAgent.groupId}`,
|
|
486
|
-
`- Agent Role: ${scope.multiAgent.roleId}`,
|
|
487
|
-
`- Agent Membership: ${scope.multiAgent.membershipId || ""}`,
|
|
488
|
-
`- Agent Fanout: ${scope.multiAgent.fanoutId || ""}`
|
|
489
|
-
]
|
|
490
|
-
: []),
|
|
491
|
-
"",
|
|
492
|
-
"## Task",
|
|
493
|
-
"",
|
|
494
|
-
task.prompt,
|
|
495
|
-
"",
|
|
496
|
-
"## Boundary",
|
|
497
|
-
"",
|
|
498
|
-
"- Write the final Markdown result to result.md.",
|
|
499
|
-
"- Keep extra files under artifacts/ or logs/.",
|
|
500
|
-
`- Read paths: ${(scope.sandboxPolicy?.readPaths || []).join(", ") || "none"}.`,
|
|
501
|
-
`- Write paths: ${(0, sandbox_profile_1.effectiveSandboxWritePaths)(sandboxPolicyForBoundary(run, scope)).join(", ") || "none"}.`,
|
|
502
|
-
"- CW enforces result acceptance. The host is responsible for OS/process/network/environment sandbox enforcement.",
|
|
503
|
-
"- Do not mutate state.json, nodes/, feedback/, dispatches/, or commits/ directly.",
|
|
504
|
-
""
|
|
505
|
-
];
|
|
506
|
-
node_fs_1.default.writeFileSync(scope.inputPath, lines.join("\n"), "utf8");
|
|
507
|
-
}
|
|
508
|
-
function upsertWorkerScope(run, scope) {
|
|
509
|
-
ensureWorkerState(run);
|
|
510
|
-
const scopes = run.workers || [];
|
|
511
|
-
const index = scopes.findIndex((candidate) => candidate.id === scope.id);
|
|
512
|
-
run.workers = index >= 0 ? scopes.map((candidate) => (candidate.id === scope.id ? scope : candidate)) : [...scopes, scope];
|
|
513
|
-
writeWorkerScope(scope);
|
|
514
|
-
return scope;
|
|
515
|
-
}
|
|
516
|
-
function updateWorkerScope(run, scope) {
|
|
517
|
-
const updated = upsertWorkerScope(run, scope);
|
|
518
|
-
writeWorkerManifest(run, updated);
|
|
519
|
-
writeWorkerIndex(run);
|
|
520
|
-
return updated;
|
|
521
|
-
}
|
|
522
|
-
function writeWorkerScope(scope) {
|
|
523
|
-
(0, state_1.writeJson)((0, paths_1.workerScopePath)(scope), scope);
|
|
524
|
-
}
|
|
525
|
-
function writeWorkerIndex(run) {
|
|
526
|
-
ensureWorkerState(run);
|
|
527
|
-
(0, state_1.writeJson)(node_path_1.default.join(workerRoot(run), "index.json"), {
|
|
528
|
-
schemaVersion: exports.WORKER_ISOLATION_SCHEMA_VERSION,
|
|
529
|
-
runId: run.id,
|
|
530
|
-
workers: (run.workers || []).map((scope) => ({
|
|
531
|
-
id: scope.id,
|
|
532
|
-
taskId: scope.taskId,
|
|
533
|
-
dispatchId: scope.dispatchId,
|
|
534
|
-
status: scope.status,
|
|
535
|
-
workerDir: scope.workerDir,
|
|
536
|
-
manifestPath: (0, paths_1.manifestPath)(scope),
|
|
537
|
-
resultPath: scope.resultPath,
|
|
538
|
-
sandboxProfileId: scope.sandboxProfileId,
|
|
539
|
-
backendId: scope.backendId,
|
|
540
|
-
multiAgent: scope.multiAgent,
|
|
541
|
-
feedbackIds: scope.feedbackIds
|
|
542
|
-
}))
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
function loadWorkerScopesFromDisk(run) {
|
|
546
|
-
ensureWorkerState(run);
|
|
547
|
-
if (!node_fs_1.default.existsSync(workerRoot(run)))
|
|
548
|
-
return [];
|
|
549
|
-
return node_fs_1.default
|
|
550
|
-
.readdirSync(workerRoot(run), { withFileTypes: true })
|
|
551
|
-
.filter((entry) => entry.isDirectory())
|
|
552
|
-
.map((entry) => node_path_1.default.join(workerRoot(run), entry.name, paths_1.WORKER_SCOPE_FILE))
|
|
553
|
-
.filter((file) => node_fs_1.default.existsSync(file))
|
|
554
|
-
.map((file) => {
|
|
555
|
-
// One corrupt/partially-written worker.json must not blank the whole
|
|
556
|
-
// listing (summarizeWorkers/listWorkerScopes) — skip it with a diagnostic
|
|
557
|
-
// and surface every worker that IS readable.
|
|
558
|
-
try {
|
|
559
|
-
return (0, validation_1.validateWorkerScope)(JSON.parse(node_fs_1.default.readFileSync(file, "utf8")));
|
|
560
|
-
}
|
|
561
|
-
catch (error) {
|
|
562
|
-
process.stderr.write(`cw: skipping unreadable worker scope ${file}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
563
|
-
return undefined;
|
|
564
|
-
}
|
|
565
|
-
})
|
|
566
|
-
.filter((scope) => scope !== undefined);
|
|
567
|
-
}
|
|
568
|
-
function requireWorkerScope(run, workerId) {
|
|
569
|
-
const scope = getWorkerScope(run, workerId);
|
|
570
|
-
if (!scope)
|
|
571
|
-
throw new Error(`Unknown worker for run ${run.id}: ${workerId}`);
|
|
572
|
-
return scope;
|
|
573
|
-
}
|
|
574
|
-
function requireWorkerTask(run, scope) {
|
|
575
|
-
const task = run.tasks.find((candidate) => candidate.id === scope.taskId);
|
|
576
|
-
if (!task)
|
|
577
|
-
throw new Error(`Unknown task for worker ${scope.id}: ${scope.taskId}`);
|
|
578
|
-
return task;
|
|
579
|
-
}
|
|
580
|
-
function workerRoot(run) {
|
|
581
|
-
return run.paths.workersDir || node_path_1.default.join(run.paths.runDir, "workers");
|
|
582
|
-
}
|
|
583
|
-
function sandboxPolicyForBoundary(run, scope, options = {}) {
|
|
584
|
-
if (scope.sandboxPolicy && !options.policy && !options.sandboxProfileId)
|
|
585
|
-
return scope.sandboxPolicy;
|
|
586
|
-
const profileId = options.sandboxProfileId || options.policy?.sandboxProfileId || scope.sandboxProfileId || sandbox_profile_1.DEFAULT_SANDBOX_PROFILE_ID;
|
|
587
|
-
// H7: when the scope.sandboxPolicy snapshot is LOST, this re-resolves the policy
|
|
588
|
-
// by its logical profileId against the WORKER's paths (scope.workerDir etc.). For
|
|
589
|
-
// a CUSTOM profile the bundled lookup would throw not-found; threading
|
|
590
|
-
// run.customSandboxProfiles lets resolveSandboxProfileById re-resolve the persisted
|
|
591
|
-
// DEFINITION here — re-enforcing the same policy with worker-correct path tokens
|
|
592
|
-
// (NOT the dispatch-time paths), so a legitimate worker write is not falsely denied.
|
|
593
|
-
return (0, sandbox_profile_1.sandboxPolicyForWorker)(profileId, {
|
|
594
|
-
cwd: run.cwd,
|
|
595
|
-
runDir: run.paths.runDir,
|
|
596
|
-
workerDir: scope.workerDir,
|
|
597
|
-
inputPath: scope.inputPath,
|
|
598
|
-
resultPath: scope.resultPath,
|
|
599
|
-
artifactsDir: scope.artifactsDir,
|
|
600
|
-
logsDir: scope.logsDir,
|
|
601
|
-
extraReadPaths: options.policy?.readPaths || [],
|
|
602
|
-
extraWritePaths: [
|
|
603
|
-
...(options.policy?.writePaths || []),
|
|
604
|
-
...(options.policy?.allowedPaths || []),
|
|
605
|
-
...(!scope.sandboxPolicy ? scope.allowedPaths || [] : [])
|
|
606
|
-
],
|
|
607
|
-
allowArtifacts: options.policy?.allowArtifacts,
|
|
608
|
-
allowLogs: options.policy?.allowLogs,
|
|
609
|
-
customProfiles: run.customSandboxProfiles
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
function blackboardManifest(run, scope) {
|
|
613
|
-
const linkage = (0, blackboard_linkage_1.blackboardLinkage)(run, scope);
|
|
614
|
-
if (!linkage.blackboardId)
|
|
615
|
-
return undefined;
|
|
616
|
-
const root = run.paths.blackboardDir || node_path_1.default.join(run.paths.runDir, "blackboard");
|
|
617
|
-
return {
|
|
618
|
-
id: linkage.blackboardId,
|
|
619
|
-
topicIds: linkage.topicIds,
|
|
620
|
-
indexPath: node_path_1.default.join(root, "index.json"),
|
|
621
|
-
messagesPath: node_path_1.default.join(root, "messages.jsonl"),
|
|
622
|
-
topicsDir: node_path_1.default.join(root, "topics"),
|
|
623
|
-
contextsDir: node_path_1.default.join(root, "contexts"),
|
|
624
|
-
artifactsDir: node_path_1.default.join(root, "artifacts"),
|
|
625
|
-
instructions: [
|
|
626
|
-
"Use the blackboard as shared coordination context.",
|
|
627
|
-
"Read index.json and the relevant topic/context/artifact files before synthesizing.",
|
|
628
|
-
"Cite blackboard artifact refs or message refs in result evidence when relevant.",
|
|
629
|
-
"Do not edit blackboard files directly; CW records accepted worker output into the blackboard."
|
|
630
|
-
]
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
function normalizeWorkerError(error, scope, options) {
|
|
634
|
-
if ((0, helpers_1.isBoundaryViolation)(error)) {
|
|
635
|
-
return (0, helpers_1.structuredError)(error.code, error.message, {
|
|
636
|
-
path: error.path,
|
|
637
|
-
retryable: false,
|
|
638
|
-
details: { allowedPaths: error.allowedPaths, workerId: scope.id, taskId: scope.taskId, sandboxProfileId: scope.sandboxProfileId }
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
if ((0, helpers_1.isStateNodeError)(error)) {
|
|
642
|
-
return {
|
|
643
|
-
...error,
|
|
644
|
-
at: error.at || new Date().toISOString(),
|
|
645
|
-
path: options.path || error.path,
|
|
646
|
-
retryable: options.retryable ?? error.retryable ?? false,
|
|
647
|
-
details: (0, helpers_1.compactMetadata)({ ...(error.details || {}), workerId: scope.id, taskId: scope.taskId })
|
|
648
|
-
};
|
|
649
|
-
}
|
|
650
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
651
|
-
return (0, helpers_1.structuredError)(options.code || "worker-runtime-error", message, {
|
|
652
|
-
path: options.path,
|
|
653
|
-
retryable: options.retryable ?? false,
|
|
654
|
-
details: { workerId: scope.id, taskId: scope.taskId }
|
|
655
|
-
});
|
|
656
|
-
}
|