feat(tools): per-write checkpoint + change card for apply_diff (B3a v2-8a, epic #1375) - #50
Open
easonLiangWorldedtech wants to merge 1 commit into
Conversation
Review statusThanks for contributing. This comment tracks the review sequence and the next action. Current step: Required CI passed. Waiting for automated review of the latest commit. If automated review does not start, a maintainer must restart it. Review-state labels are managed by this workflow; do not edit them manually. |
easonLiangWorldedtech
force-pushed
the
feat/fws-v2-7-changecard-core
branch
from
September 6, 2026 00:54
11eeb88 to
a552872
Compare
easonLiangWorldedtech
force-pushed
the
feat/fws-v2-8a-applydiff-wiring
branch
from
September 6, 2026 00:55
60c76ff to
2f6cb0a
Compare
apply_diff previously wrote with no per-file checkpoint and no change card, so its edits had no rollback surface in chat. Wire it to the v2-4 journal + v2-7 change-card pipeline with the same parity as write_to_file / edit_file / apply_patch: reuse the unified diff and stats already computed for the tool message, auto-approved steps get the compact card, live perWriteCheckpoints setting with default-on semantics, and a checkpoint failure never blocks the write.
easonLiangWorldedtech
force-pushed
the
feat/fws-v2-8a-applydiff-wiring
branch
from
September 6, 2026 02:30
2f6cb0a to
77c435f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
v2-8a of the file-write safety v2 rebuild (epic #1375): apply-diff tool wiring (B3a) — the
apply_difftool gets the same per-write checkpoint + change-card treatment aswrite_to_file/edit_file/apply_patch.apply_diffpreviously wrote with no per-file checkpoint and no change card, so its edits had no rollback surface in chat. This is unit 2 of 4 in the split of the reviewed B3a content (legacy #1411, 1891 lines standalone → v2-7 core, v2-8a apply-diff tool wiring, v2-8b apply-patch/edit/search tool wiring, v2-9 settings/i18n UI).src/core/tools/ApplyDiffTool.ts— after the diff view is saved,apply_diffnow callscheckpointSavewith the per-write journal + change-card payload: it reuses the unified diff and stats already computed for the tool message (never recomputed), resolves auto-approval with the samecheckAutoApprovalcall shape the other wired tools use (auto-approved steps get the compact card via the v2-7 builder), and honors the liveperWriteCheckpointssetting with default-on semantics (skip only when explicitlyfalse). The approval message — built identically in both save branches — is now computed once and reused by the checkpoint's auto-approval resolution.apply_diffonly ever modifies an existing file (a missing file errors out before the patch is applied), so the operation is always"update". A checkpoint failure is swallowed (.catch(() => {})) — parity with the other wired tools — so it never blocks the write.src/core/tools/apply-patch/apply.ts—ApplyPatchFileChangegainsdiff?,diffStats?,autoApproved?(the approval-diff fields the per-step change card reuses; theapply_patchconsumer wiring lands in v2-8b).ApplyDiffTool.changeCard.spec.ts(5 tests): per-write checkpoint recorded with the applied diff + stats after a successful write (the success test also pins thecheckAutoApprovalcall-argument shape: live state, cwd,ask: "tool", the approval message text, protection flag); auto-approved step marked so the v2-7 builder renders the compact card;perWriteCheckpoints: false→ no checkpoint call; approval declined → nothing recorded and the tool still reports the error; provider state unavailable (providerRef.deref()→undefined) →state?.perWriteCheckpointsshort-circuits without throwing and the checkpoint still records. TheApplyDiffTool.prefix follows the v2-7index.checkpointSave.spec.tsconvention: the Stryker diff gate'spreferDirectTestFilesmatch is case-sensitive, and without it the suite would be excluded from the mutation test set whenever the related set also contains a direct match ofapply.ts.Gates (local, pre-push)
ApplyDiffTool.changeCardspec plus the adjacentchangeCard/apply.spec/applyPatchTool.execute/applyPatchTool.partialsuites.--max-warnings=0on all 3 touched files (fullzoo-codelint via pre-commit);eslint-suppressions.jsoncounts unchanged.pnpm check-types: clean (11/11 tasks).scripts/stryker-diff.mjs ci, base11eeb8845= v2-7 head (PR feat(checkpoints): per-step change card core: payload builder, emission hook, changeCardDetail setting (B3a v2-7, epic #1375) #49), head this commit): 21 changed-code mutants (all in theApplyDiffTool.tscheckpoint block), all Killed — 0 Survived / 0 NoCoverage.Equivalent mutants
None — the final run is clean (0 Survived / 0 NoCoverage), so no exclusion directives were needed. An intermediate run surfaced 4 survivors, all killed by test/code hardening before push: the dead
let completeMessage = ""initializer (both save branches overwrote it before use — the message is now computed once and shared, which removes the unobservable literal) and threecheckAutoApprovalcall-site mutants (the empty-argument object literal, theask: "tool"channel string, and thestate?.optional chaining) killed by the call-argument assertion in the success test and a new test whereproviderRef.deref()returnsundefined(the checkpoint path must stay alive with no provider state).Line budget
Standalone diff vs the PR base (
11eeb8845): 311 lines (294+/17−, 3 files) — within the 400-line soft design target.Stacking / merge order
Base:
feat/fws-v2-7-changecard-core(PR #49). v2-8b (apply-patch/edit/search tool wiring) stacks on this PR; v2-9 (settings UI + i18n) stacks on those. After the whole v2-8a..v2-9 chain lands on main, each base switches tomainwith an identical diff.Rebase note (round 23)
Rebased onto the current v2-7 head
a5528729c(was11eeb8845) after v2-7'schangeCardDetailoptional-field fix. This PR's diff content is byte-identical across the rebase, and the Stryker diff gate mutates only changed diff lines — the outcome above therefore stands; no re-run required.