Skip to content

Session replay: turn stepper + transport bar (P1+P2)#9

Merged
lroolle merged 1 commit into
mainfrom
feat/session-replay
Jul 12, 2026
Merged

Session replay: turn stepper + transport bar (P1+P2)#9
lroolle merged 1 commit into
mainfrom
feat/session-replay

Conversation

@lroolle

@lroolle lroolle commented Jul 12, 2026

Copy link
Copy Markdown
Member

Implements P1+P2 of docs/design/session-replay.md — zero capture changes, works on every trace ever captured.

What

  • src/replay.ts (new, pure, inlined): visibleAt(pairs, cursor) is the whole feature — the wire as of a moment, fed through the existing buildSession path. Plus replayEvents (response-end boundaries), nextBoundary/prevBoundary/anchorAt walkers, and nextTick (playback scheduler with ≤2s idle compression).
  • Transport bar in the Session view: ⏮ / ▶⏸ / 1x 2x 8x 60x / scrubber / elapsed clock / exit. The scrubber doubles as a minimap: turns are tall accent marks, errors red, probes/telemetry short ticks. Drag to scrub (render cache keys on the anchor pair, so sub-boundary scrubbing is free).
  • Keyboard: / step turns, shift+←/→ step wire requests, Space play/pause, Home/End, Esc exits. Entering via starts at the beginning; via steps back from now.
  • Deep links: #/session/<key>/@<pair-id> opens paused at that pair; pausing/stepping updates the URL via replaceState. Anchored on pair id so links survive cross-run history merges.
  • Live: new pairs extend the track at the right edge; "live ⤓" exits and re-attaches the tail (the new-activity pill is suppressed during replay — reveals are the cursor's doing). Snapshots replay identically offline and label the exit "✕ exit".

Design-doc open questions resolved: requests list stays full during replay; probes render as minimap ticks. Doc updated (P1+P2 shipped, P3/P4 remain).

Verification

  • 174/174 tests (12 new in tests/replay.test.ts, replay-machinery guards in the snapshot test)
  • Stubbed-DOM behavioral smoke driving the real page script: step back/forward, time label, hash anchoring, minimap mark count, playback through the tape with pause-at-end, Esc exit, deep-link entry — all pass
  • No real-browser visual check possible in this container — worth a quick scrub-while-live-streams test on your side

🤖 Generated with Claude Code

Replay is a time cursor over the same session data: pairs whose response
completed at or before the cursor are visible, everything after doesn't
exist yet. visibleAt() feeds the existing buildSession path, so both panes
(wire threads + conversation) rebuild naturally from partial history —
exactly the code path that renders mid-capture live sessions today.

- src/replay.ts: pure timeline primitives (visibleAt, replayEvents,
  boundary walkers, anchorAt, nextTick with idle compression), inlined
  into the page and unit-tested like summarize.ts.
- Transport bar in the Session view: play/pause at 1/2/8/60x with idle
  gaps compressed to <=2s, scrubber-as-minimap (turns tall accent, errors
  red, probes ticks), drag to scrub, elapsed/total clock.
- Keyboard: arrows step turns, shift+arrows step wire requests, Space
  plays, Home/End jump, Esc exits back to the live tail.
- Deep links anchor on pair id (#/session/<key>/@<pair-id>) — pausing
  updates the URL, opening one starts replay paused at that moment; ids
  survive cross-run history merges where wall-clock offsets wouldn't.
- Live captures keep extending the track; "live" exits and re-attaches
  the tail. Snapshots replay identically offline.

Verified by 12 unit tests plus a stubbed-DOM behavioral smoke driving the
page script end-to-end (step/seek/play/deep-link).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lroolle lroolle merged commit be304d8 into main Jul 12, 2026
1 check passed
@lroolle lroolle deleted the feat/session-replay branch July 12, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant