# 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/session-context.ts` — `buildSessionContext()` converts persisted `branch_summary` entries into LLM-visible `branchSummary` messages on rebuilt context. - `packages/coding-agent/src/tools/index.ts` — registers the tool and shares the `checkpoint.enabled` gate. ## 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 text - `rewound: true` The returned tool result is not the final rewind. `AgentSession` waits until `turn_end`, then applies the rewind side effects asynchronously. ## Flow 1. `RewindTool.createIf()` in `packages/coding-agent/src/tools/checkpoint.ts` hides the tool from subagents. 2. `RewindTool.execute()` rejects subagent calls with `ToolError("Checkpoint not available in subagents.")`. 3. It rejects calls with no active checkpoint using `ToolError("No active checkpoint.")`. 4. It trims `params.report`; if empty, it throws `ToolError("Report cannot be empty.")`. 5. It returns a `toolResult()` with `details.report` and `details.rewound = true`. 6. On the rewind tool result's `message_end`, `AgentSession` extracts the report from `details.report` or the first text content block and stores it in `#pendingRewindReport`. 7. On `turn_end`, if `#pendingRewindReport` is set, `AgentSession.#applyRewind()` runs. 8. `#applyRewind()` computes `safeCount = clamp(checkpointMessageCount, 0, agent.state.messages.length)`, calls `agent.replaceMessages(agent.state.messages.slice(0, safeCount))`, then resets the advisor runtime via `#advisorRuntime?.reset()`. 9. It then calls `sessionManager.branchWithSummary(checkpointEntryId, report, { startedAt })`. That moves the persisted session leaf back to the checkpoint entry and appends a new `branch_summary` entry whose `summary` is the rewind report. 10. If `checkpointEntryId` no longer resolves, it logs a warning and falls back to `branchWithSummary(null, report, { startedAt })`, branching from root instead. 11. `#applyRewind()` appends a hidden in-memory custom message `{ customType: "rewind-report", content: report, display: false }` and persists the same payload through `sessionManager.appendCustomMessageEntry("rewind-report", ...)` with `details = { startedAt, rewoundAt }`. 12. Finally it clears `#checkpointState` and `#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-report` carrying 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_summary` and `custom_message` entries into the session `.jsonl` file through normal `SessionManager` append persistence. - Session files are named `_.jsonl` in the session directory; default directory selection is documented in `SessionManager.create()` as `~/.omp/agent/sessions//` when no override is passed. - User-visible prompts / interactive UI - The tool result itself is visible. - The persisted `branch_summary` becomes an LLM-visible `branchSummary` message when context is rebuilt from `SessionManager.buildSessionContext()` (via `createBranchSummaryMessage()` in `session-context.ts`); `packages/agent/src/compaction/messages.ts` renders it as a user-role text message using `packages/agent/src/compaction/prompts/branch-summary-context.md`. - The persisted `rewind-report` custom message also participates in rebuilt LLM context because `custom_message` entries are converted through `createCustomMessage()`. - Background work / cancellation - Rewind application is deferred to `turn_end`. There is no separate job object or cancel handle. ## Limits & Caps - Availability is gated by `checkpoint.enabled`, default `false`, in `packages/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_000` in `packages/coding-agent/src/session/session-persistence.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, logs `Rewind branch checkpoint missing, falling back to root`, and branches from root. ## Notes - Checkpoint selection is implicit. `rewind` always targets the single `#checkpointState` captured by the last successful `checkpoint`; there is no checkpoint list, label, or ID parameter. - Restored state is transcript/session-tree state only: - in-memory `agent.state.messages` prefix up to `checkpointMessageCount` - persisted session leaf reset to `checkpointEntryId` or root fallback - retained rewind report as `branch_summary` and hidden `rewind-report` custom message - 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 new `branch_summary` entry and moves the leaf; it does not delete the abandoned path from the `.jsonl` session log. The active context is cut over to the new branch, but the old entries remain in session storage.