@chllming/wave-orchestration 0.8.9 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +135 -18
  3. package/docs/README.md +9 -3
  4. package/docs/architecture/README.md +1498 -0
  5. package/docs/concepts/context7-vs-skills.md +1 -1
  6. package/docs/concepts/operating-modes.md +3 -3
  7. package/docs/concepts/what-is-a-wave.md +1 -1
  8. package/docs/guides/author-and-run-waves.md +27 -4
  9. package/docs/guides/monorepo-projects.md +226 -0
  10. package/docs/guides/planner.md +10 -3
  11. package/docs/guides/{recommendations-0.8.9.md → recommendations-0.9.1.md} +8 -7
  12. package/docs/guides/sandboxed-environments.md +158 -0
  13. package/docs/guides/terminal-surfaces.md +14 -12
  14. package/docs/plans/current-state.md +11 -7
  15. package/docs/plans/end-state-architecture.md +3 -1
  16. package/docs/plans/examples/wave-example-design-handoff.md +3 -1
  17. package/docs/plans/examples/wave-example-live-proof.md +6 -1
  18. package/docs/plans/examples/wave-example-rollout-fidelity.md +2 -0
  19. package/docs/plans/migration.md +48 -18
  20. package/docs/plans/sandbox-end-state-architecture.md +153 -0
  21. package/docs/plans/wave-orchestrator.md +4 -4
  22. package/docs/reference/cli-reference.md +125 -57
  23. package/docs/reference/coordination-and-closure.md +1 -1
  24. package/docs/reference/github-packages-setup.md +1 -1
  25. package/docs/reference/migration-0.2-to-0.5.md +9 -7
  26. package/docs/reference/npmjs-token-publishing.md +53 -0
  27. package/docs/reference/npmjs-trusted-publishing.md +4 -50
  28. package/docs/reference/package-publishing-flow.md +272 -0
  29. package/docs/reference/runtime-config/README.md +140 -12
  30. package/docs/reference/sample-waves.md +100 -5
  31. package/docs/reference/skills.md +1 -1
  32. package/docs/reference/wave-control.md +23 -5
  33. package/docs/roadmap.md +43 -201
  34. package/package.json +1 -1
  35. package/releases/manifest.json +38 -0
  36. package/scripts/wave-orchestrator/adhoc.mjs +49 -17
  37. package/scripts/wave-orchestrator/agent-process-runner.mjs +344 -0
  38. package/scripts/wave-orchestrator/agent-state.mjs +0 -1
  39. package/scripts/wave-orchestrator/artifact-schemas.mjs +7 -0
  40. package/scripts/wave-orchestrator/autonomous.mjs +96 -29
  41. package/scripts/wave-orchestrator/benchmark-external.mjs +23 -7
  42. package/scripts/wave-orchestrator/benchmark.mjs +33 -10
  43. package/scripts/wave-orchestrator/closure-engine.mjs +138 -17
  44. package/scripts/wave-orchestrator/config.mjs +239 -24
  45. package/scripts/wave-orchestrator/control-cli.mjs +71 -28
  46. package/scripts/wave-orchestrator/coord-cli.mjs +22 -14
  47. package/scripts/wave-orchestrator/coordination-store.mjs +8 -0
  48. package/scripts/wave-orchestrator/dashboard-renderer.mjs +123 -44
  49. package/scripts/wave-orchestrator/dep-cli.mjs +47 -21
  50. package/scripts/wave-orchestrator/derived-state-engine.mjs +6 -3
  51. package/scripts/wave-orchestrator/feedback.mjs +28 -11
  52. package/scripts/wave-orchestrator/gate-engine.mjs +106 -38
  53. package/scripts/wave-orchestrator/human-input-resolution.mjs +5 -1
  54. package/scripts/wave-orchestrator/install.mjs +13 -0
  55. package/scripts/wave-orchestrator/launcher-progress.mjs +91 -0
  56. package/scripts/wave-orchestrator/launcher-runtime.mjs +179 -68
  57. package/scripts/wave-orchestrator/launcher.mjs +222 -53
  58. package/scripts/wave-orchestrator/ledger.mjs +7 -2
  59. package/scripts/wave-orchestrator/planner.mjs +48 -27
  60. package/scripts/wave-orchestrator/project-profile.mjs +31 -8
  61. package/scripts/wave-orchestrator/projection-writer.mjs +13 -1
  62. package/scripts/wave-orchestrator/proof-cli.mjs +18 -12
  63. package/scripts/wave-orchestrator/reducer-snapshot.mjs +6 -0
  64. package/scripts/wave-orchestrator/retry-cli.mjs +19 -13
  65. package/scripts/wave-orchestrator/retry-control.mjs +3 -3
  66. package/scripts/wave-orchestrator/retry-engine.mjs +93 -6
  67. package/scripts/wave-orchestrator/role-helpers.mjs +30 -0
  68. package/scripts/wave-orchestrator/session-supervisor.mjs +94 -85
  69. package/scripts/wave-orchestrator/shared.mjs +77 -14
  70. package/scripts/wave-orchestrator/supervisor-cli.mjs +1306 -0
  71. package/scripts/wave-orchestrator/terminals.mjs +12 -32
  72. package/scripts/wave-orchestrator/tmux-adapter.mjs +300 -0
  73. package/scripts/wave-orchestrator/wave-control-client.mjs +84 -16
  74. package/scripts/wave-orchestrator/wave-files.mjs +43 -6
  75. package/scripts/wave.mjs +13 -0
