rewind
End an active checkpoint by pruning exploratory context and retaining a concise report.
Source
- Entry:
packages/coding-agent/src/tools/checkpoint.ts - Model-facing prompt:
packages/coding-agent/src/prompts/tools/rewind.md - Key collaborators:
packages/coding-agent/src/session/agent-session.ts— validates pending rewind state, applies the actual rewind, and injects the retained report.packages/coding-agent/src/session/session-manager.ts— branches the persisted session tree and appends persisted summary/report entries.packages/coding-agent/src/session/messages.ts— converts persistedbranch_summaryentries into LLM-visible branch-summary messages on rebuilt context.packages/coding-agent/src/tools/index.ts— registers the tool and shares thecheckpoint.enabledgate.
Inputs
| Field | Type | Required | Description |
|---|---|---|---|
report |
string |
Yes | Investigation findings. execute() trims it and rejects the empty result. |
Outputs
The tool returns a single text result plus structured details:
- text body:
Rewind requested.Report captured for context replacement.
details:report: string— trimmed report textrewound: true
The returned tool result is not the final rewind. AgentSession waits until turn_end, then applies the rewind side effects asynchronously.
Flow
RewindTool.createIf()inpackages/coding-agent/src/tools/checkpoint.tshides the tool from subagents.RewindTool.execute()rejects subagent calls withToolError("Checkpoint not available in subagents.").- It rejects calls with no active checkpoint using
ToolError("No active checkpoint."). - It trims
params.report; if empty, it throwsToolError("Report cannot be empty."). - It returns a
toolResult()withdetails.reportanddetails.rewound = true. - On
tool_execution_end,AgentSessionextracts the report fromdetails.reportor the first text content block and stores it in#pendingRewindReport. - On
turn_end, if#pendingRewindReportis set,AgentSession.#applyRewind()runs. #applyRewind()computessafeCount = clamp(checkpointMessageCount, 0, agent.state.messages.length)and callsagent.replaceMessages(agent.state.messages.slice(0, safeCount)).- It then calls
sessionManager.branchWithSummary(checkpointEntryId, report, { startedAt }). That moves the persisted session leaf back to the checkpoint entry and appends a newbranch_summaryentry whosesummaryis the rewind report. - If
checkpointEntryIdno longer resolves, it logs a warning and falls back tobranchWithSummary(null, report, { startedAt }), branching from root instead. #applyRewind()appends a hidden in-memory custom message{ customType: "rewind-report", content: report, display: false }and persists the same payload throughsessionManager.appendCustomMessageEntry("rewind-report", ...)withdetails = { startedAt, rewoundAt }.- Finally it clears
#checkpointStateand#pendingRewindReport.
Modes / Variants
- Normal rewind: checkpoint entry exists; session history branches from that exact entry.
- Fallback rewind: checkpoint entry ID is missing from the current session tree; rewind branches from root and logs a warning.
- Immediate turn-end apply: rewind side effects happen only after the surrounding assistant turn finishes, not inside
RewindTool.execute().
Side Effects
- Session state (transcript, memory, jobs, checkpoints, registries)
- Replaces in-memory conversation history with the prefix ending at the checkpoint tool result.
- Adds a hidden custom message
rewind-reportcarrying the retained report. - Clears the active checkpoint state and pending rewind report.
- Repositions the persisted session leaf to the checkpoint branch point and appends new session entries.
- Filesystem
- Persists the new
branch_summaryandcustom_messageentries into the session.jsonlfile through normalSessionManagerappend persistence. - Session files are named
<ISO-timestamp-with-:-and-.-replaced>_<uuidv7>.jsonlin the session directory; default directory selection is documented inSessionManager.create()as~/.omp/agent/sessions/<encoded-cwd>/when no override is passed.
- Persists the new
- User-visible prompts / interactive UI
- The tool result itself is visible.
- The persisted
branch_summarybecomes an LLM-visiblebranchSummarymessage when context is rebuilt fromSessionManager.buildSessionContext();messages.tsrenders it as a user-role text message usingpackages/agent/src/compaction/prompts/branch-summary-context.md. - The persisted
rewind-reportcustom message also participates in rebuilt LLM context becausecustom_messageentries are converted throughcreateCustomMessage().
- Background work / cancellation
- Rewind application is deferred to
turn_end. There is no separate job object or cancel handle.
- Rewind application is deferred to
Limits & Caps
- Availability is gated by
checkpoint.enabled, defaultfalse, inpackages/coding-agent/src/config/settings-schema.ts. - Top-level sessions only.
- Requires exactly one active checkpoint; there is no path to name or choose among multiple checkpoints.
- Report text must be non-empty after
trim(). - Rewind restores only the message prefix recorded by
checkpointMessageCount; there is no file restore, artifact restore, blob restore, or process restore path. - Persisted report/summary content is still subject to the global session persistence cap
MAX_PERSIST_CHARS = 500_000inpackages/coding-agent/src/session/session-manager.ts.
Errors
ToolError("Checkpoint not available in subagents.")— thrown for subagent sessions.ToolError("No active checkpoint.")— thrown when no checkpoint state is present.ToolError("Report cannot be empty.")— thrown when the trimmed report is empty.- Missing checkpoint entry IDs during apply do not fail the tool call;
#applyRewind()catches the error, logsRewind branch checkpoint missing, falling back to root, and branches from root.
Notes
- Checkpoint selection is implicit.
rewindalways targets the single#checkpointStatecaptured by the last successfulcheckpoint; there is no checkpoint list, label, or ID parameter. - Restored state is transcript/session-tree state only:
- in-memory
agent.state.messagesprefix up tocheckpointMessageCount - persisted session leaf reset to
checkpointEntryIdor root fallback - retained rewind report as
branch_summaryand hiddenrewind-reportcustom message
- in-memory
- Not restored:
- filesystem contents
- git state
- artifacts under
packages/coding-agent/src/session/artifacts.ts - blob-store payloads under
packages/coding-agent/src/session/blob-store.ts - prompt history rows in
packages/coding-agent/src/session/history-storage.ts - auth or other agent storage in
packages/coding-agent/src/session/agent-storage.ts
- There is no concurrent-edit reconciliation. If code or session-adjacent state changes during the checkpoint window, rewind does not merge or revert them; it only drops conversation context and rewires the session branch.
- Rewind is not destructive to persisted session history.
branchWithSummary()appends a newbranch_summaryentry and moves the leaf; it does not delete the abandoned path from the.jsonlsession log. The active context is cut over to the new branch, but the old entries remain in session storage.