ADR 0043: Message-owned review snapshots and guarded rollback
- Status: Accepted
- Date: 2026-08-02
- Related: 03-tools-and-permissions · 04-data-storage · 06-host-rpc-protocol · 08-component-spec · E2E-057
- Supersedes: ADR 0042's Git-dependent review source, D098, and D179
Context
The previous Review implementation reconstructed each card from the current Git working tree. A commit therefore removed the evidence for an earlier tool message, and a later edit to the same path could make an old message appear to describe work it never performed. The same model had no safe way to restore a specific message's previous file content.
Review is a conversation feature, so its evidence must belong to the message that produced it rather than to a mutable repository snapshot.
Decision
- Before a workspace
WriteorEdit, host-core captures the previous file bytes in a session-scoped snapshot outside the workspace. After a successful tool, it writes a boundeddetails.reviewrecord into the tool result. The record contains the snapshot id, message/tool id, relative path, operation, added/modified/deleted status, addition/deletion counts, expandable hunks, active/rolled-back state, and whether rollback is reversible. - The renderer derives
InlineReviewCardand the Review panel's chronological history from persisted tool messages only. It never refreshes or matches a current Git diff. A card stays immediately after its owning tool row and remains visible after commit, workspace switching, and restart. review.rollback({sessionId, snapshotId})is a host-owned operation. Before writing, host-core verifies that the current file hash equals the post-tool hash recorded in the snapshot. A mismatch returnsconflictand leaves the file untouched. A match restores the previous bytes or removes a file that the message created, then persistsstate: "rolledBack"on the tool row.- Snapshot storage is bounded and session-owned:
<data_dir>/review-changes/<sessionId>/<snapshotId>/{before,meta.json}. Session deletion removes it; startup removes directories for missing sessions. Forked transcripts retain visible diff evidence but mark rollback unavailable because the source snapshot belongs to another session. - Scratch-root writes, failed tools, and tools without a structured workspace path do not create review records. Large or binary files may still show status/count metadata while omitting hunks and rollback when the bounded previous content cannot be retained.
Consequences
- Committing after a tool no longer makes its review number or card disappear.
- Every visible diff is tied to the exact message that produced it, including additions, deletions, and modifications.
- Rollback is explicit, idempotent, and refuses to overwrite later work.
- Review no longer promises to describe unrelated shell mutations; structured Write/Edit results are the durable review boundary.
- Snapshot bytes add host-owned local storage, bounded by file and diff caps.
Alternatives rejected
- Keep reading Git HEAD: commits erase the evidence and cannot identify the message responsible for a later same-path edit.
- Store only a renderer patch: the renderer cannot safely restore files, and the patch would be lost on restart or session reload.
- Rollback unconditionally: it could overwrite a user's later edit or an external change, so the post-tool hash guard is mandatory.