OpenProgram / Runtime operations / Canonical design

File changes, Review, and history recovery

This page defines file attribution, single-turn Undo, historical Revert, multi-turn Rewind, conversation Branch, Review scopes, conflict handling, and recovery storage. The chat visual specification controls appearance only; implementation, tests, and product claims follow these semantics.

Current implementation · unified file window and historyLocal resources · preview and editingScope · App / Web / TUI / runtime

Return to the previous browsing location

Folder A → subfolder B → file 1 → file 2. Back retraces previous locations; Forward restores later ones. Opening a different location after Back replaces forward history. Folders restore paths, expansion, and scroll positions; files retain existing autosave behavior.

Loading another list page, background refresh, and file-size updates preserve the viewport. Only explicit user positioning, search navigation, or navigation restoration may change browsing position.

Implementation status and boundaries

Navigation/scroll stability and preserving session routes while opening files passed functional review, quality review, and complete verification. Retain the latest 100 locations per current project, within the current window only. Reuse existing tabs/navigation; do not modify disk files, add polling, or mix navigation history with file-version History.

View, edit, and recover file versions in one window

Files open in preview first and autosave after entering edit mode. History shows human/model changes and checks current versions before recovery. Below is an interactive design demonstration; format engines and saving remain under implementation acceptance.

Proposal.docx

Switch tabs after editing

Recent edits persist first as local drafts, then write in the background. Returning resumes editing; no Save action or persistent Saved label is needed.

Another program also changed the file

Show “File changed by another operation.” Retain the draft, offer disk-version inspection or Save a copy, and never overwrite automatically.

Open an old version

Use the current file’s previewer. Recovery is a new recorded operation preserving pre-recovery content and supporting reapplication.

Actual targets and reuse options for common formats

Text, code, Markdown: preview, source editing, autosave. DOCX, PPTX, XLSX: complete local-engine preview/editing, verified by real-file open, modification, export, and reopen; text extraction cannot replace page/slide previews. Include DOC/PPT/XLS and ODT/ODS/ODP compatibility tests; conversion-only engines explicitly save a new format rather than overwrite originals. CSV/TSV offer at least table preview and text editing. PDF: pages, zoom, search; annotations/editing only as actually supported. PNG/JPEG/WebP/BMP/GIF/SVG/TIFF: preview; static bitmaps offer crop, rotate, annotation, while ordinary save must not silently rasterize animation/vector content. PSD: composite and layer-information preview, retaining original PSD; enable original-format editing only after lossless round-trip verification. Audio/video reuse local HTML players. Unparseable, encrypted, oversized, or unsupported files show explicit status and download access.

Office candidates include ONLYOFFICE Docs, OnlyOffice browser/WASM and LibreOffice WASM. The default must deploy locally without uploading documents to third-party sites. Complete-server options remain configurable adapter candidates, not the only capability when absent from default installation.

PDF.js is a PDF viewer candidate;TOAST UI Image Editor is a bitmap-editor candidate, with usageStatistics disabled and bundled resources;ag-psd is a PSD-preview candidate whose color-mode, text-layer, and effect limitations require preserving originals.Photopea supports embedding but is third-party hosted, so never load it or send local files by default. Final selection depends on pinned source versions and local sample validation.

Unified opening, editing, and version protocol

File references carry stable project/session ownership and relative paths; display paths are not credentials. Capability detection verifies extension, type, and contents before choosing adapters. Adapters receive only document content/version, not arbitrary disk access, and expose bytes/Blob export, change/error events, and destroy. Large Office/image resources load only for relevant files, without slowing initial chat.

Human edits and model writes share version validation, complete-file publication, and immutable before/after storage. Existing project_file_write idempotency records hold results/fingerprints, not recoverable versions; this adds actual version storage. Human records use actor=user; model records link real session/turn, without fabricated chat turns or human history becoming sidebar sessions. History aggregates by file while model turn Review retains attribution.

Retain versions by ownership: human project edits belong to projects; model records retain actual sessions/turns. Aggregate indexes reference existing versions without duplicating source documents. Archived sessions remain readable; permanent deletion removes their entries/owned versions under existing rules, and caches must not redisplay originals. Residual Memory sources show “Original session deleted” or lose links, without source copies. Project files and independent human history survive deletion of individual chats.

Autosave and version archival are separate. Editor undo handles immediate changes. Drafts persist first; modified files publish after a short coalescing window. History groups continuous editing periods, approximately five minutes apart; switching documents, ending editing, or recovery also closes periods. File saves do not wait five minutes. Each publication validates the read revision; retries are idempotent and out-of-order responses cannot overwrite newer drafts. Save failures retain drafts and retryable errors. Restart reads persisted records, never reconstructing past versions from current files.

Rich-editor lifecycles are independent of tabs. Hide views on switching while exporting engines stay alive; release engines only after newest content reaches durable drafts. Office iframes do not recreate within a document session because React remounts or DOM moves. Close, rename, and recovery await final export; failure retains editor/draft. Preview/edit reuse one instance; read-only history instances cannot write current files.

Paper reading and annotations

The upstream viewer stylesheet is scoped to the PDF reader, including its root variables. Generic names such as .sidebar cannot change the surrounding application shell.

The PDF workspace follows the compact reading layout in the supplied PDF Expert reference: the existing OpenProgram document tab stays above a flat toolbar, a collapsible left sidebar contains thumbnails and the document outline, and the remaining space shows continuous PDF pages. Reading controls provide page navigation, fit-width/fit-page and numeric zoom, text selection, in-document links and highlighted search results. Only implemented Reading and Annotate tools appear; original-text editing, OCR, page surgery and format conversion are outside this iteration.

The visual system inherits OpenProgram's typography and light/dark tokens: neutral toolbar surfaces, white paper, dark reading background, subdued dividers and one blue selection accent. Reference palette: ink #202124, toolbar #27272a, canvas #151517, paper #ffffff, divider #414145 and focus #4a90e2. Toolbar labels use the application font at 13px; controls are 32px high. Desktop uses a single reading toolbar with a contextual annotation row; narrow panels wrap controls without covering document text. The sidebar is 180px wide and removable. The implementation uses actual rendered pages, with no placeholder content or decorative dashboard elements.

Use the already pinned PDF.js 6.3.289 legacy viewer library, text layer, link service, find controller and annotation editor. Retain its local module/worker compatibility and production CSP. The upstream viewer source defines the lifecycle and editor APIs. PDF Expert's Mac feature reference establishes the reading and annotation comparison. The alternative EmbedPDF viewer is not adopted for this iteration: replacing the decoder and introducing a second rendering engine is unnecessary for the requested reading, highlight and text-note capabilities.

Copying a selection in the PDF text layer joins layout line breaks automatically. Preserve paragraph breaks and literal punctuation, join CJK text without inserted spaces, preserve ordinary hyphens and remove discretionary soft hyphens. This is a local clipboard transform; it never edits the PDF or applies to search fields, annotation text editors or other application content. A visible checkbox allows the reader to keep original line breaks.

Project PDFs support highlight and free-text note annotations through PDF.js. Save standard PDF annotations back through the existing DocumentController rich-editor lease, durable draft store and optimistic revision checks. Debounced export, explicit save, close, history restore and rename use the same controller ownership as Office/raster documents. Draft-byte updates must not recreate a live viewer or lose its undo stack. History snapshots and attachments remain read-only. No PDF-supplied scripting or external document upload is enabled; original bytes, input and canvas limits, errors and download remain available.

Acceptance uses actual FileViewer/DocumentWindow entries under production CSP and desktop-compatible APIs. Verify continuous nonblank pages and selectable text, clipboard payload including prose/CJK/paragraph cases, page/sidebar/outline/zoom/search behavior, readonly history/attachments, highlight and note creation, save and close/reopen using real PDF bytes, persisted annotations through a separate decoder, failure retention and no obsolete editor publication. Existing file/history/controller, complete Web, repository contracts, browser and documentation checks remain required, followed by both independent reviews and installed-App inspection.

PDF runtime compatibility

The local PDF decoder is pinned to PDF.js 6.3.289. Its main module and worker use the matching legacy/build distribution, served at the existing same-origin /document-assets/pdfjs/ URLs. The upstream browser support guidance and package README prescribe this distribution for environments missing recent JavaScript APIs. The modern build requires Uint8Array.prototype.toHex, which the desktop's Electron 37 / Chromium 138 runtime lacks. The legacy pair supplies upstream compatibility code in both execution contexts; a main-page-only polyfill cannot repair the worker.

Keep the reviewed decoder version, local CMaps, fonts, WASM, license inventory, lazy loading, 64 MiB input bound, canvas bounds, disabled scripting and original-file download. Do not upgrade Electron or add application-owned global polyfills for this repair. The generated manifest identifies both the version and build distribution. Read-only PDF capabilities do not change.

