@chllming/wave-orchestration 0.6.3 → 0.7.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.
Files changed (112) hide show
  1. package/CHANGELOG.md +57 -1
  2. package/README.md +39 -7
  3. package/docs/agents/wave-orchestrator-role.md +50 -0
  4. package/docs/agents/wave-planner-role.md +39 -0
  5. package/docs/context7/bundles.json +9 -0
  6. package/docs/context7/planner-agent/README.md +25 -0
  7. package/docs/context7/planner-agent/manifest.json +83 -0
  8. package/docs/context7/planner-agent/papers/cooperbench-why-coding-agents-cannot-be-your-teammates-yet.md +3283 -0
  9. package/docs/context7/planner-agent/papers/dova-deliberation-first-multi-agent-orchestration-for-autonomous-research-automation.md +1699 -0
  10. package/docs/context7/planner-agent/papers/dpbench-large-language-models-struggle-with-simultaneous-coordination.md +2251 -0
  11. package/docs/context7/planner-agent/papers/incremental-planning-to-control-a-blackboard-based-problem-solver.md +1729 -0
  12. package/docs/context7/planner-agent/papers/silo-bench-a-scalable-environment-for-evaluating-distributed-coordination-in-multi-agent-llm-systems.md +3747 -0
  13. package/docs/context7/planner-agent/papers/todoevolve-learning-to-architect-agent-planning-systems.md +1675 -0
  14. package/docs/context7/planner-agent/papers/verified-multi-agent-orchestration-a-plan-execute-verify-replan-framework-for-complex-query-resolution.md +1173 -0
  15. package/docs/context7/planner-agent/papers/why-do-multi-agent-llm-systems-fail.md +5211 -0
  16. package/docs/context7/planner-agent/topics/planning-and-orchestration.md +24 -0
  17. package/docs/evals/README.md +96 -1
  18. package/docs/evals/arm-templates/README.md +13 -0
  19. package/docs/evals/arm-templates/full-wave.json +15 -0
  20. package/docs/evals/arm-templates/single-agent.json +15 -0
  21. package/docs/evals/benchmark-catalog.json +7 -0
  22. package/docs/evals/cases/README.md +47 -0
  23. package/docs/evals/cases/wave-blackboard-inbox-targeting.json +73 -0
  24. package/docs/evals/cases/wave-contradiction-conflict.json +104 -0
  25. package/docs/evals/cases/wave-expert-routing-preservation.json +69 -0
  26. package/docs/evals/cases/wave-hidden-profile-private-evidence.json +81 -0
  27. package/docs/evals/cases/wave-premature-closure-guard.json +71 -0
  28. package/docs/evals/cases/wave-silo-cross-agent-state.json +77 -0
  29. package/docs/evals/cases/wave-simultaneous-lockstep.json +92 -0
  30. package/docs/evals/cooperbench/real-world-mitigation.md +341 -0
  31. package/docs/evals/external-benchmarks.json +85 -0
  32. package/docs/evals/external-command-config.sample.json +9 -0
  33. package/docs/evals/external-command-config.swe-bench-pro.json +8 -0
  34. package/docs/evals/pilots/README.md +47 -0
  35. package/docs/evals/pilots/swe-bench-pro-public-full-wave-review-10.json +64 -0
  36. package/docs/evals/pilots/swe-bench-pro-public-pilot.json +111 -0
  37. package/docs/evals/wave-benchmark-program.md +302 -0
  38. package/docs/guides/planner.md +48 -11
  39. package/docs/plans/context7-wave-orchestrator.md +20 -0
  40. package/docs/plans/current-state.md +8 -1
  41. package/docs/plans/examples/wave-benchmark-improvement.md +108 -0
  42. package/docs/plans/examples/wave-example-live-proof.md +1 -1
  43. package/docs/plans/examples/wave-example-rollout-fidelity.md +340 -0
  44. package/docs/plans/wave-orchestrator.md +62 -11
  45. package/docs/plans/waves/reviews/wave-1-benchmark-operator.md +118 -0
  46. package/docs/reference/coordination-and-closure.md +436 -0
  47. package/docs/reference/live-proof-waves.md +25 -3
  48. package/docs/reference/npmjs-trusted-publishing.md +3 -3
  49. package/docs/reference/proof-metrics.md +90 -0
  50. package/docs/reference/runtime-config/README.md +61 -0
  51. package/docs/reference/sample-waves.md +29 -18
  52. package/docs/reference/wave-control.md +164 -0
  53. package/docs/reference/wave-planning-lessons.md +131 -0
  54. package/package.json +5 -4
  55. package/releases/manifest.json +18 -0
  56. package/scripts/research/agent-context-archive.mjs +18 -0
  57. package/scripts/research/manifests/agent-context-expanded-2026-03-22.mjs +17 -0
  58. package/scripts/research/sync-planner-context7-bundle.mjs +133 -0
  59. package/scripts/wave-orchestrator/artifact-schemas.mjs +232 -0
  60. package/scripts/wave-orchestrator/autonomous.mjs +7 -0
  61. package/scripts/wave-orchestrator/benchmark-cases.mjs +374 -0
  62. package/scripts/wave-orchestrator/benchmark-external.mjs +1384 -0
  63. package/scripts/wave-orchestrator/benchmark.mjs +972 -0
  64. package/scripts/wave-orchestrator/clarification-triage.mjs +78 -12
  65. package/scripts/wave-orchestrator/config.mjs +175 -0
  66. package/scripts/wave-orchestrator/control-cli.mjs +1123 -0
  67. package/scripts/wave-orchestrator/control-plane.mjs +697 -0
  68. package/scripts/wave-orchestrator/coord-cli.mjs +360 -2
  69. package/scripts/wave-orchestrator/coordination-store.mjs +211 -9
  70. package/scripts/wave-orchestrator/coordination.mjs +84 -0
  71. package/scripts/wave-orchestrator/dashboard-renderer.mjs +38 -3
  72. package/scripts/wave-orchestrator/dashboard-state.mjs +22 -0
  73. package/scripts/wave-orchestrator/evals.mjs +23 -0
  74. package/scripts/wave-orchestrator/executors.mjs +3 -2
  75. package/scripts/wave-orchestrator/feedback.mjs +55 -0
  76. package/scripts/wave-orchestrator/install.mjs +55 -1
  77. package/scripts/wave-orchestrator/launcher-closure.mjs +4 -1
  78. package/scripts/wave-orchestrator/launcher-runtime.mjs +24 -21
  79. package/scripts/wave-orchestrator/launcher.mjs +796 -35
  80. package/scripts/wave-orchestrator/planner-context.mjs +75 -0
  81. package/scripts/wave-orchestrator/planner.mjs +2270 -136
  82. package/scripts/wave-orchestrator/proof-cli.mjs +195 -0
  83. package/scripts/wave-orchestrator/proof-registry.mjs +317 -0
  84. package/scripts/wave-orchestrator/replay.mjs +10 -4
  85. package/scripts/wave-orchestrator/retry-cli.mjs +184 -0
  86. package/scripts/wave-orchestrator/retry-control.mjs +225 -0
  87. package/scripts/wave-orchestrator/shared.mjs +26 -0
  88. package/scripts/wave-orchestrator/swe-bench-pro-task.mjs +1004 -0
  89. package/scripts/wave-orchestrator/traces.mjs +157 -2
  90. package/scripts/wave-orchestrator/wave-control-client.mjs +532 -0
  91. package/scripts/wave-orchestrator/wave-control-schema.mjs +309 -0
  92. package/scripts/wave-orchestrator/wave-files.mjs +17 -5
  93. package/scripts/wave.mjs +27 -0
  94. package/skills/repo-coding-rules/SKILL.md +1 -0
  95. package/skills/role-cont-eval/SKILL.md +1 -0
  96. package/skills/role-cont-qa/SKILL.md +13 -6
  97. package/skills/role-deploy/SKILL.md +1 -0
  98. package/skills/role-documentation/SKILL.md +4 -0
  99. package/skills/role-implementation/SKILL.md +4 -0
  100. package/skills/role-infra/SKILL.md +2 -1
  101. package/skills/role-integration/SKILL.md +15 -8
  102. package/skills/role-planner/SKILL.md +39 -0
  103. package/skills/role-planner/skill.json +21 -0
  104. package/skills/role-research/SKILL.md +1 -0
  105. package/skills/role-security/SKILL.md +2 -2
  106. package/skills/runtime-claude/SKILL.md +2 -1
  107. package/skills/runtime-codex/SKILL.md +1 -0
  108. package/skills/runtime-local/SKILL.md +2 -0
  109. package/skills/runtime-opencode/SKILL.md +1 -0
  110. package/skills/wave-core/SKILL.md +25 -6
  111. package/skills/wave-core/references/marker-syntax.md +16 -8
  112. package/wave.config.json +45 -0
