feat!: sunset the review-panel webview — built-in preview + native diff are the review surfaces (D3/D17, spec §6.10); Keep/Reject lens copy (PUC-2)

Deletes the last bespoke UI surface (TrackChangesPreviewController + its
sealed webview client assets); every entry point re-points at native VS
Code chrome per spec §5: the #41 right-click entries become
cowriting.openReviewPreview (enter coediting if needed -> "Open Preview to
the Side"), Ctrl+Alt+R/Cmd+Alt+R moves to cowriting.reviewChanges (native
diff), and the F12 CodeLens per-proposal titles read "Keep"/"Reject" with
a top-of-file "Keep all (N)"/"Reject all" pair once >=2 proposals are
pending. EditFlow drops its own askClaude/askEditInstruction (the
webview's only caller) and its now-unused constructor params.

Coverage that lived only in the webview's test seams (renderHtmlFor,
receiveMessage, isOpen, ...) moves to direct calls against the surviving
controllers/pure renderReview (test/e2e/suite/helpers.ts gains a shared
renderHtmlFor probe); a genuine gap (pending-proposal + unchanged-block
rendering) is backfilled in test/previewAnnotations.test.ts. README's "how
it works" is rewritten as the native-surface map; the superseded F6/F7/F9/
F10/F11 sections are kept as a marked historical record rather than
deleted outright.

292 unit + 91 E2E green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
BenStullsBets
2026-07-02 14:51:18 -07:00
parent 17fc01e8d8
commit 2170a0d282
23 changed files with 412 additions and 1475 deletions
+8 -13
View File
@@ -10,7 +10,7 @@ const settle = () => new Promise((r) => setTimeout(r, 400));
async function getApi(): Promise<CowritingApi> {
const ext = vscode.extensions.getExtension("benstull.vscode-cowriting-plugin")!;
const api = (await ext.activate()) as CowritingApi;
assert.ok(api?.trackChangesPreviewController && api?.proposalController, "exports controllers");
assert.ok(api?.editFlow && api?.proposalController, "exports controllers");
return api;
}
@@ -36,20 +36,18 @@ suite("F12 SLICE-3 — accept-all (#46, INV-42)", () => {
test("acceptAll applies every pending proposal and reconstructs the document", async () => {
const original = "# All\n\nFirst para alpha.\n\nSecond para beta.\n\nThird para gamma.\n";
const rewrite = "# All\n\nFirst para ALPHA.\n\nSecond para BETA.\n\nThird para GAMMA.\n";
const { doc, key } = await freshDoc("docs/f12-all.md", original);
const { doc } = await freshDoc("docs/f12-all.md", original);
const api = await getApi();
const ctl = api.trackChangesPreviewController;
const editFlow = api.editFlow;
await vscode.commands.executeCommand("cowriting.showTrackChangesPreview");
await settle();
editFlow.setEditTurnForTest(async () => ({ replacement: rewrite, model: "sonnet", sessionId: "e2e-f12-all" }));
const ids = await editFlow.runEditAndPropose(doc, { kind: "document" }, "uppercase the nouns");
await settle();
assert.strictEqual(ids.length, 3, "three changed blocks → three pending proposals");
// Simulate the toolbar "Accept all" button posting its intent.
ctl.receiveMessage(key, { type: "acceptAll" });
// Route through the real "Keep all" command (Task 8, PUC-2) — the doc is the
// active editor from freshDoc, matching the top-of-file CodeLens's own target.
await vscode.commands.executeCommand("cowriting.acceptAllProposals");
await settle();
await settle();
@@ -65,8 +63,6 @@ suite("F12 SLICE-3 — accept-all (#46, INV-42)", () => {
const { doc } = await freshDoc("docs/f12-orphan.md", original);
const api = await getApi();
const editFlow = api.editFlow;
await vscode.commands.executeCommand("cowriting.showTrackChangesPreview");
await settle();
editFlow.setEditTurnForTest(async () => ({ replacement: rewrite, model: "sonnet", sessionId: "e2e-f12-orphan" }));
const ids = await editFlow.runEditAndPropose(doc, { kind: "document" }, "uppercase");
@@ -96,14 +92,13 @@ suite("F12 SLICE-3 — accept-all (#46, INV-42)", () => {
assert.strictEqual(api.proposalController.listProposals(doc).length, 1, "the orphaned proposal remains pending");
});
// A single pending proposal still applies through the batch path (the button is
// hidden < 2 pending in the webview, but the command/seam handle any count).
// A single pending proposal still applies through the batch path (the
// top-of-file "Keep all" CodeLens is hidden < 2 pending, Task 8 PUC-2, but the
// command/seam handle any count).
test("acceptAllProposals with one pending proposal applies it", async () => {
const { doc } = await freshDoc("docs/f12-one.md", "# One\n\nThe only paragraph here.\n");
const api = await getApi();
const editFlow = api.editFlow;
await vscode.commands.executeCommand("cowriting.showTrackChangesPreview");
await settle();
editFlow.setEditTurnForTest(async () => ({
replacement: "# One\n\nThe ONLY paragraph here.\n",
model: "sonnet",