The application shell permits connect-src 'self' blob: so decoders can read retained local file versions through their object URLs. This only extends local byte reads; external HTTP/WebSocket destinations remain blocked, and blob scripts, eval, objects and third-party frames are not enabled. PDF acceptance applies the actual shell policy to the test page, including a rejected external-fetch probe. A permissive standalone browser harness does not establish installed-App behavior.

Acceptance uses the public FileViewer entry to render nonblank pages, navigate, zoom, search text, recover from invalid input, and close/reopen without runtime errors. Run the same checks without native toHex and Math.sumPrecise in the main page and worker, plus an installed-desktop check with the reported PDF. The asset manifest must identify the exact staged module and worker bytes. These checks supplement the full Web, repository-contract, browser and documentation gates.

Optional Office installation

Office document support is an optional local component shared by presentations, word-processing documents and spreadsheets. Default App, runtime and Python builds omit its assets and do not download them. Opening an unsupported Office document checks local availability only. If missing, the document surface explains the supported formats, approximately 699 MiB download, local processing and ONLYOFFICE license, and offers Install and Cancel. Cancel dismisses the installation choice without downloading; the user may choose again. PDF viewing remains independent.

Only an owner-authenticated, local-origin POST initiates installation from a fixed release URL and pinned archive SHA-256. The installer bounds downloads and extraction, rejects unsafe archive paths and links, verifies the full existing Office manifest, and atomically publishes the pack to the profile cache. Concurrent requests share one installation. Failures retain the previous selected pack and remove temporary downloads. Once installed the current worker serves the parent module and isolated host without a restart, and the document opens automatically. Closing the document stops its UI requests; an explicitly requested installation may finish for other documents.

Previously installed profile resources remain usable. App-bundled resources from older releases are no longer selected. Development staging remains an explicit standalone command for editor tests; ordinary builds ignore stale staged packs. This change does not introduce a generic extension registry, automatic updates, uninstall controls or third-party document upload.

Office loading

Office startup keeps a full-size rendering surface beneath a centered, theme-aware loading overlay. The status follows the application language and distinguishes loading resources from opening the document. It uses no simulated percentage. Startup errors replace the status and expose an explicit retry.

The adapter uses the pinned upstream mount/activate API so closing a loading document immediately destroys its pending host. An AbortSignal cancels the availability request and pending activation; a bounded startup deadline begins before activation. Failed or cancelled instances never attach to the document controller. Preview/edit transitions preserve the existing editor and native undo. Independent Office origins, asset identity checks and persistence callbacks remain unchanged. This reduces unnecessary concurrent startup work; cold native conversion time is measured separately from the loading presentation.

Office loads pinned local resources from a separate origin allowing only resource-tree GET/HEAD, not main APIs, authentication, or WebSocket. Both pages validate origin, instance, and request; macros default off. Large resources install separately into local cache with user confirmation. Opening checks installation only, never downloads automatically. Remote deployments without a separate resource origin explicitly disable editing rather than redirect to third parties. PDF/images/media load on demand; the file window loads only when opened. KaTeX retains complete WOFF2 fonts without duplicate legacy WOFF/TTF fallbacks. Asset gates retain 2 MiB compressed initial transfer and 350 KiB compressed single-script limits.

Large binaries use bounded byte uploads or local staging, not ordinary chat messages. Enforce size while reading and clean temporary files on cancel; engine messages validate origin, instance, and request ID. Document scripts, macros, and active HTML/SVG gain no main-window authority. Third-party services require explicit user configuration and awareness that files are sent there. If safe original-format writes are unavailable, export a clearly labeled copy rather than writing PNG/OOXML bytes under another extension.

Complete delivery and acceptance, not partial-format success

Order: validate reusable engines; complete unified versions/binary publication; integrate previews/editors; unify preview-first, autosave, History; verify recovery, window switching, restart, and failures; perform independent specification/quality reviews and full combined-candidate checks; update the default App last. Every adapter needs genuinely valid files, not fabricated binaries as format evidence.

Acceptance individually covers Word, PPT, spreadsheets, images, PSD, PDF, text, media. Editable formats require actual modification, writeback, reopen, and version recovery. Read-only formats require actual rendering and explicit capabilities. Include concurrent external edits, interrupted writes, corruption, oversized files, cancellation, offline operation, project moves, and legacy history. Mark complete only when visible support, source, tests, and installed version agree.

One model, four operations

These four terms are distinct: they say whether code or conversation changes and whether one turn or a history segment is affected. Select an operation on the left to inspect its complete impact.

Operation
Four semantics do not mean four peer buttons.Turn cards show the applicable Undo or Revert; user checkpoints open Restore sheets; assistant footers provide Branch. After successful Undo, show Redo when strict preflight permits it; historical Revert’s inverse is Reapply. Both execute new reapply transactions without a separate linear redo stack.

Complete file-version lifecycle

One history entry handles text, Word, PPT, and later document tools. Complete files support recovery; text/format previews change display only, not original versions. Below shows user states; implementation details expand on demand.

Repeated edits to one file

Proposal.docx
First turn: original → modified
Further edits in the same turn: update final version

History retains the original; replace records only after successful new-version commit

Interrupted during save

Proposal.docx
Write outcome unconfirmed

Reopening shows incomplete state, never “no changes” or uncertain recovery

Corrupt history file

Unable to read file-change records

Preserve records and report errors; do not create empty history or continue overwriting targets

Normal saves, failure retries, and old-version protection

Each before/after uses an independently complete version file. Persist content, verify it, persist the version directory, then publish the manifest. Failed manifest updates leave previously referenced content intact. Failed attempts never overwrite published versions. Only after explicitly cancelling an unsuccessful attempt may retry reread the current file as before; successful modifications always retain the turn’s initial before.

Prepared and committed records are separate. Incomplete writes retain pending-confirmation markers; projections show no exact recovery, never infer script success or invent after from current disk. Cancelled attempts confirmed uncommitted are not displayed as changes. Corrupt/unsupported manifests return explicit errors; only genuinely absent manifests mean no records. Old manifests/blob_ref remain readable without bulk rewrites.

DeepSeek and Codex source evidence

DeepSeek’s JSONL persistence uses synchronized temporary files, exclusive publication, and directory synchronization, distinguishing corrupt from missing records;session repair marks interrupted tools as outcome unknown instead of inventing success. Adopt both principles for version integrity/interruption state. Its fs-local provides target locking, version conditions, and text-write results, but not full-file undo/reapply or Office versioning. Retain OpenProgram recovery transactions; session-log recovery is not file recovery. Retain Codex exact-delta attribution without treating arbitrary Bash as exact edits.

Integrating new tools and excluded capabilities

Local generators uniformly call write(file_path, source_path=...) to publish complete files. Text tools retain write/edit/apply_patch and share checkpoint prepare/commit/abort. Model claims of success are insufficient; arbitrary Bash followed by directory scans cannot establish attribution. CheckpointStore owns state; Review/session summaries are projections, not duplicate version stores. Future Office semantic diffs read immutable versions without implementing undo. Remote stores require conditional writes and verifiable version IDs before claiming exact recovery.

Retain existing turn aggregation, session branches, and recovery transactions. Add no full-disk scans, polling, generic plugin registry, Office revision views, or remote storage. Lost history cannot be reconstructed. System crashes and external programs ignoring locks may still require manual recovery; preserve evidence and refuse uncertain overwrites rather than promising automatic recovery of every external edit.

Implementation and acceptance plan

First reproduce failed repeated-write commits, retry after failure, and corrupt-record overwrite; then fix shared history storage and incomplete-record projections. Verify registered tools, reopened sessions, Review, and recovery entries, then independent specification/quality reviews and full checks. Shared history, session summaries, and Review projections are implemented; independent reviews, fault regressions, and full tests passed.

Document edits and version recovery

Word, PPT, PDF, and images use complete-file versions. Turn file records identify modified documents; Undo restores before and reapply restores after. Restart reads the same durable records.

Modification complete

Proposal.docx · contents updated

Inspect file record · undo this turn

Reopen session

The same turn still shows Proposal.docx; history depends on neither script output nor memory caches.

Inspect record · reapply

File changed later

Check current contents before Undo. Mismatch with saved versions blocks recovery and preserves later edits.

File changed; recovery not applied

Implementation and scope

Scripts write results to independent temporary files, then publish through existing write(file_path, source_path=...) . Specify exactly one of content/source_path. source_path is a local regular file subject to read permissions. Targets retain write authorization, read-baseline, and approval fingerprint checks. Both source/target fingerprints participate in approval waits and are rechecked before publication. Write a complete temporary file in the target directory, then replace; failures clean temporary files and preserve the target. Write raw bytes with before/after records, never text-convert documents. Identical source/target, directories, links, oversized or unreadable sources fail before modification. Source reads are capped at 64 MiB. Existing targets revalidate open handles, content, and paths under advisory locks. This serializes only cooperating writers, not external writes between final validation/replacement. Windows closes handles lacking delete sharing before replacement and revalidates again, without OS-level conditional-replacement guarantees.

