# Proof audit pass 1 — fixture matrix

PR [#22930](https://github.com/pingdotgg/t3code/pull/22930), mirrored as [#22927](https://git.cafe/pingdotgg/t3code/pulls/22927). Scope: [448b8a9186](https://github.com/pingdotgg/t3code/commit/448b8a918694e84137f850c6526d75aacfb2292d) → [0a986b24eb](https://github.com/pingdotgg/t3code/commit/0a986b24ebe66ef3c28d2c2301832bbd95fd0e33), branch `fix/issue-22886`. Read-only inspection in `/home/ubuntu/wt/pr-22930-after`, 2026-10-21. **All matrix cells are PLANNED / NOT EXECUTED.** This is an evidence specification, not a merge verdict or a claim of visual verification.

## Run dimensions and evidence contract

Every row runs at **1440×900 light, 1440×900 dark, 390×844 light, 390×844 dark** (CSS viewport, device scale recorded). The narrow viewport is responsive **web**, not evidence for native mobile. Run normal-viewer rows in **unified and split** layouts, with wrap on and off for rows 01, 05, 10, 16, 23, 26. Run both **thread right-panel review** and **global Pull Requests page review**; editor round-trip specifically requires an actual in-app file surface and return to the same review surface, not an external editor launch. Where a page cannot open a file surface, record that limitation and perform its equivalent review-surface switch separately; do not count it as an editor round trip.

`S` = short: three files, one small hunk each, one response, fits viewport with tree closed and no annotations. `L` = long: at least eleven files with long, uniquely numbered hunks, three actual diff pages with non-null cursors after pages one and two; load page three and choose a mid-file offset and a near-bottom offset. `H` = huge: synthetic real viewer content whose **logical** height exceeds 30,000,000 CSS px. A visually long file alone does not establish pagination or physical-scroll-window rebasing.

For every `S/L` row run **both**, not one representative. For `L` save offset, first visible path/hunk/line, loaded cursors, folds, selected commit label, condensed header state; for `S` assert top zero and expanded chrome. Record visible context as well as logical offset: preserving raw px can still move the reader to another line after layout changes. Expected pixel drift must be reported, never silently called exact preservation.

**REC** means a continuous recording is required; stills are insufficient. Capture the starting state, trigger, pending/empty/loading phase, and eventual settled state including late pages/highlighter layout. Attach before/after stills as supplements. Navigation rows repeat three times to expose sticky-header drift. Include a small timestamped request/event log alongside the video (fixture revision, head, cursor requests, failures, cancellations and responses), without tokens, private content or pairing URLs. Label every clip with commit, row, viewport, theme, layout, surface, forge mode and fixture revision. Same seeded inputs must be used at base and head for before/after comparisons; a baseline that never reproduces the defect is not proof of the fix.

## Real-app seeding recipes

These are instructions for a later authorized primary-agent run; none was performed here. Use an isolated test checkout and isolated `.t3` state. With its dev server stopped, `vp run migrate-dev-db` makes a one-way read-only snapshot of real stopped projects/threads. Do not run against or write to live `~/.t3/userdata`. Create disposable local fixture files matching patch paths so opening an editor file is meaningful. Open the seeded project/thread and PR through the actual app, not a component harness or a standalone mockup. Bind the same reference to a second stopped thread and expose the global PR page to test scope boundaries.

- **F-S / F-L:** Use an already available read-only test PR with the specified content, or a **STUB FORGE FIXTURE** injected at the provider/service boundary in a disposable environment. Supply schema-valid detail, activity, commits, viewed-files, diff pages and, where required, diff file contents. Keep real app routing, environment RPC, query registry, review store, Pierre viewer, file surface and scrolling. No DOM injection, store injection or hand-built screenshots as integrated proof. A copied thread database does **not** seed remote forge diff responses. For L verify actual pagination requests; do not assume eleven files forces server pagination.
- **F-UPDATE:** Stateful **STUB FORGE FIXTURE** with revisions A and B advanced by the fixture controller, independently of UI. Detail includes valid `updatedAt`, head OID and commit list; activity/check revisions and page content change as each row requires. Serve normal host invalidation/read behavior, and log first-page and tail-cursor responses. Changing only `updatedAt` cannot prove a new commit, new comment or check transition. No real forge writes are needed.
- **F-SLOW:** F-L with controller-held response gates for page one, page two/three and file-content/highlighter readiness. Release explicitly after capturing the pending phase; use event/response completion as the settle criterion. Simulated network delay is labeled. Do not insert arbitrary sleeps into automated tests.
- **F-ERROR / F-RAW / F-EMPTY / F-H:** Provider-boundary stub responses tailored below, retaining the actual app and viewer. RAW uses verified unsupported text or malformed patch and records which parser branch was reached. H verifies `getScrollHeight()` and logical positions, rather than assigning only a fake scrollHeight. Errors use schema-valid provider failures. Fixtures must be sanitized public data for upload.
- **F-WATCH:** In a disposable copied thread, link the test reference and arm the real watch through the app/service workflow, with provider stub pending→settled checks or a new bot remark. Observe the real watch sync/wake and resulting query refresh; block any automatic agent from performing forge writes. A fabricated UI refresh token alone is not proof of a watch wake. If that safe watch configuration is unavailable, label this row blocked and test the client refresh path separately.

## Fixture matrix

All rows inherit the four viewport/theme combinations above. REC applies even to failure, empty and fallback transitions. The “seed” column adds row-specific requirements to the recipes above.

| ID | Render path / fixture | Trigger / steps | Real-app seed | Required observable result | Evidence |
|---|---|---|---|---|---|
| 01 | Normal parsed viewer, S/L, all commits | Explicit PR Refresh from toolbar; repeat from page refresh entry point | F-S/F-L + F-UPDATE A→identical B; L page three already loaded, mixed folds | Files return; logical offset/context, fold choices and chrome restore; all loaded cursors revalidated in order; no permanent zero-file view | REC + request log |
| 02 | Normal viewer, S/L | **Watch wake refresh** while reading Code | F-WATCH + F-S/F-L, checks pending→settled; keep Code active | Show actual wake notification/event and consequent client reads; same code position/folds/commit remain; distinguish watch latency from renderer behavior | REC + watch/event log |
| 03 | Normal viewer, S/L | **New commit**, first page changes | F-UPDATE head A→B, add real commit metadata and changed patch; leave anchored file unchanged in one subcase | New content appears; stable surviving file identity/folds retained; valid saved offset or documented clamp; no stale tail appended | REC + head/cursor log |
| 04 | Normal viewer, L | New commit changes **only page two/three**; page one byte-identical; numeric cursors reused | F-L/F-UPDATE A→B, same page-one response, altered later files and matching detail revision | Refreshed deep content visible, no stale cached pages, saved depth restored; unchanged first page cannot mask changed tail | REC + page content hashes |
| 05 | Normal viewer + inline thread annotations, S/L | **New comment** on anchored file; separately a top-level comment | F-UPDATE activity adds schema-valid comment/thread; patch unchanged; updatedAt advances | Comment appears through real annotation/activity path; code selection/folds/context remain as applicable; measure displacement from annotation height | REC |
| 06 | Normal viewer + review decorations, S/L | **Check status** queued→running→success and failure, without patch change | F-UPDATE checks fields and activity/status revisions; also subcase where host updatedAt stays fixed | Status refreshes; code view stays stable; log whether diff refresh actually happens rather than assuming every check update restarts it | REC + read log |
| 07 | Normal viewer, S/L | Agent-turn **background** refresh while page three is active | Advance real pull-request refresh stream via authorized isolated turn-completion/invalidation path, F-S/F-L unchanged patch | Mounted slices retained; no selection or scroll reset; no duplicate self-cursor fetch loop | REC + refresh-stream log |
| 08 | Normal viewer, L | Background refresh changes first page | F-L/F-UPDATE through background path, replace page one and cursor chain | Changed-page merge drops obsolete tails; new chain loads without mixing old/new files; report preservation limits, not presumed full explicit-refresh behavior | REC + cursor log |
| 09 | Hidden mounted Code tab, S/L | **Tab away/back**: Code→Summary→Code, Code→Timeline→Code, Code→Guide→Code | F-S/F-L; first visit mounts each destination; retain chosen commit and mixed folds | Same Code state on return; other tabs retain their own scrolling; no cumulative sticky drift across three trips | REC |
| 10 | Hidden Code / deferred layout, L | Leave Code, refresh while hidden, return before/after held pages settle | F-SLOW + F-UPDATE; exercise hidden-mounted tab and detached review surface separately | Restoration waits for usable layout; saved target not overwritten by temporary clamp; no late jump after return | REC + gate log |
| 11 | Detached/recreated review surface, S/L | **Editor file round trip**: PR→in-app file tab→same PR, three trips | F-S/F-L plus matching local source files; real file surface, retain same environment/thread/reference | Commit label, fold overrides, toggled files, offset/depth and condensed chrome survive actual detach/remount; quantify line and px drift | REC |
| 12 | Commit-specific viewer, S/L | Select an individual commit; refresh, tab trip and editor round trip | Stub supports actual commit-specific diff and file-content requests, two distinguishable commit patches; select via Code menu and separately Timeline commit | Correct commit **contents and label** survive; a label above an unsupported-diff error is insufficient | REC + commit request log |
| 13 | Commit scope reset, S/L | Switch selected commit→different commit→All commits; remove selected commit from refreshed list | F-UPDATE two commit diffs plus rewritten commit list | Intentional scope switch resets offset/folds to new scope defaults; missing commit returns All commits; stale selection/composer never attaches to new scope | REC |
| 14 | Per-session state isolation, S/L | Same PR in thread A, thread B, global page; PR A→B→A; environment A→B→A | Two copied stopped threads, two fixture references and two isolated environment IDs; seed visibly different choices via UI | No offset/commit/fold leakage across environment/thread/reference/project identity; return to A recovers A's session | REC |
| 15 | Folds / viewed header paths, S/L | Fold via chevron and file-header click; Expand/Collapse All; toggle viewed; then refresh/editor trip | F-S/F-L, viewed flags and permissions available in stub; one viewed and one unviewed file | Stable file IDs keep correct choices; header control clicks do not double-toggle; changed file content updates viewer without resetting unrelated folds | REC |
| 16 | File tree open/closed, S/L | Reveal a folded file from tree; then refresh and round trip; use long path names | F-S/F-L, long nested paths, loaded target and later-page target as separate cases | Tree selection reveals correct file and unfolds once; narrow viewport remains usable; explicit reveal wins over pending saved scroll | REC |
| 17 | Paginated normal viewer, L | Sentinel auto-load; tree “Load more”; then explicit refresh | F-L with three pages, distinct cursor IDs, each boundary visible; tree open and closed | Both pagination entry points append exactly once, count/depth correct; refreshed cursor chain replaces old chain | REC + request counts |
| 18 | Later-page loading/footer error, L | Restore saved page-three depth; fail page two; Retry; separately manual loading failure | F-SLOW/F-ERROR, first page succeeds, later page rejects; retry returns valid page | First-page content retained; no request storm; clamp settles once after failure; Retry works and no stale deferred target overrides subsequent user position | REC + failure/retry counts |
| 19 | Loading and cold layout, S/L | Initial cold load; explicit refresh during pending restore; sequential refresh before completion | F-SLOW; empty cache/cold highlighter; hold and release page responses in a documented order | Loading state resolves; latest restoration retains original target/depth across restart; no stale response contaminates different scope | REC + gate/revision log |
| 20 | Restoration cancellation, L | During held restore, separately wheel, touchmove, pointerdown, native-scrollbar mousedown, viewer keydown | F-SLOW; start saved at page three, return with page two held; each input begins a fresh run | User input cancels pending restore and late pages cannot jump back; latest user position saved for next trip; verify touch at narrow viewport | REC + input/gate log |
| 21 | Find/reveal during restoration, L | Find a match in folded file, keyboard search then navigate result; tree/file reveal while pages pending | F-SLOW with unique marker in folded loaded file and later-page file | Match unfolds/reveals and wins over restore; Find keydown inside viewer cancels; unrelated outside keydown does not cancel viewer restore | REC |
| 22 | Long→short/empty refresh, L→S/empty | New revision removes deep content/pages, then editor trip | F-UPDATE three-page A→one-page B then empty C; at saved bottom with condensed header | Clamp to new max once, stop paging; top-zero expands chrome even without native scroll event; no repeated blank or old position revival | REC + cursor log |
| 23 | Selection preserved on unchanged file, S/L | Select single line and multiline range, left/right diff sides; refresh changing another file; background comment/check update | F-UPDATE anchored file exact bytes/metadata unchanged; selected file remains present while others change | Highlight stays on correct file/side/range when continuously rendered; distinguish background retention from explicit refresh temporarily clearing all files; record any selection loss | REC |
| 24 | Selection/composer invalidation, S/L | Change/remove/rename/type-change selected file during refresh; separately open unsent inline composer before unchanged refresh | F-UPDATE contentVersion-changing patch, removed file, rename and regular-file→symlink identity variants; type distinctive local-only text | Stale anchor clears and cannot submit against wrong content; **explicit unchanged refresh may discard active selection/composer**—record loss as limitation/issue, never label preservation; do not post | REC |
| 25 | Inline threads, drafts, orphans, S/L | Add comment above viewport, resolve/unresolve thread, show orphan panel, pending review comment, then refresh/trip | Stub threads left/right, multiline, outdated or omitted-hunk line and absent path; pending draft through UI without submitting | Correct annotation grouping; updated decorations render; orphan path remains accessible; no accidental fold reset, stale anchor or unexpected scroll displacement hidden by still | REC |
| 26 | Logical scroll window, H | Refresh and three editor trips at logical 570, 20,000,000 and near logical max | F-H real viewer, page depth and verified logical height >30M; record logical offset and actual visible line | No physical-window clamp or sticky-header subtraction drift; report settling drift and lost context separately | REC + logical metrics |
| 27 | Raw-only fallback, short/long raw text | Refresh, tab trip, editor trip | F-RAW no parsed files and terminal cursor null; unsupported text and parser failure tested independently | Raw content readable, toolbar usable; **raw wrapper lacks normal viewer onScroll/restore wiring**, so establish actual position behavior and flag unsupported preservation rather than extrapolate | REC |
| 28 | Mixed parsed/raw/truncated content, S/L | Refresh/round trip, load last page containing raw data or omitted files | F-L plus raw terminal slice, truncated flag and omittedFileStats; parsed file with withheld hunks | Normal viewer, withheld-content notice, raw footer and omitted-count warnings agree; raw fallback not taken before outstanding cursor exhausted; correct context/counts after revalidation | REC + response log |
| 29 | Empty result, PR/commit scopes | Load empty, transition nonempty→empty→nonempty; tab/editor trips | F-EMPTY blank/whitespace patch, no files and null next cursor; separate all-commits and single-commit responses | Correct no-file message, stable toolbar, no stale files/selection; compare top/chrome reset rather than claim meaningful empty scroll restoration | REC |
| 30 | Initial unavailable/error→retry, S/L destination | Fail first page, Retry, then refresh fails first page after deep view | F-ERROR provider forbidden/not-found/unsupported/transient variants routed through actual unavailable component; retry returns F-S/F-L | Error message/retry reachable; saved restore canceled/reset on terminal initial error as implemented; recovery does not revive invalid deep target; document unsupported commit-diff case | REC |
| 31 | Detail unavailable / Suspense / tab fallback | Delay Code module/read; fail detail with no detail; recover and open Code | Isolated cold client plus F-SLOW detail gate and schema-valid detail error, then valid fixture | Detail ghost/unavailable and Code loading remain distinct; no claim of preserved diff while it was never mounted; correct review state after recovery | REC |
| 32 | Session retention boundaries | Open 33 PR review scopes; revisit recent and evicted scope; >2048 file overrides | Stub 33 distinct references, separate H fixture with 2049 selectable file identities; set through app UI or label as supplemental logic-only if impractical | 32-session and 2048-toggle caps intentional; recent state retained, oldest can reset; distinguish bounded session retention from browser-reload persistence | REC for app interaction; logic test supplement |
| 33 | Browser focus/visibility refresh, S/L | Browser tab away/back after ≥10s since last refresh; separately resume after ≥6m idle | F-UPDATE + real focus/visibility/interaction lifecycle; capture eligibility clock/log; manual timing permitted for evidence, do not bake sleeps into tests | Observe real `useLiveRefresh` detail read and whether updatedAt triggers full refresh; Code position stable; distinguish from in-app tab switch and watch wake | REC + timing/event log |
| 34 | Desktop shell and remote web, S/L | Repeat rows 01, 02, 11, 12 against remote environment; desktop app file round trip | Same isolated fixture environment exposed via supported dev sharing; authorized primary uses real desktop shell/remote web and documents transport; no baked localhost URLs | Verify actual client/connection provenance; web-only footage cannot establish Electron shell behavior; remote destination retains correct state scope | REC |

## Derivation and acceptance limits

The [Code tab](https://github.com/pingdotgg/t3code/blob/0a986b24ebe66ef3c28d2c2301832bbd95fd0e33/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx#L1449) has loading, unavailable, raw-only, empty, and normal virtualized viewer returns. Normal rendering additionally includes inline annotations, orphan conversations, file tree, paginated footer errors/loading, raw footer and withheld content. Rows 01–34 enumerate these branches and the transitions relevant to preservation; error states are guardrails rather than promises of persisted positions.

The [detail panel](https://github.com/pingdotgg/t3code/blob/0a986b24ebe66ef3c28d2c2301832bbd95fd0e33/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx#L538) increments explicit refresh on qualifying activity revisions and host refresh, whereas the Code tab's background token comes from the environment turn refresh stream. A watch wake, a window-focus read, a check update and an in-app tab switch are distinct triggers. Capture which chain actually ran; merely clicking Refresh cannot substitute for all four.

The [scroll controller](https://github.com/pingdotgg/t3code/blob/0a986b24ebe66ef3c28d2c2301832bbd95fd0e33/apps/web/src/components/pullRequest/pullRequestCodeScroll.logic.ts#L10) stores raw logical offset/page depth, not a semantic line anchor. The [review store](https://github.com/pingdotgg/t3code/blob/0a986b24ebe66ef3c28d2c2301832bbd95fd0e33/apps/web/src/components/pullRequest/pullRequestReviewStore.ts#L29) persists selected commit/folds/scroll/chrome in memory per environment/thread/reference, not across browser reload. DOM line selection and active composer live locally in the Code component; they are not stored with this session state. During explicit refresh slices become empty and anchor validation can clear them even when eventual contents are unchanged. Rows 23–24 specifically prevent overclaiming selection preservation; this is a source-derived risk, not a newly reproduced bug.

Existing [logic tests](https://github.com/pingdotgg/t3code/blob/0a986b24ebe66ef3c28d2c2301832bbd95fd0e33/apps/web/src/components/pullRequest/pullRequestCodeViewState.test.ts) cover many state-machine cases, but fake scroll surfaces do not prove actual Pierre layout, shadow DOM interaction, annotations, native scrollbars or highlighter settlement. No tests were run in this matrix-only pass. The current PR description reports web/GitCafe Refresh, editor and commit-label evidence, acknowledges deep-scroll drift, and explicitly excludes integrated GitHub pagination, failed pages, huge offsets and commit contents on GitCafe. Those are author-reported bounds; media was not inspected here and does not mark any cell passed.

Native mobile has separate rendering and no changed files in this diff; this matrix does not claim native iOS/Android coverage. Agent runtime adapters and wire contracts are unchanged. Forge provider capabilities do matter: GitCafe's unsupported commit-specific diff cannot satisfy row 12; use a labeled stub or an already-existing supported read-only GitHub fixture. Stub-forge clips prove app behavior under controlled responses, not live host compatibility. End-to-end watch evidence requires the real watch path, not only stubbed client tokens.

## FRICTION

- **Machine mismatch:** `~/.agents/MACHINE` reads `freestyle`; requester expected `fs-17`. No marker or host configuration changed. Evidence runner should resolve provenance before claiming execution on fs-17.
- **CLI PATH:** initial `cafe` invocation returned `command not found`; adding `~/.bun/bin` and `~/.local/share/vite-plus/bin` exposed the installed CLI. Read-only metadata then confirmed mirror [#22927](https://git.cafe/pingdotgg/t3code/pulls/22927), head matching the requested revision. No forge writes or CI reruns.
- **Scope:** no browser/server launch, computer use, fixture installation or visual check was authorized for this pass. This deliverable specifies future seeds and recordings only. No production state read or copied.
- **Evidence gaps:** raw-only fallback uses another scroller without the normal viewer save callback; selections/composers are not retained session state; commit-label-only footage cannot establish commit content; semantic position can drift despite raw offset restoration. These require explicit evidence or bounded claims.
- **T3 bookkeeping:** registered the requested PR with this thread as required by the harness; this is app-owned metadata, not a forge write. No watch was started.
- **Upload:** only this sanitized Markdown matrix is uploaded via the requested ghdrop skill. Repository unchanged; artifact lives outside the repository.

Prepared with GPT-6.1-sol through the Codex harness, read-only proof audit.
