Repository navigation
[split-1066] U3 - feat(tools): onParameterParseFailure teardown boundary #1936
Description
Activity
easonLiangWorldedtech commented
on Oct 10, 2026 ContributorAuthorMore actionsPending row: cancellation-aware diff open
The review row on PR 1931 asks that
DiffViewProvider.open()andopenDiffEditor()become cancellation-aware. Today a task disposed whileopen()is in flight leaves the pending open and its deferred-scroll timeout running, so a later partial delta can resurrect a diff view for a task that no longer exists.Acceptance:
- Task disposal cancels or is awaited by the in-flight open, and the deferred scroll timeout is disposed.
- A test disposes the task mid-
open()and asserts no diff view survives and no timeout fires afterwards. - Negative control recorded for this unit: the number of tests the mutation kills, so the port to sibling units can be compared.
This unit goes first; the change then ports in merge order 1928, 1931, 1929, 1930, 1932.
easonLiangWorldedtech commented
on Oct 10, 2026 ContributorAuthorMore actionsDefect: the rollback guard silently skips the
saveDirectlybranch, andreset()forgets instead of cleaningFound while checking the coupling with U6 (#1932), at U3 head
5ff7bea73. Both halves are U3 code:
the guard came in with5c0f21219and the swallowing caller with2a9bfabfb.1. A guard keyed on a flag only one path sets.
DiffViewProvider.revertChanges()opens with
if (!this.relPath || !this.isEditing) return, butisEditing = trueis assigned only inside
open(). ThePREVENT_FOCUS_DISRUPTIONbranch never callsopen(), so in that branch
revertChanges()early-returns and nothing rolls back: the directories handed over by
adoptCreatedDirs()stay on disk and the filesaveDirectly()wrote stays written. Worse, the
callerWriteToFileTool.revertDiffChangesBeforeReset()still returnstrue, so the teardown is
reported as complete andreportRevertFailure()never fires. A swallowed failure is worse than a
reported one. A guard condition must be proven reachable from every entry point; using a flag
that only one path sets turns the guard off for the other path.2.
reset()forgets instead of cleaning.reset()setscreatedDirs = []and
adoptedCreatedDirs = []without removing anything from disk, so "early return + reset" leaves
the preflight-created directories on disk permanently: after the reset no code path knows them.Acceptance criteria
- With
experiments: { preventFocusDisruption: true }, a failed or deniedsaveDirectlywrite
removes the directories this call created and unlinks a file it created (modify: content
restored) - the rollback works on the branch that never opened a diff view. - The rollback return value reflects what actually happened: "nothing to do" and "did the work"
must not be conflated with "silently skipped", and a skipped rollback must reach
reportRevertFailure(). reset()may only drop the directory list after the directories are gone, or the caller must
roll back before it resets - proven by a test that fails whenreset()runs first.- Every test added for this runs with the experiment ON as well as OFF: the default branch
passes today and proves nothing about this defect.
Ported from the retired fork tracking item 6093538947. Timing: next legitimate push of #1931 (a
review in flight blocks the push, not this item).- With
easonLiangWorldedtech commented
on Oct 10, 2026 ContributorAuthorMore actionsFollow-up on new-file rollback ownership in unit U3 (pull 1931).
adoptCreatedDirs closes the rollback gap for the execute() preflight only: the streaming path still relies on DiffViewProvider.open() recording the directories it creates itself, and nothing asserts both entry points. A converging guard that only has one writer silently fails on the other path.
Acceptance: two tests, one per entry point (the execute() preflight, and open() during a partial stream), each proving that a rolled-back new-file write removes every directory that write created and nothing it did not create.
Owner: unit U3. Scheduled to ride the next legitimate push of that unit.
easonLiangWorldedtech commented
on Oct 10, 2026 ContributorAuthorMore actionsContingency note for unit U3 (pull 1931).
A discarded change is kept on disk rather than deleted: .tmp-cr-audit/p1066-u3-cancellation.patch, 99 additions and 11 deletions, which makes open() and openDiffEditor() cancellation-aware. It was reverted only because the checklist row it answered belonged to an older head, not because the change was wrong.
Acceptance: if a maintainer asks for cancellation-aware diff opening, apply the patch on the current head, re-run the DiffViewProvider spec and its negative controls, and re-measure how many tests each control reddens - do not re-derive it.
Owner: unit U3.
Unit U3 of the PR #1066 split (4/6).
Split plan: #703
PR: #1931
Content source of record: tag
pr1066-source=46d1d218701f0ce2d675b1b315489bacb6b0f77d(easonLiangWorldedtech/Zoo-Code).Unit contract
BaseTool.onParameterParseFailure()teardown boundary plus theWriteToFileTooloverride: when the final block fails to parse,execute()never runs, so this boundary finalizes the open partial ask, restores the diff document, releases the per-task state, and reports the earlier streaming failure instead of the incidental parse error.Why this unit exists on its own
Single provider group (BaseTool boundary + one tool override) + single gate scope.
Boundary
4b23b6a270aa(previous unit head, U5)e3c10401f760Files and budget
src/core/tools/BaseTool.ts+36/-3 — byte-identical to sourcesrc/core/tools/WriteToFileTool.ts+22/-0 — content subset of sourcesrc/core/tools/__tests__/writeToFileTool.spec.ts+192/-0 — content subset of sourceVerification (must pass by once, binary)
zdt split verify --contract U3.json --worktree <wt> --head e3c10401f760— PASS (every changed file is a content subset of the source of record, or an explicitly sanctionedallowNewfile).Task.spec.ts,writeToFileTool.spec.ts,writeToFileTool-partial-state-cleanup.spec.ts,removeClineFromStack-delegation.spec.ts,presentAssistantMessage-custom-tool.spec.ts).--prune-suppressions --max-warnings=0: clean on every touched file; suppression counts unchanged..changesetfile, no CHANGELOG edit (AGENTS.md).Deviations recorded
hasPathStabilizedForTask,// Stryker disable next-line ConditionalExpressionwith a concrete reason: the!== undefinedclause is not distinguishable by any test). It belongs to U4's content and travels with it.Reproduce