# PR #21460 runtime-proof fixture matrix (pass 1, read-only audit)

Head 4cc74410d2 | merge-base 8d3b061121 | surface: server only.
Diff = 3 files: `packages/provider-core/src/server/ProviderAdapter.ts` (adds optional `pendingBackgroundWork` to the adapter-level `provider_thread.updated`), `packages/provider-opencode/src/server/v2/adapter.ts`, `apps/server/src/orchestration-v2/Adapters/OpenCode2AdapterV2.test.ts`.

## Findings that shape the matrix

1. **The new field has no consumer at this head.** `ProviderEventIngestor.ts:565` maps `provider_thread.updated` to the domain event `provider-thread.updated` with `payload: providerThread` only, so `pendingBackgroundWork` is dropped. It never reaches `orchestration_events`, projections, WS clients or logs. The only consumer is the stacked PR #21461. On a running server built from this head alone, the snapshot can't be observed. Runtime proof of R1/R2 "snapshot published in order" therefore needs either (a) the adapter event stream (unit/adapter tests, or a debug tap), or (b) the #21461 stack on top.
2. **What a running server *can* see at this head:** extra or reordered `provider-thread.updated` events, plus refreshed `pendingBackgroundTasks` on **intermediate ancestors**. Before: settle → `syncRoster(rootOf(call.state))`, which refreshed the root only. After: `syncRosterAncestors(call.state)`, which refreshes the session itself and every caller up to the root. After the change, `syncRoster` also emits when `publishedBackgroundWork` flips even though the roster is unchanged. This also adds re-emits after started/ended/inbox events, after reconcile, cancel, and wake replay (`runWake`, `takeRunningWake`). The payload difference for these extra emits is `updatedAt` only. Persisted in isolated `statev2.sqlite` `orchestration_events` (type `provider-thread.updated`) and the provider-thread projection.
3. **The earlier evidence's RED test is not in this PR.** `RunExecutionService.test.ts "drains queued child output"` doesn't exist at 4cc74410d2 (grep: no hits). The "baseline drops queued child events" red proof belongs to #21461. The live fs-05 transcript says of itself that it shows "compatibility only, race not reproduced live".
4. **"variant" is not a dimension of the fix.** It's OpenCode's model reasoning variant (`adapter.ts:633-645,1314`, surfaced as `modelSelection.options[{id:"variant"}]`). The tests inject `session.model.selected {variant:"thinking"|"none"}` purely as a **stream-position sentinel**, so the watcher knows the adapter processed everything up to that point. The fix doesn't read it. What actually differs per native thread is that `ThreadState`'s `wakes`, `reports`, `calls` (background flag), `busy` membership, `subagent.call.state` (caller link, used by `syncRosterAncestors`) and `publishedBackgroundWork` are all per-session. Replace "different variant" with **"a session that held a wake while top-level is later called as another session's child"**: its caller chain changes after the wake was queued.
5. **Live OpenCode can't be run on this machine.** `opencode` 1.18.18 is installed, but `status.ts:720` routes only `generation === "v2"` (OpenCode 2.x) to the OpenCode2 adapter changed here, and there are no credentials (`~/.local/share/opencode/` has no `auth.json`). A live run needs OpenCode ≥2.0 with a provider login (earlier evidence used 2.0.32 on fs-05).
6. **Recorded drivers available:** `apps/server/src/orchestration-v2/testkit/fixtures/opencode2_{nested_background,background,inbox,interrupt,resume_after_restart,subagent,...}` (ndjson transcripts), run by `testkit/OpenCodeReplayFixtures.integration.test.ts` through `OpenCode2OrchestratorReplayHarness` (`Adapters/OpenCode2AdapterV2.testkit.ts`) and `ProviderReplayHarness.ts`. Their `output.ts` asserts on domain events, so they **can't see `pendingBackgroundWork`** (finding 1). None of these fixtures is new or changed in this PR, so they serve as regression and compatibility checks. They can't show a before/after difference.

## Matrix

