# #22585 supplemental fixture overlay

This is a supplemental overlay on the chip-evidence fixture. It is **not** the original fixture and must not be relabelled as such.

- sourceHead: `7d1650ea51f81a4000937f5c76d31221f1c89ac2` (unchanged; nothing committed, nothing pushed)
- original fixtureSha: `7d1650ea51f81a4000937f5c76d31221f1c89ac2`
- Overlay touches 4 existing fixture files plus `apps/mobile/app.config.ts` (fixture-gated orientation only). No other production, lower-layer, native, build or script files change.
- Overlay patch SHA-256: `afa04931f56c36377f6567eabdce7410b431522bea595e945090bb2467cae2bd` (`/tmp/22585-supplemental-overlay.patch`)
- Overlay archive SHA-256: `1b163126bbaa361d8448498e87b795a508b7413321c0ae2a4552016ac13faf51` (`/tmp/22585-supplemental-overlay.tar`; deterministic: sorted, mtime 2026-01-01Z, uid/gid 0)
- Per-file hashes: `/tmp/22585-supplemental-overlay-files.sha256`
- All of the above: `/tmp/22585-supplemental-SHA256SUMS`

| File | 7d SHA-256 | Overlay SHA-256 |
|---|---|---|
| CallerFixtures.tsx | c4dcf8f4…a732bba | 189092e7…299778e |
| ChipEvidenceApp.tsx | 7dcc1ede…d4d2bce | ba9ddf67…d570db |
| README.md | dbb15a84…0c5772 | 300a5731…a6c |
| fixtures.ts | bcac50ea…68230f | deaa54b9…70db |

The original 7d bytes and their hashes are in `/tmp/22585-supplemental-orig/`.

## Replay (identical for before and after)

1. Build each snapshot as the README describes: `node apps/mobile/scripts/chip-evidence-snapshot.mjs <sha> /tmp/chip-<side>` from a checkout at 7d. Use before=`a93b03c8a5a888cfa7fac1fd6cb7a814221adf72` and after=`7d1650ea51f81a4000937f5c76d31221f1c89ac2`.
2. Then overlay the same archive onto each snapshot: `tar -xf /tmp/22585-supplemental-overlay.tar -C /tmp/chip-<side>`. Verify with `cd /tmp/chip-<side> && sha256sum -c /tmp/22585-supplemental-overlay-files.sha256`. The archive does not contain `rasterizer.tsx`, so the baseline's no-op rasterizer adapter is preserved.
3. Record in metadata: `sourceSha=<side sha>`, `fixtureSha=7d1650ea51…`, `supplementalOverlaySha256=afa04931…` (patch) or `1b163126…` (archive). Do not overwrite the snapshot's `chip-evidence-source.json` fixtureSha; add the overlay hash beside it.
4. Alternative for a git checkout at 7d: `git apply /tmp/22585-supplemental-overlay.patch` (checked clean against pristine 7d).

Baseline compatibility: every new production import exists at a93b03c8a5: ThreadListV2Row/PendingRow, SettingsScreen, workspaceConnections, orchestrationEnvironment.threadSearch, ThreadRouteScreen, ThreadFileScreen, AttachmentFileScreen, SymbolView and PullRequestDescription. Among those source files, only `CommandPalette.tsx` differs between baseline and head, and that difference is the lower-layer icon work. No baseline typecheck or build was run here, because no third build is allowed before review.

## New scenes (appended after `C2-pr`; existing scene order and data unchanged)

URL: `t3code-preview://chip-fixture?scene=<scene>&theme=<id>&appearance=<light|dark>`

- `T3-placeholder`: linked project `Placeholder favicon`, favicon URL `file:///fixture/project-favicon-missing`. Covers user context, user raw link and assistant raw link through `resolveProjectChipIcon`, then rasterized auto-monogram "PF". Capture all three paths.
- `E2-repository`: screen surface, padding 16, `max-w-[760px]` guide column. Repository context `https://github.com/fixture/repo`. Markdown: `#12`, `fixture/other#7`, commit `a1b2c3d4e5`, `@octocat`, `@fixture/mobile`, relative file, absolute file and context link.
- `E2-attention`: the same markdown inside the exact guide attention wrapper (`gap-3 rounded-xl border border-border bg-grouped-card p-4` with eye symbol and label). The label is a literal copy of `attentionLabels.risk`.
- `E2-description-live`: `PullRequestDescription` with real `expanded` state and a PR-URL repository context. Capture clipped, then tap Show more and capture expanded, then Show less and capture restored.
- `K2-excerpt`: the palette opens. Type exactly `fixture excerpt` and wait ≥200 ms for the debounce. Expect a user-source excerpt on `Loaded favicon` and an assistant-source excerpt on `Emoji project`. The connected-environment pin lasts only while the scene is mounted and is restored on leave. Open it fresh by URL; do not compare palette state from other scenes captured after it.
- `G3-rows-screen` / `G3-rows-sidebar`: production `ThreadListV2PendingRow` (draft) and `ThreadListV2Row` card, card selected, slim (production `opacity-40` favicon wrapper) and slim selected, for the favicon, emoji, one-glyph and two-glyph projects. Pane backgrounds are `bg-screen` and `bg-drawer`, as in HomeScreen. Scroll to capture all 20 rows.
- `G3-settings`: the real `SettingsScreen` (`bg-sheet`, AppBar) containing a copy of the overview header row (`flex-row items-center gap-4 px-2`, 48pt) for the same 4 projects. This is a labelled wrapper copy, not the routed Settings screen.

