@chllming/wave-orchestration 0.8.5 → 0.8.7

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 (58) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +14 -9
  3. package/docs/README.md +3 -1
  4. package/docs/context7/bundles.json +19 -20
  5. package/docs/context7/planner-agent/README.md +4 -1
  6. package/docs/guides/author-and-run-waves.md +4 -1
  7. package/docs/guides/planner.md +3 -1
  8. package/docs/guides/signal-wrappers.md +165 -0
  9. package/docs/guides/terminal-surfaces.md +15 -0
  10. package/docs/plans/context7-wave-orchestrator.md +24 -7
  11. package/docs/plans/current-state.md +7 -3
  12. package/docs/plans/end-state-architecture.md +16 -4
  13. package/docs/plans/examples/wave-example-design-handoff.md +1 -1
  14. package/docs/plans/examples/wave-example-live-proof.md +1 -1
  15. package/docs/plans/migration.md +179 -72
  16. package/docs/plans/wave-orchestrator.md +11 -5
  17. package/docs/reference/cli-reference.md +21 -4
  18. package/docs/reference/coordination-and-closure.md +26 -5
  19. package/docs/reference/live-proof-waves.md +9 -0
  20. package/docs/reference/npmjs-trusted-publishing.md +2 -2
  21. package/docs/reference/runtime-config/README.md +9 -3
  22. package/docs/reference/sample-waves.md +5 -5
  23. package/docs/reference/skills.md +9 -1
  24. package/docs/reference/wave-control.md +18 -0
  25. package/docs/reference/wave-planning-lessons.md +7 -1
  26. package/docs/research/coordination-failure-review.md +6 -6
  27. package/package.json +1 -1
  28. package/releases/manifest.json +38 -0
  29. package/scripts/context7-api-check.sh +57 -13
  30. package/scripts/wave-orchestrator/agent-state.mjs +42 -0
  31. package/scripts/wave-orchestrator/autonomous.mjs +42 -6
  32. package/scripts/wave-orchestrator/clarification-triage.mjs +4 -3
  33. package/scripts/wave-orchestrator/control-cli.mjs +145 -11
  34. package/scripts/wave-orchestrator/control-plane.mjs +12 -1
  35. package/scripts/wave-orchestrator/coordination-store.mjs +124 -4
  36. package/scripts/wave-orchestrator/coordination.mjs +35 -0
  37. package/scripts/wave-orchestrator/executors.mjs +11 -6
  38. package/scripts/wave-orchestrator/gate-engine.mjs +5 -5
  39. package/scripts/wave-orchestrator/install.mjs +2 -0
  40. package/scripts/wave-orchestrator/launcher-runtime.mjs +12 -1
  41. package/scripts/wave-orchestrator/launcher.mjs +236 -0
  42. package/scripts/wave-orchestrator/ledger.mjs +14 -12
  43. package/scripts/wave-orchestrator/reducer-snapshot.mjs +8 -6
  44. package/scripts/wave-orchestrator/retry-engine.mjs +19 -11
  45. package/scripts/wave-orchestrator/routing-state.mjs +50 -3
  46. package/scripts/wave-orchestrator/session-supervisor.mjs +119 -10
  47. package/scripts/wave-orchestrator/shared.mjs +1 -0
  48. package/scripts/wave-orchestrator/signals.mjs +681 -0
  49. package/scripts/wave-orchestrator/task-entity.mjs +4 -4
  50. package/scripts/wave-orchestrator/terminals.mjs +14 -14
  51. package/scripts/wave-orchestrator/wave-control-schema.mjs +2 -0
  52. package/scripts/wave-orchestrator/wave-files.mjs +15 -21
  53. package/scripts/wave-orchestrator/wave-state-reducer.mjs +72 -5
  54. package/scripts/wave-status.sh +200 -0
  55. package/scripts/wave-watch.sh +200 -0
  56. package/skills/README.md +3 -0
  57. package/skills/signal-hygiene/SKILL.md +51 -0
  58. package/skills/signal-hygiene/skill.json +20 -0
@@ -96,7 +96,7 @@ Unified operator control surface. Preferred over legacy `wave coord`, `wave retr
96
96
 
97
97
  ### wave control status
98
98
 
99
- Read-only view: blocking edges, logical agent state, tasks, dependencies, rerun intent, proof bundles, and next timers.
99
+ Read-only view: blocking edges, logical agent state, tasks, dependencies, rerun intent, proof bundles, next timers, and derived wave or agent signal snapshots.
100
100
 
101
101
  When a launcher attempt is already running, `wave control status` treats that active attempt as the authoritative current fan-out. Older relaunch plans or unrelated closure blockers remain visible in the payload, but they do not override the live attempt view.
102
102
 
@@ -104,6 +104,15 @@ When a launcher attempt is already running, `wave control status` treats that ac
104
104
  wave control status --lane <lane> --wave <n> [--agent <id>] [--run <id>] [--json]
105
105
  ```
106
106
 
107
+ The JSON payload now includes:
108
+
109
+ - `signals.wave`
110
+ Versioned wave-level signal state for wrappers and external operators.
111
+ - `signals.agents`
112
+ Versioned per-agent signal state, including `shouldWake` plus any observed ack metadata.
113
+
114
+ Starter repos also include `scripts/wave-status.sh` and `scripts/wave-watch.sh` as thin readers over this JSON payload. They use exit `0` for completed, `20` for input-required, `40` for failed, and `30` from `wave-watch.sh --until-change` when the signal changed but the wave stayed active. For the full wrapper contract, read [../guides/signal-wrappers.md](../guides/signal-wrappers.md).
115
+
107
116
  ### wave control telemetry