@@ -0,0 +1,1498 @@
1
+ # Wave Orchestration Architecture
2
+
3
+ This document is a detailed, ground-truth architecture reference for Wave Orchestration.
4
+ It is derived from reading every source module, test file, configuration surface, and design document in the repository.
5
+
6
+ ## Table of Contents
7
+
8
+ 1. [Project Purpose and Design Philosophy](#1-project-purpose-and-design-philosophy)
9
+ 2. [System Overview](#2-system-overview)
10
+ 3. [Canonical Authority Model](#3-canonical-authority-model)
11
+ 4. [Module Architecture](#4-module-architecture)
12
+ 5. [Wave Execution Lifecycle](#5-wave-execution-lifecycle)
13
+ 6. [Coordination and Blackboard Model](#6-coordination-and-blackboard-model)
14
+ 7. [Gate Evaluation and Proof Model](#7-gate-evaluation-and-proof-model)
15
+ 8. [Closure Sweep: How Waves Actually Close](#8-closure-sweep-how-waves-actually-close)
16
+ 9. [Retry and Recovery](#9-retry-and-recovery)
17
+ 10. [Run-State Reconciler](#10-run-state-reconciler)
18
+ 11. [Sandbox Supervisor Model](#11-sandbox-supervisor-model)
19
+ 12. [Runtime Abstraction and Executor Adapters](#12-runtime-abstraction-and-executor-adapters)
20
+ 13. [Skills, Context7, and Compiled Context](#13-skills-context7-and-compiled-context)
21
+ 14. [Entity Model](#14-entity-model)
22
+ 15. [Artifact Hierarchy](#15-artifact-hierarchy)
23
+ 16. [Telemetry and Wave Control](#16-telemetry-and-wave-control)
24
+ 17. [CLI Surface Map](#17-cli-surface-map)
25
+ 18. [Research Grounding](#18-research-grounding)
26
+
27
+ ---
28
+
29
+ ## 1. Project Purpose and Design Philosophy
30
+
31
+ ### What Wave Is
32
+
33
+ Wave Orchestration is a framework for structured, multi-agent repository work. It replaces ad-hoc "vibe coding" sessions with a system where planning, coordination, evidence, proof, and closure are all explicit and machine-inspectable. The core thesis is that agentic coding is fast but fragile: agents hallucinate completion, coordination collapses at scale, and there is no trustworthy record of what actually happened. Wave makes all of those failure modes visible and addressable.
34
+
35
+ Wave is the orchestration substrate for **LEAP-claw**, the proprietary agent framework built on top of Wave's coordination, proof, and closure model. LEAP-claw agents operate through Wave's runtime abstraction, using Wave's canonical authority set, blackboard coordination, and proof-bounded closure while adding proprietary planning, reasoning, and execution strategies. Wave provides the runtime and coordination guarantees; LEAP-claw provides the agent intelligence.
36
+
37
+ The framework is **not** a chat wrapper or a prompt library. It is a runtime orchestrator that:
38
+
39
+ - Parses structured wave definitions from markdown
40
+ - Launches multiple coding agents in parallel across different LLM runtimes (Codex, Claude, OpenCode, LEAP-claw)
41
+ - Coordinates them through shared canonical state (not chat messages)
42
+ - Evaluates structured proof of completion through a multi-stage gate stack
43
+ - Closes waves only when all declared goals, proof artifacts, and closure stewards agree
44
+
45
+ ### Design Principles
46
+
47
+ 1. **Canonical authority set, not a single event log.** Three append-only sources of truth (wave definitions, coordination log, control-plane log) replace a single monolithic state store. Each is authoritative over a different domain.
48
+
49
+ 2. **Phase engines replace a monolithic launcher.** Each concern (implementation selection, state derivation, gate evaluation, retry planning, closure sequencing) is a separate module with explicit inputs and outputs. The launcher is a thin orchestrator that wires them together.
50
+
51
+ 3. **Planning engines emit intent; the supervisor emits facts.** The implementation engine says "launch agent A1"; the session supervisor records that A1 actually started at time T. This separation is critical for replay.
52
+
53
+ 4. **Proof and closure are separate states.** An agent's owned slice can be proven (`owned_slice_proven`) without the wave being closure-ready (`wave_closure_ready`). Closure requires all cross-cutting conditions to also pass.
54
+
55
+ 5. **Tasks are first-class entities.** Work units have ownership, leases, artifact contracts, dependency edges, and explicit closure state machines, not just "agent finished" flags.
56
+
57
+ 6. **Retry is a dedicated deterministic subsystem.** Retry decisions are computed from stored state by pure functions, testable without launching any processes.
58
+
59
+ 7. **Structured result envelopes replace log parsing.** Agents write typed JSON envelopes with a common header and role-specific payloads. Gates read envelopes, not log text.
60
+
61
+ 8. **One strict artifact hierarchy.** Every artifact is classified as canonical event, structured snapshot, derived cache, or human-facing projection. Decision logic never reads projections.
62
+
63
+ 9. **Replay is first-class.** A single reducer path (`wave-state-reducer.mjs`) rebuilds full wave state from the canonical authority set. Traces bundle everything needed for offline replay.
64
+
65
+ 10. **The system stays opinionated about repo work.** Wave is a bounded-wave coding orchestrator with closure discipline, not a general-purpose agent framework.
66
+
67
+ ### What Problem It Solves
68
+
69
+ Multi-agent coding systems fail in predictable ways documented in recent research (see [Section 18](#18-research-grounding)). Wave targets each failure mode with a specific architectural mechanism:
70
+
71
+ | Failure Mode | Wave Mechanism |
72
+ |---|---|
73
+ | Cosmetic board, no canonical state | Append-only JSONL authority set; board is a projection |
74
+ | Hidden evidence never pooled | Shared summaries, per-agent inboxes, integration gate |
75
+ | No global-state reconstruction | Reducer rebuilds full state from canonical sources |
76
+ | Simultaneous coordination collapse | Helper assignments, dependency barriers, explicit blocking |
77
+ | Expert signal averaged away | Named stewards, capability routing, proof gates |
78
+ | Contradictions smoothed over | Contradiction entities, clarification triage, repair tracking |
79
+ | Premature closure | Multi-stage gate stack, structured proof markers, closure stewards |
80
+
81
+ ---
82
+
83
+ ## 2. System Overview
84
+
85
+ ### High-Level Architecture
86
+
87
+ ```
88
+ +--------------------------+
89
+ | wave.mjs (CLI) |
90
+ | Subcommand router |
91
+ +----------+---------------+
92
+ |
93
+ +---------------------------+---------------------------+
94
+ | | |
95
+ +-----------+ +----------------+ +--------------+
96
+ | install | | launcher.mjs | | autonomous |
97
+ | planner | | (Thin orch.) | | (Multi-wave |
98
+ | doctor | | | | barrier) |
99
+ | draft | +-------+--------+ +--------------+
100
+ | adhoc | |
101
+ +-----------+ |
102
+ +---------------+---------------+
103
+ | | |
104
+ +------+------+ +-----+------+ +------+------+
105
+ | Impl Engine | | Derived | | Gate Engine |
106
+ | (run select)| | State Eng. | | (evaluate) |
107
+ +-------------+ +------------+ +--------------+
108
+ | | |
109
+ +------+------+ +-----+------+ +------+------+
110
+ | Retry Engine| | Closure | | Wave State |
111
+ | (plan retry)| | Engine | | Reducer |
112
+ +-------------+ +------------+ +--------------+
113
+ |
114
+ +---------------+---------------+
115
+ | |
116
+ +------+------+ +-------+-------+
117
+ | Session | | Projection |
118
+ | Supervisor | | Writer |
119
+ | (launch, | | (dashboards, |
120
+ | wait, tmux)| | traces, etc) |
121
+ +-------------+ +---------------+
122
+ ```
123
+
124
+ ### Four-Layer Model
125
+
126
+ **Layer 1 -- Canonical State** (append-only, never rewritten)
127
+ - `control-plane.mjs`: Lifecycle events (wave runs, agent runs, attempts, proof bundles, gates, contradictions, facts, human inputs)
128
+ - `coordination-store.mjs`: Workflow events (requests, acks, claims, evidence, decisions, blockers, handoffs, clarifications, escalations)
129
+ - `wave-files.mjs`: Parsed wave definitions from `docs/plans/waves/wave-<N>.md` (read-only)
130
+
131
+ **Layer 2 -- Phase Engines** (pure functions reading canonical state, emitting decisions)
132
+ - `implementation-engine.mjs`: Selects which agents to launch (initial, retry, override, persisted relaunch)
133
+ - `derived-state-engine.mjs`: Computes shared summaries, inboxes, assignments, ledger, docs queue, security and integration summaries
134
+ - `gate-engine.mjs`: Evaluates all closure gates and returns verdicts
135
+ - `closure-engine.mjs`: Sequences the staged closure sweep
136
+ - `retry-engine.mjs`: Plans retry targets, reusable work, executor fallbacks
137
+ - `wave-state-reducer.mjs`: Rebuilds full deterministic wave state from canonical sources
138
+
139
+ **Layer 3 -- Supervisor and Projection Writer** (side effects)
140
+ - `session-supervisor.mjs`: Launches processes, manages tmux sessions, writes observed lifecycle events (`agent_run.started`, `agent_run.completed`)
141
+ - `projection-writer.mjs`: Persists all human-facing projections (dashboards, traces, boards, summaries, inboxes, ledgers)
142
+ - `signals.mjs`: Writes versioned signal-state projections for long-running agents
143
+
144
+ **Layer 4 -- Launcher Orchestrator** (thin wiring)
145
+ - `launcher.mjs`: Parses args, acquires lock, iterates waves, calls engines in correct order, delegates all decisions
146
+
147
+ ---
148
+
149
+ ## 3. Canonical Authority Model
150
+
151
+ The system's source of truth is split across three canonical sources. Everything else is a derived projection.
152
+
153
+ ### Authority Set
154
+
155
+ | Source | Storage | Authority Over |
156
+ |--------|---------|----------------|
157
+ | Wave definitions | Markdown files parsed at startup | Goals, agent roles, deliverables, exit contracts, proof artifacts, eval targets, component promotions, skills |
158
+ | Control-plane event log | Append-only JSONL per wave | Entity lifecycle: `wave_run`, `agent_run`, `attempt`, `proof_bundle`, `rerun_request`, `human_input`, `gate`, `contradiction`, `fact`, `artifact`, `benchmark_run`, `verification`, `review` |
159
+ | Coordination log | Append-only JSONL per wave | Workflow state: `request`, `ack`, `claim`, `evidence`, `decision`, `blocker`, `handoff`, `clarification-request`, `orchestrator-guidance`, `human-escalation`, `human-feedback`, `integration-summary` |
160
+
161
+ ### Key Invariants
162
+
163
+ - Canonical logs are append-only. Events are never rewritten or deleted.
164
+ - The wave-state reducer can rebuild full wave state from these three sources alone.
165
+ - Result envelopes are immutable per attempt. A new attempt creates new envelopes; old ones are preserved.
166
+ - Projections (dashboards, boards, summaries, inboxes) are derived from canonical state and are safe to regenerate.
167
+ - **Decision logic never reads projections.** Gates, retry planning, and closure read canonical state and structured envelopes.
168
+
169
+ ### Derived Projections
170
+
171
+ | Projection | Source | Purpose |
172
+ |---|---|---|
173
+ | Rolling message board | Coordination log + assignments + dependencies | Human-facing coordination view |
174
+ | Shared summary | Coordination log + execution summaries | Cross-agent awareness |
175
+ | Per-agent inboxes | Coordination log filtered by agent | Targeted awareness |
176
+ | Assignment snapshots | Coordination log + capability routing | Helper assignment tracking |
177
+ | Dependency snapshots | Cross-lane dependency tickets | Blocking dependency view |
178
+ | Wave ledger | Coordination log + feedback + assignments | Audit trail per wave |
179
+ | Docs queue | Execution summaries + doc-delta claims | Documentation closure input |
180
+ | Integration summary | Execution summaries + integration markers | Integration gate input |
181
+ | Security summary | Security review reports | Security gate input |
182
+ | Dashboard JSON | All of the above + agent status | Operator monitoring |
183
+ | Trace bundles | All canonical + derived state per attempt | Replay and audit |
184
+
185
+ ---
186
+
187
+ ## 4. Module Architecture
188
+
189
+ ### Core Modules (71 `.mjs` files in `scripts/wave-orchestrator/`)
190
+
191
+ #### Entry Point and Configuration
192
+
193
+ | Module | Size | Role |
194
+ |--------|------|------|
195
+ | `wave.mjs` | CLI router | Dispatches subcommands to dedicated modules |
196
+ | `config.mjs` | 47KB | Loads and normalizes `wave.config.json`, executor profiles, lane policies, skill routing |
197
+ | `shared.mjs` | 19KB | Constants (paths, defaults, regexes), utility functions (timestamps, file I/O, argument parsing) |
198
+ | `roots.mjs` | 375B | Resolves `PACKAGE_ROOT` and `WORKSPACE_ROOT` |
199
+
200
+ #### Canonical State Modules
201
+
202
+ | Module | Size | Role |
203
+ |--------|------|------|
204
+ | `wave-files.mjs` | 117KB | Parses wave markdown into structured definitions; validates waves; builds manifests; reconciles run state |
205
+ | `coordination-store.mjs` | 49KB | Reads/writes coordination JSONL; materializes coordination state; compiles shared summaries and inboxes |
206
+ | `control-plane.mjs` | 25KB | Reads/writes control-plane JSONL; builds task snapshots; manages proof bundles, rerun requests, human-input workflow |
207
+ | `coordination.mjs` | 43KB | Builds execution prompts; manages orchestrator boards; human feedback request reading |
208
+
209
+ #### Phase Engine Modules
210
+
211
+ | Module | Size | Role |
212
+ |--------|------|------|
213
+ | `implementation-engine.mjs` | 3KB | `planInitialWaveAttempt()` and `planRetryWaveAttempt()` -- selects which agent runs to launch |
214
+ | `derived-state-engine.mjs` | 27KB | `buildWaveDerivedState()` -- computes all blackboard projections from canonical sources |
215
+ | `gate-engine.mjs` | 56KB | Evaluates implementation, component, assignment, dependency, clarification, cont-eval, security, integration, documentation, and cont-QA gates |
216
+ | `closure-engine.mjs` | 17KB | `runClosureSweepPhase()` and `planClosureStages()` -- orchestrates the staged closure sequence |
217
+ | `retry-engine.mjs` | 40KB | Plans retry targets, identifies reusable work, computes executor fallback chains, generates persisted relaunch plans |
218
+ | `wave-state-reducer.mjs` | 26KB | `rebuildWaveState()` -- deterministic state reconstruction from canonical authority set for live queries and replay |
219
+
220
+ #### Session and Output Modules
221
+
222
+ | Module | Size | Role |
223
+ |--------|------|------|
224
+ | `session-supervisor.mjs` | 28KB | Process lifecycle: launches detached agent runners, waits for completion, manages locks, records `agent_run.started` / `agent_run.completed` events |
225
+ | `launcher-runtime.mjs` | 14KB | Builds agent launch specs: resolves skills, builds execution prompts, handles Context7 prefetch, manages rate-limit retries |
226
+ | `projection-writer.mjs` | 10KB | Single persistence layer for all projections: dashboards, traces, summaries, inboxes, boards, ledgers, docs queues |
227
+ | `traces.mjs` | 45KB | Builds hermetic trace bundles per attempt with quality metrics |
228
+
229
+ #### Agent and Task Modules
230
+
231
+ | Module | Size | Role |
232
+ |--------|------|------|
233
+ | `agent-state.mjs` | 43KB | Builds and validates agent execution summaries for all roles (implementation, cont-QA, cont-eval, integration, documentation, security, design) |
234
+ | `task-entity.mjs` | 31KB | Task entity model with ownership, leases, artifact contracts, dependency edges, closure state machines |
235
+ | `result-envelope.mjs` | 19KB | Builds immutable attempt-scoped result envelopes with common header and role-specific payloads |
236
+ | `contradiction-entity.mjs` | 13KB | Materializes contradictions from control-plane events; tracks repair work |
237
+
238
+ #### Executor and Skills
239
+
240
+ | Module | Size | Role |
241
+ |--------|------|------|
242
+ | `executors.mjs` | 15KB | Builds executor-specific launch commands for Codex, Claude, OpenCode, and Local |
243
+ | `skills.mjs` | 33KB | Skill loading, resolution by role/runtime/deploy-kind, artifact generation |
244
+ | `context7.mjs` | 14KB | Context7 bundle integration, prefetch, library resolution, prompt fingerprinting |
245
+
246
+ #### Coordination and Human Input
247
+
248
+ | Module | Size | Role |
249
+ |--------|------|------|
250
+ | `clarification-triage.mjs` | 21KB | Orchestrator-first triage of clarification requests from repo policy, ownership, prior decisions |
251
+ | `human-input-workflow.mjs` | 13KB | Human feedback request lifecycle management |
252
+ | `human-input-resolution.mjs` | 11KB | Resolution of human input requests back into coordination state |
253
+ | `routing-state.mjs` | builds | Deterministic helper assignment from capability routing, explicit targets, least-busy fallback |
254
+
255
+ #### Specialized Features
256
+
257
+ | Module | Size | Role |
258
+ |--------|------|------|
259
+ | `autonomous.mjs` | 16KB | Multi-wave autonomous execution with inter-wave barriers, dependency checks, external attempt limits |
260
+ | `planner.mjs` | 131KB | Agentic wave planning, draft generation, component maturity tracking, exit contract authoring |
261
+ | `adhoc.mjs` | 46KB | Ad-hoc transient runs on the same runtime surface |
262
+ | `benchmark.mjs` | 34KB | Benchmark running and result tracking |
263
+ | `swe-bench-pro-task.mjs` | 31KB | SWE-Bench Pro task orchestration |
264
+ | `install.mjs` | 31KB | Workspace initialization, upgrades, adoption, `wave doctor` validation |
265
+
266
+ ---
267
+
268
+ ## 5. Wave Execution Lifecycle
269
+
270
+ ### Phase 1: Startup
271
+
272
+ ```
273
+ CLI invocation
274
+ -> parseArgs() -- resolve lane, project, wave range, executor, options
275
+ -> acquireLauncherLock() -- prevent concurrent launchers on same lane
276
+ -> parseWaveFiles() -- parse all wave-<N>.md into structured definitions
277
+ -> applyExecutorSelectionsToWave() -- resolve per-agent executor from lane policy
278
+ -> applyContext7SelectionsToWave() -- resolve Context7 library selections
279
+ -> validateWaveDefinition() -- validate agents, deliverables, exit contracts
280
+ -> buildManifest() -- build manifest of all docs and waves
281
+ -> writeManifest() -- persist manifest JSON
282
+ ```
283
+
284
+ ### Phase 2: Per-Wave Loop
285
+
286
+ For each wave in the selected range:
287
+
288
+ ```
289
+ 1. buildWaveDerivedState()
290
+ Computes shared summary, inboxes, message board, assignments, dependencies,
291
+ ledger, docs queue, security summary, integration summary from canonical state.
292
+
293
+ 2. writeWaveDerivedProjections()
294
+ Persists all derived state to disk.
295
+
296
+ 3. resetPersistedWaveLaunchState()
297
+ Clears stale relaunch plans unless --resume-control-state is set.
298
+
299
+ 4. planInitialWaveAttempt()
300
+ Selects which agents to launch:
301
+ a. Check for reusable pre-completed agents (proven work from prior attempts)
302
+ b. Check for operator retry overrides
303
+ c. Check for persisted relaunch plans (from prior launcher crash)
304
+ d. Fall back to selectInitialWaveRuns() -- all non-pre-completed agents
305
+
306
+ 5. For design-first waves: launch design agents first, wait for design gate,
307
+ then transition to implementation agents.
308
+
309
+ 6. For each selected agent run:
310
+ a. launchAgentSession() -- build prompt, resolve skills, create tmux session
311
+ b. recordAgentRunStarted() -- supervisor writes control-plane event
312
+
313
+ 7. waitForWaveCompletion()
314
+ Polling loop watching status files, with periodic:
315
+ - refreshDerivedState() -- recompute blackboard projections
316
+ - monitorWaveHumanFeedback() -- reconcile answered feedback
317
+ - syncLiveWaveSignals() -- update signal projections
318
+ - emitCoordinationAlertEvents() -- flag overdue acks and stale clarifications
319
+ - recordAgentRunFinished() -- supervisor writes completion events
320
+
321
+ 8. materializeAgentExecutionSummaries()
322
+ Build structured summaries from agent output for gate evaluation.
323
+
324
+ 9. buildGateSnapshot()
325
+ Evaluate all gates: implementation, component, assignment, dependency,
326
+ clarification, design, cont-eval, security, integration, docs, cont-QA.
327
+
328
+ 10. If implementation gate passes and closure agents declared:
329
+ runClosureSweepPhase() -- staged closure (see Section 8)
330
+
331
+ 11. If any gate fails and retries remain:
332
+ planRetryWaveAttempt() -- select agents to relaunch (see Section 9)
333
+ Go to step 6.
334
+
335
+ 12. On wave completion:
336
+ markWaveCompleted() -- update run-state
337
+ writeWaveAttemptTraceProjection() -- persist trace bundle
338
+ computeReducerSnapshot() -- persist reducer state for replay
339
+ flushWaveControlTelemetry() -- deliver telemetry events
340
+ ```
341
+
342
+ ### Phase 3: Cleanup
343
+
344
+ ```
345
+ -> cleanupLaneTmuxSessions() -- kill tmux sessions (unless --keep-sessions)
346
+ -> removeLaneTemporaryTerminalEntries() -- clean terminal registry
347
+ -> releaseLauncherLock() -- release lock for other launchers
348
+ ```
349
+
350
+ ### Autonomous Mode
351
+
352
+ `wave autonomous` adds an outer loop around the per-wave launcher:
353
+
354
+ ```
355
+ for each wave in lane order:
356
+ 1. Check cross-lane dependency barriers
357
+ 2. Check run-state for already-completed waves
358
+ 3. Spawn `wave launch --start-wave N --end-wave N` as subprocess
359
+ 4. If wave fails after max external attempts, stop
360
+ 5. Continue to next wave
361
+ ```
362
+
363
+ Autonomous mode disables `--terminal-surface none` and requires a real executor (not `local`).
364
+
365
+ ---
366
+
367
+ ## 6. Coordination and Blackboard Model
368
+
369
+ ### Why a Blackboard
370
+
371
+ Traditional multi-agent systems fail when agents treat chat output as system of record. Evidence gets lost, contradictions are smoothed over, and there is no way to reconstruct what the system actually knew at any point. Wave uses a blackboard-style architecture where agents work against shared canonical state.
372
+
373
+ ### How It Works
374
+
375
+ 1. **Agents write to canonical logs, not to each other.** An implementation agent posts a `claim`, `evidence`, `blocker`, or `clarification-request` to the coordination log.
376
+
377
+ 2. **The derived-state engine compiles shared awareness.** After any state change, `buildWaveDerivedState()` recomputes:
378
+ - Shared summary: aggregated coordination state visible to all agents
379
+ - Per-agent inboxes: filtered view of state relevant to a specific agent
380
+ - Message board: human-readable markdown projection
381
+ - Assignment snapshot: who owns what capability-targeted requests
382
+ - Dependency snapshot: cross-lane blocking state
383
+
384
+ 3. **Agents receive compiled context, not raw logs.** When an agent is launched or re-contextualized, it receives the shared summary and its inbox, not a dump of raw log lines.
385
+
386
+ 4. **The orchestrator triages clarifications.** When an agent posts a `clarification-request`, the `clarification-triage.mjs` module resolves it from repo policy, ownership, and prior decisions before escalating to human feedback.
387
+
388
+ 5. **Human input flows through the control plane.** Human feedback requests are tracked as `human_input` entities with explicit lifecycle states (`pending -> assigned -> answered|escalated|resolved|timed_out|rerouted`).
389
+
390
+ ### Coordination Record Types
391
+
392
+ | Kind | Purpose |
393
+ |------|---------|
394
+ | `request` | Agent asks for something from another agent or the orchestrator |
395
+ | `ack` | Agent acknowledges a request |
396
+ | `claim` | Agent claims a deliverable is complete |
397
+ | `evidence` | Agent provides supporting evidence for a claim |
398
+ | `decision` | Orchestrator or agent records a decision |
399
+ | `blocker` | Something is blocking progress |
400
+ | `handoff` | Work is transferred between agents |
401
+ | `clarification-request` | Agent needs clarification before proceeding |
402
+ | `orchestrator-guidance` | Orchestrator provides direction |
403
+ | `human-escalation` | Issue escalated to human operator |
404
+ | `human-feedback` | Human provides feedback |
405
+ | `integration-summary` | Cross-agent integration state |
406
+
407
+ ### Blocking Semantics
408
+
409
+ Coordination records have explicit blocking behavior:
410
+
411
+ - **Hard blockers** (`hard`, `proof-critical`, `closure-critical`): Block wave progression
412
+ - **Soft blockers** (`soft`): Visible but non-blocking
413
+ - **Stale/Advisory** (`stale`, `advisory`): Informational only
414
+
415
+ Operators can downgrade blockers via `wave control task` commands: `defer`, `mark-advisory`, `mark-stale`, `resolve-policy`.
416
+
417
+ ### Helper Assignments
418
+
419
+ When an agent posts a capability-targeted request, the routing engine assigns it:
420
+
421
+ 1. Check explicit targets in the request
422
+ 2. Check `capabilityRouting.preferredAgents` in config
423
+ 3. Match capability owners with demonstrated same-wave completions
424
+ 4. Fall back to least-busy agent
425
+
426
+ Assignments remain blocking until the linked follow-up resolves or is explicitly downgraded.
427
+
428
+ ---
429
+
430
+ ## 7. Gate Evaluation and Proof Model
431
+
432
+ ### Two-Phase Proof
433
+
434
+ Wave separates individual agent proof from wave-level closure:
435
+
436
+ **Phase 1: `owned_slice_proven`** (per-agent)
437
+
438
+ An agent's owned slice is proven when:
439
+ - All declared deliverables exist on disk
440
+ - Proof markers meet or exceed the exit contract
441
+ - Proof artifacts (if declared) are present with valid SHA256
442
+ - Doc-delta is declared if required
443
+ - Component promotions meet target maturity
444
+ - No open self-owned blockers
445
+
446
+ **Phase 2: `wave_closure_ready`** (cross-cutting)
447
+
448
+ All owned slices are proven AND:
449
+ - No unresolved contradictions
450
+ - No open clarification barriers
451
+ - No open helper assignment barriers
452
+ - No open cross-lane dependency barriers
453
+ - Integration gate passed
454
+ - Documentation gate passed
455
+ - cont-EVAL gate passed (if applicable)
456
+ - Security review gate passed (if applicable)
457
+ - cont-QA final verdict is PASS
458
+ - Component matrix promotions validated
459
+
460
+ Only when `wave_closure_ready = true` does the system emit a `wave_run.completed` event.
461
+
462
+ ### Gate Stack
463
+
464
+ The `gate-engine.mjs` evaluates gates in this order:
465
+
466
+ | Gate | Evaluates | Required |
467
+ |------|-----------|----------|
468
+ | Implementation | All agent exit codes and execution summaries | Always |
469
+ | Component | Per-component maturity promotions | When declared |
470
+ | Design | Design packets are `ready-for-implementation` | When design agents present |
471
+ | Assignment | All helper assignments resolved | When assignments exist |
472
+ | Dependency | Cross-lane dependency tickets resolved | When dependencies exist |
473
+ | Clarification | All clarification barriers cleared | When clarifications exist |
474
+ | cont-EVAL | Eval report artifact + `[wave-eval]` marker + exact target_ids | When E0 declared |
475
+ | Security | Security report + `[wave-security]` marker | When security agent declared |
476
+ | Integration | Integration evidence aggregation | Always |
477
+ | Documentation | Doc closure state | Always |
478
+ | Component Matrix | Cross-agent component validation | When components declared |
479
+ | cont-QA | Final verdict + `[wave-gate]` marker | Always |
480
+
481
+ ### Result Envelopes
482
+
483
+ Agents produce structured JSON envelopes (not free-form text). Each envelope has:
484
+
485
+ **Common header (all roles):**
486
+ ```
487
+ schemaVersion, agentId, waveNumber, attempt, completedAt, exitCode,
488
+ role, proof{}, deliverables[], proofArtifacts[], gaps[],
489
+ unresolvedBlockers[], riskNotes[], facts[]
490
+ ```
491
+
492
+ **Role-specific payloads:**
493
+ - `implementation`: docDelta, components[]
494
+ - `integration`: state (clean|claims_pending|conflicts_detected|blocked), counts
495
+ - `documentation`: docClosure state, paths
496
+ - `cont-qa`: verdict, gateClaims (architecture/integration/durability/live/docs)
497
+ - `cont-eval`: state, targets, benchmarks, regressions
498
+ - `security`: state (clean|findings|blocked), findings/approvals counts
499
+ - `deploy`: state, environment, healthCheck
500
+
501
+ Envelope path: `.tmp/<lane>-wave-launcher/results/wave-<N>/attempt-<A>/<agentId>.json`
502
+
503
+ ---
504
+
505
+ ## 8. Closure Sweep: How Waves Actually Close
506
+
507
+ ### The Core Problem
508
+
509
+ Agents say "done" before the work is actually done. This is the single most common failure mode in multi-agent coding systems. An agent can produce plausible-looking output, claim PASS, and move on -- but the deliverables don't exist, the tests don't run, the integration breaks, or the proof is narrative rather than structural. Wave's closure model exists to make premature closure impossible.
510
+
511
+ ### Closure Is Not "Agent Finished"
512
+
513
+ A wave does not close when agents finish running. A wave closes when:
514
+
515
+ 1. Every agent's **owned slice is structurally proven** (deliverables exist, proof markers valid, SHA256 checks pass)
516
+ 2. Every **cross-cutting concern** is clear (no open blockers, clarifications, dependencies, contradictions)
517
+ 3. A **staged sweep of closure stewards** has validated the integrated result
518
+ 4. The **final cont-QA verdict** is PASS based on structural evidence, not agent self-report
519
+
520
+ This is enforced by the `closure-engine.mjs` module. The launcher cannot bypass closure; the gate stack is fail-closed.
521
+
522
+ ### How the Closure Sweep Executes
523
+
524
+ The sweep is sequential and staged. Each stage launches a closure agent, waits for it to complete, evaluates the gate, and only proceeds to the next stage if the gate passes. This is implemented in `runClosureSweepPhase()`.
525
+
526
+ ```
527
+ ┌─────────────────────────────────────────────────────────────────────┐
528
+ │ IMPLEMENTATION PHASE (parallel) │
529
+ │ A1, A2, A3... run concurrently │
530
+ │ Each writes: status file, execution summary, result envelope │
531
+ │ Gate: readWaveImplementationGate() checks all exit codes + summaries│
532
+ │ If any fail → retry (Section 9), do not enter closure │
533
+ └──────────────────────────┬──────────────────────────────────────────┘
534
+ │ all agents exit 0 + valid summaries
535
+
536
+ ┌─────────────────────────────────────────────────────────────────────┐
537
+ │ STAGE 1: cont-EVAL (optional — only if E0 declared in wave) │
538
+ │ Launch: E0 agent │
539
+ │ Reads: implementation result envelopes, eval target declarations │
540
+ │ Writes: eval report artifact + [wave-eval] structured marker │
541
+ │ Gate: readWaveContEvalGate() │
542
+ │ ✓ Report artifact exists │
543
+ │ ✓ [wave-eval] marker present with exact target_ids match │
544
+ │ ✓ benchmark_ids valid │
545
+ │ On fail: only E0 reruns; all implementation proof preserved │
546
+ └──────────────────────────┬──────────────────────────────────────────┘
547
+ │ gate passes (or stage skipped)
548
+
549
+ ┌─────────────────────────────────────────────────────────────────────┐
550
+ │ STAGE 2: Security Review (optional — only if security agent exists) │
551
+ │ Launch: security review agent (A7) │
552
+ │ Reads: implementation envelopes, source diff, dependency state │
553
+ │ Writes: security report + [wave-security] structured marker │
554
+ │ Gate: readWaveSecurityGate() │
555
+ │ ✓ Report exists │
556
+ │ ✓ [wave-security] marker with state=clear|concerns|blocked │
557
+ │ ✓ state != blocked (concerns are logged but non-blocking) │
558
+ │ On fail: only A7 reruns; implementation proof preserved │
559
+ └──────────────────────────┬──────────────────────────────────────────┘
560
+ │ gate passes (or stage skipped)
561
+
562
+ ┌─────────────────────────────────────────────────────────────────────┐
563
+ │ STAGE 3: Integration │
564
+ │ Launch: integration steward (A8) │
565
+ │ Reads: all implementation envelopes, coordination state, │
566
+ │ contradiction entities, shared summary │
567
+ │ Writes: integration evidence, contradiction resolutions │
568
+ │ Gate: readWaveIntegrationBarrier() │
569
+ │ ✓ Integration state is clean or claims_pending (not blocked) │
570
+ │ ✓ No unresolved hard contradictions │
571
+ │ ✓ Evidence aggregation shows cross-agent consistency │
572
+ │ On fail: only A8 reruns │
573
+ └──────────────────────────┬──────────────────────────────────────────┘
574
+ │ gate passes
575
+
576
+ ┌─────────────────────────────────────────────────────────────────────┐
577
+ │ STAGE 4: Documentation │
578
+ │ Launch: documentation steward (A9) │
579
+ │ Reads: doc-delta claims from implementation envelopes, │
580
+ │ component matrix, shared plan docs │
581
+ │ Writes: documentation closure report │
582
+ │ Gate: readWaveDocumentationGate() + readWaveComponentMatrixGate() │
583
+ │ ✓ Doc closure state is valid │
584
+ │ ✓ Component matrix promotions are consistent across agents │
585
+ │ ✓ Current levels match expected post-promotion state │
586
+ │ On fail: only A9 reruns │
587
+ └──────────────────────────┬──────────────────────────────────────────┘
588
+ │ gate passes
589
+
590
+ ┌─────────────────────────────────────────────────────────────────────┐
591
+ │ STAGE 5: cont-QA (final verdict) │
592
+ │ Launch: cont-QA steward (A0) │
593
+ │ Reads: ALL preceding closure evidence, all envelopes, │
594
+ │ full coordination state, forwarded closure gaps │
595
+ │ Writes: final verdict + [wave-gate] structured marker │
596
+ │ Gate: readWaveContQaGate() │
597
+ │ ✓ Verdict artifact exists │
598
+ │ ✓ [wave-gate] marker present │
599
+ │ ✓ Verdict is PASS (not FAIL, not PARTIAL) │
600
+ │ This is the terminal gate. PASS here = wave_closure_ready │
601
+ └─────────────────────────────────────────────────────────────────────┘
602
+ ```
603
+
604
+ ### What Each Closure Agent Actually Validates
605
+
606
+ **cont-EVAL (E0):** Runs declared eval targets from the wave's `### Eval targets` section against the benchmark catalog. Verifies that eval results meet declared thresholds. Writes a typed eval report with `target_ids` linking back to wave declarations. The gate enforces exact match between declared and reported target IDs.
607
+
608
+ **Security Reviewer (A7):** Reviews source changes for OWASP top-10, dependency vulnerabilities, credential exposure, and wave-declared security concerns. Writes a structured report with `state` field. `clear` = no findings. `concerns` = findings logged but non-blocking. `blocked` = critical findings that must be resolved.
609
+
610
+ **Integration Steward (A8):** The cross-agent consistency checker. Reads all implementation envelopes to detect contradictions (agent A1 changed an interface that agent A2 depends on), verify that claims from different agents are compatible, and confirm that the integrated codebase is coherent. Works against the materialized contradiction entities from the control plane.
611
+
612
+ **Documentation Steward (A9):** Validates that all doc-delta claims from implementation agents were actually fulfilled, that the component maturity matrix is consistent (no agent promoted a component that another agent left at a lower level), and that shared plan docs reflect the current state.
613
+
614
+ **cont-QA (A0):** The final authority. Has access to everything: all envelopes, all coordination state, all forwarded closure gaps, all prior closure-stage reports. Makes the terminal PASS/FAIL decision based on structural evidence. The gate rejects narrative-only verdicts -- the `[wave-gate]` marker must be present with the exact structured format.
615
+
616
+ ### Closure Gap Forwarding
617
+
618
+ A special case exists for `wave-proof-gap` status codes. When a closure-stage agent (e.g., A7 security review) identifies a gap but the gap is not a hard failure, the system does not stop the closure sweep:
619
+
620
+ 1. Records the gap as a `closure-critical` blocker in the coordination log via `forwardedClosureGapRecord()`
621
+ 2. Continues launching subsequent closure stages (A8, A9, A0) with the gap as structured input
622
+ 3. Later closure agents evaluate the available artifacts. They don't refuse to run just because an earlier stage had a gap
623
+ 4. The final disposition remains blocked until all forwarded gaps are resolved
624
+
625
+ **Why this matters:** Without gap forwarding, a minor security concern in Stage 2 would prevent the system from collecting integration evidence (Stage 3), documentation validation (Stage 4), and the QA assessment (Stage 5). That evidence is valuable regardless of whether the security gap needs resolution. Gap forwarding collects maximum evidence before blocking.
626
+
627
+ ### Closure Role Bindings
628
+
629
+ Closure roles are resolved through `resolveWaveRoleBindings()`:
630
+
631
+ | Role | Default Agent ID | Config Override |
632
+ |------|-----------------|----------------|
633
+ | cont-QA | A0 | `roles.contQaAgentId` or wave-level `contQaAgentId` |
634
+ | cont-EVAL | E0 | `roles.contEvalAgentId` or wave-level `contEvalAgentId` |
635
+ | Integration | A8 | `roles.integrationAgentId` or wave-level `integrationAgentId` |
636
+ | Documentation | A9 | `roles.documentationAgentId` or wave-level `documentationAgentId` |
637
+ | Security | A7 | Detected by `isSecurityReviewAgent()` from role prompt path |
638
+
639
+ Waves can override these defaults. Starter defaults (`E0`, `A7`, `A8`, `A9`, `A0`) fill gaps only when a wave does not declare its own bindings.
640
+
641
+ ### Design-First Gating (Pre-Closure)
642
+
643
+ Before the closure sweep, waves can optionally run a **design-first pass**:
644
+
645
+ 1. Design agents (detected by `isDesignAgent()`) run before implementation agents
646
+ 2. Design agents produce **design packets** under `docs/plans/waves/design/`
647
+ 3. The design gate blocks implementation until every design packet is `ready-for-implementation`
648
+ 4. Once the design gate clears, implementation agents fan out normally
649
+ 5. Hybrid design stewards (flagged by `isImplementationOwningDesignAgent()`) rejoin the implementation fan-out after their design pass
650
+
651
+ This is orchestrated by `resolvePostDesignPassTransition()` in `launcher.mjs`.
652
+
653
+ ### Infra Gate (Post-Implementation, Pre-Closure)
654
+
655
+ An additional gate checks infrastructure signal state. `readWaveInfraGate()` in `closure-engine.mjs` scans agent logs for structured infra signals and blocks if any signal ended in a non-conformant state. Conformant states (`conformant`, `setup-required`, `setup-in-progress`, `action-required`, `action-approved`, `action-complete`) are non-blocking.
656
+
657
+ ### Strict Validation Rules
658
+
659
+ Live closure enforces strict marker validation. This is intentionally unforgiving:
660
+
661
+ - **cont-EVAL:** Report artifact must exist. `[wave-eval]` marker must be present with `target_ids` exactly matching the wave's declared eval targets. `benchmark_ids` must reference valid catalog entries.
662
+ - **Security:** Report must exist. `[wave-security]` marker must be present with `state` in `{clear, concerns, blocked}`.
663
+ - **cont-QA:** Final verdict artifact must exist. `[wave-gate]` marker must be present with structured verdict.
664
+ - **Legacy tolerance:** Underspecified or evaluator-era artifacts fail in live closure. They are only tolerated in replay mode for historical compatibility.
665
+
666
+ ### Smart Rerun After Closure Failure
667
+
668
+ When a closure gate fails, the system does not rerun the entire wave:
669
+
670
+ | Failure Point | What Reruns | What Is Preserved |
671
+ |---|---|---|
672
+ | cont-EVAL fails | Only E0 | All implementation proof |
673
+ | Security fails | Only A7 | All implementation proof + E0 results |
674
+ | Integration fails | Only A8 | All implementation proof + E0 + A7 |
675
+ | Documentation fails | Only A9 | All proof + E0 + A7 + A8 |
676
+ | cont-QA fails | Only A0 | All proof + all closure stages |
677
+
678
+ This targeted rerun is computed by `planRetryWaveAttempt()` in the implementation engine, which reads the gate snapshot to identify exactly which closure role failed.
679
+
680
+ ---
681
+
682
+ ## 9. Retry and Recovery
683
+
684
+ ### Retry Planning
685
+
686
+ The `retry-engine.mjs` is a pure-function module that computes retry decisions from stored state:
687
+
688
+ 1. **Identify reusable work.** Agents with valid proof from prior attempts are marked `pre-completed` and skip relaunch. The `selectReusablePreCompletedAgentIds()` function checks:
689
+ - Exit code 0
690
+ - Valid execution summary
691
+ - Proof registry confirms proof is still valid
692
+ - No retry override targeting this agent
693
+
694
+ 2. **Compute relaunch targets.** Failed agents are selected for relaunch. The system considers:
695
+ - Direct failures (non-zero exit, timeout, missing status)
696
+ - Shared component sibling failures (one component failure blocks siblings)
697
+ - Closure gap invalidation (proof revoked by contradiction)
698
+
699
+ 3. **Apply operator overrides.** Operators can set retry overrides via `wave control rerun` to force specific agents to rerun or skip.
700
+
701
+ 4. **Persist relaunch plans.** If the launcher crashes, the relaunch plan survives on disk so the next launch can resume from the same point.
702
+
703
+ ### Executor Fallback
704
+
705
+ When a runtime fails repeatedly, the retry engine can reassign an agent to a fallback executor from the lane policy's fallback chain. The `executorFallbackChain()` function reads:
706
+ 1. Agent's explicit executor profile
707
+ 2. Lane role defaults
708
+ 3. Global fallback chain in config
709
+
710
+ ### Barriers
711
+
712
+ Retry can be blocked by barriers that require human intervention:
713
+ - Unresolved clarifications requiring human feedback
714
+ - Cross-lane dependency barriers
715
+ - Helper assignment barriers with no available owner
716
+ - Repeated failures exhausting the retry budget
717
+
718
+ The barrier is surfaced through the coordination log and dashboard so operators can act.
719
+
720
+ ---
721
+
722
+ ## 10. Run-State Reconciler
723
+
724
+ ### What the Reconciler Does
725
+
726
+ The reconciler answers one question: **which waves are actually complete?** It inspects on-disk artifacts (status files, execution summaries, coordination state, dependency tickets, assignment records) and determines whether each wave's completion evidence is structurally valid. This runs at launcher startup before any new execution begins.
727
+
728
+ The core function is `reconcileRunStateFromStatusFiles()` in `wave-files.mjs`. It is called from `launcher.mjs` during startup and can also be invoked standalone via `wave launch --reconcile-status`.
729
+
730
+ ### Why It Exists
731
+
732
+ Several scenarios can leave run state and disk artifacts out of sync:
733
+
734
+ - The launcher crashes mid-wave, leaving status files on disk but no recorded completion
735
+ - A wave completed in a prior launcher run, but the wave definition has changed since (prompt drift)
736
+ - Coordination state has changed (new blockers, clarifications, escalations) that invalidate a previous completion
737
+ - An operator manually edited artifacts or resolved dependencies outside the launcher
738
+
739
+ The reconciler detects all of these and produces a correct run state.
740
+
741
+ ### How It Works
742
+
743
+ ```
744
+ reconcileRunStateFromStatusFiles(allWaves, runStatePath, statusDir, options)
745
+
746
+ ├─ Read existing run-state.json (previous completions, history)
747
+
748
+ ├─ For each wave definition:
749
+ │ │
750
+ │ └─ analyzeWaveCompletionFromStatusFiles()
751
+ │ │
752
+ │ ├─ Status File Validation
753
+ │ │ ├─ Read agent status files (wave-<N>-<agentId>.status)
754
+ │ │ ├─ Check exit code == 0
755
+ │ │ └─ Verify metadata (promptHash present)
756
+ │ │
757
+ │ ├─ Prompt Drift Detection
758
+ │ │ ├─ Compare current prompt hash to status file's recorded hash
759
+ │ │ └─ Flag: prompt-hash-missing or prompt-hash-mismatch
760
+ │ │
761
+ │ ├─ Agent Summary Validation (per role)
762
+ │ │ ├─ cont-QA → validateContQaSummary()
763
+ │ │ ├─ cont-EVAL → validateContEvalSummary()
764
+ │ │ ├─ Security → validateSecuritySummary()
765
+ │ │ ├─ Integration → validateIntegrationSummary()
766
+ │ │ ├─ Documentation → validateDocumentationClosureSummary()
767
+ │ │ └─ Implementation → validateImplementationSummary()
768
+ │ │
769
+ │ ├─ Coordination State Checks
770
+ │ │ ├─ Open clarifications → open-clarification
771
+ │ │ ├─ Open clarification-linked requests → open-clarification-request
772
+ │ │ ├─ Unresolved human escalations → open-human-escalation
773
+ │ │ ├─ Pending human feedback → open-human-feedback
774
+ │ │ ├─ Blocking helper assignments → helper-assignment-unresolved / open
775
+ │ │ └─ Open dependency tickets → dependency-open / unresolved
776
+ │ │
777
+ │ ├─ Component Matrix Validation
778
+ │ │ ├─ Promotion consistency across agents
779
+ │ │ └─ Current levels match expected state
780
+ │ │
781
+ │ └─ Returns: { ok: boolean, reasons: [{code, detail}], evidence: {...} }
782
+
783
+ ├─ For each analyzed wave, decide outcome:
784
+ │ ├─ ok == true → mark "completed"
785
+ │ ├─ Previously completed + only prompt drift → preserve as "completed_with_drift"
786
+ │ └─ Otherwise → mark "blocked" with reasons
787
+
788
+ ├─ Write state transitions to run-state.json history (append-only)
789
+
790
+ └─ Return reconciliation report:
791
+ { completedFromStatus, addedFromBefore, blockedFromStatus, preservedWithDrift, state }
792
+ ```
793
+
794
+ ### Blocking Reason Codes
795
+
796
+ When a wave fails reconciliation, the reasons are tagged with specific codes:
797
+
798
+ | Code | Meaning |
799
+ |------|---------|
800
+ | `nonzero-status` | Agent exited with non-zero code |
801
+ | `missing-status` | Agent status file does not exist |
802
+ | `prompt-hash-missing` | Status file lacks promptHash metadata |
803
+ | `prompt-hash-mismatch` | Prompt has changed since agent ran |
804
+ | `invalid-cont-qa-summary` | cont-QA summary validation failed |
805
+ | `invalid-cont-eval-summary` | cont-EVAL summary validation failed |
806
+ | `invalid-security-summary` | Security summary validation failed |
807
+ | `invalid-integration-summary` | Integration summary validation failed |
808
+ | `invalid-documentation-summary` | Documentation summary validation failed |
809
+ | `invalid-implementation-summary` | Implementation proof validation failed |
810
+ | `component-promotions-invalid` | Component matrix promotion inconsistencies |
811
+ | `component-matrix-invalid` | Current level mismatches |
812
+ | `open-clarification` | Unresolved clarification records in coordination log |
813
+ | `open-clarification-request` | Clarification-linked requests still open |
814
+ | `open-human-escalation` | Human escalations unresolved |
815
+ | `open-human-feedback` | Human feedback still pending |
816
+ | `helper-assignment-unresolved` | Blocking assignments not assigned |
817
+ | `helper-assignment-open` | Blocking assignments assigned but not completed |
818
+ | `dependency-assignment-unresolved` | Inbound dependencies not assigned |
819
+ | `dependency-open` | Required cross-lane dependencies remain open |
820
+
821
+ ### Prompt Drift Preservation
822
+
823
+ When a wave was previously completed by an actual launcher run, but the wave definition has since changed (causing prompt hash mismatch), the reconciler does **not** invalidate the completion. Instead it preserves the wave as `completed_with_drift`.
824
+
825
+ The logic in `shouldPreserveCompletedWave()` requires both conditions:
826
+
827
+ 1. **Previous completion is authoritative**: the wave's `lastSource` is not empty and not `"legacy-run-state"` (i.e., it was completed by a real execution, not imported from old data)
828
+ 2. **Only prompt drift reasons exist**: every blocking reason is in `{prompt-hash-missing, prompt-hash-mismatch}` and no other validation failures are present
829
+
830
+ This is a pragmatic choice: prompt changes alone (e.g., editing a wave description after completion) should not force a full re-execution. But if the agent summary is also invalid, or coordination state has open blockers, the completion is revoked.
831
+
832
+ ### Run State Structure
833
+
834
+ The persistent run state at `.tmp/<lane>-wave-launcher/run-state.json`:
835
+
836
+ ```javascript
837
+ {
838
+ completedWaves: [0, 1, 2], // derived sorted list
839
+ waves: {
840
+ "0": {
841
+ wave: 0,
842
+ currentState: "completed", // or "completed_with_drift" or "blocked"
843
+ lastTransitionAt: "2024-03-22T...",
844
+ lastSource: "live-launcher", // who determined this state
845
+ lastReasonCode: "wave-complete", // why
846
+ lastDetail: "Wave 0 completed.", // human-readable
847
+ lastEvidence: { // supporting metadata
848
+ waveFileHash: "sha256:...",
849
+ statusFiles: [{ agentId, path, promptHash, code, completedAt, sha256 }],
850
+ summaryFiles: [{ agentId, path, sha256 }],
851
+ coordinationLogSha256: "sha256:...",
852
+ assignmentsSha256: "sha256:...",
853
+ gateSnapshotSha256: "sha256:..."
854
+ }
855
+ }
856
+ },
857
+ history: [ // append-only audit trail
858
+ { seq: 1, at: "...", wave: 0, fromState: null, toState: "completed", source: "live-launcher", ... }
859
+ ]
860
+ }
861
+ ```
862
+
863
+ ### Evidence Collection
864
+
865
+ Every state transition records comprehensive evidence via `buildRunStateEvidence()`:
866
+
867
+ - `waveFileHash`: SHA256 of the wave definition file
868
+ - `statusFiles[]`: Per-agent status file metadata (path, promptHash, exit code, SHA256)
869
+ - `summaryFiles[]`: Per-agent execution summary metadata (path, SHA256)
870
+ - `coordinationLogSha256`: Hash of the coordination log at transition time
871
+ - `assignmentsSha256`: Hash of the assignment snapshot
872
+ - `dependencySnapshotSha256`: Hash of the dependency snapshot
873
+ - `gateSnapshotSha256`: Hash of the gate snapshot
874
+ - `blockedReasons[]`: List of blocking reasons (if transition is to "blocked")
875
+
876
+ This makes every run-state transition auditable: you can verify exactly what evidence supported the decision.
877
+
878
+ ### Reconcile-Only Mode
879
+
880
+ `wave launch --reconcile-status` runs reconciliation without executing any waves. It also cleans up stale artifacts:
881
+
882
+ - Removes stale launcher locks (from crashed launchers)
883
+ - Kills orphaned tmux sessions
884
+ - Prunes stale terminal registry entries
885
+ - Clears stale dashboard artifacts
886
+
887
+ Output format (`reconcile-format.mjs`):
888
+ ```
889
+ [reconcile] added from status files: wave-0, wave-1
890
+ [reconcile] wave 2 not reconstructable: nonzero-status=A1 exited 1; open-clarification=CR-001
891
+ [reconcile] wave 3 preserved as completed: prompt-hash-mismatch=A2 hash changed
892
+ [reconcile] completed waves now: 0, 1, 3
893
+ ```
894
+
895
+ ---
896
+
897
+ ## 11. Sandbox Supervisor Model
898
+
899
+ ### The Problem
900
+
901
+ Sandboxed environments (like Codex's sandbox) have constraints that break the standard launcher model:
902
+
903
+ - **Short-lived sessions**: Sandbox `exec` commands have wall-clock timeouts shorter than real wave execution
904
+ - **Process pressure**: Bursty agent spawning can hit `EAGAIN`, `EMFILE`, `ENFILE` limits
905
+ - **Launcher death**: The launcher process can die before agents finish, orphaning tmux sessions
906
+ - **Ambiguous terminal state**: A missing tmux session does not mean the agent failed
907
+
908
+ The standard `wave launch` model assumes the launcher process stays alive for the entire wave. In sandboxed environments, this assumption breaks.
909
+
910
+ ### Solution: Async Submit/Observe
911
+
912
+ The sandbox model separates the client (short-lived) from the daemon (long-running) through five commands:
913
+
914
+ ```
915
+ ┌──────────────────────────────────────────────────────────────────────┐
916
+ │ wave submit [launcher options] [--json] │
917
+ │ │
918
+ │ Purpose: Quick queue, return runId, exit immediately │
919
+ │ 1. Parse and validate launcher flags │
920
+ │ 2. Generate runId: run-<timestamp>-<random> │
921
+ │ 3. Create supervisor/runs/<runId>/ │
922
+ │ 4. Write request.json (immutable) + state.json (status=pending) │
923
+ │ 5. Append event to events.jsonl: { type: "submitted" } │
924
+ │ 6. Call ensureSupervisorRunning() — spawn daemon if needed │
925
+ │ 7. Return { runId, statePath, supervisorPid } │
926
+ │ 8. Exit 0 │
927
+ └──────────────────────────────────────────────────────────────────────┘
928
+
929
+ ┌──────────────────────────────────────────────────────────────────────┐
930
+ │ wave supervise [--project <id>] [--lane <name>] [--once] │
931
+ │ │
932
+ │ Purpose: Long-running daemon that claims and supervises runs │
933
+ │ Loop: │
934
+ │ 1. Update heartbeat + lease in daemon.lock (15s renewal) │
935
+ │ 2. Scan supervisor/runs/*/state.json for all states │
936
+ │ 3. Reconcile "running" states: │
937
+ │ - If launcher-status.json exists → read exit code → terminal │
938
+ │ - If PID alive (signal 0) → still running │
939
+ │ - If PID dead + no status → mark failed │
940
+ │ 4. If no active runs: claim next "pending" run │
941
+ │ - Spawn detached launcher process │
942
+ │ - Launcher writes to launcher.log │
943
+ │ - Launcher writes launcher-status.json atomically on exit │
944
+ │ 5. Sleep 2s, repeat (or break if --once) │
945
+ └──────────────────────────────────────────────────────────────────────┘
946
+
947
+ ┌──────────────────────────────────────────────────────────────────────┐
948
+ │ wave status --run-id <id> [--project <id>] [--lane <name>] [--json] │
949
+ │ │
950
+ │ Purpose: Read-only state snapshot (no side effects) │
951
+ │ Reads supervisor/runs/<runId>/state.json and returns current state │
952
+ └──────────────────────────────────────────────────────────────────────┘
953
+
954
+ ┌──────────────────────────────────────────────────────────────────────┐
955
+ │ wave wait --run-id <id> [--timeout-seconds <n>] [--json] │
956
+ │ │
957
+ │ Purpose: Observational poll until terminal or timeout │
958
+ │ Polls state.json every 2s │
959
+ │ Returns when status ∈ {completed, failed} or deadline reached │
960
+ │ Non-cancelling: timeout does NOT kill the run │
961
+ │ Sets process.exitCode from launcher exit code │
962
+ └──────────────────────────────────────────────────────────────────────┘
963
+
964
+ ┌──────────────────────────────────────────────────────────────────────┐
965
+ │ wave attach --run-id <id> --project <id> --lane <name> ... │
966
+ │ │
967
+ │ Purpose: Projection-only attach surface │
968
+ │ --agent <id> attaches to a live session when one exists, otherwise │
969
+ │ follows the recorded agent log │
970
+ │ --dashboard reuses the stable lane dashboard attach flow │
971
+ │ Missing projection is an operator error, not a run-health verdict │
972
+ └──────────────────────────────────────────────────────────────────────┘
973
+ ```
974
+
975
+ ### Run State Machine
976
+
977
+ ```
978
+ ┌─────────────────────────────────────────────┐
979
+ │ "pending" │
980
+ │ • submittedAt set │
981
+ │ • launcherPid: null, exitCode: null │
982
+ └──────────┬──────────────────────────────────┘
983
+ │ daemon claims run, spawns launcher
984
+ ┌──────────▼──────────────────────────────────┐
985
+ │ "running" │
986
+ │ • startedAt set │
987
+ │ • launcherPid: <pid> (detached process) │
988
+ └──────────┬──────────────────────────────────┘
989
+ │ launcher writes launcher-status.json
990
+ │ OR launcher process dies unexpectedly
991
+ ┌──────────▼──────────────────────────────────┐
992
+ │ "completed" | "failed" │
993
+ │ • completedAt set │
994
+ │ • exitCode: <0|1|...> │
995
+ └─────────────────────────────────────────────┘
996
+ ```
997
+
998
+ ### Daemon Lock and Lease Mechanism
999
+
1000
+ Only one supervisor daemon runs per lane. The lock at `.tmp/<lane>-wave-launcher/supervisor/daemon.lock` contains:
1001
+
1002
+ ```javascript
1003
+ {
1004
+ supervisorId: "supervisor-<pid>-<random>",
1005
+ pid: 45821,
1006
+ project: "default",
1007
+ lane: "main",
1008
+ acquiredAt: "2024-03-22T10:30:00.000Z",
1009
+ heartbeatAt: "2024-03-22T10:30:15.000Z", // renewed every poll cycle
1010
+ leaseExpiresAt: "2024-03-22T10:30:17.000Z" // 15s from heartbeat
1011
+ }
1012
+ ```
1013
+
1014
+ **Acquisition:** Try exclusive file create (`O_EXCL`). If the file exists:
1015
+ - Read the existing lock
1016
+ - Check if the PID is alive (`process.kill(pid, 0)`) AND the lease is fresh (`leaseExpiresAt > now`)
1017
+ - If stale or dead: delete the lock, retry
1018
+ - If alive and fresh: return `null` (daemon already running)
1019
+
1020
+ **Renewal:** Each poll cycle updates `heartbeatAt` and extends `leaseExpiresAt` by 15 seconds.
1021
+
1022
+ **Stale detection:** If `leaseExpiresAt < Date.now()` and PID is not responding to signal 0, the lock is considered stale and can be claimed by a new daemon.
1023
+
1024
+ ### Launcher Spawning
1025
+
1026
+ When the daemon claims a pending run, it spawns the launcher as a **detached child process**:
1027
+
1028
+ ```javascript
1029
+ spawn('bash', ['-lc', wrapperCommand], {
1030
+ cwd: REPO_ROOT,
1031
+ detached: true, // survives daemon exit
1032
+ stdio: "ignore", // no parent I/O dependency
1033
+ env: { ...process.env, WAVE_SUPERVISOR_RUN_ID: runId }
1034
+ });
1035
+ child.unref(); // parent won't wait for exit
1036
+ ```
1037
+
1038
+ The wrapper shell command:
1039
+ 1. Runs `node wave-launcher.mjs <args>`
1040
+ 2. Redirects all output to `launcher.log`
1041
+ 3. Captures the exit code
1042
+ 4. Writes `launcher-status.json` atomically (the terminal state marker)
1043
+
1044
+ **Critical design choice:** `detached: true` + `unref()` means the launcher process survives even if the supervisor daemon dies. The daemon does not need to stay alive for the launcher to complete.
1045
+
1046
+ ### Orphan Adoption
1047
+
1048
+ If the supervisor daemon dies and restarts (or a new daemon starts):
1049
+
1050
+ 1. New daemon acquires the lock (old one is stale)
1051
+ 2. Scans `supervisor/runs/*/state.json` for runs in "running" state
1052
+ 3. For each running run:
1053
+ - Check `launcher-status.json`
1054
+ - If present: reconcile to `completed` or `failed` based on exit code
1055
+ - Else check if the launcher PID is alive (`process.kill(pid, 0)`)
1056
+ - If alive: the run is healthy, just supervise it
1057
+ - Else inspect any `agents/*.runtime.json`
1058
+ - If a runtime PID is alive or heartbeat is fresh: keep the run running with degraded terminal disposition
1059
+ - If all runtime records are terminal and no launcher status exists: mark as `failed` with detail "launcher exited before writing status"
1060
+
1061
+ This is conservative: the daemon only cleans up after confirming both that the PID is dead and the lease has expired.
1062
+
1063
+ ### Supervisor State Files
1064
+
1065
+ All supervisor state lives under `.tmp/<lane>-wave-launcher/supervisor/`:
1066
+
1067
+ ```
1068
+ supervisor/
1069
+ ├── daemon.lock Daemon lease file
1070
+ └── runs/
1071
+ └── <runId>/
1072
+ ├── request.json Immutable: submitted request (never changes)
1073
+ ├── state.json Mutable: current daemon snapshot
1074
+ ├── events.jsonl Append-only: supervisor observation history
1075
+ ├── launcher-status.json Atomic: launcher exit record (written once)
1076
+ └── launcher.log Text: launcher stdout/stderr stream
1077
+ └── agents/
1078
+ └── <agentId>.runtime.json Runtime pid/heartbeat/disposition snapshot (`agents/<agentId>.runtime.json`)
1079
+ ```
1080
+
1081
+ ### Canonical Authority in Sandboxed Runs
1082
+
1083
+ The sandbox model adds a fourth observation layer but does not change the canonical authority set:
1084
+
1085
+ | Authority | What It Covers |
1086
+ |-----------|---------------|
1087
+ | Wave definitions | Declared work, closure roles, proof contracts |
1088
+ | Coordination log | Workflow state, claims, evidence, blockers |
1089
+ | Control-plane log | Entity lifecycle, proof bundles, gates |
1090
+ | **Supervisor run state** | **Daemon-observed runtime facts (PIDs, exits, leases)** |
1091
+
1092
+ The supervisor state is authoritative for *what the daemon observed about process execution*. It does not override wave definitions or coordination state.
1093
+
1094
+ ### Typical Sandbox Workflow
1095
+
1096
+ For operator setup in LEAPclaw, OpenClaw, Nemoshell, Docker, and similar short-lived exec environments, read [../guides/sandboxed-environments.md](../guides/sandboxed-environments.md) first. The example below shows the runtime shape, not the full operator checklist.
1097
+
1098
+ ```bash
1099
+ # Client: quick exit, daemon takes over
1100
+ runId=$(wave submit --project backend --lane main \
1101
+ --executor codex --no-dashboard --json | jq -r .runId)
1102
+
1103
+ # Client: wait with timeout (non-cancelling)
1104
+ wave wait --run-id "$runId" --project backend --lane main --timeout-seconds 600
1105
+
1106
+ # Or poll from external automation
1107
+ wave status --run-id "$runId" --project backend --lane main --json
1108
+ ```
1109
+
1110
+ ### Current Limitations
1111
+
1112
+ The sandbox supervisor model is functional but some design-doc features are still partial:
1113
+
1114
+ - **Per-agent runtime records** now exist and carry PID, PGID, heartbeat, runner metadata, and terminal disposition, and the supervisor can now recover completed runs from finalized progress journals or canonical run-state when the launcher exits late
1115
+ - **Full orphan adoption** across daemon restarts remains partial; the daemon can continue supervising degraded runs, resume the active wave, and recover finalized status from canonical state, but it still refuses to synthesize success from agent runtime files alone
1116
+ - **Tmux is now dashboard-only**. Agent execution uses detached process runners, `wave attach --agent` falls back to log following when no live interactive session exists, and dashboard attach falls back to the last written dashboard file when no live dashboard session is present
1117
+ - **Setup guidance is split by intent**. Use [../guides/sandboxed-environments.md](../guides/sandboxed-environments.md) for operator setup, deployment, and container advice, and keep [../plans/sandbox-end-state-architecture.md](../plans/sandbox-end-state-architecture.md) for the deeper design rationale and remaining gap analysis
1118
+
1119
+ ---
1120
+
1121
+ ## 12. Runtime Abstraction and Executor Adapters
1122
+
1123
+ ### What Stays the Same Across Runtimes
1124
+
1125
+ - Wave parsing and validation
1126
+ - State reduction and phase decisions
1127
+ - Eval targets, deliverables, proof artifacts
1128
+ - Component and closure gates
1129
+ - Skill resolution (resolved before executor projection)
1130
+ - Shared summaries and inboxes
1131
+ - Authority-set state and projections
1132
+ - Trace bundles and replay
1133
+
1134
+ ### Where Runtime-Specific Logic Lives
1135
+
1136
+ The `executors.mjs` module builds launch specs for each runtime:
1137
+
1138
+ **Codex** (`codex exec`):
1139
+ - `--sandbox` flags (none, unsafe-full-access, danger-full-access)
1140
+ - `--add-dir` for skill directory projection
1141
+ - JSON mode, search, images support
1142
+ - Full-access sandbox modes for repo-modifying work
1143
+
1144
+ **Claude** (`claude -p`):
1145
+ - System prompt overlay via `--system-prompt`
1146
+ - Settings merge from `.claude/settings.json`
1147
+ - Hooks and permission model
1148
+ - Skill text merged into system prompt
1149
+
1150
+ **OpenCode** (`opencode run`):
1151
+ - Generated `opencode.json` configuration
1152
+ - Attached files and instruction overlays
1153
+ - Skill content projected through config
1154
+
1155
+ **LEAP-claw** (proprietary agent framework):
1156
+ - Wave's orchestration substrate serves as the runtime for LEAP-claw agents
1157
+ - LEAP-claw agents participate in the same blackboard coordination, proof, and closure model as any other executor
1158
+ - Proprietary planning and reasoning strategies are layered on top of Wave's canonical authority set
1159
+ - Skill projection, context compilation, and result envelope contracts apply identically
1160
+ - LEAP-claw agents can be mixed with Codex, Claude, and OpenCode agents within the same wave via the runtime mix policy
1161
+
1162
+ **Local** (smoke executor):
1163
+ - Prompt/closure verification without a real hosted runtime
1164
+ - Used for testing and dry-run validation
1165
+
1166
+ ### Runtime Resolution Order
1167
+
1168
+ When determining which executor an agent uses:
1169
+
1170
+ 1. Explicit `### Executor` block in the agent's wave definition
1171
+ 2. Executor profile id from config
1172
+ 3. Lane role default from `wave.config.json`
1173
+ 4. CLI `--executor` flag
1174
+ 5. Global default executor
1175
+
1176
+ ### Runtime Mix Policy
1177
+
1178
+ Waves can use multiple executors simultaneously. The config supports:
1179
+ - Mix targets capping agents per executor
1180
+ - Profiles declaring fallback chains
1181
+ - Lane policy supplying role-based defaults
1182
+ - Retry-time reassignment to policy-safe fallbacks
1183
+
1184
+ ---
1185
+
1186
+ ## 13. Skills, Context7, and Compiled Context
1187
+
1188
+ ### Skills System
1189
+
1190
+ Skills are reusable operating knowledge bundles stored in `skills/<skill-id>/`:
1191
+
1192
+ ```
1193
+ skills/<skill-id>/
1194
+ skill.json -- metadata: id, name, description, tags, roles, runtimes
1195
+ SKILL.md -- reusable instructions (runtime-agnostic)
1196
+ adapters/
1197
+ codex.md -- Codex-specific overlay
1198
+ claude.md -- Claude-specific overlay
1199
+ opencode.md -- OpenCode-specific overlay
1200
+ local.md -- Local executor overlay
1201
+ references/ -- optional reference material
1202
+ ```
1203
+
1204
+ **Resolution order:**
1205
+ 1. Base skills (global)
1206
+ 2. Role-specific skills (e.g., `role-design/`, `role-implementation/`)
1207
+ 3. Runtime-specific skills (e.g., `runtime-claude/`, `runtime-codex/`)
1208
+ 4. Deploy-kind skills (e.g., `provider-railway/`)
1209
+ 5. Explicit per-agent `### Skills` in wave definition
1210
+
1211
+ The orchestrator resolves skill IDs without knowing the runtime. The executor adapter then projects skills into the runtime's surface:
1212
+ - Codex: skill directories via `--add-dir`
1213
+ - Claude: merged skill text in system prompt overlay
1214
+ - OpenCode: instructions and attached files via generated config
1215
+ - Local: prompt-only projections
1216
+
1217
+ ### Context7
1218
+
1219
+ Context7 provides external documentation fetched at launch time. The integration works as:
1220
+
1221
+ 1. `wave.config.json` declares a Context7 bundle index at `docs/context7/bundle-index.json`
1222
+ 2. Wave definitions can declare `### Context7` selections per agent
1223
+ 3. At launch, `prefetchContext7ForSelection()` fetches library documentation
1224
+ 4. Fetched content is cached in `.tmp/<lane>-wave-launcher/context7/`
1225
+ 5. Context7 content is injected into the agent's execution prompt
1226
+
1227
+ ### Compiled Context
1228
+
1229
+ Rather than hand-maintaining separate context files for each runtime, Wave compiles context dynamically:
1230
+
1231
+ 1. **Project profile** (`.wave/project-profile.json`): Repo-level defaults
1232
+ 2. **Shared summary**: Aggregated coordination state
1233
+ 3. **Per-agent inbox**: Filtered coordination state
1234
+ 4. **Skills**: Resolved and projected for the target runtime
1235
+ 5. **Context7**: External documentation fetched at launch
1236
+ 6. **Signal state**: Versioned signal projections for long-running agents
1237
+ 7. **Design packets**: Output from design-pass agents
1238
+ 8. **Message board**: Human-readable coordination projection
1239
+
1240
+ All of this is assembled into a single execution prompt per agent at launch time by `buildExecutionPrompt()` in `coordination.mjs`.
1241
+
1242
+ ---
1243
+
1244
+ ## 14. Entity Model
1245
+
1246
+ ### Core Entities
1247
+
1248
+ | Entity | Lifecycle States | Purpose |
1249
+ |--------|-----------------|---------|
1250
+ | `wave_run` | planned -> running -> completed\|failed\|blocked | Top-level wave execution |
1251
+ | `agent_run` | planned -> started -> completed\|failed\|timed_out\|cancelled | Per-agent execution |
1252
+ | `attempt` | planned -> running -> completed\|failed\|cancelled | One execution pass (wave can have multiple) |
1253
+ | `proof_bundle` | active -> superseded\|revoked | Proof evidence with SHA256 validation |
1254
+ | `rerun_request` | active -> applied\|cleared | Operator-requested targeted reruns |
1255
+ | `human_input` | pending -> assigned -> answered\|escalated\|resolved\|timed_out\|rerouted | Human feedback lifecycle |
1256
+ | `gate` | pending -> passed\|blocked\|waived | Gate evaluation result |
1257
+ | `task` | pending -> in_progress -> proven\|blocked -> completed | Durable work unit |
1258
+ | `contradiction` | detected -> repair_needed -> resolved\|dismissed | Conflict between agents |
1259
+ | `fact` | active -> superseded | Stable semantic facts with content hashing |
1260
+ | `coordination_record` | open -> acknowledged -> in_progress -> resolved\|closed\|superseded\|cancelled | Workflow event |
1261
+
1262
+ ### Task Entity
1263
+
1264
+ Tasks are first-class entities defined in `task-entity.mjs`:
1265
+
1266
+ - **Task types:** design, implementation, integration, documentation, cont-qa, cont-eval, security, component, helper, dependency, clarification, human-input, escalation
1267
+ - **Closure states:** open -> owned_slice_proven -> wave_closure_ready -> closed (also: cancelled, superseded)
1268
+ - **Lease states:** unleased -> leased -> released\|expired
1269
+ - **Dependency edges:** Tasks can declare `blocks` and `blockedBy` relationships
1270
+
1271
+ The `evaluateOwnedSliceProven()` function checks all per-task closure conditions.
1272
+
1273
+ ### Fact Lineage
1274
+
1275
+ Facts have stable semantic IDs with separate content hashing:
1276
+ - `factId`: Stable identifier across versions
1277
+ - `contentHash`: Changes when the fact's content changes
1278
+ - `citedBy`, `contradictedBy`: Cross-referencing for lineage
1279
+ - `supersedes`, `supersededBy`: Version chain
1280
+
1281
+ ---
1282
+
1283
+ ## 15. Artifact Hierarchy
1284
+
1285
+ Every artifact in the system belongs to exactly one of four classes:
1286
+
1287
+ ### Class 1: Canonical Event Streams (append-only, never rewritten)
1288
+
1289
+ | Artifact | Path |
1290
+ |----------|------|
1291
+ | Control-plane log | `.tmp/<lane>-wave-launcher/control-plane/wave-<N>.jsonl` |
1292
+ | Coordination log | `.tmp/<lane>-wave-launcher/coordination/wave-<N>.jsonl` |
1293
+ | Cross-lane dependency tickets | `.tmp/wave-orchestrator/dependencies/<ticket-id>.json` |
1294
+
1295
+ ### Class 2: Canonical Structured Snapshots (immutable, attempt-scoped)
1296
+
1297
+ | Artifact | Path |
1298
+ |----------|------|
1299
+ | Agent result envelopes | `.tmp/<lane>-wave-launcher/results/wave-<N>/attempt-<A>/<agentId>.json` |
1300
+ | Design packets | `docs/plans/waves/design/` (repo-owned) |
1301
+
1302
+ ### Class 3: Derived Caches (computed from canonical, safe to delete)
1303
+
1304
+ | Artifact | Path |
1305
+ |----------|------|
1306
+ | Shared summaries | `.tmp/<lane>-wave-launcher/coordination/wave-<N>-shared-summary.md` |
1307
+ | Per-agent inboxes | `.tmp/<lane>-wave-launcher/inboxes/wave-<N>/<agentId>.md` |
1308
+ | Assignment snapshots | `.tmp/<lane>-wave-launcher/assignments/wave-<N>.json` |
1309
+ | Dependency snapshots | `.tmp/<lane>-wave-launcher/dependency-snapshots/wave-<N>.json` |
1310
+ | Ledgers | `.tmp/<lane>-wave-launcher/ledger/wave-<N>.json` |
1311
+ | Docs queues | `.tmp/<lane>-wave-launcher/docs-queue/wave-<N>.json` |
1312
+ | Security summaries | `.tmp/<lane>-wave-launcher/security/wave-<N>.json` |
1313
+ | Integration summaries | `.tmp/<lane>-wave-launcher/integration/wave-<N>.json` |
1314
+
1315
+ ### Class 4: Human-Facing Projections (generated from canonical + derived)
1316
+
1317
+ | Artifact | Path |
1318
+ |----------|------|
1319
+ | Global dashboard | `.tmp/<lane>-wave-launcher/dashboards/global.json` |
1320
+ | Per-wave dashboard | `.tmp/<lane>-wave-launcher/dashboards/wave-<N>.json` |
1321
+ | Markdown boards | `.tmp/<lane>-wave-launcher/coordination/wave-<N>-board.md` |
1322
+ | Status files | `.tmp/<lane>-wave-launcher/status/` |
1323
+ | Trace bundles | `.tmp/<lane>-wave-launcher/traces/wave-<N>/attempt-<A>/` |
1324
+ | Signal projections | `.tmp/<lane>-wave-launcher/signals/` |
1325
+ | Proof registries | `.tmp/<lane>-wave-launcher/proof/wave-<N>.json` |
1326
+ | Retry overrides | `.tmp/<lane>-wave-launcher/control/retry-override-wave-<N>.json` |
1327
+
1328
+ **Critical rule:** Decision-making modules (gates, retry, closure, reducer) read only Class 1 and Class 2 artifacts. Classes 3 and 4 exist for human operators and agent context injection.
1329
+
1330
+ ---
1331
+
1332
+ ## 16. Telemetry and Wave Control
1333
+
1334
+ ### Local-First Model
1335
+
1336
+ Wave Control is a local-first telemetry system with optional remote delivery:
1337
+
1338
+ 1. **Local event spool.** All events are first written to the local control-plane JSONL log.
1339
+ 2. **Queue for remote delivery.** Events are batched into a queue for the Wave Control service.
1340
+ 3. **Best-effort delivery.** Remote delivery is non-blocking. If it fails, the local spool is the authoritative record.
1341
+ 4. **Metadata-only by default.** The packaged default mode is `metadata-only`, sending only structured metadata (not full logs or source code).
1342
+
1343
+ ### Event Types
1344
+
1345
+ The `wave-control-schema.mjs` module normalizes these entity types:
1346
+ - `wave_run`, `agent_run`, `wave_signal`, `agent_signal`
1347
+ - `coordination_record`, `task`, `attempt`, `gate`, `proof_bundle`
1348
+ - `rerun_request`, `human_input`, `artifact`, `contradiction`, `fact`
1349
+ - `benchmark_run`, `benchmark_item`, `verification`, `review`
1350
+
1351
+ ### Configuration
1352
+
1353
+ ```json
1354
+ // wave.config.json
1355
+ {
1356
+ "waveControl": {
1357
+ "enabled": true,
1358
+ "endpoint": "https://wave-control.up.railway.app/api/v1",
1359
+ "reportMode": "metadata-only",
1360
+ "authTokenEnv": "WAVE_CONTROL_AUTH_TOKEN"
1361
+ }
1362
+ }
1363
+ ```
1364
+
1365
+ Opt-out options:
1366
+ - `waveControl.enabled: false` in config
1367
+ - `waveControl.reportMode: "disabled"` in config
1368
+ - `--no-telemetry` CLI flag
1369
+
1370
+ ---
1371
+
1372
+ ## 17. CLI Surface Map
1373
+
1374
+ ### Command Groups
1375
+
1376
+ | Command | Module | Purpose |
1377
+ |---------|--------|---------|
1378
+ | `wave init` | `install.mjs` | Initialize workspace with Wave |
1379
+ | `wave upgrade` | `install.mjs` | Upgrade existing Wave config |
1380
+ | `wave self-update` | `install.mjs` | Update the Wave package |
1381
+ | `wave doctor` | `install.mjs` | Validate workspace setup |
1382
+ | `wave project setup` | `planner.mjs` | Save project defaults |
1383
+ | `wave draft` | `planner.mjs` | Generate wave definitions |
1384
+ | `wave launch` | `launcher.mjs` | Execute waves (core orchestrator) |
1385
+ | `wave autonomous` | `autonomous.mjs` | Multi-wave autonomous execution |
1386
+ | `wave submit` | `supervisor-cli.mjs` | Submit async run request |
1387
+ | `wave supervise` | `supervisor-cli.mjs` | Long-running supervisor daemon |
1388
+ | `wave status` | `supervisor-cli.mjs` | Read supervisor run state |
1389
+ | `wave wait` | `supervisor-cli.mjs` | Wait for run completion |
1390
+ | `wave control` | `control-cli.mjs` | Read-only status, task, rerun, proof, telemetry surfaces |
1391
+ | `wave coord` | `coord-cli.mjs` | Direct coordination log inspection |
1392
+ | `wave feedback` | `feedback.mjs` | Human feedback collection and delivery |
1393
+ | `wave dashboard` | `dashboard-renderer.mjs` | Dashboard rendering and display |
1394
+ | `wave retry` | `retry-cli.mjs` | Retry control (legacy, prefer `wave control rerun`) |
1395
+ | `wave proof` | `proof-cli.mjs` | Proof registry (legacy, prefer `wave control proof`) |
1396
+ | `wave dep` | `dep-cli.mjs` | Cross-lane dependency management |
1397
+ | `wave adhoc` | `adhoc.mjs` | Ad-hoc transient runs |
1398
+ | `wave benchmark` | `benchmark.mjs` | Benchmark execution and tracking |
1399
+ | `wave local` | `local-executor.mjs` | Local smoke executor |
1400
+
1401
+ ### Preferred Operator Surfaces
1402
+
1403
+ `wave control` is the preferred operator surface for runtime interaction:
1404
+ - `wave control status` -- live state projection
1405
+ - `wave control task` -- create, get, list, act on blocking items
1406
+ - `wave control rerun` -- targeted rerun management
1407
+ - `wave control proof` -- proof bundle management
1408
+ - `wave control telemetry` -- event queue inspection
1409
+
1410
+ Legacy surfaces (`wave coord`, `wave retry`, `wave proof`) remain for direct log inspection but `wave control` is the recommended path.
1411
+
1412
+ ---
1413
+
1414
+ ## 18. Research Grounding
1415
+
1416
+ Wave's architecture is directly informed by published research on multi-agent systems, harness engineering, and coordination failure. The key sources and how they map to the architecture:
1417
+
1418
+ ### Harness and Runtime
1419
+
1420
+ | Source | Architectural Influence |
1421
+ |--------|------------------------|
1422
+ | [Effective harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) (Anthropic) | Session supervisor design, structured status files, timeout handling |
1423
+ | [Harness engineering: leveraging Codex](https://openai.com/index/harness-engineering/) (OpenAI) | Executor adapter model, sandbox modes, launch spec pattern |
1424
+ | [Building Effective AI Coding Agents for the Terminal](https://arxiv.org/abs/2603.05344) | Terminal surface management, tmux session model, runtime overlays |
1425
+ | [Verified Multi-Agent Orchestration](https://arxiv.org/abs/2603.11445) | Plan-execute-verify-replan maps to Wave's implementation-gate-retry-closure cycle |
1426
+
1427
+ ### Coordination and Closure
1428
+
1429
+ | Source | Architectural Influence |
1430
+ |--------|------------------------|
1431
+ | [LLM-Based Multi-Agent Blackboard System](https://arxiv.org/abs/2510.01285) | Blackboard architecture pattern, shared state over direct messaging |
1432
+ | [Exploring Advanced LLM Multi-Agent Systems Based on Blackboard Architecture](https://arxiv.org/abs/2507.01701) | Projection model (canonical state -> derived views -> human projections) |
1433
+ | [Why Do Multi-Agent LLM Systems Fail?](https://arxiv.org/abs/2503.13657) | Failure taxonomy that Wave's gate stack addresses point by point |
1434
+ | [Silo-Bench](https://arxiv.org/abs/2603.01045) | Integration barriers, dependency barriers, evidence pooling mechanisms |
1435
+
1436
+ ### Skills and Context
1437
+
1438
+ | Source | Architectural Influence |
1439
+ |--------|------------------------|
1440
+ | [SoK: Agentic Skills](https://arxiv.org/abs/2602.20867) | Skill bundle format, resolution order, runtime projection |
1441
+ | [Agent Workflow Memory](https://arxiv.org/abs/2409.07429) | Compiled context model, dynamic assembly over static files |
1442
+ | [Agent READMEs](https://arxiv.org/abs/2511.12884) | Project profile, shared plan docs, per-agent context compilation |
1443
+
1444
+ ### Evaluation and Benchmarking
1445
+
1446
+ | Source | Architectural Influence |
1447
+ |--------|------------------------|
1448
+ | [EvoClaw: Evaluating AI Agents on Continuous Software Evolution](https://arxiv.org/abs/2603.13428) | Adapted as `evoclaw-style-sequence` benchmark family for measuring long-horizon wave sequencing, dependent wave maintenance, and error accumulation across wave chains |
1449
+ | [VeRO: An Evaluation Harness for Agents to Optimize Agents](https://arxiv.org/abs/2602.22480) | Proof-oriented evaluation model, benchmark validity buckets, review entity types |
1450
+ | [MetaClaw: Just Talk](https://arxiv.org/abs/2603.17187) | Failure-driven skill synthesis, zero-downtime evolution of agent capabilities (referenced via OpenClaw platform) |
1451
+
1452
+ **Note on naming:** LEAP-claw is the proprietary agent framework built on Wave's orchestration substrate. OpenClaw, EvoClaw, and MetaClaw are unrelated external projects: OpenClaw is an open-source multi-agent platform, EvoClaw and MetaClaw are research papers. Wave adapts their evaluation methodologies into its benchmark catalog (`docs/evals/external-benchmarks.json`) but does not embed or depend on their codebases. The `leap-claw` identifier also appears in test fixtures as a lane name for integration testing.
1453
+
1454
+ ### Known Gaps
1455
+
1456
+ The architecture addresses the documented failure modes structurally but empirical validation is still in progress:
1457
+ - Limited published results on coordination-oriented benchmarks exercised systematically
1458
+ - Stress data on simultaneous coordination under contention is limited
1459
+ - Expertise routing is explicit but shallow (declared capability, not demonstrated quality)
1460
+ - DPBench-style simultaneous coordination is only indirectly addressed
1461
+
1462
+ ---
1463
+
1464
+ ## Appendix: Key File Paths
1465
+
1466
+ ```
1467
+ Entry point: scripts/wave.mjs
1468
+ Core orchestrator: scripts/wave-orchestrator/launcher.mjs
1469
+ Phase engines: scripts/wave-orchestrator/{implementation,derived-state,gate,closure,retry}-engine.mjs
1470
+ State reducer: scripts/wave-orchestrator/wave-state-reducer.mjs
1471
+ Session supervisor: scripts/wave-orchestrator/session-supervisor.mjs
1472
+ Supervisor CLI: scripts/wave-orchestrator/supervisor-cli.mjs
1473
+ Projection writer: scripts/wave-orchestrator/projection-writer.mjs
1474
+ Wave parser: scripts/wave-orchestrator/wave-files.mjs
1475
+ Reconcile formatting: scripts/wave-orchestrator/reconcile-format.mjs
1476
+ Agent state: scripts/wave-orchestrator/agent-state.mjs
1477
+ Task entities: scripts/wave-orchestrator/task-entity.mjs
1478
+ Coordination store: scripts/wave-orchestrator/coordination-store.mjs
1479
+ Control plane: scripts/wave-orchestrator/control-plane.mjs
1480
+ Executor adapters: scripts/wave-orchestrator/executors.mjs
1481
+ Skills: scripts/wave-orchestrator/skills.mjs
1482
+ Context7: scripts/wave-orchestrator/context7.mjs
1483
+ Config: scripts/wave-orchestrator/config.mjs
1484
+ Result envelopes: scripts/wave-orchestrator/result-envelope.mjs
1485
+ Contradictions: scripts/wave-orchestrator/contradiction-entity.mjs
1486
+ Signals: scripts/wave-orchestrator/signals.mjs
1487
+ Traces: scripts/wave-orchestrator/traces.mjs
1488
+ Tests: test/wave-orchestrator/*.test.ts (61 files)
1489
+ Wave config: wave.config.json
1490
+ Wave definitions: docs/plans/waves/wave-<N>.md
1491
+ Skills bundles: skills/<skill-id>/
1492
+ Run state: .tmp/<lane>-wave-launcher/run-state.json
1493
+ Supervisor state: .tmp/<lane>-wave-launcher/supervisor/
1494
+ Supervisor daemon lock: .tmp/<lane>-wave-launcher/supervisor/daemon.lock
1495
+ Supervisor runs: .tmp/<lane>-wave-launcher/supervisor/runs/<runId>/
1496
+ Sandbox setup guide: docs/guides/sandboxed-environments.md
1497
+ Sandbox architecture: docs/plans/sandbox-end-state-architecture.md
1498
+ ```