Repository navigation
fix(write-to-file): run diff cleanup when handleError rejects (split 5/6 of #1066) - #1932
Open
easonLiangWorldedtech wants to merge 18 commits into
Open
easonLiangWorldedtech wants to merge 18 commits into
easonLiangWorldedtech wants to merge 18 commits into
Conversation
easonLiangWorldedtech
requested review from
JamesRobert20,
edelauna,
navedmerchant and
taltas
as code owners
October 5, 2026 17:12
Contributor
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 6 minutes. View limit details
📝 Summary
|
U6 — execute() error-path cleanup invariant
Part of the upstream PR 1066 split. Own issue: 1937. Content source of record:
72143527fd33306e5541116093c2cbf803cce9e0..pr-1066-audit).Why this unit exists: execute() cleanup invariant: the finally around handleError, the writeApproved flag and the consecutive-mistake-counter order. Soft budget overshoot: 439 a+d (single provider group, single gate scope).
Boundaries
e3c10401f9b93a6f8872143527fd33306e5541116093c2cbf803cce9e0..pr-1066-audit(local)Fidelity (machine-verified)
Result: PASS — standalone 439 a+d / 2 files (SOFT-OVERSHOOT (rationale required in PR body))
src/core/tools/WriteToFileTool.ts: OK (content subset of source)src/core/tools/__tests__/writeToFileTool.spec.ts: OK (content subset of source)Budget rationale (soft overshoot): see the deviations list
Design contract
Chain position
Merge order is fixed: U12 (1927) -> U4 -> U5 -> U3 -> U6 -> U7 -> FINAL (1928). This PR is opened against
mainbecause the split branches live on the fork; the diff GitHub shows is therefore cumulative through this unit. The unit's own content is the delta from the previous unit head (U3), listed under Fidelity above. The sole merge target of the series is the FINAL integration PR (1928); merging the chain in order keeps every bot-visible diff clean.Verification (this unit, as pushed)
.changesetfile, no CHANGELOG edit.Recreate policy
If the bot stalls on a pre-merge check and the existing head cannot obtain bot review/approval (empty-commit re-trigger attempted and failed), the unit is recreated from the tagged content source of record — never from a per-PR head. At most 1 PR per issue.
Linked issue
Closes #1937 (unit U6 of the upstream PR 1066 split).
Round update — Lifecycle Resource Cleanup
Shared root cause behind the
Lifecycle Resource Cleanuprow (all five units of 1066).handlePartial()registers this task's partial-stream entry — and itsTaskAbortedlistener — before it checks the prevent-focus-disruption experiment. With the experiment enabled the delta returns without ever showing a preview and never reachesexecute()'s teardown, so the entry and the listener stay attached for the rest of the task's life, and astreamFailedmark armed by an earlier failed delta keeps suppressing this task's later diff previews. The sibling units carry the same release in their own PRs, each verified red-first with a negative control.This unit (U6):
execute()is already covered by thefinally { this.resetTaskPartialState(task) }block, so only the suppressed-preview return inhandlePartial()lacked a release; it now has one.Red first: the new test failed with
expected 1 to be +0. Green: 57 passed / 5 skipped. Negative control: removing the release turns exactly that one test red; restored green.Main refresh. Merged org main
036245c5e(U1 1927). U1's content no longer appears in this diff: 10 files +2048/−45 → 7 files +1593/−40, 0 behind main. Conflicts were confined tosrc/core/task/__tests__/Task.spec.ts(andTask.tson U7) — the region U1 rewrote; resolved by taking main's version of the shared save-stage tests (try/finally plus the fixed-task-idui_messages.jsoncleanup fromcf9206a42) rather than re-implementing U1.Verification after the merge: Task.spec 172 passed, writeToFileTool.spec 57/5, eslint 0/0.
Scope declared in the split plan
CodeRabbit's Out of Scope Changes row asks to either narrow this PR to the
execute()cleanup scope or update the linked split. The plan was updated first, per this chain's planned-and-issued rule - see, comment 6076465965 (2026-10-09), which declares U6's scope at headc6b77fbce. The files outside theexecute()cleanup scope are therefore planned, not drift:src/core/tools/BaseTool.ts- partial-stream state ownership: the per-tasktaskPartialStreamStatemap and its release pair live inBaseTool, so the prevent-focus-disruption release cannot be expressed without touching it.src/core/webview/ClineProvider.ts+src/__tests__/removeClineFromStack-delegation.spec.ts- teardown wiring: the shared finalization and the diff-view reset the cleanup path calls are owned there.handlePartial()- it registers the per-task entry and theTaskAbortedlistener; releasing that registration is the defect this unit fixes.Chain merge order: U1 1927 (merged) -> U2 1928 -> U3 1931 -> U4 1929 -> U5 1930 -> U6 1932. The same root cause is fixed once and ported; every port commit cites the source commit.
Rows from the 2026-10-09 review
Two rows in that review need files outside the
execute()cleanup set. The scope was extended in the split plan before the fix was pushed: (retired fork tracking item 41).DiffViewProvider.revertChanges()must roll the created file and directories back even whenopen()failed beforeactiveDiffEditorwas assigned. Same root cause as 1930; ported verbatim from7b783452c/6cae369d9.handlePartial()re-checks that this task's stream entry is still live after each await (provider state, filesystem probe, partial ask,open()).execute()test, same shape as the three on 1929.Fix commit:
443993e57. Negative controls are one-to-one (each re-check and each release site kills exactly its own test).