108
117
 
109
118
  Inspect and deliver the local Wave Control event queue.
@@ -124,13 +133,15 @@ wave control task create \
124
133
  --lane <lane> --wave <n> --agent <id> \
125
134
  --kind <kind> --summary "<text>" \
126
135
  [--detail "<text>"] [--target <agent-or-capability>] \
127
- [--priority normal|high] [--depends-on <id>] \
136
+ [--priority normal|high] [--blocking true|false] \
137
+ [--severity hard|soft|stale|advisory|proof-critical|closure-critical] \
138
+ [--depends-on <id>] \
128
139
  [--artifact <ref>] [--operator <name>] [--json]
129
140
  ```
130
141
 
131
142
  Valid `--kind` values: `request`, `blocker`, `clarification`, `handoff`, `evidence`, `claim`, `decision`, `human-input`.
132
143
 
133
- Only `request`, `blocker`, `clarification`, `human-input`, and `escalation` are treated as blocking edges by `wave control status`. The rest (`handoff`, `evidence`, `claim`, `decision`) are informational.
144
+ `wave control status` only treats `request`, `blocker`, `clarification`, `human-input`, and `escalation` as potentially blocking. Tasks of those kinds can still be downgraded with `blocking=false` or non-blocking severities such as `advisory` and `stale`, so they remain visible without owning the active blocking edge.
134
145
 
135
146
  **List tasks:**
136
147
 
@@ -163,6 +174,10 @@ Actions:
163
174
  | `reassign` | `--to <agent>` | Supersede the original, reroute to a new agent |
164
175
  | `answer` | `--response "<text>"` | Answer a human-input or escalation task |
165
176
  | `escalate` | `[--detail]` | Escalate to human feedback queue |
177
+ | `defer` | `[--detail]` | Keep the task open but mark it non-blocking soft work |
178
+ | `mark-advisory` | `[--detail]` | Keep the task visible but non-blocking with advisory severity |
179
+ | `mark-stale` | `[--detail]` | Keep the task as historical context without blocking closure |
180
+ | `resolve-policy` | `[--detail]` | Close the task by operator policy and downgrade linked clarification follow-up when applicable |
166
181
 
167
182
  **Operator answer example** (responding to a human-input escalation):
168
183
 
@@ -193,6 +208,8 @@ wave control rerun request \
193
208
 
194
209
  `--agent` is repeatable or comma-separated. At least one of `--agent` or `--resume-cursor` is required.
195
210
 
211
+ The launcher may also write a rerun request automatically after recoverable failures such as timeout, max-turn, rate-limit, or missing-status outcomes. Those requests still appear through `wave control rerun get`, so operators can inspect or replace the targeted recovery plan before the next attempt.
212
+
196
213
  **Get active rerun request:**
197
214
 
198
215
  ```
@@ -544,7 +561,7 @@ Interactive draft currently offers worker role kinds:
544
561
  - `research`
545
562
  - `security`
546
563
 
547
- Agentic planner payloads also accept `workerAgents[].roleKind = "design"`. The shipped `0.8.5` surface uses `design-pass` as the default executor profile for that role and typically assigns a packet path like `docs/plans/waves/design/wave-<n>-<agentId>.md`. Interactive draft scaffolds the docs-first default; hybrid design stewards are authored by explicitly adding implementation-owned paths and the normal implementation contract sections.
564
+ Agentic planner payloads also accept `workerAgents[].roleKind = "design"`. The shipped `0.8.7` surface uses `design-pass` as the default executor profile for that role and typically assigns a packet path like `docs/plans/waves/design/wave-<n>-<agentId>.md`. Interactive draft scaffolds the docs-first default; hybrid design stewards are authored by explicitly adding implementation-owned paths and the normal implementation contract sections.
548
565
 
549
566
  ## Ad-Hoc Task Commands
550
567
 
@@ -108,14 +108,31 @@ Wave treats these coordination statuses as open:
108
108
  - `acknowledged`
109
109
  - `in_progress`
110
110
 
111
- It treats these as non-blocking:
111
+ It treats these statuses as closed:
112
112
 
113
113
  - `resolved`
114
114
  - `closed`
115
115
  - `superseded`
116
116
  - `cancelled`
117
117
 
118
- That means a targeted helper request keeps blocking until the request leaves the open set in coordination state.
118
+ But "open" and "blocking" are now different questions.
119
+
120
+ Open records can carry a blocker severity:
121
+
122
+ - `hard`
123
+ - `soft`
124
+ - `stale`
125
+ - `advisory`
126
+ - `proof-critical`
127
+ - `closure-critical`
128
+
129
+ Practical rule:
130
+
131
+ - `proof-critical`, `closure-critical`, and hard required barriers still stop the wave outright
132
+ - `soft` blockers stay visible and may still drive repair work or retry targeting
133
+ - `stale` and `advisory` records remain in coordination history without owning the active blocking edge
134
+
135
+ That means a targeted helper request only blocks while it remains open *and* still has blocking severity in coordination state.
119
136
 
120
137
  This page is documenting runtime semantics first. The important contract is that closure follows the durable coordination state, not that a particular human or agent used one exact command path to mutate it.
121
138
 
@@ -181,7 +198,7 @@ What happens next:
181
198
  - that assignment is written into the assignment snapshot
182
199
  - the shared summary and A8 inbox now show the open helper work
183
200
 