@@ -0,0 +1,195 @@
1
+ import path from "node:path";
2
+ import { appendCoordinationRecord } from "./coordination-store.mjs";
3
+ import { parseWaveFiles } from "./wave-files.mjs";
4
+ import {
5
+ buildLanePaths,
6
+ parseNonNegativeInt,
7
+ readJsonOrNull,
8
+ REPO_ROOT,
9
+ sanitizeAdhocRunId,
10
+ sanitizeLaneName,
11
+ } from "./shared.mjs";
12
+ import {
13
+ readWaveProofRegistry,
14
+ registerWaveProofBundle,
15
+ } from "./proof-registry.mjs";
16
+
17
+ function printUsage() {
18
+ console.log(`Usage:
19
+ pnpm exec wave proof show --lane <lane> --wave <n> [--agent <id>] [--json]
20
+ pnpm exec wave proof register --lane <lane> --wave <n> --agent <id> --artifact <path> [--artifact <path> ...] [--component <id[:level]> ...] [--authoritative] [--satisfy-owned-components] [--completion <level>] [--durability <level>] [--proof-level <level>] [--doc-delta <state>] [--operator <name>] [--detail <text>] [--json]
21
+ pnpm exec wave proof <subcommand> --run <id> [--wave 0] ...
22
+ `);
23
+ }
24
+
25
+ function parseArgs(argv) {
26
+ const args = argv[0] === "--" ? argv.slice(1) : argv;
27
+ const subcommand = String(args[0] || "").trim().toLowerCase();
28
+ const options = {
29
+ lane: "main",
30
+ wave: null,
31
+ runId: "",
32
+ agentId: "",
33
+ artifactPaths: [],
34
+ components: [],
35
+ authoritative: false,
36
+ satisfyOwnedComponents: false,
37
+ completion: "",
38
+ durability: "",
39
+ proofLevel: "",
40
+ docDeltaState: "",
41
+ operator: "human-operator",
42
+ detail: "",
43
+ json: false,
44
+ };
45
+ for (let i = 1; i < args.length; i += 1) {
46
+ const arg = args[i];
47
+ if (arg === "--lane") {
48
+ options.lane = sanitizeLaneName(args[++i]);
49
+ } else if (arg === "--run") {
50
+ options.runId = sanitizeAdhocRunId(args[++i]);
51
+ } else if (arg === "--wave") {
52
+ options.wave = parseNonNegativeInt(args[++i], "--wave");
53
+ } else if (arg === "--agent") {
54
+ options.agentId = String(args[++i] || "").trim();
55
+ } else if (arg === "--artifact") {
56
+ options.artifactPaths.push(String(args[++i] || "").trim());
57
+ } else if (arg === "--component") {
58
+ options.components.push(String(args[++i] || "").trim());
59
+ } else if (arg === "--authoritative") {
60
+ options.authoritative = true;
61
+ } else if (arg === "--satisfy-owned-components") {
62
+ options.satisfyOwnedComponents = true;
63
+ } else if (arg === "--completion") {
64
+ options.completion = String(args[++i] || "").trim();
65
+ } else if (arg === "--durability") {
66
+ options.durability = String(args[++i] || "").trim();
67
+ } else if (arg === "--proof-level") {
68
+ options.proofLevel = String(args[++i] || "").trim();
69
+ } else if (arg === "--doc-delta") {
70
+ options.docDeltaState = String(args[++i] || "").trim();
71
+ } else if (arg === "--operator") {
72
+ options.operator = String(args[++i] || "").trim() || "human-operator";
73
+ } else if (arg === "--detail") {
74
+ options.detail = String(args[++i] || "").trim();
75
+ } else if (arg === "--json") {
76
+ options.json = true;
77
+ } else if (arg === "--help" || arg === "-h") {
78
+ return { help: true, subcommand, options };
79
+ } else {
80
+ throw new Error(`Unknown argument: ${arg}`);
81
+ }
82
+ }
83
+ return { help: false, subcommand, options };
84
+ }
85
+
86
+ function loadWave(lanePaths, waveNumber) {
87
+ const waves = parseWaveFiles(lanePaths.wavesDir, { laneProfile: lanePaths.laneProfile });
88
+ const wave = waves.find((entry) => entry.wave === waveNumber);
89
+ if (!wave) {
90
+ throw new Error(`Wave ${waveNumber} not found in ${lanePaths.wavesDir}`);
91
+ }
92
+ return wave;
93
+ }
94
+
95
+ function resolveLaneForRun(runId, fallbackLane) {
96
+ return (
97
+ readJsonOrNull(path.join(REPO_ROOT, ".wave", "adhoc", "runs", runId, "result.json"))?.lane ||
98
+ fallbackLane
99
+ );
100
+ }
101
+
102
+ function coordinationLogPath(lanePaths, waveNumber) {
103
+ return path.join(lanePaths.coordinationDir, `wave-${waveNumber}.jsonl`);
104
+ }
105
+
106
+ export async function runProofCli(argv) {
107
+ const { help, subcommand, options } = parseArgs(argv);
108
+ if (help || !subcommand) {
109
+ printUsage();
110
+ return;
111
+ }
112
+ if (!["show", "register"].includes(subcommand)) {
113
+ throw new Error("Expected subcommand: show | register");
114
+ }
115
+ if (options.runId) {
116
+ options.lane = resolveLaneForRun(options.runId, options.lane);
117
+ }
118
+ const lanePaths = buildLanePaths(options.lane, {
119
+ adhocRunId: options.runId || null,
120
+ });
121
+ if (options.wave === null && options.runId) {
122
+ options.wave = 0;
123
+ }
124
+ if (options.wave === null) {
125
+ throw new Error("--wave is required");
126
+ }
127
+ const wave = loadWave(lanePaths, options.wave);
128
+ if (subcommand === "show") {
129
+ const registry = readWaveProofRegistry(lanePaths, wave.wave);
130
+ const entries = options.agentId
131
+ ? (registry?.entries || []).filter((entry) => entry.agentId === options.agentId)
132
+ : (registry?.entries || []);
133
+ const payload = {
134
+ lane: lanePaths.lane,
135
+ wave: wave.wave,
136
+ entries,
137
+ };
138
+ console.log(JSON.stringify(payload, null, 2));
139
+ return;
140
+ }
141
+ if (!options.agentId) {
142
+ throw new Error("register requires --agent");
143
+ }
144
+ if (options.artifactPaths.length === 0) {
145
+ throw new Error("register requires at least one --artifact");
146
+ }
147
+ const agent = (wave.agents || []).find((entry) => entry.agentId === options.agentId);
148
+ if (!agent) {
149
+ throw new Error(`Unknown wave agent id: ${options.agentId}`);
150
+ }
151
+ const { entry, registry } = registerWaveProofBundle({
152
+ lanePaths,
153
+ wave,
154
+ agent,
155
+ artifactPaths: options.artifactPaths,
156
+ componentIds: options.components,
157
+ authoritative: options.authoritative,
158
+ satisfyOwnedComponents: options.satisfyOwnedComponents,
159
+ completion: options.completion || null,
160
+ durability: options.durability || null,
161
+ proofLevel: options.proofLevel || null,
162
+ docDeltaState: options.docDeltaState || null,
163
+ detail: options.detail || "",
164
+ recordedBy: options.operator || "human-operator",
165
+ });
166
+ appendCoordinationRecord(coordinationLogPath(lanePaths, wave.wave), {
167
+ id: entry.id,
168
+ lane: lanePaths.lane,
169
+ wave: wave.wave,
170
+ agentId: options.operator || "human-operator",
171
+ kind: "evidence",
172
+ targets: [
173
+ `agent:${agent.agentId}`,
174
+ `agent:${wave.integrationAgentId || lanePaths.integrationAgentId || "A8"}`,
175
+ `agent:${wave.contQaAgentId || lanePaths.contQaAgentId || "A0"}`,
176
+ ],
177
+ priority: options.authoritative ? "high" : "normal",
178
+ artifactRefs: entry.artifacts.map((artifact) => artifact.path),
179
+ summary:
180
+ entry.summary ||
181
+ `${entry.authoritative ? "Authoritative" : "Registered"} proof bundle for ${agent.agentId}`,
182
+ detail:
183
+ entry.detail ||
184
+ `Proof bundle recorded for ${agent.agentId} by ${options.operator || "human-operator"}.`,
185
+ status: "resolved",
186
+ source: "operator",
187
+ });
188
+ const payload = {
189
+ lane: lanePaths.lane,
190
+ wave: wave.wave,
191
+ entry,
192
+ registry,
193
+ };
194
+ console.log(JSON.stringify(payload, null, 2));
195
+ }
@@ -0,0 +1,317 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import {
4
+ readProofRegistry,
5
+ writeProofRegistry,
6
+ } from "./artifact-schemas.mjs";
7
+ import {
8
+ appendWaveControlEvent,
9
+ readWaveControlPlaneState,
10
+ syncWaveControlPlaneProjections,
11
+ } from "./control-plane.mjs";
12
+ import { REPO_ROOT, ensureDirectory, hashText, toIsoTimestamp } from "./shared.mjs";
13
+
14
+ function cloneJson(value) {
15
+ return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
16
+ }
17
+
18
+ function safeArray(values) {
19
+ return Array.isArray(values) ? values : [];
20
+ }
21
+
22
+ function matchingDeclaredProofArtifact(agent, artifactPath) {
23
+ return safeArray(agent?.proofArtifacts).find((artifact) => artifact?.path === artifactPath) || null;
24
+ }
25
+
26
+ function absoluteArtifactPath(repoRelativePath) {
27
+ return path.resolve(REPO_ROOT, String(repoRelativePath || ""));
28
+ }
29
+
30
+ function buildProofArtifactRecord(agent, artifactPath) {
31
+ const declared = matchingDeclaredProofArtifact(agent, artifactPath);
32
+ const absolutePath = absoluteArtifactPath(artifactPath);
33
+ const exists = fs.existsSync(absolutePath);
34
+ return {
35
+ path: artifactPath,
36
+ kind: declared?.kind || null,
37
+ requiredFor: safeArray(declared?.requiredFor),
38
+ exists,
39
+ sha256: exists ? hashText(fs.readFileSync(absolutePath, "utf8")) : null,
40
+ };
41
+ }
42
+
43
+ function normalizeRegisteredComponent(agent, componentInput, detail = null) {
44
+ const normalized = String(componentInput || "").trim();
45
+ if (!normalized) {
46
+ return null;
47
+ }
48
+ const [componentId, explicitLevel = ""] = normalized.split(":", 2);
49
+ const cleanComponentId = String(componentId || "").trim();
50
+ if (!cleanComponentId) {
51
+ return null;
52
+ }
53
+ return {
54
+ componentId: cleanComponentId,
55
+ level: String(explicitLevel || "").trim() || agent?.componentTargets?.[cleanComponentId] || null,
56
+ state: "met",
57
+ detail: String(detail || "").trim() || null,
58
+ };
59
+ }
60
+
61
+ function ensureDeliverableState(agent, summary) {
62
+ const deliverables = safeArray(agent?.deliverables);
63
+ if (deliverables.length === 0) {
64
+ return summary;
65
+ }
66
+ const current = new Map(
67
+ safeArray(summary.deliverables).map((item) => [item.path, item]),
68
+ );
69
+ for (const deliverablePath of deliverables) {
70
+ const existing = current.get(deliverablePath);
71
+ if (existing?.exists === true) {
72
+ continue;
73
+ }
74
+ current.set(deliverablePath, {
75
+ path: deliverablePath,
76
+ exists: fs.existsSync(absoluteArtifactPath(deliverablePath)),
77
+ });
78
+ }
79
+ summary.deliverables = Array.from(current.values());
80
+ return summary;
81
+ }
82
+
83
+ function mergeComponents(summary, components) {
84
+ const current = new Map(
85
+ safeArray(summary.components).map((item) => [item.componentId, item]),
86
+ );
87
+ for (const component of components) {
88
+ if (!component?.componentId) {
89
+ continue;
90
+ }
91
+ const existing = current.get(component.componentId) || {};
92
+ current.set(component.componentId, {
93
+ componentId: component.componentId,
94
+ level: component.level || existing.level || null,
95
+ state: component.state || existing.state || "met",
96
+ detail: component.detail || existing.detail || "",
97
+ });
98
+ }
99
+ summary.components = Array.from(current.values());
100
+ return summary;
101
+ }
102
+
103
+ function mergeProofArtifacts(summary, artifacts) {
104
+ const current = new Map(
105
+ safeArray(summary.proofArtifacts).map((item) => [item.path, item]),
106
+ );
107
+ for (const artifact of artifacts) {
108
+ if (!artifact?.path) {
109
+ continue;
110
+ }
111
+ const existing = current.get(artifact.path) || {};
112
+ current.set(artifact.path, {
113
+ path: artifact.path,
114
+ kind: artifact.kind || existing.kind || null,
115
+ exists: artifact.exists === true || existing.exists === true,
116
+ requiredFor: safeArray(artifact.requiredFor).length > 0
117
+ ? safeArray(artifact.requiredFor)
118
+ : safeArray(existing.requiredFor),
119
+ sha256: artifact.sha256 || existing.sha256 || null,
120
+ });
121
+ }
122
+ summary.proofArtifacts = Array.from(current.values());
123
+ return summary;
124
+ }
125
+
126
+ function latestAuthoritativeEntry(proofRegistry, agentId) {
127
+ return safeArray(proofRegistry?.entries)
128
+ .filter(
129
+ (entry) =>
130
+ entry?.authoritative === true &&
131
+ entry?.agentId === agentId &&
132
+ !["revoked", "superseded"].includes(String(entry?.state || "").trim().toLowerCase()),
133
+ )
134
+ .sort((left, right) => Date.parse(left.recordedAt || "") - Date.parse(right.recordedAt || ""))
135
+ .at(-1) || null;
136
+ }
137
+
138
+ export function waveProofRegistryPath(lanePaths, waveNumber) {
139
+ return path.join(lanePaths.proofDir, `wave-${waveNumber}.json`);
140
+ }
141
+
142
+ export function readWaveProofRegistry(lanePaths, waveNumber) {
143
+ const controlState = readWaveControlPlaneState(lanePaths, waveNumber);
144
+ if (controlState.proofBundles.length === 0) {
145
+ return readProofRegistry(waveProofRegistryPath(lanePaths, waveNumber), {
146
+ lane: lanePaths?.lane || null,
147
+ wave: waveNumber,
148
+ });
149
+ }
150
+ const registry = syncWaveControlPlaneProjections(
151
+ lanePaths,
152
+ waveNumber,
153
+ controlState,
154
+ ).proofRegistry;
155
+ return registry || readProofRegistry(waveProofRegistryPath(lanePaths, waveNumber), {
156
+ lane: lanePaths?.lane || null,
157
+ wave: waveNumber,
158
+ });
159
+ }
160
+
161
+ export function writeWaveProofRegistry(lanePaths, waveNumber, payload) {
162
+ const filePath = waveProofRegistryPath(lanePaths, waveNumber);
163
+ ensureDirectory(path.dirname(filePath));
164
+ return writeProofRegistry(filePath, payload, {
165
+ lane: lanePaths?.lane || null,
166
+ wave: waveNumber,
167
+ });
168
+ }
169
+
170
+ export function registerWaveProofBundle({
171
+ lanePaths,
172
+ wave,
173
+ agent,
174
+ artifactPaths = [],
175
+ componentIds = [],
176
+ authoritative = false,
177
+ satisfyOwnedComponents = false,
178
+ completion = null,
179
+ durability = null,
180
+ proofLevel = null,
181
+ docDeltaState = null,
182
+ detail = "",
183
+ recordedBy = "human-operator",
184
+ }) {
185
+ const recordedAt = toIsoTimestamp();
186
+ const normalizedArtifacts = Array.from(
187
+ new Set(safeArray(artifactPaths).map((value) => String(value || "").trim()).filter(Boolean)),
188
+ ).map((artifactPath) => buildProofArtifactRecord(agent, artifactPath));
189
+ const normalizedComponents = [
190
+ ...safeArray(componentIds).map((componentId) =>
191
+ normalizeRegisteredComponent(agent, componentId, detail),
192
+ ),
193
+ ...(satisfyOwnedComponents
194
+ ? safeArray(agent?.components).map((componentId) =>
195
+ normalizeRegisteredComponent(agent, componentId, detail),
196
+ )
197
+ : []),
198
+ ].filter((component, index, values) =>
199
+ component && values.findIndex((other) => other?.componentId === component.componentId) === index,
200
+ );
201
+ const entry = {
202
+ id: `proof-${agent.agentId}-${recordedAt.replace(/[-:.TZ]/g, "").slice(0, 14)}`,
203
+ agentId: agent.agentId,
204
+ authoritative,
205
+ recordedAt,
206
+ recordedBy,
207
+ detail: String(detail || "").trim() || null,
208
+ summary: authoritative
209
+ ? `Authoritative proof bundle registered for ${agent.agentId}`
210
+ : `Proof bundle registered for ${agent.agentId}`,
211
+ satisfyOwnedComponents,
212
+ proof:
213
+ completion || durability || proofLevel || authoritative
214
+ ? {
215
+ state: "met",
216
+ completion: completion || agent?.exitContract?.completion || null,
217
+ durability: durability || agent?.exitContract?.durability || null,
218
+ proof: proofLevel || agent?.exitContract?.proof || null,
219
+ detail: String(detail || "").trim() || null,
220
+ }
221
+ : null,
222
+ docDelta: docDeltaState
223
+ ? {
224
+ state: docDeltaState,
225
+ detail: String(detail || "").trim() || null,
226
+ }
227
+ : null,
228
+ components: normalizedComponents,
229
+ artifacts: normalizedArtifacts,
230
+ };
231
+ appendWaveControlEvent(lanePaths, wave.wave, {
232
+ entityType: "proof_bundle",
233
+ entityId: entry.id,
234
+ action: "registered",
235
+ source: "operator",
236
+ actor: recordedBy,
237
+ data: {
238
+ proofBundleId: entry.id,
239
+ agentId: entry.agentId,
240
+ state: "active",
241
+ authoritative: entry.authoritative,
242
+ recordedAt: entry.recordedAt,
243
+ recordedBy: entry.recordedBy,
244
+ detail: entry.detail,
245
+ summary: entry.summary,
246
+ satisfyOwnedComponents: entry.satisfyOwnedComponents,
247
+ proof: entry.proof,
248
+ docDelta: entry.docDelta,
249
+ components: entry.components,
250
+ artifacts: entry.artifacts,
251
+ scope: "wave",
252
+ satisfies: normalizedComponents.map((component) => component.componentId),
253
+ },
254
+ });
255
+ const normalized = syncWaveControlPlaneProjections(
256
+ lanePaths,
257
+ wave.wave,
258
+ readWaveControlPlaneState(lanePaths, wave.wave),
259
+ ).proofRegistry;
260
+ return {
261
+ registry: normalized,
262
+ entry: cloneJson(entry),
263
+ };
264
+ }
265
+
266
+ export function augmentSummaryWithProofRegistry(agent, summary, proofRegistry) {
267
+ const authoritativeEntry = latestAuthoritativeEntry(proofRegistry, agent?.agentId);
268
+ if (!authoritativeEntry) {
269
+ return summary;
270
+ }
271
+ const next = cloneJson(summary) || {
272
+ agentId: agent?.agentId || null,
273
+ };
274
+ if (authoritativeEntry.proof?.state === "met") {
275
+ next.proof = {
276
+ completion:
277
+ authoritativeEntry.proof.completion ||
278
+ next.proof?.completion ||
279
+ agent?.exitContract?.completion ||
280
+ null,
281
+ durability:
282
+ authoritativeEntry.proof.durability ||
283
+ next.proof?.durability ||
284
+ agent?.exitContract?.durability ||
285
+ null,
286
+ proof:
287
+ authoritativeEntry.proof.proof ||
288
+ next.proof?.proof ||
289
+ agent?.exitContract?.proof ||
290
+ null,
291
+ state: "met",
292
+ detail:
293
+ authoritativeEntry.proof.detail ||
294
+ next.proof?.detail ||
295
+ "Satisfied by authoritative proof registry.",
296
+ };
297
+ }
298
+ if (authoritativeEntry.docDelta) {
299
+ next.docDelta = cloneJson(authoritativeEntry.docDelta);
300
+ }
301
+ mergeProofArtifacts(next, authoritativeEntry.artifacts);
302
+ if (authoritativeEntry.satisfyOwnedComponents || safeArray(authoritativeEntry.components).length > 0) {
303
+ mergeComponents(
304
+ next,
305
+ safeArray(authoritativeEntry.components).length > 0
306
+ ? authoritativeEntry.components
307
+ : safeArray(agent?.components).map((componentId) => ({
308
+ componentId,
309
+ level: agent?.componentTargets?.[componentId] || null,
310
+ state: "met",
311
+ detail: authoritativeEntry.detail || "",
312
+ })),
313
+ );
314
+ }
315
+ ensureDeliverableState(agent, next);
316
+ return next;
317
+ }
@@ -1,4 +1,5 @@
1
1
  import path from "node:path";
