Repository navigation
Block resuming checkpoints with an uncertain in-flight write #7
Description
Problem
write creates or overwrites files, but it is missing from the core isMutating() classification. A checkpoint written immediately before a write call therefore records inFlightTool.mutating: false. Both resume checks trust that recorded flag, so a checkpoint whose file-write outcome is uncertain can be accepted for continuation.
This is a maintainer-priority reliability issue: the consequences and compatibility with existing journals need review before expanding contributor work on session recovery. It is intentionally not labeled good first issue.
Verified reproduction
At the linked commit, isMutating("write") returns false. Passing an otherwise compatible synthetic checkpoint with the following in-flight tool to resumeBlock(checkpoint, null) returns null (no blocker):
inFlightTool: {
id: "root-c1",
name: "write",
argumentsHash: "synthetic-fixture",
mutating: false,
}The CLI-facing checkResumable() also checks only the stored mutating flag. The existing in-flight apply_patch tests demonstrate the intended refusal behavior for mutations, but do not cover this misclassified write case.
The confirmed problem is acceptance of an uncertain file-write state. This reproduction does not demonstrate that the same write was automatically executed twice. No process-kill end-to-end experiment or live model call was performed.
Expected behavior
An interrupted in-flight write whose effect cannot be established must be treated as an uncertain mutation and must not pass the normal resume checks. Old journals that recorded write with mutating: false need the same protection; updating only the classification for newly written checkpoints is insufficient.
Acceptance criteria
-
writeis classified as mutating for newly recorded checkpoints. - Existing checkpoints with an in-flight
writeand a false stored mutation flag are evaluated using the current tool classification and blocked when execution is uncertain. - Core
resumeBlock()and the CLI-facingcheckResumable()agree on these cases. - Regression coverage distinguishes a checkpoint before a write starts, an in-flight write without a durable completion checkpoint, and a write whose observation and completion checkpoint were durably recorded.
- Normal read-only resumptions remain supported, and existing compatibility/corruption checks remain intact.
- The refusal explains that the working tree must be inspected before starting a new run; it does not guess whether the file changed.
Starting points
packages/core/src/checkpoint.ts: tool classification andresumeBlock()packages/core/src/loop.ts: durable intent before executionpackages/journal/src/index.ts: CLI resume checkpackages/core/test/resume.test.tspackages/journal/test/journal.test.ts
Suggested validation
pnpm exec vitest run packages/core/test/resume.test.ts packages/journal/test/journal.test.ts
pnpm typecheckUse deterministic checkpoints, journal fixtures, and a fake executor for regression coverage. An integration test should exercise the resume decision used by the CLI without contacting a model endpoint. This issue does not require changing the journal format or implementing automatic replay of uncertain mutations.
Maintainer coordination
Please discuss the handling of legacy checkpoints with @TaewoooPark before starting implementation. This issue can be reproduced and tested without an API key or GPU.
Verified against 4d3e20a on 2026-09-21 using synthetic state.
Activity
TaewoooPark commentedon Sep 22, 2026
Opened #33 with the patch and before/after validation. It covers new and legacy write checkpoints, journal/core agreement, and interactive
/resume/--continue. All five GitHub CI jobs pass.Please review by 2026-09-25 00:30 KST (2026-09-24 15:30 UTC), especially interruption boundaries and legacy journals. This issue remains open while the PR is under review.
TaewoooPark commentedon Sep 24, 2026
Resolved by PR #33, merged as 524369d. All six acceptance criteria are now checked. Post-merge main CI passed all five jobs.
Validation covers new and legacy in-flight writes (including stored
mutating: false), agreement between core and journal checks, interruption boundaries, and preserved read-only/completed resumptions. Built-CLI and actual PTY checks confirm that refused/resumeand--continueattempts leave history/channel unchanged and send no model request; a failed--continuealso does not launch its optional initial task as a fresh run.Released in 0.3.4: npm package · GitHub Release.