Skip to content

feat: play replay tabs as sequential chapters#2024

Merged
Nikhil (shadowfax92) merged 8 commits into
mainfrom
feat/sequential-tab-replay
Jul 24, 2026
Merged

feat: play replay tabs as sequential chapters#2024
Nikhil (shadowfax92) merged 8 commits into
mainfrom
feat/sequential-tab-replay

Conversation

@shadowfax92

Copy link
Copy Markdown
Contributor

Summary

  • Treat recorded Chrome tabs as first-activity-ordered replay chapters, playing each visual recording fully before a fixed one-second explanatory handoff.
  • Keep the selected tab, event timeline, warnings, scrubber, rrweb viewport, and 1x/2x/4x speed on one tab-local transport with one live Replayer.
  • Skip missing visual chapters with stable full-list numbering, support manual reset/cancellation and sequence restart, and safely absorb late recording revisions without stale timers or false completion.

This is built from the clean main replay. It does not reuse the camera, global-clock, or double-buffer orchestration from #2019.

Test plan

  • bun run scripts/run-bun-test.ts apps/claw-app/screens/replay/Replay.test.tsx apps/claw-app/screens/replay/ReplayViewport.test.tsx apps/claw-app/screens/replay/PlaybackTransport.test.tsx apps/claw-app/screens/replay/tab-view.test.ts apps/claw-app/screens/replay/replay-events.test.ts apps/claw-app/screens/replay/replay.data.test.ts
  • bun run --filter @browseros/claw-app typecheck
  • bun run check
  • bun run test

All Replay component regressions run under React Strict Mode.

@shadowfax92

Copy link
Copy Markdown
Contributor Author

Greptile (@greptileai) review

@shadowfax92

Copy link
Copy Markdown
Contributor Author

Claude (@claude) review

@claude

claude Bot commented Jul 24, 2026

Copy link
Copy Markdown

Claude finished Nikhil (@shadowfax92)'s task in 2m 39s —— View job


Claude finished the review

