# Proof audit pass 1: minimum fixture matrix

Scope: [#24914](https://git.cafe/pingdotgg/t3code/issues/24914), [b76a110aa4](https://git.cafe/pingdotgg/t3code/commit/b76a110aa4) → [38ffe0a923](https://git.cafe/pingdotgg/t3code/commit/38ffe0a923). Full seven-file diff and changed callers inspected read-only. No edits, servers, browser/device sessions, tests, forge operations, or existing screenshots inspected. This is a matrix verdict, not a verdict that captures or implementation have passed.

## Seed contract

Use isolated real-app state only. Parent already reproduced async request + foreground sleep, with sidebar Working and no question at baseline; reuse that recipe, without needing to inspect that screenshot. For live seed A, have the provider call the exposed async user-input tool with a harmless two-choice question, then run a foreground shell sleep long enough to capture. Verify the server shell contains a user_input request with blocking:false and a running active run. Do not use a background sleep: it can end the foreground turn. Use distinct titled threads and projects for grouping; long titles/project names exercise truncation. Keep a quiet control project to avoid status aggregation contamination.

| Seed | How to seed the real app / raw state required |
|---|---|
| A | Live recipe above: running + pendingRuntimeRequest.kind=user_input + blocking:false. Must yield Working and hasPendingQuestion:true; not hasPendingUserInput. |
| N | A separate foreground long-running command with no user-input request. Working, no added question marker. |
| B | Provider's blocking user-input tool, leave unanswered. Raw user_input with blocking:true. Awaiting Input/Input, no secondary marker. |
| L | Legacy input request with blocking omitted. Prefer an existing compatible provider path; otherwise insert this exact raw shell through an isolated app fixture source. Same result as B. |
| C | Let A's foreground turn finish with its async question unanswered. Raw nonworking run + blocking:false pending question becomes Awaiting Input/Input, not Working + marker. |
| D | Answer A while foreground work continues, then let work complete. Pending request clears: Working without marker, then normal Done/Completed or visited ready. Use another unvisited thread for visible Completed. |
| G | A with an active goal, through real goal creation: redesigned web/mobile label Goal retains question marker. |
| P | Approval, pending child approval/input, or guest request produced through the app's real flows; overrides Working in the pill resolver. If coexistence cannot be produced legitimately, raw-shell fixture only, explicitly labeled. |
| E | Raw-shell fixtures for preparing/starting/queued/running/waiting, blockedOnThreadWait, missing optional flag. Feed raw server-shaped shells through presentThreadShell rather than setting hasPendingQuestion by hand. |

For deterministic mobile static fixtures, use the actual app navigation, stores, contracts, presentThreadShell and ThreadListV2Row on EAS iOS. Supply A/N/B/L/C/D/G raw V2 shells with fixed IDs, active/latest run IDs, dates, request IDs and request kind/blocking as above; include enough run/message data for normal list status/duration. Selection must come from the actual selected thread key. This is a **real-app static fixture**, not live provider proof. Do not substitute a standalone component render. First try an isolated fixture backend/projection source connected to the full client. If no such source can seed the requested state, an app-store injection is **HARNESS ONLY**, and must be labeled in every asset/caption. It supplements rather than replaces the parent's live web reproduction.

## Minimum state/path matrix

“Affected” means the changed branch can alter that surface. “Recording” is mandatory for time/interaction rows; a still cannot prove them. Static rows may share a whole-app frame if all targets remain readable.

| ID | Caller / conditional | Seeds | Affected / expected result | Capture / recording |
|---|---|---|---|---|
| W1 | Redesigned sidebar card, active and inactive rows | A,N,B,C,D | Yes: A Working + existing timer + indigo question icon; N no question; B/C Input with no extra icon; D normal completion. Row accessible label adds `, question waiting` only to A. | Whole app 1440 and 390, light/dark. Open mobile-width sidebar; pointer away from row. |
| W2 | Same card, Goal label | G | Yes: Goal + timer + question; accessible name also says question waiting. | Include G beside W1; no separate theme/width pass. |
| W3 | Same card hover/focus, snooze menu, sweep and drag status-slot gates | A | Yes, conditional visibility: status hides for hover/focus controls/menu/sweep; drag replaces slot. No clipping or persistent lost marker after exit. | RECORD desktop pointer/focus/menu and applicable sweep/drag, enter → exit. A static capture taken while hovering is invalid evidence of missing marker. |
| W4 | Redesigned sidebar slim variant | A or legitimately settled/snoozed control | Shared accessible-name computation affected, but slim branch has no added visual marker. Do not promise parity with card. If active A cannot legitimately remain slim, mark that combination unreachable. | One control view + accessible-name inspection; may be a frame in W3. |
| W5 | Legacy sidebar thread row → ThreadStatusLabel full | A,N,B,C,D | Yes: A sky Working dot plus indigo question dot; tooltip/role-img name `Working · Question waiting`. Controls retain one status dot and normal labels. | Whole app 1440/390 × light/dark. At 390 `hidden md:inline` hides visible label, but this remains the full component branch. |
| W6 | Legacy overflow “Show more” → ThreadStatusLabel compact | A + hidden N | Yes: two compact dots, min-width replaces fixed width; same expanded tooltip/accessible name. | Whole app 1440/390 × light/dark. Project expanded, overflow present, thread list NOT expanded, A among hidden rows. This is not a collapsed-project-header pill. |
| W7 | Legacy overflow aggregate winner / equal-priority tie | A,N,P | Yes: only winning pill contributes its questionDotClass. Higher-priority approval/input/guest/failure hides Working; equal Working statuses preserve the first winner (existing `>` comparison). A-first gives marker; N-first can hide it. | RECORD reorder/winner change, hover compact tooltip, Show more → Show less. One theme/desktop width sufficient; include observations, do not assume aggregate means “any question”. |
| W8 | CommandPaletteThreadItems → ThreadRowLeadingStatus → ThreadStatusLabel full | A,N,B,C,D | Yes: second full-pill caller, separate layout constraint with search title/subtitle/PR status. Same new dots/name; visible label hides below md. | Whole app palette open, 1440/390 × light/dark, query matching fixture titles. |
| W9 | Full and compact Tooltip branches | A,N | Yes: question waiting text only A; aria-label is identical for full/compact. Decorative dot has no text of its own. | RECORD hover/focus tooltip open/close in legacy full, overflow compact and palette; inspect accessibility attributes. One desktop appearance sufficient. |
| M1 | HomeScreen → ThreadListV2Row card, screen pane | A,N,B,C,D,G | Yes: A/G Working/Goal + timer + questionmark.bubble; N/B/C/D no added bubble. Unselected uses adaptive indigo. | Whole EAS iOS app, static fixture, light/dark; include all readable control rows. |
| M2 | HomeScreen primary sidebar pane OR ThreadNavigationSidebar → card | A duplicated into two threads + controls | Yes: selected icon uses selectedThreadRowColors.iconTintClassName; unselected uses adaptive indigo. Both callers must be visited, even if they look identical. | Whole EAS iOS app, selected and unselected A visible together where possible, light/dark. Capture each reachable caller/pane; use supported split width if needed. |
| M3 | Mobile card selected:false vs true transition | A | Yes: tint changes with selection; no missing symbol, wrong row reuse, or timer collision. | RECORD select another row and return on EAS iOS. Static fixture proves tint/layout only; it does not prove answering a live question. |
| M4 | Mobile slim variant; Woke/statusLabel/time fallback | D + settled/snoozed controls | No added symbol in slim (cardContent is not used). In card Woke occurs only ready; normal status/no-status branches must not gain bubble. | Include one slim and one ready/Woke control in static list; record expand/collapse shelf only if needed to expose it. |
| T1 | Live request appears while foreground work continues | N → A | Yes: Working stays Working; marker appears; elapsed duration continues. | RECORD actual whole web app, at least two timer values and question UI visible after selecting thread. |
| T2 | Answer while active | A → D(active) → D(completed) | Yes: marker disappears when request resolves, Working continues until completion, no stale mark after navigating away/back. | RECORD answer + continued work + finish. Do not use static fixture as runtime proof. |
| T3 | Run finishes before async answer | A → C → answered | Yes: Working+marker changes to normal Input/Awaiting Input; answering clears it. | RECORD separate unanswered run. |
| T4 | Blocking vs legacy blocking controls | B,L | No Working+question marker; question UI behaves as blocking. | One live B control recording; L can be fixture/data assertion if no provider can emit legacy omission. |
| S1 | presentThreadShell runtime gates | E | preparing/starting/running set hasPendingQuestion only for nonblocking user_input; nonworking/queued/waiting set hasPendingUserInput for pending async input. Non-user request/null never gains flag. | Data/assertion transcript, no screenshot multiplication. No sleeps/polling in tests. |
| S2 | resolveThreadStatusPill precedence and optional field | E,P | Approval/child approval → Input/child input → Guest precede Working; waiting runtime branch differs from projection runtimeIsWorking; blocked running → Waiting unless prior input wins. Preparing/starting/queued → Connecting. Missing/false hasPendingQuestion adds nothing. Failed/Plan Ready/Completed/null remain unchanged. | Focused data assertions/transcript; combine with W7 visual winner check. Do not inject impossible combinations and call them live. |

## Minimum capture set and packing

1. Before/after matched whole-web-app stills at **1440×900 and 390×844**, light and dark, in each of four layouts: redesigned sidebar cards (W1/W2), legacy full rows (W5), legacy overflow Show more (W6), and command palette (W8). That is **16 head frames + 16 base frames = 16 labeled pairs**. Seed the same readable A/N/B/C/D controls; G fits redesigned cards. If height cannot show controls readably, add frames rather than shrinking/cropping the app. Keep narrow sidebar open. Theme means the normal palette in light/dark, not an unrequested all-palette expansion.
2. EAS iOS static full-app before/after stills, light/dark, for the screen-list caller and navigation-sidebar caller, plus the Home primary-column pane if it requires a distinct width/navigation layout: **at least 4 head + 4 base frames**, or **6 + 6** when the primary-column pane is distinct. Both selected and unselected A must be visible in each relevant selection-enabled layout; otherwise add a selection frame per appearance. Record actual device/logical width; retain phone-width evidence, and use a supported wider iOS layout for primary-column coverage rather than faking an unreachable phone pane. Do not claim 390 CSS pixels equals native screenshot pixel width. These captures are explicitly static fixture proof, not provider execution.
3. Minimum **two live web sequences per revision**: (a) N→A, timer progress, tooltip/palette/navigation, answer while still Working, finish; (b) A→C, answer, plus blocking B control. Use one appearance/desktop width; static width/theme pairs cover styling. Long idle gaps may be trimmed, but label cuts and retain continuous segments around transitions.
4. One additional web interaction recording per revision can combine W3/W4/W7/W9: card controls restore, full/compact tooltip, overflow winning-status changes and expand/collapse. One EAS iOS selection/navigation recording per revision covers M3/M4. If main recordings already show all these steps readably, no separate file is required.
5. A short raw-shell/data transcript covers S1/S2 and legacy omission. Capture accessibility names separately; still images cannot prove them. A provider-state transcript plus live videos establishes projection→UI behavior. Base active A should lack the new marker while remaining Working; controls should match head.

All before/after captions must identify revision, app surface/caller, theme, viewport/device, seed IDs and whether live, static real-app fixture, or HARNESS ONLY. Whole app means the complete viewport/device screen, not a component gallery or cropped icon.

## FRICTION

- Current audit intentionally did not capture evidence, run tests, check EAS access, or validate seed execution. Parent owns subsequent capture work. Existing baseline reproduction is acknowledged, not independently audited here.
- Repository showcase is not an async-question fixture switch: EXPO_PUBLIC_SHOWCASE=1 prepares capture/navigation behavior; scripts/mobile-showcase-environment.ts seeds V1 projection_threads/projection_thread_sessions. Do not assume it seeds the V2 pendingRuntimeRequest states needed here. A compatible isolated V2 fixture source must be supplied and verified in the actual client. No new CLI flag or ready-made injection API is claimed.
- Selected mobile styling depends on actual route/selectedThreadKey and pane. Selection may navigate away on phone; preserve a real sidebar route or supported wider iOS layout, and record it. If impossible in the requested static app mode, report selected-path coverage missing; a standalone row harness does not close that gap.
- Compact overflow aggregation can suppress the indicator when an equal-priority no-question Working thread is first, or a higher-priority status wins. This is an observation to report, not a conclusion that this diff fixes project-wide discoverability.
- Web/mobile slim rows do not render the new visual marker. Matrix includes them explicitly; whether product intent requires a marker there is a separate scope decision.
- EAS availability, installed head/base native artifacts and fixture connectivity remain unverified. Do not silently substitute local simulator, Android, or a component gallery for the requested EAS iOS static mode.
- No PR was opened/worked, no forge state read/written, no merge/watch, no checkout changes. Only this public-safe matrix is uploaded using ghdrop; no tokens, startup pairing URLs, screenshots, or customer data are included.

**VERDICT: SUFFICIENT for matrix.** Every changed presentation condition and render caller is mapped, with theme/width/selection coverage, real-app seed intent, explicit fixture limitations, and mandatory recordings for time/interaction behavior. This verdict does not certify capture completion or bug-fix correctness.
