# Proof audit, pass 1: Settings search keyboard layouts

PR [#33395](https://git.cafe/pingdotgg/t3code/pull/33395), issue [#33385](https://github.com/pingdotgg/t3code/issues/33385).
Before: [73fb49d0b3](https://github.com/pingdotgg/t3code/commit/73fb49d0b3a61bff74aebc362fc6c17d6c0d39be).
After: [379bf92ec0](https://github.com/pingdotgg/t3code/commit/379bf92ec0d5c5c3d52dfafe4716b8e7700432e9).
Source inspected in `/home/ubuntu/wt/pr-33395`, whose HEAD matched the after SHA and whose working tree was clean. This is a derived fixture plan, not a claim that any capture or test was executed. No browsers, servers, leases, or additional worktrees were started.

## Findings

1. No recordings exist in this pass. Static render output is unchanged, but focus and the compact search overlay change observably. All required proof rows below therefore require **recording**; stills cannot establish the focus transition, selection, or absence of a transition.
2. The PR description's outcome table uses an older before commit, [4f0b74e190](https://github.com/pingdotgg/t3code/commit/4f0b74e190), and omits compact before outcomes. Recreate paired evidence at the exact before/after SHAs above. The table is useful supporting text, not paired capture proof.
3. The new browser tests mount the component with a mocked one-item search catalog and dispatch onto body. They cover Russian Slash, Ctrl/Meta physical F, German typed slash, and two negative keys. They do not by themselves establish compact overlay behavior, existing-query selection, or real-app modal and editable exclusions. Their reported result in the PR was not rerun during this read-only proof audit.
4. Synthetic key/code events are the permitted VM substitute. Label every recording “synthetic keyboard layout events”; this proves app event handling, not an OS layout switch, native browser Find suppression, Electron interception, or mobile keyboard behavior.

## Code-derived render inventory

- The only production caller of [SettingsSidebarNav](https://github.com/pingdotgg/t3code/blob/379bf92ec0d5c5c3d52dfafe4716b8e7700432e9/apps/web/src/components/settings/SettingsSidebarNav.tsx) is `SettingsContentLayout` in [the Settings route](https://github.com/pingdotgg/t3code/blob/379bf92ec0d5c5c3d52dfafe4716b8e7700432e9/apps/web/src/routes/_chat.settings.tsx). Settings route, menu, palette, and keybinding entry paths converge here. The other caller is [the composition browser test](https://github.com/pingdotgg/t3code/blob/379bf92ec0d5c5c3d52dfafe4716b8e7700432e9/apps/web/src/components/settings/SettingsSidebarNav.composition.browser.test.tsx), under SidebarProvider with `/settings/general` and a mocked Theme item. No separate production provider/agent/RPC/contracts path changes.
- The sole prop is `pathname`; current hash comes from the router. Exact section and descendant paths highlight their section. `/settings/diagnostics` highlights Maintenance; `/settings/open-source-licenses` highlights About. An unmatched path has no selected row and a first-section keyboard tab stop (not necessarily reachable through the real router). All section choices share the same render shape; their labels/icons vary.
- At viewport width >= `md` (default 48rem/768 CSS px), navigation is 15rem wide, with text, headings, search input and footer. Below `md`, idle navigation is a 3.5rem icon rail, headings are hidden, labels are screen-reader-only, input wrapper is hidden, and a Search icon button appears. `compactSearchOpen=true` changes compact navigation to an absolute, full-width overlay, reveals input/headings/labels, and removes the icon button. At wide widths it mainly removes an already hidden compact button. Footer stays hidden below `md`, including while expanded.
- `query.trim().length===0`: normal section tree and slash key hint. Nonempty query: clear button and results menu replace tree. Zero matches shows “No settings found” and no listbox role/id; >=1 match creates listbox/options with title, section subtitle, section icon, truncation, active highlight, and scroll-to-highlight. There is no count cap; long lists scroll. Index starts/resets to 0, arrows wrap, mousemove changes highlight, and shrinking results clamps it.
- Blank whitespace follows the normal-tree branch but remains an input value. A truly empty available catalog and a nonmatching query collapse to the same zero-result render branch. Short/long titles and section labels truncate; no special length branch exists.
- `SettingsSearchItem` shape is id/title/to plus optional targetId/searchTerms/scope, secondary rank, and platform/capability flags. targetId changes navigation destination; secondary and matching rank change ordering, not row structure. Platform filters include Electron, macOS, Windows, release channel, secrets. Availability filters include cloud config, environment/config/connection availability, provider-settings availability, local-backend maintain permission/local disabled, primary environment, WSL state/error, auto-settlement, managed tunnel, peer links, fast checkout, text generators. These alter membership/count, already represented by zero/one/many fixtures; the shortcut listener does not depend on any of them. Secrets also adds a static nav row.
- Footer uses two lazy/Suspense children with null fallbacks: absent without cloud config or while auth loads; sign-in when loaded and signed out; avatar when signed in. There is no component-owned loading or error UI. WSL query loading/error only changes catalog membership. Disconnected/unavailable settings scope shows content notices outside this sidebar; the sidebar still mounts.
- Themes affect inherited colors and focus/selection appearance, with no theme branch in this component. Web and Electron reuse it; native mobile does not. Browser width is the branch criterion, not modal content width. Parent modal changes inset below `sm`, rounding/border at `sm`, and margins at `lg`; these are unchanged and need not multiply this shortcut audit.
- Interactions: window slash/find listener (with defaultPrevented, composition, modifier, editable, popup/dialog and key-capture guards); focus opens compact search; empty-query blur closes it; nonempty blur retains it; clear and Escape reset query/index; arrows/hover select results; Enter/click clears, closes compact mode, reveals a target and either navigates to a hash or scrolls to an already current hash. Section clicks clear hash; tree arrows/Home/End move focus without navigation; Left/Right are consumed. Compact icon opens search. Footer opens auth/user controls. Closing Settings unmounts the listener.

## Capture conventions and seeding

W = 1280x900 CSS px, default Light appearance. C = 700x900 CSS px, default Dark appearance. Set appearance using the real Appearance settings color-scheme control before navigating to `/settings/general`. Use the same fonts, zoom, app settings, and data on both refs. W covers the wide branch; C covers the compact branch. Both themes are sampled without a full width/theme cross-product because no styling changed. Optional breakpoint checks at 767/768px belong to F15.

Use the primary agent's isolated dev server and its app authentication, never the live database or a hard-coded bundle origin. Empty chat history is adequate for these device-local Settings fixtures; no project/thread RPC seeding is required. For existing-query fixtures, fill the actual Search settings combobox through the app, then focus a stable noneditable Settings control (for example the Settings close button) without activating it. For compact empty search, open by icon to seed if necessary, then blur and verify the rail is restored before the shortcut case. Do not dispatch every event onto body and claim editable/dialog coverage: dispatch onto the actual focused target.

For each synthetic event use a bubbling, cancelable keydown. Show the case label, starting focus, event key/code/modifiers, then ending focus and query selection. Export a companion result log containing `defaultPrevented`, active element identity, input value, selectionStart/selectionEnd, route/hash, viewport/theme, and commit. Labels/logs are evidence annotations, not product UI. Verify actual combobox identity, not just a generic INPUT. In compact cases show the closed rail and resulting overlay in the same recording. Keep each case at a stable state long enough to judge; end/ref changes must be clearly labelled Before/After.

## Keyboard equivalence suite

| Group | Events | Expected at before -> after |
|---|---|---|
| New physical-key behavior | `key=".", code="Slash"`; `key="а", code="KeyF", ctrlKey=true`; same with metaKey | ignored -> search focused; compact opens. Russian/Ukrainian collapse because these event tuples are identical. Run each independently from reset state at W and C. |
| Newly accepted punctuation side effect | `key="-", code="Slash"` (German), `key="!", code="Slash"` (AZERTY), unshifted | ignored -> search focused outside editables. Same physical-key branch as Russian; at least one representative in W recording, both in companion log. |
| Preserved typed-key behavior | `/`+Slash; `f`+KeyF with Ctrl and Meta; `/`+Digit7+Shift; Latin-layout typed `f`+another Key-letter code with Ctrl | focused -> focused. Physical Latin `KeyF` with `key="u"` and Ctrl must remain ignored. Case folding accepts `F` when shiftKey is false. |
| Negative key/modifier behavior | `?`+Slash+Shift, `,`+Slash+Shift, plain `7`+Digit7; Slash with Ctrl/Meta/Alt; physical F without Ctrl/Meta; physical F with Alt or Shift; AltGr-style Ctrl+Alt slash | ignored -> ignored. Reset focus before every case. |
| Event guards | composing keydown; pre-canceled keydown; missing code with non-Latin key; editable/popup/key-capture targets | no search takeover. A pre-canceled event already has defaultPrevented=true; compare focus, not false prevention. Missing code with typed `/` or typed Ctrl+f still works. No repeat guard or OS-platform check exists in this listener. |

## Fixture matrix

“Required” is the minimum evidence set for this change. “Waived” inventories an unchanged branch without requiring unrelated captures. Every interaction/time-dependent row is marked recording, even if waived. All proposed outcomes below are code expectations, not observed results.

| ID / fixture | Data and real-app seed | Diff affects / expected outcome | Minimum viewport × theme; medium | Status |
|---|---|---|---|---|
| F01 wide empty focus | `/settings/general`, query empty (also whitespace control), noneditable focused; run new and preserved key groups independently | Yes: new tuples transfer focus; old shortcuts still work; tree and slash hint remain | W × Light; recording | MISSING — required |
| F02 compact rail to empty overlay | Same route, empty query, closed icon rail; focus noneditable control; repeat Russian Slash, Ctrl-F, Meta-F independently | Yes: before stays rail; after opens full compact search and focuses input after render; titles/headings return | C × Dark; recording | MISSING — required |
| F03 wide populated refocus/selection | Fill `theme` (real catalog gives Themes, with targetId `appearance`); blur to noneditable control; dispatch each new shortcut. Then replace selection with `font` | Yes: before retains old focus/selection; after focuses existing search and selects its whole value; typed replacement updates results | W × Light; recording | MISSING — required |
| F04 compact populated retained overlay | Fill `font` (>1 result), blur to noneditable control; query keeps overlay open; dispatch new shortcuts | Yes: overlay remains; focus returns and selects value. Distinct from opening a hidden input | C × Dark; recording | MISSING — required |
| F05 wide empty-result search | Fill `zzzz-no-setting-33395`; verify zero options/status, blur; physical Ctrl-F; clear and recover | Yes: newly accepted find refocuses/selects even with zero results; status/clear control render unchanged | W × Light; recording | MISSING — required |
| F06 compact empty-result search | Same nonmatch seeded in expanded compact search, blur; physical Meta-F; clear | Yes: newly accepted find refocuses/selects zero-result state; no hidden focus loss | C × Dark; recording | MISSING — required |
| F07 editable focus guard and find exception | Real search INPUT with value; real Keybindings filter INPUT or another Settings input. Slash on focused input must stay there; physical Ctrl/Meta-F from an ordinary input must transfer/select | Changed matcher reaches existing guard: slash preserves editable focus, find can take ordinary input focus. Search slash must not select/clear its own value | W × Light; recording. TEXTAREA/contenteditable exact-selector subcases may use labelled DOM harness if no reachable Settings control exists | MISSING — required representative; harness subcases explicitly labelled |
| F08 nested popup and shortcut capture | `/settings/keybindings`: click a shortcut pill to focus its `data-keybinding-capture` input; do not save drafts. `/settings/appearance`: open a real select popup and target an option. Try physical slash/find | Changed matcher must preserve nested-control focus; Settings app modal itself is exempt via data-app-modal (F01/F02). Capture widget may consume event before listener | W × Light; recording. Exact role=dialog / aria-modal-only selector variants may use labelled DOM harness; no claim of app dialog capture if fabricated | MISSING — required real popup + key-capture representatives |
| F09 ignored keys/event guards | Noneditable target in real Settings; run negative key/modifier cases, Latin physical-F mismatch, composing and pre-canceled events | Changed matcher must not broaden Shift/Alt/Latin shortcuts or steal guarded focus; compact must stay closed when ignored | W × Light; recording; compact negative Slash+Shift also in C × Dark F02 sequence | MISSING — required |
| F10 clear and close recovery | From F04/F06: Escape with query, clear button separately, then blur when empty; reopen via icon; use one real result via Enter/click to close overlay | Directly reached flow, unchanged handlers: Escape/clear restores tree while focused; empty blur restores rail; result clears search, closes overlay and jumps to target. Escape during composition must preserve query | C × Dark; recording | MISSING — required recovery sequence |
| F11 active section and target navigation variants | `/settings/general`, `/settings/appearance`, `/settings/diagnostics`, `/settings/open-source-licenses`; normal section click; select Themes -> appearance hash; repeat same hash for scroll-only branch; id-only result such as Interface font. Unknown pathname only in labelled mounted-component harness | No handler or pathname/hash change. Covers exact/descendant/detail aliases, groups with/without headings, targetId/id, new route versus same-hash scroll, nav tree keyboard movement | No additional minimum; recording if exercised; can share F10 target jump | WAIVED — unchanged variants; not claimed captured |
| F12 one/many/long results and active clamp | Query `theme`/`font`/`a`; record actual returned rows; arrows wrap, hover, scroll, shrink query result count then recover. A deterministic exactly-one or artificially long title needs a labelled catalog harness if natural catalog cannot supply it | No changed rendering/ranking/index logic. One and many use same option branch; none is F05/F06. Long title/subtitle truncation, long list overflow, active index clamp are unchanged | No additional minimum; recording if exercised | WAIVED — unchanged counts/length variants |
| F13 footer auth/loading | Wide app without cloud config -> absent; configured signed-out -> sign-in; signed-in -> avatar; auth/lazy pending -> absent. Compact footer hidden in all cases. Seed actual account/config via app only; forced pending/auth records must be labelled harness | No diff to footer or lazy imports. Pending and no-config collapse to null; no sidebar-owned error branch | No additional minimum; recording for loading or sign-in interaction; still only for settled passive variants | WAIVED — unrelated account states |
| F14 platform and catalog availability | Use actual web/Electron build and connected/disconnected environments/permissions/capabilities. Filters listed above collapse to zero/one/many rows. Platform/secrets nav membership needs corresponding build config; deterministic unsupported flags use labelled catalog harness | No changed platform/data dependency. Web production route is the minimum. Electron shares source but native shortcut routing is unverified. Native mobile has no caller of this component | No additional minimum; recording if interaction or asynchronous availability changes | WAIVED — unchanged filters; desktop/OS/mobile not claimed verified |
| F15 remaining widths/themes | 767/768px for md boundary; <=639px for parent full-screen Settings, >=1024px parent margins; W Dark and C Light plus custom themes are inherited styling variants | No styling changes. W Light and C Dark cover both actual component layout branches and sample both themes; parent breakpoints do not add listener branches | No additional minimum; recording if resizing/opening, otherwise settled still | WAIVED — no full cross-product required |
| F16 scope notice / listener teardown | Settings scope unavailable or environment disconnected: content notice while nav mounts. Close Settings, focus underlying app, dispatch keys; reopen Settings | No scope/connection/listener lifecycle change; nav shortcut is device-local and data independent. No backend/provider/MCP execution needed | No additional minimum; recording if exercised | WAIVED — unchanged scope/lifecycle branches |

Minimum delivery can be **four recordings**: before W/Light and C/Dark, after W/Light and C/Dark, with labelled chapters covering F01–F10; separate shorter clips are equally acceptable. Cover W rows F01/F03/F05/F07/F08/F09 and C rows F02/F04/F06/F09-negative/F10. Each before/after pair uses identical data and event sequence; after the intended before failure, manually open/fill search to seed later comparison chapters rather than silently skipping them. Companion logs include full key-equivalence cases. F07/F08 fabricated selector subcases are supplemental harness evidence, not a substitute for real-app input/popup/capture representatives.

## Friction and cleanup

FRICTION: none. Free space checked at start: 11 GB. No task-owned server, browser, lease, or extra worktree requires cleanup. No source edits, pushes, forge comments, or PR mutations performed. Only this scratch report was created for the requested public upload.

VERDICT: INSUFFICIENT F01–F10 recordings at specified before/after commits
