@chllming/wave-orchestration 0.8.8 → 0.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.8.9 - 2026-03-27
6
+
7
+ ### Changed
8
+
9
+ - The current release surface now points consistently at `0.8.9`, including the README, current-state notes, migration guide, release manifest, tracked install-state fixtures, and the versioned recommendations guide `docs/guides/recommendations-0.8.9.md`.
10
+
11
+ ### Fixed And Hardened
12
+
13
+ - Reducer snapshots now preserve design packet report paths when rebuilding summaries from result envelopes, so `designGate` no longer reopens as `missing-design-packet` after a successful design pass.
14
+ - Launcher transitions after design-only passes now stop on the actual design-gate blocker instead of falling through to a misleading downstream implementation `missing-result-envelope` failure.
15
+ - Trace bundle summary reconstruction now also resolves design packet report paths, so copied trace summaries stay aligned when design summaries are rebuilt from logs.
16
+
17
+ ### Testing And Validation
18
+
19
+ - `pnpm exec vitest run --config vitest.config.ts test/wave-orchestrator/wave-state-reducer.test.ts test/wave-orchestrator/launcher.test.ts test/wave-orchestrator/traces.test.ts`
20
+ - `pnpm test`
21
+ - `node scripts/wave.mjs doctor --json`
22
+ - `node scripts/wave.mjs launch --lane main --dry-run --no-dashboard`
23
+
5
24
  ## 0.8.8 - 2026-03-27
6
25
 
7
26
  ### Changed
package/README.md CHANGED
@@ -103,18 +103,17 @@ Wave is built to mitigate those failures with a canonical authority set, generat
103
103
 
104
104
  Current release:
105
105
 
