# Proof audit, pass 1

PR [#28195](https://git.cafe/pingdotgg/t3code/pull/28195), branch `fix/issue-28178`, reviewed head [9e4299152e](https://git.cafe/pingdotgg/t3code/commit/9e4299152ede4514520d37791b603e2613095d51) against merge-base [15fe283272](https://git.cafe/pingdotgg/t3code/commit/15fe2832727893cbdd2214383f9f971474849695).

Scope: evidence planning only. All six changed files and the PR description (`data.resource.description`), inline feedback, reviews, and head checks were read. No app, browser, simulator, provider, or tests were launched. No captures or new runtime transcripts exist in this pass. PR-reported tests and runtime output are reported evidence, not independently verified artifacts. The working tree was clean at entry. Do not change the reviewed head while capturing without updating this matrix.

## Findings first

1. **Evidence is incomplete by design.** The description reports a real Codex before/after run, but explicitly has no attached screenshots and no mobile verification. It also leaves the budget and uncertain-delivery reasons unverified at runtime. The head integration test covers a simulated Claude resume failure and handoff-before-user ordering, not visual rendering. A passing test or a screenshot of a fabricated divider cannot substitute for the real Codex recovery pair.
2. **Ordering has two distinct outcomes.** A free run-start position places the divider above the recovered user message. An occupied position appends after the current maximum. Capture both an occupied position with a visible first item and an orphan reservation with no visible first item; these produce different timelines. Do not describe “above the user message” as unconditional.
3. **Retry deserves separate evidence.** Allocation occurs before the event-write transaction, and the derived item ID contains a newly allocated handoff ID. If that write fails and a retry reaches recovery again, the old reservation can survive while a new ID appends. This is consistent with the existing CodeRabbit finding after inspecting the implementation; it was not reproduced here. V7 shows the resulting layout; S6 must distinguish an actual failed-write retry from a synthetic occupied-slot fixture. A synthetic SQL reservation alone does not prove retry behavior.
4. **The row is an existing neutral divider, not a new summary card.** The new item is `status=completed`, has exactly one source provider and one destination, and carries `strategy=full_thread_summary`. Neither client displays `title="Recovered context"` or the summary. `contextHandoffId` is a data association, not a clickable summary link in these renderers. The web endpoint interaction is a provider/model tooltip; the native endpoint interaction is an account alert.

## Trace and branch inventory

Source links below are pinned to the reviewed head.

| Layer / caller | Branches and data that matter to proof | Matrix coverage |
| --- | --- | --- |
| [EffectWorker](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/EffectWorker.ts#L141) → `ProviderTurnStartService.start` | Two production call sites: `provider-turn.start`, and `provider-turn.restart` after interrupt/detach/replace handling (line 373). User dispatch, queue/scheduled/agent intake ultimately use these service paths; there is no recovery-divider button, setting, palette item, keybinding, or separate transport implementation. | R1, S1; restart equivalence S4. |
| [ProviderTurnStartService](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/ProviderTurnStartService.ts#L1223) | Native ref null → ordinary fresh thread; native fork path → separate fork behavior; resume succeeds and handoffs fit → no recovery item. Pending matching-native delivery bypasses resume → `uncertain_history_delivery`; failed resume → `resume_failed`; successful resume, old budget fails, fresh budget fits, no pending background work → `handoff_budget_exhausted`. If fresh budget also fails, it keeps the resumed thread; if background work/subagents block replacement it errors. A stale/non-starting attempt exits; failed fresh-thread creation exits/errors before the new item. | C0, S1–S4. All three positive reasons share the exact new event construction. |
| [Recovery item construction](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/ProviderTurnStartService.ts#L1328) | Latest earlier run on the **same provider-thread row** supplies one `fromModelSelections` entry; no such run supplies `[]`. Source provider IDs still have length one. Destination model is explicit. Item has current run/root node/provider thread, null provider turn/native ref/parent, equal start/completion/update timestamps, completed status, full-thread strategy, summary and handoff ID. There is no new loading/running/failed item-state branch; later provider failure does not recolor this completed item. | V1–V5, S4. Metadata shape assertions in S1–S3. |
| [TurnItemPositionStore.allocate / normalize](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/TurnItemPositionStore.ts#L44) | Existing `(thread,item)` ID returns its existing ordinal immediately, regardless of requested placement. Otherwise supplied run ordinal wins, then DB run ordinal, then the runless bucket. Bucket is `runOrdinal*1,000,000` through `+999,999` (runless 0…999,999). Default/explicit `append` is max+1, or base+1 when empty. `run_start` takes base when empty or when min>base; min=base appends max+1. SQL/no-row failures are tagged allocation errors. | V1, V6, V7, S5, S6. |
| Position-store callers | New caller: recovery construction requests `run_start`. Existing direct caller: [RunExecutionService](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/RunExecutionService.ts#L1441) reserves held streaming assistant/reasoning items with default append. [EventSink.normalizeEvents](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/EventSink.ts#L332) calls `normalize` for every turn-item update; normalize calls allocate with default append and reuses the already reserved recovery ID/ordinal. There are no other production allocate/normalize callers. | R1, S5. |
| [runtimeLayer](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/runtimeLayer.ts#L164), two unit-test harnesses, integration test | Adds the SQL-backed position-store dependency to the turn-start layer; tests supply it. Runtime startup is covered by a real recovery run. The changed tests have no independent renderer or UI states. The new integration test asserts handoff existence and first two run-item types `[handoff,user_message]`; the new allocator test asserts base placement, occupied-slot append and subsequent append. | S1, S5. No extra screenshot for DI/test code. |
| Event persistence → wire → clients | New handoff, transfer, and turn-item events are written together. Pre-allocation is outside that write. [WireProjection](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/server/src/orchestration-v2/WireProjection.ts#L154) strips handoff `summary`; contracts already accept the shape. `itemSupport` resolves the linked handoff/transfer. Snapshot/history and live event paths preserve the item; ordinal, not the later event timestamp, governs its placement. | R1, S1–S3, S6. Verify snapshot and live delivery, not just SQLite. |
| Web timeline | [session-logic](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/web/src/session-logic.ts#L297) treats handoff as a standalone event; `MessagesTimeline` → `V2EventTimelineRow` → [V2LifecycleRow](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/web/src/components/chat/V2LifecycleRow.tsx#L78) → `EnvironmentHandoffRow` → `HandoffRow` → `TimelineSystemDivider` / `HandoffEndpoint`. The other `V2LifecycleRow` call site is inside a group already filtered to subagents, so handoff cannot reach it. `resourceSummary`/`onOpenThread` do not alter the handoff branch. Handoffs are exempt from superseded-attempt folding. | V1–V7, R1, R2. Desktop uses this same web path; no Electron-specific divider branch. |
| Other web HandoffRow caller | [ChatView footer](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/web/src/components/ChatView.tsx#L3120) supplies `pending=true` for a predicted provider switch. This new recovery item never passes `pending`. Footer and recovery divider can coexist when a different *next* provider is selected. Same-provider recovery alone must not create a pending footer. | R1 no-duplicate check; E1 explains inherited preview states. |
| Mobile timeline | [threadActivity](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/mobile/src/lib/threadActivity.ts#L938) flushes handoffs into standalone singleton activity groups; they remain visible when work folds. [ThreadFeed](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/mobile/src/features/threads/ThreadFeed.tsx#L1729) → `ThreadHandoffRow` → [ThreadHandoffDivider](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/apps/mobile/src/features/threads/thread-handoff-row.tsx#L48) → `ThreadContextDivider` / `HandoffEndpoint`. Non-handoff/null endpoints return null, but a valid new handoff resolves endpoints even with missing runs. `environmentId` selects metadata, `iconColor` and `surfaceColor` select theme/icon contrast. | V1–V7, R1, R2. |
| Other mobile divider caller | ThreadFeed footer at line 3697 renders `Context handoff pending` from `pendingHandoff`. It is not a status of the new completed item. Multi-activity groups cannot select ThreadHandoffRow; grouping intentionally prevents that state for handoffs. | R1, E1. |
| [Shared endpoint resolver](https://git.cafe/pingdotgg/t3code/blob/9e4299152ede4514520d37791b603e2613095d51/packages/client-runtime/src/handoff.ts#L44) | Nonempty explicit source selections win. Empty/missing selections map source IDs to the latest earlier run for that provider instance; no matching earlier run leaves source model undefined. Destination uses explicit `toModel`, otherwise matching handoff run's model (the new producer always supplies it). Zero sources suppress the arrow; multiple sources add comma separators, but this producer always yields one source, including when previousRun is missing. | V1, V3, V4; E1 excludes unproduced cardinalities. |
| Endpoint metadata / counts / lengths | Web: known slug → short model label (and sub-provider qualifier removal); unknown nonempty model → trimmed raw model; absent/empty model → provider display name, then instance ID. Mobile: known slug → short name/name; otherwise raw model, then provider display name/ID. Metadata/config missing uses raw labels/fallback icons, without a spinner. Web has provider-colored model text; native uses muted text. Badge appears for accent color or multiple matching accounts, subject to enabled-instance and ACP agent grouping. Badge/no-badge, known/raw/provider-only labels, and short/overflow lengths are the layout distinctions; individual model names and provider logos are equivalent representatives. | V1–V4, R2. Disabled historical account or configured ACP/icon URL uses the existing same endpoint branch; no new recovery-specific icon pipeline. |
| Width/theme/platform | No divider media-query or viewport prop exists. Web uses wrapping flex containers and truncating labels; mobile uses flex wrapping and single-line shrinking labels. Theme tokens control label, separator, icon/background colors. iOS uses native SF Symbols / native alert; Android uses Tabler fallback symbols and its alert implementation. Web/desktop share DOM rendering. Local, relay and tunnel connections carry identical IDs/shape; no URL/origin is added. | Wide light/dark V1; narrow/long V2/V4; iOS and Android V1/R2. No exhaustive provider × theme × connection Cartesian product. |
| Interactions and time | Divider has no expand, summary action, elapsed timer or active animation. Web endpoint spans are keyboard-focusable tooltip triggers; hover/focus shows account + model and moving/blurring dismisses. Mobile endpoint Pressable opens account alert and dismissal returns to the same timeline. Live insertion above an already shown user message, completion, folding, history loading and reconnect/reopen are ordering/persistence interactions, so use recordings. Metadata arrival can change raw to short labels and must be recorded if that transition is claimed. | R1, R2; V4 is a *stable missing-metadata* still, not proof of a loading transition. |

## Named fixture matrix

Every row starts **missing** in pass 1. “Affected” refers to this diff, not whether renderer code changed. A reused renderer branch can be exercised by the newly emitted data. Stills are sufficient only for stable states. Synthetic projection fixtures and harness captures must be labelled in the image/video and manifest; they do not prove native recovery. Transcripts must contain actual queried items/positions plus the corresponding log/event record, not only a test-pass count.

Capture targets (CSS points at DPR 1 for web; logical points for native): `W-L` = Chromium 1280×800 light; `W-D` = Chromium 1280×800 dark; `W-N` = Chromium 390×844 dark; `I-L` = iOS portrait 393×852 light; `I-D` = same dark; `A-D` = Android portrait 412×915 dark. Device dimensions may be the closest available, but record the actual dimensions, scale, OS and theme. Pair before/after with identical dimensions, theme, sidebar/panel state, scroll position and message text; hide developer panels that differ by branch.

| ID / named fixture | Input / expected appearance | Affected by diff? | Minimum evidence (viewport × theme × row) | Real-app seed or labelled alternative | Pass-1 status |
| --- | --- | --- | --- | --- | --- |
| B0 — baseline recovery | Two remembered-word turns; native resume fails on turn 3; recovery answers correctly but main has **no divider** between turns 2 and 3. | Before control for the bug. | **Still**, W-L and I-L; corresponding head frames are V1. | Run the same real Codex procedure on the pinned merge-base with a separate fresh dev home. After two completed turns, stop its server, repoint only the target provider-thread native ID to a valid-format unknown ID, restart and dispatch turn 3. Preserve reason log and sorted items. Never use live userdata. | MISSING stills; prior PR prose is not an artifact. |
| C0 — normal/no recovery | Initial fresh turn and an ordinary successful continuation have no recovery item/divider. | Default append is unchanged; negative control. | **Server transcript**, no extra viewport. Can be collected during B0/V1 setup. | Same real dev thread before corruption; query items after turns 1 and 2. For successful native resume specifically, stop/restart without corruption before continuing. | MISSING transcript. |
| V1 — ordinary completed recovery | One known short source model → one known short destination model, normally same Codex model; no account badge; completed neutral divider **above** turn-3 user text, preceding turn-2 reply visible. | Yes: item presence and free-slot ordering. | **Stills**, W-L + W-D + I-L + A-D. W-L/I-L pair with B0. Native can attach to the same recovered server data; do not run extra paid turns just for theme/client variations. | Real Codex repro from B0 at reviewed head. Set theme in Appearance; open `/<environmentId>/<threadId>` on web, and select the same environment/thread in mobile's thread route (params `environmentId`, `threadId`). Use a configured valid Codex model; record the exact model. | MISSING all four head stills. |
| V2 — different long models, badged account, narrow lane | Explicit previous-run model A differs from destination B. Use long known display labels and/or a long unknown historical source slug (48–80 chars); account badge enabled by accent or a second matching account. Divider/endpoints wrap or truncate without overlap/clipping. | Yes: new endpoint fields can produce this shape; styles reused. | **Stills**, W-N + A-D. Record the exact label lengths and resulting wrap/truncation. | Real app: change model on the same provider-thread row before forcing resume recovery, and set account appearance/another matching instance in Providers. For deterministic long historical names/badges, copy the real V1 item into the dev projection with only endpoint/model/config changes while stopped; label **renderer fixture**, or use a temporary renderer harness outside the worktree. Do not submit an invalid long destination slug to Codex. | MISSING stills. |
| V3 — no previous source model | `fromModelSelections=[]`, exactly one source ID, and no earlier source-provider run available. Source renders provider display name (or ID) → known target model; arrow remains present. | Yes: explicit previousRun-absent branch. | **Stills**, W-L + I-L. | A renderer/projection fixture based on V1, empty explicit source selections and omit earlier source-provider runs from the fixture projection. Normal two-turn repro cannot create this shape; native/import reachability is not established here. Label **partial-history renderer fixture**. A separate resolver transcript may cover the “earlier instance run exists” case because it looks like V1. | MISSING labelled harness/fixture stills. |
| V4 — metadata unavailable | Keep nonempty model strings in the item but remove matching provider/model metadata. Raw source/destination slugs and fallback icons replace short labels; account-ID tooltip/alert fallback. Use long slugs to expose truncation. | Newly emitted historical item can outlive metadata; no new loader UI. | **Stills**, W-N + I-D, stable metadata absent. If demonstrating metadata arrival instead, it is a **recording**. | Isolated renderer fixture with provider/config list empty or without that instance. Real app alternative: remove the provider instance after V1 in the dev environment and reopen historical thread, if allowed by app settings; do not alter hub credentials. Label harness if config is injected. | MISSING stills. |
| V5 — recovery plus existing same-run handoff | Existing switch/merge-back handoff already at base+1, user at next append slot; recovery takes base. Two distinct divider rows appear in order: recovery, existing handoff, user. | Yes: insertion relative to already allocated handoff/user, not only a lone message. | **Stills**, W-L + I-L; transcript includes both item IDs and ordinals. | Use the server integration-harness pattern: establish A, establish B, return to A with pending provider-switch/merge-back handoff, detach A and force its resume failure. Render the actual output through the app using isolated fixture state, labelled **adapter harness**, unless both real providers are available. Same-provider model change alone need not create the existing switch divider. | MISSING labelled capture + transcript. |
| V6 — run-start occupied by a visible item | Another handoff owns base; user/other items already follow. New recovery appends at max+1, so one divider is before the user and a second is after it. Later assistant append stays after recovery. | Yes: occupied-slot fallback. | **Stills**, W-L + I-L; positions/items transcript. | Deterministic server/allocator harness: allocate message, first run-start item, second distinct run-start recovery, then reply; emit matching handoff items and render resulting projection. There is no app action explicitly requesting “recover twice in this run.” Label **slot-collision harness**; don't claim it happened naturally. | MISSING labelled capture + transcript. |
| V7 — run-start occupied by an orphan reservation | Position at base exists but has no visible turn item; user at base+1; recovery with a different ID appears **below** the user (max+1). This is distinct from V6's two visible dividers. | Yes; represents failed-write retry risk. | **Stills**, W-L + I-L; positions-vs-items transcript. A claimed retry sequence additionally requires S6. | Real-app artificial trigger: with dev server stopped after two turns, reserve the known next run's base in `orchestration_v2_turn_item_positions` under a unique synthetic item ID, then corrupt native ID and restart/send turn 3. Label **synthetic orphan reservation**. Alternatively render allocator/harness output. This proves the slot-taken layout only. | MISSING labelled capture + transcript. |
| R1 — live insertion and persistence | Start with recovered turn's optimistic/committed user message; recovery event arrives above it; stream/settle answer; collapse/expand previous work; leave/reopen or reload; handoff remains once, in correct order, with no spurious same-provider “pending” footer. Scroll/load earlier if history paging is exercised. | Yes: live new event, chronology, folded and snapshot paths. | **Recording**, W-L + I-L. Can supply settled V1 frames from these recordings if resolution and framing match. A still cannot prove insertion/reconnect/folding. | Real V1 repro, start recording **before dispatching turn 3**, then carry through completion and reopen. For older-window loading, create enough fixture history to page and load the recovered run; label any synthetic paging data. Record metadata arrival too if it occurs. Existing failed/interrupted/superseded attempt work may be included without changing the handoff's completed style. | MISSING recordings. |
| R2 — endpoint interactions | Hover each web endpoint, focus each with keyboard, dismiss; tooltip contains account and model. Native tap each endpoint, show account alert, dismiss, return unchanged. Repeat at least one unknown/badged endpoint from V2/V4 to verify fallback/full account label behind truncation. No summary-detail navigation is expected. | Newly visible affordances; interaction code reused. | **Recording**, W-L + I-L + A-D. Native platform alerts differ. | Drive the existing endpoint controls in V1 and V2/V4. No server mutation is required. For V4 record fallback account ID. Do not present a tooltip/alert still as proof of its opening/dismissal behavior. | MISSING recordings. |
| S1 — resume_failed | Failed native resume; fresh native ID; completed recovery item matches recovery handoff ID/strategy; item is at base and before user; answer still recalls marker. | Yes. | **Server transcript**, shared with V1/R1; no extra screenshot. Include B0 comparison. | Real Codex unknown-native-ID repro. Log must show `reason: 'resume_failed'`, plus error tag, run/provider IDs. Query sorted turn items, matching handoff, transfer, and replacement native ID. Recollect current artifacts; PR description alone is not proof. | MISSING independently retained transcript. |
| S2 — handoff_budget_exhausted | Resume **succeeds**; nonempty pending history fails old native budget, fits fresh budget; no background work. Same divider shape as V1 (or V5 if a switch item exists), fresh native ID. | Yes: same new emission for second reason. | **Server transcript**, no distinct visual. Reuse V1 shape. | Prefer deterministic server harness using existing exhausted-target scenarios: old target usage e.g. 30,000/32,000, enough current pending history to fail old budget but fit fresh. Confirm the actual reason log; a huge message alone may fail both budgets and never recover. Real app can seed dev provider-thread `contextUsage` while stopped, then switch back with pending context; provider telemetry may override it. Label harness when synthetic adapter/telemetry is used. | MISSING reason-specific transcript. |
| S3 — uncertain_history_delivery | Existing handoff has `delivery.status='pending'` and delivery native ID exactly matches target native ref. Resume is bypassed, fresh native recovery is selected; same V1 shape. | Yes: same new emission for third reason. | **Server transcript**, no distinct visual. | Real dev SQL fixture: obtain a real handoff first, stop server, mark its delivery pending with matching `nativeThreadId`, preserving valid delivery item arrays/shape. Restart and send next turn. Or use existing integration harness injection-failure scenario (fail injection acknowledgement once, then retry). Query/log must show `uncertain_history_delivery`, not resume_failed. Label injection/SQL fault as such. | MISSING reason-specific transcript. |
| S4 — no-emission/error guards | Native-null ordinary start; resume success/fit; old and fresh budgets both fail; pending background/subagent work blocks replacement; stale/not-starting attempt; fresh `ensureThread` fails. No *new recovery* item for these exits. If recovery was committed then later turn start/delivery fails, its item stays completed/neutral beside ordinary error UI. | Guard behavior unchanged; boundaries of the new write matter. | **Server transcript** with item counts/status and reason/error records; no new divider visual beyond C0/V1. | Deterministic adapter/service harness using existing budget/background/refused-start scenarios and controlled stale attempt/fresh ensure failure. Start/restart effect callers share the same service; transcript one restart path if that is claimed. Do not imply every run failure suppresses an already committed divider. | MISSING boundary transcript. |
| S5 — allocation invariants | Empty bucket/free base; nonempty bucket/free base; occupied base; default/explicit append; same-ID reuse despite changed placement; supplied vs stored vs runless ordinal; EventSink normalization preserves reservation; later assistant/reasoning append does not collide. | Yes for placement; legacy defaults regression control. | **Position/item transcript or focused allocator harness output**, no extra UI. Include concrete input→ordinal records, not only “tests passed.” | Existing allocator tests cover several cases. Read/execute a temporary driver using the real position store against an in-memory/isolated DB for remaining variants; no production edits. Run ordinal 2 example: message 2,000,001; recovery 2,000,000; second new run-start 2,000,002; reply 2,000,003. Empty runless run-start is 0; default empty append is 1. | MISSING runtime allocation transcript; code/test assertions inspected only. |
| S6 — failed recovery write and retry | Force failure **after** position reservation and **before** the three-event recovery write commits, then allow retry. Distinguish existing-ID reuse from newly allocated handoff/item IDs; record any orphan slot and actual rendered ordinal. | Yes; specific retry risk in finding 3. | **Server transcript** of fault/worker retry plus positions/items/events. If showing sequence in client, **recording**, W-L; V7 supplies stable outcome coverage. | Controlled service/EventSink fault-injection harness outside production code, using the real allocator and retry path; no public RPC toggles this failure. Use a Deferred/event/worker drain for milestones, not sleeps. Show whether the next attempt reaches recovery and whether a new ID appends. Mark **fault-injection harness**. Never replace this with a manually seeded slot and claim it validates retries. | MISSING fault/retry transcript; static concern only. |
| E1 — inherited states not emitted here | Zero/multiple source endpoints (no arrow / comma list); missing destination model fallback; failed/red handoff; pending footer; no-handoff guard returning null; non-singleton mobile group; summary/title length/emptiness; resourceSummary/onOpenThread variants; every provider-logo asset. | No new producer branch for these states. The new item is completed, one-source, explicit destination. | **No additional capture required** for this diff. R1 checks no duplicate footer; existing switch divider may appear in V5. | Do not fabricate these as “native recovery” cases. The new handoff summary is removed from wire and not displayed; summary length does not create a card or expanded state. Existing failure/pending renderer styles may be smoke-tested separately but are outside the minimum. | EXCLUDED with code rationale. |

Minimum set is exactly B0, C0, V1–V7, R1–R2, S1–S6 above; compatible rows can share artifacts when the manifest names every covered assertion. Do not multiply S1/S2/S3 by themes: their visual producer is identical. Do not require separate screenshots per provider, transport or desktop wrapper when output/DOM is identical. Keep one real Codex proof; deterministic adapter/projection captures cover rare shapes with explicit labels. If native devices are unavailable, a native renderer harness can cover geometry only and must be labelled; it does **not** satisfy real native alert/interaction recordings R2. Report the missing native proof rather than quietly substituting a responsive web screenshot.

## Seeding and transcript handoff

Use the task's already isolated dev runtime or one fresh, explicit dev home. Let migrations run once, stop it by its captured PID/session before direct SQL, and read the actual `statev2.sqlite` path from that runtime. The documented SQLite helper takes `--base-dir <isolated-home>`, one statement per invocation, and makes a backup. Never write `~/.t3/userdata`, never set baked-in web origins, and never change CLIProxyAPI hub settings or delete a real Codex rollout. Record each run into a new timestamped directory below the capturer's own `/tmp/lead-28195-r1/<step>/`.

The production-compatible driver can use authenticated `orchestration.dispatchCommand` (`thread.create`, `message.dispatch`, plus appropriate project setup) and `orchestration.getThreadProjection` / `orchestration.subscribeThread`; use contract-typed commands and await persisted terminal events. The existing integration harness demonstrates create/dispatch/detach/drain calls. Inspect runtime RPC availability and auth through the approved app skill; this audit has not connected to an app or generated credentials.

For the documented Codex failure seed, scope this single-statement template to the exact dev thread and provider-thread row. Supply a unique valid-format native ID Codex never created; preserve the ref's other fields. Parameterize SQL in the eventual driver rather than interpolating untrusted input:

```sql
UPDATE orchestration_v2_projection_provider_threads
SET payload_json = json_set(payload_json, '$.nativeThreadRef.nativeId', :unknown_native_id)
WHERE thread_id = :thread_id AND provider_thread_id = :provider_thread_id;
```

This is an intentional fault seed in an ephemeral projection. Do not rewrite the event log or use the seeded projection itself as evidence that recovery ran. After restart, query the new output/events and the fresh native ID. A replay/rebuild can erase direct projection fixtures; verify that the injected native ID is still present before dispatch. For V7, derive next run ordinal from actual stored runs; reserve exactly that bucket base while stopped, with a unique synthetic item ID. A branch/rollback can leave ordinal gaps, so do not assume “third prompt” always means ordinal 3.

Use these read-only query shapes for an actual transcript (bind the real IDs; they deliberately do not print private summary text):

```sql
SELECT ordinal, type, status, turn_item_id, run_id,
       json_extract(payload_json, '$.contextHandoffId') AS context_handoff_id,
       json_extract(payload_json, '$.fromModelSelections') AS from_models,
       json_extract(payload_json, '$.toModel') AS to_model,
       json_extract(payload_json, '$.strategy') AS strategy
FROM orchestration_v2_projection_turn_items
WHERE thread_id = :thread_id
ORDER BY ordinal, turn_item_id;
```

```sql
SELECT p.ordinal, p.turn_item_id, i.type, i.status
FROM orchestration_v2_turn_item_positions p
LEFT JOIN orchestration_v2_projection_turn_items i
  ON i.thread_id = p.thread_id AND i.turn_item_id = p.turn_item_id
WHERE p.thread_id = :thread_id
ORDER BY p.ordinal, p.turn_item_id;
```

```sql
SELECT context_handoff_id, target_run_id, to_provider_thread_id, strategy, status,
       json_extract(payload_json, '$.transferId') AS transfer_id,
       json_extract(payload_json, '$.delivery.nativeThreadId') AS delivery_native_id,
       json_extract(payload_json, '$.delivery.status') AS delivery_status
FROM orchestration_v2_projection_context_handoffs
WHERE thread_id = :thread_id;
```

Also preserve the matching context-transfer ID/resolution, replacement provider-thread native ID, and the actual `Recovering provider context in a fresh native session` log with reason/errorTag/run IDs. Check that all three recovery events committed together and that the handoff's source/destination IDs agree with the item. The real before/after control should show the same recall answer and fallback reason, with only head adding the row. Keep server logs/driver output separate from screenshots and redact credentials before uploading.

For V2–V7, seed from a schema-valid app-written V1 item. If changing a turn-item ordinal in a projection fixture, keep its SQL ordinal, payload ordinal, and position-store row consistent. Include valid related thread/run/node/provider/handoff records; use the existing app's fresh rows as templates. Direct fixture projection writes establish renderer geometry only; business-behavior proof must come from actual service commands/events. A temporary harness must live outside the worktree and must not monkey-patch client DOM after render.

Capture manifests should state row IDs, base/head SHA links, native or harness, fixture mechanism, real route, viewport/theme/platform/scale, and associated query/log artifact names. Keep auth tokens, pairing URLs, account secrets and unrelated real-user content out of uploads. Upload stills/recordings/transcripts with ghdrop; no PR comments or edits were authorized for this step.

FRICTION: none