Reference Codex TurnDiffTracker exact-delta checks and shell snapshot staging/verification/replacement; the latter stores shell environments, not document versions. Retain Codex explicit-edit attribution: generic Bash, background processes, and external editors do not automatically become exact turn changes. Scripts cannot overwrite final targets then append history afterward. Preserve text-write arguments, failures, rollback transactions, branch ownership, and durable session layout. Complete bytes restore document formats, images, and layout; no Word tracked changes or PPT visual diffs currently exist.

Establish read baselines first: models read originals, then generate staged versions. Binary reads return type/byte count, not garbled model output. New files require no prior read. Script-tool descriptions state this flow, without extra Save buttons, full-disk scans, or polling.

Acceptance uses registered write, reopened sessions, and public history operations: version DOCX/PPTX creation/overwrites; byte-identical undo/reapply; conflicts for external changes; failed writes preserve targets; existing text writes remain valid.

Current implementation and gaps requiring repair

The following are verified in current source and explain inflated hundreds-of-thousands-line statistics, slow responses, and potentially partial multi-turn recovery.

Current pathCurrent stateRiskTarget
agent_loop._snapshot_cwdBash cwd scans, candidate precopy, and executor calls are removed.Ordinary Bash, background logs, and external writes no longer enter turn mutations.Complete Only trusted file mutators generate receipts.
_checkpoint_changed_filesThis path is removed; prepared receipts explicitly distinguish regular before images from absence.Existing files beyond the statistics budget remain modify, with unknown statistics rather than counting the full file as new.Complete Missing baselines are not encoded as absent.
CheckpointStore.restore_turnSingle-turn entries use complete plans, profile-stable locks, durable intents, conditional leaf mutation, verification, and rollback. Legacy methods remain only for migration tests; production revert_turn no longer calls them.Conflicts, missing blobs, and stale plans perform zero writes. External pathname/open-fd races preserve external content and enter recovery_required.Complete Both single- and multi-turn operations use transactional apply.
rewind_toPlan the active suffix once, fold same-path changes, use dirfd/no-follow conditional writes and durable intents, then HEAD CAS after file verification; do not revert turn-by-turn or rewrite old nodes.Changes to files, plans, parent directories, HEAD, or branch versions block commit. Mixed crash states safely roll back on startup or enter recovery_required.Complete WS defaults to plan-only; apply requires plan hash and idempotency key.
rewind_to + caller subtreeRecursively include owned children in the same session, outside worktrees, with explicit origins in causal closure. Each receipt has durable monotonic mutation_sequence; fold same paths by actual workspace order.Running owned or same-workspace linked actors block recovery. Completed/cancelled/errored owned change sets with durable heads enter the same transaction; ambiguous legacy jobs gain no recovery authority.Complete Linked peers/cross-session actors and worktrees report impact only, without joining parent change sets.
/api/chat/checkoutOne HEAD CAS atomically records workspace mismatch; consecutive checkouts retain the true source head of materialized files.Block the next mutating turn until explicit Keep current files or Restore branch code. Both decisions bind source/target; stale requests cannot apply to newer checkouts.Complete Restore reuses transactional preflight, idempotency, rollback, and crash recovery without moving conversation HEAD.
ProjectGit.revert_agent_commitProjectGit calls are removed from single-turn Undo/Revert production paths.Single-turn recovery no longer resets/reverts user Git or reads/modifies index/commits.Complete Workspace Git operations retain separate entries.
ShadowGitStoreTurn/Branch Review and diffs read only exact mutation journals; Workspace Review reads only Git status/numstat. Shadow Git is no longer a Review fact source.Legacy shadow-commit paths remain but no longer affect cards, Review, or recovery eligibility.Review fallback complete Legacy caches may be cleaned separately later.
Checkpoint GC / unknown turnPlans must prove the target turn, every action, and recovery blobs available. Unknown, expired, corrupt, or inexact receipts expose no executable history action.Review metadata remains readable, but code restore is unavailable; do not write Reverted metadata or move HEAD.Complete Expired data permits read-only Review only.
Branch metadataUnify restore transactions, HEAD/version CAS, branch refs, writer epochs, and checkout alignment. Preserve source leaves; Rewind does not globally hide old conversation nodes.Checkout, Keep, and Restore bind expected source/target. Concurrent HEAD/file changes return blocked, rolled_back, or recovery_required.Complete Branch projections and Review use the same mutation sequence.
TurnFilesChipsPersist aggregates and the first three files with assistant metadata. Query legacy only on viewport entry. Cards mount at most 20 rows and no diffs.Review lists contain 100 files per page; diffs at most 200 lines / 256 KiB. Request IDs and snapshots reject stale responses/cross-scope reads.Complete Clicking files or Review opens a deterministic center Review tab.
Web / TUI / Python CLIWeb WS and Python CLI share read-only plans, explicit confirm/apply, plan hashes, idempotency keys, and result states. Web center Review integrates three scopes.Web diffs/payloads are bounded with actor/producer/linked impact visible. TUI/CLI share recovery protocols without duplicating Web panes.Protocol and Web Review complete
Project file explorerDirectories load on expansion; search considers loaded nodes only.Files in unexpanded directories are undiscoverable; directory results lack reusable stable snapshot/cursor contracts.Pending Project-scoped backend search, directory pagination, stable cursors.
File WebSocket lifecycleSome Review requests already echo request_id; project-file requests still use global response-type serialization, andlist_turn_files lacks request IDs.Concurrent callers cannot independently claim responses; global serialization blocks unrelated loads.Pending All file-related WS actions require request_id and correlate responses by it.
Read cache and draftsRead caches/drafts are unbounded; drafts live only in page memory.Long usage accumulates memory; reload may lose dirty drafts.Pending Bounded LRU read cache plus independent durable dirty-draft storage.
Review filters and pagingReview fetches one file page, then categorizes Code/Tests/Docs/Large client-side.Categories represent only that page, not stable filtered results across pages/workspace changes.Pending Server filters/sorts before paginating fixed snapshots.
Official references, adoption, and boundaries
SystemConfirmed behaviorAdoptRejected or unknown
Claude Code checkpointEach user prompt creates a checkpoint tracking Write/Edit/NotebookEdit, explicitly excluding Bash. Restore code, conversation, or both; without tracked edits, omit code recovery. Apart from foreground context: fork skill, other subagent changes are not restored. Symlink/hardlink/nonregular paths are skipped with warnings, permitting partial recovery. Keep 100 file checkpoints per session; persisted with sessions and cleaned by configurable cleanupPeriodDays , defaulting to 30 days.Adopt Prompt checkpoints, separate recovery options, explicit unavailable states.Adapt OpenProgram blocks the entire operation or transactionally rolls back any path failure; skipped paths cannot yield overall success. Official docs do not guarantee conversation-only rewind for prompts beyond the latest 100.
Claude Code fork/branch and SDK fork copy conversation into a new session while retaining the original, explicitly neither copying nor reverting filesystems. VS Code separately offers Fork conversation and rewind code.Adapt OpenProgram retains same-task Branch and adds source-preserving new-task Fork; with-files uses isolated worktrees in Git projects.Reject Undisclosed default reuse of current files after forks.
Claude DesktopSession diff entry, left file list/right single-file diff, line comments, Review code.Adopt Independent Review, on-demand single-file diffs, structured line feedback.Do not copy Branding, icons, dimensions, toolbar ordering, or PR controls.
Claude WebSession diffs, left/right layout, line comments, and Create PR are confirmed; official pages do not confirm Review code.Adopt Separate Review from chat.Unknown Do not infer Desktop Review code capabilities for Web.
Codex exact turn diffTurnDiffTracker Consumes exact AppliedPatchDelta within the current turn only, without rereading workspace. Inexact data invalidates turn diff. It is an in-memory aggregator, not a durable recovery journal.Adapt Adopt exact deltas as attribution input; OpenProgram adds durable receipts, digests, before/after blobs, and transaction states.Do not claim Codex provides a durable Undo journal.
Codex historythread/fork Creates a new thread ID and copies history only; TUI editing of old prompts uses source-preserving forks. Legacy thread/rollback is deprecated; experimental thread/revert handles conversation only. Neither restores files.Adopt Source-preserving forks and immutable history.Unknown Whether Codex App has unpublished per-turn checkpoints/file Undo.
Codex Git ReviewRepository Review distinguishes Last turn from Git state, with Unstaged/Staged/Commit/Branch, multiple repositories, line comments, and whole/file/hunk Git stage/revert. TUI /diff uses for untracked files: --exclude-standard.Adopt Workspace Git subscopes and ignored-file exclusion.Name separately Git Discard is not checkpoint Restore; desktop Git revert is not turn Undo.
Not publicly guaranteed by reference systems:Claude does not specify overwrite/reject/merge rules for external concurrency, multi-file atomicity, digest preflight, or crash consistency. Durable Codex exact-turn deltas and Desktop per-turn file Undo are unconfirmed. Complete preflight, workspace locks, durable intents, rollback staging, and crash recovery are OpenProgram additions.
Target architecture and trust boundaries