106
- - `@chllming/wave-orchestration@0.8.8`
107
- - Release tag: [`v0.8.8`](https://github.com/chllming/agent-wave-orchestrator/releases/tag/v0.8.8)
106
+ - `@chllming/wave-orchestration@0.8.9`
107
+ - Release tag: [`v0.8.9`](https://github.com/chllming/agent-wave-orchestrator/releases/tag/v0.8.9)
108
108
  - Public install path: npmjs
109
109
  - Authenticated fallback: GitHub Packages
110
110
 
111
- Highlights in `0.8.8`:
111
+ Highlights in `0.8.9`:
112
112
 
113
- - The shipped starter surface now includes `skills/signal-hygiene/` plus seeded `scripts/wave-status.sh` and `scripts/wave-watch.sh` wrappers for long-running-agent and operator wait loops.
114
- - Long-running agents and resident orchestrators now get prompt-level signal-state and signal-ack paths, so wakeups are edge-triggered by versioned signal changes instead of relying on terminal injection.
115
- - Versioned wave or agent signal snapshots are now a first-class operator surface under `.tmp/<lane>-wave-launcher/signals/`, with failure treated as terminal in both the runtime and the wrapper exit contract.
116
- - `0.8.5` design-role and hybrid design-steward behavior remains part of the shipped release surface, and the current release line keeps the `0.8.7` capability-specific same-wave helper routing, blocker-severity consistency, and stable per-wave tmux session reuse hardening.
117
- - Release docs, current-state notes, migration guidance, publishing instructions, and the packaged operator recommendations guide now point at the `0.8.8` surface.
113
+ - Reducer snapshots now preserve design packet report paths when they rebuild summaries from result envelopes, so successful design passes no longer get replayed as `missing-design-packet`.
114
+ - Launcher transitions after design-only passes now stop on the real design-gate failure and record a design-specific blocker instead of falling through to a misleading downstream implementation `missing-result-envelope` error.
115
+ - Trace bundle summary reconstruction now also preserves design packet report paths, so copied summary artifacts stay aligned when a trace has to rebuild a design summary from logs.
116
+ - Release docs, current-state notes, migration guidance, publishing instructions, the packaged operator recommendations guide, and the tracked install-state fixtures now all point at the `0.8.9` surface.
118
117
 
119
118
  Requirements:
120
119
 
package/docs/README.md CHANGED
@@ -36,15 +36,15 @@ The useful path is journey-first:
36
36
  - Drafting or revising waves:
37
37
  Read [guides/author-and-run-waves.md](./guides/author-and-run-waves.md), then use [plans/wave-orchestrator.md](./plans/wave-orchestrator.md) as the operator runbook.
38
38
  - Adding an optional pre-implementation design steward:
39
- Read [guides/author-and-run-waves.md](./guides/author-and-run-waves.md), then the standing prompt in [agents/wave-design-role.md](./agents/wave-design-role.md). The shipped `0.8.8` surface includes `role-design` plus `tui-design`, with docs-first design stewards by default and explicit hybrid design stewards when a wave also gives that same agent code ownership.
39
+ Read [guides/author-and-run-waves.md](./guides/author-and-run-waves.md), then the standing prompt in [agents/wave-design-role.md](./agents/wave-design-role.md). The shipped `0.8.9` surface includes `role-design` plus `tui-design`, with docs-first design stewards by default and explicit hybrid design stewards when a wave also gives that same agent code ownership.
40
40
  - Want signal-driven automation or long-running watcher loops:
41
41
  Read [guides/signal-wrappers.md](./guides/signal-wrappers.md). It covers the seeded `wave-status.sh` and `wave-watch.sh` wrappers, the versioned signal snapshot files, and the ack-loop contract behind `signal-hygiene`.
42
42
  - Adding a security review pass:
43
43
  Read [plans/wave-orchestrator.md](./plans/wave-orchestrator.md) and the standing reviewer prompt in [agents/wave-security-role.md](./agents/wave-security-role.md).
44
44
  - Upgrading an existing repo:
45
45
  Read [plans/migration.md](./plans/migration.md), then review the release notes in [../CHANGELOG.md](../CHANGELOG.md) before running `pnpm exec wave upgrade`.
46
- - Want the practical `0.8.8` operating stance:
47
- Read [guides/recommendations-0.8.8.md](./guides/recommendations-0.8.8.md) for the recommended default around relaxed blocker states, advisory turn budgets, and targeted recovery.
46
+ - Want the practical `0.8.9` operating stance:
47
+ Read [guides/recommendations-0.8.9.md](./guides/recommendations-0.8.9.md) for the recommended default around relaxed blocker states, advisory turn budgets, and targeted recovery.
48
48
  - Want the concrete runtime module map:
49
49
  Read [plans/end-state-architecture.md](./plans/end-state-architecture.md) for the engine-by-engine architecture and artifact ownership model.
50
50
  - Want the CLI surface map:
@@ -61,7 +61,7 @@ Good fits:
61
61
  - multi-owner waves where downstream implementers need the same decisions and assumptions
62
62
  - ambiguous tasks where open questions should become explicit before code owners fan out
63
63
 
64
- The starter contract in `0.8.8` is:
64
+ The starter contract in `0.8.9` is:
65
65
 
66
66
  - import `docs/agents/wave-design-role.md`
67
67
  - own one packet such as `docs/plans/waves/design/wave-<n>-<agentId>.md`
@@ -6,7 +6,7 @@ If you want the full author-to-launch workflow, start with [author-and-run-waves
6
6
 
7
7
  It reduces repeated setup questions, stores project defaults, and generates wave specs plus markdown that already fit the launcher.
8
8
 
9
- The published `0.8.8` package already includes the optional `design` worker role for pre-implementation design packets. This guide calls out where that affects drafting.
9
+ The published `0.8.9` package already includes the optional `design` worker role for pre-implementation design packets. This guide calls out where that affects drafting.
10
10
 
11
11
  ## What Ships Today
12
12
 
@@ -1,15 +1,15 @@
1
1
  ---
2
- title: "0.8.8 Recommendations"
3
- summary: "How to use 0.8.8's softer blocker states, advisory turn budgets, and targeted recovery without weakening proof and closure."
2
+ title: "0.8.9 Recommendations"
3
+ summary: "How to use 0.8.9's softer blocker states, advisory turn budgets, and targeted recovery without weakening proof and closure."
4
4
  ---
5
5
 
6
- # 0.8.8 Recommendations
6
+ # 0.8.9 Recommendations
7
7
 
8
- Use this guide when you are adopting `0.8.8` and want one practical operating stance for the softer blocker states, advisory turn-budget behavior, and targeted recovery flow that the current package line ships.
8
+ Use this guide when you are adopting `0.8.9` and want one practical operating stance for the softer blocker states, advisory turn-budget behavior, and targeted recovery flow that the current package line ships.
9
9
 
10
10
  ## Recommended Default
11
11
 
12
- For most repos, the safest `0.8.8` default is:
12
+ For most repos, the safest `0.8.9` default is:
13
13
 
14
14
  - bound work with `budget.minutes`
15
15
  - leave generic `budget.turns` as advisory metadata
@@ -75,7 +75,7 @@ Only set a hard runtime ceiling when you deliberately want the runtime itself to
75
75
 
76
76
  ## 2. Softer Coordination States
77
77
 
78
- `0.8.8` keeps “still visible” separate from “still blocking”.
78
+ `0.8.9` keeps “still visible” separate from “still blocking”.
79
79
 
80
80
  Use these states intentionally:
81
81
 
@@ -111,7 +111,7 @@ If the current wave cannot truthfully close without the answer, keep it blocking
111
111
 
112
112
  ## 4. Recovery Recommendation
113
113
 
114
- My recommendation after reviewing the current `0.8.8` code path is:
114
+ My recommendation after reviewing the current `0.8.9` code path is:
115
115
 
116
116
  - let timeout, max-turn, rate-limit, and missing-status failures go through the built-in targeted recovery path first
117
117
  - inspect the queued rerun or resume request before manually relaunching the whole wave
@@ -1,10 +1,10 @@
1
1
  # Current State
2
2
 
3
- - The published package is `0.8.8`, and that release now includes the optional pre-implementation `design` worker role, the `role-design`, `tui-design`, and `signal-hygiene` starter bundles, plus the seeded signal-wrapper scripts for long-running-agent and operator wait loops.
3
+ - The published package is `0.8.9`; that release keeps the shipped design-role and signal-hygiene starter surface, preserves design packet report paths during reducer and trace summary reconstruction, and reports blocked design passes as design-gate failures before implementation starts.
4
4
  - The canonical shipped runtime architecture is documented in `docs/plans/end-state-architecture.md`; historical cutover notes remain in `docs/plans/architecture-hardening-migration.md`.
5
5
  - The repository contains the published `@chllming/wave-orchestration` package plus the starter scaffold used by `wave init`.
6
6
  - The runtime is package-first and non-destructive for adopting repos: `wave init --adopt-existing` records existing repo-owned plans, waves, prompts, and config without overwriting them, and `wave upgrade` writes only `.wave/install-state.json` plus `.wave/upgrade-history/`.
7
- - The recommended `0.8.8` operating stance is documented in `docs/guides/recommendations-0.8.8.md`: keep proof and closure strict, keep generic `budget.turns` advisory, and use softer coordination states only for non-proof follow-up.
7
+ - The recommended `0.8.9` operating stance is documented in `docs/guides/recommendations-0.8.9.md`: keep proof and closure strict, keep generic `budget.turns` advisory, and use softer coordination states only for non-proof follow-up.
8
8
  - Runtime launch entrypoints now perform a best-effort npmjs version check, cache the result under `.wave/package-update-check.json`, and point operators at `pnpm exec wave self-update` when a newer published package exists.
9
9
  - This source repo is itself kept as an adopted Wave workspace, so `node scripts/wave.mjs doctor --json` should pass from the repo root.
10
10
  - The default lane is `main`.
@@ -1,6 +1,6 @@
1
1
  # End-State Architecture
2
2
 
3
- This document describes the canonical architecture for the current Wave runtime. It is the authoritative reference for the engine boundaries, canonical authority set, and artifact ownership model that the shipped `0.8.8` surface now follows.
3
+ This document describes the canonical architecture for the current Wave runtime. It is the authoritative reference for the engine boundaries, canonical authority set, and artifact ownership model that the shipped `0.8.9` surface now follows.
4
4
 
5
5
  The thesis is unchanged: bounded waves, closure roles, proof artifacts, selective rerun, and delivery discipline. What changes is the internal authority model. The launcher stops being the decision engine and becomes a thin orchestrator that reads decisions from canonical state, sequences the engines, and delegates process work to the session supervisor.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Wave 12 - Optional Design Steward Handoff
2
2
 
3
- This is a showcase-first sample wave for the shipped `design` worker role in `0.8.8`.
3
+ This is a showcase-first sample wave for the shipped `design` worker role in `0.8.9`.
4
4
 
5
5
  This example demonstrates the docs-first design-steward path where a design packet is published before code-owning implementation begins.
6
6
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  This is a showcase-first sample wave.
4
4
 
5
- Use it as the single reference example for the current `0.8.8` Wave surface.
5
+ Use it as the single reference example for the current `0.8.9` Wave surface.
6
6
 
7
7
  It intentionally combines more sections than a normal production wave so one file can demonstrate:
8
8
 
@@ -1,6 +1,6 @@
1
1
  # Migration
2
2
 
3
- This page is the practical repo-upgrade guide for the current `0.8.8` surface.
3
+ This page is the practical repo-upgrade guide for the current `0.8.9` surface.
4
4
 
5
5
  Use it when you are:
6
6
 
@@ -10,20 +10,20 @@ Use it when you are:
10
10
 
11
11
  For the completed internal architecture cutover record, see [architecture-hardening-migration.md](./architecture-hardening-migration.md). That document is historical. This one is the operator-facing upgrade checklist.
12
12
 
13
- ## What `0.8.8` Changes
13
+ ## What `0.8.9` Changes
14
14
 
15
- The current `0.8.8` surface keeps the `0.8.7` policy-consistency and stable per-wave session reuse hardening, and now also packages the operator recommendations guide and install-state alignment follow-up in the release itself.
15
+ The current `0.8.9` surface keeps the `0.8.8` packaged operator-guidance alignment and adds a focused repair for design-pass replay and post-design transition handling.
16
16
 
17
17
  The practical changes are:
18
18
 
19
- - generic `budget.turns` stays advisory metadata unless the runtime-specific ceiling is set explicitly with `claude.maxTurns` or `opencode.steps`
20
- - capability-targeted helper routing now treats demonstrated same-wave success as capability-specific evidence; unrelated completed work no longer makes an agent the preferred helper owner
21
- - advisory or stale clarification and human-input records remain visible in coordination history and reducer blocker views, but they no longer reopen `clarifying` or blocked reducer state by themselves
22
- - wave-agent and resident-orchestrator tmux sessions now reuse stable per-wave session names, so relaunches and stale launcher exits stop accumulating extra tmux sessions for the same wave
19
+ - reducer snapshots now preserve design packet report paths when they rebuild summaries from result envelopes
20
+ - blocked design passes now stop at the design gate instead of being surfaced later as downstream implementation envelope failures
21
+ - trace bundle summary reconstruction now also resolves design packet report paths, so copied design summaries stay aligned when they are rebuilt from logs
22
+ - the current release surface and tracked install-state fixtures now all move together on `0.8.9`
23
23
 
24
- If your repo copied starter docs, shell automation, or operator runbooks, these are the areas most likely to need a sync before the `0.8.8` package cut.
24
+ If your repo copied starter docs, shell automation, or operator runbooks, these are the areas most likely to need a sync before the `0.8.9` package cut.
25
25
 
26
- For a practical `0.8.8` operating stance after the upgrade, read [../guides/recommendations-0.8.8.md](../guides/recommendations-0.8.8.md).
26
+ For a practical `0.8.9` operating stance after the upgrade, read [../guides/recommendations-0.8.9.md](../guides/recommendations-0.8.9.md).
27
27
 
28
28
  ## What `0.8.6` Changes
29
29
 
@@ -138,14 +138,14 @@ pnpm exec wave coord inbox --lane main --wave 0 --agent A1 --dry-run
138
138
 
139
139
  Use `pnpm exec wave dashboard --lane <lane> --attach current` or `--attach global` when you need to reattach to a tmux-backed dashboard after the upgrade.
140
140
 
141
- ## `0.8.8` Release Model
141
+ ## `0.8.9` Release Model
142
142
 
143
- The current `0.8.8` surface is three changes together:
143
+ The current `0.8.9` surface is three changes together:
144
144
 
145
145
  - the shipped `design` worker role and hybrid design-steward flow introduced in `0.8.5`
146
146
  - the signal-driven long-running-agent and wrapper model introduced in `0.8.6`
147
147
  - the policy-consistency, targeted-recovery, capability-specific routing, and stable per-wave session reuse hardening introduced in `0.8.7`
148
- - the packaged recommendations guide and install-state alignment follow-up released in `0.8.8`
148
+ - the packaged recommendations guide and install-state alignment follow-up released in `0.8.9`
149
149
 
150
150
  ### Signal-driven waiting and wrapper model
151
151
 
@@ -329,9 +329,9 @@ If the repo copied starter `wave.config.json` defaults, also sync:
329
329
  - if the repo uses hybrid design stewards, confirm the same agent rejoins implementation only when the authored wave explicitly gives it code ownership
330
330
  - if the repo uses long-running agents or shell automation, confirm the new wrapper exit contract and ack-loop semantics before relying on an older polling script
331
331
 
332
- ## Upgrading From `0.8.3` To `0.8.8`
332
+ ## Upgrading From `0.8.3` To `0.8.9`
333
333
 
334
- Treat this as one move to the current `0.8.8` surface.
334
+ Treat this as one move to the current `0.8.9` surface.
335
335
 
336
336
  ### What changed across that range
337
337
 
@@ -364,7 +364,7 @@ If your repo copied starter docs or skills, sync:
364
364
  - dry-run one design-steward wave if the repo wants the new authored surface
365
365
  - if the repo uses long-running watcher agents or shell automation, validate `scripts/wave-status.sh` and `scripts/wave-watch.sh` against a live or staged lane
366
366
 
367
- ## Upgrading From `0.6.x` Or `0.7.x` To `0.8.8`
367
+ ## Upgrading From `0.6.x` Or `0.7.x` To `0.8.9`
368
368
 
369
369
  This is the main migration path for older adopted repos.
370
370
 
@@ -405,7 +405,7 @@ pnpm exec wave control proof get --lane main --wave 0 --json
405
405
 
406
406
  If the repo carries proof-first waves, verify that required proof artifacts still exist locally and not only in historical summaries.
407
407
 
408
- ## Upgrading From `0.5.x` Or Earlier To `0.8.8`
408
+ ## Upgrading From `0.5.x` Or Earlier To `0.8.9`
409
409
 
410
410
  Do not treat this as a tiny patch bump.
411
411
 
@@ -515,4 +515,4 @@ For repos that depend on replay parity, replay at least:
515
515
 
516
516
  ## Summary
517
517
 
518
- The current `0.8.8` surface keeps the same authority-set and phase-engine architecture, ships both the design-role starter surface and the signal-driven long-running-agent starter surface, keeps the `0.8.7` policy and routing hardening, and now also packages the practical operator recommendations guide inside the release line. For most repos already on `0.8.x`, the upgrade is package bump plus validation. For older adopted repos, the real work is syncing repo-owned prompts, skills, planner corpus, wrapper scripts, and runbooks so they describe the runtime the package now ships.
518
+ The current `0.8.9` surface keeps the same authority-set and phase-engine architecture, ships both the design-role starter surface and the signal-driven long-running-agent starter surface, keeps the `0.8.7` policy and routing hardening, and now also packages the practical operator recommendations guide inside the release line. For most repos already on `0.8.x`, the upgrade is package bump plus validation. For older adopted repos, the real work is syncing repo-owned prompts, skills, planner corpus, wrapper scripts, and runbooks so they describe the runtime the package now ships.
@@ -561,7 +561,7 @@ Interactive draft currently offers worker role kinds:
561
561
  - `research`
562
562
  - `security`
563
563
 
564
- Agentic planner payloads also accept `workerAgents[].roleKind = "design"`. The shipped `0.8.8` 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.9` 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.
565
565
 
566
566
  ## Ad-Hoc Task Commands
567
567
 
@@ -134,7 +134,7 @@ Practical rule:
134
134
 
135
135
  That means a targeted helper request only blocks while it remains open *and* still has blocking severity in coordination state.
136
136
 
137
- For the practical `0.8.8` recommendation on when to keep records blocking versus when to downgrade them to `soft`, `stale`, or `advisory`, see [../guides/recommendations-0.8.8.md](../guides/recommendations-0.8.8.md).
137
+ For the practical `0.8.9` recommendation on when to keep records blocking versus when to downgrade them to `soft`, `stale`, or `advisory`, see [../guides/recommendations-0.8.9.md](../guides/recommendations-0.8.9.md).
138
138
 
139
139
  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.
140
140
 
@@ -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.8` release procedure publishes through a repository Actions secret named `NPM_TOKEN`.
5
+ The current `0.8.9` 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.8`.
51
+ 5. Push the release commit and release tag, for example `v0.8.9`.
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.
@@ -74,7 +74,7 @@ Practical guidance:
74
74
  - prefer `budget.minutes` for normal synthesis, integration, and closure work
75
75
  - use generic `budget.turns` as a planning hint, not a hard failure trigger
76
76
  - only set `claude.maxTurns` or `opencode.steps` when you deliberately want a hard ceiling for that runtime
77
- - see [../../guides/recommendations-0.8.8.md](../../guides/recommendations-0.8.8.md) for the recommended `0.8.8` operating stance that combines advisory turn budgets with softer non-proof coordination states
77
+ - see [../../guides/recommendations-0.8.9.md](../../guides/recommendations-0.8.9.md) for the recommended `0.8.9` operating stance that combines advisory turn budgets with softer non-proof coordination states
78
78
 
79
79
  ## Runtime Pages
80
80
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "Sample Waves"
3
- summary: "Showcase-first sample waves that demonstrate the shipped 0.8.8 authored surface, including the optional design-role path."
3
+ summary: "Showcase-first sample waves that demonstrate the shipped 0.8.9 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.8` authored Wave surface.
8
+ This guide points to showcase-first sample waves that demonstrate the shipped `0.8.9` 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.8` 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.9` 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.8`:
45
+ Together these samples cover the main surfaces added or hardened through `0.8.9`:
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.8` 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.9` 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,7 @@ 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.8` 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.9` 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
128
 
129
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.
130
130
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chllming/wave-orchestration",
3
- "version": "0.8.8",
3
+ "version": "0.8.9",
4
4
  "license": "MIT",
5
5
  "description": "Generic wave-based multi-agent orchestration for repository work.",
6
6
  "repository": {
@@ -2,6 +2,24 @@
2
2
  "schemaVersion": 1,
3
3
  "packageName": "@chllming/wave-orchestration",
4
4
  "releases": [
5
+ {
6
+ "version": "0.8.9",
7
+ "date": "2026-03-27",
8
+ "summary": "Design-gate report-path preservation, accurate post-design failure reporting, trace-summary alignment, and 0.8.9 release-surface sync.",
9
+ "features": [
10
+ "Reducer snapshots now preserve design packet report paths when rebuilding summaries from result envelopes, so `designGate` no longer reopens as `missing-design-packet` after a successful design pass.",
11
+ "Launcher transitions after design-only passes now stop on the actual design-gate blocker and record a design-specific blocker instead of falling through to a misleading downstream implementation `missing-result-envelope` error.",
12
+ "Trace bundle summary reconstruction now also resolves design packet report paths, so copied trace summaries stay aligned when design summaries are rebuilt from logs.",
13
+ "README, current-state notes, migration guidance, release manifest, tracked install-state fixtures, and the versioned recommendations guide now all point at the `0.8.9` package surface.",
14
+ "Planner migration guidance and the `planner-agentic` bundle placeholder remain part of the shipped current-surface docs so adopted repos still have one aligned upgrade target."
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.9` release surface.",
18
+ "If your repo copied current-surface docs or runbooks, sync `README.md`, `docs/README.md`, `docs/plans/current-state.md`, `docs/plans/migration.md`, `docs/reference/coordination-and-closure.md`, `docs/reference/runtime-config/README.md`, and `docs/guides/recommendations-0.8.9.md` so local guidance matches the packaged release.",
19
+ "If your repo copied trace or replay helpers around design packets, sync the updated reducer, launcher, and trace-summary reconstruction behavior before relying on rebuilt design summaries in replay tooling."
20
+ ],
21
+ "breaking": false
22
+ },
5
23
  {
6
24
  "version": "0.8.8",
7
25
  "date": "2026-03-27",
@@ -500,6 +500,49 @@ function buildGateSnapshot(params) {
500
500
  });
501
501
  }
