Native transcript navigation and source UX delivery
This document records the native Rust/GPUI delivery that makes long EXEPERT
Desktop conversations easier to read and navigate. It covers two connected
increments built from baseline commit
b356c453bd2e339a69b41dca3768d8f53d31948b:
- hard Codex activity folding, browser-style middle-button auto-scroll, and loaded user-message checkpoint rails; and
- compact paired checkpoint previews plus responsive icon-first EXEPERT, Codex, and DSH source tabs.
The delivery changes presentation and process-local transcript interaction only. Codex App Server history remains authoritative. Codex and DSH paging, search, storage, settings, protocol ownership, and retention are unchanged. No PostgreSQL, Docker, Supabase, migration, or new Rust dependency was added.
Delivered behavior
| Area | Delivered contract | Surfaces |
|---|---|---|
| Codex activity folding | Commands, tools, developer activity, and reasoning summaries start with only a bounded one-line summary mounted; expansion alone mounts the full projected body and structured details | Codex |
| Always-visible content | Warnings, user messages, assistant commentary, and final answers remain fully visible | Codex |
| Disclosure identity | Expanded state is process-local and keyed by server, task, turn, and item; stable item-qualified element IDs replace index-derived activity IDs | Codex |
| Middle-button auto-scroll | An unmodified middle click toggles vertical auto-scroll with a visible anchor, 12 px dead zone, linear speed, 1,800 px/s cap, and 50 ms frame clamp | Native Chat, Codex, DSH Chat, DSH Trajectory |
| Motion cancellation | A second middle click, left/right click, wheel input, Escape, checkpoint jump, programmatic jump, or scope/surface change cancels auto-scroll | All four transcript surfaces |
| Boundary behavior | Reaching the top or bottom pauses movement without disarming it; reversing pointer direction resumes movement | All four transcript surfaces |
| User checkpoints | Loaded user rows produce independently virtualized, stable-key markers with chronological loaded-window ordinals | All four transcript surfaces |
| Checkpoint keyboard UX | Enter/Space activates a marker; Up/Down/Home/End navigate markers; the active marker tracks the latest user row at or before the first visible transcript row, or the first loaded marker when none precedes it | All four transcript surfaces |
| Paired preview | Hover and keyboard focus open the same compact card with primary user text and an optional muted resident agent response | All four transcript surfaces |
| Codex response truth | Only an authoritative same-turn AgentFinal can appear beneath a Codex user checkpoint | Codex |
| DSH response truth | Only a completed same-turn assistant/message can appear; chunks and model boundary records are excluded | DSH Chat, DSH Trajectory |
| Omitted-history cue | When no resident Codex user row exists and an older page can actually load, an unnumbered marker jumps to LOAD OLDER HISTORY without requesting data | Codex |
| Source selector | Local EXEPERT, Codex, and DeepSeek marks replace text-only tabs; icons remain visible and the selected label appears at measured header widths of 720 px or more | Desktop Chat header |
| Source accessibility | Stable IDs, ARIA names/selection, focus rings, hover tooltips, focus tooltips, and Enter/Space activation are preserved | Desktop Chat header |
Interaction architecture
TranscriptScrollState owns stable bookmarks, adaptive wheel motion,
middle-button auto-scroll, tail-follow interaction, and animation generation.
TranscriptCheckpointRailState separately reconciles loaded user markers and
their focus handles. Checkpoints carry only bounded process-local excerpts and
stable row keys; they never carry an App Server cursor or trigger paging.
The transcript views remeasure resident rows when rail presence changes. This prevents cached row geometry from overlapping a newly visible rail while the existing stable-key bookmark preserves the reader's anchor.
Hard Codex activity folding
The earlier visual line clamp did not remove long command or developer bodies from the render tree. The replacement uses distinct render branches:
- collapsed rows mount a Unicode-aware single-line summary only;
- expanded rows mount complete projected text and allowlisted structured details;
- collapsing unmounts the full body and remeasures the affected row;
- live reasoning no longer expands itself automatically;
- warnings bypass activity folding and remain visible; and
- source-copy actions retain the complete projected text even while the row is visually collapsed.
The disclosure button exposes truthful expanded state, state-aware chevrons, keyboard focus styling, and stable IDs derived from the qualified item key. Hidden/raw reasoning remains excluded upstream and cannot be revealed by the control.
Middle-button auto-scroll
The auto-scroll session stores the click anchor, current pointer, velocity, last frame time, and generation. Pointer displacement inside 12 px is neutral. Beyond that dead zone, velocity grows linearly and is capped at 1,800 px/s. Elapsed frame time is capped at 50 ms so a delayed frame cannot cause a large jump.
Starting auto-scroll pauses tail-follow. Reaching a list boundary produces no jitter and does not deactivate the session. A second middle click or any explicit competing navigation cancels the session. Reduced-motion mode keeps the functional anchor while omitting decorative animation.
The four surfaces share the motion engine but retain their existing source- specific reconciliation and focus-restoration paths.
Checkpoints and compact previews
Checkpoint identity comes from the stable transcript row key, not the loaded ordinal. Loading older history can renumber accessible labels without changing marker identity. Eviction or filtering removes only markers whose rows are no longer resident. The active marker is the latest checkpoint at or before the first visible row; when the viewport begins before every loaded checkpoint, the first loaded checkpoint is the bounded fallback.
Each user and response excerpt is independently normalized to one visual line and bounded to 160 Unicode scalar values. The preview card is at most 360 px wide and never wider than the viewport minus a 32 px gutter. Both sections wrap and clamp to three lines, so long unbroken tokens cannot become a window- wide tooltip strip. The accessibility description includes both excerpts when the response exists.
Resident response pairing is deliberately source-specific:
- Native Chat uses the last non-empty assistant message before the next user message.
- Codex uses the last non-empty authoritative
AgentFinalin the same turn. Commentary, commands, tools, developer activity, reasoning, other turns, and provisional finals are excluded. - DSH uses the last non-empty
assistant/messagebefore the next user row and enforces the same turn when a user turn ID exists.assistant/chunk,model/start, andmodel/endrows are excluded.
If no matching resident response exists, the agent section is omitted. The UI does not fabricate a response and does not load history on hover or focus.
Codex omitted-history truthfulness
An omitted-history timeline row can represent three distinct states: another page can load, the newest 500-item resident cap is reached, or the reduced- fidelity server cannot page older history. The checkpoint rail now projects an unnumbered history affordance only for the first state.
Activating the affordance cancels motion and jumps to the existing history row.
It does not enqueue CodexRuntimeCommand, consume a cursor, or mutate mirror
freshness. The user must still activate LOAD OLDER HISTORY explicitly.
Source identity and asset provenance
The header now uses one shared native icon-tab primitive:
- EXEPERT uses original product artwork under
assets/activity; - Codex and DeepSeek use locally vendored, adapted theSVG source marks;
- the native asset source embeds every mark into the executable;
- runtime hotlinking and network loading are absent;
- selected, hover, focus, keyboard, and accessibility states remain explicit; and
- the measured stage width controls whether the selected source label is visible.
THIRD_PARTY_NOTICES.md records the source URLs, retrieval metadata, original
response hashes, adapted bundled-file hashes, presentation-only modifications,
trademark ownership, and the unresolved legal/brand review boundary. The
source endpoints are mutable, so the recorded hashes pin the exact retrieved
inputs used by this delivery.
Privacy, persistence, and ownership boundaries
- Activity expansion, auto-scroll state, checkpoint focus, excerpts, paired previews, and source-tab focus handles remain process-local.
- Transcript and search content is not added to settings, diagnostics, or serialized state.
- Checkpoint rails consume only loaded/resident rows and never own cursors.
- Codex App Server remains the source of truth for persisted Codex history.
- DSH remains a separate canonical source with its existing local store.
- The existing 500-item Codex cap, lazy paging/search, mirror ownership, mutation firewall, source-copy semantics, and raw-reasoning exclusion remain unchanged.
- No database, migration, transport, external protocol or product API, settings schema, or dependency changed. New Rust helpers and constants stay within the existing native desktop UI module boundary.
Accessibility contract
- Activity controls expose stable item-qualified IDs, accurate expanded state, expand/collapse labels, focus styling, and directional chevrons.
- Each ordinary user marker is a button named
Jump to user message Nwith a bounded paired description and stable row-qualified ID. - An ordinary checkpoint rail is a navigation region named
User messages. The history-only Codex rail instead usesOlder user messages, and its unnumbered button explains that older checkpoints are outside loaded history. - Hover and keyboard focus use the same structured preview content.
- Source tabs retain
chat-source-exepert,chat-source-codex, andchat-source-dsh, plus ARIA selection and stable accessible names. - Enter and Space switch an inactive source; standard focus traversal remains native GPUI behavior.
Verification record
The final source candidate was checked with:
cd desktop
cargo +1.96.0-x86_64-pc-windows-msvc fmt --all -- --check
cargo +1.96.0-x86_64-pc-windows-msvc test --workspace --all-targets --locked --target x86_64-pc-windows-msvc
cargo +1.96.0-x86_64-pc-windows-msvc clippy --workspace --all-targets --locked --target x86_64-pc-windows-msvc -- -D warnings
cargo +1.96.0-x86_64-pc-windows-msvc build --package exepert-desktop --target x86_64-pc-windows-msvc --release --locked
cargo +1.96.0-x86_64-pc-windows-msvc test --package exepert-desktop --lib --target x86_64-pc-windows-msvc --locked -- --ignored --test-threads=1
cargo +1.96.0-x86_64-pc-windows-msvc test --package exepert-desktop --test codex_timeline_render --target x86_64-pc-windows-msvc --locked -- --ignored --test-threads=1
cd ..
pnpm.cmd --dir docs-site exec docusaurus build
git diff --check
Observed results on 2026-09-02:
- the complete locked all-target workspace suite passed; its library portion reported 453 passed and two intentionally ignored native harnesses, and every enabled integration suite passed;
- all Codex UX contracts passed, including authoritative pairing, truthful omitted-history behavior, rail remeasurement, responsive tabs, and paired accessibility copy;
- all four opt-in Windows GPUI harnesses passed explicitly and serially: bounded Codex folding geometry, independent transcript/checkpoint virtualization, frame-driven auto-scroll, and narrow-window paired preview;
- strict workspace Clippy passed with plain
-D warningsand no allowlist; - Rustfmt and
git diff --checkpassed; - the optimized Windows release build passed and produced
desktop/target/x86_64-pc-windows-msvc/release/exepert-desktop.exe(39,141,376 bytes); and - the Docusaurus production build passed with the delivery page and sidebar entry.
The first increment's Windows acceptance exercised folding, expansion, auto-scroll activation/cancellation, and checkpoint navigation. The refinement increment adds deterministic source-pairing tests and a native narrow-viewport preview harness. A fresh physical mouse/keyboard pass over the final compact card and source-tab visuals remains a human interaction check, not an automated claim.
Known follow-up edges
Two pre-existing limits are recorded in
_bmad-output/implementation-artifacts/deferred-work.md:
- The no-new-dependencies boundary retains a handcrafted truncation helper. It preserves UTF-8 and common combining, emoji, joiner, variation-selector, and flag sequences, but does not implement every Unicode grapheme-extension class.
- Ordinary desktop harnesses retain fewer than 80 realized checkpoint rows. An unusually tall transcript viewport around 2,500 px may realize 80 or more 32 px markers because of the rail's 64 px overdraw.
Neither follow-up changes paging, persistence, source truth, or normal desktop interaction behavior.
Repository change inventory
This is the exhaustive path inventory relative to baseline commit b356c45.
At documentation finalization Git reported exactly 23 changed paths: 7
additions, 16 modifications, and no deletions or renames. Generated Cargo and
Docusaurus output remains ignored and is not part of the commit.
Root records and implementation specifications
M THIRD_PARTY_NOTICES.md
M _bmad-output/implementation-artifacts/deferred-work.md
A _bmad-output/implementation-artifacts/spec-transcript-checkpoint-source-navigation-refinement.md
A _bmad-output/implementation-artifacts/spec-transcript-folding-navigation.md
Native desktop source and embedded assets
A desktop/exepert-desktop/assets/activity/chat-chevron-right.svg
A desktop/exepert-desktop/assets/activity/source-exepert.svg
A desktop/exepert-desktop/assets/third_party/thesvg/codex.svg
A desktop/exepert-desktop/assets/third_party/thesvg/deepseek.svg
M desktop/exepert-desktop/src/app.rs
M desktop/exepert-desktop/src/ui/activity.rs
M desktop/exepert-desktop/src/ui/chat.rs
M desktop/exepert-desktop/src/ui/codex_transcript.rs
M desktop/exepert-desktop/src/ui/dsh_transcript.rs
M desktop/exepert-desktop/src/ui/native_chat_transcript.rs
M desktop/exepert-desktop/src/ui/transcript.rs
Native desktop tests and contracts
M desktop/exepert-desktop/tests/chat_presentation_ux_contract.rs
M desktop/exepert-desktop/tests/codex_timeline_render.rs
M desktop/exepert-desktop/tests/codex_ux_contract.rs
M desktop/exepert-desktop/tests/emoji_ux_contract.rs
Documentation and navigation
A docs-site/docs/architecture/native-transcript-navigation-delivery.md
M docs-site/docs/architecture/native-codex-client.md
M docs-site/docs/frontend-modules/native-desktop-chat.md
M docs-site/sidebars.ts
Maintainer reading order
- Read the two completed implementation specifications under
_bmad-output/implementation-artifacts/for the approved intent and review trails. - Review
desktop/exepert-desktop/src/ui/transcript.rsfor the shared motion, checkpoint, preview, and stable-bookmark engine. - Review
desktop/exepert-desktop/src/app.rsfor source-specific projection, hard Codex activity rendering, and responsive source-tab composition. - Compare the Native, Codex, and DSH transcript views for their thin bindings over the shared state.
- Review
THIRD_PARTY_NOTICES.mdand the source-selector asset tests before distributing the two third-party marks. - Read the contract tests and native harnesses before changing row identity, checkpoint realization, motion cancellation, or accessibility semantics.
Git delivery boundary
The feature branch is codex/transcript-navigation-refinement. The commit
containing this document is the delivery commit. No deployment or binary
distribution is part of the GitHub merge; the optimized executable remains a
local build artifact.