Conversation DAG, exact mutation journal, and Git workspace view are independent fact sources. History planners may read all three; only recoverable journal receipts authorize file recovery.

File-change and history-recovery architectureDirect tools create exact receipts; ordinary Bash is excluded from turn attribution. Journals derive turn/session Review; Git derives Workspace Review. History planners update files/HEAD only after preflight and durable intents. Trusted file mutatorswrite · edit · apply_patchvalidated mutation-capable adapter Generic Bash / external processno turn receipt · no turn Undo Mutation receiptbefore/after digest · op · actorrecovery blob ref · stats Mutation journalappend-only transactionsturn · current branch · revert Conversation DAGuser · llm · code nodesHEAD and sibling branches Derived Review scopesThis turn · Current branchWorkspace comes from Git only History operation plannerimpact · target projectionconflict and recoverability Durable operation intentprepared · applyingcommitted · rolled_back Workspace transactionlock · stage · apply · verify HEAD transactiononly for conversation modes
Ordinary Bash versus Workspace Review:Bash may run in sandboxes/worktrees, but generic shell results in shared local workspaces are not automatically attributed to turns. Git shows current changes without proving their turn origin or granting Undo authority.
File browsing, search, and Review query contracts

Project explorer and Review use project/session-bound server snapshots. Directory, search, and Review filtering establish complete ordered candidates before paging; clients cannot infer complete project/scope results from current pages.

QueryFact source and scopeSorting, filtering, paginationInvalidation
Directory listingProject root resolved by project_id ; path must be normalized, root-relative, and a directory. Reject traversal, symlink escapes, and server-prohibited directories.Stable sort by type (directories, files) and normalized root-relative path, then snapshot. At most 100 entries per page; cursors are opaque tokens, not array indexes.Directory-version, ignore-rule, or project/path/sort mismatches return STALE_SNAPSHOT; clients restart from page one.
Project searchServer traverses the same project root with identical access/ignore rules, independent of expanded tree nodes. Results include only project files/directories matching names or root-relative paths.Filter by query, match mode, and type, then stable rank/root-relative path and snapshot. Page filtered results only; query/mode changes discard cursors.Project switches, expired search snapshots, or changed root versions show refreshable status; old project results cannot remain under new projects.
Review scopeThis turn / Current branch read mutation journals; Workspace reads Git HEAD/index/worktree. Each item retains source, actor, and change-set attribution.Server filters by category, path query, operation, diff state, and sort, then snapshots/pages that result. Counts/totals describe the complete filtered result, not one page.Reject cursors on scope, assistant-message, filter, sort, or snapshot mismatch. Workspace additionally compares fixed candidates and each index/worktree identity. Clear selection/diff when selected files leave the snapshot.
Review file diffAccept only paths returned by the same Review snapshot. Turn/branch reads journal blobs; Workspace reads recorded HEAD/index/worktree blob pairs.Diff cursors are opaque tokens bound to file identity, blob pair, scope snapshot, and line budget. At most 200 lines or 256 KiB per request.Changed snapshots, candidates, index/worktree identities, or blob pairs return stale, never later pages from another version.

Stable cursors

{
  "snapshot_id": "snap_...",
  "query_kind": "directory | project_search | review_scope | review_diff",
  "owner": {"project_id": "...", "session_id": "..."},
  "basis": "directory/version or journal/Git revision",
  "filter": {"query": "...", "category": "...", "sort": "..."},
  "cursor": "opaque token",
  "next_cursor": "opaque token | null",
  "page_size": 100
}

Cursor invariants

  • Cursors are valid only with identical originating snapshot, owner, query kind, filters, and sorting. Reject client-supplied offsets, path anchors, and cross-project tokens.
  • Snapshots retain stable candidate ordering or immutable revisions sufficient to reconstruct it. Later pages never rescan and mix new/deleted/reordered entries.
  • Snapshots may have capacity/TTL limits. Eviction/version changes explicitly return stale; clients reload initial results rather than silently continuing old cursors on latest lists.
  • Directories/search use their own cursors; Review lists and single-file diffs have separate noninterchangeable namespaces.

Workspace Review snapshot

{
  "snapshot_id": "workspace_...",
  "project_id": "...",
  "head_identity": "commit/tree identity",
  "index_identity": "index tree identity",
  "candidates": [{
    "path": "canonical relative path",
    "status": "XY or ??",
    "base": {"kind": "blob | absent", "digest": "...", "mode": "..."},
    "index": {"kind": "blob | absent", "digest": "...", "mode": "..."},
    "worktree": {"kind": "regular | absent", "digest": "...", "mode": "...", "identity": "lstat fingerprint"}
  }]
}

Workspace invariants

  • Snapshot creation fixes all uncommitted candidates at once, sorted by normalized relative path: staged, unstaged, untracked, rename/delete paths, preserving old/new path mappings.
  • Each candidate pins HEAD base, index blob, and worktree content identity/blob pair. Text diffs render only from that pair, never rerun current git diff on later requests as a substitute.
  • Before later pages or file diffs, reread status candidate vectors, index-tree identity, and target no-follow worktree identity. Any addition, deletion, status, mode, index blob, digest, or path-mapping change returns STALE_SNAPSHOT.
  • Snapshot content blobs share Review quotas; missing, oversized, or expired blobs return stale/unavailable, never approximating old diffs from current worktrees.

All file WebSocket requests

RuleContractProhibited
Required correlation keyAll browse/read/write/create/rename/copy/delete/reveal, turn-summary/diff, and Review-scope/diff requests carry client-generated UUID request_id, echoed unchanged on success, stale, validation errors, and transport errors.Reject missing/non-UUID file requests; never claim responses by type, path, or arrival order.
Response validationClients use request_id as the sole pending key and additionally validate action, project/session, snapshot, and target path. Unmount, project changes, or new queries cancel/forget old keys.Do not eliminate races with a global queue; slow directory requests cannot block unrelated reads/diffs.
Write idempotency and conflictsSide-effecting actions also carry independent idempotency_key and existing optimistic-lock conditions. Servers create durable records from action, owner, canonical payload, and precondition fingerprints.request_id Correlates transport only, not write idempotency.New reconnect request IDs do not imply new writes; cached mtime cannot override server conflicts.
Error shapeEvery result provides request_id, action, owner, status, and stable error code;STALE_SNAPSHOT, NOT_FOUND, CONFLICT and INVALID_REQUEST is explicitly handled by UI.Do not silently swallow frames missing IDs, with incorrect owners, or unknown responses, nor apply them to current file state.

Write idempotency_key

{
  "record_key": {"owner": "profile + project", "action": "project_file_write", "idempotency_key": "uuid"},
  "fingerprint": "sha256(action + owner + canonical payload + precondition)",
  "state": "prepared | in_flight | completed",
  "operation_id": "fileop_...",
  "result": "canonical terminal result or null"
}

Idempotency invariants

  • Owner is the authorized profile/project. Canonical payload uses normalized root-relative paths, operation parameters, and content digests, excluding request_id and idempotency_key. Precondition fingerprints include expected mtime/digest, source/target paths, overwrite conditions, and affected-directory versions.
  • Servers atomically claim (owner, action, idempotency_key) in the same durable scope as mutations. A different fingerprint for the same record key returns IDEMPOTENCY_KEY_CONFLICT with zero file writes.
  • Same-fingerprint in-flight retries bind existing operation_id and wait until the current request deadline. If unfinished, return IN_PROGRESS and operation ID. Clients may retry only that key, never submit another write.
  • Durable records retain canonical terminal results. Every same-fingerprint retry replays results even with different request_id, without reexecuting mutations. Restart first recovers or classifies in-flight records before replay.
  • Retention covers client retry windows and worker recovery. Expiry never deletes in-flight records or interprets expired keys as successful replays with different fingerprints.

Caches and unsaved drafts

StorageKey and capacityEviction and consistencyData protection
Read cacheKey: project_id + canonical relative path + content revision; at most 64 entries / 16 MiB, access-order LRU.Cache only successful complete reads. Writes, rename/delete, tree revisions, and capacity invalidate/evict oldest clean reads. Misses trigger new request_id requests only.Cache is not edit state and stores no dirty text.
Dirty draft storeNative browser IndexedDB database openprogram-file-drafts , keyed by project_id + canonical relative path; persists UTF-8 drafts, baseline revisions/mtime, save status, and update time. Limit: 32 drafts or 8 MiB.Clean drafts may delete; dirty drafts never participate in LRU eviction. Update entries and aggregate byte/count indexes in one readwrite transaction.Reload, tab unmount, project switching, and cache eviction cannot delete dirty drafts. Server changes retain drafts with conflict state; save still submits original baseline conditions.
Path changes and cleanupSuccessful rename moves same-project draft keys in one IndexedDB transaction; copy shares no source draft. Deletion first lists dirty drafts and requires explicit save, retain/export, or discard. Project cleanup is reserved for future explicit unlink/delete commands, currently absent.Failed file operations leave draft keys unchanged. Confirmed discard clears draft and project index atomically; cleanup failure preserves records and reports failure. A project disappearing from list_projects is not user authorization.Identical paths across projects never share cache, drafts, selection, or search snapshots. Tree refresh, Review changes, temporary registry unavailability, and background responses never reset editor buffers.