502
502
 
503
+ export function resolvePostDesignPassTransition({
504
+ waveNumber,
505
+ designGate,
506
+ remainingImplementationRuns,
507
+ currentRuns,
508
+ fallbackLogPath = null,
509
+ }) {
510
+ const nextRuns = Array.isArray(remainingImplementationRuns) ? remainingImplementationRuns : [];
511
+ if (designGate?.ok && nextRuns.length > 0) {
512
+ const nextAgentIds = nextRuns.map((run) => run.agent.agentId);
513
+ return {
514
+ kind: "continue-implementation",
515
+ nextRuns,
516
+ attemptDetail: `Design pass complete; continuing with implementation agents ${nextAgentIds.join(", ")}.`,
517
+ eventMessage: `Design pass complete; launching implementation agents next: ${nextAgentIds.join(", ")}.`,
518
+ coordinationDetails: `next_agents=${nextAgentIds.join(",")}`,
519
+ };
520
+ }
521
+ if (!designGate?.ok) {
522
+ const currentAgentIds = (Array.isArray(currentRuns) ? currentRuns : []).map((run) => run.agent.agentId);
523
+ const blockedAgentId = designGate?.agentId || currentAgentIds[0] || null;
524
+ const detail =
525
+ designGate?.detail ||
526
+ `Design gate blocked wave ${waveNumber}; implementation did not start.`;
527
+ return {
528
+ kind: "blocked",
529
+ failure: {
530
+ agentId: blockedAgentId,
531
+ statusCode: designGate?.statusCode || "design-gate-blocked",
532
+ detail,
533
+ logPath: designGate?.logPath || fallbackLogPath,
534
+ },
535
+ eventMessage: `Design gate blocked wave ${waveNumber}: ${detail}`,
536
+ coordinationDetails:
537
+ `agent=${blockedAgentId || "unknown"}; reason=${designGate?.statusCode || "design-gate-blocked"}; ${detail}`,
538
+ };
539
+ }
540
+ return {
541
+ kind: "no-op",
542
+ nextRuns,
543
+ };
544
+ }
545
+
503
546
  function waveGateLabel(gateName) {
504
547
  switch (gateName) {
505
548
  case "designGate":
@@ -1650,22 +1693,29 @@ export async function runLauncherCli(argv) {
1650
1693
  !isClosureRoleAgentId(run.agent.agentId, roleBindings) &&
1651
1694
  (!isDesignAgent(run.agent) || isImplementationOwningDesignAgent(run.agent)),
1652
1695
  );
1653
- if (designGate?.ok && remainingImplementationRuns.length > 0) {
1696
+ const postDesignTransition = resolvePostDesignPassTransition({
1697
+ waveNumber: wave.wave,
1698
+ designGate,
1699
+ remainingImplementationRuns,
1700
+ currentRuns: runsToLaunch,
1701
+ fallbackLogPath: path.relative(REPO_ROOT, messageBoardPath),
1702
+ });
1703
+ if (postDesignTransition.kind === "continue-implementation") {
1654
1704
  recordAttemptState(lanePaths, wave.wave, attempt, "completed", {
1655
1705
  selectedAgentIds: runsToLaunch.map((run) => run.agent.agentId),
1656
- detail: `Design pass complete; continuing with implementation agents ${remainingImplementationRuns.map((run) => run.agent.agentId).join(", ")}.`,
1706
+ detail: postDesignTransition.attemptDetail,
1657
1707
  });
1658
1708
  recordCombinedEvent({
1659
- message: `Design pass complete; launching implementation agents next: ${remainingImplementationRuns.map((run) => run.agent.agentId).join(", ")}.`,
1709
+ message: postDesignTransition.eventMessage,
1660
1710
  });
1661
1711
  appendCoordination({
1662
1712
  event: "wave_design_ready",
1663
1713
  waves: [wave.wave],
1664
1714
  status: "running",
1665
- details: `next_agents=${remainingImplementationRuns.map((run) => run.agent.agentId).join(",")}`,
1715
+ details: postDesignTransition.coordinationDetails,
1666
1716
  actionRequested: "None",
1667
1717
  });
1668
- runsToLaunch = remainingImplementationRuns;
1718
+ runsToLaunch = postDesignTransition.nextRuns;
1669
1719
  for (const run of runsToLaunch) {
1670
1720
  setWaveDashboardAgent(dashboardState, run.agent.agentId, {
1671
1721
  state: "pending",
@@ -1677,139 +1727,156 @@ export async function runLauncherCli(argv) {
1677
1727
  traceAttempt += 1;
1678
1728
  continue;
1679
1729
  }
1730
+ if (postDesignTransition.kind === "blocked") {
1731
+ failures = [postDesignTransition.failure];
1732
+ recordCombinedEvent({
1733
+ level: "error",
1734
+ agentId: postDesignTransition.failure.agentId,
1735
+ message: postDesignTransition.eventMessage,
1736
+ });
1737
+ appendCoordination({
1738
+ event: "wave_gate_blocked",
1739
+ waves: [wave.wave],
1740
+ status: "blocked",
1741
+ details: postDesignTransition.coordinationDetails,
1742
+ actionRequested: `Lane ${lanePaths.lane} owners should resolve the design packet gap before implementation starts.`,
1743
+ });
1744
+ }
1680
1745
  }
1681
- const implementationGate = readWaveImplementationGate(wave, agentRuns);
1682
- if (!implementationGate.ok) {
1683
- failures = [
1684
- {
1685
- agentId: implementationGate.agentId,
1686
- statusCode: implementationGate.statusCode,
1687
- logPath: implementationGate.logPath || path.relative(REPO_ROOT, messageBoardPath),
1688
- },
1689
- ];
1690
- recordCombinedEvent({
1691
- level: "error",
1692
- agentId: implementationGate.agentId,
1693
- message: `Implementation exit contract blocked wave ${wave.wave}: ${implementationGate.detail}`,
1694
- });
1695
- appendCoordination({
1696
- event: "wave_gate_blocked",
1697
- waves: [wave.wave],
1698
- status: "blocked",
1699
- details: `agent=${implementationGate.agentId}; reason=${implementationGate.statusCode}; ${implementationGate.detail}`,
1700
- actionRequested: `Lane ${lanePaths.lane} owners should resolve the implementation contract gap before wave progression.`,
1701
- });
1702
- } else {
1703
- const componentGate = readWaveComponentGate(wave, agentRuns, {
1704
- laneProfile: lanePaths.laneProfile,
1705
- mode: "live",
1706
- });
1707
- if (!componentGate.ok) {
1708
- if (componentGate.statusCode === "shared-component-sibling-pending") {
1709
- applySharedComponentWaitStateToDashboard(componentGate, dashboardState);
1710
- }
1746
+ if (failures.length === 0) {
1747
+ const implementationGate = readWaveImplementationGate(wave, agentRuns);
1748
+ if (!implementationGate.ok) {
1711
1749
  failures = [
1712
1750
  {
1713
- agentId: componentGate.agentId,
1714
- statusCode: componentGate.statusCode,
1715
- logPath:
1716
- componentGate.logPath || path.relative(REPO_ROOT, messageBoardPath),
1717
- detail: componentGate.detail,
1718
- ownerAgentIds: componentGate.ownerAgentIds || [],
1719
- satisfiedAgentIds: componentGate.satisfiedAgentIds || [],
1720
- waitingOnAgentIds: componentGate.waitingOnAgentIds || [],
1721
- failedOwnContractAgentIds: componentGate.failedOwnContractAgentIds || [],
1751
+ agentId: implementationGate.agentId,
1752
+ statusCode: implementationGate.statusCode,
1753
+ logPath: implementationGate.logPath || path.relative(REPO_ROOT, messageBoardPath),
1722
1754
  },
1723
1755
  ];
1724
1756
  recordCombinedEvent({
1725
1757
  level: "error",
1726
- agentId: componentGate.agentId,
1727
- message: `Component promotion blocked wave ${wave.wave}: ${componentGate.detail}`,
1758
+ agentId: implementationGate.agentId,
1759
+ message: `Implementation exit contract blocked wave ${wave.wave}: ${implementationGate.detail}`,
1728
1760
  });
1729
1761
  appendCoordination({
1730
1762
  event: "wave_gate_blocked",
1731
1763
  waves: [wave.wave],
1732
1764
  status: "blocked",
1733
- details: `component=${componentGate.componentId || "unknown"}; reason=${componentGate.statusCode}; ${componentGate.detail}`,
1734
- actionRequested: `Lane ${lanePaths.lane} owners should close the component promotion gap before wave progression.`,
1765
+ details: `agent=${implementationGate.agentId}; reason=${implementationGate.statusCode}; ${implementationGate.detail}`,
1766
+ actionRequested: `Lane ${lanePaths.lane} owners should resolve the implementation contract gap before wave progression.`,
1735
1767
  });
1736
- } else if (launchedImplementationRuns.length > 0) {
1737
- const reducerDecision = refreshReducerSnapshot(attempt);
1738
- const helperAssignmentBarrier =
1739
- reducerDecision?.reducerState?.gateSnapshot?.helperAssignmentBarrier ||
1740
- readWaveAssignmentBarrier(derivedState);
1741
- const dependencyBarrier =
1742
- reducerDecision?.reducerState?.gateSnapshot?.dependencyBarrier ||
1743
- readWaveDependencyBarrier(derivedState);
1744
- if (!helperAssignmentBarrier.ok) {
1745
- failures = [
1746
- {
1747
- agentId: null,
1748
- statusCode: helperAssignmentBarrier.statusCode,
1749
- logPath: path.relative(REPO_ROOT, messageBoardPath),
1750
- detail: helperAssignmentBarrier.detail,
1751
- },
1752
- ];
1753
- recordCombinedEvent({
1754
- level: "error",
1755
- message: `Helper assignment barrier blocked wave ${wave.wave}: ${helperAssignmentBarrier.detail}`,
1756
- });
1757
- appendCoordination({
1758
- event: "wave_gate_blocked",
1759
- waves: [wave.wave],
1760
- status: "blocked",
1761
- details: `reason=${helperAssignmentBarrier.statusCode}; ${helperAssignmentBarrier.detail}`,
1762
- actionRequested: `Lane ${lanePaths.lane} owners should resolve helper assignments before closure.`,
1763
- });
1764
- } else if (!dependencyBarrier.ok) {
1768
+ } else {
1769
+ const componentGate = readWaveComponentGate(wave, agentRuns, {
1770
+ laneProfile: lanePaths.laneProfile,
1771
+ mode: "live",
1772
+ });
1773
+ if (!componentGate.ok) {
1774
+ if (componentGate.statusCode === "shared-component-sibling-pending") {
1775
+ applySharedComponentWaitStateToDashboard(componentGate, dashboardState);
1776
+ }
1765
1777
  failures = [
1766
1778
  {
1767
- agentId: null,
1768
- statusCode: dependencyBarrier.statusCode,
1769
- logPath: path.relative(REPO_ROOT, messageBoardPath),
1770
- detail: dependencyBarrier.detail,
1779
+ agentId: componentGate.agentId,
1780
+ statusCode: componentGate.statusCode,
1781
+ logPath:
1782
+ componentGate.logPath || path.relative(REPO_ROOT, messageBoardPath),
1783
+ detail: componentGate.detail,
1784
+ ownerAgentIds: componentGate.ownerAgentIds || [],
1785
+ satisfiedAgentIds: componentGate.satisfiedAgentIds || [],
1786
+ waitingOnAgentIds: componentGate.waitingOnAgentIds || [],
1787
+ failedOwnContractAgentIds: componentGate.failedOwnContractAgentIds || [],
1771
1788
  },
1772
1789
  ];
1773
1790
  recordCombinedEvent({
1774
1791
  level: "error",
1775
- message: `Dependency barrier blocked wave ${wave.wave}: ${dependencyBarrier.detail}`,
1792
+ agentId: componentGate.agentId,
1793
+ message: `Component promotion blocked wave ${wave.wave}: ${componentGate.detail}`,
1776
1794
  });
1777
1795
  appendCoordination({
1778
1796
  event: "wave_gate_blocked",
1779
1797
  waves: [wave.wave],
1780
1798
  status: "blocked",
1781
- details: `reason=${dependencyBarrier.statusCode}; ${dependencyBarrier.detail}`,
1782
- actionRequested: `Lane ${lanePaths.lane} owners should resolve required dependency tickets before closure.`,
1799
+ details: `component=${componentGate.componentId || "unknown"}; reason=${componentGate.statusCode}; ${componentGate.detail}`,
1800
+ actionRequested: `Lane ${lanePaths.lane} owners should close the component promotion gap before wave progression.`,
1783
1801
  });
1802
+ } else if (launchedImplementationRuns.length > 0) {
1803
+ const reducerDecision = refreshReducerSnapshot(attempt);
1804
+ const helperAssignmentBarrier =
1805
+ reducerDecision?.reducerState?.gateSnapshot?.helperAssignmentBarrier ||
1806
+ readWaveAssignmentBarrier(derivedState);
1807
+ const dependencyBarrier =
1808
+ reducerDecision?.reducerState?.gateSnapshot?.dependencyBarrier ||
1809
+ readWaveDependencyBarrier(derivedState);
1810
+ if (!helperAssignmentBarrier.ok) {
1811
+ failures = [
1812
+ {
1813
+ agentId: null,
1814
+ statusCode: helperAssignmentBarrier.statusCode,
1815
+ logPath: path.relative(REPO_ROOT, messageBoardPath),
1816
+ detail: helperAssignmentBarrier.detail,
1817
+ },
1818
+ ];
1819
+ recordCombinedEvent({
1820
+ level: "error",
1821
+ message: `Helper assignment barrier blocked wave ${wave.wave}: ${helperAssignmentBarrier.detail}`,
1822
+ });
1823
+ appendCoordination({
1824
+ event: "wave_gate_blocked",
1825
+ waves: [wave.wave],
1826
+ status: "blocked",
1827
+ details: `reason=${helperAssignmentBarrier.statusCode}; ${helperAssignmentBarrier.detail}`,
1828
+ actionRequested: `Lane ${lanePaths.lane} owners should resolve helper assignments before closure.`,
1829
+ });
1830
+ } else if (!dependencyBarrier.ok) {
1831
+ failures = [
1832
+ {
1833
+ agentId: null,
1834
+ statusCode: dependencyBarrier.statusCode,
1835
+ logPath: path.relative(REPO_ROOT, messageBoardPath),
1836
+ detail: dependencyBarrier.detail,
1837
+ },
1838
+ ];
1839
+ recordCombinedEvent({
1840
+ level: "error",
1841
+ message: `Dependency barrier blocked wave ${wave.wave}: ${dependencyBarrier.detail}`,
1842
+ });
1843
+ appendCoordination({
1844
+ event: "wave_gate_blocked",
1845
+ waves: [wave.wave],
1846
+ status: "blocked",
1847
+ details: `reason=${dependencyBarrier.statusCode}; ${dependencyBarrier.detail}`,
1848
+ actionRequested: `Lane ${lanePaths.lane} owners should resolve required dependency tickets before closure.`,
1849
+ });
1850
+ } else {
1851
+ recordCombinedEvent({
1852
+ message: `Implementation pass complete; running closure sweep for ${wave.wave}.`,
1853
+ });
1854
+ const closureResult = await runClosureSweepPhase({
1855
+ lanePaths,
1856
+ wave,
1857
+ closureRuns: agentRuns.filter((run) =>
1858
+ isClosureRoleAgentId(run.agent.agentId, roleBindings),
1859
+ ),
1860
+ coordinationLogPath: derivedState.coordinationLogPath,
1861
+ refreshDerivedState,
1862
+ dashboardState,
1863
+ recordCombinedEvent,
1864
+ flushDashboards,
1865
+ options,
1866
+ feedbackStateByRequestId,
1867
+ appendCoordination,
1868
+ });
1869
+ failures = closureResult.failures;
1870
+ timedOut = timedOut || closureResult.timedOut;
1871
+ materializeAgentExecutionSummaries(wave, agentRuns);
1872
+ failures = annotateFailuresWithRecoveryHints(failures, agentRuns);
1873
+ refreshDerivedState(attempt);
1874
+ }
1784
1875
  } else {
1785
1876
  recordCombinedEvent({
1786
- message: `Implementation pass complete; running closure sweep for ${wave.wave}.`,
1787
- });
1788
- const closureResult = await runClosureSweepPhase({
1789
- lanePaths,
1790
- wave,
1791
- closureRuns: agentRuns.filter((run) =>
1792
- isClosureRoleAgentId(run.agent.agentId, roleBindings),
1793
- ),
1794
- coordinationLogPath: derivedState.coordinationLogPath,
1795
- refreshDerivedState,
1796
- dashboardState,
1797
- recordCombinedEvent,
1798
- flushDashboards,
1799
- options,
1800
- feedbackStateByRequestId,
1801
- appendCoordination,
1877
+ message: "Implementation exit contracts and component promotions are satisfied.",
1802
1878
  });
1803
- failures = closureResult.failures;
1804
- timedOut = timedOut || closureResult.timedOut;
1805
- materializeAgentExecutionSummaries(wave, agentRuns);
1806
- failures = annotateFailuresWithRecoveryHints(failures, agentRuns);
1807
- refreshDerivedState(attempt);
1808
1879
  }
1809
- } else {
1810
- recordCombinedEvent({
1811
- message: "Implementation exit contracts and component promotions are satisfied.",
1812
- });
1813
1880
  }
1814
1881
  }
1815
1882
  }
@@ -10,6 +10,8 @@ import {
10
10
  import { readControlPlaneEvents } from "./control-plane.mjs";
11
11
  import {
12
12
  isContEvalReportOnlyAgent,
13
+ resolveDesignReportPath,
14
+ isDesignAgent,
13
15
  isSecurityReviewAgent,
14
16
  resolveSecurityReviewReportPath,
15
17
  } from "./role-helpers.mjs";
@@ -702,6 +704,11 @@ function resolveRunSummaryPayload(wave, run) {
702
704
  ? path.resolve(REPO_ROOT, wave.contQaReportPath || wave.evaluatorReportPath)
703
705
  : run.agent?.agentId === (wave?.contEvalAgentId || "E0") && wave?.contEvalReportPath
704
706
  ? path.resolve(REPO_ROOT, wave.contEvalReportPath)
707
+ : isDesignAgent(run.agent)
708
+ ? (() => {
709
+ const designReportPath = resolveDesignReportPath(run.agent);
710
+ return designReportPath ? path.resolve(REPO_ROOT, designReportPath) : null;
711
+ })()
705
712
  : isSecurityReviewAgent(run.agent)
706
713
  ? (() => {
707
714
  const securityReportPath = resolveSecurityReviewReportPath(run.agent);
@@ -23,7 +23,10 @@ import {
23
23
  import { buildHumanInputRequests } from "./human-input-workflow.mjs";
24
24
  import { projectLegacySummaryFromEnvelope } from "./result-envelope.mjs";
25
25
  import { buildRequestAssignments } from "./routing-state.mjs";
26
- import { resolveSecurityReviewReportPath } from "./role-helpers.mjs";
26
+ import {
27
+ resolveDesignReportPath,
28
+ resolveSecurityReviewReportPath,
29
+ } from "./role-helpers.mjs";
27
30
 
28
31
  const REDUCER_VERSION = 2;
29
32
 
@@ -37,6 +40,10 @@ function resolveReducerReportPath(waveDefinition, agent) {
37
40
  if (agent.agentId === (waveDefinition.contEvalAgentId || "E0")) {
38
41
  return waveDefinition.contEvalReportPath || null;
39
42
  }
43
+ const designReportPath = resolveDesignReportPath(agent);
44
+ if (designReportPath) {
45
+ return designReportPath;
46
+ }
40
47
  return resolveSecurityReviewReportPath(agent);
41
48
  }
42
49