F4 SLICE-5: host E2E (propose/accept/reject/persist/stale/coexist) + seam fix: event-level net-effect matching survives host word-diff splitting (INV-9) (#12)

The accept E2E exposed a latent F3 limitation: VS Code word-diffs one
applied WorkspaceEdit into several minimal hunks when old/new share
interior tokens, so the registry's per-hunk exact match missed and seam
edits fell through as fragmented human spans. PendingEditRegistry.match
is replaced by matchEvent (all hunks inside the registered full range +
equal net delta — one applyEdit is one change event). Plan AMENDMENT 1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-06-10 22:12:15 -07:00
parent 452c071efb
commit 8fdea97d36
7 changed files with 278 additions and 35 deletions
@@ -1153,6 +1153,21 @@ git commit -m "F4: document propose/accept — manual smoke, README, playground
---
## Amendments (during execution)
- **AMENDMENT 1 (Task 7):** the F4 accept E2E exposed a latent F3 seam
limitation — the host word-diffs one applied WorkspaceEdit into SEVERAL
minimal hunks when old/new share interior tokens (F4's realistic
replacements do; F3's test strings never did), so the registry's per-hunk
exact match missed and the edit fell through as fragmented HUMAN spans.
Fix: `PendingEditRegistry.match` (per-change equality) is replaced by
`matchEvent` (event-level net-effect match: every hunk inside the
registered full pre-edit range + equal net length delta — sound because one
applyEdit is one change event), and `AttributionController.onDidChange`
matches the event once, applying the full intended replacement as ONE
algebra edit on a hit. Unit tests rewritten accordingly
(`test/pendingEdits.test.ts`); INV-9's miss-warning path unchanged.
## Self-review notes
- **Spec coverage:** §6.3 model → Task 1/3; store prune → Task 2; §6.4 controller contracts (propose/acceptById/rejectById/getRendered/getStaleCount, hidden command) → Tasks 4/5; §6.5 PUC-1..5 → Tasks 4/6/7; §5 UX (amber deco, second comments controller, ✓/✗ title actions, status-bar stale count) → Tasks 4/5; INV-10..13 asserted in E2E (Task 7); §6.8 testing strategy → Tasks 13 (unit) + 7 (host E2E) + 8 (manual smoke); §7.3 done-bar → Task 8 gate + smoke.