IndexedDB dirty-draft contract

{
  "database": "openprogram-file-drafts",
  "stores": ["drafts", "project_index"],
  "draft": {
    "key": "project_id + canonical relative path",
    "draft_utf8_bytes": 0,
    "baseline_utf8_bytes": 0,
    "baseline_revision": "...",
    "baseline_mtime": 0,
    "updated_at": "local monotonic ordering"
  }
    }

Persistence and recovery invariants

  • Use native IndexedDB without dependencies. Quotas use TextEncoder UTF-8 byte lengths, counting drafts, baselines, and metadata;project_index stores per-project keys/count/bytes. Startup restores dirty drafts from project_index; missing/inconsistent indexes rebuild by scanning drafts without deletion.
  • Create, update, rename, discard, and future explicit project cleanup calculate old/new bytes and write drafts/indexes in one readwrite transaction. Exceeding 32 entries or 8 MiB performs no writes and preserves existing drafts.
  • Check budgets before accepting input that exceeds durable-draft quotas. Full storage blocks new dirty drafts and visibly offers save, revert, export, or explicit discard. Never evict existing dirty drafts. If updating encounters browser QuotaExceededError , preserve the latest successful durable version, show persistence failure, and pause changes enlarging that record until space is handled or explicitly exported/discarded.
  • Before server deletion of files with dirty drafts, UI requires save, retain/export, or explicit discard; clear keys only after successful discard. No current project unlink/delete action exists, so missing registry entries do not clean drafts. Future explicit cleanup must show project draft count/bytes and confirm clearing all keys/index; cancellation/failure preserves them.
  • Draft content stays only in the current origin’s IndexedDB, outside logs, telemetry, model context, WebSocket payloads, and cross-device synchronization. Explicit discard, future confirmed project cleanup, browser site-data clearing, and app uninstall delete it. Recovery never automatically uploads or rewrites project files.
Review ordering is fixed:Resolve scope/owner → get/create fact-source snapshot → server filter/sort → paginate filtered results → render one page. Category/search controls are not secondary filtering of a loaded page.
Mutation journal data contract
{
  "transaction_id": "mtx_...",
  "session_id": "...",
  "workspace_id": "workspace_...",
  "workspace_sequence": 184,
  "branch_ref": "branch_...",
  "lineage_head_id": "...",
  "producer_turn_id": "actual assistant message id",
  "origin_turn_id": "user-visible parent turn id",
  "actor_id": "main | child_...",
  "job_id": null,
  "worktree_id": null,
  "kind": "edit | revert | rewind",
  "status": "prepared | applied | committed | aborted | rolled_back | recovery_required",
  "files": [{
    "file_lineage_id": "file_...",
    "path": "canonical absolute path",
    "operation": "create | modify | delete | rename",
    "old_path": null,
    "before": {"kind":"regular","digest":"sha256:...","blob_ref":"blob_...","mode":"0644"},
    "after":  {"kind":"absent"},
    "stats": {"added":16,"removed":4,"binary":false},
    "diff_state": "available | large | binary | timeout",
    "recoverability": "exact | unavailable",
    "unavailable_reason": null
  }]
}

Invariants

  • Persist prepared receipts before original writes, then write files and mark committed only after confirming after state. Failed prepared persistence must stop trusted mutators before disk writes.
  • {kind:"absent"} means path absence was precisely confirmed; baseline acquisition failures use only recoverability=unavailable and reasons, never absent.
  • recoverability=unavailable applies only to successfully journaled mutations whose explicit size/type policy omits recovery blobs, never to suppress journal failures.
  • Each user prompt defines before_turn; assistant completion defines after_turn. UI explicitly identifies the restored boundary.
  • Repeated edits to one file lineage within a turn fold into net first-before to last-after changes; rename preserves lineage.
  • Transactions sharing a checkout claim globally monotonic workspace_sequence under workspace locks. Multi-turn projections use sequence/lineage, not DAG seq/DFS.
  • Regular before/after states both retain blob refs for stable historical diffs, recovery, and conditional Reapply.
  • Recanonicalize paths at capture/plan/apply; persist/recheck parent-chain identity, leaf lstat, device/inode, and hardlink counts using validated directory handles or equivalent no-follow primitives.
  • Current branch folds active-lineage transactions only, excluding siblings.
  • Revert/Restore/Reapply also create mutation transactions; originals remain immutable.

Checkpoint and WorkspaceRevision

ObjectRequired fieldsPurpose
BranchStable branch_id, parent branch, fork checkpoint, HEAD, head_version, writer epoch; sessions separately store active_branch_id.Source branch HEAD never moves backward. Restore/Branch confirmation immediately creates new branch refs; pure history browsing changes only navigation cursors.
Checkpointcheckpoint_id, boundary=before_turn|after_turn, user/assistant node, branch id, journal sequence, workspace revision.Defines the recovery destination without duplicating file lists.
ChangeSetProducer turn, origin turn, branch, actor/job/worktree, transaction sequence, net file-lineage changes.Cards group by origin but deduplicate change-set IDs and retain actual producers.
WorkspaceRevisionRevision ID, managed-path projection digest, branch/checkpoint, alignment state.Checks agreement among branch checkout, conversation-only restore, and actual workspace.
RestorePlanPlan hash, idempotency key, expected HEAD/revision, target checkpoint, file actions, conflicts.Prevents preview/confirmation TOCTOU; repeated requests cannot execute twice.

RestoreIntent / RestoreAction

{
  "restore_intent_id": "restore_...",
  "idempotency_key": "...",
  "plan_hash": "sha256:...",
  "source_branch_id": "branch_source",
  "target_branch_id": "branch_target",
  "expected_head_version": 42,
  "expected_workspace_revision": 184,
  "target_checkpoint_id": "cp_...",
  "mode": "code_and_conversation",
  "status": "prepared | applying | committed | aborted | rolled_back | recovery_required",
  "actions": [{
    "action_id": "ra_...",
    "file_lineage_id": "file_...",
    "path": "/canonical/path",
    "expected_current_digest": "sha256:...",
    "target_digest": "sha256:...",
    "target_blob_ref": "blob_...",
    "rollback_digest": "sha256:...",
    "rollback_blob_ref": "blob_...",
    "applied_digest": null,
    "state": "pending | applied | verified | rolled_back",
    "error": null
  }]
}

Recovery-record invariants

  • Plan is a read-only preview; Intent is a confirmed durable execution record, bound by plan hash.
  • Persist each action’s state before/after replacement; restart never infers progress from directory contents.
  • Rollback writes its blob only while current digest still equals that action’s applied digest.
  • Unsafe rollback retains exact per-path state in the intent and enters recovery_required.
  • Activate target branches only after all code actions verify; source refs/HEAD never change.

Three Review scopes

ScopeFact sourceContainsRecovery capability
This turnCommitted change sets for a specified origin turnParent direct change set plus owned children, each retaining independent producer_turn_id, deduplicated by transaction ID with actors shown.Undo/Revert requires exact receipts throughout selected causal closure, terminal actors, and matching current digests.
Current branchIncremental mutation projection of active lineageAll turns and explicit revert/rewind/reapply; excludes siblings/external writes.Initiate from specific turns/checkpoints; no unscoped one-click branch Undo.
WorkspaceGit tracked diff + git ls-files --others --exclude-standardCurrent uncommitted changes, respecting .gitignore. Internally choose Unstaged, Staged, Branch, or Commit.No turn Undo. Git Discard and checkpoint Restore have separate entries/confirmation wording; non-Git is explicitly unavailable.
Multi-turn Rewind: one plan, one transaction

Each turn has before_turn and after_turn checkpoints. User-message Restore defaults to before the request; assistant cards may restore after the reply. Compute suffixes only along source-branch predecessors, excluding siblings. Preserve source refs/HEAD. Conversation modes immediately create target refs and switch active branches after coordinated commit.

IDLE

Choose checkpoint and recovery mode.

PLANNING

Freeze expected HEAD, workspace version, suffix.

READY

Show turn/file impact, unavailable items, branch result.

BLOCKED

Conflicts, missing blobs, running tasks, or unsafe paths: zero writes.

APPLYING

Persist intent, lock workspace, stage, apply, verify.

COMMITTED

Append transaction; move HEAD if needed; refresh UI.

Multi-file recovery is not one atomic filesystem operation.Guarantees come from durable intents, rollback staging, per-file atomic replacement, and restart recovery. If apply and rollback both fail, show Recovery required, never Reverted or a moved conversation HEAD.

Planning algorithm