| id | preconditions | stimulus (OpenCode v2 event order) | BEFORE 8d3b061121 | AFTER 4cc74410d2 | where observable | driver | existing coverage |
|---|---|---|---|---|---|---|---|
| R1 | root → foreground middle → **background** grandchild (`subagent_depth=2`) | middle `execution.succeeded`; root `execution.succeeded` (root turn ends, run → waiting); grandchild `execution.succeeded`; `session.inbox.enqueued` on middle (deep report); middle `execution.started` + `inbox.delivered` + text + `execution.succeeded` | adapter emits no `pendingBackgroundWork`. Ancestor (middle) roster isn't refreshed on settle (root only) | adapter `provider_thread.updated` for middle carries `pendingBackgroundWork:true` while the report is queued. Ordered sequence: `running` → `GRANDCHILD_OK` → `completed` → then `false` (last). `hasPendingBackgroundWorkForThread` false after drain | adapter stream only (test). On a server at this head: middle `provider-thread.updated` rows with refreshed `pendingBackgroundTasks` in `orchestration_events`; the boolean is not persisted | **Recorded:** `opencode2_nested_background` replay (same event shape, labels `session.execution.succeeded.2` root end … `session.inbox.enqueued.4`/`execution.started.4` middle continuation). **Live:** needs OpenCode ≥2.0 + creds (not on this box). The continuation-runs outcome passes on baseline too (fs-05 baseline live run; fixture predates PR) | `OpenCode2AdapterV2.test.ts` "keeps a finished background subagent's queued report pending until its native continuation ends" (rewritten in this PR); replay `OpenCodeReplayFixtures.integration.test.ts` › opencode2_nested_background |
| R2 (target of 4cc74410d2) | session OTHER resumed top-level and holds a running wake (its own execution started/succeeded → continuation offered); then root SESSION calls OTHER via the `subagent` tool, so OTHER becomes SESSION's child | root turn ends (`SESSION execution.succeeded`) while OTHER's wake is held → SESSION snapshot `true`; then the continuation turn for OTHER starts (`runWake`/`takeRunningWake` → `replay(wake)`) | after replay only OTHER's own subtree was re-synced (359f713fca); caller SESSION stays `pendingBackgroundWork:true` (red: "expected true to be false") | `syncRosterAncestors(state)` after replay re-syncs OTHER and its caller chain; both OTHER and SESSION publish `false` | adapter stream only; not persisted at this head | **Recorded-in-test only.** Synthetic event list in the adapter test with `makeProviderReplayGate`. No ndjson fixture covers "held wake then called as child". Live repro needs OpenCode 2.x and a precise race (resume → call a session with a held wake), which isn't practical to drive by prompt. **Not runtime-provable at this head** (finding 1). Per the PR body, the `takeRunningWake` call site (adapter.ts:3287) has no test of its own; only `runWake` (3316) is exercised | `OpenCode2AdapterV2.test.ts` "clears the caller's pending work when a called session's held wake runs" (added in 4cc74410d2) |
| R2b (renamed from "variant") | nested background report queued, then **cancelled** during a held wake | `session.inbox.cancelled` on middle for `msg_deep_report` while root's continuation wake is held; continuation turn runs | middle snapshot stays pending / not re-emitted | middle publishes `pendingBackgroundWork:false`; `hasPendingBackgroundWork` false | adapter stream | test-only (synthetic) | "clears a nested report cancelled during a held wake" (added) |
| R2c | reconcile after lost background (stream reconnect) | reconcile path settles calls `interrupted`, discards wakes/reports | roster not re-synced after wake discard | `for session of sessions.toReversed() syncRoster` (descendants before ancestors) emits `false` | adapter stream; `provider-thread.updated` rows with emptied `pendingBackgroundTasks` | recorded: `opencode2_resume_after_restart` / `opencode2_interrupt` replays as compatibility checks only; no test in this PR asserts the reconcile emission | **gap**: no focused test for the reconcile or cancel (`discardWakes` at adapter.ts:3381) `syncRosterAncestors` additions |
| R3 | single-session turn, no subagents/wakes/reports | `execution.started` … `execution.succeeded` | `provider_thread.updated` with no `pendingBackgroundWork` | same events, now with `pendingBackgroundWork:false`. Domain events unchanged except possibly extra `provider-thread.updated` from the post-event `syncRosterAncestors` hook when `publishedBackgroundWork` is first set (undefined → false triggers one emit) | `orchestration_events` count/order of `provider-thread.updated` for the thread; run status sequence | **Recorded:** `opencode2_simple`, `opencode2_tool_call`, `opencode2_question`, `opencode2_permission` replays (output.ts must still pass). **Live:** needs OpenCode 2.x | all OpenCode replay fixtures + existing adapter tests. Worth checking: is the first-event extra emit (undefined≠false) covered by any `output.ts` asserting event counts? |

## Recommended proof at current head
- Scoped: `cd apps/server && vp test run src/orchestration-v2/Adapters/OpenCode2AdapterV2.test.ts src/orchestration-v2/testkit/OpenCodeReplayFixtures.integration.test.ts`. Red for R2: revert only the two `syncRosterAncestors(state)` lines from 4cc74410d2 and rerun the named test.
- Runtime: a server at 4cc74410d2 alone can't expose the published snapshot. Either run the transcript on the #21461 stack, labelled as such, or label any 4cc74410d2-only live run as compatibility only (R1 continuation order + R3 unchanged), with the snapshot ordering proven by the adapter tests.
- Live requires OpenCode ≥2.0 + provider auth (fs-05). This machine has OpenCode 1.18.18 (v1 adapter path) and no auth, so replay fixtures are the only local runtime driver, and they're recorded.
