Add /fork and /rewind slash commands (stack 2/2) - #2
Draft
Aarya2004 wants to merge 9 commits into
Draft
Conversation
added 9 commits
September 1, 2026 09:00
The specs, the parsed variants, and the handler slots land first with stub bodies so the exhaustive switches and the registry-walking router test prove the wiring before any behavior exists. `route` now splits into `parse` plus `dispatch` so a caller can inspect the parsed command once instead of parsing it twice. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
A rewind runs only when the identical request is repeated. The gate arms on the whole target, so a turn arriving between the preview and the repeat re-arms rather than firing a rewind the user never saw described. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
`dropHistoryTurnsAfter` owns freeing the dropped turns and clamping the model-context cursor. The durable store keeps its slice reallocation and the live runtime shrinks its list, but neither repeats the free-and-clamp rule, so an in-place rewind cannot drift from the stored one. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
`/rewind <count>` drops trailing turns from the live session. The shell already holds the session writer lock, so the truncation happens in process and commits through the live replacement path instead of through `Store.rewindSession`, which would block on the lock this shell owns. Both the confirmation and the completion say that file changes are untouched, because the equivalent command in other agents restores files and this one does not. Any command other than a repeated `/rewind` disarms the gate. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
`/fork <turn>` branches the live session and moves the shell into the branch. The session is closed before the store call because `forkSessionCopy` takes the source's writer lock, which this process holds while a session is open. That makes every failure past the close a shell with no session, so the source is reopened on each failing path and the notice always says which session the shell ended up on. Background work carries forward rather than stopping, because the source survives a fork and its in-flight commands belong to the branch too. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
Both commands accept 1 through the live history length. Holding that rule in one tested function keeps the two ranges from drifting. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
The e2e file drives the real shell through tmux: it builds turns against the fake gateway, proves the rewind needs two identical requests and that an intervening command cancels it, proves the fork names both ids and that the next prompt lands in the branch while the source keeps every turn, and reads every session back off disk afterwards. Classified verification-only, since branching and undo are deliberate rare operations that must stay correct without being made hot. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
A successful fork always has both ids and always lands in the branch; a failed one always has a reason and lands somewhere else. Modelling them as one struct left `forked_id` and `problem` coupled by convention. One `forkFailure` helper now owns the rule that every failure past the session close reopens a session before answering, which also closes the path where an allocation failure returned without reopening one. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
Only `RewindTarget` crosses into the command layer. Claude-Session: https://claude.ai/code/session_01Hjm7J6N3SL5Y62TJ3bPxwD
This was referenced Sep 1, 2026
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.
Review mirror of vercel-labs#568, the interactive half of vercel-labs#537. Stacked on #1.
The base branch here is stack 1/2, so this diff shows only the nine slash-command commits. When #1's branch changes, this PR tracks it. Review and discussion belong on the upstream PR; do not merge this one.