184
- `wave control task list` and `wave control task get` surface both blocking and informative coordination kinds. `wave control status` only turns `request`, `blocker`, `clarification-request`, `human-feedback`, and `human-escalation` into blocking task edges; plain `handoff`, `evidence`, `claim`, and `decision` records stay visible without falsely blocking the owner. When a launcher attempt is already running, status scopes the top-level blocking edge to that active attempt instead of letting stale relaunch metadata or unrelated closure tasks dominate the wave-level view.
201
+ `wave control task list` and `wave control task get` surface both blocking and informative coordination kinds. `wave control status` only turns `request`, `blocker`, `clarification-request`, `human-feedback`, and `human-escalation` into candidate blocking task edges, and then only if the current record still has `blocking=true` plus a blocking severity. Plain `handoff`, `evidence`, `claim`, and `decision` records stay visible without falsely blocking the owner. When a launcher attempt is already running, status scopes the top-level blocking edge to that active attempt instead of letting stale relaunch metadata or unrelated closure tasks dominate the wave-level view.
185
202
 
186
203
  ### Step 3: Why A1 Can Be Done But The Wave Is Still Blocked
187
204
 
@@ -253,15 +270,19 @@ Important implication:
253
270
 
254
271
  - even if code is landed, an open clarification chain can still block the wave
255
272
  - a routed clarification that stays `open` past the acknowledgement policy can be rerouted during the same live attempt instead of waiting for a full retry cycle
256
- - operators can now inspect and intervene through one command surface:
273
+ - operators can now inspect and intervene through one command surface, including downgrade or policy-close actions when the remaining issue is no longer proof-critical:
257
274
 
258
275
  ```bash
259
276
  pnpm exec wave control status --lane main --wave 10 --agent A7 --json
260
277
  pnpm exec wave control task act reassign --lane main --wave 10 --id clarify-a7-rollout --to A1
278
+ pnpm exec wave control task act mark-stale --lane main --wave 10 --id clarify-a7-rollout
279
+ pnpm exec wave control task act mark-advisory --lane main --wave 10 --id request-clarify-a7-rollout
280
+ pnpm exec wave control task act defer --lane main --wave 10 --id blocker-doc-follow-up
281
+ pnpm exec wave control task act resolve-policy --lane main --wave 10 --id clarify-a7-rollout --detail "Policy already covered in the published rollout guide."
261
282
  pnpm exec wave control task act resolve --lane main --wave 10 --id escalation-clarify-a7-rollout --detail "Published command surface covers this question."
262
283
  ```
263
284
 
264
- That keeps clarification routing, dismissal, escalation, and human-answer handling inside the canonical coordination state instead of forcing ad hoc file edits.
285
+ That keeps clarification routing, downgrade, dismissal, escalation, policy closure, and human-answer handling inside the canonical coordination state instead of forcing ad hoc file edits.
265
286
 
266
287
  When the operator answers through the feedback queue directly, the answer path now repairs the same canonical state:
267
288
 
@@ -40,6 +40,7 @@ For live-proof owners:
40
40
  - declare `### Proof artifacts` for machine-visible local evidence
41
41
  - keep the executor sticky unless fallback is explicitly required
42
42
  - prefer wall-clock budgets over tiny hard turn caps
43
+ - treat generic `budget.turns` as advisory; only set runtime-specific turn ceilings when you want a true hard stop
43
44
 
44
45
  Example:
45
46
 
@@ -118,6 +119,12 @@ For proof-bearing owners, default to sticky retry:
118
119
 
119
120
  Only enable cross-executor retry when there is a deliberate reason to do so.
120
121
 
122
+ Budget guidance:
123
+
124
+ - `budget.minutes` is the primary attempt budget and should be the normal control for live-proof owners
125
+ - generic `budget.turns` is now advisory metadata for Claude and OpenCode unless you also set the runtime-specific limit
126
+ - use `claude.max_turns` or `opencode.steps` only when a hard per-attempt ceiling is intentional
127
+
121
128
  If you do allow fallback, declare it explicitly:
122
129
 