## X2 (applies to existing scenes)

`Thread`, `ThreadFile` and `ThreadAttachment` are now registered in the fixture stack with the production screens and the production route param types. The header back button returns.

- **Thread (reachable):** tap a thread context chip or a raw thread link in T1 to T5 or U1-2. The feed calls `navigation.navigate("Thread", { environmentId, threadId })` for both. The screen mounts with the seeded shell; no environment connection exists, so it shows its own offline state.
- **ThreadAttachment (reachable):** tap a non-media file context record (U1-1 `app.tsx`; F1 `app.tsx`, `sample.unknown`, `data.csv`). `composerDocumentAttachmentRecord` sends these to `ThreadAttachment`. Image, video and PDF records open in-component previews instead. Attachment bytes are not served offline, so the screen shows its own load failure or unavailable state.
- **ThreadFile (registered, NOT reachable offline):** feed file-path taps open the in-component `FilePreviewModal`. They navigate to `ThreadFile` only when a `fileMetadata` query reports a directory, and that query needs filesystem read scope. The media menu's "Open in file viewer" is disabled without `canReadMedia`. Reaching it would mean seeding auth scopes or a connection, which is out of bounds. It remains a gap.

These taps prove the real route, params and screen mount. They do not prove fetched content.

## Revision r3 (C1 fix + W1 orientation)

Previous r2 artifacts are kept in `/tmp/22585-supplemental-prev/` (patch `ba153127…`, archive `f30c4dbf…`).

- **C1 root cause (confirmed):** `makeThreadShellFixture` (`apps/mobile/src/test-fixtures.ts`) forwards every unset override as an explicit `undefined` (`modelSelection`, `projectId`, `runtimeMode`, `interactionMode`, `branch`, `worktreePath`). `makeRawThreadShell` spreads `input` last, so those `undefined` values overwrite its valid defaults. The fixture shell passed only env/id/title, so it had `modelSelection: undefined`, and `ThreadComposer` read `.instanceId` of it (log `/tmp/22585-composer-app-log-export.log` lines 1076 and 1078). The same incomplete shell fed G3 rows, Home and Archive.
- **Fix (fixture-only):** `fixtures.ts` adds `fixtureThreadShell(environmentId, input)`, which builds the shell with `presentThreadShell(env, makeRawThreadShell(input))` and throws if the raw shell fails `Schema.is(OrchestrationV2ThreadShell)`. All four shells in `ChipEvidenceApp.tsx` (main, linked list, linked atom, remote) use it. `validateFixtures()` (run by `fixtures.test.ts`) now also builds and contract-checks the main shell. The shared test helper and production code are unchanged.
- **W1:** `app.config.ts` sets `orientation: process.env.EXPO_PUBLIC_CHIP_EVIDENCE === "1" ? "default" : "portrait"`. Other builds stay portrait.
- **Config base equality:** `apps/mobile/app.config.ts` is blob `d1d0398e0942a1b2df2cef22df68a9bc953a4a36` at both a93b03c8a5 and 7d1650ea51, so the archive's full-file copy changes only the orientation line on either side. A config-only patch is also provided: `/tmp/22585-supplemental-config.patch` (SHA-256 `cad211c4e4606e2ebc036729b090cb1eea743ce7e362afd16686dd38dd4b07cd`). It applies cleanly to both bases.
- **Note:** `orientation` is a native (prebuild) setting, so landscape needs a new native build with the overlay. A JS-only reload does not pick it up.
- **Replay check:** the full patch applied to a pristine 7d export and matched all 5 per-file hashes.

## Checks (r3, with overlay applied to 7d)

- `vp test run` over composerChipPresentation, enrichedLinkPresentation, projectIcon, mobileTheme, nativeComposerTheme and chip-evidence/fixtures: 6 files, **38/38 passed**.
- `apps/mobile` typecheck (`tsc-rs --noEmit`): exit 0.
- `vp lint` (chip-evidence + app.config.ts): exit 0. `vp fmt --check`: clean.
- A temporary regression test, not kept, confirmed the old `makeThreadShellFixture` shell has `modelSelection === undefined` and fails the contract, and that `fixtureThreadShell` yields `instanceId: "codex"`.
