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
|
@@ -1,31 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
//
|
|
2
|
+
// core/trust/telemetry-attestation.ts — ed25519 usage/result attestation.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// the claim into an attestation:
|
|
4
|
+
// MILESTONE 8. The AGENT (executor) signs; CW only VERIFIES with an
|
|
5
|
+
// operator-given PUBLIC key — CW holds no private key, ever. Uses
|
|
6
|
+
// node:crypto's built-in ed25519 sign/verify (no npm dependency).
|
|
8
7
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
8
|
+
// `crypto.verify`/`crypto.createPublicKey` are allowed here per
|
|
9
|
+
// v2/PLAN.md's lint carve-out for this exact file (Target shape,
|
|
10
|
+
// core/trust/telemetry-attestation.ts comment) — this remains otherwise
|
|
11
|
+
// pure (no fs, no process.env, no clock; `resolveTrustPublicKey`'s lazy
|
|
12
|
+
// `require("node:fs")` is the one exception, ported byte-identically
|
|
13
|
+
// from the old build's own lazy-require pattern so a bundle that never
|
|
14
|
+
// resolves a key path pays no fs cost).
|
|
16
15
|
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
// Evidence: SPEC/ledger-trust.md "The signing model", "Attestation
|
|
17
|
+
// verify", byte-compat items 2 and 11;
|
|
18
|
+
// plugins/cool-workflow/src/telemetry-attestation.ts:1-319.
|
|
19
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
26
|
+
}) : (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
o[k2] = m[k];
|
|
29
|
+
}));
|
|
30
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
31
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32
|
+
}) : function(o, v) {
|
|
33
|
+
o["default"] = v;
|
|
34
|
+
});
|
|
35
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
36
|
+
var ownKeys = function(o) {
|
|
37
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
38
|
+
var ar = [];
|
|
39
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
40
|
+
return ar;
|
|
41
|
+
};
|
|
42
|
+
return ownKeys(o);
|
|
43
|
+
};
|
|
44
|
+
return function (mod) {
|
|
45
|
+
if (mod && mod.__esModule) return mod;
|
|
46
|
+
var result = {};
|
|
47
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
48
|
+
__setModuleDefault(result, mod);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
29
52
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
53
|
exports.stableStringify = stableStringify;
|
|
31
54
|
exports.canonicalTelemetryPayload = canonicalTelemetryPayload;
|
|
@@ -34,9 +57,17 @@ exports.verifyTelemetryAttestation = verifyTelemetryAttestation;
|
|
|
34
57
|
exports.resolveTrustPublicKey = resolveTrustPublicKey;
|
|
35
58
|
exports.signTelemetry = signTelemetry;
|
|
36
59
|
exports.verifyTelemetrySignatures = verifyTelemetrySignatures;
|
|
37
|
-
const
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
60
|
+
const crypto = __importStar(require("node:crypto"));
|
|
61
|
+
/** `src/telemetry-attestation.ts`'s `stableStringify` — sorts keys
|
|
62
|
+
* recursively, AND maps a top-level `undefined` input to the literal
|
|
63
|
+
* string `"null"`. Divergent from `core/hash.ts`'s
|
|
64
|
+
* `ledgerStableStringify` exactly at the top-level-undefined edge (see
|
|
65
|
+
* v2/PLAN.md byte-compat item 2). Re-exported under this file's own
|
|
66
|
+
* name (rather than importing `telemetryStableStringify` from
|
|
67
|
+
* core/hash.ts) because SPEC/ledger-trust.md's "Exported functions"
|
|
68
|
+
* list names `stableStringify` as a real export of THIS module — the
|
|
69
|
+
* two are byte-identical behavior, kept as separate named exports per
|
|
70
|
+
* their separate call sites. */
|
|
40
71
|
function stableStringify(value) {
|
|
41
72
|
if (value === null || typeof value !== "object")
|
|
42
73
|
return JSON.stringify(value) ?? "null";
|
|
@@ -54,10 +85,10 @@ function canonicalTelemetryPayload(usage, ctx) {
|
|
|
54
85
|
runId: ctx.runId,
|
|
55
86
|
taskId: ctx.taskId,
|
|
56
87
|
promptDigest: ctx.promptDigest,
|
|
57
|
-
// Present ONLY when the signer covered the result
|
|
58
|
-
// canonical bytes byte-identical to the original 4-field
|
|
59
|
-
// pre-result-coverage signature still verifies
|
|
60
|
-
...(ctx.resultDigest !== undefined ? { resultDigest: ctx.resultDigest } : {})
|
|
88
|
+
// Present ONLY when the signer covered the result — omitting the key
|
|
89
|
+
// keeps the canonical bytes byte-identical to the original 4-field
|
|
90
|
+
// payload, so every pre-result-coverage signature still verifies.
|
|
91
|
+
...(ctx.resultDigest !== undefined ? { resultDigest: ctx.resultDigest } : {}),
|
|
61
92
|
});
|
|
62
93
|
}
|
|
63
94
|
function messageOf(error) {
|
|
@@ -72,9 +103,9 @@ function numberAt(usage, ...keys) {
|
|
|
72
103
|
}
|
|
73
104
|
return undefined;
|
|
74
105
|
}
|
|
75
|
-
/** Map the agent's free-form usage report onto
|
|
76
|
-
* snake_case / camelCase variants
|
|
77
|
-
*
|
|
106
|
+
/** Map the agent's free-form usage report onto token buckets, tolerating
|
|
107
|
+
* snake_case / camelCase variants. CW never invents a number — an
|
|
108
|
+
* unreported bucket stays `undefined`, never 0. */
|
|
78
109
|
function normalizeReportedUsage(usage) {
|
|
79
110
|
if (!usage)
|
|
80
111
|
return {};
|
|
@@ -83,11 +114,15 @@ function normalizeReportedUsage(usage) {
|
|
|
83
114
|
outputTokens: numberAt(usage, "outputTokens", "output_tokens", "completionTokens", "completion_tokens"),
|
|
84
115
|
cacheReadTokens: numberAt(usage, "cacheReadTokens", "cache_read_tokens", "cacheReadInputTokens", "cache_read_input_tokens"),
|
|
85
116
|
cacheWriteTokens: numberAt(usage, "cacheWriteTokens", "cache_write_tokens", "cacheCreationInputTokens", "cache_creation_input_tokens"),
|
|
86
|
-
totalTokens: numberAt(usage, "totalTokens", "total_tokens")
|
|
117
|
+
totalTokens: numberAt(usage, "totalTokens", "total_tokens"),
|
|
87
118
|
};
|
|
88
119
|
}
|
|
89
|
-
/** Verify the agent's signed usage against the operator-provisioned
|
|
90
|
-
*
|
|
120
|
+
/** Verify the agent's signed usage against the operator-provisioned
|
|
121
|
+
* public key. Two-arm check (v2/PLAN.md byte-compat item 11): try the
|
|
122
|
+
* 5-field payload (with resultDigest) first; on a miss, retry the
|
|
123
|
+
* 4-field payload (old signers still verify). `coversResult` is set
|
|
124
|
+
* ONLY on a first-arm match — a 4-field fallback match never covers the
|
|
125
|
+
* result, even when a resultDigest sits on the record. Never throws. */
|
|
91
126
|
function verifyTelemetryAttestation(usage, signatureB64, trustPublicKeyPem, ctx) {
|
|
92
127
|
if (!usage || Object.keys(usage).length === 0) {
|
|
93
128
|
return { status: "absent", reason: "agent reported no usage" };
|
|
@@ -100,7 +135,7 @@ function verifyTelemetryAttestation(usage, signatureB64, trustPublicKeyPem, ctx)
|
|
|
100
135
|
}
|
|
101
136
|
let publicKey;
|
|
102
137
|
try {
|
|
103
|
-
publicKey =
|
|
138
|
+
publicKey = crypto.createPublicKey(trustPublicKeyPem);
|
|
104
139
|
}
|
|
105
140
|
catch (error) {
|
|
106
141
|
return { status: "unattested", reason: `trust key unreadable: ${messageOf(error)}` };
|
|
@@ -114,18 +149,18 @@ function verifyTelemetryAttestation(usage, signatureB64, trustPublicKeyPem, ctx)
|
|
|
114
149
|
catch {
|
|
115
150
|
return { status: "unattested", reason: "signature is not valid base64" };
|
|
116
151
|
}
|
|
117
|
-
const matches = (c) =>
|
|
152
|
+
const matches = (c) => crypto.verify(null, Buffer.from(canonicalTelemetryPayload(usage, c), "utf8"), publicKey, signature);
|
|
118
153
|
let ok = false;
|
|
119
154
|
let coversResult = false;
|
|
120
155
|
try {
|
|
121
156
|
ok = matches(ctx);
|
|
122
|
-
// A match on the first arm (which carries resultDigest when CW has
|
|
123
|
-
// the signature covered the result
|
|
157
|
+
// A match on the first arm (which carries resultDigest when CW has
|
|
158
|
+
// one) means the signature covered the result, not just the usage.
|
|
124
159
|
coversResult = ok && ctx.resultDigest !== undefined;
|
|
125
|
-
// Back-compat: a signer that predates result coverage signed only
|
|
126
|
-
// payload, so on a miss retry WITHOUT resultDigest. A NEW
|
|
127
|
-
// the result fails BOTH arms when the result is
|
|
128
|
-
//
|
|
160
|
+
// Back-compat: a signer that predates result coverage signed only
|
|
161
|
+
// the 4-field payload, so on a miss retry WITHOUT resultDigest. A NEW
|
|
162
|
+
// signer who covered the result fails BOTH arms when the result is
|
|
163
|
+
// edited (its resultDigest no longer matches).
|
|
129
164
|
if (!ok && ctx.resultDigest !== undefined)
|
|
130
165
|
ok = matches({ ...ctx, resultDigest: undefined });
|
|
131
166
|
}
|
|
@@ -136,9 +171,10 @@ function verifyTelemetryAttestation(usage, signatureB64, trustPublicKeyPem, ctx)
|
|
|
136
171
|
? { status: "attested", algorithm: "ed25519", ...(coversResult ? { coversResult: true } : {}) }
|
|
137
172
|
: { status: "unattested", reason: "signature does not match reported usage (tampered, replayed, or wrong key)" };
|
|
138
173
|
}
|
|
139
|
-
/** Resolve a trust key from a config value that is EITHER an inline PEM
|
|
140
|
-
* to a `.pem` file. Returns undefined when absent/unreadable
|
|
141
|
-
* never a hard throw). CW only ever loads a PUBLIC key
|
|
174
|
+
/** Resolve a trust key from a config value that is EITHER an inline PEM
|
|
175
|
+
* or a path to a `.pem` file. Returns undefined when absent/unreadable
|
|
176
|
+
* (⇒ `unattested`, never a hard throw). CW only ever loads a PUBLIC key
|
|
177
|
+
* here. */
|
|
142
178
|
function resolveTrustPublicKey(value) {
|
|
143
179
|
if (!value)
|
|
144
180
|
return undefined;
|
|
@@ -148,7 +184,9 @@ function resolveTrustPublicKey(value) {
|
|
|
148
184
|
if (trimmed.includes("BEGIN") && trimmed.includes("KEY"))
|
|
149
185
|
return trimmed;
|
|
150
186
|
try {
|
|
151
|
-
// Lazy require so a bundle that never resolves a key path pays no
|
|
187
|
+
// Lazy require so a bundle that never resolves a key path pays no
|
|
188
|
+
// fs cost — byte-identical pattern to the old build's own lazy
|
|
189
|
+
// require here.
|
|
152
190
|
const fs = require("node:fs");
|
|
153
191
|
if (fs.existsSync(trimmed))
|
|
154
192
|
return fs.readFileSync(trimmed, "utf8");
|
|
@@ -159,18 +197,16 @@ function resolveTrustPublicKey(value) {
|
|
|
159
197
|
return undefined;
|
|
160
198
|
}
|
|
161
199
|
// ---------------------------------------------------------------------------
|
|
162
|
-
// EXECUTOR-SIDE HELPER — the CW RUNTIME NEVER CALLS THIS.
|
|
163
|
-
//
|
|
164
|
-
// touches a private key, never a model, so it does not cross the red line; it is
|
|
165
|
-
// kept here only so signer and verifier share one canonicalization.
|
|
200
|
+
// EXECUTOR-SIDE HELPER — the CW RUNTIME NEVER CALLS THIS. Provided for
|
|
201
|
+
// signing wrappers and tests; touches a private key, never a model.
|
|
166
202
|
// ---------------------------------------------------------------------------
|
|
167
203
|
function signTelemetry(usage, privateKeyPem, ctx) {
|
|
168
204
|
const payload = Buffer.from(canonicalTelemetryPayload(usage, ctx), "utf8");
|
|
169
|
-
const key =
|
|
170
|
-
return
|
|
205
|
+
const key = crypto.createPrivateKey(privateKeyPem);
|
|
206
|
+
return crypto.sign(null, payload, key).toString("base64");
|
|
171
207
|
}
|
|
172
208
|
function stableDigest(value) {
|
|
173
|
-
return `sha256:${
|
|
209
|
+
return `sha256:${crypto.createHash("sha256").update(stableStringify(value), "utf8").digest("hex")}`;
|
|
174
210
|
}
|
|
175
211
|
function verifyTelemetrySignatures(records, trustPublicKeyPem) {
|
|
176
212
|
const checks = [];
|
|
@@ -188,16 +224,11 @@ function verifyTelemetrySignatures(records, trustPublicKeyPem) {
|
|
|
188
224
|
continue;
|
|
189
225
|
}
|
|
190
226
|
if (!record.reportedUsage) {
|
|
191
|
-
// A claimed-`attested` record with no re-verifiable raw usage cannot be
|
|
192
|
-
// independently checked — fail closed rather than trust the stored verdict.
|
|
193
227
|
failed += 1;
|
|
194
228
|
checks.push({ name: `signature[${i}]`, pass: false, code: "telemetry-usage-unavailable" });
|
|
195
229
|
continue;
|
|
196
230
|
}
|
|
197
231
|
if (record.reportedUsageDigest !== stableDigest(record.reportedUsage)) {
|
|
198
|
-
// The raw usage is stored so a public-key verifier can re-run ed25519.
|
|
199
|
-
// The hash-chained record binds its digest; verify the two still match
|
|
200
|
-
// before trusting the raw payload for signature re-verification.
|
|
201
232
|
failed += 1;
|
|
202
233
|
checks.push({ name: `signature[${i}]`, pass: false, code: "telemetry-usage-digest-mismatch" });
|
|
203
234
|
continue;
|
|
@@ -206,16 +237,11 @@ function verifyTelemetrySignatures(records, trustPublicKeyPem) {
|
|
|
206
237
|
runId: record.runId,
|
|
207
238
|
taskId: record.taskId,
|
|
208
239
|
promptDigest: record.promptDigest,
|
|
209
|
-
|
|
210
|
-
// reconstructs the 5-field payload (and falls back to 4-field for old records).
|
|
211
|
-
resultDigest: record.resultDigest
|
|
240
|
+
resultDigest: record.resultDigest,
|
|
212
241
|
});
|
|
213
242
|
if (result.status === "attested") {
|
|
214
243
|
reverified += 1;
|
|
215
244
|
checks.push({ name: `signature[${i}]`, pass: true });
|
|
216
|
-
// Only a signature that actually COVERED the result digest anchors it — a
|
|
217
|
-
// 4-field fallback (coversResult false) must not let an injected resultDigest
|
|
218
|
-
// be trusted downstream.
|
|
219
245
|
if (result.coversResult && record.resultDigest) {
|
|
220
246
|
resultBound.push({ taskId: record.taskId, resultDigest: record.resultDigest });
|
|
221
247
|
}
|
|
@@ -227,7 +253,7 @@ function verifyTelemetrySignatures(records, trustPublicKeyPem) {
|
|
|
227
253
|
pass: false,
|
|
228
254
|
code: result.reason && result.reason.startsWith("trust key unreadable")
|
|
229
255
|
? "telemetry-pubkey-unreadable"
|
|
230
|
-
: "telemetry-signature-mismatch"
|
|
256
|
+
: "telemetry-signature-mismatch",
|
|
231
257
|
});
|
|
232
258
|
}
|
|
233
259
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// core/trust/telemetry-ledger.ts — the hash-chained telemetry
|
|
3
|
+
// attestation ledger's PURE half: genesisPrevHash, computeRecordHash,
|
|
4
|
+
// reportedUsageDigest, verifyTelemetryLedger. Directory/file IO
|
|
5
|
+
// (telemetryLedgerPath, loadTelemetryLedger, appendTelemetryAttestation)
|
|
6
|
+
// lives in shell/telemetry-ledger-io.ts.
|
|
7
|
+
//
|
|
8
|
+
// MILESTONE 8. Byte-exact port of the old build's src/telemetry-ledger.ts
|
|
9
|
+
// verify-side logic. Uses core/hash.ts's `sha256`/`telemetryStableStringify`
|
|
10
|
+
// (see v2/PLAN.md byte-compat item 2's key-omission-vs-null rule).
|
|
11
|
+
//
|
|
12
|
+
// Evidence: SPEC/ledger-trust.md "Telemetry ledger record", byte-compat
|
|
13
|
+
// items 2 and 12; plugins/cool-workflow/src/telemetry-ledger.ts:1-224.
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.TelemetryLedgerCorruptError = exports.TELEMETRY_LEDGER_SCHEMA_VERSION = void 0;
|
|
16
|
+
exports.genesisPrevHash = genesisPrevHash;
|
|
17
|
+
exports.computeRecordHash = computeRecordHash;
|
|
18
|
+
exports.reportedUsageDigest = reportedUsageDigest;
|
|
19
|
+
exports.recordId = recordId;
|
|
20
|
+
exports.verifyTelemetryLedgerRecords = verifyTelemetryLedgerRecords;
|
|
21
|
+
exports.corruptTelemetryLedgerVerification = corruptTelemetryLedgerVerification;
|
|
22
|
+
const hash_1 = require("../hash");
|
|
23
|
+
exports.TELEMETRY_LEDGER_SCHEMA_VERSION = 1;
|
|
24
|
+
/** A telemetry ledger that EXISTS on disk but cannot be parsed (or whose
|
|
25
|
+
* shape is not a record array). This is exactly the corruption/
|
|
26
|
+
* truncation case the hash chain exists to catch — it must fail closed,
|
|
27
|
+
* never be silently treated as the "empty/absent" chain (which verifies
|
|
28
|
+
* as clean). */
|
|
29
|
+
class TelemetryLedgerCorruptError extends Error {
|
|
30
|
+
file;
|
|
31
|
+
constructor(file) {
|
|
32
|
+
super(`Telemetry ledger exists but is corrupt (unparseable): ${file}`);
|
|
33
|
+
this.name = "TelemetryLedgerCorruptError";
|
|
34
|
+
this.file = file;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.TelemetryLedgerCorruptError = TelemetryLedgerCorruptError;
|
|
38
|
+
/** genesis prevHash for a run's chain (no prior record). */
|
|
39
|
+
function genesisPrevHash(runId) {
|
|
40
|
+
return (0, hash_1.sha256)(`cw-telemetry-ledger:${runId}`);
|
|
41
|
+
}
|
|
42
|
+
/** The canonical bytes a recordHash binds — every field except
|
|
43
|
+
* recordHash itself. `reportedUsage`/`resultDigest` are OMITTED (not
|
|
44
|
+
* `null`) when absent, so a usage-only record's hash is byte-identical
|
|
45
|
+
* to a pre-result-coverage one (back-compat with old ledgers) — see
|
|
46
|
+
* v2/PLAN.md byte-compat item 2. */
|
|
47
|
+
function recordHashInput(record) {
|
|
48
|
+
return (0, hash_1.telemetryStableStringify)({
|
|
49
|
+
schemaVersion: record.schemaVersion,
|
|
50
|
+
runId: record.runId,
|
|
51
|
+
recordId: record.recordId,
|
|
52
|
+
recordedAt: record.recordedAt,
|
|
53
|
+
workerId: record.workerId,
|
|
54
|
+
taskId: record.taskId,
|
|
55
|
+
promptDigest: record.promptDigest,
|
|
56
|
+
reportedUsageDigest: record.reportedUsageDigest,
|
|
57
|
+
...(record.reportedUsage !== undefined ? { reportedUsage: record.reportedUsage } : {}),
|
|
58
|
+
usageSignature: record.usageSignature || null,
|
|
59
|
+
...(record.resultDigest !== undefined ? { resultDigest: record.resultDigest } : {}),
|
|
60
|
+
attestation: record.attestation,
|
|
61
|
+
attestationReason: record.attestationReason || null,
|
|
62
|
+
prevHash: record.prevHash,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function computeRecordHash(record) {
|
|
66
|
+
return (0, hash_1.sha256)(recordHashInput(record));
|
|
67
|
+
}
|
|
68
|
+
/** sha256 of the canonical reported usage (compact, chainable). Absent
|
|
69
|
+
* usage gets the digest of `null`, so "the agent reported nothing" is
|
|
70
|
+
* itself bound. */
|
|
71
|
+
function reportedUsageDigest(usage) {
|
|
72
|
+
return (0, hash_1.sha256)((0, hash_1.telemetryStableStringify)(usage ?? null));
|
|
73
|
+
}
|
|
74
|
+
/** Deterministic (chain POSITION, not a process-global counter or
|
|
75
|
+
* wall-clock stamp): `tel-` + chain position, zero-padded to 3. */
|
|
76
|
+
function recordId(seq) {
|
|
77
|
+
return `tel-${String(seq).padStart(3, "0")}`;
|
|
78
|
+
}
|
|
79
|
+
/** Re-prove the whole telemetry chain for a run: prevHash linkage +
|
|
80
|
+
* per-record hash recompute. Recomputes every hash independently —
|
|
81
|
+
* never trusts the stored value. An empty ledger verifies as
|
|
82
|
+
* present:false (nothing to prove), NOT a failure. Pure: takes the
|
|
83
|
+
* already-loaded record array plus the run id, never touches disk. */
|
|
84
|
+
function verifyTelemetryLedgerRecords(runId, records) {
|
|
85
|
+
const checks = [];
|
|
86
|
+
const tally = { attested: 0, unattested: 0, absent: 0 };
|
|
87
|
+
for (const record of records)
|
|
88
|
+
tally[record.attestation] += 1;
|
|
89
|
+
if (!records.length) {
|
|
90
|
+
return { present: false, verified: true, records, checks, ...tally };
|
|
91
|
+
}
|
|
92
|
+
// (a) chain linkage.
|
|
93
|
+
let chainOk = true;
|
|
94
|
+
for (let i = 0; i < records.length; i++) {
|
|
95
|
+
const expectedPrev = i === 0 ? genesisPrevHash(runId) : records[i - 1].recordHash;
|
|
96
|
+
const pass = records[i].prevHash === expectedPrev;
|
|
97
|
+
if (!pass)
|
|
98
|
+
chainOk = false;
|
|
99
|
+
checks.push({ name: `chain-link[${i}]`, pass, code: pass ? undefined : "telemetry-chain-broken" });
|
|
100
|
+
}
|
|
101
|
+
// (b) per-record independent hash recompute (digest integrity).
|
|
102
|
+
let digestsOk = true;
|
|
103
|
+
for (let i = 0; i < records.length; i++) {
|
|
104
|
+
const { recordHash, ...rest } = records[i];
|
|
105
|
+
const recomputed = computeRecordHash(rest);
|
|
106
|
+
const pass = recomputed === recordHash;
|
|
107
|
+
if (!pass)
|
|
108
|
+
digestsOk = false;
|
|
109
|
+
checks.push({ name: `record-hash[${i}]`, pass, code: pass ? undefined : "telemetry-digest-mismatch" });
|
|
110
|
+
}
|
|
111
|
+
return { present: true, verified: chainOk && digestsOk, records, checks, ...tally };
|
|
112
|
+
}
|
|
113
|
+
/** The corrupt-ledger verification shape (present:true, verified:false,
|
|
114
|
+
* one `ledger-load`/`telemetry-ledger-corrupt` failed check). Shared
|
|
115
|
+
* constant so both the CLI-facing shell reader and any pure caller
|
|
116
|
+
* report the exact same shape for a corrupt file. */
|
|
117
|
+
function corruptTelemetryLedgerVerification() {
|
|
118
|
+
return {
|
|
119
|
+
present: true,
|
|
120
|
+
verified: false,
|
|
121
|
+
records: [],
|
|
122
|
+
checks: [{ name: "ledger-load", pass: false, code: "telemetry-ledger-corrupt" }],
|
|
123
|
+
attested: 0,
|
|
124
|
+
unattested: 0,
|
|
125
|
+
absent: 0,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/core/types.ts — barrel for cross-cutting pure type modules under
|
|
3
|
+
// src/core/types/. Mirrors the src/cli.ts + src/cli/ convention: a thin
|
|
4
|
+
// top-level file next to the directory it fronts.
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./types/boundary"), exports);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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
|
+
// core/version.ts — the one version string `cw version` prints.
|
|
5
|
+
//
|
|
6
|
+
// Pure. POLA: keep the exact same version marker the old build reports, so
|
|
7
|
+
// `cw version` output does not change bytes just because the code under it
|
|
8
|
+
// was rebuilt. See SPEC/cli-surface.md "Exact outputs > Version" and
|
|
9
|
+
// conformance/cases/version-basic.case.js (regex `/^\d+\.\d+\.\d+\n$/`).
|
|
10
|
+
exports.CURRENT_COOL_WORKFLOW_VERSION = "0.2.0";
|
|
11
|
+
// State-kernel schema version constants (SPEC/state-core.md "Version
|
|
12
|
+
// constants"). Pinned to the old build's src/version.ts byte-for-byte.
|
|
13
|
+
exports.WORKFLOW_APP_SCHEMA_VERSION = 1;
|
|
14
|
+
exports.CURRENT_RUN_STATE_SCHEMA_VERSION = 1;
|
|
15
|
+
exports.LEGACY_RUN_STATE_SCHEMA_VERSION = 0;
|
|
16
|
+
exports.MIN_SUPPORTED_RUN_STATE_SCHEMA_VERSION = 0;
|