2
+ import { augmentSummaryWithProofRegistry } from "./proof-registry.mjs";
2
3
  import { readJsonOrNull } from "./shared.mjs";
3
4
  import { buildGateSnapshot } from "./launcher.mjs";
4
5
  import {
@@ -59,7 +60,7 @@ function buildReplayLanePaths(metadata) {
59
60
  };
60
61
  }
61
62
 
62
- function buildReplayAgentRuns(dir, wave, metadata) {
63
+ function buildReplayAgentRuns(dir, wave, metadata, proofRegistry = null) {
63
64
  const isHermeticTrace = Number(metadata?.traceVersion) >= 2;
64
65
  return (metadata?.agents || []).map((agentMetadata) => {
65
66
  const waveAgent =
@@ -69,6 +70,11 @@ function buildReplayAgentRuns(dir, wave, metadata) {
69
70
  };
70
71
  const summaryPath = absoluteBundlePath(dir, agentMetadata.summaryPath);
71
72
  const summaryPayload = summaryPath ? readJsonOrNull(summaryPath) : null;
73
+ const augmentedSummary = augmentSummaryWithProofRegistry(
74
+ waveAgent,
75
+ summaryPayload && typeof summaryPayload === "object" ? summaryPayload : null,
76
+ proofRegistry,
77
+ );
72
78
  return {
73
79
  agent: {
74
80
  ...waveAgent,
@@ -86,8 +92,8 @@ function buildReplayAgentRuns(dir, wave, metadata) {
86
92
  statusPath: absoluteBundlePath(dir, agentMetadata.statusPath),
87
93
  summaryPath,
88
94
  summary:
89
- summaryPayload && typeof summaryPayload === "object"
90
- ? summaryPayload
95
+ augmentedSummary
96
+ ? augmentedSummary
91
97
  : !isHermeticTrace
92
98
  ? agentMetadata.summary || null
93
99
  : null,
@@ -174,7 +180,7 @@ export function replayTraceBundle(dir) {
174
180
  };
175
181
  }
176
182
  const lanePaths = buildReplayLanePaths(bundle.metadata);
177
- const agentRuns = buildReplayAgentRuns(dir, wave, bundle.metadata);
183
+ const agentRuns = buildReplayAgentRuns(dir, wave, bundle.metadata, bundle.proofRegistry || null);
178
184
  const derivedState = {
179
185
  coordinationState: bundle.coordinationState,
180
186
  ledger: bundle.ledger,