# Proof audit, pass 1 — mobile code fences

PR [#33680](https://git.cafe/pingdotgg/t3code/pull/33680), branch `fix/issue-33638`. Read-only source snapshot: [e455e688cc](https://git.cafe/pingdotgg/t3code/commit/e455e688ccd0cc271c948492b1853558c50824ad) against local `origin/main` [633438d54f](https://git.cafe/pingdotgg/t3code/commit/633438d54f17b99f73f1a09466ecbe4a6aa0d545) (also merge base), in `/home/user/wt/pr-33680`. All six changed files reviewed. At final verification the shared checkout had externally advanced to [0f0c652771](https://git.cafe/pingdotgg/t3code/commit/0f0c65277170275015ac8cd050a22ceba6b88163). Its four-file diff extracts the same routing decisions into codeFenceRenderer and adds tests/comments; the inspected render-path expectations remain the same. This report and its source links remain pinned to the requested e455e688cc; it does not claim a fresh full audit or test run of the later commit. Forge metadata still reported head 25fea911d4 at retrieval ([25fea911d4](https://git.cafe/pingdotgg/t3code/commit/25fea911d44860e207263ddc865a43b025f6cf6e)); the requested local e455e688cc snapshot is authoritative for this audit, not that lagging metadata. This is a proof-coverage audit, not a merge-readiness verdict.

## Findings first

1. **Current-head proof is insufficient.** Existing captures are at [a230081021](https://git.cafe/pingdotgg/t3code/commit/a230081021) versus historical before [bbdc7dca32](https://git.cafe/pingdotgg/t3code/commit/bbdc7dca32). They do not exercise the new long-press menu or final iOS responder hierarchy. Refresh changed paths, retain the unchanged native/list controls and historical before material. No new historical before captures are required for this finish pass; the old before images do not represent current main.
2. **Install the current native fingerprint before capturing.** Main's [d655e2cca6](https://git.cafe/pingdotgg/t3code/commit/d655e2cca6ce918356f5914f7facff76db311b5c) updates both generated IDs/theme data and vendored native lexer from highlights 0.2.0 to 0.5.0 (for example diff ID 15→34, Kotlin 41→76). Passing JS/WASM tests or retaining language names is not native visual proof. Old native fingerprints from Evidence.md are not current-build provenance.
3. **Correct the old matrix before sending work to the capturer.** Fallback code is now intentionally nonselectable; replace range-selection work with L1's two-action native copy menu. Actual app omits `streamingAnimation`, whose dependency default is false; consequently an unclosed fence reports complete and can already be highlighted. Only a harness reaches explicit `complete=false`; do not try to capture a nonexistent real-app “plain until close” state. Case-sensitive special dispatch versus lowercased fallback creates the previously unlisted MERMAID route (M4).
4. **Raw videos recover three supposed gaps.** Decoded final frames of E2 and U1 show wrap off; P1 shows details collapsed. Four-second contact sheets miss these endpoints. These old interactions are not defective for that reason; their new wrapper/colors still require current-head verification. S1 remains incomplete for sustained visible growth plus preserved wrap state; all iOS interaction proof is absent.
5. **Do not silently promote old captions to current proof.** PR description still says only comment/merge changes followed the screenshots; subsequent functional changes contradict that statement. The old clocks differ and iOS backdrop samples shifted content; retain that qualification. This request supplies no new frozen-clock requirement, so timestamps alone are not an instruction to recreate historical before images.

## Change/staleness legend

- **U** = upstream highlighter/native-data upgrade [d655e2cca6](https://git.cafe/pingdotgg/t3code/commit/d655e2cca6ce918356f5914f7facff76db311b5c), brought in by merges; latest merge is [e455e688cc](https://git.cafe/pingdotgg/t3code/commit/e455e688ccd0cc271c948492b1853558c50824ad). Affects fallback tokenization, palette records and supported language set; not native tree-sitter/plain/list bodies.
- **R** = special Mermaid/math precedence [0c6994dceb](https://git.cafe/pingdotgg/t3code/commit/0c6994dceb238aa76db19ca22524714ee0982ce7). Current dispatch is Mermaid, enabled math, then general fallback. Old diagrams still show shared-frame geometry, but cannot prove dispatch against the newer Mermaid-aware lexer.
- **C** = copy-menu/nonselectable change [bda955f68f](https://git.cafe/pingdotgg/t3code/commit/bda955f68fe6c373315d32b261f8834ae41e10c5). New Menu/Pressable body affects fallback interaction/layout.
- **P** = menu inside horizontal scroller [25fea911d4](https://git.cafe/pingdotgg/t3code/commit/25fea911d44860e207263ddc865a43b025f6cf6e). New scroller content flex/padding and responder placement affect fallback body layout on both platforms and specifically iOS panning.
- **H** = reviewed head. **A/I** = Android/iOS portrait handset, **D/L** = dark/light T3 Code theme, base Text size 16/default measured OS scale unless row overrides. Use one existing handset of each platform; no tablet/landscape/physical-device matrix is required. Narrow user/card/quote widths cover constraints; tablet width remains supplementary. Every row containing interaction or timing requires **recording**; a still/contact sheet cannot substitute. Static checkpoints can be taken during a combined run.
- **OK AT HEAD** means the relevant code path is unchanged since an opened old artifact, not that the old file was captured at H. **STALE** means the relevant path/runtime changed after capture. Status is per subpath when a file mixes stale and reusable content.

## Complete render-path inventory

### Changed components and inputs

- [EnrichedMarkdownText.tsx:174](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/native/EnrichedMarkdownText.tsx#L174): `MarkdownCodeBlock` supplies original `language`, normalized `code`, `isComplete`, placement/id. Mermaid special dispatch is an exact lowercase match; complete→Mermaid, incomplete→native. Math is exact lowercase plus preference; complete→nested math renderer (blank lines collapsed, trimmed), incomplete→native. Disabled math falls through and currently resolves to text/native. Then native-language exclusion/unknown id→native, known fallback plus codeStyle→HighlightedCodeBlock; missing style→native. Base style always supplies codeBlock. Empty whole Markdown/whitespace assistant segments have no block. `fileEmbedLabel` selects a different document preprocessing path but both preserve fence bodies. `preserveSoftBreaks`, text alignment/direction, margins and slot placement affect surrounding layout. Links/images/task options do not select another code renderer; streaming link changes can rerender surrounding blocks and belong in S1's state check. Android's enclosing file-link Menu also exists in thread callers, so L1 must open the code menu rather than the enclosing menu.
- Native fences excluded, case-insensitively: `bash c css go golang html java javascript js json jsx markdown md py python rs rust sh shell ts tsx typescript yaml yml zsh`. Every other nonzero ID from `highlights.generated.ts` uses fallback, including aliases (e.g. kt/rb) and newly known MERMAID; `text/plain/plaintext/txt`, empty and unknown names stay native. Resolver trims/lowercases but only accepts table IDs; it does not infer arbitrary aliases from filenames for a fence. Native grammar-name mappings without a compiled default grammar (e.g. cpp/ruby/swift/php) still need fallback. Hundreds of lexer IDs collapse into colored-token/default-label versus explicitly mapped-label fixtures; no fixture per grammar is justified.
- [HighlightedCodeBlock.tsx:76](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/native/HighlightedCodeBlock.tsx#L76) has one caller: codeBlockElement. `code`, original `fence`, resolved `language`, `complete`, `scheme`, `textStyle`, `codeStyle` define input space. Wrapper/header colors come from textStyle; code inherits codeStyle color/font family/size/lineHeight/padding (12). iOS font Menlo; Android monospace. Hook enabled+language→highlighted lines; disabled→raw code. Empty lines yield separators, null token colors inherit base color, >1,000-unit lines remain plain, CRLF line splitting is normalized for display. Token fontStyle is not applied by this component. `wrapped=false`→horizontal ScrollView→Menu→Pressable→Text; true→Menu→Pressable→Text directly. Per-block wrap state, active glyph and accessibility label reverse together. Header Copy always writes raw block.code. Body long-press opens Copy/raw or Copy as Markdown; fallback Text is not selectable. No copied/checkmark/loading/disabled state exists.
- Label normalizes original fence to lowercase: `cc/cpp/cxx→C++`, `cs/csharp→C#`, `graphql→GraphQL`, `objc/objectivec→Objective-C`, `php→PHP`, `rb→Ruby`, `scss→SCSS`, `sql→SQL`, `toml→TOML`, `xml→XML`; otherwise uppercase first letter. Mapping vs default, alias/case, and long label are C2/T1; do not duplicate each map entry visually.
- [CodeBlockFrame.tsx:12](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/native/CodeBlockFrame.tsx#L12) and HeaderButton have exactly two component callers: HighlightedCodeBlock and MermaidBlock. `label`, `actions`, `children`, textStyle control frame; 8 radius, hairline border/divider, fixed 32 header, 12 horizontal inset, 14 action gap. Button active true→full tint, otherwise 60%; icon/platform implementation differs, hitSlop=10. Highlighted has wrap+copy (active/inactive). Mermaid has toggle+copy when ready, copy only when pending/error. Text size scales label by .9×.85; it does not increase fixed header height or icon size. Long label/action overlap and OS scaling are T1. No zero-action caller exists.
- [MermaidCodeBlock.tsx:119](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/native/MermaidCodeBlock.tsx#L119) has one caller: codeBlockElement. Suspense pending→copy-only source; ready SVG→two-action diagram, showCode→selectable source; parse/load error→message+source/copy-only. Empty Mermaid is an error, not an empty fallback block. Small/wide intrinsic ratios determine fit; theme/foreground/link roles recolor SVG. Diagram tap null→exporting hidden SVG (no visible spinner; duplicate taps ignored)→open FilePreviewModal; close→null/reopen. iOS vs Android export scale differs. Empty callback/file-write rejection→null/retry. Successful promise cache persists across remount, 64-entry cap evicts oldest; loader/type failure removes failed caches. M1/M2/M3/H3 cover these without requiring every parser error string or 65 diagrams.
- [codeBlockMarkdown.ts:1](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/native/codeBlockMarkdown.ts#L1) is called only by highlighted menu's Copy as Markdown. It selects max(3, longest backtick run+1), retains original fence string and code, and inserts line breaks. No-language and long-run branches exist in tests; no-language cannot reach current highlighted router, so no app capture is required for that helper-only branch. L1 tests the reachable ordinary/long-run serialization. Native collector strips trailing LF from block.code; compare clipboard to parsed code, not the original trailing-fence newline.

### Every app caller of SelectableMarkdownText

| Caller / source | Layout/data distinctions | Representative rows / reachability |
|---|---|---|
| [ThreadFeed.tsx:1217](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/features/threads/ThreadFeed.tsx#L1217) AssistantMarkdownBlocks | Assistant textStyle, ordinary segments, recursive details with extra left padding; artifact-template segments render another unchanged card; whitespace segments omitted. | C1/C2/S1/P1. Empty non-code segments need no still. |
| [ThreadFeed.tsx:2462](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/features/threads/ThreadFeed.tsx#L2462) and second segment call at 2494 | User role palette, narrower bubble/duo column, preserveSoftBreaks, clipboard context; review-wrapper prose splits into separate calls. | U1/R1; both ordinary user renderer calls equivalent. Wider tablet/duo layout does not add another code branch. |
| [PendingUserInputCard.tsx:78](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/features/threads/PendingUserInputCard.tsx#L78) QuestionText | Preview styles, question/sheet constraint, writingDirection; iOS paragraph alignment derives from set direction; Android native alignment. Option text does not use this renderer. | Q1 conditional actual tool call; no static assistant reply can impersonate pending-input UI. |
| [FileMarkdownPreview.tsx:238](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/features/files/FileMarkdownPreview.tsx#L238) | Preview roles, frontmatter masking, fileEmbedLabel preprocessing, padding18/max760. Called by workspace ThreadFile/NewTaskFile in ThreadFilesRouteScreen and rendered attachment/ZIP-entry Markdown in AttachmentDocumentBody. | F1; captured/live file modes use same code rendering. Source/plain mode is a separate unchanged surface. |
| [PullRequestMarkdown.tsx:238](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/features/pull-requests/PullRequestMarkdown.tsx#L238) | Preview styles; host/explicit soft breaks, task handler, ordinary segment vs HTML-table row/cell. | Q2; reached by PullRequestDescription, PullRequestTimeline (including reviews), PullRequestDiscussionScreen; guide PullRequestGuideScreen summaries/attention notes/note bodies/questions, ReviewGuideExcerpt captions, GuideOutline summary. Ordinary previews collapse to F1/R1, very narrow columns to T1 width stress; unique PR-data availability remains unclaimed. |
| [ReviewCommentCard.tsx:166](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/mobile/src/features/review/ReviewCommentCard.tsx#L166) | Preview style in padded card; empty comment omits renderer; separate native/plain diff is unaffected by this PR. Called by user review-comment segment and ComposerContextSheet review-comment record (non-pull-request section). | R1; can seed legacy wrapper as user data without posting a remote review. Sheet outer container is supplementary. |

Only mobile iOS/Android import these components. Web/desktop, server, provider adapters and wire contracts are unchanged. Connection mode transports the same Markdown; there is no local/remote/tunnel conditional introduced here, so do not expand the capture matrix by provider or connection mode.

## Fixture matrix / exact remaining captures

Minimum excludes explicitly supplementary/code-only rows. Read status cells before scheduling work: P2/N1 need no dedicated new capture. “Checkpoint within” does not mean separate setup or another device lease. Reuse the same synthetic thread set.

| Row / fixture | Required data and visible checkpoints | Diff affected? | Minimum device × theme × row | Real-app seed route | Existing capture status / next action |
|---|---|---|---|---|---|
| C1 — core colors / native control | Three closed root fences: diff hunk/context/removal/addition; Kotlin comment, keyword, number, string and function; TypeScript native control. Default wrap off. | Yes: diff/Kotlin; TS control. | A×D/L + I×D/L; **still** at H. | Reuse core assistant reply in old seeds; same exact user prompt is a second role sample. | **STALE U+C+P**: all four old after stills (C1-android-light-after.png, C1-android-dark-after.png, C1-ios-light-after-final.png, C1-ios-dark-after.png). Opened all before/after pairs. Before stills remain historical baseline; retain clock qualifications. Replace only four after stills, using current native build. |
| C2 — fallback language / label / alias sampler | Swift, Dart, rb→Ruby, uppercase SQL→SQL, cpp→C++; add kt→Kt to sample alias ID with default label. One short colored body each. | Yes; mapped and default label branches. | A×D; **still checkpoints**, multiple screens allowed. | Reuse sampler reply; append ```kt + val alias = 42 + closing fence. | **STALE U+C+P**: [C2-android-dark-after-bottom.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b355b34a561874f5/C2-android-dark-after-bottom.png) shows all five old languages correctly colored. **MISSING** kt alias/default-label checkpoint; combine with this refresh. No new before needed. |
| E1 — empty / whitespace-only body | Closed empty sql (block.code="") and ruby containing spaces, newline and tab. Frame, two actions, body height; no invented source. | Yes: empty Text/token arrays and new touch wrapper. | A×D; **still**, checkpoint within edge pass. | Reuse edge reply, preserving spaces/tab exactly; old synthetic raw reply is verified. | **STALE C+P**: [E1-E2-android-dark-unwrapped-after.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/98d735eeaaacf58d/E1-E2-android-dark-unwrapped-after.png). Existing image visibly contains both blank bodies and intact headers. Refresh checkpoint, no separate recording or empty-message fixture. |
| E2 — overlong line / plain-token branch | Kotlin string line >1,000 UTF-16 units then val next = 42. Wrap to see full plain long line and colored following line; restore unwrapped. | Yes new caller of existing token-length guard. | A×D; **recording**, append to W1. | Reuse edge reply (1,001 x characters). | **STALE U+C+P**: [E2-android-dark-after-wrap.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6ab0aaf5834529fc/E2-android-dark-after-wrap.mp4) and its two stills. **Correction to old Evidence.md:** decoded terminal video frame IS unwrapped; wrap-off is present, not missing. Repeat only as part of current edge pass. |
| W1 — assistant pan / wrap / independent blocks / header copy | Kotlin with indentation, blank line, tab, héllo 👋 漢字, <1,000-unit line ending END_SENTINEL; adjacent second Kotlin fence. Pan to right and back, wrap on/off, pan again; second block retains its state. Header Copy→paste synthetic source in unsent draft→clear. | Yes; P specifically changes iOS scroller/JS-responder ancestry. | A×D + I×D; **recording**. | Reuse edge reply; use actual Kotlin body (old priority clip uses diff, which covers shared pan mechanics only). | **STALE C+P** on Android: [W1-android-dark-after-clean.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b809ec26b26abfac/W1-android-dark-after-clean.mp4) and pan/wrap excerpt. **MISSING** iOS; exact source equality/draft clear not proved. Do NOT repeat old range-selection requirement: new fallback text is intentionally nonselectable. |
| L1 — long-press copy menu (new required row) | Same long code as W1: open/dismiss menu both unwrapped (also after panning) and wrapped; both Copy and Copy as Markdown. Also long-press short-code whitespace/padding and empty SQL body to check the touch target. Add uppercase SQL fence whose body contains literal ``` plus Unicode/blank line/tab; paste and compare raw body vs four-backtick Markdown with original SQL case. Confirm no selection handles or enclosing-message menu. | Yes: C adds menu, P moves it inside scroller. | A×D + I×D; **recording**, extend W1. One light-menu checkpoint in U1/theme pass, no extra full run. | Ordinary synthetic user/assistant fence; exact extra payload in appendix. Driver can send it. | **MISSING** at every revision: old captures predate C, so no old selection/copy video can prove this menu. Show actual menu, both actions, dismissal, then successful pan/header taps; compare clipboard text in a scratch assertion or unsent draft, clear it. |
| U1 — narrow user bubble / role palette | Long diff or Kotlin in user bubble plus separate assistant block; user foreground/background/border roles; pan→wrap on→off without changing assistant wrap state. | Yes distinct role colors and constrained width. | A×L; **recording**; inspect iOS user bubble during C1/W1, no additional iOS clip. | Reuse wide-diff user message, or send edge Markdown as user content. | **STALE U+C+P**: [U1-android-light-after.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bbeca55b7059158e/U1-android-light-after.mp4). **Correction:** decoded last frame returns to unwrapped, although four-second contact sheet misses it. No separate missing-wrap-off recovery required. Add light menu checkpoint for L1 here. |
| S1 — real streaming / same mounted fence | First short Kotlin block contains a long line, wrap it on; second Kotlin fence arrives progressively; keep growth visible, capture opening, ≥2 distinct middle bodies, closing fence and stable end; first wrap state survives later prose/link-pill updates. | Yes fallback rendered from opening fence. | A×D + I×D; **recording** started before send. | Driver can request a progressively produced reply; cannot guarantee agent chunk cadence. Stock Replay (dev) ignores prompt text and plays fixed scenarios; it cannot seed these exact fences with the supplied driver. A separately labelled custom replay would need additional setup. | **INCOMPLETE + STALE U+C+P**: [S1-android-dark-after.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e891559a760e4253/S1-android-dark-after.mp4) exposes only a header before final body; retry is light, growth mostly below viewport, and neither proves first-block wrap persistence. Inspected dense raw-video middle frames as well as sheets. **MISSING** iOS. Finished text/static open fence is insufficient. |
| S2 — special fences while real text grows | Growing lowercase mermaid flowchart (partial invalid source→valid diagram) and enabled math fence (partial expression→settled equation); compare finished special renderer with uppercase MERMAID fallback. Actual app reports complete=true even before closing fence, so do not expect native-until-close. | Yes: R precedence against U; actual open-source rendering path. | A×D; **recording**, append to M1/N2 using a short streamed special reply. | Driver can request exact staged source, but cannot guarantee chunk cadence. Keep partial special source visible; static open text cannot prove temporal transitions. If no intermediate native client frame is emitted, mark unobserved. | **MISSING**: old S1 only streams Kotlin; Mermaid recordings start from settled diagrams and math recording toggles a finished fence. No old video covers real partial special-source routing. |
| P1 — slot placements / details disclosure | Root diff with prose above/below; quoted Kotlin; NOTE admonition diff; Kotlin inside <details>. Inspect constrained widths/margins; open→close details. | Yes: root/blockquote/admonition slots; assistant recursion. | A×D; **recording** with legible placement checkpoints. | Reuse placement assistant reply verbatim. | **STALE U+C+P**: [P1-android-dark-after.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6ffbe6694ef4f959/P1-android-dark-after.mp4). **Correction:** raw last frame IS collapsed; expanded and collapsed endpoints exist. Do not schedule a separate collapse-only capture. Current fallback wrapper/colors still need refresh. |
| P2 — list-contained native limit | Numbered list item containing an indented diff fence; remains plain/native without custom fallback header. Quoted/root code outside list provides contrast. | Not reached by fix; documented limitation. | A×D; existing **still** sufficient. | Reuse placement. Preserve indentation; quote nested in a list also cannot acquire a slot. | **OK AT HEAD for list branch**: [P2-N1-android-dark-after.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/80d5f43fe25fb58b/P2-N1-android-dark-after.png) visibly shows plain list diff. Collector still suppresses slots for inList. Colored quote at top of same file is stale; do not treat the whole image as current fallback proof. No dedicated recapture. |
| N1 — native / unknown / plain passthrough | Native TS (C1); unknown t3-unknown-language; text/plain id=0; unlabelled fenced and indented code. Preserve native headers and plain bodies, no duplicate custom actions. | Routing controls; branch unchanged. | A×D; existing **still** sufficient; TS also included in C1. | Reuse placement. Empty whole Markdown has no code block and needs no screenshot. | **OK AT HEAD for these controls**: [P2-N1-android-dark-after.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/80d5f43fe25fb58b/P2-N1-android-dark-after.png) and native TS portions of C1. No dedicated recapture. This status excludes math, which is split into N2. |
| N2 — math precedence / setting round trip | Lowercase math fence x^2 + y^2 = z^2, plus multiline body with blank lines; math off→native code, on→equation (blank lines removed/trimmed), off→code. Uppercase MATH remains native at head even when setting is on (exact special-name match; no math lexer ID). | Yes: R reorders special route; math still has no fallback lexer at H. | A×D; **recording**. Add uppercase control checkpoint to same reply/run. | Reuse placement; add MATH fence and multiline math; toggle Settings→Appearance→Render math; restore original value. | **STALE R**: [N1-android-dark-math-after.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ded0b7aefce8982c/N1-android-dark-math-after.mp4) then [N1-android-dark-math-after.part-002.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ce071a4bfbac032a/N1-android-dark-math-after.part-002.mp4). Opened enabled equation from raw video at 156s and restored-code sheet. Old setting round trip exists; **MISSING** current reordered-route proof and uppercase control. No need to repeat plain controls separately; S2 supplies the growing-source case. |
| T1 — large text / long label / theme update | Fortran-fixed-form + Kotlin in narrow user bubble. Text 22 and one larger measured OS font step; header actions legible/operable. Restore defaults; D→L→alternate palette→D on same code, token/frame colors refresh, wrap/menu remain usable. | Yes font/style/width inputs, fixed 32-unit header and label/actions sizing. | A×D/L/alternate; **recording**. | Reuse edge user prompt; Appearance Text size (not Code & Diffs font size), OS font settings, color scheme/palette. | **MISSING**: old E1 still only shows default-size long label. No enlarged-text or live-theme recording exists. Do not multiply every fixture across sizes/palettes. |
| M1 — Mermaid ready / source / fullscreen | Lowercase mermaid: small flowchart and wider sequence diagram. Show code↔diagram, header source Copy→paste/clear, tap diagram→viewer→close→reopen. Header has two actions; source remains selectable (unlike new highlighted fences). | Shared frame extraction + R precedence after U adds Mermaid lexer. | A×D (small+wide) + I×L (small); **recording**. Existing Android before still remains frame baseline. | Reuse simple Mermaid and correctly fenced sequence payload; do not reuse malformed multi-Mermaid reply without correction. | **STALE R** for current dispatch: [M1-android-dark-after-interactions.mp4](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f1414b5cd4ac12c1/M1-android-dark-after-interactions.mp4) and diagram/source after stills. Old before/after frames match except timestamps; shared-frame geometry proof remains useful. **MISSING** source-copy validation, wide interaction, all iOS interactions. Current ready/source checkpoints can come from new recording; no replacement historical before needed. |
| M2 — Mermaid malformed / empty / copy-only frame | Malformed flowchart and empty mermaid fence: error text plus source/empty body, one Copy action, no diagram toggle. | Shared frame + R precedence. | A×D; **still**, checkpoint in M1 session. iOS error duplicate not minimum (I×L M1 already covers platform frame/icons). | Reuse dedicated exact malformed/empty seed, not stray-fence reply. | **STALE R**: [M2-android-dark-after-exact.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ce727c8e4daaf8b4/M2-android-dark-after-exact.png) correctly shows both errors at old head. Refresh one combined checkpoint after confirming route at H; no separate iOS error recapture required. |
| M3 — Mermaid cold pending / cached return | New unseen diagram in fresh JS runtime: source/copy-only fallback→ready/toggle; scroll away/back reuses settled cache. | Shared frame in pending state; cache body logic unchanged. | A×D; **recording**, appended to M1 if observable. Pending exact subframe is conditional; do not block on scheduler timing. | Fresh runtime plus new diagram text; ordinary seed cannot hold loader pending. Forced delay is H3. | **MISSING** cold/cached-return clip. Record normal entry/return during M1; if pending never visibly appears, label it unobserved rather than claiming still proof. No separate required harness capture. |
| M4 — case-sensitive special name vs fallback (new row) | Same source in mermaid and MERMAID: lowercase diagram/source toggle; uppercase is colored code with wrap/copy and menu because fallback normalization is case-insensitive but special dispatch is exact. | Yes: U expands recognized languages; R preserves lowercase priority. | A×D; **still checkpoint** in M1; menu/scroll reused from L1/W1. | Send exact mixed-case fence info. Parser preserves codeDetail.lang; do not let agent normalize it. | **MISSING** from old evidence/matrix. This is an actual current route, not an assertion that uppercase diagrams are intended to render. Report any product disagreement separately; prove what H does. |
| F1 — rendered Markdown document container | Synthetic .md with frontmatter + core and quoted Kotlin; rendered/Markdown view, 18-unit padding/max-width 760, fileEmbed preprocessing branch. | Yes another real caller. | A×D; **still** (navigation alone need not be recorded; if claiming wrap interaction, use recording). | Attach scratch .md through composer, open attachment in Markdown mode with environment context; or scratch workspace file through Files. Driver only sends prompts; attachment/file creation is an additional step. | **MISSING**: no rendered document capture. Static chat/review images do not show this container. File/raw source mode does not satisfy it. |
| R1 — review card / segmented user prose | Existing valid legacy review_comment wrapper with Kotlin comment plus final diff sibling; add ordinary fenced prose before/after wrapper if demonstrating segmented user path. | Yes comment Markdown slot; separate native diff sibling is not this PR. | A×D; **still** checkpoint. Ordinary user segments equivalent to U1; no second required screenshot. | Reuse Respond to Display Fixture user message. Reply can be OK; no real PR review/comment is created. Context-sheet card uses same renderer/style; conditional on existing context record. | **STALE U+C+P**: [R1-android-dark-after-final.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8659b15b23155286/R1-android-dark-after-final.png) clearly shows Kotlin inside card and separate diff. Refresh once; no need to recreate review infrastructure. |
| Q1 — question Markdown / direction | Fenced Kotlin in pending question body with LTR/RTL prose; preview textStyle, Android vs iOS paragraph alignment. Options are plain Text, not code-renderer callers. | Yes equivalent caller; code block styling same as preview/narrow rows. | Supplementary A×D + I×L; **recording** only if claiming question expansion/RTL transition. No separate minimum capture. | Driver prompt can ask an agent to invoke request_user_input; cannot manufacture pending-tool data itself. Requires tool/provider availability or labelled component harness. | **MISSING; supplementary / app-conditional**. No old image proves this caller. F1/R1/U1 represent changed frame/style/width; no invented claim of actual question-tool coverage. |
| Q2 — PR body / timeline / discussion / guide / columns | Preview-style fence in PR body, review/timeline, discussion, guide summary/attention/note/question/caption/outline; HTML-table body cells provide very narrow columns, optional host soft breaks/task handlers. | Yes shared caller; no PR transport change. | Supplementary A×D; **still** for static cell, **recording** for disclosure/wrap. No separate minimum if narrow-frame stress and preview rows pass. | Existing read-only PR/guide data with exact Markdown, otherwise labelled harness. Chat seed driver cannot seed PR API responses; do not post a PR/comment just for this audit. | **MISSING; supplementary / existing-data conditional**. Inventory complete in caller table; no capture is claimed. |
| H1 — incomplete flag / missing style guards | Explicit complete=false: fallback frame raw (highlight hook null) vs native special mermaid/math until complete. markdownStyle.codeBlock absent→native fallback. Missing language/unknown id separately N1. | Yes guards, but actual app has codeStyle and streamingAnimation defaults false. | **CODE-ONLY**, no minimum capture; labelled **recording** if harness exercises flag transitions. | Cannot produce false isComplete through current app props, even by sending an open fence. Requires renderer harness with streamingAnimation enabled/direct props; not a real-app seed. | **No capture; not a missing app requirement.** Old H1 text “incomplete→native” was wrong for ordinary fallback code. S1 is still required to prove real growing content/state. |
| H2 — missing native modules / raw highlight fallback | No T3Highlights→plain tokens in custom frame; missing EnrichedMarkdownParser→all slots stay native; present module→colored tokens; enabled=false/blank hook language→raw code. | New caller of compatibility fallback; installed app assumptions. | **CODE-ONLY / HARNESS-ONLY**, not minimum. Still for forced absent module, recording only if changing availability. | Proper fingerprint-matched installed client must contain modules. Ordinary Markdown cannot remove them. Blank language cannot reach HighlightedCodeBlock via its router; incomplete hook branch H1. | **No capture; supplementary.** Do not use the old 0.2 native client with H's 0.5 generated IDs as a module-absence fixture: that is a mismatched build, not valid proof. |
| H3 — Mermaid forced loader/export failures | Import/type-load rejection→generic error/source/copy-only (failed cache entry evicted); forced pending; empty bitmap callback or file-write rejection→remain diagram, clear exporting guard, allow retry. Duplicate tap while exporting/open ignored. | Shared frame only; underlying failure bodies/export logic unchanged. | **HARNESS-ONLY recording**, supplementary. | Seed can cause parse error (M2) but cannot force module import failure, delayed promise, export callback or filesystem rejection. Requires explicit isolated fault injection. | **No capture; supplementary.** Normal M1 viewer proves success path. No user-visible spinner/error state exists for export failure, so do not demand a nonexistent still. |

## Seeding details and the smallest practical capture schedule

The supplied [seed-driver.mjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ec7b8278b8648c63/seed-driver.mjs) exports `seed(tools, tabId, prompt)`: click New thread, type exact prompt in the authenticated web composer, Submit. It sends ordinary user messages through the server and a real agent; it does **not** directly inject assistant replies or let its caller control chunk timing. Its IndexedDB helper only reads raw messages. This audit never executed it.

The exact old synthetic content is available in [seeds-after-final2.json](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/682cc4229b7094f5/seeds-after-final2.json). Reuse text, not a live database. `Rename Config and Add Code Examples` supplies core, `Format Code Examples in Markdown` sampler, `Preserve Markdown Code Block Formatting` edge, `Exact Markdown Formatting Request` placement, `Mermaid Flowchart Output` small diagram, `Render Unclosed Mermaid Label` exact malformed/empty, and `Respond to Display Fixture` the user review wrapper. The `Unresolved Mermaid Diagram Request` assistant reply contains a stray fence between examples; it is not a clean replacement for the dedicated exact malformed/empty fixture. Verify actual returned bytes before accepting a seeded assistant fixture. User-side fixtures are deterministic but must be labelled as user-role proof.

The stock free Replay (dev) agent reads fixed scenarios and ignores prompt contents; selecting it while sending these prompts will not echo these fixtures. This was checked in [dev-replay-agent.ts](https://github.com/pingdotgg/t3code/blob/e455e688ccd0cc271c948492b1853558c50824ad/apps/server/scripts/dev-replay-agent.ts#L319). Custom timed replay could be honest real-pipeline proof if separately set up and labelled, but no such fixture was provided or created here. S1/S2 cannot be guaranteed merely by a finished static reply or the seed helper; mark a failed timing attempt unobserved instead of substituting stills.

| Device/theme run | Required new material; combine checkpoints rather than new setups |
|---|---|
| Android dark | C1 still; C2 label sampler stills; edge recording W1+L1+E2 with E1 still; S1 streaming; placement P1; math N2 plus S2 special-source growth; Mermaid M1+M3 with M2/M4 still checkpoints; F1 document and R1 review-card stills. Start/finish typography T1 here. |
| Android light / alternate palette | C1 still; U1 narrow-bubble recording including L1 light-menu checkpoint; T1 text/theme round trip. Return settings to original values. |
| iOS dark | C1 still; W1+L1 edge interaction recording including horizontal pan after dismissing the long-press menu and after restoring wrap off; S1 streaming recording. |
| iOS light | C1 still; M1 small-diagram source/copy/fullscreen round trip recording. |

P2 and N1 retain their old unchanged-path stills. Q1/Q2/H1/H2/H3 are supplementary reachability accounting, not hidden demands on the capturer. M3's cached return belongs in M1; a visibly held pending frame is conditional and not a separate mandatory harness session. Do not add an iOS M2 error-only still, an entire platform × theme product for every grammar, range-selection proof for fallback code, or replacement historical before captures.

### New exact seed fragments

Use the old core/edge/placement bodies for their rows. Append the following alias and case controls to sampler/Mermaid/math respectively. Fence info case must be retained.

`````markdown
```kt
val alias = 42
```

```MERMAID
flowchart LR
    A[Start] --> B[Done]
```

```MATH
x^2 + y^2 = z^2
```

```math
x^2

+ y^2 = z^2
```
`````

L1's Markdown-copy case uses an outer four-backtick SQL fence and a literal three-backtick run inside its source:

`````markdown
````SQL
SELECT 'héllo 👋 漢字 ``` END_SENTINEL' AS value;

	-- indented marker
SELECT 42;
````
`````

The indentation before `-- indented marker` is one literal tab (U+0009). The direct header Copy and menu Copy expect exactly the parser's `block.code` (trailing LF removed). Copy as Markdown expects four opening backticks followed by original `SQL`, LF, that same code, LF and four closing backticks. Kotlin W1 with no embedded backticks covers the ordinary three-backtick output. Paste only into an unsent draft/scratch comparison, confirm content and clear it. There is no in-app “Copied” state to wait for, and simulator haptics are not visual proof.

For S1, make the first Kotlin declaration line long enough to visibly wrap (otherwise a wrap-state reset is visually unobservable). Keep its header and some wrapped text visible as the second fence grows; choose only enough second-block lines to fit multiple changing intermediate bodies in view before moving to the tail. Include changing prose/link references after the second fence to exercise renderer updates. Ask for or replay actual deltas; do not animate a still.

For S2, observe a short growing flowchart from incomplete label to valid `A[Start] --> B[Done]`, then a growing lowercase math expression with Render math on. Because the actual app reports `isComplete=true`, partial Mermaid source may enter the parser/error/Suspense path before the closing fence; do not assert it should remain native code. Check its eventual diagram and equation, without claiming malformed partial source is itself a regression.

## Inspection record and limits

Opened all 19 original stills used in this audit: four C1 platform/theme before/after pairs (8), C2 before/after (2), M1 diagram/source before/after (4), E1/E2 unwrapped and wrapped (2), P2/N1, M2 exact, R1 (3). Full pixels were viewed directly or in labelled inspection mosaics. Opened 10 contact sheets covering W1 clean/pan-wrap, S1 original/retry, E2, P1, M1 interactions, N1 parts 1/2, U1. The unused original W1 contact was downloaded but is not relied upon.

Downloaded/probed nine original recordings. Decoded and opened dense middle-frame sheets for S1 original (18–28s) and retry (73–83s); opened the raw N1 equation frame at 156s; decoded and opened the terminal raw frames for E2, U1 and P1. Those terminal frames contradict the old report's three endpoint-omission claims. Inspection was targeted, not a claim of exhaustive real-time playback or independent app reproduction. The supplied evidence's source/clock/build metadata were read; exact native build provenance at H is still missing. Existing tests were read to understand line-length/serialization semantics; no tests or runtime app turns were run by this audit.

The unchanged native-control conclusion was checked beyond the PR diff: EnrichedMarkdownText, SelectableMarkdownText, markdown style/theme sources, and the enriched-markdown 1.2.0-t3.18 package reference are unchanged between the old before revision and current main. Main's ThreadFeed changes affect scroll/keyboard behavior; they are another reason not to call whole old screens exact current-main comparisons. P2/N1 status only credits unchanged block contents.

Derived inspection image below: terminal raw-video frames from the old captured revision, rescaled and labelled for this audit; these are not new app captures or substitutes for recordings.

![Recovered old-video endpoints: E2 unwrapped, U1 unwrapped, P1 details collapsed](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/2574c16ad4a9b183/recovered-terminal-frames.png)

## Scratch, deletion, cleanup and coverage

Step `audit-1`; all downloads, scripts, decoded frames, indexes and this report are inside `/tmp/lead-33680-r2/audit-1/`. No worktree changes, pushes, PR comments, branch operations, live database access, browser tabs, servers, simulators or device leases were made/started. Nothing was deleted. Scratch and downloaded originals are retained; originals were already publicly uploaded by the earlier capturer. Worktree was clean on entry and final status had no uncommitted changes. HEAD externally advanced as documented above; this audit made no checkout mutations. Disk available: 109 GB. All six PR files, their renderer callers/dependency slot rules, later functional commits and relevant highlighter upgrade were covered within the 45-minute budget (started 08:22 UTC; final verification after 08:42 UTC). No child agents were started.

FRICTION:

- tool | Python urllib downloads received HTTP 403; curl retrieved the same public artifacts successfully | Prefer curl for this artifact host.
- tool | Pillow was absent; ImageMagick produced inspection mosaics instead | List available image-processing tools in the audit environment.
- other | The shared checkout externally advanced during this read-only audit; its diff was checked and source links remain pinned | Keep review snapshots frozen or notify the reviewer before advancing them.
- forge | PR metadata reported the pre-merge head while the requested checkout contains the merge head | Pin a review SHA, as this brief did; do not silently substitute forge metadata.

AI-assisted; verified with the tests and tools listed above.

VERDICT: INSUFFICIENT C1 C2 E1 E2 W1 L1 U1 S1 S2 P1 N2 T1 M1 M2 M3 M4 F1 R1
