Repository navigation
Open
Description
Tracking issue for the B1 PR (branch feat/per-write-checkpoints-b1; PR to be opened after review).
Part of the file-write safety series — plan: easonLiangWorldedtech/Zoo-Code#33, epic: #1375. Item: B1 — Per-write checkpoint. Stacked on #1395 (S3 atomic publish); to be rebased onto main once #1395 lands.
Scope
- Every successful
write_to_file/edit_file/apply_patchrecords a shadow-git checkpoint after the write succeeds (one per write;apply_patch= one checkpoint after the whole patch), in addition to the existing pre-write and user-message checkpoints. The checkpoint reuses the existing shadow git at<globalStorage>/tasks/<taskId>/checkpointsand the existingcheckpoint_savedplumbing — no new say/webview message types. - Task start records one O(1) baseline checkpoint (
allowEmpty, suppressed, no worktree), exactly once per task. - The per-write checkpoint and the baseline are non-blocking (fire-and-forget, crash-safe) so the write path keeps its ≈0 added latency.
- New setting
perWriteCheckpoints(boolean, defaulttrue) — the master switch for the B cluster, gating both behaviors; ships with the full persisted-setting round trip (types, ExtensionState, ClineProvider getState/getStateToPostToWebview, webview SettingsView cachedState save flow, CheckpointSettings UI, all locales).
Acceptance
- One checkpoint per successful write (mock-service assertions per tool); none on rejected or failed writes
- Task-start baseline recorded exactly once per task instance, cheap (no worktree)
- Rollback index: the checkpoint id is surfaced through the existing
checkpoint_saved/currentCheckpointUpdatedplumbing - Setting round trip: default
true; storedtrue/false/unset all resolve correctly ingetStateToPostToWebview(); UI save via cachedState; import/export round trip - CI green (ubuntu unit-test gate), 100% codecov patch coverage
Status
- PR: to be opened
Corrections measured at 8415547 on feat/per-write-checkpoints-b1, 2026-11-09
- Bullet 8 above promises the per-write checkpoint and the task-start baseline are non-blocking, fire-and-forget, and keep the write path at about zero added latency. That is not what the code does. The call is awaited —
await checkpointSave(task, false, true).catch(() => {})at ApplyPatchTool.ts:196, :206 and :220,await checkpointSave(task, ...)at EditFileTool.ts:473 and WriteToFileTool.ts:185 — so the write path waits for the save to settle. What is true is narrower and worth saying precisely: a checkpoint failure cannot fail the write, because the rejection is swallowed, but this is awaited-with-swallow rather than fire-and-forget, and the added latency is not approximately zero. - The setting and its copy did land completely:
perWriteCheckpointsnow appears in all eighteen locale files, English at webview-ui/src/i18n/locales/en/settings.json:772-775, namingwrite_to_file,edit_fileandapply_patchand stating that an editor save records no checkpoint. That was proved with a control in which the previous copy fails nineteen of twenty-four rows. - Scope note for readers of the diff: the unit delta at this head is 23 files, +273 minus 43, and
src/core/task/Task.tsis not among them — it is byte-identical to the parent at 6,587 lines. Three rows ofcore/task/__tests__/Task.spec.tsnevertheless fail in CI's coverage-core lane at this head and passed at the parent head, so whoever reads this should not infer from the file list that Task behaviour is untouched by this change; the failing rows areTypeError: Cannot set property abort of #<Task> which has only a getterand the open question is cross-file state in that lane, not this file. - Two questions stay unowned rather than quietly closed: the bounded wait, expiry and cancellation semantics for queued checkpoint work (
Task.ts:3880-3920withcheckpoints/index.ts:236-263, threadsPRRT_...7pkQandPRRT_...7p-r), and the stray.<name>.<pid>.<ts>.backupfile left by a crash between the two renames atApplyPatchTool.ts:588and:590, which has no sweeper anywhere in the tree and is filed as its own follow-up rather than resolved inside a thread.
Metadata
Metadata
Assignees
Labels
No labels
Activity