PhaseRuleFailure result
Resolve lineageFollow conversation predecessors from current HEAD to target user checkpoint; include caller subtrees only through explicit ownership.Target outside active lineage: reject and request branch switching first.
Fold target stateProject target path states from journals; one final action per file across turns, not sequential overwrites.Discontinuous journals or inexact historical receipts make code modes unavailable; conversation mode remains available.
PreflightPlan from global current_workspace_revision to the target checkpoint, comparing only file lineages affected by actual actions. Check blobs, parent/leaf identities, types, roots, space, permissions.Any failure enters BLOCKED with paths listed and zero file changes. Conversation/workspace mismatch is not itself a source digest.
Prepare intentPersist plan ID, expected branch/head version, workspace revision, before/target images, writer epoch, recovery mode; requests are idempotent.Changed state before confirmation returns stale-plan for renewed preview.
Apply filesAcquire workspace mutation lock; persist pending/applied/verified/rolled_back and transaction-applied digest per action. Replace files atomically; delete only with matching current digest.Before rollback, reconfirm current digest equals this transaction’s applied digest. External rewrites are preserved and enter RECOVERY_REQUIRED.
Create conversation branchConversation-only or code+conversation first prepares stable target ID/ref without changing source HEAD. Pre-first-turn targets use persistent synthetic ROOT, prohibiting head_id=None fallback.Create/activate with expected-source head_version CAS. Failure restores files per intent and retains source/active branches.
FinalizeAppend rewind transactions/navigation events without globally marking old nodes rewound. Advance branch writer epochs so old asynchronous tasks cannot write back.Startup scans nonterminal intents and finishes or rolls back, never guesses success.

Recovery modes

ModeFilesConversation HEADSubsequent behavior
Code + conversation DefaultRestore checkpointImmediately create target branch pointing before target prompt; activate after commitPrefill original prompt; preserve source ref/HEAD.
Conversation onlyKeep currentImmediately create and activate target branchShow workspace mismatch. Confirming Keep current files appends adopt_workspace_revision event and a new branch checkpoint, continuing from that explicit baseline.
Code onlyRestore checkpointKeep currentAppend rewind transaction; show “Code restored; conversation remains at latest position.”
Branches, checkout, and sub-agents
ScenarioTarget semanticsFile rules
Branch from assistant resultImmediately create stable target branch ID/ref pointing to the assistant and switch active_branch_id; source HEAD remains unchanged.Files unchanged by default, with “Files stay as they are” subtitle. Pure history browsing moves navigation cursors only, without creating/moving branches.
Fork into new taskCreate source-preserving new task/thread, retaining original task/HEAD; optionally copy conversation only or checkpoint file state.Git with-files prefers isolated worktrees before checkpoint materialization. Non-Git offers no silent directory copying; use explicit same-task Code + conversation Restore.
Checkout sibling branchSwitch the visible/model-used conversation lineage.Compute branch/workspace alignment. Browsing is allowed; before mutation, explicitly keep the workspace or restore branch code projection.
Owned child (foreground or background)Criterion: relation + creates_agent + origin_turn_id, not foreground/background status. Children always retain independent producer turns/change sets; parents group by origin only.Running children block parent restore. Completed children join owned causal closure, individually listed and transaction-deduplicated, never inferred by caller DFS.
Independent actorBackground terminals, job runners, channels, and schedulers without ownership register independent workspace-writer identities.While running they block same-workspace restore. Completed writeback checks branch writer epoch; old tasks cannot rewrite restored branches.
Existing peer / cross-session dispatchagent(to=existing), send message, and existing peers are linked collaboration, not exclusively owned descendants.Parent restore does not modify peer conversations/change sets by default. Impact sheets separately list linked actors and block code recovery for overlapping workspaces/paths.
Worktree childFile state belongs to an independent worktree.Parent Undo/Rewind never touches it; merge/discard use its own transactions/conflict semantics.
Worktree mergeMerge creates an independent mutation transaction owned by the merging producer turn.Parent recovery uses only the merge transaction, not potentially deleted child-worktree checkpoints.
Sibling branchRewind affects active-lineage suffixes only.Sibling journals remain unchanged; switching back recalculates alignment.
Branch, Fork, and Restore have distinct buttons.Same-task Branch navigates conversation without touching files by default. Fork creates a source-preserving new task; Restore explicitly recovers history. Use Code + conversation Restore to continue historical code in the current task, and Git-worktree Fork for simultaneously runnable code states.

Resume, Archive, and Purge invariants

OperationContractProhibited
Resume sessionUnknown sessions return not-found. Recover all prepared/applied/recovery-required transactions before loading real node IDs,active_branch_id, branch HEAD/version, and workspace revision.Never treat unknown IDs as new sessions or generate loaded-<index> fake IDs.
Resume empty branchBefore the first turn, HEAD points to persistent synthetic ROOT. Web/TUI/Rich CLI share one branch-result schema.Never use persisted_head or tip or head_id=None to automatically choose another tip.
Archive branchDefault deletion archives branch refs only, retaining nodes, journals, checkpoint refs, and reactivation.Never delete shared ancestors or accidentally expose predecessors as new tips.
Purge branchExplicit advanced operation: reference-counted GC releases only exclusive objects unreferenced by branches, checkpoints, operations, audit, or active intents.Never delete one predecessor node at a time from leaves or let blob GC bypass references.
Conflicts, unavailability, and concurrency states
Later edit to the same file

Historical Revert does not auto reverse-merge; Rewind preflights current digests. Any mismatch blocks the entire file operation.

BLOCKED_CONFLICT · 0 writes
Checkpoint blobs garbage-collected

Summaries/diff metadata remain reviewable. Code restore is disabled; Conversation only stays available.

UNAVAILABLE_BLOB_EXPIRED
Large file without recovery blob

Operation, path, size, and recoverability remain exact. Line counts are exact only with tool deltas or budgeted before/after; otherwise additions/deletions are unknown. No Undo or counting the entire file as new.

UNAVAILABLE_SIZE_POLICY
Symlinks / hardlinks / special files

Do not follow/overwrite; show paths/reasons and require original tools or version control.

UNSAFE_FILE_TYPE
Running turn / background task

No confirmable plan while same-workspace mutation locks remain held; stop or await tasks first.

WORKSPACE_BUSY
State changes after confirmation

Apply checks expected HEAD, workspace version, plan token. Return stale-plan and refresh impact rather than execute old plans.

STALE_PLAN · 0 writes
Process crash during apply

Startup reads durable intents/per-path states. Safely roll back to ROLLED_BACK; if external writes make rollback destructive, preserve state for manual recovery.

COMMITTED | ROLLED_BACK | RECOVERY_REQUIRED
Non-Git workspace

Exact This turn / Current branch journals work; Workspace is unavailable without scans.

WORKSPACE_REVIEW_UNAVAILABLE
Ignored background-log growth

Without mutation receipts and excluded by Git exclude-standard, absent from turn cards/default Workspace Review.

EXCLUDED_BY_DESIGN
Exact edits to gitignored or authorized out-of-repository paths

Trusted receipts still enter journals and support Undo/Restore, though absent from Git Workspace scope. Ordinary Bash and receiptless ignored changes remain excluded.

JOURNALED_NOT_GIT_VISIBLE
Reapply reverted change sets

Requires current digest matching post-revert state, no later same-lineage mutations, and available after blobs; append a new transaction.

READY | BLOCKED_DEPENDENCY
External side effects

Databases, APIs, deployments, package installation, Git index/commits, running processes, network requests, and unrecorded Bash are outside file Restore. Confirmation lists possible repeated effects individually.

UNSUPPORTED_SIDE_EFFECTS_VISIBLE

UI information architecture and entries

LocationDisplayOperationProhibited
Assistant turn cardExact file count, net additions/deletions, first three files, full border, approximately 40px header. Use the user-specified 19px FeatherIcon for direct edits, not the site logo. Always show both totals including zero, with a 2.5px two-color actual-proportion bar. Actions, buttons, and Undo icons never flex-shrink; direction icons are 1em, matching text height. Titles truncate. At ≤420px, shorten to “N files,” preserving icons, statistics, actions, and 40px header. Keep header divider; de-emphasize directories and emphasize basenames, fixed-width statistics, categories only in Review.Latest recoverable turn: Undo; after successful Undo and renewed preflight: Redo; historical turn: Revert; after historical Revert and renewed preflight: Reapply; every turn: Review. Undo/Revert/Redo/Reapply use text/direction icons; Review is neutral outlined. Headers show executable actions only; unavailable, blocked, and Reverted explanations stay in footers.Redo/Reapply append new reapply transactions without linear stacks. No header chips, disabled-state badges, or reference-product branding.
User message footerExisting Restore checkpoint message action.Open checkpoint impact sheet, explicitly before_turn/after_turn, default Code + conversation.Never restore immediately on click; show impact, recoverability, external effects first.
Assistant message footerBranch action.Branch from here, subtitle Files stay as they are.No implicit checkpoint restore.
Changes center tabThis turn / Current branch / Workspace, with Unstaged/Staged/Branch/Commit inside Workspace. Left file navigation, right single-file diff, always-visible source labels. Search/category counts cover complete filtered results; page numbers refer only to that result set.Unified / Side-by-side, line comments, Open file, Reveal. Scope/search/category/sort changes clear cursor, selection, diff. File uses existing virtualized editor tabs rather than duplicating full files inside Review.Workspace has no turn Undo. Mount one bounded diff; never filter only the loaded client page.
History impact sheetTarget prompt, undone-turn count, file count, branch result, mode, conflicts, unavailable reasons.Confirm Rewind, Conversation only, Code only; cancellation has no effects.No Force while blocked; advanced manual recovery belongs in Review.
Alignment bannerExplain conversation-branch/workspace-projection mismatch.Keep current files or Restore branch code.Do not merely warn then silently start mutating turns.
Performance, retention, security, compatibility
Turn finalize

