# Read-only evidence auditor, pass 1

PR [#24271](https://git.cafe/pingdotgg/t3code/pulls/24271) ([GitHub counterpart](https://github.com/pingdotgg/t3code/pull/24271)). Checkout `/home/ubuntu/wt/pr-24271`; measured HEAD [3526fde952](https://git.cafe/pingdotgg/t3code/commit/3526fde95203012921d319d9cfe50af35305be01). Audit date 2026-10-24 UTC.

## Fixture matrix

All test references below refer to `apps/mobile/src/native/NativeHeaderToolbar.test.tsx` at the audited head. These are React DOM/jsdom tests of the toolbar and real `NativeStackScreenOptions`, with navigation mocked. Retained callbacks are invoked in JavaScript, not by device taps.

| Fixture | Evidence | Result and precise scope |
|---|---|---|
| Left button | Parameterized test lines 96–158; retained button pressed before/after closure value changes | Measured pass: first/guide.pdf then second/guide.pdf; no additional navigation.setOptions calls after handler-only update. |
| Left direct menu action | Same left fixture, direct menu action | Measured pass: latest committed closure value, unchanged registration count. |
| Left nested menu action | Same left fixture, one submenu depth | Measured pass: latest committed closure value, unchanged registration count. |
| Right button | Same parameterized test, right placement | Measured pass: latest committed closure value, unchanged registration count. |
| Right direct menu action | Same right fixture | Measured pass: latest committed closure value, unchanged registration count. |
| Right nested menu action | Same right fixture, one submenu depth | Measured pass: latest committed closure value, unchanged registration count. |
| Bottom button | Same parameterized test, bottom placement | Measured pass: latest committed closure value, unchanged registration count. |
| Bottom direct menu action | Same bottom fixture | Measured pass: latest committed closure value, unchanged registration count. |
| Bottom nested menu action | Same bottom fixture, one submenu depth | Measured pass: latest committed closure value, unchanged registration count. |
| Abandoned/uncommitted replacement | Test lines 172–199: startTransition replacement suspends; retained default-right button pressed; later replacement commits | Measured pass: suspended render does not publish pending handler; previous committed handler remains callable, then changes on replacement commit. Does not cover every abort mechanism, menu actions, or all placements. |
| Multiple toolbar instances | Test lines 201–236: two keyed default-right instances, separately retained button callbacks | Measured pass: callbacks dispatch to each instance’s updated handler. Mock has one navigation options store; this establishes handler-ref isolation, not independent real screens or simultaneous native toolbar presentation. |
| Unmount | Same isolation fixture: remove first toolbar, then all toolbars | Measured pass: removed toolbar’s retained button does nothing; surviving toolbar still dispatches; final retained callback does nothing after final unmount. No menu-specific or placement-specific unmount fixture. |
| Custom header | Test lines 160–170 with throwing-default navigation-like context | Measured pass: Connecting custom span applies; equivalent rerender adds no setOptions call; Reconnecting updates rendered element. Synthetic context, mocked navigation; no actual navigator/provider or device mount. Does not test a custom child’s interactive handler. |
| iOS applicability | NativeHeaderToolbar.tsx lines 237–258 publishes handler array in layout effect and clears it on cleanup; recursive menu conversion registers direct/nested actions; lines 281–290 select native item factories | Source-backed: fix applies to iOS native-header item path. No iOS runtime or capture verified on this VM. |
| Android applicability | NativeHeaderToolbar.android.tsx lines 1–48: type-only import, every implementation returns null; AndroidScreenHeader.tsx renders NativeAppBar with direct IconButton and AndroidAnchoredMenu actions; FilesHeader.tsx lines 50–79 uses that separate header | Source confirms Reviewer A’s claim: Android NativeHeaderToolbar is inert; Android in-flow headers use a separate path. This iOS dispatch regression suite does not prove Android header interaction behavior. |

Source: [toolbar implementation](https://git.cafe/pingdotgg/t3code/src/commit/3526fde95203012921d319d9cfe50af35305be01/apps/mobile/src/native/NativeHeaderToolbar.tsx), [regression fixtures](https://git.cafe/pingdotgg/t3code/src/commit/3526fde95203012921d319d9cfe50af35305be01/apps/mobile/src/native/NativeHeaderToolbar.test.tsx), [Android stub](https://git.cafe/pingdotgg/t3code/src/commit/3526fde95203012921d319d9cfe50af35305be01/apps/mobile/src/native/NativeHeaderToolbar.android.tsx), [Android header](https://git.cafe/pingdotgg/t3code/src/commit/3526fde95203012921d319d9cfe50af35305be01/apps/mobile/src/components/ui/AndroidScreenHeader.tsx), [Files header](https://git.cafe/pingdotgg/t3code/src/commit/3526fde95203012921d319d9cfe50af35305be01/apps/mobile/src/features/files/FilesHeader.tsx).

## Independently measured

`cd /home/ubuntu/wt/pr-24271 && vp test run apps/mobile/src/native/NativeHeaderToolbar.test.tsx` exited 0: 1 file passed, 6 tests passed; reported duration 5.77 s, start 09:24:20 UTC. Three placement cases plus custom header, suspension, and isolation/unmount account for the six tests.

The handler-only fixture changes a render argument captured by callbacks while keeping labels/menu structure and mocked route params unchanged. “No extra native registration” means no extra calls to mocked navigation.setOptions during that update; native bridge registration, rendering cost, and device frame timing were not measured. Presentation changes and route-param changes may legitimately register new options and are outside that assertion.

`command -v adb`, `command -v emulator`, and `command -v android-emulator` found no executables on current PATH. No installation or alternative-machine/tooling search was attempted. Working tree was clean initially; final status checked separately. No source edits, mutation tests, commits, pushes, PR comments, backend, browser, native build, or device session performed. No live T3 userdata accessed.

## Reported evidence, not independently reproduced

The task brief reports: step 1 reverting the original fix produced three stale-handler failures; step 2 suspension and unmount/isolation fixtures caught deliberate regressions. This pass did not perform those mutations or inspect their original logs. Attribute these as earlier-step reports, not fresh measurements. The earlier bounded search in /opt, /home/ubuntu/Android, and /usr/local/bin finding no Android tooling is also supplied context, not a search repeated in this pass.

## Recommended append-only PR body text

> Evidence audit at [3526fde952](https://git.cafe/pingdotgg/t3code/commit/3526fde95203012921d319d9cfe50af35305be01): `vp test run apps/mobile/src/native/NativeHeaderToolbar.test.tsx` passed all six tests. The React DOM/jsdom fixtures invoke retained button, direct menu, and nested menu callbacks for left/right/bottom placements after a handler-only committed update and assert no extra mocked `navigation.setOptions` calls. Separate button fixtures cover an uncommitted suspended replacement, per-toolbar handler isolation, and retained callbacks becoming inert after unmount. A custom-header fixture covers equivalent rerender deduplication and changed element content.
>
> These are JavaScript regression tests with mocked navigation, not native device captures or measurements of native bridge registrations. Source confirms Android’s `NativeHeaderToolbar.android.tsx` is inert and Android uses separate in-flow headers; the changed native-header dispatch path applies to iOS. Android device capture remains unverified because local Android tooling is absent; iOS verification is unavailable on this VM. No backend, native-client build, browser, or emulator was launched for this audit.
>
> Earlier steps report three stale-handler failures when reverting the original fix and deliberate-regression detection by suspension and unmount/isolation tests. The read-only evidence auditor independently reran the passing suite but did not reproduce those mutations.

## FRICTION

- Device evidence blocked by absent local Android tooling and unavailable iOS runtime on this VM. Per test-t3-mobile skill and task constraints, no install, automation-system switch, or remote machine access attempted.
- Local main is unsuitable as a precise PR diff baseline: main...HEAD includes substantial unrelated changes. Inspected the supplied head, relevant files, and individual task commits; did not fetch or assert the live PR base/head/body/CI state.
- A read-only command attempted to read nonexistent StackHeader.android.tsx; the shared StackHeader.tsx and actual Android toolbar stub were inspected instead.
- Mandatory thread PR registration was performed through the app tool; no PR content or repository state was changed.

## Concurrent checkout change

Final status remained clean, but HEAD changed externally during this pass to [1bee62f103](https://git.cafe/pingdotgg/t3code/commit/1bee62f10398d27e8bd669b4bc917eee24d5c5e5). The six-test execution above occurred at the requested original head. A subsequent git diff found no changes in NativeHeaderToolbar.tsx, NativeHeaderToolbar.test.tsx, NativeHeaderToolbar.android.tsx, StackHeader.tsx, AndroidScreenHeader.tsx, or FilesHeader.tsx between the two heads. Other mobile/navigation/dependency files changed in the merge; no fresh test result at the new head is claimed. Pass 2 must pin the final head.

## AUDIT

PASS WITH PLATFORM LIMITATIONS for the source/test evidence claims above. No blocking contradiction found between the specified behavior and these focused fixtures. Native device behavior remains UNVERIFIED on both platforms. Android in-flow header behavior is outside the changed dispatch path. This is pass 1 evidence review, not final PR-body approval, merge-readiness assessment, or CI certification. Parent should run pass 2 against the final PR body and final head.
