fix(#70): INV-5 — reject after an interior tweak restores the retained original #73
Reference in New Issue
Block a user
Delete Branch "s70-inv5-reject-gap"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #70.
Rejecting an optimistically-applied proposal after typing inside its pending range silently skipped the revert (the exact-substring anchor orphans per INV-11, and
revertInPlaceskipped the WorkspaceEdit yet removed the proposal and reported success) — INV-5 did not hold on that path.Fix — issue direction (a) with an honest (b) fallback; (c) fuzzy resolve rejected (INV-11: never guess):
DocState.appliedSpansis the real F12 applied-range bookkeeping: written at optimistic-apply, rebuilt from an exact resolve when absent (reload/reopen), shifted through interior-safe edits via the new pureshiftTracked(anchorer.ts, unit-tested), and distrusted (deleted) when an edit straddles a span boundary or the document closes.revertInPlace: exact resolve → tracked span → loud failure (warning with a Discard proposal (leave text) action, proposal kept,falsereturned). Read-only sidecars (INV-16) now refuse finalize/revert too.rejectAllorders by the same fallback and returns{ reverted, skipped }; the command and the QuickPick batch menu both report skips.Tests: +11
shiftTrackedunit tests (312 unit total); +5 host E2E (repro, gesture routing, distrusted hard-fail, rejectAll parity, lens reachability); fullLoop reject leg now tweaks inside the pending range first. 312 unit + 94/5 E2E green (1 occasionally pending = the known #54 undo-capability probe).Follow-up (pre-existing, filed separately):
resolve()accepts a single exact occurrence without a context check — a duplicated block can hijack any anchor consumer.Plan:
docs/superpowers/plans/2026-07-02-70-inv5-reject-after-interior-edit.md(session 0066).🤖 Generated with Claude Code