cool-workflow 0.1.79 → 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 +51 -3
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +64 -0
- package/apps/architecture-review-fast/workflow.js +153 -0
- 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 +132 -17
- package/dist/capability-registry.js +138 -168
- package/dist/cli.js +97 -98
- 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 +79 -6
- package/dist/error-feedback.js +8 -4
- package/dist/evidence-reasoning.js +3 -3
- 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 +73 -421
- package/dist/mcp-server.js +79 -183
- 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/lifecycle-operations.js +2 -1
- package/dist/orchestrator/report.js +8 -0
- package/dist/orchestrator.js +26 -9
- package/dist/reclamation.js +26 -21
- package/dist/run-export.js +494 -25
- 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 +89 -597
- 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 +165 -304
- 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 +71 -0
- package/docs/canonical-workflow-apps.7.md +37 -0
- package/docs/cli-mcp-parity.7.md +16 -0
- package/docs/contract-migration-tooling.7.md +6 -0
- package/docs/control-plane-scheduling.7.md +6 -0
- package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
- package/docs/durable-state-and-locking.7.md +8 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +6 -0
- package/docs/execution-backends.7.md +6 -0
- package/docs/index.md +2 -0
- package/docs/launch/demo.tape +28 -0
- package/docs/launch/launch-kit.md +96 -17
- package/docs/launch/pre-launch-checklist.md +53 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +8 -0
- package/docs/multi-agent-eval-replay-harness.7.md +6 -0
- package/docs/multi-agent-operator-ux.7.md +6 -0
- package/docs/multi-agent-trust-policy-audit.7.md +27 -0
- package/docs/node-snapshot-diff-replay.7.md +6 -0
- package/docs/observability-cost-accounting.7.md +6 -0
- package/docs/project-index.md +27 -6
- package/docs/real-execution-backends.7.md +6 -0
- package/docs/release-and-migration.7.md +8 -0
- package/docs/release-tooling.7.md +6 -0
- package/docs/routines.md +23 -0
- package/docs/run-registry-control-plane.7.md +89 -2
- package/docs/run-retention-reclamation.7.md +8 -0
- package/docs/source-context-profiles.7.md +119 -0
- package/docs/state-explosion-management.7.md +13 -0
- package/docs/team-collaboration.7.md +6 -0
- package/docs/trust-model.md +267 -0
- package/docs/unix-principles.md +49 -1
- package/docs/vendor-manifest-loadability.7.md +43 -0
- package/docs/web-desktop-workbench.7.md +6 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +142 -0
- package/package.json +4 -1
- package/scripts/agents/builtin-templates.json +7 -0
- package/scripts/agents/claude-p-agent.js +129 -43
- package/scripts/architecture-review-fast.js +362 -0
- package/scripts/bump-version.js +5 -10
- package/scripts/canonical-apps-list.js +64 -0
- package/scripts/canonical-apps.js +36 -4
- package/scripts/coverage-gate.js +211 -0
- 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/source-context.js +291 -0
- package/scripts/version-sync-check.js +5 -7
- package/skills/ci-triage/SKILL.md +50 -0
- package/skills/ci-triage/agents/openai.yaml +4 -0
- package/skills/cool-workflow/SKILL.md +4 -1
- package/skills/deploy-check/SKILL.md +55 -0
- package/skills/deploy-check/agents/openai.yaml +4 -0
- package/skills/design-qa/SKILL.md +49 -0
- package/skills/design-qa/agents/openai.yaml +4 -0
- package/skills/pr-review/SKILL.md +45 -0
- package/skills/pr-review/agents/openai.yaml +4 -0
- package/dist/capability-dispatcher.js +0 -86
package/dist/trust-audit.js
CHANGED
|
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.TRUST_AUDIT_SCHEMA_VERSION = void 0;
|
|
7
|
+
exports.trustAuditGenesis = trustAuditGenesis;
|
|
8
|
+
exports.verifyTrustAudit = verifyTrustAudit;
|
|
7
9
|
exports.ensureTrustAudit = ensureTrustAudit;
|
|
8
10
|
exports.recordTrustAuditEvent = recordTrustAuditEvent;
|
|
9
11
|
exports.recordSandboxPathDecision = recordSandboxPathDecision;
|
|
@@ -22,17 +24,139 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
22
24
|
const node_path_1 = __importDefault(require("node:path"));
|
|
23
25
|
const state_1 = require("./state");
|
|
24
26
|
const evidence_grounding_1 = require("./evidence-grounding");
|
|
27
|
+
const execution_backend_1 = require("./execution-backend");
|
|
28
|
+
const telemetry_attestation_1 = require("./telemetry-attestation");
|
|
25
29
|
exports.TRUST_AUDIT_SCHEMA_VERSION = 1;
|
|
30
|
+
// ---- Tamper-evidence chain (v0.1.81) --------------------------------------
|
|
31
|
+
// Same discipline as telemetry-ledger.ts / reclamation.ts: the event log is
|
|
32
|
+
// hash-chained in APPEND order, and verifyTrustAudit recomputes every hash
|
|
33
|
+
// independently (never trusts a stored value), so an edited or removed event is
|
|
34
|
+
// detected. Durability (fsync) only guards against power loss; this guards
|
|
35
|
+
// against post-hoc edits — the threat an external auditor actually cares about.
|
|
36
|
+
//
|
|
37
|
+
// THREAT MODEL (be honest about the limit): the genesis is sha256(runId), so this
|
|
38
|
+
// detects casual/partial tampering, accidental corruption, truncation, removal,
|
|
39
|
+
// and forged-unchained lines — but NOT a determined local writer who re-chains the
|
|
40
|
+
// WHOLE log with this module's own sha256 after an edit. That is the same limit
|
|
41
|
+
// reclamation.ts's tombstone chain has, and it is INHERENT to a local, self-
|
|
42
|
+
// recomputable chain: closing it needs an anchor the writer cannot reproduce.
|
|
43
|
+
// CW cannot self-sign that anchor — by design CW holds NO private key (see
|
|
44
|
+
// telemetry-attestation.ts: "CW never holds the private key"; the AGENT signs its
|
|
45
|
+
// usage, CW only VERIFIES with the operator-provisioned public half). The single
|
|
46
|
+
// cryptographic anchor that exists is therefore the agent's telemetry signature,
|
|
47
|
+
// which binds agent-reported USAGE (worker-isolation cross-links the chain into it)
|
|
48
|
+
// — it does NOT cover CW-only sandbox/policy/commit-gate decisions, which have no
|
|
49
|
+
// external signer. For those, the only stronger guarantee is operational: commit
|
|
50
|
+
// events.jsonl to an external append-only medium (git history / a remote log) the
|
|
51
|
+
// local writer cannot rewrite. The chain is a strict upgrade over a bare append-
|
|
52
|
+
// only log, not a substitute for an external anchor — and that anchor is not
|
|
53
|
+
// something CW can mint for itself.
|
|
54
|
+
/** Single source of truth for a run's audit-paths object: the schemaVersion plus
|
|
55
|
+
* the three derived file paths under auditRoot(run). ensureTrustAudit /
|
|
56
|
+
* refreshTrustAudit spread this, and createEventId reads .eventLogPath from it, so
|
|
57
|
+
* the path-derivation rule lives in exactly one place. */
|
|
58
|
+
function trustAuditPaths(run) {
|
|
59
|
+
const dir = auditRoot(run);
|
|
60
|
+
return {
|
|
61
|
+
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
62
|
+
eventLogPath: node_path_1.default.join(dir, "events.jsonl"),
|
|
63
|
+
summaryPath: node_path_1.default.join(dir, "summary.json"),
|
|
64
|
+
indexPath: node_path_1.default.join(dir, "index.json")
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Genesis prevHash for a run's chain (no prior event). */
|
|
68
|
+
function trustAuditGenesis(runId) {
|
|
69
|
+
return (0, execution_backend_1.sha256)(`cw-trust-audit:${runId}`);
|
|
70
|
+
}
|
|
71
|
+
/** Canonical bytes the eventHash binds: every field EXCEPT eventHash itself
|
|
72
|
+
* (prevEventHash included, so the chain link is bound).
|
|
73
|
+
*
|
|
74
|
+
* The hash binds the PERSISTED form. `stableStringify` keeps an undefined-valued
|
|
75
|
+
* key as `"k":null`, but the `JSON.stringify` that writes events.jsonl DROPS such
|
|
76
|
+
* keys — so without this round-trip the record-time hash (over the in-memory event,
|
|
77
|
+
* which can carry nested undefined like an absent dispatchId in worker-sandbox
|
|
78
|
+
* metadata) would never match the verify-time hash (over the parsed-from-disk
|
|
79
|
+
* event), false-failing legitimate worker events as `trust-audit-digest-mismatch`.
|
|
80
|
+
* Round-tripping makes record-time == verify-time. It is identity for events with
|
|
81
|
+
* no undefined fields, so existing intact chains hash unchanged. */
|
|
82
|
+
function computeEventHash(event) {
|
|
83
|
+
const { eventHash, ...rest } = event;
|
|
84
|
+
return (0, execution_backend_1.sha256)((0, telemetry_attestation_1.stableStringify)(JSON.parse(JSON.stringify(rest))));
|
|
85
|
+
}
|
|
86
|
+
/** The hash to chain the NEXT event to: the stored eventHash, or a recompute for
|
|
87
|
+
* a legacy event written before the chain existed. */
|
|
88
|
+
function chainHashOf(event) {
|
|
89
|
+
return event.eventHash || computeEventHash(event);
|
|
90
|
+
}
|
|
91
|
+
/** Read events in FILE (append) order, tolerating corrupt lines — one bad line
|
|
92
|
+
* must not brick the whole audit read surface (it is counted, not thrown). The
|
|
93
|
+
* chain links append order, so this is the order verification walks. */
|
|
94
|
+
function readEventsRaw(eventLogPath) {
|
|
95
|
+
if (!node_fs_1.default.existsSync(eventLogPath))
|
|
96
|
+
return { events: [], corruptLines: 0 };
|
|
97
|
+
let corruptLines = 0;
|
|
98
|
+
const events = [];
|
|
99
|
+
for (const line of node_fs_1.default.readFileSync(eventLogPath, "utf8").split(/\n/g)) {
|
|
100
|
+
const trimmed = line.trim();
|
|
101
|
+
if (!trimmed)
|
|
102
|
+
continue;
|
|
103
|
+
try {
|
|
104
|
+
events.push(JSON.parse(trimmed));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
corruptLines += 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { events, corruptLines };
|
|
111
|
+
}
|
|
112
|
+
/** Re-prove the run's trust-audit chain: prevEventHash linkage (append order) +
|
|
113
|
+
* per-event hash recompute. A corrupt line, an edited event, or a removed event
|
|
114
|
+
* flips verified=false. Legacy events without a hash are reported as `unchained`
|
|
115
|
+
* (skipped), NOT treated as a forgery — they predate the chain. */
|
|
116
|
+
function verifyTrustAudit(run) {
|
|
117
|
+
const audit = ensureTrustAudit(run);
|
|
118
|
+
const { events, corruptLines } = readEventsRaw(audit.eventLogPath);
|
|
119
|
+
const checks = [];
|
|
120
|
+
let verified = corruptLines === 0;
|
|
121
|
+
if (corruptLines > 0)
|
|
122
|
+
checks.push({ name: "parse", pass: false, code: "trust-audit-corrupt-line" });
|
|
123
|
+
let chained = 0;
|
|
124
|
+
let unchained = 0;
|
|
125
|
+
let expectedPrev = trustAuditGenesis(run.id);
|
|
126
|
+
for (let i = 0; i < events.length; i++) {
|
|
127
|
+
const event = events[i];
|
|
128
|
+
const recomputed = computeEventHash(event);
|
|
129
|
+
if (event.eventHash === undefined) {
|
|
130
|
+
unchained += 1;
|
|
131
|
+
expectedPrev = recomputed; // advance the chain over legacy events
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
chained += 1;
|
|
135
|
+
if (event.eventHash !== recomputed) {
|
|
136
|
+
verified = false;
|
|
137
|
+
checks.push({ name: `event-hash[${i}]`, pass: false, code: "trust-audit-digest-mismatch" });
|
|
138
|
+
}
|
|
139
|
+
if (event.prevEventHash !== undefined && event.prevEventHash !== expectedPrev) {
|
|
140
|
+
verified = false;
|
|
141
|
+
checks.push({ name: `chain-link[${i}]`, pass: false, code: "trust-audit-chain-broken" });
|
|
142
|
+
}
|
|
143
|
+
expectedPrev = event.eventHash;
|
|
144
|
+
}
|
|
145
|
+
// A log with ANY chained event must have EVERY event chained: a single run is
|
|
146
|
+
// written by one code version, so it is all-chained (chain era) or all-legacy
|
|
147
|
+
// (pre-chain). An unchained (eventHash-less) line mixed into a chained log is a
|
|
148
|
+
// forgery attempt — drop the hash to be waved through as "legacy" — so it fails.
|
|
149
|
+
if (chained > 0 && unchained > 0) {
|
|
150
|
+
verified = false;
|
|
151
|
+
checks.push({ name: "unchained-events", pass: false, code: "trust-audit-unchained-event" });
|
|
152
|
+
}
|
|
153
|
+
return { present: events.length > 0, verified, eventCount: events.length, chained, unchained, corruptLines, checks };
|
|
154
|
+
}
|
|
26
155
|
function ensureTrustAudit(run) {
|
|
27
156
|
const auditDir = auditRoot(run);
|
|
28
157
|
node_fs_1.default.mkdirSync(auditDir, { recursive: true });
|
|
29
158
|
run.paths.auditDir = auditDir;
|
|
30
|
-
const audit = {
|
|
31
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
32
|
-
eventLogPath: node_path_1.default.join(auditDir, "events.jsonl"),
|
|
33
|
-
summaryPath: node_path_1.default.join(auditDir, "summary.json"),
|
|
34
|
-
indexPath: node_path_1.default.join(auditDir, "index.json")
|
|
35
|
-
};
|
|
159
|
+
const audit = { ...trustAuditPaths(run) };
|
|
36
160
|
run.audit = audit;
|
|
37
161
|
if (!node_fs_1.default.existsSync(audit.eventLogPath))
|
|
38
162
|
node_fs_1.default.writeFileSync(audit.eventLogPath, "", "utf8");
|
|
@@ -90,6 +214,12 @@ function recordTrustAuditEvent(run, input) {
|
|
|
90
214
|
parentEventIds: unique(input.parentEventIds || []).sort(),
|
|
91
215
|
metadata: scrubMetadata(input.metadata || {})
|
|
92
216
|
});
|
|
217
|
+
// Tamper-evidence chain: link this event to the prior one (append order) and
|
|
218
|
+
// bind its content with eventHash BEFORE persisting. verifyTrustAudit recomputes
|
|
219
|
+
// both independently, so a later edit or removal is detectable.
|
|
220
|
+
const prior = readEventsRaw(audit.eventLogPath).events;
|
|
221
|
+
event.prevEventHash = prior.length ? chainHashOf(prior[prior.length - 1]) : trustAuditGenesis(run.id);
|
|
222
|
+
event.eventHash = computeEventHash(event);
|
|
93
223
|
// DURABLE append (v0.1.40 self-audit P1): the audit log is the one artifact
|
|
94
224
|
// whose loss breaks audit-completeness, so fsync it before returning — never a
|
|
95
225
|
// bare appendFileSync, which can drop the last event on power loss.
|
|
@@ -127,15 +257,7 @@ function recordHostAttestation(run, input) {
|
|
|
127
257
|
}
|
|
128
258
|
function listTrustAuditEvents(run) {
|
|
129
259
|
const audit = ensureTrustAudit(run);
|
|
130
|
-
|
|
131
|
-
return [];
|
|
132
|
-
return node_fs_1.default
|
|
133
|
-
.readFileSync(audit.eventLogPath, "utf8")
|
|
134
|
-
.split(/\n/g)
|
|
135
|
-
.map((line) => line.trim())
|
|
136
|
-
.filter(Boolean)
|
|
137
|
-
.map((line) => JSON.parse(line))
|
|
138
|
-
.sort(compareEvents);
|
|
260
|
+
return readEventsRaw(audit.eventLogPath).events.sort(compareEvents);
|
|
139
261
|
}
|
|
140
262
|
/** Search audit events by kind, worker, or candidate (v0.1.65).
|
|
141
263
|
* Filters are AND-ed; empty filters match all. */
|
|
@@ -159,6 +281,7 @@ function summarizeTrustAudit(run) {
|
|
|
159
281
|
runId: run.id,
|
|
160
282
|
generatedAt: new Date().toISOString(),
|
|
161
283
|
eventCount: events.length,
|
|
284
|
+
integrity: verifyTrustAudit(run),
|
|
162
285
|
eventLogPath: audit.eventLogPath,
|
|
163
286
|
indexPath: audit.indexPath,
|
|
164
287
|
summaryPath: audit.summaryPath,
|
|
@@ -255,12 +378,7 @@ function summarizeTrustAudit(run) {
|
|
|
255
378
|
return summary;
|
|
256
379
|
}
|
|
257
380
|
function refreshTrustAudit(run) {
|
|
258
|
-
const audit = {
|
|
259
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
260
|
-
eventLogPath: node_path_1.default.join(auditRoot(run), "events.jsonl"),
|
|
261
|
-
summaryPath: node_path_1.default.join(auditRoot(run), "summary.json"),
|
|
262
|
-
indexPath: node_path_1.default.join(auditRoot(run), "index.json")
|
|
263
|
-
};
|
|
381
|
+
const audit = { ...trustAuditPaths(run) };
|
|
264
382
|
node_fs_1.default.mkdirSync(node_path_1.default.dirname(audit.eventLogPath), { recursive: true });
|
|
265
383
|
if (!node_fs_1.default.existsSync(audit.eventLogPath))
|
|
266
384
|
node_fs_1.default.writeFileSync(audit.eventLogPath, "", "utf8");
|
|
@@ -365,15 +483,7 @@ function auditRoot(run) {
|
|
|
365
483
|
return run.paths.auditDir || node_path_1.default.join(run.paths.runDir, "audit");
|
|
366
484
|
}
|
|
367
485
|
function readEvents(eventLogPath) {
|
|
368
|
-
|
|
369
|
-
return [];
|
|
370
|
-
return node_fs_1.default
|
|
371
|
-
.readFileSync(eventLogPath, "utf8")
|
|
372
|
-
.split(/\n/g)
|
|
373
|
-
.map((line) => line.trim())
|
|
374
|
-
.filter(Boolean)
|
|
375
|
-
.map((line) => JSON.parse(line))
|
|
376
|
-
.sort(compareEvents);
|
|
486
|
+
return readEventsRaw(eventLogPath).events.sort(compareEvents);
|
|
377
487
|
}
|
|
378
488
|
function workerRows(events, run) {
|
|
379
489
|
const workerIds = unique([...(run.workers || []).map((worker) => worker.id), ...events.map((event) => event.workerId || "")]).sort();
|
|
@@ -419,9 +529,11 @@ function commitRows(events, run) {
|
|
|
419
529
|
});
|
|
420
530
|
}
|
|
421
531
|
function createEventId(run, kind) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
532
|
+
// Deterministic (FreeBSD-audit L12/L13): chain-local sequence (event-log length),
|
|
533
|
+
// no wall-clock stamp — event.id is bound into the eventHash chain (computeEventHash),
|
|
534
|
+
// so a stable id keeps the chain reproducible on replay.
|
|
535
|
+
const count = readEvents(trustAuditPaths(run).eventLogPath).length + 1;
|
|
536
|
+
return `audit-${(0, state_1.safeFileName)(kind)}-${String(count).padStart(4, "0")}`;
|
|
425
537
|
}
|
|
426
538
|
function redactPolicy(policy) {
|
|
427
539
|
if (!policy)
|
package/dist/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MIN_SUPPORTED_RUN_STATE_SCHEMA_VERSION = exports.LEGACY_RUN_STATE_SCHEMA_VERSION = exports.CURRENT_RUN_STATE_SCHEMA_VERSION = exports.WORKFLOW_APP_SCHEMA_VERSION = exports.CURRENT_COOL_WORKFLOW_VERSION = void 0;
|
|
4
|
-
exports.CURRENT_COOL_WORKFLOW_VERSION = "0.1.
|
|
4
|
+
exports.CURRENT_COOL_WORKFLOW_VERSION = "0.1.81";
|
|
5
5
|
exports.WORKFLOW_APP_SCHEMA_VERSION = 1;
|
|
6
6
|
exports.CURRENT_RUN_STATE_SCHEMA_VERSION = 1;
|
|
7
7
|
exports.LEGACY_RUN_STATE_SCHEMA_VERSION = 0;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.structuredError = structuredError;
|
|
4
|
+
exports.isBoundaryViolation = isBoundaryViolation;
|
|
5
|
+
exports.isStateNodeError = isStateNodeError;
|
|
6
|
+
exports.mergeScopes = mergeScopes;
|
|
7
|
+
exports.unique = unique;
|
|
8
|
+
exports.compactMetadata = compactMetadata;
|
|
9
|
+
exports.countBy = countBy;
|
|
10
|
+
function structuredError(code, message, options = {}) {
|
|
11
|
+
return {
|
|
12
|
+
code,
|
|
13
|
+
message,
|
|
14
|
+
at: new Date().toISOString(),
|
|
15
|
+
path: options.path,
|
|
16
|
+
retryable: options.retryable,
|
|
17
|
+
details: options.details
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function isBoundaryViolation(value) {
|
|
21
|
+
return Boolean(value && typeof value === "object" && "allowedPaths" in value && "message" in value);
|
|
22
|
+
}
|
|
23
|
+
function isStateNodeError(value) {
|
|
24
|
+
return Boolean(value && typeof value === "object" && "code" in value && "message" in value);
|
|
25
|
+
}
|
|
26
|
+
function mergeScopes(left, right) {
|
|
27
|
+
const merged = [...left];
|
|
28
|
+
for (const scope of right) {
|
|
29
|
+
const index = merged.findIndex((candidate) => candidate.id === scope.id);
|
|
30
|
+
if (index >= 0)
|
|
31
|
+
merged[index] = scope;
|
|
32
|
+
else
|
|
33
|
+
merged.push(scope);
|
|
34
|
+
}
|
|
35
|
+
return merged;
|
|
36
|
+
}
|
|
37
|
+
function unique(values) {
|
|
38
|
+
return Array.from(new Set(values.filter(Boolean)));
|
|
39
|
+
}
|
|
40
|
+
function compactMetadata(value) {
|
|
41
|
+
const entries = Object.entries(value).filter(([, entry]) => entry !== undefined);
|
|
42
|
+
return entries.length ? Object.fromEntries(entries) : undefined;
|
|
43
|
+
}
|
|
44
|
+
function countBy(items, key) {
|
|
45
|
+
const counts = {};
|
|
46
|
+
for (const item of items) {
|
|
47
|
+
const value = key(item);
|
|
48
|
+
counts[value] = (counts[value] || 0) + 1;
|
|
49
|
+
}
|
|
50
|
+
return counts;
|
|
51
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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_MANIFEST_FILE = exports.WORKER_SCOPE_FILE = void 0;
|
|
7
|
+
exports.manifestPath = manifestPath;
|
|
8
|
+
exports.workerScopePath = workerScopePath;
|
|
9
|
+
exports.workerArtifacts = workerArtifacts;
|
|
10
|
+
exports.createWorkerId = createWorkerId;
|
|
11
|
+
// Path, artifact, and id derivation for worker isolation. Pure functions of a
|
|
12
|
+
// WorkerScope (or run + taskId) — no run-state mutation, no disk I/O. Carved out
|
|
13
|
+
// of worker-isolation.ts following the established router pattern
|
|
14
|
+
// (run-registry/{format,policy}.ts, orchestrator/*-operations.ts).
|
|
15
|
+
//
|
|
16
|
+
// BEHAVIOR-PRESERVING — pure code movement, zero logic change. Re-exported from
|
|
17
|
+
// worker-isolation.ts so the public surface is byte-unchanged.
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
const state_1 = require("../state");
|
|
20
|
+
exports.WORKER_SCOPE_FILE = "worker.json";
|
|
21
|
+
exports.WORKER_MANIFEST_FILE = "manifest.json";
|
|
22
|
+
function manifestPath(scope) {
|
|
23
|
+
return node_path_1.default.join(scope.workerDir, exports.WORKER_MANIFEST_FILE);
|
|
24
|
+
}
|
|
25
|
+
function workerScopePath(scope) {
|
|
26
|
+
return node_path_1.default.join(scope.workerDir, exports.WORKER_SCOPE_FILE);
|
|
27
|
+
}
|
|
28
|
+
function workerArtifacts(scope) {
|
|
29
|
+
return [
|
|
30
|
+
{ id: "worker", kind: "json", path: workerScopePath(scope) },
|
|
31
|
+
{ id: "worker-manifest", kind: "json", path: manifestPath(scope) },
|
|
32
|
+
{ id: "worker-input", kind: "markdown", path: scope.inputPath }
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
// Deterministic worker id (v0.1.40 self-audit P2): a wall-clock stamp + Math.random()
|
|
36
|
+
// made every dispatch mint a different id, so audit references were not reproducible
|
|
37
|
+
// across re-runs of the same inputs. The id is now derived from the task plus a
|
|
38
|
+
// per-task sequence (count of worker scopes already allocated for that task + 1),
|
|
39
|
+
// so re-running the same workflow yields byte-identical worker ids while retries of
|
|
40
|
+
// the SAME task still get a fresh, unique id. (workerId is excluded from the
|
|
41
|
+
// snapshot source fingerprint, so this does not change replay digests.)
|
|
42
|
+
function createWorkerId(run, taskId) {
|
|
43
|
+
const prefix = `worker-${(0, state_1.safeFileName)(taskId)}-`;
|
|
44
|
+
const seq = (run.workers || []).filter((scope) => scope.id.startsWith(prefix)).length + 1;
|
|
45
|
+
return `${prefix}${String(seq).padStart(4, "0")}`;
|
|
46
|
+
}
|