Complexity depends only on committed changed paths, without workspace traversal. Persist summaries at finalize and return with transcripts.

Review loading

Server filters/stably sorts first; 100 files per page. Clients retain current/adjacent pages only. Selected-file batches contain at most 200 lines or 256 KiB with continuation.

Diff budget

Over-budget computation returns timeout metadata, without blocking Agent completion or approximating cross-turn diffs from before/current disk.

Snapshot pagination

Directory, project search, and Review categories/search/sort/opaque cursors bind one snapshot. Workspace/project changes make old pages stale for complete refresh, never mixed pages.

Request identity

Every file WS request has UUID request_id; changing files/projects cancels old requests. Late responses must also match owner, scope, snapshot revision, change set, blob pair.

Large restore plan

Thousands-file preflight is observable background work with paginated conflicts. Once APPLYING, it cannot cancel, only finish or transactionally roll back.

Recovery blobs

Use separate content-addressed storage, deduplicated by digest and restricted to local users, outside session Git. Default retention: latest 100 checkpoints and first baseline of each lineage.

GC visibility

Never collect pinned checkpoints, active tasks, unresolved conflicts, prepared/applying intents, or branch-referenced checkpoints. Other expired blobs show Review available / Code restore unavailable.

Secrets

Blobs stay outside logs, telemetry, model context. Session deletion cleans unreferenced blobs. External paths require explicit authorization at capture and recovery.

Read cache and drafts

Read cache: 64 entries / 16 MiB LRU. Durable dirty drafts: separate 32 entries / 8 MiB quota, never auto-evicted.

Legacy sessions

Legacy checkpoints allow read-only Review or explicit unavailable only. Without digest/recovery contracts, offer no new Undo/Rewind code modes or request_id-less compatibility entries.

TUI parity

/rewind Shows the same server plan before mode selection/confirmation; never directly invoke old rewind_to.

App/Web parity

Same plan/apply protocol and idempotent request IDs. UI renders canonical server impact without recomputation.

Line comments

Bind change-set ID, before/after blobs, side, hunk/line. Scope/branch/recovery changes mark comments stale; never send against another version.

Stable module responsibilities and compatibility removal

ModuleFinal responsibilityExcluded responsibility
apps/server/.../ws_actions/files.pyProject-root authorization, directory listings, project search, reads and mutating file operations. Uniformly validate project/path, request_id, idempotency keys, directory/search snapshots.No turn/branch Review computation or browser cache/draft storage.
apps/server/.../ws_actions/turn_files.pyGenerate Review scopes, filtered pages, and snapshot-bound file diffs from journals/Git; uniformly echo request_id.No project-tree search or turn-diff bypass of Review snapshots.
apps/web/lib/net/ws-request.tsCreate request IDs, maintain ID-keyed pending registries, timeouts/cancellation, strict response checks.Never match first responses by type or maintain global file-request serialization.
apps/web/lib/files/files-shared.tsManage bounded read caches, durable drafts, and explicit invalidation through project-scoped keys.Not an unbounded cross-component content store; no Review pages or socket listeners.
FileTree / FilesPageRender directories/search/file-operation intents using server pages/project-search results only.Do not scan loaded nodes as project search or reorder cross-page results locally.
ReviewTabPaneStore scope/filter/snapshot/cursor/selection and render server-confirmed pages/file diffs.No current-page category/search filtering or reuse of another scope’s diff.
FileTabPaneEditor buffers, save-conflict notices, dirty-draft lifecycle; canonical contents come from project files.Never call legacy turn diffs directly; historical comparisons open through Review tabs.
Remove temporary compatibility entries:Delete response-type-paired filesWsRequest global queues, file actions missing request_id , directFileTabPane calls to the turn_file_diff entry, and paths treating list_turn_files as new-message summary backfill. Old sessions without usable journal/Review snapshots return read-only unavailable, without legacy fallbacks bypassing contracts.
Implementation brief and acceptance matrix

A–J are complete and passed independent specification/quality reviews. New tasks require the same reviews before updating status here.

TaskProduction boundaryPublic-entry cases that must fail firstExclusionsStatus and evidence
A · Exact mutation journalprograms/tools/files/, turn context/finalize, checkpoint manifest/store.Existing >5 MiB files are not entirely new on first edit; ignored Bash logs stay outside turns; failed edits produce no receipts.No Review UI or user-Git changes.review-passed Public-entry, affected tests, and static checks verified.
B · Safe single-turn Undo/Revertagent/internals/_revert.py, workspace lock, durable intent.Later same-file edits cause zero writes; mismatched created-file digests prevent deletion; mid-operation I/O failures never partially mark success.No multi-turn HEAD moves.review-passed Public-entry, affected tests, and static checks verified.
C · Multi-turn planner/applyagent/_rewind.py, session head API, intent recovery, WS/CLI protocol.Restore one file across three turns; file failure preserves HEAD; siblings unaffected; stale plans write nothing.No compaction or DAG-schema rewriting.review-passed Public-entry, affected tests, and static checks verified.
D · Review scopes and UIws_actions/turn_files.py, message metadata, center tab/store, chat card.History does not query each message; Workspace excludes ignored files; one bounded diff mounted; three scopes have consistent provenance.No third pane, new window, or reference branding.review-passed Public-entry, affected tests, TypeScript, UI gates verified.
E · Branch alignment and multi-agent ownershipcheckout/branch UI, active-lineage fold, owned/linked/worktree ownership.After conversation-only checkout, mutation never silently starts. Running owned background children block parent restore; completed children join closure by origin. Linked peers/cross-session actors remain untouched; worktree children do not alter parent workspaces.No generic workspace cloning.review-passed Public-entry, affected tests, TypeScript, Ruff, WS-action gates verified.
F · Project query snapshotsws_actions/files.py Directory pagination, project search, path authorization, snapshot registry inFileTree ; result state.Search finds named files in unexpanded directories. Directory changes after page one cannot enter old cursors; cross-project cursors are rejected.No visual-layout changes, full-text indexes, or third-party search services.review-passed Directory/search use stable cursors, incremental same-snapshot pages, and bounded results.
G · File request identityFile WS dispatch,ws-request.ts, durable idempotency records, and all file/Review callers.Two same-action requests may return out of order to their correct callers. Missing request_id is rejected. Same idempotency_key in-flight retries bind original operations and replay completed results; same keys with different fingerprints conflict without writes.Nonfile WS protocols unchanged; request_id is not write idempotency.review-passed Request identity, durable mutation, disconnect retries, worker leases, and bounded pending registries verified.
H · Bounded cache and durable draftsfiles-shared.ts, native IndexedDB draft store,FileViewer, FileTabPane, tab close/rename/delete lifecycle. Project unlink/delete cleanup hooks await explicit product operations.Exceeding read-cache budgets evicts only clean LRU entries. Reload/tab/project changes retain IndexedDB dirty drafts. Quota/browser QuotaExceededError preserves old drafts/indexes atomically, blocks new dirty records when full, and shows notices. No project unlink/delete exists; disappearance from list_projects never implies authorization.No collaborative editing, remote draft sync, unlimited offline file copies, or project-removal UI/actions.review-passed 64-entry/16 MiB cache, 32-entry/8 MiB drafts, lifecycle compensation/recovery verified.
I · Filtered Review paginationturn_files.py Filter/sort/snapshot/page in ReviewTabPane ; query state.Categories cover all pages. Category/query/sort changes invalidate cursors/diffs. Workspace snapshots pin staged/unstaged/untracked candidates and per-file blob pairs; later index/worktree changes return stale.No third Review pane or changed journal/Git fact sources.review-passed Server filters before paging; Review cursors bind frozen snapshots and detect staleness.
J · Canonical entry-point cutoverFile-module call graph, old-adapter removal, legacy-session unavailable display.No filesWsRequest global queues, request_id-less actions, or direct turn_file_diff UI calls. Old sessions cannot use bypass fallbacks.No hidden compatibility switches for legacy entries; retain verifiable read-only metadata.review-passed Canonical request path established; old actions/fallbacks and temporary registries removed. Server/frontend split into stable acyclic responsibilities.
K · Turn card empty and failure statesassistant-bubble.tsx, message-rail.tsx, turn-files-chips.tsx and card CSS.Plain replies mount neither card nor Review. Legacy file-writing turns query on demand; empty results hide, failures show compact retryable state.No journal, Review-scope, diff, or recovery protocol changes.review-passed Empty/error/retry, stale responses, rail round trips, TypeScript, Web unit tests, static checks, production builds, documentation gates verified.