Todo list

  • Gather context (CLAUDE.md, diff, changed files)
  • Understand request (code review of PR feat: play replay tabs as sequential chapters #2024)
  • Review replay.data.ts changes
  • Review use-playback.ts changes
  • Review Replay.tsx changes (main logic)
  • Review test coverage
  • Post final review feedback

Summary

This is a large, well-tested change (27 new/updated cases in Replay.test.tsx, all under Strict Mode) that turns tab replay into a sequential-chapter player. The git history shows this already went through several self-driven review-fix rounds (address sequential chapter review findings, make chapter loading revision-safe, handle recording load edge cases, resume growing chapter recordings), and it shows — the edge cases I'd normally flag (races between metadata revisions, growing recordings, live sessions, manual overrides) already have dedicated tests. CI is green except the still-running Tests job.

Findings

1. Replay.tsx concentrates a lot of orchestration state in one component (packages/browseros-agent/apps/claw-app/screens/replay/Replay.tsx:45-352)
The component owns 12 refs plus several useStates to drive the chapter state machine (auto-start, empty-sequence detection, chapter-end detection, transition scheduling, pending-tab-seek flushing). It's currently correct per the test suite, but the sheer number of interacting refs (autoStartedSessionRef, operatorControlledSessionRef, emptySequenceSessionRef, reachedChapterEndRef, pendingTabSeekRef, pendingTabPlaybackRef, ...) makes it hard to reason about by reading the component alone — you have to hold the whole cross-product of session/tab/transition state in your head. Consider extracting the sequence-orchestration logic (lines ~217-510) into a dedicated hook (e.g. useChapterSequence) in a follow-up, purely for readability/testability in isolation — not a blocker for this PR given the test coverage.

2. Silent error swallowing in the event-snapshot retry loop (packages/browseros-agent/apps/claw-app/screens/replay/replay.data.ts:153-179)

try {
  const result = await eventsQuery.refetch()
  ...
} catch {}

Failed refetches (network errors, non-404 API errors) are swallowed with no logging before the 10s retry is armed. This is a minor debuggability concern — if event downloads are silently failing, an operator watching a "stuck" replay has no console signal to go on. Consider a console.warn in the catch, consistent with the existing pattern in ReplayViewport.tsx:138-141.

3. Minor: EVENT_SNAPSHOT_RETRY_MS / CHAPTER_TRANSITION_MS are local magic-number constants (replay.data.ts:33, Replay.tsx:27-28)
These are fine to keep local since they're UI/component-specific timings rather than cross-cutting operational timeouts (unlike packages/shared/src/constants/timeouts.ts), but flagging per repo convention in case there's a project preference to centralize even UI transition durations — non-blocking.

4. No functional bugs found. I traced the trickier interactions by hand:

  • The revision-tracking refetch chain in replay.data.ts (refreshChainRef, requestedRevision) correctly serializes fetches and re-arms retries against the current sessionRevision even when the retry timer was armed for a stale revision (it's cleared at the top of the effect on every new revision).
  • usePlayback.play()/togglePlay() correctly restart from 0 only when time >= totalSeconds, and guard isPlaying on totalSeconds > 0 for empty/static chapters.
  • tab-view.ts's playableTabStream WeakMap cache is keyed by the raw events array reference, which naturally invalidates the memo (and the mounted Replayer in ReplayViewport.tsx, since events is an effect dependency there) whenever a chapter's recording grows — consistent with the "resume growing chapter recordings" fix in the last commit.

Verification

  • Did not execute bun run test / bun run check locally (no node_modules installed in this sandbox and installing was out of scope for a review-only pass); relying on CI, which shows Code Quality and Claude Code checks green and the Tests workflow still in progress.

@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds sequential, tab-local playback of replay recordings.

  • Orders tabs as chapters, skips chapters without visual snapshots, and displays one-second handoffs.
  • Coordinates chapter selection, rrweb playback, transport state, completion, cancellation, and late recording revisions.
  • Adds revision-aware event loading and extensive Strict Mode regression coverage.

Confidence Score: 3/5

The event-refresh serialization should be fixed before merging because an obsolete slow request can prevent the current replay from loading.

Revision guards reject stale payloads, but all refetches share a persistent promise chain, so a slow or hanging request blocks newer session and revision downloads before those guards can run.

packages/browseros-agent/apps/claw-app/screens/replay/replay.data.ts

Important Files Changed

Filename Overview
packages/browseros-agent/apps/claw-app/screens/replay/Replay.tsx Introduces chapter sequencing, transitions, tab-local transport state, late-revision recovery, and completion handling.
packages/browseros-agent/apps/claw-app/screens/replay/replay.data.ts Adds revision-attributed event snapshots and retries, but serializes current loads behind obsolete requests.
packages/browseros-agent/apps/claw-app/screens/replay/use-playback.ts Adds explicit play and pause operations while retaining speed and chapter restart behavior.
packages/browseros-agent/apps/claw-app/screens/replay/Replay.test.tsx Adds broad Strict Mode coverage for chapter progression, skipped tabs, cancellation, restart, and recording revisions.

Sequence Diagram

sequenceDiagram
  participant Metadata
  participant ReplayData
  participant Replay
  participant Player as rrweb Player
  Metadata->>ReplayData: Publish recording revision
  ReplayData->>ReplayData: Fetch matching event snapshot
  ReplayData->>Replay: Provide ordered tab chapters
  Replay->>Player: Play selected chapter
  Player-->>Replay: Reach chapter end
  Replay->>Replay: Show one-second handoff
  Replay->>Player: Reset and play next visual chapter
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/browseros-agent/apps/claw-app/screens/replay/replay.data.ts:150
**Obsolete refresh blocks current replay**

When an event request for an old revision or previous route session responds slowly or never settles, the persistent promise chain holds every newer refetch behind it, causing the current replay to remain empty with `eventsLoaded` false until that obsolete request finishes.

Reviews (1): Last reviewed commit: "fix(replay): resume growing chapter reco..." | Re-trigger Greptile

Comment thread packages/browseros-agent/apps/claw-app/screens/replay/replay.data.ts Outdated
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds sequential, tab-local replay chapters with automatic handoffs and revision-aware event loading.

  • Orders recorded tabs as chapters and skips tabs without playable visual recordings.
  • Keeps playback speed, timeline, viewport, warnings, and transport synchronized to the selected chapter.
  • Adds cancellation, restart, late-recording revision handling, and extensive Strict Mode regression coverage.

Confidence Score: 5/5

The PR appears safe to merge with no concrete blocking or independently actionable issues identified.

The chapter lifecycle, manual controls, timer invalidation, session resets, and revision-aware refresh behavior are internally coordinated and covered across the principal reachable playback states.

Important Files Changed

Filename Overview
packages/browseros-agent/apps/claw-app/screens/replay/Replay.tsx Introduces chapter selection, sequential advancement, transition cancellation, completion/restart handling, and tab-local replay presentation.
packages/browseros-agent/apps/claw-app/screens/replay/replay.data.ts Adds revision-attributed event snapshots, serialized refreshes, retry handling, and an explicit current-revision loading state.
packages/browseros-agent/apps/claw-app/screens/replay/use-playback.ts Adds explicit play and pause operations while preserving chapter-local seek, speed, and completion behavior.
packages/browseros-agent/apps/claw-app/screens/replay/Replay.test.tsx Adds broad Strict Mode coverage for chapter sequencing, skipped recordings, manual cancellation, revisions, restarts, and cleanup.
packages/browseros-agent/apps/claw-app/screens/replay/PlaybackTransport.test.tsx Extends transport coverage for explicit pause, resume, completion restart, and speed preservation.

Sequence Diagram

sequenceDiagram
  participant User
  participant Replay
  participant Viewport as ReplayViewport
  participant Player as rrweb Replayer
  User->>Replay: Open replay
  Replay->>Replay: Select first playable chapter
  Replay->>Viewport: Mount tab-local events
  Viewport->>Player: Create Replayer
  Replay->>Player: Play chapter
  Player-->>Replay: Report local playback time
  Replay->>Replay: Detect chapter completion
  Replay->>Replay: Select next playable tab
  Replay-->>User: Show one-second chapter handoff
  Replay->>Player: Play next chapter
  Replay-->>User: Show replay complete
Loading

Reviews (2): Last reviewed commit: "fix(replay): resume growing chapter reco..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

✅ Tests passed — 1718/1722

Suite Passed Failed Skipped
agent 350/350 0 0
build 34/34 0 0
claw-app 239/239 0 0
⚠️ claw-mcp 0/0 0 0
⚠️ claw-onboard 0/0 0 0
⚠️ claw-server-rust-quality 0/0 0 0
⚠️ claw-server-rust 0/0 0 0
server-agent 313/313 0 0
server-api 171/171 0 0
server-browser 10/10 0 0
server-integration 10/10 0 0
server-lib 299/300 0 1
server-root 38/41 0 3
server-tools 254/254 0 0

View workflow run

@shadowfax92
Nikhil (shadowfax92) merged commit 32fad6e into main Jul 24, 2026
22 checks passed
Nikhil (shadowfax92) added a commit that referenced this pull request Jul 24, 2026
Sequential tab chapters (#2024) made the visible tab's rrweb stream the
transport, so any tool that ran after its tab stopped emitting DOM events
became unreachable. In the 2026-07-24 Trendshift session tab 1 records
9.003s of events but receives tools at 24.225s, 26.717s and 38.321s; the
chapter ended at 9.003s, and only 6 of 16 tab-attributed tools fell inside
their tab's span at all. Untabbed tools such as name_session were filtered
out of every chapter.

Replaces chapter orchestration with one global activity clock and a pure
session plan:

- session-replay.ts derives the current tool, the visible tab, and the
  tab-local projection as a function of global time. No camera history, so
  a backward seek, a forward seek, and a live refresh all agree.
- usePlayback owns activity time from animation-frame timestamps instead of
  mirroring rrweb, and resumes when a live recording grows past where it
  stopped.
- ReplayViewport keeps its single Replayer and aligns it to the projected
  time, holding a boundary frame while global activity continues past the
  end of the track. Caption and address bar now have separate sources.
- The action timeline is global again: every tool is listed, untabbed and
  no-visual tools stay current without moving the camera, and a tab click
  pins the camera only.

Tool starts come from the durationMs already on the dispatch row; missing,
negative, and non-finite values fall back to completion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant