cool-workflow 0.1.97 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +11 -2
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/cli/dispatch.js +236 -0
- package/dist/cli/entry.js +120 -0
- package/dist/cli/io.js +21 -4
- package/dist/cli/parseargv.js +157 -0
- package/dist/cli.js +6 -33
- package/dist/core/capability-table.js +3534 -0
- package/dist/core/format/help.js +314 -0
- package/dist/{state-explosion/format.js → core/format/state-explosion-text.js} +10 -1
- package/dist/core/hash.js +137 -0
- package/dist/core/multi-agent/candidate-scoring.js +219 -0
- package/dist/core/multi-agent/collaboration.js +481 -0
- package/dist/core/multi-agent/coordinator.js +515 -0
- package/dist/core/multi-agent/eval-replay.js +306 -0
- package/dist/core/multi-agent/runtime.js +929 -0
- package/dist/core/multi-agent/topology.js +298 -0
- package/dist/core/multi-agent/trust-policy.js +197 -0
- package/dist/core/pipeline/commit-gate.js +320 -0
- package/dist/{pipeline-contract.js → core/pipeline/contract.js} +24 -37
- package/dist/core/pipeline/dispatch.js +103 -0
- package/dist/core/pipeline/drive-decide.js +227 -0
- package/dist/core/pipeline/error-feedback.js +161 -0
- package/dist/core/pipeline/loop-expansion.js +124 -0
- package/dist/{result-normalize.js → core/pipeline/result-normalize.js} +14 -37
- package/dist/core/pipeline/runner.js +230 -0
- package/dist/{contract-migration.js → core/state/contract-migration.js} +68 -92
- package/dist/{state-migrations.js → core/state/migrations.js} +103 -96
- package/dist/core/state/node-projection.js +95 -0
- package/dist/core/state/node-snapshot.js +230 -0
- package/dist/core/state/run-paths.js +93 -0
- package/dist/{schema-validate.js → core/state/schema-validate.js} +35 -28
- package/dist/core/state/schema.js +50 -0
- package/dist/core/state/state-explosion/digest.js +243 -0
- package/dist/core/state/state-explosion/graph.js +527 -0
- package/dist/{state-explosion → core/state/state-explosion}/helpers.js +34 -3
- package/dist/core/state/state-explosion/report.js +187 -0
- package/dist/{state-explosion → core/state/state-explosion}/size.js +25 -7
- package/dist/{state-node.js → core/state/state-node.js} +90 -113
- package/dist/core/state/types.js +19 -0
- package/dist/{validation.js → core/state/validation.js} +64 -131
- package/dist/core/trust/evidence-grounding.js +134 -0
- package/dist/core/trust/ledger.js +199 -0
- package/dist/{telemetry-attestation.js → core/trust/telemetry-attestation.js} +94 -68
- package/dist/core/trust/telemetry-ledger.js +127 -0
- package/dist/core/types.js +20 -0
- package/dist/core/version.js +16 -0
- package/dist/{workflow-app-framework.js → core/workflow-apps/app-schema.js} +337 -426
- package/dist/mcp/dispatch.js +104 -0
- package/dist/mcp/server.js +144 -0
- package/dist/mcp-server.js +6 -84
- package/dist/{agent-config.js → shell/agent-config.js} +118 -71
- package/dist/shell/app-run-cli.js +88 -0
- package/dist/shell/audit-cli.js +259 -0
- package/dist/shell/audit-provenance.js +83 -0
- package/dist/shell/candidate-scoring-io.js +459 -0
- package/dist/shell/collaboration-io.js +264 -0
- package/dist/shell/commit-summary.js +104 -0
- package/dist/shell/commit.js +290 -0
- package/dist/shell/coordinator-io.js +476 -0
- package/dist/shell/demo-cli.js +19 -0
- package/dist/shell/dispatch.js +162 -0
- package/dist/{doctor.js → shell/doctor.js} +123 -56
- package/dist/shell/drive.js +873 -0
- package/dist/shell/error-feedback-io.js +305 -0
- package/dist/shell/eval-io.js +473 -0
- package/dist/{multi-agent-eval/format.js → shell/eval-text.js} +78 -49
- package/dist/{evidence-reasoning.js → shell/evidence-reasoning.js} +124 -255
- package/dist/shell/exec-backend-cli.js +88 -0
- package/dist/shell/execution-backend/agent.js +475 -0
- package/dist/shell/execution-backend/ci.js +15 -0
- package/dist/shell/execution-backend/container.js +69 -0
- package/dist/shell/execution-backend/envelopes.js +55 -0
- package/dist/shell/execution-backend/local.js +113 -0
- package/dist/shell/execution-backend/probes.js +175 -0
- package/dist/shell/execution-backend/registry.js +402 -0
- package/dist/shell/execution-backend/remote.js +128 -0
- package/dist/shell/execution-backend/types.js +11 -0
- package/dist/shell/feedback-cli.js +81 -0
- package/dist/shell/feedback-operations.js +48 -0
- package/dist/shell/fs-atomic.js +276 -0
- package/dist/shell/harness.js +98 -0
- package/dist/shell/ledger-cli.js +212 -0
- package/dist/shell/ledger-io.js +169 -0
- package/dist/shell/man-cli.js +89 -0
- package/dist/shell/metrics-cli.js +98 -0
- package/dist/shell/multi-agent-cli.js +1002 -0
- package/dist/shell/multi-agent-host.js +563 -0
- package/dist/shell/multi-agent-io.js +387 -0
- package/dist/{multi-agent-operator-ux.js → shell/multi-agent-operator-ux.js} +234 -191
- package/dist/shell/node-store.js +124 -0
- package/dist/{observability/format.js → shell/observability-format.js} +7 -1
- package/dist/{observability/intake.js → shell/observability-intake.js} +79 -56
- package/dist/{observability.js → shell/observability.js} +159 -332
- package/dist/{onramp.js → shell/onramp.js} +11 -0
- package/dist/{operator-ux/format.js → shell/operator-ux-text.js} +250 -239
- package/dist/shell/operator-ux.js +431 -0
- package/dist/shell/orchestrator.js +231 -0
- package/dist/shell/pipeline-cli.js +667 -0
- package/dist/shell/pipeline.js +217 -0
- package/dist/shell/reclamation-io.js +1366 -0
- package/dist/shell/registry-cli.js +329 -0
- package/dist/{remote-source.js → shell/remote-source.js} +12 -5
- package/dist/shell/report-cli.js +101 -0
- package/dist/shell/report-view-cli.js +117 -0
- package/dist/{orchestrator → shell}/report.js +289 -282
- package/dist/shell/reporter.js +62 -0
- package/dist/shell/run-export-cli.js +106 -0
- package/dist/shell/run-export.js +680 -0
- package/dist/shell/run-registry-io.js +1014 -0
- package/dist/shell/run-store.js +164 -0
- package/dist/{sandbox-profile.js → shell/sandbox-profile.js} +134 -95
- package/dist/{scheduler.js → shell/scheduler-io.js} +248 -48
- package/dist/shell/scheduling-io.js +311 -0
- package/dist/shell/state-cli.js +181 -0
- package/dist/shell/state-explosion-cli.js +197 -0
- package/dist/shell/telemetry-cli.js +85 -0
- package/dist/{telemetry-demo.js → shell/telemetry-demo.js} +149 -119
- package/dist/shell/telemetry-ledger-io.js +132 -0
- package/dist/{term.js → shell/term.js} +36 -46
- package/dist/shell/topology-io.js +361 -0
- package/dist/shell/trust-audit.js +471 -0
- package/dist/{multi-agent-trust.js → shell/trust-policy-io.js} +67 -205
- package/dist/shell/verifier.js +48 -0
- package/dist/shell/workbench-host.js +250 -0
- package/dist/shell/workbench-text.js +18 -0
- package/dist/shell/workbench.js +175 -0
- package/dist/shell/worker-cli.js +124 -0
- package/dist/shell/worker-isolation.js +852 -0
- package/dist/shell/workflow-app-loader.js +650 -0
- package/docs/agent-delegation-drive.7.md +4 -0
- package/docs/cli-mcp-parity.7.md +284 -211
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +4 -0
- package/docs/cross-agent-ledger.7.md +217 -0
- package/docs/designs/handoff-ledger.md +145 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
- package/docs/execution-backends.7.md +4 -0
- package/docs/handoff-setup.md +120 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +4 -0
- package/docs/multi-agent-operator-ux.7.md +4 -0
- package/docs/node-snapshot-diff-replay.7.md +4 -0
- package/docs/observability-cost-accounting.7.md +4 -0
- package/docs/project-index.md +143 -71
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +4 -0
- package/docs/run-registry-control-plane.7.md +4 -0
- package/docs/run-retention-reclamation.7.md +25 -0
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/web-desktop-workbench.7.md +4 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +9 -13
- package/package.json +1 -1
- package/scripts/agents/codex-agent.js +34 -4
- package/scripts/agents/cw-attest-wrap.js +2 -2
- package/scripts/bump-version.js +4 -3
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +30 -10
- package/scripts/dogfood-architecture-review.js +2 -3
- package/scripts/dogfood-release.js +3 -3
- package/scripts/gen-parity-doc.js +15 -2
- package/scripts/golden-path.js +4 -4
- package/scripts/onramp-check.js +1 -1
- package/scripts/parity-check.js +38 -21
- package/scripts/release-flow.js +9 -3
- package/scripts/sync-project-index.js +51 -27
- package/scripts/validate-run-state-schema.js +2 -2
- package/scripts/version-sync-check.js +30 -30
- package/dist/candidate-scoring.js +0 -729
- package/dist/capability-core.js +0 -1186
- package/dist/capability-registry.js +0 -879
- package/dist/cli/command-surface.js +0 -490
- package/dist/cli/format.js +0 -56
- package/dist/cli/handlers/audit.js +0 -82
- package/dist/cli/handlers/blackboard.js +0 -81
- package/dist/cli/handlers/candidate.js +0 -40
- package/dist/cli/handlers/clones.js +0 -34
- package/dist/cli/handlers/collaboration.js +0 -61
- package/dist/cli/handlers/eval.js +0 -40
- package/dist/cli/handlers/maintenance.js +0 -107
- package/dist/cli/handlers/multi-agent.js +0 -165
- package/dist/cli/handlers/node.js +0 -41
- package/dist/cli/handlers/operational.js +0 -155
- package/dist/cli/handlers/operator.js +0 -146
- package/dist/cli/handlers/registry.js +0 -68
- package/dist/cli/handlers/run.js +0 -153
- package/dist/cli/handlers/scheduling.js +0 -132
- package/dist/cli/handlers/workbench.js +0 -41
- package/dist/cli/handlers/worker.js +0 -45
- package/dist/cli/run-summary.js +0 -45
- package/dist/clones.js +0 -162
- package/dist/collaboration.js +0 -726
- package/dist/commit.js +0 -592
- package/dist/compare.js +0 -18
- package/dist/coordinator/classify.js +0 -45
- package/dist/coordinator/paths.js +0 -42
- package/dist/coordinator/util.js +0 -126
- package/dist/coordinator.js +0 -990
- package/dist/daemon.js +0 -44
- package/dist/dispatch.js +0 -250
- package/dist/drive.js +0 -827
- package/dist/error-feedback.js +0 -419
- package/dist/evidence-grounding.js +0 -184
- package/dist/execution-backend/agent.js +0 -294
- package/dist/execution-backend/probes.js +0 -112
- package/dist/execution-backend/util.js +0 -47
- package/dist/execution-backend.js +0 -961
- package/dist/gates.js +0 -48
- package/dist/harness.js +0 -61
- package/dist/loop-expansion.js +0 -60
- package/dist/mcp/tool-call.js +0 -434
- package/dist/mcp/tool-definitions.js +0 -1040
- package/dist/mcp-surface.js +0 -30
- package/dist/multi-agent/graph.js +0 -84
- package/dist/multi-agent/helpers.js +0 -141
- package/dist/multi-agent/ids.js +0 -20
- package/dist/multi-agent/paths.js +0 -22
- package/dist/multi-agent-eval/normalize.js +0 -51
- package/dist/multi-agent-eval.js +0 -678
- package/dist/multi-agent-host.js +0 -777
- package/dist/multi-agent.js +0 -984
- package/dist/node-projection.js +0 -59
- package/dist/node-snapshot.js +0 -260
- package/dist/operator-ux.js +0 -631
- package/dist/orchestrator/app-operations.js +0 -211
- package/dist/orchestrator/audit-operations.js +0 -182
- package/dist/orchestrator/candidate-operations.js +0 -117
- package/dist/orchestrator/cli-options.js +0 -294
- package/dist/orchestrator/collaboration-operations.js +0 -86
- package/dist/orchestrator/feedback-operations.js +0 -81
- package/dist/orchestrator/host-operations.js +0 -78
- package/dist/orchestrator/lifecycle-operations.js +0 -626
- package/dist/orchestrator/migration-operations.js +0 -44
- package/dist/orchestrator/multi-agent-operations.js +0 -362
- package/dist/orchestrator/topology-operations.js +0 -84
- package/dist/orchestrator.js +0 -917
- package/dist/pipeline-runner.js +0 -285
- package/dist/reclamation/hash.js +0 -72
- package/dist/reclamation.js +0 -812
- package/dist/reporter.js +0 -67
- package/dist/run-export.js +0 -784
- package/dist/run-registry/derive.js +0 -175
- package/dist/run-registry/format.js +0 -124
- package/dist/run-registry/gc.js +0 -251
- package/dist/run-registry/policy.js +0 -16
- package/dist/run-registry/queue.js +0 -115
- package/dist/run-registry.js +0 -850
- package/dist/run-state-schema.js +0 -68
- package/dist/scheduling.js +0 -184
- package/dist/state-explosion.js +0 -1014
- package/dist/state.js +0 -367
- package/dist/telemetry-ledger.js +0 -196
- package/dist/topology.js +0 -565
- package/dist/triggers.js +0 -184
- package/dist/trust-audit.js +0 -644
- package/dist/types/blackboard.js +0 -2
- package/dist/types/candidate.js +0 -2
- package/dist/types/collaboration.js +0 -2
- package/dist/types/core.js +0 -2
- package/dist/types/drive.js +0 -10
- package/dist/types/error-feedback.js +0 -2
- package/dist/types/evidence-reasoning.js +0 -2
- package/dist/types/execution-backend.js +0 -2
- package/dist/types/multi-agent.js +0 -2
- package/dist/types/observability.js +0 -2
- package/dist/types/pipeline.js +0 -2
- package/dist/types/reclamation.js +0 -8
- package/dist/types/report-bundle.js +0 -6
- package/dist/types/result.js +0 -2
- package/dist/types/run-registry.js +0 -2
- package/dist/types/run.js +0 -2
- package/dist/types/sandbox.js +0 -2
- package/dist/types/schedule.js +0 -2
- package/dist/types/state-node.js +0 -2
- package/dist/types/topology.js +0 -2
- package/dist/types/trust.js +0 -2
- package/dist/types/workbench.js +0 -2
- package/dist/types/worker.js +0 -2
- package/dist/types/workflow-app.js +0 -2
- package/dist/types.js +0 -44
- package/dist/util/fingerprint.js +0 -19
- package/dist/util/fingerprint.test.js +0 -27
- package/dist/verifier.js +0 -78
- package/dist/version.js +0 -8
- package/dist/workbench-host.js +0 -182
- package/dist/workbench.js +0 -192
- package/dist/worker-accept/acceptance.js +0 -114
- package/dist/worker-accept/blackboard-fanout.js +0 -80
- package/dist/worker-accept/blackboard-linkage.js +0 -19
- package/dist/worker-accept/context.js +0 -2
- package/dist/worker-accept/telemetry-ledger.js +0 -126
- package/dist/worker-accept/validation.js +0 -77
- package/dist/worker-accept/verifier-completion.js +0 -73
- package/dist/worker-isolation/helpers.js +0 -51
- package/dist/worker-isolation/paths.js +0 -46
- package/dist/worker-isolation.js +0 -656
- package/dist/workflow-api.js +0 -131
- /package/dist/{types → core/types}/boundary.js +0 -0
package/dist/trust-audit.js
DELETED
|
@@ -1,644 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.CORRELATION_ID_FIELDS = exports.TRUST_AUDIT_SCHEMA_VERSION = void 0;
|
|
7
|
-
exports.trustAuditGenesis = trustAuditGenesis;
|
|
8
|
-
exports.verifyTrustAudit = verifyTrustAudit;
|
|
9
|
-
exports.ensureTrustAudit = ensureTrustAudit;
|
|
10
|
-
exports.recordTrustAuditEvent = recordTrustAuditEvent;
|
|
11
|
-
exports.recordSandboxPathDecision = recordSandboxPathDecision;
|
|
12
|
-
exports.recordSandboxPolicyDecision = recordSandboxPolicyDecision;
|
|
13
|
-
exports.recordHostAttestation = recordHostAttestation;
|
|
14
|
-
exports.setAuditEventCache = setAuditEventCache;
|
|
15
|
-
exports.clearAuditEventCache = clearAuditEventCache;
|
|
16
|
-
exports.listTrustAuditEvents = listTrustAuditEvents;
|
|
17
|
-
exports.searchAuditEvents = searchAuditEvents;
|
|
18
|
-
exports.summarizeTrustAudit = summarizeTrustAudit;
|
|
19
|
-
exports.refreshTrustAudit = refreshTrustAudit;
|
|
20
|
-
exports.workerTrustAudit = workerTrustAudit;
|
|
21
|
-
exports.normalizeEvidence = normalizeEvidence;
|
|
22
|
-
exports.evidenceProvenance = evidenceProvenance;
|
|
23
|
-
exports.validateAcceptanceRationale = validateAcceptanceRationale;
|
|
24
|
-
exports.buildAcceptanceRationale = buildAcceptanceRationale;
|
|
25
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
26
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
27
|
-
const state_1 = require("./state");
|
|
28
|
-
const evidence_grounding_1 = require("./evidence-grounding");
|
|
29
|
-
const execution_backend_1 = require("./execution-backend");
|
|
30
|
-
const telemetry_attestation_1 = require("./telemetry-attestation");
|
|
31
|
-
exports.TRUST_AUDIT_SCHEMA_VERSION = 1;
|
|
32
|
-
// ---- Tamper-evidence chain (v0.1.81) --------------------------------------
|
|
33
|
-
// Same discipline as telemetry-ledger.ts / reclamation.ts: the event log is
|
|
34
|
-
// hash-chained in APPEND order, and verifyTrustAudit recomputes every hash
|
|
35
|
-
// independently (never trusts a stored value), so an edited or removed event is
|
|
36
|
-
// detected. Durability (fsync) only guards against power loss; this guards
|
|
37
|
-
// against post-hoc edits — the threat an external auditor actually cares about.
|
|
38
|
-
//
|
|
39
|
-
// THREAT MODEL (be honest about the limit): the genesis is sha256(runId), so this
|
|
40
|
-
// detects casual/partial tampering, accidental corruption, truncation, removal,
|
|
41
|
-
// and forged-unchained lines — but NOT a determined local writer who re-chains the
|
|
42
|
-
// WHOLE log with this module's own sha256 after an edit. That is the same limit
|
|
43
|
-
// reclamation.ts's tombstone chain has, and it is INHERENT to a local, self-
|
|
44
|
-
// recomputable chain: closing it needs an anchor the writer cannot reproduce.
|
|
45
|
-
// CW cannot self-sign that anchor — by design CW holds NO private key (see
|
|
46
|
-
// telemetry-attestation.ts: "CW never holds the private key"; the AGENT signs its
|
|
47
|
-
// usage, CW only VERIFIES with the operator-provisioned public half). The single
|
|
48
|
-
// cryptographic anchor that exists is therefore the agent's telemetry signature,
|
|
49
|
-
// which binds agent-reported USAGE (worker-isolation cross-links the chain into it)
|
|
50
|
-
// — it does NOT cover CW-only sandbox/policy/commit-gate decisions, which have no
|
|
51
|
-
// external signer. For those, the only stronger guarantee is operational: commit
|
|
52
|
-
// events.jsonl to an external append-only medium (git history / a remote log) the
|
|
53
|
-
// local writer cannot rewrite. The chain is a strict upgrade over a bare append-
|
|
54
|
-
// only log, not a substitute for an external anchor — and that anchor is not
|
|
55
|
-
// something CW can mint for itself.
|
|
56
|
-
/** Single source of truth for a run's audit-paths object: the schemaVersion plus
|
|
57
|
-
* the three derived file paths under auditRoot(run). ensureTrustAudit /
|
|
58
|
-
* refreshTrustAudit spread this, and createEventId reads .eventLogPath from it, so
|
|
59
|
-
* the path-derivation rule lives in exactly one place. */
|
|
60
|
-
function trustAuditPaths(run) {
|
|
61
|
-
const dir = auditRoot(run);
|
|
62
|
-
return {
|
|
63
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
64
|
-
eventLogPath: node_path_1.default.join(dir, "events.jsonl"),
|
|
65
|
-
summaryPath: node_path_1.default.join(dir, "summary.json"),
|
|
66
|
-
indexPath: node_path_1.default.join(dir, "index.json")
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
/** Genesis prevHash for a run's chain (no prior event). */
|
|
70
|
-
function trustAuditGenesis(runId) {
|
|
71
|
-
return (0, execution_backend_1.sha256)(`cw-trust-audit:${runId}`);
|
|
72
|
-
}
|
|
73
|
-
/** Canonical bytes the eventHash binds: every field EXCEPT eventHash itself
|
|
74
|
-
* (prevEventHash included, so the chain link is bound).
|
|
75
|
-
*
|
|
76
|
-
* The hash binds the PERSISTED form. `stableStringify` keeps an undefined-valued
|
|
77
|
-
* key as `"k":null`, but the `JSON.stringify` that writes events.jsonl DROPS such
|
|
78
|
-
* keys — so without this round-trip the record-time hash (over the in-memory event,
|
|
79
|
-
* which can carry nested undefined like an absent dispatchId in worker-sandbox
|
|
80
|
-
* metadata) would never match the verify-time hash (over the parsed-from-disk
|
|
81
|
-
* event), false-failing legitimate worker events as `trust-audit-digest-mismatch`.
|
|
82
|
-
* Round-tripping makes record-time == verify-time. It is identity for events with
|
|
83
|
-
* no undefined fields, so existing intact chains hash unchanged. */
|
|
84
|
-
function computeEventHash(event) {
|
|
85
|
-
const { eventHash, ...rest } = event;
|
|
86
|
-
return (0, execution_backend_1.sha256)((0, telemetry_attestation_1.stableStringify)(JSON.parse(JSON.stringify(rest))));
|
|
87
|
-
}
|
|
88
|
-
/** The hash to chain the NEXT event to: the stored eventHash, or a recompute for
|
|
89
|
-
* a legacy event written before the chain existed. */
|
|
90
|
-
function chainHashOf(event) {
|
|
91
|
-
return event.eventHash || computeEventHash(event);
|
|
92
|
-
}
|
|
93
|
-
/** Read events in FILE (append) order, tolerating corrupt lines — one bad line
|
|
94
|
-
* must not brick the whole audit read surface (it is counted, not thrown). The
|
|
95
|
-
* chain links append order, so this is the order verification walks. */
|
|
96
|
-
function readEventsRaw(eventLogPath) {
|
|
97
|
-
if (!node_fs_1.default.existsSync(eventLogPath))
|
|
98
|
-
return { events: [], corruptLines: 0 };
|
|
99
|
-
let corruptLines = 0;
|
|
100
|
-
const events = [];
|
|
101
|
-
for (const line of node_fs_1.default.readFileSync(eventLogPath, "utf8").split(/\n/g)) {
|
|
102
|
-
const trimmed = line.trim();
|
|
103
|
-
if (!trimmed)
|
|
104
|
-
continue;
|
|
105
|
-
try {
|
|
106
|
-
events.push(JSON.parse(trimmed));
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
corruptLines += 1;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return { events, corruptLines };
|
|
113
|
-
}
|
|
114
|
-
/** Re-prove the run's trust-audit chain: prevEventHash linkage (append order) +
|
|
115
|
-
* per-event hash recompute. A corrupt line, an edited event, or a removed event
|
|
116
|
-
* flips verified=false. Legacy events without a hash are reported as `unchained`
|
|
117
|
-
* (skipped), NOT treated as a forgery — they predate the chain. */
|
|
118
|
-
function verifyTrustAudit(run) {
|
|
119
|
-
const audit = ensureTrustAudit(run);
|
|
120
|
-
const { events, corruptLines } = readEventsRaw(audit.eventLogPath);
|
|
121
|
-
const checks = [];
|
|
122
|
-
let verified = corruptLines === 0;
|
|
123
|
-
if (corruptLines > 0)
|
|
124
|
-
checks.push({ name: "parse", pass: false, code: "trust-audit-corrupt-line" });
|
|
125
|
-
let chained = 0;
|
|
126
|
-
let unchained = 0;
|
|
127
|
-
let expectedPrev = trustAuditGenesis(run.id);
|
|
128
|
-
for (let i = 0; i < events.length; i++) {
|
|
129
|
-
const event = events[i];
|
|
130
|
-
const recomputed = computeEventHash(event);
|
|
131
|
-
if (event.eventHash === undefined) {
|
|
132
|
-
unchained += 1;
|
|
133
|
-
expectedPrev = recomputed; // advance the chain over legacy events
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
chained += 1;
|
|
137
|
-
if (event.eventHash !== recomputed) {
|
|
138
|
-
verified = false;
|
|
139
|
-
checks.push({ name: `event-hash[${i}]`, pass: false, code: "trust-audit-digest-mismatch" });
|
|
140
|
-
}
|
|
141
|
-
if (event.prevEventHash !== undefined && event.prevEventHash !== expectedPrev) {
|
|
142
|
-
verified = false;
|
|
143
|
-
checks.push({ name: `chain-link[${i}]`, pass: false, code: "trust-audit-chain-broken" });
|
|
144
|
-
}
|
|
145
|
-
expectedPrev = event.eventHash;
|
|
146
|
-
}
|
|
147
|
-
// A log with ANY chained event must have EVERY event chained: a single run is
|
|
148
|
-
// written by one code version, so it is all-chained (chain era) or all-legacy
|
|
149
|
-
// (pre-chain). An unchained (eventHash-less) line mixed into a chained log is a
|
|
150
|
-
// forgery attempt — drop the hash to be waved through as "legacy" — so it fails.
|
|
151
|
-
if (chained > 0 && unchained > 0) {
|
|
152
|
-
verified = false;
|
|
153
|
-
checks.push({ name: "unchained-events", pass: false, code: "trust-audit-unchained-event" });
|
|
154
|
-
}
|
|
155
|
-
return { present: events.length > 0, verified, eventCount: events.length, chained, unchained, corruptLines, checks };
|
|
156
|
-
}
|
|
157
|
-
// ---- Correlation-id fields (single source of truth, F12) -------------------
|
|
158
|
-
// These id fields are plain pass-throughs that flow input -> persisted event ->
|
|
159
|
-
// summary index unchanged. They were previously re-listed by hand in three
|
|
160
|
-
// places (recordTrustAuditEvent, the index writer, and partially in
|
|
161
|
-
// multi-agent-trust), so adding a new correlation id meant editing every list and
|
|
162
|
-
// silently dropping it from the index when one was missed. They now live in ONE
|
|
163
|
-
// array; both spread sites pick from it via pickCorrelationIds, so a new id is
|
|
164
|
-
// added in exactly one place.
|
|
165
|
-
//
|
|
166
|
-
// SERIALIZATION-PRESERVING by design: this is a plain key-copy with NO transform,
|
|
167
|
-
// so the persisted JSON for these keys is byte-identical to the old hand-spread
|
|
168
|
-
// (compact() still drops the undefined ones). The hash chain that binds these
|
|
169
|
-
// fields is therefore unaffected. Fields needing derivation/normalization
|
|
170
|
-
// (feedbackIds, sandboxProfileId, policyRef, multiAgentPolicyRef, normalizedPath,
|
|
171
|
-
// envVars, …) are intentionally NOT here — they keep their bespoke handling at the
|
|
172
|
-
// call site.
|
|
173
|
-
exports.CORRELATION_ID_FIELDS = [
|
|
174
|
-
"candidateId",
|
|
175
|
-
"scoreId",
|
|
176
|
-
"selectionId",
|
|
177
|
-
"commitId",
|
|
178
|
-
"multiAgentRunId",
|
|
179
|
-
"agentRoleId",
|
|
180
|
-
"agentGroupId",
|
|
181
|
-
"agentMembershipId",
|
|
182
|
-
"agentFanoutId",
|
|
183
|
-
"agentFaninId",
|
|
184
|
-
"blackboardId",
|
|
185
|
-
"blackboardTopicId",
|
|
186
|
-
"blackboardMessageId",
|
|
187
|
-
"blackboardContextId",
|
|
188
|
-
"blackboardArtifactRefId",
|
|
189
|
-
"blackboardSnapshotId",
|
|
190
|
-
"coordinatorDecisionId",
|
|
191
|
-
"topologyId",
|
|
192
|
-
"topologyRunId"
|
|
193
|
-
];
|
|
194
|
-
/** Copy exactly the correlation-id keys (and no others) from `source`, preserving
|
|
195
|
-
* each value verbatim (including `undefined`, which compact()/JSON.stringify drop
|
|
196
|
-
* identically to the prior per-key spread). Spread the result; do not transform. */
|
|
197
|
-
function pickCorrelationIds(source) {
|
|
198
|
-
const picked = {};
|
|
199
|
-
for (const field of exports.CORRELATION_ID_FIELDS)
|
|
200
|
-
picked[field] = source[field];
|
|
201
|
-
return picked;
|
|
202
|
-
}
|
|
203
|
-
// The summary index has always carried every correlation id EXCEPT scoreId (the
|
|
204
|
-
// per-candidate score lives in the candidates[] rows, not the flat event index).
|
|
205
|
-
// Pin that exception in ONE place so the index stays byte-identical while still
|
|
206
|
-
// inheriting any NEW id from CORRELATION_ID_FIELDS automatically.
|
|
207
|
-
const INDEX_OMITTED_CORRELATION_IDS = new Set(["scoreId"]);
|
|
208
|
-
/** Correlation ids for the summary index: the full pick minus the keys the index
|
|
209
|
-
* has historically omitted (see INDEX_OMITTED_CORRELATION_IDS). */
|
|
210
|
-
function indexCorrelationIds(event) {
|
|
211
|
-
const picked = pickCorrelationIds(event);
|
|
212
|
-
for (const field of INDEX_OMITTED_CORRELATION_IDS)
|
|
213
|
-
delete picked[field];
|
|
214
|
-
return picked;
|
|
215
|
-
}
|
|
216
|
-
function ensureTrustAudit(run) {
|
|
217
|
-
const auditDir = auditRoot(run);
|
|
218
|
-
node_fs_1.default.mkdirSync(auditDir, { recursive: true });
|
|
219
|
-
run.paths.auditDir = auditDir;
|
|
220
|
-
const audit = { ...trustAuditPaths(run) };
|
|
221
|
-
run.audit = audit;
|
|
222
|
-
if (!node_fs_1.default.existsSync(audit.eventLogPath))
|
|
223
|
-
node_fs_1.default.writeFileSync(audit.eventLogPath, "", "utf8");
|
|
224
|
-
return audit;
|
|
225
|
-
}
|
|
226
|
-
function recordTrustAuditEvent(run, input) {
|
|
227
|
-
const audit = ensureTrustAudit(run);
|
|
228
|
-
const event = compact({
|
|
229
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
230
|
-
id: createEventId(run, input.kind),
|
|
231
|
-
createdAt: new Date().toISOString(),
|
|
232
|
-
runId: run.id,
|
|
233
|
-
kind: input.kind,
|
|
234
|
-
decision: input.decision,
|
|
235
|
-
source: input.source,
|
|
236
|
-
actor: input.actor,
|
|
237
|
-
workerId: input.workerId,
|
|
238
|
-
taskId: input.taskId,
|
|
239
|
-
nodeId: input.nodeId,
|
|
240
|
-
feedbackIds: input.feedbackIds?.filter(Boolean).sort(),
|
|
241
|
-
// Plain correlation-id pass-throughs (candidateId … topologyRunId) come from the
|
|
242
|
-
// single CORRELATION_ID_FIELDS list. Key order is preserved (the list is in the
|
|
243
|
-
// same order the keys used to be hand-written), so the persisted JSON — and thus
|
|
244
|
-
// the eventHash chain — is byte-identical.
|
|
245
|
-
...pickCorrelationIds(input),
|
|
246
|
-
sandboxProfileId: input.sandboxProfileId || input.policySnapshot?.id,
|
|
247
|
-
policyRef: input.policyRef || (input.policySnapshot?.id ? `run.sandboxProfiles.${input.policySnapshot.id}` : undefined),
|
|
248
|
-
multiAgentPolicyRef: input.policyRef,
|
|
249
|
-
policySnapshot: redactPolicy(input.policySnapshot),
|
|
250
|
-
normalizedPath: input.normalizedPath ? node_path_1.default.resolve(input.normalizedPath) : undefined,
|
|
251
|
-
command: input.command,
|
|
252
|
-
networkTarget: input.networkTarget,
|
|
253
|
-
envVars: input.envVars ? unique(input.envVars.map(String)).sort() : undefined,
|
|
254
|
-
evidence: normalizeEvidence(run, input.evidence || [], {
|
|
255
|
-
source: input.source,
|
|
256
|
-
workerId: input.workerId,
|
|
257
|
-
taskId: input.taskId,
|
|
258
|
-
resultNodeId: input.nodeId
|
|
259
|
-
}),
|
|
260
|
-
evidenceRefs: unique(input.evidenceRefs || []).sort(),
|
|
261
|
-
parentEventIds: unique(input.parentEventIds || []).sort(),
|
|
262
|
-
metadata: scrubMetadata(input.metadata || {})
|
|
263
|
-
});
|
|
264
|
-
// Tamper-evidence chain: link this event to the prior one (append order) and
|
|
265
|
-
// bind its content with eventHash BEFORE persisting. verifyTrustAudit recomputes
|
|
266
|
-
// both independently, so a later edit or removal is detectable.
|
|
267
|
-
const prior = readEventsRaw(audit.eventLogPath).events;
|
|
268
|
-
event.prevEventHash = prior.length ? chainHashOf(prior[prior.length - 1]) : trustAuditGenesis(run.id);
|
|
269
|
-
event.eventHash = computeEventHash(event);
|
|
270
|
-
// DURABLE append (v0.1.40 self-audit P1): the audit log is the one artifact
|
|
271
|
-
// whose loss breaks audit-completeness, so fsync it before returning — never a
|
|
272
|
-
// bare appendFileSync, which can drop the last event on power loss.
|
|
273
|
-
(0, state_1.durableAppendFileSync)(audit.eventLogPath, `${JSON.stringify(event)}\n`);
|
|
274
|
-
refreshTrustAudit(run);
|
|
275
|
-
return event;
|
|
276
|
-
}
|
|
277
|
-
function recordSandboxPathDecision(run, input) {
|
|
278
|
-
return recordTrustAuditEvent(run, {
|
|
279
|
-
kind: input.kind || "sandbox.path",
|
|
280
|
-
decision: input.decision,
|
|
281
|
-
source: input.source || "cw-validated",
|
|
282
|
-
workerId: input.workerId,
|
|
283
|
-
taskId: input.taskId,
|
|
284
|
-
sandboxProfileId: input.sandboxProfileId,
|
|
285
|
-
policySnapshot: input.policySnapshot,
|
|
286
|
-
normalizedPath: input.target,
|
|
287
|
-
feedbackIds: input.feedbackIds,
|
|
288
|
-
metadata: input.metadata
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
function recordSandboxPolicyDecision(run, input) {
|
|
292
|
-
return recordTrustAuditEvent(run, {
|
|
293
|
-
...input,
|
|
294
|
-
source: input.source || "cw-validated"
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
function recordHostAttestation(run, input) {
|
|
298
|
-
return recordTrustAuditEvent(run, {
|
|
299
|
-
...input,
|
|
300
|
-
kind: input.kind || "sandbox.host-attestation",
|
|
301
|
-
decision: "recorded",
|
|
302
|
-
source: "host-attested"
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
// Per-request event log cache (v0.1.95). When set, readEvents returns
|
|
306
|
-
// memoized results keyed by event log path. Clears after each request.
|
|
307
|
-
let _eventLogCache = null;
|
|
308
|
-
function setAuditEventCache(cache) {
|
|
309
|
-
_eventLogCache = cache;
|
|
310
|
-
}
|
|
311
|
-
function clearAuditEventCache() {
|
|
312
|
-
_eventLogCache = null;
|
|
313
|
-
}
|
|
314
|
-
function listTrustAuditEvents(run) {
|
|
315
|
-
const audit = ensureTrustAudit(run);
|
|
316
|
-
if (_eventLogCache) {
|
|
317
|
-
const cached = _eventLogCache.get(audit.eventLogPath);
|
|
318
|
-
if (cached)
|
|
319
|
-
return cached;
|
|
320
|
-
}
|
|
321
|
-
const events = readEventsRaw(audit.eventLogPath).events.sort(compareEvents);
|
|
322
|
-
_eventLogCache?.set(audit.eventLogPath, events);
|
|
323
|
-
return events;
|
|
324
|
-
}
|
|
325
|
-
/** Search audit events by kind, worker, or candidate (v0.1.65).
|
|
326
|
-
* Filters are AND-ed; empty filters match all. */
|
|
327
|
-
function searchAuditEvents(run, filters) {
|
|
328
|
-
let events = listTrustAuditEvents(run);
|
|
329
|
-
if (filters.kind)
|
|
330
|
-
events = events.filter((e) => e.kind === filters.kind);
|
|
331
|
-
if (filters.workerId)
|
|
332
|
-
events = events.filter((e) => e.workerId === filters.workerId);
|
|
333
|
-
if (filters.candidateId)
|
|
334
|
-
events = events.filter((e) => e.candidateId === filters.candidateId);
|
|
335
|
-
if (filters.limit && filters.limit > 0)
|
|
336
|
-
events = events.slice(0, filters.limit);
|
|
337
|
-
return events;
|
|
338
|
-
}
|
|
339
|
-
function summarizeTrustAudit(run) {
|
|
340
|
-
const audit = ensureTrustAudit(run);
|
|
341
|
-
const events = readEvents(audit.eventLogPath);
|
|
342
|
-
const summary = {
|
|
343
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
344
|
-
runId: run.id,
|
|
345
|
-
generatedAt: new Date().toISOString(),
|
|
346
|
-
eventCount: events.length,
|
|
347
|
-
integrity: verifyTrustAudit(run),
|
|
348
|
-
eventLogPath: audit.eventLogPath,
|
|
349
|
-
indexPath: audit.indexPath,
|
|
350
|
-
summaryPath: audit.summaryPath,
|
|
351
|
-
byKind: countBy(events, (event) => event.kind),
|
|
352
|
-
byDecision: countBy(events, (event) => event.decision),
|
|
353
|
-
bySource: countBy(events, (event) => event.source),
|
|
354
|
-
bySandboxProfile: countBy(events.filter((event) => event.sandboxProfileId), (event) => event.sandboxProfileId || "none"),
|
|
355
|
-
workers: workerRows(events, run),
|
|
356
|
-
candidates: candidateRows(events, run),
|
|
357
|
-
commits: commitRows(events, run),
|
|
358
|
-
multiAgent: {
|
|
359
|
-
runs: run.multiAgent?.runs.length || 0,
|
|
360
|
-
roles: run.multiAgent?.roles.length || 0,
|
|
361
|
-
groups: run.multiAgent?.groups.length || 0,
|
|
362
|
-
memberships: run.multiAgent?.memberships.length || 0,
|
|
363
|
-
fanouts: run.multiAgent?.fanouts.length || 0,
|
|
364
|
-
fanins: run.multiAgent?.fanins.length || 0,
|
|
365
|
-
events: events.filter((event) => Boolean(event.multiAgentRunId ||
|
|
366
|
-
event.agentRoleId ||
|
|
367
|
-
event.agentGroupId ||
|
|
368
|
-
event.agentMembershipId ||
|
|
369
|
-
event.agentFanoutId ||
|
|
370
|
-
event.agentFaninId)).length
|
|
371
|
-
},
|
|
372
|
-
blackboard: {
|
|
373
|
-
boards: run.blackboard?.boards.length || 0,
|
|
374
|
-
topics: run.blackboard?.topics.length || 0,
|
|
375
|
-
messages: run.blackboard?.messages.length || 0,
|
|
376
|
-
contexts: run.blackboard?.contexts.length || 0,
|
|
377
|
-
artifacts: run.blackboard?.artifacts.length || 0,
|
|
378
|
-
snapshots: run.blackboard?.snapshots.length || 0,
|
|
379
|
-
decisions: run.blackboard?.decisions.length || 0,
|
|
380
|
-
events: events.filter((event) => Boolean(event.blackboardId ||
|
|
381
|
-
event.blackboardTopicId ||
|
|
382
|
-
event.blackboardMessageId ||
|
|
383
|
-
event.blackboardContextId ||
|
|
384
|
-
event.blackboardArtifactRefId ||
|
|
385
|
-
event.blackboardSnapshotId ||
|
|
386
|
-
event.coordinatorDecisionId)).length
|
|
387
|
-
},
|
|
388
|
-
topologies: {
|
|
389
|
-
runs: run.topologies?.runs.length || 0,
|
|
390
|
-
events: events.filter((event) => Boolean(event.topologyId || event.topologyRunId || event.kind.startsWith("topology."))).length
|
|
391
|
-
},
|
|
392
|
-
multiAgentTrust: {
|
|
393
|
-
rolePolicies: events.filter((event) => event.kind === "multi-agent.role-policy").length,
|
|
394
|
-
permissionDecisions: events.filter((event) => event.kind === "multi-agent.permission").length,
|
|
395
|
-
blackboardWrites: events.filter((event) => event.kind === "blackboard.write").length,
|
|
396
|
-
messageProvenance: events.filter((event) => event.kind === "blackboard.message-provenance").length,
|
|
397
|
-
judgeRationales: events.filter((event) => event.kind === "judge.rationale").length,
|
|
398
|
-
panelDecisions: events.filter((event) => event.kind === "judge.panel-decision").length,
|
|
399
|
-
policyViolations: events.filter((event) => event.kind === "policy.violation").length
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
// Durable (v0.1.40 self-audit P1): the summary/index are the read-side view of
|
|
403
|
-
// the audit log; persist them durably so a crash can't leave them pointing past
|
|
404
|
-
// the last durably-appended event.
|
|
405
|
-
(0, state_1.writeJson)(audit.summaryPath, summary, { durable: true });
|
|
406
|
-
(0, state_1.writeJson)(audit.indexPath, {
|
|
407
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
408
|
-
runId: run.id,
|
|
409
|
-
events: events.map((event) => ({
|
|
410
|
-
id: event.id,
|
|
411
|
-
createdAt: event.createdAt,
|
|
412
|
-
kind: event.kind,
|
|
413
|
-
decision: event.decision,
|
|
414
|
-
source: event.source,
|
|
415
|
-
workerId: event.workerId,
|
|
416
|
-
taskId: event.taskId,
|
|
417
|
-
// Same single CORRELATION_ID_FIELDS list the record path uses, so the index
|
|
418
|
-
// can never silently omit a correlation id that the event carries. (The index
|
|
419
|
-
// historically omitted scoreId; that is preserved below by deleting it after
|
|
420
|
-
// the pick, keeping this writer's output byte-identical.)
|
|
421
|
-
...indexCorrelationIds(event),
|
|
422
|
-
sandboxProfileId: event.sandboxProfileId,
|
|
423
|
-
policyRef: event.policyRef,
|
|
424
|
-
multiAgentPolicyRef: event.multiAgentPolicyRef
|
|
425
|
-
}))
|
|
426
|
-
}, { durable: true });
|
|
427
|
-
run.audit = audit;
|
|
428
|
-
return summary;
|
|
429
|
-
}
|
|
430
|
-
function refreshTrustAudit(run) {
|
|
431
|
-
const audit = { ...trustAuditPaths(run) };
|
|
432
|
-
node_fs_1.default.mkdirSync(node_path_1.default.dirname(audit.eventLogPath), { recursive: true });
|
|
433
|
-
if (!node_fs_1.default.existsSync(audit.eventLogPath))
|
|
434
|
-
node_fs_1.default.writeFileSync(audit.eventLogPath, "", "utf8");
|
|
435
|
-
run.audit = audit;
|
|
436
|
-
return summarizeTrustAudit(run);
|
|
437
|
-
}
|
|
438
|
-
function workerTrustAudit(run, workerId) {
|
|
439
|
-
return { workerId, events: listTrustAuditEvents(run).filter((event) => event.workerId === workerId) };
|
|
440
|
-
}
|
|
441
|
-
function normalizeEvidence(run, evidence, provenance) {
|
|
442
|
-
const baseDirs = [run.cwd, run.paths.runDir].filter(Boolean);
|
|
443
|
-
return evidence.map((entry) => ({
|
|
444
|
-
...entry,
|
|
445
|
-
// Auto-compute confidence tier from locator shape + (in strict mode) filesystem.
|
|
446
|
-
// "verified" is never auto-assigned — requires explicit host attestation (v0.1.55).
|
|
447
|
-
confidence: entry.confidence || (0, evidence_grounding_1.computeEvidenceConfidence)(entry.locator || entry.path || entry.summary, baseDirs),
|
|
448
|
-
// Extract actual file content for file-style evidence locators (v0.1.74).
|
|
449
|
-
contentPreview: entry.contentPreview || ((entry.locator || entry.path) ? (0, evidence_grounding_1.extractEvidenceContent)(entry.locator || entry.path || "", baseDirs) : undefined),
|
|
450
|
-
provenance: {
|
|
451
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
452
|
-
runId: run.id,
|
|
453
|
-
source: provenance.source || entry.provenance?.source || "runtime-derived",
|
|
454
|
-
workerId: provenance.workerId || entry.provenance?.workerId,
|
|
455
|
-
taskId: provenance.taskId || entry.provenance?.taskId,
|
|
456
|
-
resultNodeId: provenance.resultNodeId || entry.provenance?.resultNodeId,
|
|
457
|
-
verifierNodeId: provenance.verifierNodeId || entry.provenance?.verifierNodeId,
|
|
458
|
-
candidateId: provenance.candidateId || entry.provenance?.candidateId,
|
|
459
|
-
scoreId: provenance.scoreId || entry.provenance?.scoreId,
|
|
460
|
-
selectionId: provenance.selectionId || entry.provenance?.selectionId,
|
|
461
|
-
commitId: provenance.commitId || entry.provenance?.commitId,
|
|
462
|
-
parentEvidenceIds: unique([...(entry.provenance?.parentEvidenceIds || []), ...(provenance.parentEvidenceIds || [])]).sort(),
|
|
463
|
-
auditEventIds: unique([...(entry.provenance?.auditEventIds || []), ...(provenance.auditEventIds || [])]).sort(),
|
|
464
|
-
note: provenance.note || entry.provenance?.note
|
|
465
|
-
}
|
|
466
|
-
}));
|
|
467
|
-
}
|
|
468
|
-
function evidenceProvenance(run, options = {}) {
|
|
469
|
-
const events = listTrustAuditEvents(run).filter((event) => {
|
|
470
|
-
if (options.candidateId && event.candidateId !== options.candidateId)
|
|
471
|
-
return false;
|
|
472
|
-
if (options.commitId && event.commitId !== options.commitId)
|
|
473
|
-
return false;
|
|
474
|
-
if (options.workerId && event.workerId !== options.workerId)
|
|
475
|
-
return false;
|
|
476
|
-
return true;
|
|
477
|
-
});
|
|
478
|
-
const evidence = [];
|
|
479
|
-
for (const node of run.nodes || [])
|
|
480
|
-
evidence.push(...(node.evidence || []));
|
|
481
|
-
for (const candidate of run.candidates || [])
|
|
482
|
-
evidence.push(...(candidate.evidence || []));
|
|
483
|
-
for (const selection of run.candidateSelections || [])
|
|
484
|
-
evidence.push(...(selection.evidence || []));
|
|
485
|
-
for (const commit of run.commits || [])
|
|
486
|
-
evidence.push(...(commit.evidence || []));
|
|
487
|
-
const filtered = evidence.filter((entry) => {
|
|
488
|
-
if (options.candidateId && entry.provenance?.candidateId !== options.candidateId)
|
|
489
|
-
return false;
|
|
490
|
-
if (options.commitId && entry.provenance?.commitId !== options.commitId)
|
|
491
|
-
return false;
|
|
492
|
-
if (options.workerId && entry.provenance?.workerId !== options.workerId)
|
|
493
|
-
return false;
|
|
494
|
-
return true;
|
|
495
|
-
});
|
|
496
|
-
return { runId: run.id, evidence: filtered, events };
|
|
497
|
-
}
|
|
498
|
-
function validateAcceptanceRationale(rationale) {
|
|
499
|
-
if (!rationale)
|
|
500
|
-
return ["acceptance rationale is missing"];
|
|
501
|
-
const failures = [];
|
|
502
|
-
if (!rationale.selectedCandidateId)
|
|
503
|
-
failures.push("selected candidate id is missing");
|
|
504
|
-
if (!rationale.scoreId)
|
|
505
|
-
failures.push("score id is missing");
|
|
506
|
-
if (!rationale.verifierNodeId)
|
|
507
|
-
failures.push("verifier node id is missing");
|
|
508
|
-
if (!rationale.evidenceCount)
|
|
509
|
-
failures.push("evidence count is zero");
|
|
510
|
-
if (!rationale.workerId)
|
|
511
|
-
failures.push("worker id is missing");
|
|
512
|
-
if (!rationale.sandboxProfileId)
|
|
513
|
-
failures.push("sandbox profile id is missing");
|
|
514
|
-
if (rationale.commitGateResult !== "passed")
|
|
515
|
-
failures.push("commit gate result is not passed");
|
|
516
|
-
return failures;
|
|
517
|
-
}
|
|
518
|
-
function buildAcceptanceRationale(input) {
|
|
519
|
-
return {
|
|
520
|
-
schemaVersion: exports.TRUST_AUDIT_SCHEMA_VERSION,
|
|
521
|
-
selectedCandidateId: input.selectedCandidateId,
|
|
522
|
-
scoreId: input.scoreId,
|
|
523
|
-
scoreCriteria: input.scoreCriteria,
|
|
524
|
-
verifierNodeId: input.verifierNodeId,
|
|
525
|
-
evidenceCount: input.evidenceCount || 0,
|
|
526
|
-
sandboxProfileId: input.sandboxProfileId,
|
|
527
|
-
workerId: input.workerId,
|
|
528
|
-
commitGateResult: input.commitGateResult,
|
|
529
|
-
auditEventIds: unique(input.auditEventIds || []).sort()
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
function auditRoot(run) {
|
|
533
|
-
return run.paths.auditDir || node_path_1.default.join(run.paths.runDir, "audit");
|
|
534
|
-
}
|
|
535
|
-
function readEvents(eventLogPath) {
|
|
536
|
-
if (_eventLogCache) {
|
|
537
|
-
const cached = _eventLogCache.get(eventLogPath);
|
|
538
|
-
if (cached)
|
|
539
|
-
return cached;
|
|
540
|
-
}
|
|
541
|
-
const events = readEventsRaw(eventLogPath).events.sort(compareEvents);
|
|
542
|
-
_eventLogCache?.set(eventLogPath, events);
|
|
543
|
-
return events;
|
|
544
|
-
}
|
|
545
|
-
function workerRows(events, run) {
|
|
546
|
-
const workerIds = unique([...(run.workers || []).map((worker) => worker.id), ...events.map((event) => event.workerId || "")]).sort();
|
|
547
|
-
return workerIds.filter(Boolean).map((workerId) => {
|
|
548
|
-
const worker = (run.workers || []).find((entry) => entry.id === workerId);
|
|
549
|
-
const scoped = events.filter((event) => event.workerId === workerId);
|
|
550
|
-
return {
|
|
551
|
-
workerId,
|
|
552
|
-
taskId: worker?.taskId || scoped.find((event) => event.taskId)?.taskId,
|
|
553
|
-
sandboxProfileId: worker?.sandboxProfileId || scoped.find((event) => event.sandboxProfileId)?.sandboxProfileId,
|
|
554
|
-
decisions: countBy(scoped, (event) => event.decision),
|
|
555
|
-
denied: scoped.filter((event) => event.decision === "denied" || event.decision === "rejected").length,
|
|
556
|
-
feedbackIds: unique(scoped.flatMap((event) => event.feedbackIds || [])).sort()
|
|
557
|
-
};
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
function candidateRows(events, run) {
|
|
561
|
-
const ids = unique([...(run.candidates || []).map((candidate) => candidate.id), ...events.map((event) => event.candidateId || "")]).sort();
|
|
562
|
-
return ids.filter(Boolean).map((candidateId) => {
|
|
563
|
-
const candidate = (run.candidates || []).find((entry) => entry.id === candidateId);
|
|
564
|
-
const selections = (run.candidateSelections || []).filter((selection) => selection.candidateId === candidateId);
|
|
565
|
-
const scoped = events.filter((event) => event.candidateId === candidateId);
|
|
566
|
-
return {
|
|
567
|
-
candidateId,
|
|
568
|
-
scoreIds: unique([...(candidate?.scores || []), ...scoped.map((event) => event.scoreId || "")]).filter(Boolean).sort(),
|
|
569
|
-
selectionIds: unique([...selections.map((selection) => selection.id), ...scoped.map((event) => event.selectionId || "")]).filter(Boolean).sort(),
|
|
570
|
-
evidenceCount: candidate?.evidence.length || scoped.flatMap((event) => event.evidence || []).length
|
|
571
|
-
};
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
function commitRows(events, run) {
|
|
575
|
-
const ids = unique([...(run.commits || []).map((commit) => commit.id), ...events.map((event) => event.commitId || "")]).sort();
|
|
576
|
-
return ids.filter(Boolean).map((commitId) => {
|
|
577
|
-
const commit = (run.commits || []).find((entry) => entry.id === commitId);
|
|
578
|
-
return {
|
|
579
|
-
commitId,
|
|
580
|
-
verifierGated: Boolean(commit?.verifierGated),
|
|
581
|
-
candidateId: commit?.candidateId,
|
|
582
|
-
selectionId: commit?.selectionId,
|
|
583
|
-
evidenceCount: commit?.evidence?.length || 0,
|
|
584
|
-
rationale: commit?.acceptanceRationale
|
|
585
|
-
};
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
|
-
function createEventId(run, kind) {
|
|
589
|
-
// Deterministic (FreeBSD-audit L12/L13): chain-local sequence (event-log length),
|
|
590
|
-
// no wall-clock stamp — event.id is bound into the eventHash chain (computeEventHash),
|
|
591
|
-
// so a stable id keeps the chain reproducible on replay.
|
|
592
|
-
const count = readEvents(trustAuditPaths(run).eventLogPath).length + 1;
|
|
593
|
-
return `audit-${(0, state_1.safeFileName)(kind)}-${String(count).padStart(4, "0")}`;
|
|
594
|
-
}
|
|
595
|
-
function redactPolicy(policy) {
|
|
596
|
-
if (!policy)
|
|
597
|
-
return undefined;
|
|
598
|
-
return {
|
|
599
|
-
...policy,
|
|
600
|
-
env: {
|
|
601
|
-
inherit: Boolean(policy.env.inherit),
|
|
602
|
-
expose: unique((policy.env.expose || []).map(String)).sort(),
|
|
603
|
-
deny: policy.env.deny ? unique(policy.env.deny.map(String)).sort() : undefined
|
|
604
|
-
},
|
|
605
|
-
metadata: scrubMetadata(policy.metadata || {})
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
function scrubMetadata(value) {
|
|
609
|
-
const result = {};
|
|
610
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
611
|
-
if (entry === undefined)
|
|
612
|
-
continue;
|
|
613
|
-
if (/secret|token|password|credential|authorization|api[_-]?key/i.test(key)) {
|
|
614
|
-
result[key] = "[redacted]";
|
|
615
|
-
}
|
|
616
|
-
else if (Array.isArray(entry)) {
|
|
617
|
-
result[key] = entry.map((item) => (typeof item === "string" && item.includes("=") ? item.split("=")[0] : item));
|
|
618
|
-
}
|
|
619
|
-
else if (entry && typeof entry === "object") {
|
|
620
|
-
result[key] = scrubMetadata(entry);
|
|
621
|
-
}
|
|
622
|
-
else {
|
|
623
|
-
result[key] = entry;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
return Object.keys(result).length ? result : undefined;
|
|
627
|
-
}
|
|
628
|
-
function compact(value) {
|
|
629
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
630
|
-
}
|
|
631
|
-
function countBy(items, key) {
|
|
632
|
-
const counts = {};
|
|
633
|
-
for (const item of items) {
|
|
634
|
-
const value = key(item);
|
|
635
|
-
counts[value] = (counts[value] || 0) + 1;
|
|
636
|
-
}
|
|
637
|
-
return counts;
|
|
638
|
-
}
|
|
639
|
-
function unique(values) {
|
|
640
|
-
return Array.from(new Set(values.filter(Boolean)));
|
|
641
|
-
}
|
|
642
|
-
function compareEvents(left, right) {
|
|
643
|
-
return left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
|
|
644
|
-
}
|
package/dist/types/blackboard.js
DELETED
package/dist/types/candidate.js
DELETED
package/dist/types/core.js
DELETED
package/dist/types/drive.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Agent Delegation Drive (v0.1.38) — result types for the `run --drive` auto-advance
|
|
3
|
-
// loop. The loop is a THIN orchestrator over the EXISTING verbs (plan / dispatch /
|
|
4
|
-
// recordWorkerOutput / commit) + the v0.1.37 scheduler; it introduces no second
|
|
5
|
-
// runner/queue. These are plain, deterministic projections of run state.
|
|
6
|
-
//
|
|
7
|
-
// DETERMINISM: every payload is derivable from the run state + an injected `now`.
|
|
8
|
-
// No now-derived NUMERIC field (counts come from state); only ISO timestamps may be
|
|
9
|
-
// now-derived (the parity probe strips them).
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|