123
130
  ```md
@@ -172,6 +179,8 @@ pnpm exec wave control proof register \
172
179
  4. any stale integration or closure owner reruns if needed
173
180
  5. already-valid implementation slices stay reused
174
181
 
182
+ For non-proof-centric owners elsewhere in the wave, recoverable timeout, max-turn, rate-limit, or missing-status outcomes can now queue targeted recovery automatically. For proof-bearing owners, the safer default is still to keep the same executor sticky and make the operator decision explicit once the new proof bundle exists.
183
+
175
184
  Authoritative proof registration is the supported way to make operator-produced evidence visible to A8, A0, rerun control, and hermetic traces without forcing an implementation agent to rediscover the same local artifacts in a fresh session. The canonical proof bundle now lands in `.tmp/<lane>-wave-launcher/control-plane/` and is projected into `.tmp/<lane>-wave-launcher/proof/` for compatibility.
176
185
 
177
186
  ## Suggested Eval Targets For Live-Proof Waves
@@ -2,7 +2,7 @@
2
2
 
3
3
  This repo now includes a dedicated npmjs publish workflow at [publish-npm.yml](../../.github/workflows/publish-npm.yml).
4
4
 
5
- The current `0.8.5` release procedure publishes through a repository Actions secret named `NPM_TOKEN`.
5
+ The current `0.8.7` release procedure publishes through a repository Actions secret named `NPM_TOKEN`.
6
6
 
7
7
  ## What This Repo Already Does
8
8
 
@@ -48,6 +48,6 @@ If this repo later needs private npm dependencies during CI, consider a separate
48
48
  2. Confirm `NPM_TOKEN` exists in the GitHub repo secrets.
49
49
  3. Confirm the package version has been bumped and committed.
50
50
  4. Confirm `README.md`, `CHANGELOG.md`, `releases/manifest.json`, and `docs/plans/migration.md` all describe the same release surface.
51
- 5. Push the release commit and release tag, for example `v0.8.5`.
51
+ 5. Push the release commit and release tag, for example `v0.8.7`.
52
52
  6. Verify both `publish-npm.yml` and `publish-package.yml` start from the tag push.
53
53
  7. Verify the npmjs publish completes successfully for the tagged source.
@@ -66,8 +66,14 @@ These fields are shared across runtimes:
66
66
  | Model | `model` in profile, `executors.claude.model`, `executors.opencode.model` | `model` | Codex uses shared `model` from profile or agent only |
67
67
  | Fallbacks | `fallbacks` in profile | `fallbacks` | Runtime ids used for retry-time reassignment |
68
68
  | Tags | `tags` in profile | `tags` | Stored in resolved executor state for policy and traces |
69
- | Budget turns | `budget.turns` in profile | `budget.turns` | Seeds Claude `maxTurns` and OpenCode `steps` when runtime-specific values are absent; it does not set a Codex turn limit |
70
- | Budget minutes | `budget.minutes` in profile | `budget.minutes` | Caps attempt timeout |
69
+ | Budget turns | `budget.turns` in profile | `budget.turns` | Advisory generic turn budget. Wave records it in resolved metadata, but only runtime-specific settings such as `claude.maxTurns` or `opencode.steps` emit hard turn-limit flags. It does not set a Codex turn limit. |
70
+ | Budget minutes | `budget.minutes` in profile | `budget.minutes` | Primary wall-clock attempt budget |
71
+
72
+ Practical guidance:
73
+
74
+ - prefer `budget.minutes` for normal synthesis, integration, and closure work
75
+ - use generic `budget.turns` as a planning hint, not a hard failure trigger
76
+ - only set `claude.maxTurns` or `opencode.steps` when you deliberately want a hard ceiling for that runtime
71
77
 
72
78
  ## Runtime Pages
73
79
 
@@ -161,7 +167,7 @@ Runtime-specific delivery:
161
167
  - OpenCode injects the compact catalog into `opencode.json` and attaches `skill.json`, `SKILL.md`, the selected adapter, and recursive `references/**` files through `--file`.
162
168
  - Local keeps skills prompt-only.
163
169
 
164
- `launch-preview.json` also records the resolved skill metadata plus a `limits` section. For Claude and OpenCode, that section reports the known turn ceiling and whether it came from the runtime-specific setting or generic `budget.turns`. For Codex, it explicitly records that Wave emitted no turn-limit flag and that any effective ceiling may come from the selected Codex profile or upstream runtime. If a live Codex run later terminates with a visible `Reached max turns (N)` log line, Wave appends that observed ceiling back into the live `launch-preview.json` as runtime evidence rather than pretending Wave set it.
170
+ `launch-preview.json` also records the resolved skill metadata plus a `limits` section. For Claude and OpenCode, that section reports the runtime-specific turn ceiling when one was actually configured; when only generic `budget.turns` exists, the preview keeps it as advisory metadata and notes that Wave emitted no hard turn-limit flag. For Codex, it explicitly records that Wave emitted no turn-limit flag and that any effective ceiling may come from the selected Codex profile or upstream runtime. If a live Codex run later terminates with a visible `Reached max turns (N)` log line, Wave appends that observed ceiling back into the live `launch-preview.json` as runtime evidence rather than pretending Wave set it.
165
171
 
166
172
  ## Recommended Validation Path
167
173
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "Sample Waves"
3
- summary: "Showcase-first sample waves that demonstrate the shipped 0.8.5 authored surface, including the optional design-role path."
3
+ summary: "Showcase-first sample waves that demonstrate the shipped 0.8.7 authored surface, including the optional design-role path."
4
4
  ---
5
5
 
6
6
  # Sample Waves
7
7
 
8
- This guide points to showcase-first sample waves that demonstrate the shipped `0.8.5` authored Wave surface.
8
+ This guide points to showcase-first sample waves that demonstrate the shipped `0.8.7` authored Wave surface.
9
9
 
10
10
  The examples are intentionally denser than typical production waves. Their job is to teach the current authoring and runtime surface quickly, not to be the smallest possible launch-ready files.
11
11
 
@@ -15,7 +15,7 @@ The examples are intentionally denser than typical production waves. Their job i
15
15
  Shows what a good `repo-landed` outcome looks like when one promoted component only closes honestly if desired-state records, reconcile-loop substrate, and cluster-view surfaces land together. It emphasizes maturity discipline, explicit deliverables, and shared-plan closure without drifting into `pilot-live` claims.
16
16
 
17
17
  - [Full modern sample wave](../plans/examples/wave-example-live-proof.md)
18
- Shows the combined `0.8.5` authored surface in one file: closure roles, `E0`, optional security review, delegated and pinned benchmark targets, richer executor config, `### Skills`, `### Capabilities`, `### Deliverables`, `### Exit contract`, `### Proof artifacts`, sticky retry, deploy environments, and proof-first live-wave structure.
18
+ Shows the combined `0.8.7` authored surface in one file: closure roles, `E0`, optional security review, delegated and pinned benchmark targets, richer executor config, `### Skills`, `### Capabilities`, `### Deliverables`, `### Exit contract`, `### Proof artifacts`, sticky retry, deploy environments, and proof-first live-wave structure.
19
19
 
20
20
  - [Optional design-steward handoff wave](../plans/examples/wave-example-design-handoff.md)
21
21
  Shows the shipped design-role surface: one pre-implementation design steward publishes a design packet, downstream implementation owners read that packet before coding, and normal closure roles still decide final completion. For terminal or operator-surface work, pair that shape with explicit `tui-design` in the design steward's `### Skills`. For the hybrid variant, explicitly give that same design agent implementation-owned paths and the normal implementation contract sections.
@@ -42,7 +42,7 @@ The examples are intentionally denser than typical production waves. Their job i
42
42
 
43
43
  ## Feature Coverage Map
44
44
 
45
- Together these samples cover the main surfaces added or hardened through `0.8.5`:
45
+ Together these samples cover the main surfaces added or hardened through `0.8.7`:
46
46
 
47
47
  - repo-landed maturity discipline and anti-overclaim framing
48
48
  - explicit shared-plan closure for future-wave safety
@@ -89,7 +89,7 @@ Adapt more aggressively when:
89
89
  ## Suggested Reading Order
90
90
 
91
91
  1. Start with [High-fidelity repo-landed rollout wave](../plans/examples/wave-example-rollout-fidelity.md) if you want the clearest example of good closure-ready wave fidelity for a repo-only outcome.
92
- 2. Read [Full modern sample wave](../plans/examples/wave-example-live-proof.md) if you want the denser proof-first and eval-heavy `0.8.5` surface.
92
+ 2. Read [Full modern sample wave](../plans/examples/wave-example-live-proof.md) if you want the denser proof-first and eval-heavy `0.8.7` surface.
93
93
  3. Read [Optional design-steward handoff wave](../plans/examples/wave-example-design-handoff.md) if the task needs a design packet before implementation fan-out.
94
94
  4. Read [docs/evals/README.md](../evals/README.md) if you want more background on benchmark target selection.
95
95
  5. Read [docs/reference/live-proof-waves.md](./live-proof-waves.md) if you want more detail on proof-first `pilot-live` authoring.
@@ -124,7 +124,9 @@ Top-level and lane-local skill attachment use the same shape:
124
124
 
125
125
  Lane-local `lanes.<lane>.skills` extends the global config instead of replacing it.
126
126
 
127
- Optional design workers in the shipped `0.8.5` surface normally attach `role-design`. That bundle is intended for docs/spec-first design packets and explicit implementation handoff work before implementation starts. When the design packet covers terminal UX, dashboards, or other operator surfaces, add `tui-design` explicitly in the wave's `### Skills`.
127
+ Optional design workers in the shipped `0.8.7` surface normally attach `role-design`. That bundle is intended for docs/spec-first design packets and explicit implementation handoff work before implementation starts. When the design packet covers terminal UX, dashboards, or other operator surfaces, add `tui-design` explicitly in the wave's `### Skills`.
128
+
129
+ Long-running agents that should stay resident and react only to orchestrator signal changes can add `signal-hygiene` explicitly in `### Skills`. That bundle is not auto-attached and is not meant for normal one-shot implementation agents.
128
130
 
129
131
  ## Resolution Order
130
132
 
@@ -204,6 +206,12 @@ For the optional `design` worker role, the default pattern is:
204
206
  - `tui-design` only when the packet covers terminal UX, dashboards, or other operator surfaces
205
207
  - no runtime-specific coding bundle unless the wave explicitly gives the design steward code ownership and makes it a hybrid design steward
206
208
 
209
+ For long-running watcher agents, the default pattern is:
210
+
211
+ - no special bundle by default
212
+ - add `signal-hygiene` only when the agent should stay alive and wait for signal-version changes
213
+ - use the provided signal state path plus signal ack path instead of inventing a second wakeup loop
214
+
207
215
  ## Generated Artifacts
208
216
 
209
217
  Executor overlay directories can contain:
@@ -19,6 +19,8 @@ Wave Control normalizes these entity types:
19
19
 
20
20
  - `wave_run`
21
21
  - `agent_run`
22
+ - `wave_signal`
23
+ - `agent_signal`
22
24
  - `coordination_record`
23
25
  - `task`
24
26
  - `attempt`
@@ -40,6 +42,8 @@ This lets the control plane answer:
40
42
  - which proof and benchmark artifacts back a claim
41
43
  - whether a benchmark result is comparison-valid or only diagnostic
42
44
  - which coordination failures blocked closure
45
+ - which blockers were hard, soft, stale, or advisory
46
+ - whether a blocked wave is terminal or recoverable and which targeted rerun request was queued
43
47
 
44
48
  ## Run Identity
45
49
 
@@ -90,6 +94,20 @@ Signals to preserve:
90
94
  - benchmark trust:
91
95
  every benchmark item should distinguish capability from validity
92
96
 
97
+ ## Blocker And Recovery Metadata
98
+
99
+ Wave Control should preserve the softer runtime policy, not flatten it away.
100
+
101
+ In practice that means `coordination_record`, `task`, `gate`, `wave_run`, and `rerun_request` payloads should keep fields such as:
102
+
103
+ - `blocking`
104
+ - `blockerSeverity`
105
+ - `recoverable`
106
+ - `recoveryReason`
107
+ - queued rerun request ids or resume targets
108
+
109
+ That distinction matters because a wave that is `blocked` by a proof-critical gate is different from a wave that is `blocked` only long enough to surface a targeted recovery after timeout, max-turn, rate-limit, or missing-status failure. The control plane should let operators ask which barriers still stop closure outright and which ones were intentionally downgraded to advisory or stale context.
110
+
93
111
  ## Artifact Contract
94
112
 
95
113
  Selected artifacts are described with typed descriptors:
@@ -74,11 +74,15 @@ runtime setup, and the closure artifacts all describe the same truth.
74
74
  ## 7. Runtime setup matters as much as wave prose
75
75
 
76
76
  - Do not use small fixed turn caps for synthesis-heavy or closure-heavy agents.
77
- Bound them with `budget.minutes`, not `budget.turns`.
77
+ Bound them with `budget.minutes`, not generic `budget.turns`.
78
+ - Treat generic `budget.turns` as advisory unless you intentionally set a
79
+ runtime-specific hard stop such as `claude.max_turns` or `opencode.steps`.
78
80
  - Pin exact model and reasoning settings for each runtime. Ambiguous profiles
79
81
  create unclear failure modes.
80
82
  - Avoid cross-runtime fallback on live-proof or deploy-sensitive slices unless
81
83
  there is a very good reason.
84
+ - For non-proof-centric owners, prefer targeted recovery and reuse over broad
85
+ relaunch when a timeout or max-turn event leaves partial artifacts behind.
82
86
  - Context7 should be explicit and real; unresolved bundles create noise instead
83
87
  of help.
84
88
 
@@ -121,6 +125,8 @@ runtime setup, and the closure artifacts all describe the same truth.
121
125
  - Are A8 and A0 told what would make the wave fail honestly?
122
126
  - Are runtime pins, Context7 bundles, and budgets specific enough to avoid
123
127
  preventable execution failures?
128
+ - Can any non-proof coordination ask be authored as `soft`, `stale`, or
129
+ `advisory` instead of silently becoming a hard closure blocker?
124
130
  - Would a reviewer understand the difference between “code landed” and
125
131
  “component promoted” just by reading the wave file?
126
132
 
@@ -229,16 +229,16 @@ This is the central failure highlighted by `HiddenBench` and `Silo-Bench`, and t
229
229
 
230
230
  ### 3. Expertise routing is explicit, but shallow
231
231
 
232
- [scripts/wave-orchestrator/routing-state.mjs](../../scripts/wave-orchestrator/routing-state.mjs) is better than unconstrained self-organization, but it still routes mostly by:
232
+ [scripts/wave-orchestrator/routing-state.mjs](../../scripts/wave-orchestrator/routing-state.mjs) is better than unconstrained self-organization, and it now has a light same-wave success preference, but it still routes mostly by:
233
233
 
234
234
  - explicit target
235
235
  - configured preferred agents
236
236
  - declared capability ownership
237
+ - demonstrated same-wave completions on the capability
237
238
  - least-busy fallback
238
239
 
239
- It does not yet weight:
240
+ Beyond that light historical-success preference, it still does not weight:
240
241
 
241
- - historical success on a capability
242
242
  - evidence quality by agent
243
243
  - confidence calibration
244
244
  - expert-leverage metrics
@@ -247,14 +247,14 @@ So the repo partially addresses the concern from `Multi-Agent Teams Hold Experts
247
247
 
248
248
  ### 4. Clarification and contradiction handling are still somewhat heuristic
249
249
 
250
- Clarification triage and integration evidence aggregation are real safeguards, but they still lean heavily on:
250
+ Clarification triage, blocker taxonomy, operator downgrade controls, and integration evidence aggregation are real safeguards, but they still lean heavily on:
251
251
 
252
252
  - ownership mappings
253
253
  - artifact references
254
254
  - structured markers
255
255
  - text-level summaries and conflict extraction
256
256
 
257
- That is enough to make the runtime operationally safer, but it is not yet a richer semantic evidence-integration layer. Subtle contradictions or latent information asymmetries may still be missed.
257
+ That is enough to make the runtime operationally safer. The newer hard-vs-soft blocker split also removes some unnecessary terminal failures by letting stale or advisory coordination remain visible without owning closure. But it is not yet a richer semantic evidence-integration layer, and subtle contradictions or latent information asymmetries may still be missed.
258
258
 
259
259
  ### 5. DPBench-style simultaneous coordination is only indirectly addressed
260
260
 
@@ -283,7 +283,7 @@ So the design points in the right direction, but the claim is not yet validated.
283
283
 
284
284
  If the standard is "does this repo merely claim multi-agent coordination," the answer is no. It has real machinery for blackboard-like state sharing, evidence-based closure, clarification handling, and coordination diagnostics.
285
285
 
286
- If the standard is "has this repo already demonstrated that its design beats the core failure modes isolated by HiddenBench, Silo-Bench, DPBench, and related work," the answer is also no. The design is substantially more credible than most MAS stacks, but the empirical proof is still missing.
286
+ If the standard is "has this repo already demonstrated that its design beats the core failure modes isolated by HiddenBench, Silo-Bench, DPBench, and related work," the answer is also no. The design is substantially more credible than most MAS stacks, and it now also reduces avoidable failure through targeted recovery, blocker severity, and policy-safe downgrade paths, but the empirical proof is still missing.
287
287
 
288
288
  The most accurate claim today is:
289
289
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chllming/wave-orchestration",
3
- "version": "0.8.5",
3
+ "version": "0.8.7",
4
4
  "license": "MIT",
5
5
  "description": "Generic wave-based multi-agent orchestration for repository work.",
6
6
  "repository": {
@@ -2,6 +2,44 @@
2
2
  "schemaVersion": 1,
3
3
  "packageName": "@chllming/wave-orchestration",
4
4
  "releases": [
5
+ {
6
+ "version": "0.8.7",
7
+ "date": "2026-03-27",
8
+ "summary": "Policy-consistency hardening, capability-specific same-wave routing, stable per-wave tmux session reuse, and 0.8.7 release-surface alignment.",
9
+ "features": [
10
+ "Generic `budget.turns` is now documented and tested consistently as advisory metadata only; hard runtime turn ceilings come only from runtime-specific settings such as `claude.maxTurns` or `opencode.steps`.",
11
+ "Capability-targeted helper routing now prefers demonstrated same-wave success for the requested capability before falling back to the least-busy matching capability owner, and unrelated completed work no longer counts as routing evidence.",
12
+ "Advisory, stale, and other non-blocking clarification or human-input records stay visible in control and reducer projections without reopening hard blocked reducer state by themselves.",
13
+ "Wave-agent, resident-orchestrator, and per-wave dashboard tmux sessions now reuse stable per-wave session names, so stale launcher exits stop accumulating extra sessions for the same wave.",
14
+ "Structured signal extraction now also recognizes markers embedded inside JSON log lines, so wrapped executor transcripts still produce proof, doc-delta, and component evidence."
15
+ ],
16
+ "manualSteps": [
17
+ "Run `pnpm exec wave doctor` and `pnpm exec wave launch --lane main --dry-run --no-dashboard` after upgrading so the repo validates against the `0.8.7` routing, blocker-severity, signal-wrapper, and stable-session behavior.",
18
+ "If your repo copied starter scripts or operator docs, sync `scripts/wave-status.sh`, `scripts/wave-watch.sh`, `docs/guides/signal-wrappers.md`, `docs/guides/terminal-surfaces.md`, `docs/reference/cli-reference.md`, and any local tmux/session runbooks that still assume run-tagged session names.",
19
+ "If your repo copied planner or routing guidance, sync `docs/guides/planner.md`, `docs/reference/wave-planning-lessons.md`, `docs/plans/wave-orchestrator.md`, the `planner-agentic` bundle entry in `docs/context7/bundles.json`, and any local helper-assignment policy docs so they describe capability-specific same-wave routing evidence instead of generic prior completion.",
20
+ "If your repo relies on advisory `budget.turns` as if it were a hard ceiling, move that limit to the runtime-specific executor config (`claude.maxTurns` or `opencode.steps`) before you depend on deterministic turn enforcement."
21
+ ],
22
+ "breaking": false
23
+ },
24
+ {
25
+ "version": "0.8.6",
26
+ "date": "2026-03-25",
27
+ "summary": "Signal-hygiene starter surface, versioned signal wrappers, terminal watcher hardening, and 0.8.6 release-surface alignment.",
28
+ "features": [
29
+ "Versioned wave and agent signal snapshots now ship as part of the operator surface under `.tmp/<lane>-wave-launcher/signals/`, with resident-orchestrator and long-running-agent ack loops built on the same model.",
30
+ "Starter repos now include `skills/signal-hygiene/`, `scripts/wave-status.sh`, and `scripts/wave-watch.sh` for long-running watcher agents plus shell-friendly operator automation.",
31
+ "Wrapper exit semantics now expose terminal failure with exit `40`, while `wave-watch.sh --until-change` still returns `30` only when a signal changed and the wave stayed active.",
32
+ "Agent signal materialization now treats completed and failed as terminal even when stale answered feedback or old coordination tasks still exist in the materialized status payload.",
33
+ "The migration guide now covers fresh adoption plus upgrades from `0.8.5`, `0.8.4`, `0.8.3`, `0.8.0`-`0.8.4`, `0.6.x`-`0.7.x`, and `0.5.x` or earlier, including repo-owned sync guidance for `skills/signal-hygiene/`, the wrapper scripts, and the `planner-agentic` corpus."
34
+ ],
35
+ "manualSteps": [
36
+ "Run `pnpm exec wave doctor` and `pnpm exec wave launch --lane main --dry-run --no-dashboard` after upgrading so the repo validates against the `0.8.6` signal-hygiene, wrapper, and design-role behavior.",
37
+ "If your repo copied starter prompts, skills, scripts, or runbooks, sync `skills/signal-hygiene/`, `scripts/wave-status.sh`, `scripts/wave-watch.sh`, `docs/guides/signal-wrappers.md`, `docs/guides/terminal-surfaces.md`, `docs/reference/cli-reference.md`, and any local operator docs that describe waiting or failure handling.",
38
+ "If your repo uses planner workflows and copied the planner starter corpus, keep `docs/agents/wave-planner-role.md`, `skills/role-planner/`, `docs/context7/planner-agent/`, `docs/reference/wave-planning-lessons.md`, and the `planner-agentic` bundle entry in sync before relying on local planner docs.",
39
+ "If your repo uses long-running watcher agents or shell automation, update local loops so wrapper exit `40` is treated as terminal failure and confirm watchers can write their signal ack files under `.tmp/<lane>-wave-launcher/signals/`."
40
+ ],
41
+ "breaking": false
42
+ },
5
43
  {
6
44
  "version": "0.8.5",
7
45
  "date": "2026-03-25",
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env bash
2
- # Minimal Context7 API smoke test (expects CONTEXT7_API_KEY in the environment).
3
2
  set -euo pipefail
4
3
 
5
4
  if [[ -z "${CONTEXT7_API_KEY:-}" ]]; then
@@ -7,15 +6,60 @@ if [[ -z "${CONTEXT7_API_KEY:-}" ]]; then
7
6
  exit 1
8
7
  fi
9
8
 
10
- URL='https://context7.com/api/v2/libs/search?libraryName=temporal&query=go%20workflow'
11
- echo "GET $URL" >&2
12
- RESP="$(curl -fsS "$URL" -H "Authorization: Bearer ${CONTEXT7_API_KEY}" -H "Accept: application/json")"
13
- RESP_JSON="$RESP" node -e "
14
- const j = JSON.parse(process.env.RESP_JSON || '{}');
15
- const list = Array.isArray(j) ? j : (j.results ?? j.items ?? []);
16
- const first = list[0];
17
- if (!first) { console.error('Unexpected response shape:', Object.keys(j)); process.exit(1); }
18
- const id = first.id ?? first.libraryId;
19
- const name = first.title ?? first.name;
20
- console.log('ok — first library:', id || name || JSON.stringify(first).slice(0, 120));
21
- "
9
+ node <<'NODE'
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+
13
+ const apiKey = process.env.CONTEXT7_API_KEY || "";
14
+ const repoRoot = process.cwd();
15
+ const bundlePath = path.join(repoRoot, "docs/context7/bundles.json");
16
+ const payload = JSON.parse(fs.readFileSync(bundlePath, "utf8"));
17
+
18
+ const entries = [];
19
+ for (const [bundleId, bundle] of Object.entries(payload.bundles || {})) {
20
+ for (const library of bundle.libraries || []) {
21
+ if (!library.libraryId) {
22
+ throw new Error(
23
+ `Bundle "${bundleId}" must pin exact Context7 libraryId values. Found libraryName=${JSON.stringify(library.libraryName || "")}.`,
24
+ );
25
+ }
26
+ entries.push({
27
+ bundleId,
28
+ libraryId: String(library.libraryId),
29
+ queryHint: String(library.queryHint || "overview"),
30
+ });
31
+ }
32
+ }
33
+
34
+ const uniqueEntries = [...new Map(entries.map((entry) => [entry.libraryId, entry])).values()];
35
+
36
+ async function validate(entry) {
37
+ const url = new URL("https://context7.com/api/v2/context");
38
+ url.searchParams.set("libraryId", entry.libraryId);
39
+ url.searchParams.set("query", entry.queryHint);
40
+ url.searchParams.set("type", "txt");
41
+ const response = await fetch(url, {
42
+ headers: {
43
+ Authorization: "Bearer " + apiKey,
44
+ Accept: "text/plain, application/json",
45
+ },
46
+ });
47
+ const text = await response.text();
48
+ if (!response.ok) {
49
+ throw new Error(`Context7 ${entry.libraryId} failed (${response.status}): ${text.slice(0, 200)}`);
50
+ }
51
+ if (text.trim().length === 0) {
52
+ throw new Error(`Context7 ${entry.libraryId} returned empty context.`);
53
+ }
54
+ console.log(`ok -- ${entry.libraryId} (${entry.bundleId})`);
55
+ }
56
+
57
+ (async () => {
58
+ for (const entry of uniqueEntries) {
59
+ await validate(entry);
60
+ }
61
+ })().catch((error) => {
62
+ console.error(error instanceof Error ? error.message : String(error));
63
+ process.exit(1);
64
+ });
65
+ NODE
@@ -160,6 +160,44 @@ function appendParsedStructuredSignalCandidates(lines, candidates, { requireAll
160
160
  candidates.push(...parsedCandidates);
161
161
  }
162
162
 
163
+ function collectEmbeddedStructuredSignalTexts(value, texts) {
164
+ if (!value || typeof value !== "object") {
165
+ return;
166
+ }
167
+ if (Array.isArray(value)) {
168
+ for (const item of value) {
169
+ collectEmbeddedStructuredSignalTexts(item, texts);
170
+ }
171
+ return;
172
+ }
173
+ if (typeof value.text === "string") {
174
+ texts.push(value.text);
175
+ }
176
+ if (typeof value.aggregated_output === "string") {
177
+ texts.push(value.aggregated_output);
178
+ }
179
+ for (const nestedValue of Object.values(value)) {
180
+ if (nestedValue && typeof nestedValue === "object") {
181
+ collectEmbeddedStructuredSignalTexts(nestedValue, texts);
182
+ }
183
+ }
184
+ }
185
+
186
+ function extractEmbeddedStructuredSignalTextsFromJsonLine(line) {
187
+ const trimmed = String(line || "").trim();
188
+ if (!trimmed || !/^[{\[]/.test(trimmed)) {
189
+ return [];
190
+ }
191
+ try {
192
+ const payload = JSON.parse(trimmed);
193
+ const texts = [];
194
+ collectEmbeddedStructuredSignalTexts(payload, texts);
195
+ return texts.filter(Boolean);
196
+ } catch {
197
+ return [];
198
+ }
199
+ }
200
+
163
201
  function collectStructuredSignalCandidates(text) {
164
202
  if (!text) {
165
203
  return [];
@@ -167,6 +205,10 @@ function collectStructuredSignalCandidates(text) {
167
205
  const candidates = [];
168
206
  let fenceLines = null;
169
207
  for (const rawLine of String(text || "").split(/\r?\n/)) {
208
+ const embeddedTexts = extractEmbeddedStructuredSignalTextsFromJsonLine(rawLine);
209
+ for (const embeddedText of embeddedTexts) {
210
+ candidates.push(...collectStructuredSignalCandidates(embeddedText));
211
+ }
170
212
  const trimmed = rawLine.trim();
171
213
  if (/^```/.test(trimmed)) {
172
214
  if (fenceLines === null) {