Complete visible acceptance

Directory and search pages

Search finds an unexpanded deep file. Concurrent create/rename makes old cursors stale; refreshed results restart in stable project order.

REQUIRED: complete project scope
All file request IDs

Issue directory/file reads, writes, renames, turn summaries, Review lists/diffs concurrently with out-of-order responses. Only matching pending requests accept responses. Same-idempotency write retries bind the same operation and replay completed results.

REQUIRED: no type-based matching or duplicate write
Dirty draft under pressure

Fill read-cache/IndexedDB quotas, reload, switch tabs/projects. Existing dirty drafts recover with original baselines. New/enlarging drafts without space commit no transaction and show visible guidance.

REQUIRED: no silent draft loss
Conversation only

Immediately create/activate stable target branch, preserving source refs/HEAD and current files. Alignment banner requires decisions before subsequent mutation.

PASS: mismatch visible
Code only

HEAD unchanged; append rewind transaction; Current branch Review reflects the new state.

PASS: history preserved
Branch from here

Confirmation immediately creates/activates target refs, preserving source HEAD/current files. The next message only extends the already-created target branch.

PASS: source preserved
Retry/Edit sibling

New branches bind explicit before/after checkpoints. Users choose current versus target files; never silently continue old run results.

PASS: checkpoint explicit
Revert and Reapply

Historical Revert succeeds only without later same-lineage dependencies. Reapply repeats preflight and appends transactions.

PASS: no redo shortcut
Filtered Review pages

Server-filter Code/Tests/Docs/Large results exceeding one page. Category/query/sort changes hide old pages/diffs. Index/worktree/candidate changes after snapshot make later pages/diffs stale.

REQUIRED: filter before page and exact workspace pair
Concurrent writer

Background tasks, other sessions, or external changes invalidate plans or trigger post-apply verification rollback.

PASS: zero overwrite
Crash recovery

Force termination/restart at every intent phase. End COMMITTED, ROLLED_BACK, or persisted path-specific RECOVERY_REQUIRED; never falsely commit or overwrite external writes.

PASS: every path explainable
Canonical cutover

Inspect call graphs from visible file entries: no temporary queues, ID-less actions, or direct-turn-diff fallback. Legacy sessions incompatible with new contracts show read-only unavailable.

REQUIRED: no compatibility bypass

Optional Office installation is implemented and independently reviewed for specification and quality. The final affected configuration, adapter, security and repository-contract selection passes 1,812 tests (82 optional-dependency skips and one expected failure). All 22 native Office/browser tests and 710 Web tests pass. Web build, TypeScript, static checks, Desktop checks and documentation links pass. The explicit-consent browser case verifies cancellation without installation, failure retry and automatic document opening; component tests verify immutable publication, origin denial and concurrent request deduplication. Actual fixed-source access through the managed HTTP client succeeds without downloading the archive body.

Implementation status

The continuous PDF reader, selectable text, clipboard normalization, outline and thumbnail navigation, highlights and free-text annotations are implemented. Public browser tests verify rendering, copying, annotation serialization, undo/redo and retained drafts after save failures in both native and desktop compatibility environments. Independent specification and quality reviews pass. Public regressions also verify restore input barriers, bounded extreme-aspect thumbnails and clearing search highlights. The complete source validation manifest passes, including real browser tests, Web tests, contracts, file component tests, build, type, static-resource and documentation checks. Installed-App acceptance is recorded separately from source verification.

PDF runtime compatibility uses the matching upstream legacy modules and permits local blob byte reads under the real shell policy. Public FileViewer tests verify rendering, navigation, zoom, search, close/reopen, invalid input and external-request rejection in native and missing-API environments. Independent specification and quality reviews, full Web and browser suites, repository contracts, affected authentication/frontend components, typecheck, production build, resource budget and documentation links pass. The reported research PDF renders and searches under the production policy with missing desktop APIs; its full document also decodes in the installed Electron runtime.

Human project binary publication/history APIs passed independent reviews and complete backend tests. Existing text writes share recovery transactions. Every write publishes immediately; history groups editing periods; recovery creates versions. Moved projects recover by current location; offline reads use saved versions. Failures/corruption show unconfirmed states.

Unified preview, text editing, and background autosave controllers completed source implementation, independent reviews, and full backend/Web/browser/documentation checks. Drafts cover unopened files; failures do not close tabs. Rename disables relevant editing and reopens new paths after success. Human/model History is unified with preview/recovery. Real DOCX/PPTX/XLSX modifications, exports, and reopen were verified. Legacy DOC/PPT/XLS save as OOXML; ODF original-format export verified. Immediate retry after failed saves and exporting input added while closing waits were verified locally. Installed default-App resources/UI were checked; runtime status is in local release records.

PDF pagination/zoom/search, PSD composites/layers, TIFF/common-image preview, and local audio/video completed implementation, independent reviews, and complete verification. Pinned local assets are used; corrupt/oversized files show errors/downloads. PDF/PSD/TIFF/audio/video remain read-only.

Local Office manifest validation, separate static origin, and authenticated availability APIs passed independent reviews/full verification. Only pinned local-source/version assets are accepted; remote origins are unavailable. Editor assets cannot access main APIs. Real Word/PPT/spreadsheet editing, export, preview switching, native undo, reopen, save retry, and final export were verified in the research engine. Office resources install separately into shared local cache; default App does not bundle them, and current workers use verified versions immediately after installation. Fonts require licenses; bundles retain source, patches, provenance. Unified Office preview/edit integration passed independent reviews/full checks (implementation ef64e6ab): 8746 backend, 672 Web unit, 16 real Office browser, and 20 other-preview browser tests passed; 542 documentation pages built with zero dead links. Edit mode waits for native confirmation; native undo survives tabs/history; close commits pending input; old formats explicitly convert to new files. Human/model history is unified,

Static PNG/JPEG/WebP editing passed independent reviews/full verification (implementation 8dc8bf81). Actual export pixels verify crop, rotation, drawing, shapes, text, native undo/redo. Editors survive preview/history/tab/page changes, retry errors, and create separate PNG conversions refusing overwrite. 8746 backend, 678 Web unit, 30 file-browser, and 16 Office-browser tests passed; 542 docs pages built with zero dead links. Initial backend concurrency-quota timeout did not recur on an unchanged full rerun. Animated/16-bit PNG remain read-only; limits: 64 MiB, 16 million pixels, 16384px per side. Export does not promise embedded-metadata retention; PSD remains composite/layer preview.

Unified human/model history passed independent reviews/full verification (implementation fcf799bd): 8767 backend, 678 Web unit, 32 file-browser, 16 Office-browser tests passed; 542 docs pages built without dead links. Initial cancellation-retry timeout passed separately on candidate/baseline and in an unchanged full rerun. Model versions reuse immutable bytes retained by their sessions; archives remain readable, permanent deletion removes readability. Legacy history backfills in bounded batches; unverifiable ownership is unavailable. Recovery changes only selected files and adds records. Project moves preserve ownership; offline access is read-only. Main-branch integration passed independent review/full combined verification.

Final integrated implementation f0e67531 includes current main fixes and passed independent specification/quality re-review. Complete combined checks passed 8862 backend, 678 Web unit, 32 file-window browser, 16 real Office browser, and 190 CLI tests. Desktop, types, builds, static-asset budgets, and 546 docs pages passed with zero dead links. Earlier self-update test process exit/replacement-state reuse passed focused/baseline checks and did not recur in the final full run; failure records remain. Default-App install/restart acceptance uses the same integrated source and verified Office resources, with runtime records separate from source checks.

File-history durability verified: immutable versions, failure retries, corrupt-record rejection, incomplete-write projections, legacy compatibility. New generators reuse source_path publication; Office semantic diffs/remote conditional storage are outside current implementation.

Document source_path publication and binary reads are implemented, independently reviewed, and tested. Full versions persist with sessions, supporting Undo, reapply, and conflicts; no Office semantic-diff view.

Current implementation status:Directory/search snapshots, file request identity, durable mutations, bounded read cache, durable drafts, server-paged Review, canonical-entry migration, and stable module boundaries all passed independent review.

Implementation evidence lives in corresponding tests; this page maintains current contracts and overall status only.

Portable snapshot consistency

Regular-file snapshots compare descriptor metadata before and after reading, and path metadata before opening and after reading. Descriptor and path identity must agree on device and inode. Metadata from different operating-system APIs is not compared as if it had identical timestamp or mode representation. Either observation changing aborts publication; the path observation supplies the stored permission mode. Legacy migration opens staged files with writable handles on Windows before flushing data, while preserving the source until publication succeeds.