cool-workflow 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +7 -5
- package/apps/architecture-review/app.json +2 -2
- package/apps/architecture-review/workflow.js +12 -12
- 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 +2 -2
- package/dist/cli/parseargv.js +2 -2
- package/dist/core/capability-table.js +13 -29
- package/dist/core/format/help.js +2 -2
- package/dist/core/hash.js +1 -1
- package/dist/core/multi-agent/candidate-scoring.js +1 -1
- package/dist/core/multi-agent/eval-replay.js +1 -1
- package/dist/core/multi-agent/runtime.js +2 -2
- package/dist/core/multi-agent/trust-policy.js +1 -1
- package/dist/core/pipeline/contract.js +1 -1
- package/dist/core/pipeline/drive-decide.js +1 -1
- package/dist/core/state/contract-migration.js +1 -1
- package/dist/core/state/migrations.js +2 -2
- package/dist/core/state/node-snapshot.js +1 -1
- package/dist/core/state/state-explosion/graph.js +4 -4
- package/dist/core/state/state-explosion/helpers.js +3 -3
- package/dist/core/state/state-explosion/report.js +1 -1
- package/dist/core/state/state-explosion/size.js +1 -1
- package/dist/core/state/state-node.js +2 -2
- package/dist/core/state/types.js +1 -1
- package/dist/core/trust/ledger.js +1 -1
- package/dist/core/trust/telemetry-attestation.js +3 -3
- package/dist/core/trust/telemetry-ledger.js +2 -2
- package/dist/core/version.js +1 -1
- package/dist/core/workflow-apps/app-schema.js +1 -1
- package/dist/mcp/dispatch.js +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/shell/agent-config.js +1 -1
- package/dist/shell/doctor.js +17 -4
- package/dist/shell/drive.js +21 -9
- package/dist/shell/execution-backend/agent.js +42 -10
- package/dist/shell/execution-backend/ci.js +1 -1
- package/dist/shell/execution-backend/container.js +1 -1
- package/dist/shell/execution-backend/envelopes.js +1 -1
- package/dist/shell/execution-backend/local.js +1 -1
- package/dist/shell/execution-backend/probes.js +1 -1
- package/dist/shell/execution-backend/registry.js +1 -1
- package/dist/shell/execution-backend/remote.js +1 -1
- package/dist/shell/execution-backend/types.js +1 -1
- package/dist/shell/fs-atomic.js +1 -1
- package/dist/shell/ledger-io.js +1 -1
- package/dist/shell/metrics-cli.js +4 -2
- package/dist/shell/multi-agent-host.js +1 -1
- package/dist/shell/reclamation-io.js +1 -1
- package/dist/shell/registry-cli.js +15 -0
- package/dist/shell/run-registry-io.js +1 -1
- package/dist/shell/sandbox-profile.js +1 -1
- package/dist/shell/scheduler-io.js +46 -37
- package/dist/shell/scheduling-io.js +32 -22
- package/dist/shell/telemetry-ledger-io.js +1 -1
- package/dist/shell/term.js +1 -1
- package/dist/shell/trust-audit.js +4 -3
- package/dist/shell/workbench-host.js +9 -1
- package/dist/shell/workbench.js +6 -11
- package/docs/agent-delegation-drive.7.md +2 -0
- package/docs/cli-mcp-parity.7.md +2 -0
- package/docs/contract-migration-tooling.7.md +2 -0
- package/docs/control-plane-scheduling.7.md +2 -0
- package/docs/durable-state-and-locking.7.md +2 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
- package/docs/execution-backends.7.md +2 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +2 -0
- package/docs/multi-agent-eval-replay-harness.7.md +2 -0
- package/docs/multi-agent-operator-ux.7.md +2 -0
- package/docs/node-snapshot-diff-replay.7.md +2 -0
- package/docs/observability-cost-accounting.7.md +4 -1
- package/docs/project-index.md +8 -3
- package/docs/real-execution-backends.7.md +2 -0
- package/docs/release-and-migration.7.md +2 -0
- package/docs/release-tooling.7.md +2 -0
- package/docs/remote-source-review.7.md +4 -4
- package/docs/report-verifiable-bundle.7.md +1 -1
- package/docs/run-registry-control-plane.7.md +2 -0
- package/docs/run-retention-reclamation.7.md +2 -0
- package/docs/security-trust-hardening.7.md +3 -1
- package/docs/state-explosion-management.7.md +2 -0
- package/docs/team-collaboration.7.md +2 -0
- package/docs/web-desktop-workbench.7.md +13 -1
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/agents/agent-adapter-core.js +22 -2
- package/scripts/agents/claude-p-agent.js +8 -3
- package/scripts/agents/gemini-agent.js +5 -1
- package/scripts/agents/opencode-agent.js +5 -1
- package/scripts/canonical-apps.js +4 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
//
|
|
12
12
|
// Evidence: SPEC/state-core.md "src/state-node.ts — StateNode lifecycle and
|
|
13
13
|
// contract gates", "StateNode transition matrix", "Deterministic id
|
|
14
|
-
// fallback", "Contract gates" (
|
|
14
|
+
// fallback", "Contract gates" (docs/rebuild/PLAN.md byte-compat item 7 — the double
|
|
15
15
|
// commit gate).
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.PipelineContractError = exports.PIPELINE_CONTRACT_SCHEMA_VERSION = exports.STATE_NODE_SCHEMA_VERSION = void 0;
|
|
@@ -115,7 +115,7 @@ function validatePipelineContract(contract) {
|
|
|
115
115
|
* check against; every real caller (shell/) passes `fs.existsSync` so the
|
|
116
116
|
* `missing-artifact-path` gate behaves exactly like the old build. Kept as
|
|
117
117
|
* an explicit parameter (never a top-level `require("node:fs")`) so this
|
|
118
|
-
* stays a pure core/ module per
|
|
118
|
+
* stays a pure core/ module per docs/rebuild/PLAN.md's core/shell split. */
|
|
119
119
|
function assertNodeSatisfiesContract(node, contract, stageId, pathExists = () => true) {
|
|
120
120
|
validatePipelineContract(contract);
|
|
121
121
|
const stage = contract.stages.find((candidate) => candidate.id === stageId);
|
package/dist/core/state/types.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// core/state/types.ts — the state-kernel's own type set.
|
|
3
3
|
//
|
|
4
|
-
// MILESTONE 3 (
|
|
4
|
+
// MILESTONE 3 (docs/rebuild/PLAN.md build order, step 3). Scoped to exactly what
|
|
5
5
|
// state-core.md's public surface needs: WorkflowRun and everything it
|
|
6
6
|
// carries, StateNode + its snapshot/replay/diff family, the pipeline
|
|
7
7
|
// contract shape, and the small persisted-record shapes validation.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// core/trust/ledger.ts — the cross-agent handoff ledger kernel.
|
|
3
3
|
//
|
|
4
|
-
// MILESTONE 8 (
|
|
4
|
+
// MILESTONE 8 (docs/rebuild/PLAN.md build order, step 8; SPEC/ledger-trust.md in
|
|
5
5
|
// full). Pure: computeLedgerDigest, buildLedgerProposal/Review,
|
|
6
6
|
// verifyLedgerEntry, applyLedgerProposal. Directory reads
|
|
7
7
|
// (listLedgerEntries/unionLedgerEntries) live in shell/ledger-io.ts, NOT
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// node:crypto's built-in ed25519 sign/verify (no npm dependency).
|
|
7
7
|
//
|
|
8
8
|
// `crypto.verify`/`crypto.createPublicKey` are allowed here per
|
|
9
|
-
//
|
|
9
|
+
// docs/rebuild/PLAN.md's lint carve-out for this exact file (Target shape,
|
|
10
10
|
// core/trust/telemetry-attestation.ts comment) — this remains otherwise
|
|
11
11
|
// pure (no fs, no process.env, no clock; `resolveTrustPublicKey`'s lazy
|
|
12
12
|
// `require("node:fs")` is the one exception, ported byte-identically
|
|
@@ -62,7 +62,7 @@ const crypto = __importStar(require("node:crypto"));
|
|
|
62
62
|
* recursively, AND maps a top-level `undefined` input to the literal
|
|
63
63
|
* string `"null"`. Divergent from `core/hash.ts`'s
|
|
64
64
|
* `ledgerStableStringify` exactly at the top-level-undefined edge (see
|
|
65
|
-
*
|
|
65
|
+
* docs/rebuild/PLAN.md byte-compat item 2). Re-exported under this file's own
|
|
66
66
|
* name (rather than importing `telemetryStableStringify` from
|
|
67
67
|
* core/hash.ts) because SPEC/ledger-trust.md's "Exported functions"
|
|
68
68
|
* list names `stableStringify` as a real export of THIS module — the
|
|
@@ -118,7 +118,7 @@ function normalizeReportedUsage(usage) {
|
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
120
|
/** Verify the agent's signed usage against the operator-provisioned
|
|
121
|
-
* public key. Two-arm check (
|
|
121
|
+
* public key. Two-arm check (docs/rebuild/PLAN.md byte-compat item 11): try the
|
|
122
122
|
* 5-field payload (with resultDigest) first; on a miss, retry the
|
|
123
123
|
* 4-field payload (old signers still verify). `coversResult` is set
|
|
124
124
|
* ONLY on a first-arm match — a 4-field fallback match never covers the
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
// MILESTONE 8. Byte-exact port of the old build's src/telemetry-ledger.ts
|
|
9
9
|
// verify-side logic. Uses core/hash.ts's `sha256`/`telemetryStableStringify`
|
|
10
|
-
// (see
|
|
10
|
+
// (see docs/rebuild/PLAN.md byte-compat item 2's key-omission-vs-null rule).
|
|
11
11
|
//
|
|
12
12
|
// Evidence: SPEC/ledger-trust.md "Telemetry ledger record", byte-compat
|
|
13
13
|
// items 2 and 12; plugins/cool-workflow/src/telemetry-ledger.ts:1-224.
|
|
@@ -43,7 +43,7 @@ function genesisPrevHash(runId) {
|
|
|
43
43
|
* recordHash itself. `reportedUsage`/`resultDigest` are OMITTED (not
|
|
44
44
|
* `null`) when absent, so a usage-only record's hash is byte-identical
|
|
45
45
|
* to a pre-result-coverage one (back-compat with old ledgers) — see
|
|
46
|
-
*
|
|
46
|
+
* docs/rebuild/PLAN.md byte-compat item 2. */
|
|
47
47
|
function recordHashInput(record) {
|
|
48
48
|
return (0, hash_1.telemetryStableStringify)({
|
|
49
49
|
schemaVersion: record.schemaVersion,
|
package/dist/core/version.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.MIN_SUPPORTED_RUN_STATE_SCHEMA_VERSION = exports.LEGACY_RUN_STATE_SCHEMA
|
|
|
7
7
|
// `cw version` output does not change bytes just because the code under it
|
|
8
8
|
// was rebuilt. See SPEC/cli-surface.md "Exact outputs > Version" and
|
|
9
9
|
// conformance/cases/version-basic.case.js (regex `/^\d+\.\d+\.\d+\n$/`).
|
|
10
|
-
exports.CURRENT_COOL_WORKFLOW_VERSION = "0.2.
|
|
10
|
+
exports.CURRENT_COOL_WORKFLOW_VERSION = "0.2.1";
|
|
11
11
|
// State-kernel schema version constants (SPEC/state-core.md "Version
|
|
12
12
|
// constants"). Pinned to the old build's src/version.ts byte-for-byte.
|
|
13
13
|
exports.WORKFLOW_APP_SCHEMA_VERSION = 1;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// `agent`, `artifact`, `subWorkflow`, `input`), and full manifest
|
|
5
5
|
// validation (`validateWorkflowApp`).
|
|
6
6
|
//
|
|
7
|
-
// MILESTONE 12 (
|
|
7
|
+
// MILESTONE 12 (docs/rebuild/PLAN.md build order; workflow-apps.md). Milestone 6+7
|
|
8
8
|
// built the minimal real subset needed to load ONE app and drive it
|
|
9
9
|
// end to end (see git history / the old header note this replaces).
|
|
10
10
|
// This milestone adds, on top of that, WITHOUT changing any existing
|
package/dist/mcp/dispatch.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// mcp/dispatch.ts — the generic MCP tool-call reader over
|
|
3
3
|
// core/capability-table.ts.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 2 (
|
|
5
|
+
// MILESTONE 2 (docs/rebuild/PLAN.md build order, step 2). Replaces the old build's
|
|
6
6
|
// 196-arm `callTool` switch (src/mcp/tool-call.ts) with a data-driven
|
|
7
7
|
// lookup: resolve the row by tool name, check its declared required-arg
|
|
8
8
|
// groups (SPEC/mcp.md's `McpBinding.requiredArgs`), re-base `cwd` if
|
package/dist/mcp/server.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// mcp/server.ts — the stdio JSON-RPC loop: initialize / tools/list /
|
|
3
3
|
// tools/call.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 2 (
|
|
5
|
+
// MILESTONE 2 (docs/rebuild/PLAN.md build order, step 2). Byte-exact port of the
|
|
6
6
|
// framing rules in SPEC/mcp.md's "JSON-RPC methods" / "Exact outputs" /
|
|
7
7
|
// "Invariants and error behavior" #9 / "Edge cases" sections:
|
|
8
8
|
// - transport: stdin/stdout, ONE JSON object per line, no
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/agent-config.ts — agent delegation config: env/file/flag resolution
|
|
3
3
|
// order, CW_HOME resolution, builtin:<name> expansion, PATH auto-detect.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 5 (
|
|
5
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/agent-config.ts.
|
|
7
7
|
//
|
|
8
8
|
// Resolution order per field: flags > env > a durable
|
package/dist/shell/doctor.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/doctor.ts — `cw doctor` environment diagnostics, in the spirit of
|
|
3
3
|
// `brew doctor`.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 5 (
|
|
5
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/doctor.ts's checks this milestone needs
|
|
7
7
|
// (node/agent/agent-binary/git/home-registry/repo-state). The `--onramp`
|
|
8
8
|
// section (buildDoctorOnramp) is later-milestone (reporting) territory and
|
|
@@ -167,7 +167,20 @@ function runDoctor(args = {}, env = process.env, cwd = process.cwd()) {
|
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
-
// 3.
|
|
170
|
+
// 3. Sandbox enforcement boundary — a fixed architectural fact (see
|
|
171
|
+
// docs/sandbox-profiles.7.md), not a host-specific problem to fix, so this
|
|
172
|
+
// is "ok" (informational), never "warn": CW validates sandbox policy and
|
|
173
|
+
// gates worker-output acceptance, but OS-level read/write/execute/network/
|
|
174
|
+
// env isolation is the execution host's responsibility, which this doctor
|
|
175
|
+
// run cannot itself verify. An "ok" check carries no `fix` line by
|
|
176
|
+
// convention (see the node/git checks above), so the pointer to the docs
|
|
177
|
+
// lives in `detail` instead.
|
|
178
|
+
checks.push({
|
|
179
|
+
name: "sandbox-enforceability",
|
|
180
|
+
status: "ok",
|
|
181
|
+
detail: "CW sandbox profiles validate policy and gate worker-output acceptance; OS-level read/write/execute/network/env isolation is the execution host's responsibility (see docs/sandbox-profiles.7.md's ENFORCEMENT section) — this doctor run cannot verify that host enforcement.",
|
|
182
|
+
});
|
|
183
|
+
// 4. git — only needed for commit provenance; a warn, not a hard fail.
|
|
171
184
|
const git = (0, node_child_process_1.spawnSync)("git", ["--version"], { encoding: "utf8", timeout: 5000 });
|
|
172
185
|
checks.push(!git.error && git.status === 0
|
|
173
186
|
? { name: "git", status: "ok", detail: `${String(git.stdout || "git").trim()}.` }
|
|
@@ -177,7 +190,7 @@ function runDoctor(args = {}, env = process.env, cwd = process.cwd()) {
|
|
|
177
190
|
detail: "git is not available — commit provenance (git HEAD) is recorded as absent.",
|
|
178
191
|
fix: "Install git (e.g. `brew install git`) if you want commit provenance.",
|
|
179
192
|
});
|
|
180
|
-
//
|
|
193
|
+
// 5. Home registry — the cross-repo run index lives here; must be writable.
|
|
181
194
|
const home = env.CW_HOME && String(env.CW_HOME).trim() ? path.resolve(String(env.CW_HOME)) : path.join(os.homedir(), ".local", "state", "cool-workflow");
|
|
182
195
|
checks.push(dirWritable(home)
|
|
183
196
|
? { name: "home-registry", status: "ok", detail: `Home registry location is writable (${home}).` }
|
|
@@ -187,7 +200,7 @@ function runDoctor(args = {}, env = process.env, cwd = process.cwd()) {
|
|
|
187
200
|
detail: `Home registry location is not writable: ${home}`,
|
|
188
201
|
fix: "Set $CW_HOME to a writable directory, or fix the permissions.",
|
|
189
202
|
});
|
|
190
|
-
//
|
|
203
|
+
// 6. Working-dir state — per-repo runs land under <cwd>/.cw.
|
|
191
204
|
const cwState = path.join(path.resolve(cwd), ".cw");
|
|
192
205
|
checks.push(dirWritable(cwState)
|
|
193
206
|
? { name: "repo-state", status: "ok", detail: `Run state location is writable (${cwState}).` }
|
package/dist/shell/drive.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// once per step and performs the spawn/commit/cache-write IO the
|
|
4
4
|
// decision names.
|
|
5
5
|
//
|
|
6
|
-
// MILESTONE 6+7 (combined; see
|
|
6
|
+
// MILESTONE 6+7 (combined; see docs/rebuild/PLAN.md Open risk 9/10 — the LARGEST
|
|
7
7
|
// milestone). Byte-exact port of the old build's src/drive.ts's
|
|
8
8
|
// imperative shell around the pure decision core now in
|
|
9
9
|
// core/pipeline/drive-decide.ts. Sub-workflow nesting and `--incremental`
|
|
@@ -76,7 +76,6 @@ const trust_audit_1 = require("./trust-audit");
|
|
|
76
76
|
const agent_config_1 = require("./agent-config");
|
|
77
77
|
const registry_1 = require("./execution-backend/registry");
|
|
78
78
|
const agent_1 = require("./execution-backend/agent");
|
|
79
|
-
const local_1 = require("./execution-backend/local");
|
|
80
79
|
const hash_1 = require("../core/hash");
|
|
81
80
|
const pipeline_1 = require("./pipeline");
|
|
82
81
|
const reporter_1 = require("./reporter");
|
|
@@ -384,6 +383,25 @@ function processSelectedTask(ctx, selectedId, preparedOutcome, deferPersist = fa
|
|
|
384
383
|
catch (error) {
|
|
385
384
|
return handleHop(ctx, selected, workerId, `result.md rejected: ${errMessage(error)}`, deferPersist, deferPersist ? run : undefined);
|
|
386
385
|
}
|
|
386
|
+
// Trust visibility (purely additive, no execution-behavior change): when
|
|
387
|
+
// the agent backend forwarded provider-namespace env vars (CW_/ANTHROPIC_/
|
|
388
|
+
// etc.) to the delegated child, record the NAMES (never values) as their
|
|
389
|
+
// own tamper-evident audit event, mirroring the worker.sub-workflow event
|
|
390
|
+
// pattern above. Only ever populated by execution-backend/agent.ts's
|
|
391
|
+
// recordedAgentHandle() — a no-op for every other backend.
|
|
392
|
+
const forwardedEnvVars = handle?.metadata?.forwardedEnvVars || [];
|
|
393
|
+
if (forwardedEnvVars.length) {
|
|
394
|
+
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
395
|
+
kind: "worker.agent-env",
|
|
396
|
+
decision: "delegated",
|
|
397
|
+
source: "runtime-derived",
|
|
398
|
+
workerId,
|
|
399
|
+
taskId: selected.id,
|
|
400
|
+
nodeId: selected.resultNodeId,
|
|
401
|
+
envVars: forwardedEnvVars,
|
|
402
|
+
metadata: { reason: "provider-namespace env vars forwarded from host process env to the delegated agent child" },
|
|
403
|
+
});
|
|
404
|
+
}
|
|
387
405
|
if (cachePath && fs.existsSync(manifest.resultPath)) {
|
|
388
406
|
writeResultCache(cachePath, fs.readFileSync(manifest.resultPath, "utf8"));
|
|
389
407
|
}
|
|
@@ -664,13 +682,7 @@ function prepareConcurrentOutcomes(ctx, batch) {
|
|
|
664
682
|
if (job) {
|
|
665
683
|
const sandboxPolicy = manifest.sandboxPolicy;
|
|
666
684
|
if (sandboxPolicy) {
|
|
667
|
-
|
|
668
|
-
for (const key of Object.keys(process.env)) {
|
|
669
|
-
if (/^(CW_|ANTHROPIC_|OPENAI_|GEMINI_|DEEPSEEK_|CODEX_|GOOGLE_|COHERE_|MISTRAL_|OLLAMA_|AZURE_|AWS_)/i.test(key)) {
|
|
670
|
-
filteredEnv[key] = process.env[key];
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
job.env = filteredEnv;
|
|
685
|
+
job.env = (0, agent_1.buildAgentChildEnv)(sandboxPolicy).env;
|
|
674
686
|
}
|
|
675
687
|
jobs.push(job);
|
|
676
688
|
jobTaskIds.push(taskId);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/execution-backend/agent.ts — agent-delegation pure helpers +
|
|
3
3
|
// concurrent batch fulfillment.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 5 (
|
|
5
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/execution-backend/agent.ts. This module holds
|
|
7
7
|
// the PURE data-transform helpers (invocation resolution, arg substitution,
|
|
8
8
|
// secret redaction, report parsing) plus the batch delegate-child spawn.
|
|
@@ -49,6 +49,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
49
49
|
};
|
|
50
50
|
})();
|
|
51
51
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.buildAgentChildEnv = buildAgentChildEnv;
|
|
52
53
|
exports.resolveAgentInvocation = resolveAgentInvocation;
|
|
53
54
|
exports.stripSecretArgs = stripSecretArgs;
|
|
54
55
|
exports.parseAgentReport = parseAgentReport;
|
|
@@ -70,6 +71,35 @@ const envelopes_1 = require("./envelopes");
|
|
|
70
71
|
function messageOf(error) {
|
|
71
72
|
return error instanceof Error ? error.message : String(error);
|
|
72
73
|
}
|
|
74
|
+
const AGENT_PROVIDER_KEY_ENV_RE = /^(CW_|ANTHROPIC_|OPENAI_|GEMINI_|DEEPSEEK_|CODEX_|GOOGLE_|COHERE_|MISTRAL_|OLLAMA_|AZURE_|AWS_)/i;
|
|
75
|
+
/** Build the env for a REAL spawned agent child under a sandbox policy: the
|
|
76
|
+
* policy's own PATH+HOME+expose/deny base (buildChildEnv), plus provider-key
|
|
77
|
+
* vars (the CW_, ANTHROPIC_, etc. prefixes), plus USER. USER is not a provider key, but a
|
|
78
|
+
* real vendor CLI (claude, at least) reads it to resolve its own OS-level
|
|
79
|
+
* login/keychain credential in headless mode -- buildChildEnv alone keeps
|
|
80
|
+
* only PATH+HOME under the readonly policy, so a spawned agent that IS
|
|
81
|
+
* logged in interactively reported "Not logged in" here. Found live: PATH+
|
|
82
|
+
* HOME alone reproduces it, adding USER back fixes it, LOGNAME alone does
|
|
83
|
+
* not. This is the ONE place that builds this env -- the single-request
|
|
84
|
+
* (runAgentProcess) and concurrent-batch (shell/drive.ts) spawn paths both
|
|
85
|
+
* call it, so the allowlist cannot drift into a second silent copy again.
|
|
86
|
+
* Returns the forwarded var NAMES too (never values) for the
|
|
87
|
+
* worker.agent-env trust-audit event. */
|
|
88
|
+
function buildAgentChildEnv(policy, baseEnv = process.env) {
|
|
89
|
+
const env = (0, local_1.buildChildEnv)(policy, baseEnv);
|
|
90
|
+
const forwarded = [];
|
|
91
|
+
for (const key of Object.keys(baseEnv)) {
|
|
92
|
+
if (AGENT_PROVIDER_KEY_ENV_RE.test(key)) {
|
|
93
|
+
env[key] = baseEnv[key];
|
|
94
|
+
forwarded.push(key);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (baseEnv.USER !== undefined && env.USER === undefined) {
|
|
98
|
+
env.USER = baseEnv.USER;
|
|
99
|
+
forwarded.push("USER");
|
|
100
|
+
}
|
|
101
|
+
return { env, forwarded };
|
|
102
|
+
}
|
|
73
103
|
/** Resolve the agent invocation from the request delegation > env.
|
|
74
104
|
* Vendor-neutral; the durable file config is folded in by the drive layer
|
|
75
105
|
* before this point (see shell/agent-config.ts's resolveAgentConfig). */
|
|
@@ -203,7 +233,7 @@ function substituteAgentArg(arg, subst) {
|
|
|
203
233
|
/** Build the recorded process handle for the envelope — secret-stripped +
|
|
204
234
|
* the agent-reported model. Same SHAPE that lands in provenance, never in
|
|
205
235
|
* evidence. */
|
|
206
|
-
function recordedAgentHandle(binary, endpoint, recordedArgs, model, reportedModel, reportedUsage, usageSignature) {
|
|
236
|
+
function recordedAgentHandle(binary, endpoint, recordedArgs, model, reportedModel, reportedUsage, usageSignature, forwardedEnvVars) {
|
|
207
237
|
const ref = binary ? [binary, ...recordedArgs].join(" ") : endpoint || "";
|
|
208
238
|
return {
|
|
209
239
|
kind: "process",
|
|
@@ -217,6 +247,7 @@ function recordedAgentHandle(binary, endpoint, recordedArgs, model, reportedMode
|
|
|
217
247
|
reportedModel,
|
|
218
248
|
...(reportedUsage ? { reportedUsage } : {}),
|
|
219
249
|
...(usageSignature ? { usageSignature } : {}),
|
|
250
|
+
...(forwardedEnvVars && forwardedEnvVars.length ? { forwardedEnvVars } : {}),
|
|
220
251
|
},
|
|
221
252
|
};
|
|
222
253
|
}
|
|
@@ -365,17 +396,18 @@ function runAgentProcess(descriptor, policy, request, label, attestation) {
|
|
|
365
396
|
const realArgs = resolved.rawArgs.map((arg) => substituteAgentArg(arg, subst));
|
|
366
397
|
const recordedArgs = stripSecretArgs(realArgs);
|
|
367
398
|
let outcome;
|
|
399
|
+
// Names only, never values — for the worker.agent-env trust-audit event
|
|
400
|
+
// below. Stays empty for a preparedAgentOutcome (a batch-delegated child
|
|
401
|
+
// that already ran elsewhere; this code path forwards nothing itself).
|
|
402
|
+
let forwardedEnvVars = [];
|
|
368
403
|
if (request.preparedAgentOutcome) {
|
|
369
404
|
outcome = request.preparedAgentOutcome;
|
|
370
405
|
}
|
|
371
406
|
else {
|
|
372
407
|
const streamStderr = shouldStreamAgentStderr(process.env, Boolean(process.stderr.isTTY));
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
childEnv[key] = process.env[key];
|
|
377
|
-
}
|
|
378
|
-
}
|
|
408
|
+
const built = buildAgentChildEnv(policy);
|
|
409
|
+
const childEnv = built.env;
|
|
410
|
+
forwardedEnvVars = built.forwarded;
|
|
379
411
|
const child = (0, node_child_process_1.spawnSync)(resolved.binary, realArgs, {
|
|
380
412
|
cwd: request.cwd,
|
|
381
413
|
env: childEnv,
|
|
@@ -392,7 +424,7 @@ function runAgentProcess(descriptor, policy, request, label, attestation) {
|
|
|
392
424
|
};
|
|
393
425
|
}
|
|
394
426
|
if (outcome.spawnError) {
|
|
395
|
-
const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, "unreported");
|
|
427
|
+
const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, "unreported", undefined, undefined, forwardedEnvVars);
|
|
396
428
|
return (0, envelopes_1.refusedEnvelope)(descriptor, policy, label, "delegation-failed", `agent process failed to spawn: ${outcome.spawnError}`, {
|
|
397
429
|
...attestation,
|
|
398
430
|
handle: handleOut,
|
|
@@ -402,7 +434,7 @@ function runAgentProcess(descriptor, policy, request, label, attestation) {
|
|
|
402
434
|
const stdout = outcome.stdout;
|
|
403
435
|
const report = parseAgentReport(stdout);
|
|
404
436
|
const reportedModel = report.model && report.model.trim() ? report.model.trim() : "unreported";
|
|
405
|
-
const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, reportedModel, report.usage, report.usageSignature);
|
|
437
|
+
const handleOut = recordedAgentHandle(resolved.binary, undefined, recordedArgs, resolved.model, reportedModel, report.usage, report.usageSignature, forwardedEnvVars);
|
|
406
438
|
if (exitCode === null) {
|
|
407
439
|
return (0, envelopes_1.refusedEnvelope)(descriptor, policy, label, "delegation-failed", `agent process returned no exit code (timed out or killed)`, { ...attestation, handle: handleOut });
|
|
408
440
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// shell/execution-backend/ci.ts — the ci delegating driver.
|
|
3
3
|
//
|
|
4
|
-
// MILESTONE 5 (
|
|
4
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). The ci driver shares its
|
|
5
5
|
// entire HTTP-delegation body with the remote driver (byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/execution-backend.ts, which also shares
|
|
7
7
|
// `runHttpDelegation` between the two); this file just re-exports the ci
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// shell/execution-backend/container.ts — the container delegating driver.
|
|
3
3
|
//
|
|
4
|
-
// MILESTONE 5 (
|
|
4
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
5
5
|
// plugins/cool-workflow/src/execution-backend.ts's container handle builder
|
|
6
6
|
// (:1068-1075) and `runContainer` (:720-792).
|
|
7
7
|
//
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// every delegating driver (container/remote/ci/agent) plus the registry's
|
|
4
4
|
// own refusal path.
|
|
5
5
|
//
|
|
6
|
-
// MILESTONE 5 (
|
|
6
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of the
|
|
7
7
|
// `delegatedEnvelope` (src/execution-backend.ts:680-713) and
|
|
8
8
|
// `refusedEnvelope` (:1095-1126) helpers, factored into one shared module
|
|
9
9
|
// since every delegating driver builds the identical shape (byte-stable
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/execution-backend/local.ts — the local-execution driver body
|
|
3
3
|
// (executeLocal) shared by the node/bun/shell built-in drivers.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 5 (
|
|
5
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/execution-backend.ts's `executeLocal` (lines
|
|
7
7
|
// 547-626) plus the leaf helpers it needs (sha256/hasExecutable/messageOf).
|
|
8
8
|
//
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// shell/execution-backend/probes.ts — per-backend readiness probe bodies.
|
|
3
3
|
//
|
|
4
|
-
// MILESTONE 5 (
|
|
4
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
5
5
|
// plugins/cool-workflow/src/execution-backend/probes.ts. Each probe is a
|
|
6
6
|
// pure free function of the host (PATH + configured env); the registry's
|
|
7
7
|
// `probeBackend` wraps these with the descriptor-derived envelope.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// registerBackend, resolveBackendSelection, attestSandbox, probeBackend,
|
|
4
4
|
// runBackend, and the CLI-facing inspection payloads.
|
|
5
5
|
//
|
|
6
|
-
// MILESTONE 5 (
|
|
6
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
7
7
|
// plugins/cool-workflow/src/execution-backend.ts (the parts not carved into
|
|
8
8
|
// local.ts/container.ts/remote.ts/ci.ts/agent.ts/probes.ts).
|
|
9
9
|
//
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/execution-backend/remote.ts — remote/ci delegating drivers (shared
|
|
3
3
|
// HTTP-delegation body) + handle builders.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 5 (
|
|
5
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/execution-backend.ts's `runHttpDelegation`
|
|
7
7
|
// (:821-876), `remoteHandle` (:1077-1084), `ciHandle` (:1086-1093), and
|
|
8
8
|
// `delegateChildScript` (:801-811).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// shell/execution-backend/types.ts — plain data shapes for the driver layer.
|
|
3
3
|
//
|
|
4
|
-
// MILESTONE 5 (
|
|
4
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of the shapes
|
|
5
5
|
// in the old build's src/types/execution-backend.ts and the sandbox slice of
|
|
6
6
|
// src/types/sandbox.ts that this subsystem needs. Types only — no logic — so
|
|
7
7
|
// this file is safe to import from both shell/ (impure) and any future core/
|
package/dist/shell/fs-atomic.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// `writeJson` here, so the write bytes stay exactly one place.
|
|
6
6
|
//
|
|
7
7
|
// Evidence: SPEC/state-core.md "Write ordering and atomic rules", "Lock
|
|
8
|
-
// protocol";
|
|
8
|
+
// protocol"; docs/rebuild/PLAN.md byte-compat items 1 and 6.
|
|
9
9
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
10
|
if (k2 === undefined) k2 = k;
|
|
11
11
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
package/dist/shell/ledger-io.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
//
|
|
6
6
|
// MILESTONE 8. Byte-exact port of the old build's src/ledger.ts stage-2
|
|
7
7
|
// git-transport functions (listLedgerEntries, unionLedgerEntries), split
|
|
8
|
-
// out per
|
|
8
|
+
// out per docs/rebuild/PLAN.md's core/shell rule since these two functions are the
|
|
9
9
|
// ONLY impure ones in the old ledger.ts module.
|
|
10
10
|
//
|
|
11
11
|
// Evidence: SPEC/ledger-trust.md "Handoff ledger entry" (listLedgerEntries/
|
|
@@ -72,12 +72,14 @@ function metricsShowCli(runId, args) {
|
|
|
72
72
|
const policy = (0, observability_1.loadCostPolicy)(args, pluginRoot());
|
|
73
73
|
return (0, observability_1.showMetricsReport)(run, { now: nowOf(args), policy });
|
|
74
74
|
}
|
|
75
|
-
/** `cw metrics summary [--scope repo|home] [--pricing ...] [--now ISO]`.
|
|
75
|
+
/** `cw metrics summary [--scope repo|home] [--pricing ...] [--now ISO] [--limit N]`.
|
|
76
|
+
* `--limit` defaults to RunRegistry.list()'s own 50-record floor when omitted. */
|
|
76
77
|
function metricsSummaryCli(args) {
|
|
77
78
|
const cwd = invocationCwd(args);
|
|
78
79
|
const scope = args.scope === "home" ? "home" : "repo";
|
|
79
80
|
const registry = new run_registry_io_1.RunRegistry(cwd);
|
|
80
|
-
const
|
|
81
|
+
const limit = args.limit === undefined ? undefined : Number(args.limit);
|
|
82
|
+
const listing = registry.list({ scope, includeArchived: true, limit });
|
|
81
83
|
const inputs = [];
|
|
82
84
|
let unreadableRuns = 0;
|
|
83
85
|
for (const record of listing.records) {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// deterministic step order), hostBlackboard's action dispatch. The
|
|
10
10
|
// `summaries.workers/candidates/feedback/commits/operator` blocks are
|
|
11
11
|
// simplified real projections (not the full operator-ux/multi-agent-
|
|
12
|
-
// operator-ux module — out of this milestone's scope per
|
|
12
|
+
// operator-ux module — out of this milestone's scope per docs/rebuild/PLAN.md's
|
|
13
13
|
// build-order list) — every FIELD the conformance cases actually assert
|
|
14
14
|
// on (`summaries.topologies.officialTopologies`, the envelope's fixed key
|
|
15
15
|
// set, `ids.*`) is still byte-exact; the parts no case reaches are
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/reclamation-io.ts — gc plan/run/verify's write-ahead reclamation
|
|
3
3
|
// transaction, plus the orphan-run sweep and the clone cache gc.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 10 (
|
|
5
|
+
// MILESTONE 10 (docs/rebuild/PLAN.md build order, step 10). Byte-exact port of the
|
|
6
6
|
// old build's src/reclamation.ts + src/reclamation/hash.ts +
|
|
7
7
|
// src/run-registry/{gc,orphans}.ts + src/clones.ts. Reuses
|
|
8
8
|
// shell/fs-atomic.ts's `withFileLock` directly (no reimplementation, per
|
|
@@ -58,6 +58,7 @@ exports.routineCreateCli = routineCreateCli;
|
|
|
58
58
|
exports.routineListCli = routineListCli;
|
|
59
59
|
exports.routineDeleteCli = routineDeleteCli;
|
|
60
60
|
exports.routineFireCli = routineFireCli;
|
|
61
|
+
exports.resolveRoutineFirePayload = resolveRoutineFirePayload;
|
|
61
62
|
exports.routineEventsCli = routineEventsCli;
|
|
62
63
|
exports.registryRefreshCli = registryRefreshCli;
|
|
63
64
|
exports.registryShowCli = registryShowCli;
|
|
@@ -79,6 +80,7 @@ exports.orphansListCli = orphansListCli;
|
|
|
79
80
|
exports.orphansGcCli = orphansGcCli;
|
|
80
81
|
exports.clonesListCli = clonesListCli;
|
|
81
82
|
exports.clonesGcCli = clonesGcCli;
|
|
83
|
+
const fs = __importStar(require("node:fs"));
|
|
82
84
|
const path = __importStar(require("node:path"));
|
|
83
85
|
const run_registry_io_1 = require("./run-registry-io");
|
|
84
86
|
const pipeline_1 = require("./pipeline");
|
|
@@ -149,6 +151,19 @@ function routineDeleteCli(id, options = {}) {
|
|
|
149
151
|
function routineFireCli(kind, payload, options = {}) {
|
|
150
152
|
return new scheduler_io_1.RoutineTriggerBridge(resolveCwd(options)).fire(kind, payload);
|
|
151
153
|
}
|
|
154
|
+
/** Resolves a `routine fire` payload: a `--payload-path`/positional file wins
|
|
155
|
+
* (parsed as JSON) over the raw CLI/MCP options bag. The file read lives
|
|
156
|
+
* here, in the shell layer, not in core/capability-table.ts. */
|
|
157
|
+
function resolveRoutineFirePayload(payloadPath, options) {
|
|
158
|
+
if (!payloadPath)
|
|
159
|
+
return options;
|
|
160
|
+
try {
|
|
161
|
+
return JSON.parse(fs.readFileSync(payloadPath, "utf8"));
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
throw new Error(`Failed to parse payload file "${payloadPath}": ${String((e && e.message) || e)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
152
167
|
function routineEventsCli(id, options = {}) {
|
|
153
168
|
return new scheduler_io_1.RoutineTriggerBridge(resolveCwd(options)).events(id);
|
|
154
169
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/run-registry-io.ts — the on-disk run registry: index/queue/history
|
|
3
3
|
// persistence, lifecycle derivation, search/resume/archive/rerun.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 10 (
|
|
5
|
+
// MILESTONE 10 (docs/rebuild/PLAN.md build order, step 10). Byte-exact port of the
|
|
6
6
|
// old build's src/run-registry.ts + src/run-registry/{derive,policy,
|
|
7
7
|
// queue}.ts. The registry is a DERIVED, rebuildable index over each repo's
|
|
8
8
|
// `.cw/runs/<id>/state.json` (the single source of truth, never mutated
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// shell/sandbox-profile.ts — the 4 bundled sandbox profiles, resolution,
|
|
3
3
|
// validation, and the runtime read/write/command/network checks.
|
|
4
4
|
//
|
|
5
|
-
// MILESTONE 5 (
|
|
5
|
+
// MILESTONE 5 (docs/rebuild/PLAN.md build order, step 5). Byte-exact port of
|
|
6
6
|
// plugins/cool-workflow/src/sandbox-profile.ts.
|
|
7
7
|
//
|
|
8
8
|
// Evidence: SPEC/execution-backend.md "Sandbox profiles".
|