feat(tui,cpu): deep rewind via keyframes + :rewind-budget#412
Merged
Conversation
The per-step snapshot ring only reaches back its capacity (256 steps). Add keyframe-based deep rewind so users can jump back into the last millions of steps (issue #392): - cpu.KeyframeRing holds periodic full-RAM snapshots; CPU.SnapshotFull captures all 256 pages. One keyframe every 4096 steps (keyframeInterval). - :rewind N reconstructs an arbitrary earlier step by restoring the nearest keyframe <= target and replaying forward to the exact step. Small jumps still pop the fine ring exactly. - :rewind-budget MB caps keyframe memory (ring cap = budget / 64 KiB); reach = cap * interval, shown in the status bar as deep:<reach>@<budget>. Memory is a ceiling, not a reservation. Interval 4096 (not the issue's 1k) so 256 MiB reaches ~16.7M steps while a deep rewind replays <=4096 instructions — benchmarked ~1.3 ms incl. replay vs the 100 ms acceptance. A step-0 keyframe is seeded on the first step so sub-interval targets are reachable. StepCount tracks position; `<` and reset keep it in sync. Forward replay assumes deterministic execution between keyframes (buffered input is snapshotted). No state-format change — StepCount and keyframes are ephemeral. cpu ring logic is unit-tested apart from the TUI; deep-rewind exactness is verified byte-for-byte against a RAM-mutating loop ROM. Closes #392
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Final v1.3.0 Theme A sub-issue — deep reverse-step for long runs (#392).
Problem
The per-step snapshot ring is a fixed 256-entry FIFO (≤16 MiB), so reverse-step only reaches back 256 steps. The issue framed this as unbounded memory growth — it is not; the real limit is reach. Storing a delta for every one of millions of steps is infeasible, so deep rewind uses periodic full snapshots + forward replay.
What
cpu.KeyframeRing— budget-bounded ring of full-RAM snapshots.CPU.SnapshotFullcaptures all 256 pages; reuses the existingRestore.keyframeInterval(4096) steps, captured during forward execution (incl. free-run).:rewind N— reconstructs the state N steps back. Small jumps pop the fine ring exactly; deep jumps restore the nearest keyframe ≤ target and replay forward to the exact step (rewindToStep→stepReplayunder areplayingRewindguard).:rewind-budget MB— resizes the ring (cap = budget / 64 KiB). Reach = cap × interval, shown in the status bar asdeep:<reach>@<budget>.Acceptance
BenchmarkDeepRewind), 75× marginA note on the issue numbers
The scope as written is internally inconsistent: full 64 KiB keyframes every 1k steps cannot reach 10M under 256 MiB (that ceiling buys ~4M). I used interval 4096 instead — 256 MiB reaches ~16.7M while a deep rewind still replays ≤4096 instructions (sub-ms). A step-0 keyframe is seeded so sub-interval targets are reachable. Determinism caveat: forward replay assumes deterministic execution between keyframes; buffered keyboard input is snapshotted so it replays correctly. Delta-from-previous-keyframe compression (smaller keyframes → more reach per byte) is a clean future optimization.
Tests
cpu:SnapshotFullround-trip,KeyframeRingcap-from-budget /Nearest+ eviction /Bytes/ nil-safety.tui: deep-rewind byte-exact reconstruction vs a RAM-mutating loop ROM, fast-path vs deep-path selection, fine-ring continuity after landing,:rewind-budgetresize/clamp/reject, beyond-reach, reset,humanCount, latency benchmark.Docs
README reverse-step section rewritten (the old "free-run does not snapshot" line was stale) + deep-rewind table; help modal entries;
docs/context.mdmerged-PR note with the inconsistency finding.Closes #392