fix(replay): walk full timeline ancestry in get_full_timeline_steps/spans#175
Conversation
…pans Previously these methods walked exactly one parent level, so a 3-level chain (root -> mid-fork -> leaf-fork) caused the leaf to lose visibility of every step that originated on the grandparent. Visible bug on dev1 session ray-agent-7bea73fa (2026-05-25): a replay timeline forked from an edited-fork forked from main rendered as 1 step in the dashboard instead of all 4 inherited. The fix introduces an iterative ancestry_chain walk that records each ancestor's contribution clamp as the cumulative min(fork_at_step) of every fork-edge below it. The leaf admits all of its own owned steps; each parent contributes only steps with step_number <= its clamp. Closer-to-leaf rows shadow ancestor rows (preserving the existing owned-over-inherited dedup invariant). Cycle defense via a HashSet of visited ids, plus a depth cap of 64 (MAX_ANCESTRY_DEPTH) as a final guard against pathological graphs. Tests: - 4 new unit tests in rewind-replay (3-level inheritance, two clamp directions, span symmetry). - 1 web integration test exercising the dashboard's /steps endpoint through a 3-level fork chain. - Removed the now-resolved "only walks one parent level up" caveat in test_fork_and_edit_step_inherited_step. Track 1 bumps per CLAUDE.md (workspace v0.15.1 already released): Cargo.toml/Cargo.lock 0.15.1 -> 0.15.2 python/rewind_cli.py CLI_VERSION 0.15.1 -> 0.15.2 python-mcp/rewind_mcp_cli.py CLI_VERSION 0.15.1 -> 0.15.2 python-mcp/pyproject.toml 0.13.11 -> 0.13.12 Track 2 bumps (rewind-agent 0.17.0 already on PyPI; python/ touched): python/pyproject.toml 0.17.0 -> 0.17.1 python/rewind_agent/__init__.py 0.17.0 -> 0.17.1 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review notes after reading the full diff + running tests:
One potential regression to consider:
Could we either (a) remove the hard cap, or (b) make it a soft guard + add a regression test for a >64-depth acyclic chain? |
PR #175 review: the visited-set already rejects cycles, and the walk is naturally bounded by timelines.len() since each iteration consumes one new id from the same finite pool. The 64-level depth cap can therefore only false-positive on legitimate deep edit/fork histories — never catch a bug the cycle check would miss. Removing it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Good catch — applied option (a) in 8359f47. The visited-set already rejects cycles, and |
|
Re-checked after 8359f47. No new blockers from my side:
Remaining warning seen in |
Summary
get_full_timeline_stepsandget_full_timeline_spansnow walk the entire ancestor chain via an iterativeancestry_chainhelper that applies a cumulativemin(fork_at_step)clamp per level. Previously they walked exactly one parent level, dropping every step that originated on the grandparent.python/was touched and 0.17.0 is published).Repro (pre-fix)
On dev1 session
ray-agent-7bea73fa(2026-05-25): a replay timeline forked from an edited-fork forked from main rendered as 1 step in the dashboard instead of all 4 inherited. Same shape on every 3+ level fork chain.Test plan
rewind-replaycover 3-level inheritance, both clamp directions, and span symmetry — all fail before the fix, pass after.test_steps_endpoint_walks_three_level_inheritanceexercises the/api/sessions/{id}/stepsendpoint through a 3-level fork chain.cargo test --workspace— all suites green (0 failed across 17+ test binaries).cargo clippy -p rewind-replay --all-targets -- -D warnings— clean. (rewind-web has pre-existing clippy errors in unrelated test files that were not introduced by this change.)test_fork_and_edit_step_inherited_step.Version bumps
Per CLAUDE.md decision tree:
crates/touched):Cargo.toml,Cargo.lock,python/rewind_cli.py,python-mcp/rewind_mcp_cli.pyall 0.15.1 → 0.15.2;python-mcp/pyproject.toml0.13.11 → 0.13.12.python/rewind_cli.pytouched):python/pyproject.tomlandpython/rewind_agent/__init__.py0.17.0 → 0.17.1.🤖 Generated with Claude Code