# Proof audit, pass 1 — PR 27882

PR: [#27882](https://git.cafe/pingdotgg/t3code/pull/27882), mirrored as [#27882](https://github.com/pingdotgg/t3code/pull/27882).

Checkout: /home/ubuntu/wt/pr-27882, branch fix/issue-27821. After: [c60e8ba864](https://github.com/pingdotgg/t3code/commit/c60e8ba864784e06d9270bd1643b3256682fd0b0). Before: [cb9629e689](https://github.com/pingdotgg/t3code/commit/cb9629e6891ef0745772b69f09c9acd0c6a74f7e), verified merge-base against origin/main. Local checkout and live GitCafe metadata match. This pass derives fixtures only and certifies no screenshots or recordings.

## Findings

1. **Evidence is missing for every affected fixture.** The current PR body explicitly identifies older before/after revisions, [26dc3688e2](https://github.com/pingdotgg/t3code/commit/26dc3688e2) / [bcf47b6896](https://github.com/pingdotgg/t3code/commit/bcf47b6896), uses relative GitCafe attachments, and says seed/driver scripts are available on request. Those assets do not satisfy the requested current-revision, public, reproducible evidence gate. They were not reused as proof.
2. **Two render sites change.** Error with shownCount > 0 adds the environment prefix to the warning below rows. Error with shownCount === 0 adds it to the centred unavailable description. Loading/capability guards precede the centred error; warning and pagination are independent siblings. shownCount is counted after grouping, filtering and overrides, not the raw result count.
3. **Real seed constraints:** B needs a loaded serverConfig and a non-scratch project before being stopped. Otherwise B can be absent from capableEnvironments/environmentQueries and never fail the list query. Use different repository canonical identities on A and B: duplicate repositories are assigned to one environment. Different directories alone do not prevent deduplication.
4. **Keep REAL and HARNESS honest.** A directly paired stopped server proves web fan-out/error labels, not T3 Connect relay wording. Labels come from friendly machine name/hostname; two servers on one host can have the same label. Record actual descriptor labels and IDs. Do not silently inject “Remote B” or a relay message into a capture called real-app.
5. **No implementation defect established in this scoped inspection.** The helper retains the first failure in target iteration order, with ID and message from that same target, continues collecting available values, and preserves waiting/refresh behavior. This is not a merge-readiness verdict. No browser, server or test ran in pass 1.

## Code-derived render and caller inventory

All source links are pinned to the audited head.

- [Merged-query helper and four factories](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/state/pullRequests.ts#L537): list, listStats, filterOptions, turnRefreshes. Input is an array of { environmentId, input }. Zero targets yields values=[], error=null, pending=false. Each target can be Initial, Success or Failure and independently waiting/settled. isPending ORs all waiting flags. First Failure in target order supplies the changed object; later failures do not replace it. AsyncResult.getOrElse collects available/previous success values. Refresh deduplicates atoms, with optional override targets. No layout lives here.
- [All consumers](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/state/pullRequests.ts#L604): usePullRequestList returns the changed error. Its only production component caller is PullRequestsPage, in five roles: visible list, baseline, facets, authored and reviewing partitions. Only visible list.error is formatted/rendered. baseline.error is checked against null for baselineEmpty; facet/partition errors are not printed. usePullRequestListStats and usePullRequestTurnRefreshes discard helper.error. usePullRequestFilterOptions returns it, but Author/Label choices only compare against null and retain fixed “Couldn't search … on the host” text. Single-environment usePullRequestTurnRefresh follows a different unchanged read.
- [Page caller and route](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/routes/_chat.pull-requests.tsx#L76): PullRequestsPage has no props. Its sole mount is /_chat/pull-requests, public path /pull-requests. Sidebar and command palette “Open pull requests” navigate there. The chat/thread PR panel is a separate component. Settings supplies connection/theme state, not another page error render.
- [Scope and labels](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/components/pullRequest/usePullRequestListView.ts#L56): presentations with non-null serverConfig are sorted by environmentId. Server/project filters and repository assignment determine query targets. environmentLabels comes from the same presentations, so missing current-target labels are not normal stable app states. Descriptors require nonempty trimmed labels and server label resolution has nonempty fallbacks. Missing/empty labels require labelled H fixtures. map.get(id) || “Environment” gives identical output for missing and empty strings; whitespace-only labels are outside the descriptor shape.
- [Main list branch order](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/components/pullRequest/PullRequestsPage.tsx#L1135): (1) capability unknown -> 7 ghosts + Loading caption; (2) unsupported -> fixed unavailable message, no Retry; (3) firstLoad -> 7 ghosts + caption; (4) listError and shownCount=0 -> changed centred error with Retry; (5) carriedToNothing -> 7 ghosts without caption; (6) shownCount=0 -> normal empty component; (7) otherwise -> groups. firstLoad means pending with listData=null, so it can suppress an error while another target is pending. Retained empty data plus a failure can show busy centred Retry; pending with no data instead shows ghosts. Current scope logic makes known capability imply a capable target, so the explicit unsupported branch is not a normal stable real-app state.
- [Normal empty branches](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/components/pullRequest/PullRequestListEmptyState.tsx#L59): no projects -> Add project; searching with query -> 5 ghosts/search caption, query display truncates after 48 chars; settled query -> no matches, Clear search and Check again; otherwise -> No pull requests/Nothing under these filters, optional Load more and Check again. refreshing/loadingMore change disabled/labels. These are unchanged and bypassed by the changed error. Filters/overrides can make shownCount zero despite nonempty underlying rows.
- [Warning and pagination](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/components/pullRequest/PullRequestsPage.tsx#L1197): warning iff listError && shownCount>0, independent of pending, appending “Showing the last pull requests loaded.” Banner Retry stays enabled while pending. Footer independently requires listData.truncated && entries.length>0, not shownCount: pending -> Updating pull requests when sentCursors=null, otherwise Loading more; settled -> Load more when canContinue or pageSize<500, otherwise Narrow your search. Load more is disabled while pending/showingCarried. These unchanged sibling modes do not change warning markup or prefix selection; no separate pagination gallery is required.
- [Unavailable props](https://github.com/pingdotgg/t3code/blob/c60e8ba864784e06d9270bd1643b3256682fd0b0/apps/web/src/components/pullRequest/PullRequestsUnavailableState.tsx#L8): default title=Could not load pull requests, error description, optional onRetry, refreshing disables Retry/sets aria-busy/refresh icon, optional host external link. The PR changes only error at the list-error call. Unsupported call passes fixed title/error only. Other callers in PullRequestDetailPanel, ThreadPullRequestsPanel and RightPanelSurfaceContent are unchanged, including their host/title variants.
- **Counts/lengths:** zero vs positive shownCount is the error-layout threshold. One vs many rows/groups moves the warning vertically; use one healthy row to keep it in frame. Group labels/counts, multiple capable environments (row labels), multiple hosts (provider badges), selected rows, stats and optimistic/sweep states change rows but not the modified message. Long label + breakable message plus a long endpoint segment exercises wrapping/overflow. Empty/whitespace Error.message or non-Error causes use the existing “The environment request failed.” default.
- **Theme/width/platform:** no explicit theme/platform branch surrounds the modified text. Theme changes semantic colors; both normal layouts need light/dark. WorkspacePageContainer is max-w-6xl with px-5/sm:px-6. Empty has p-6/md:p-12 and max-w-sm header. PullRequestsColumn has a container breakpoint for search, scrolling/condensed header and overflow-x-hidden. Narrow web at 390x844 is a normal web viewport, not native mobile. Split detail panels narrow the list; maximized makes it zero width/inert. Electron changes titlebar/native-control reserve and shortcut context, but uses this same error DOM. Native mobile is unchanged. No separate platform capture is required; record actual list-column width.
- **Interactions:** typing/debounced 250 ms search/Enter; server/project/host/state/involvement/filter/sort changes; both Retry buttons; header Refresh (invalidation then list/stats); Load more/cursors and turn-refresh collapse; live visibility/focus/interval/activity refresh; row selection/detail tabs/open/close/maximize/resize; row actions/close sweep; shortcuts/clipboard; condensed search/Ctrl-Cmd-F. Required recordings below cover failure via search, Retry and excluding B, plus controlled first-error handoff. The unchanged pagination, automatic refresh, row-action and panel flows are inventoried without becoming extra requirements. Any flow claimed as additional proof must be a recording.

## Seed plans

New IDs P01–P09 deliberately replace the old F-row checklist. Every affected fixture is missing in pass 1.

**REAL S:** the capturer creates a new timestamped run directory under /tmp/lead-27882-r1/proof-audit-1/ (or a separately explicitly assigned capture scratch root). Start exactly two isolated dev servers A/B with T3CODE_DEV_SEED=0, distinct explicit --home-dir paths inside the run and separate free ports; read actual dev-runner output. Keep logs/PIDs there. No live database copy/migration, VITE_HTTP_URL or VITE_WS_URL, or audited-checkout edits. Pair the client with A normally; /settings/connections -> Add environment with B's fresh pairing URL adds B to that same client. Agent “Linked environments” peer linking is not client pairing.

Create one non-scratch project on each server through Add project or authenticated projects.mutate RPC: type=project.create, fresh commandId/projectId, title, workspaceRoot. Use distinct repository canonical identities. B can use a separate local fixture repo with no remote; A must use a permitted public repository with a real visible PR. No provider turns. Wait for both configs/project shells and verify both target IDs before stopping B by its captured PID. A's host CLI needs usable forge auth: record that precondition; if unavailable, report infra rather than relabeling mock rows as REAL. The two servers may share a machine label; do not change global machine configuration to manufacture distinct labels.

Leave B enabled/saved and trigger a fresh query. P01 settles with a matching A row. P02 retains all servers and uses a fresh query proven to yield no A matches; wait until pending clears and B fails. B-only all-failed scope without carried data is an alternate way to the same settled centred layout. Do not remove/disable B to simulate failure, since that removes its target. Record actual labels/messages; a direct failure does not demonstrate relay-specific wording. Keep the same public PR/query/data across Before/After and record enough returned seed data to explain any live drift.

**HARNESS H:** mount the real PullRequestsPage, route and shipped CSS at each exact revision, supplying deterministic environment scope/presentations and per-environment AsyncResult atoms at the boundary. Keep createMergedEnvironmentQuery, formatEnvironmentQueryError, page formatting and both error renderers real. Do not substitute warning markup or an already formatted merged error. Same boundary inputs work on both revisions: helper naturally returns string Before and object After. For impossible label-map subcases only, override returned environmentLabels while retaining B in targets; document it. Label every output HARNESS with the reason. Use full valid PullRequestListResult shapes (entries/providers/viewers/errors/truncated/nextCursors), contract-shaped entries, stable dates and logged raw inputs. Existing test answer/entry factories are examples, not a UI driver.

H long label: “Remote build workstation — release engineering — west coast”.
H long message: “Relay could not reach the environment endpoint (endpoint_request_failed). The saved endpoint remote-build-workstation-west-coast.example.test is unavailable. Check that the environment is running and try again.”
This wording is synthetic and cannot be presented as a real relay run.

## Minimum affected matrix

D=1440x1000, N=390x844, DPR 1. Same explicit theme/fonts/viewport/sidebar/panel/data/scroll per Before/After pair. Normal rows use panel closed and one visible healthy PR or zero rows. Any transition below requires recording; still strips are insufficient.

| ID | Fixture and exact branch/data | Affected | Real seed or labelled harness | Minimum viewport × theme × row / medium | Status |
| --- | --- | --- | --- | --- | --- |
| P01 | Named failure beside rows: A Success with one visible PR, B Failure with nonempty message, settled, known/supported. After adds B label + colon; suffix/Retry retained. | Warning text | REAL S, all servers/new search after B stops. Actual transport error and descriptor label; live healthy A rows suffice, cached rows are not required. | D × light and dark × P01: 2 Before/After still pairs | MISSING |
| P02 | Named failure without rows: A Success empty (or B-only all-failed), B Failure, pending=false, shownCount=0. Changed description under Could not load pull requests, Retry. Error beats ordinary No matches/No projects. | Centred text | REAL S, all-server no-match query settled. No data vs empty successful data share this settled visual. | D × light and dark × P02: 2 still pairs | MISSING |
| P03 | Narrow long warning: P01 shape, H long label+message, positive shownCount; inspect complete text, wrapping, horizontal clipping and Retry. | Warning wrapping | HARNESS H for controlled arbitrary label/message. Narrow viewport itself is real-app capable. | N × dark × P03: 1 still pair | MISSING |
| P04 | Narrow long centred error: P02 shape, same H long label/message; inspect title, description wrapping and Retry. | Centred wrapping | HARNESS H for synthetic long content. | N × light × P04: 1 still pair | MISSING |
| P05 | Fallback warning: B absent from label map, then B maps to empty string. Both yield Environment: + message and suffix. Same visual output for these inputs. | Warning fallback | HARNESS H; B remains failed query target. Driver logs/checks both inputs; one representative visual suffices. | D × dark × P05: 1 still pair | MISSING |
| P06 | Fallback centred error: same missing/empty map subcases, shownCount=0. Environment: + message in description. | Centred fallback | HARNESS H; impossible stable presentation/target mismatch as above. | D × light × P06: 1 still pair | MISSING |
| P07 | Rows failure/retry/recovery: healthy list -> stop B -> type/submit query retaining A row -> failure -> banner Retry -> repeat failure -> Filters > Server > A -> warning gone, A row retained. Banner Retry stays enabled pending; no minimum spinner duration assumed. | Failure text plus recovery control | REAL S. Actual controls/events; settled P01 checkpoints may be included. | D × dark × P07: Before/After RECORDING pair | MISSING |
| P08 | Centred Retry: P02 -> Retry -> pending -> named error returns -> choose healthy A -> ordinary empty result, error gone. Pending may keep empty data and busy/disabled Retry, or show ghosts if no data. | Centred text/pending error | REAL S actual no-match query/Retry. Do not artificially hold RPC while claiming REAL; if a transient is too short, state that limit and optionally add separate labelled H segment. | D × light × P08: Before/After RECORDING pair | MISSING |
| P09 | First failure/default: ordered targets A,B,C, A row stable. C fails with Error("C unavailable"), then B fails with whitespace Error.message, B recovers, then C uses non-Error cause. Expect C -> B/default -> C -> C/default. First target failure, not first by time; ID/message stay paired. | Error object identity and prefix | HARNESS H. Two-server setup cannot give controlled C or arbitrary Cause shapes. Feed raw atoms, not mocked merged error. Blank/non-Error defaults have identical output shape. | D × dark × P09: Before/After RECORDING pair with settled checkpoints | MISSING |

Minimum: eight Before/After still pairs (P01/P02 twice each, P03–P06 once) and three Before/After recording pairs (P07–P09). Theme/width combinations are not multiplied across every string variation. Matching video frames may serve corresponding settled stills if configuration/pixels match and the manifest identifies them; recordings remain mandatory for P07–P09.

## Unchanged paths accounted for

| State/context | Seed feasibility | Medium if claimed as proof | Status and collapse |
| --- | --- | --- | --- |
| No targets/unknown config; first pending/no data; error while another target pending | Real initial connection/navigation; H for deterministic interleaving. Current unsupported guard needs H. | Loading/arrival: RECORDING; fixed unsupported H: still | CODE-TRACED, unchanged; relevant error/pending boundary in P08. |
| No projects; successful empty; empty filters; settled query; clear/search/carry ghosts | Real project/query/filter flows; H for exact debounce/carry timing | Settled: still; any search/carry/clear: RECORDING | CODE-TRACED, unchanged; ordinary empty recovery in P08. |
| Groups/counts/row environment/provider labels; selection/stats/overrides/sweep | Suitable real public rows, H for deterministic grouping/stats | Settled: still; action: RECORDING | CODE-TRACED, unchanged; representative P01/P07 row sufficient. |
| Footer absent, Load more ready/disabled, Updating, Loading more, 500-row limit; footer with errors | Real high-PR repo/Load more; H for exact cap/cursor/pending/carry. entries.length gate allows footer even when overrides reduce shownCount to zero. | Settled: still; pending/continuation: RECORDING | CODE-TRACED, unchanged sibling; no extra F11/F12 gallery needed. |
| Author/Label hosted search failure, per-project result.errors/provider unavailable metadata | Real Filters/host scopes, H for exact failed hosted searches | Search/failure: RECORDING | CODE-TRACED, unchanged. Menus test error against null, not print object. Result.errors differs from transport failure. |
| Panel open/split/maximized/URL-selected, condensed header, Electron titlebar, appearance | Real row selection/resize/toggle/scroll/settings | Settled: still; panel/scroll/theme transitions: RECORDING | CODE-TRACED, unchanged. P03/P04 constrain width; maximized hides list; P01/P02 cover both themes. |
| Header Refresh/live refresh/turn completion/row actions/sweep/panel and copy shortcuts | Real controls/events; H clock/event driver if deterministic sequence needed | RECORDING | CODE-TRACED, unchanged; no provider work or extra timing gallery required. |
| Detail/thread unavailable callers and native mobile | Other callers/separate mobile implementation | Out of capture scope | CODE-TRACED, not affected. |

## Handoff and evidence acceptance

For every pair, record exact full revisions, browser build/OS/DPR, viewport and actual list-column width, explicit theme, fixture ID and REAL/HARNESS, raw seed inputs, target IDs/order/labels, route/search state, pending flags, clock strategy and sidebar/panel/scroll. Keep a run manifest and logs in a new timestamped directory per run; never replace the previous run by deletion.

Capture Before at the specified merge-base and After at the specified head with the same fixture/action driver. Freeze relative dates/clock and motion consistently for stills; preserve timers needed for search/retry recordings and log clock control. Record transport/data drift and never claim “only the prefix changed” without matched inputs/diffs. Label Before and After. Inspect aligned zero-threshold and practical-threshold diffs or equivalent alignment evidence for layout drift; a longer prefix may legitimately reflow content.

Upload images/videos AND seed script, harness source, action/capture driver, fixture data and sanitized manifest through ghdrop, and link them in the lead's evidence. Public artifacts must open without GitCafe auth. Omit tokens, pairing URLs, cookies, credentials/private data and local auth state. Preserve raw logs until sanitized evidence is uploaded. This pass creates the fixture specification only; executable seed/capture scripts remain the capturer's deliverables.

Pass 1 coverage: complete diff including added test inspected, helper callers and list-area branch/interaction inventory traced. No checkout edits/pushes/comments, browsers, dev servers or new tests. Live metadata reported 41 successful checks at the audited head; these are not visual proof. Disk 26 GB, above stop threshold. No server started, none to stop. Completed within the 45-minute budget.

Public upload validation: unauthenticated curl GET returned HTTP 200 and downloaded bytes matched the uploaded matrix.

FRICTION:
tool | First long inline artifact-writing call was rejected by the JavaScript parser before execution; rerun using a raw template string succeeded | Use raw multiline command strings for long Markdown artifacts.
tool | Python urllib public-link probe returned HTTP 403; unauthenticated curl returned HTTP 200 with identical bytes | Use curl for this service URL validation.
VERDICT: INSUFFICIENT P01, P02, P03, P04, P05, P06, P07, P08, P09
