F6 #34: delete the dead two-pane diff-view UI, keep the baseline data layer

F10 (#29) made the rendered preview the single review surface and hid the F6
two-pane vscode.diff view (command + ctrl+alt+d set when:false). This removes
that now-unreachable view code:

- DiffViewController: drop toggle/findDiffTab/epochLabel/isDiffOpen, the
  `cowriting-baseline:` TextDocumentContentProvider + BASELINE_SCHEME + baselineUri
  + the content-provider change emitter, and the toggleDiffView command. The
  baseline DATA layer is fully intact — ensureBaseline/advance/pin/capture,
  getBaseline, baselineFilePath, onDidChangeBaseline, persistence (INV-19), and
  the machine-landing auto-advance (INV-18) that F7/F10 consume.
- package.json: remove the toggleDiffView command, its commandPalette entry, and
  the ctrl+alt+d keybinding.
- E2E: diffView suite keeps the baseline-data-layer tests, drops the two-pane
  view tests; the F10 + no-workspace suites assert toggleDiffView is now absent
  (was: declared-but-hidden).

Deliberate deviation from the issue's literal acceptance: pinDiffBaseline is
KEPT. The canonical Solution Design (coauthoring-interactive-review.md §6.7)
scopes the removal to the two-pane VIEW only ("keep the controller + baseline
store"); pin() lives in the baseline lifecycle (§6.4), never touches vscode.diff,
and is exercised by live F7 baseline-reset tests. Where the P3 capture draft and
the approved spec conflict, the spec wins (documentation-leads-automation).

194 unit + 49 E2E green; typecheck + build clean. No F7/F10 behavior change.

Closes #34

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-06-12 02:10:14 -07:00
parent fd263ec674
commit 3520397e41
6 changed files with 64 additions and 199 deletions
+1 -15
View File
@@ -69,14 +69,9 @@
"title": "Propose Agent Edit (internal seam)", "title": "Propose Agent Edit (internal seam)",
"category": "Cowriting" "category": "Cowriting"
}, },
{
"command": "cowriting.toggleDiffView",
"title": "Cowriting: Toggle Diff View",
"category": "Cowriting"
},
{ {
"command": "cowriting.pinDiffBaseline", "command": "cowriting.pinDiffBaseline",
"title": "Cowriting: Pin Diff Baseline to Now", "title": "Cowriting: Pin Review Baseline to Now",
"category": "Cowriting" "category": "Cowriting"
}, },
{ {
@@ -103,10 +98,6 @@
"command": "cowriting.rejectProposal", "command": "cowriting.rejectProposal",
"when": "false" "when": "false"
}, },
{
"command": "cowriting.toggleDiffView",
"when": "false"
},
{ {
"command": "cowriting.pinDiffBaseline", "command": "cowriting.pinDiffBaseline",
"when": "false" "when": "false"
@@ -145,11 +136,6 @@
] ]
}, },
"keybindings": [ "keybindings": [
{
"command": "cowriting.toggleDiffView",
"key": "ctrl+alt+d",
"when": "false"
},
{ {
"command": "cowriting.showTrackChangesPreview", "command": "cowriting.showTrackChangesPreview",
"key": "ctrl+alt+r", "key": "ctrl+alt+r",
+17 -106
View File
@@ -1,12 +1,15 @@
/** /**
* DiffViewController — F6 diff-view toggle (spec §6.2/§6.4). Owns the baseline * DiffViewController — F6 baseline data layer (spec §6.4/§6.7). Owns the baseline
* lifecycle (initialize at first sight / advance at every machine landing / pin * lifecycle (initialize at first sight / advance at every machine landing / pin
* on demand), serves the baseline as a readonly `cowriting-baseline:` virtual * on demand) and serves it to F7/F10 via `getBaseline` + the additive
* document, and toggles a native vscode.diff (baseline left, the LIVE document * `onDidChangeBaseline` event. A pure data layer: never mutates the document,
* right). A pure view: never mutates the document, sidecar, or attribution * sidecar, or attribution state (INV-19).
* state (INV-19).
* *
* F6 works on ANY text document, not just workspace files — it needs no * The F6 two-pane `vscode.diff` *view* (toggle UI + the `cowriting-baseline:`
* virtual document) was removed in #34 once F10 made the rendered preview the
* single review surface; only the baseline store survives here (spec §6.7).
*
* The baseline works on ANY text document, not just workspace files — it needs no
* `.threads/` sidecar, only a stable doc identity + a storage home. So it has * `.threads/` sidecar, only a stable doc identity + a storage home. So it has
* its OWN diffable predicate (any `file:` or `untitled:` doc), decoupled from * its OWN diffable predicate (any `file:` or `untitled:` doc), decoupled from
* F2's workspace `isTracked`. Persistable docs (`file:`) keep their baseline in * F2's workspace `isTracked`. Persistable docs (`file:`) keep their baseline in
@@ -14,40 +17,24 @@
* untitled buffers have no durable identity, so their baseline is in-memory * untitled buffers have no durable identity, so their baseline is in-memory
* only (lost on reload) — the same degrade the storage-unavailable path uses. * only (lost on reload) — the same degrade the storage-unavailable path uses.
*/ */
import * as path from "node:path";
import { createHash } from "node:crypto"; import { createHash } from "node:crypto";
import * as vscode from "vscode"; import * as vscode from "vscode";
import { BaselineStore, type Baseline, type BaselineReason } from "./baselineStore"; import { BaselineStore, type Baseline, type BaselineReason } from "./baselineStore";
export const BASELINE_SCHEME = "cowriting-baseline";
export class DiffViewController implements vscode.Disposable { export class DiffViewController implements vscode.Disposable {
private readonly disposables: vscode.Disposable[] = []; private readonly disposables: vscode.Disposable[] = [];
/** Source of truth for the content provider, keyed by `document.uri.toString()`. */ /** Source of truth for the baseline, keyed by `document.uri.toString()`. */
private readonly baselines = new Map<string, Baseline>(); private readonly baselines = new Map<string, Baseline>();
private readonly onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
/** F7 (additive): fires on every baseline capture (open / advance / pin) so /** F7 (additive): fires on every baseline capture (open / advance / pin) so
* the track-changes preview refreshes without polling. Mirrors the internal * the track-changes preview refreshes without polling. Carries the real
* content-provider change signal but carries the real document URI. */ * document URI. */
private readonly onDidChangeBaselineEmitter = new vscode.EventEmitter<{ uri: string }>(); private readonly onDidChangeBaselineEmitter = new vscode.EventEmitter<{ uri: string }>();
readonly onDidChangeBaseline = this.onDidChangeBaselineEmitter.event; readonly onDidChangeBaseline = this.onDidChangeBaselineEmitter.event;
private storageWarned = false; private storageWarned = false;
constructor(private readonly store: BaselineStore | null) { constructor(private readonly store: BaselineStore | null) {
const provider: vscode.TextDocumentContentProvider = {
onDidChange: this.onDidChangeEmitter.event,
provideTextDocumentContent: (uri) => {
// The baseline URI carries the real document URI in its query (see baselineUri).
return this.baselines.get(uri.query)?.text ?? "";
},
};
this.disposables.push( this.disposables.push(
this.onDidChangeEmitter,
this.onDidChangeBaselineEmitter, this.onDidChangeBaselineEmitter,
vscode.workspace.registerTextDocumentContentProvider(BASELINE_SCHEME, provider),
vscode.commands.registerCommand("cowriting.toggleDiffView", () =>
this.toggle(vscode.window.activeTextEditor),
),
vscode.commands.registerCommand("cowriting.pinDiffBaseline", () => vscode.commands.registerCommand("cowriting.pinDiffBaseline", () =>
this.pinCommand(vscode.window.activeTextEditor), this.pinCommand(vscode.window.activeTextEditor),
), ),
@@ -60,7 +47,7 @@ export class DiffViewController implements vscode.Disposable {
// ---- diffability / identity -------------------------------------------------------- // ---- diffability / identity --------------------------------------------------------
/** Any text document F6 can diff: a saved file OR an unsaved buffer. */ /** Any text document F6 tracks a baseline for: a saved file OR an unsaved buffer. */
private isDiffable(document: vscode.TextDocument): boolean { private isDiffable(document: vscode.TextDocument): boolean {
return document.uri.scheme === "file" || document.uri.scheme === "untitled"; return document.uri.scheme === "file" || document.uri.scheme === "untitled";
} }
@@ -76,11 +63,6 @@ export class DiffViewController implements vscode.Disposable {
private storageKey(uriKey: string): string { private storageKey(uriKey: string): string {
return createHash("sha256").update(uriKey).digest("hex"); return createHash("sha256").update(uriKey).digest("hex");
} }
/** The readonly virtual-doc URI; its query carries the real document URI. */
private baselineUri(document: vscode.TextDocument): vscode.Uri {
const name = path.basename(document.uri.path) || "untitled";
return vscode.Uri.from({ scheme: BASELINE_SCHEME, path: "/" + name, query: this.uriKey(document) });
}
// ---- baseline lifecycle (§6.4) ----------------------------------------------------- // ---- baseline lifecycle (§6.4) -----------------------------------------------------
@@ -109,13 +91,13 @@ export class DiffViewController implements vscode.Disposable {
this.capture(document, "machine-landing"); this.capture(document, "machine-landing");
} }
/** Human pin: baseline := now; the open diff visibly empties (left = right). */ /** Human pin: baseline := now; the preview's change-marks empty (left = right). */
pin(document: vscode.TextDocument): void { pin(document: vscode.TextDocument): void {
if (!this.isDiffable(document)) return; if (!this.isDiffable(document)) return;
this.capture(document, "pinned"); this.capture(document, "pinned");
} }
/** Capture buffer text at this epoch, persist (if persistable), refresh any open diff. */ /** Capture buffer text at this epoch, persist (if persistable), notify F7/F10. */
private capture(document: vscode.TextDocument, reason: BaselineReason): void { private capture(document: vscode.TextDocument, reason: BaselineReason): void {
const key = this.uriKey(document); const key = this.uriKey(document);
const baseline: Baseline = { uri: key, text: document.getText(), capturedAt: new Date().toISOString(), reason }; const baseline: Baseline = { uri: key, text: document.getText(), capturedAt: new Date().toISOString(), reason };
@@ -127,8 +109,6 @@ export class DiffViewController implements vscode.Disposable {
this.warnStorageOnce(); this.warnStorageOnce();
} }
} }
// An open diff re-requests the left side when its baseline URI changes.
this.onDidChangeEmitter.fire(this.baselineUri(document));
this.onDidChangeBaselineEmitter.fire({ uri: key }); this.onDidChangeBaselineEmitter.fire({ uri: key });
} }
@@ -136,78 +116,13 @@ export class DiffViewController implements vscode.Disposable {
if (this.storageWarned) return; if (this.storageWarned) return;
this.storageWarned = true; this.storageWarned = true;
void vscode.window.showWarningMessage( void vscode.window.showWarningMessage(
"Cowriting: diff-view storage is unavailable — baselines are kept in memory only and won't survive a reload.", "Cowriting: baseline storage is unavailable — baselines are kept in memory only and won't survive a reload.",
); );
} }
// ---- toggle UX (§6.5 PUC-1) --------------------------------------------------------
/**
* If this doc's baseline diff is open → close it and reveal the normal editor;
* else open vscode.diff (baseline left, the live document right). Warns only
* when there is no active text editor (or a non-diffable scheme).
*/
private async toggle(editor: vscode.TextEditor | undefined): Promise<void> {
if (!editor || !this.isDiffable(editor.document)) {
void vscode.window.showWarningMessage(
"Cowriting: focus a text editor to toggle its diff view.",
);
return;
}
const document = editor.document;
const openTab = this.findDiffTab(document.uri);
if (openTab) {
await vscode.window.tabGroups.close(openTab);
await vscode.window.showTextDocument(document, { preview: false });
return;
}
this.ensureBaseline(document);
const baseline = this.baselines.get(this.uriKey(document))!;
const name = path.basename(document.uri.path) || "untitled";
const unsaved = this.isPersistable(document) ? "" : " (unsaved)";
const title = `${name} — my changes since ${this.epochLabel(baseline)}${unsaved}`;
await vscode.commands.executeCommand(
"vscode.diff",
this.baselineUri(document),
document.uri,
title,
{ preview: false },
);
}
/** The open baseline-diff tab for this document, if any. */
private findDiffTab(modified: vscode.Uri): vscode.Tab | undefined {
for (const group of vscode.window.tabGroups.all) {
for (const tab of group.tabs) {
const input = tab.input;
if (
input instanceof vscode.TabInputTextDiff &&
input.original.scheme === BASELINE_SCHEME &&
input.modified.toString() === modified.toString()
) {
return tab;
}
}
}
return undefined;
}
/** Human-readable epoch for the diff tab title (§5 / §6.5). */
private epochLabel(baseline: Baseline): string {
const time = new Date(baseline.capturedAt).toLocaleTimeString();
switch (baseline.reason) {
case "opened":
return `opened ${time}`;
case "machine-landing":
return `Claude landed ${time}`;
case "pinned":
return `pinned ${time}`;
}
}
private pinCommand(editor: vscode.TextEditor | undefined): void { private pinCommand(editor: vscode.TextEditor | undefined): void {
if (!editor || !this.isDiffable(editor.document)) { if (!editor || !this.isDiffable(editor.document)) {
void vscode.window.showWarningMessage("Cowriting: focus a text editor to pin its diff baseline."); void vscode.window.showWarningMessage("Cowriting: focus a text editor to pin its review baseline.");
return; return;
} }
this.pin(editor.document); this.pin(editor.document);
@@ -219,10 +134,6 @@ export class DiffViewController implements vscode.Disposable {
const b = this.baselines.get(uriString); const b = this.baselines.get(uriString);
return b ? { text: b.text, reason: b.reason, capturedAt: b.capturedAt } : undefined; return b ? { text: b.text, reason: b.reason, capturedAt: b.capturedAt } : undefined;
} }
/** Is this doc's baseline diff currently open in any tab group? */
isDiffOpen(uriString: string): boolean {
return this.findDiffTab(vscode.Uri.parse(uriString)) !== undefined;
}
/** Absolute on-disk path of this doc's persisted baseline, or undefined (untitled/in-memory). */ /** Absolute on-disk path of this doc's persisted baseline, or undefined (untitled/in-memory). */
baselineFilePath(uriString: string): string | undefined { baselineFilePath(uriString: string): string | undefined {
if (!this.store || vscode.Uri.parse(uriString).scheme !== "file") return undefined; if (!this.store || vscode.Uri.parse(uriString).scheme !== "file") return undefined;
+8 -7
View File
@@ -50,13 +50,14 @@ export function activate(context: vscode.ExtensionContext): CowritingApi | undef
}), }),
); );
// --- F6: diff-view toggle (Features #17 + #19) — workspace-INDEPENDENT --- // --- F6: baseline data layer (Features #17 + #19) — workspace-INDEPENDENT ---
// F6 works on ANY diffable doc (file or untitled), so it is constructed // The two-pane vscode.diff VIEW was removed in #34 (F10's rendered preview is
// regardless of whether a folder is open, and its commands are always live // the single review surface); only the baseline store survives, consumed by
// (never stubbed). Baseline lives in VS Code's per-extension GLOBAL storage // F7/F10. It tracks a baseline for ANY diffable doc (file or untitled), so it
// (always present), never the repo (INV-19). The machine-landing advance is // is constructed regardless of whether a folder is open. Baseline lives in VS
// wired in the with-root branch below (landings only occur on workspace files // Code's per-extension GLOBAL storage (always present), never the repo
// through the seam). The controller self-wires baseline capture on open. // (INV-19). The machine-landing advance is wired below. The controller
// self-wires baseline capture on open.
const baselineStorageDir = context.globalStorageUri?.fsPath; const baselineStorageDir = context.globalStorageUri?.fsPath;
const baselineStore = baselineStorageDir ? new BaselineStore(baselineStorageDir) : null; const baselineStore = baselineStorageDir ? new BaselineStore(baselineStorageDir) : null;
const diffViewController = new DiffViewController(baselineStore); const diffViewController = new DiffViewController(baselineStore);
+17 -15
View File
@@ -40,8 +40,11 @@ suite("no-workspace authoring (F8 — real folder-less, #8 lineage)", () => {
"cowriting.toggleAttribution", "cowriting.toggleAttribution",
"cowriting.acceptProposal", "cowriting.acceptProposal",
"cowriting.rejectProposal", "cowriting.rejectProposal",
// #34: the F6 two-pane diff VIEW was removed (F10 preview is the single
// review surface); its toggle command is gone (the baseline store stays).
"cowriting.toggleDiffView",
]) { ]) {
assert.ok(!all.includes(retired), `${retired} is retired (F10 preview-only)`); assert.ok(!all.includes(retired), `${retired} is retired`);
} }
}); });
@@ -73,25 +76,24 @@ suite("no-workspace authoring (F8 — real folder-less, #8 lineage)", () => {
assert.strictEqual(api.sidecarRouter.sidecarPath(key), undefined, "untitled artifact is in-memory only (no disk)"); assert.strictEqual(api.sidecarRouter.sidecarPath(key), undefined, "untitled artifact is in-memory only (no disk)");
}); });
// F6 (#19) is workspace-INDEPENDENT: its commands are real (not stubs) even // F6 (#19) baseline data layer is workspace-INDEPENDENT: it captures a baseline
// with no folder open, and the toggle works on an untitled buffer. // for an untitled buffer even with no folder open (the two-pane VIEW was
test("F6 toggle works with no folder open (untitled buffer)", async () => { // removed in #34; only the data layer remains). pinDiffBaseline stays real.
test("F6 baseline data layer works with no folder open (untitled buffer)", async () => {
const all = await vscode.commands.getCommands(true); const all = await vscode.commands.getCommands(true);
assert.ok(all.includes("cowriting.toggleDiffView"), "toggleDiffView registered");
assert.ok(all.includes("cowriting.pinDiffBaseline"), "pinDiffBaseline registered"); assert.ok(all.includes("cowriting.pinDiffBaseline"), "pinDiffBaseline registered");
const ext = vscode.extensions.getExtension("benstull.vscode-cowriting-plugin")!;
const api = (await ext.activate()) as CowritingApi;
const untitled = await vscode.workspace.openTextDocument({ content: "no-folder scratch\n", language: "markdown" }); const untitled = await vscode.workspace.openTextDocument({ content: "no-folder scratch\n", language: "markdown" });
await vscode.window.showTextDocument(untitled); await vscode.window.showTextDocument(untitled);
await new Promise((r) => setTimeout(r, 300)); await new Promise((r) => setTimeout(r, 300));
await vscode.commands.executeCommand("cowriting.toggleDiffView"); const key = untitled.uri.toString();
const baseline = api.diffViewController.getBaseline(key);
assert.ok(baseline, "baseline captured for the untitled buffer with no folder");
assert.strictEqual(baseline!.reason, "opened");
// pin resets the baseline to now — works folder-less.
await vscode.commands.executeCommand("cowriting.pinDiffBaseline");
await new Promise((r) => setTimeout(r, 300)); await new Promise((r) => setTimeout(r, 300));
const opened = vscode.window.tabGroups.all.some((g) => assert.strictEqual(api.diffViewController.getBaseline(key)!.reason, "pinned", "pin works with no folder");
g.tabs.some(
(t) =>
t.input instanceof vscode.TabInputTextDiff &&
t.input.original.scheme === "cowriting-baseline" &&
t.input.modified.toString() === untitled.uri.toString(),
),
);
assert.ok(opened, "a cowriting-baseline diff opened for the untitled buffer with no folder");
}); });
}); });
+13 -51
View File
@@ -23,10 +23,13 @@ async function getApi(): Promise<CowritingApi> {
} }
const settle = () => new Promise((r) => setTimeout(r, 300)); const settle = () => new Promise((r) => setTimeout(r, 300));
// Order-dependent (F2F4 pattern): later tests consume earlier state. Owns // The F6 two-pane vscode.diff VIEW was removed in #34 (F10's rendered preview is
// docs/diffview.md exclusively. F6 works on ANY file (#19), so the last two // the single review surface); only the baseline DATA layer survives, consumed by
// tests use an out-of-workspace file and an untitled buffer. // F7/F10. This suite covers that data layer. Order-dependent (F2F4 pattern):
suite("F6 diff-view toggle (host E2E — any file, programmatic seam ingress, no LLM)", () => { // later tests consume earlier state. Owns docs/diffview.md exclusively. The
// baseline works on ANY file (#19), so the last two tests use an out-of-workspace
// file and an untitled buffer.
suite("F6 baseline data layer (host E2E — any file, programmatic seam ingress, no LLM)", () => {
const TARGET = "A target sentence Claude will rewrite via the seam."; const TARGET = "A target sentence Claude will rewrite via the seam.";
const REPLACEMENT = "A SENTENCE CLAUDE REWROTE via the seam."; const REPLACEMENT = "A SENTENCE CLAUDE REWROTE via the seam.";
@@ -40,21 +43,6 @@ suite("F6 diff-view toggle (host E2E — any file, programmatic seam ingress, no
assert.strictEqual(baseline!.text, doc.getText(), "baseline = open-time buffer"); assert.strictEqual(baseline!.text, doc.getText(), "baseline = open-time buffer");
}); });
test("toggle opens a diff tab (original scheme cowriting-baseline) over the live doc (PUC-1)", async () => {
const api = await getApi();
assert.strictEqual(api.diffViewController.isDiffOpen(docUri()), false, "no diff open yet");
await vscode.commands.executeCommand("cowriting.toggleDiffView");
await settle();
assert.strictEqual(api.diffViewController.isDiffOpen(docUri()), true, "diff tab open");
const active = vscode.window.tabGroups.activeTabGroup.activeTab;
assert.ok(active && active.input instanceof vscode.TabInputTextDiff, "active tab is a diff");
assert.strictEqual(
(active!.input as vscode.TabInputTextDiff).original.scheme,
"cowriting-baseline",
"left side served by the baseline provider",
);
});
test("typing leaves the baseline unchanged while the buffer diverges", async () => { test("typing leaves the baseline unchanged while the buffer diverges", async () => {
const doc = await openDoc(); const doc = await openDoc();
const api = await getApi(); const api = await getApi();
@@ -105,17 +93,17 @@ suite("F6 diff-view toggle (host E2E — any file, programmatic seam ingress, no
); );
}); });
test("pin resets the baseline to now: baseline == buffer, reason pinned (PUC-3)", async () => { test("pin resets the baseline to now: baseline == buffer, reason pinned", async () => {
const doc = await openDoc(); const doc = await openDoc();
const api = await getApi(); const api = await getApi();
await vscode.commands.executeCommand("cowriting.pinDiffBaseline"); await vscode.commands.executeCommand("cowriting.pinDiffBaseline");
await settle(); await settle();
const baseline = api.diffViewController.getBaseline(docUri())!; const baseline = api.diffViewController.getBaseline(docUri())!;
assert.strictEqual(baseline.reason, "pinned"); assert.strictEqual(baseline.reason, "pinned");
assert.strictEqual(baseline.text, doc.getText(), "pinned baseline == current buffer (diff empties)"); assert.strictEqual(baseline.text, doc.getText(), "pinned baseline == current buffer (change-marks empty)");
}); });
test("the baseline is persisted in GLOBAL storage, never the repo (PUC-4, INV-19)", async () => { test("the baseline is persisted in GLOBAL storage, never the repo (INV-19)", async () => {
await openDoc(); await openDoc();
const api = await getApi(); const api = await getApi();
const p = api.diffViewController.baselineFilePath(docUri()); const p = api.diffViewController.baselineFilePath(docUri());
@@ -131,25 +119,7 @@ suite("F6 diff-view toggle (host E2E — any file, programmatic seam ingress, no
assert.ok(p!.includes(`${path.sep}baselines${path.sep}`), "baseline lives under <globalStorage>/baselines/"); assert.ok(p!.includes(`${path.sep}baselines${path.sep}`), "baseline lives under <globalStorage>/baselines/");
}); });
test("toggle again closes the diff tab and reveals the normal editor (PUC-1)", async () => { test("a baseline is captured + persisted for a file OUTSIDE the workspace folder (#19)", async () => {
const api = await getApi();
if (!api.diffViewController.isDiffOpen(docUri())) {
await openDoc();
await vscode.commands.executeCommand("cowriting.toggleDiffView");
await settle();
}
assert.strictEqual(api.diffViewController.isDiffOpen(docUri()), true, "diff open before close");
await vscode.commands.executeCommand("cowriting.toggleDiffView");
await settle();
assert.strictEqual(api.diffViewController.isDiffOpen(docUri()), false, "diff tab closed");
assert.strictEqual(
vscode.window.activeTextEditor?.document.uri.toString(),
docUri(),
"the normal editor for the doc is active after closing the diff",
);
});
test("toggle works on a file OUTSIDE the workspace folder, persisted in global storage (#19)", async () => {
const api = await getApi(); const api = await getApi();
const outsideDir = fs.mkdtempSync(path.join(os.tmpdir(), "cowriting-outside-")); const outsideDir = fs.mkdtempSync(path.join(os.tmpdir(), "cowriting-outside-"));
const outsidePath = path.join(outsideDir, "outside.md"); const outsidePath = path.join(outsideDir, "outside.md");
@@ -162,19 +132,14 @@ suite("F6 diff-view toggle (host E2E — any file, programmatic seam ingress, no
const baseline = api.diffViewController.getBaseline(outsideUri.toString()); const baseline = api.diffViewController.getBaseline(outsideUri.toString());
assert.ok(baseline, "baseline captured for an out-of-folder file"); assert.ok(baseline, "baseline captured for an out-of-folder file");
assert.strictEqual(baseline!.reason, "opened"); assert.strictEqual(baseline!.reason, "opened");
await vscode.commands.executeCommand("cowriting.toggleDiffView");
await settle();
assert.strictEqual(api.diffViewController.isDiffOpen(outsideUri.toString()), true, "diff opens for the outside file");
const fp = api.diffViewController.baselineFilePath(outsideUri.toString()); const fp = api.diffViewController.baselineFilePath(outsideUri.toString());
assert.ok(fp && fs.existsSync(fp), "outside-file baseline persisted in global storage"); assert.ok(fp && fs.existsSync(fp), "outside-file baseline persisted in global storage");
assert.ok(!fp!.startsWith(WS + path.sep), "not under the workspace folder"); assert.ok(!fp!.startsWith(WS + path.sep), "not under the workspace folder");
// close it so it doesn't bleed into the untitled test's active-tab checks
await vscode.commands.executeCommand("cowriting.toggleDiffView");
await settle();
fs.rmSync(outsideDir, { recursive: true, force: true }); fs.rmSync(outsideDir, { recursive: true, force: true });
void doc;
}); });
test("toggle works on an UNTITLED buffer, baseline in-memory only (#19)", async () => { test("an UNTITLED buffer gets an in-memory baseline, never persisted to disk (#19)", async () => {
const api = await getApi(); const api = await getApi();
const untitled = await vscode.workspace.openTextDocument({ content: "scratch line\n", language: "markdown" }); const untitled = await vscode.workspace.openTextDocument({ content: "scratch line\n", language: "markdown" });
await vscode.window.showTextDocument(untitled); await vscode.window.showTextDocument(untitled);
@@ -184,8 +149,5 @@ suite("F6 diff-view toggle (host E2E — any file, programmatic seam ingress, no
const baseline = api.diffViewController.getBaseline(key); const baseline = api.diffViewController.getBaseline(key);
assert.ok(baseline, "untitled buffer got an in-memory baseline"); assert.ok(baseline, "untitled buffer got an in-memory baseline");
assert.strictEqual(api.diffViewController.baselineFilePath(key), undefined, "untitled is NOT persisted to disk"); assert.strictEqual(api.diffViewController.baselineFilePath(key), undefined, "untitled is NOT persisted to disk");
await vscode.commands.executeCommand("cowriting.toggleDiffView");
await settle();
assert.strictEqual(api.diffViewController.isDiffOpen(key), true, "diff opens for the untitled buffer");
}); });
}); });
+8 -5
View File
@@ -215,16 +215,19 @@ suite("F10 interactive review (host E2E — preview is the single review surface
api.attributionController.getSpans("docs/f10clean.md").some((s) => s.authorKind === "agent"), api.attributionController.getSpans("docs/f10clean.md").some((s) => s.authorKind === "agent"),
"agent span recorded (attribution data layer intact)", "agent span recorded (attribution data layer intact)",
); );
// the retired toggle is gone from the palette (no editor decorations — INV-32). // the retired in-editor surfaces are gone from the palette (no editor decorations — INV-32).
const all = await vscode.commands.getCommands(true); const all = await vscode.commands.getCommands(true);
assert.ok(!all.includes("cowriting.toggleAttribution"), "cowriting.toggleAttribution is retired"); assert.ok(!all.includes("cowriting.toggleAttribution"), "cowriting.toggleAttribution is retired");
// the F6 diff toggle's keybinding is hidden (when:false) — it is not a user surface. // #34: the F6 two-pane diff VIEW was removed (F10 preview is the single review
// surface) — its toggle command + ctrl+alt+d keybinding are gone entirely.
assert.ok(!all.includes("cowriting.toggleDiffView"), "cowriting.toggleDiffView command is gone (#34)");
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../../package.json"), "utf8")); const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../../package.json"), "utf8"));
const dKb = (pkg.contributes.keybindings as Array<{ command: string; key: string; when?: string }>).find( const dKb = (pkg.contributes.keybindings as Array<{ command: string; key: string; when?: string }>).find(
(k) => k.command === "cowriting.toggleDiffView" && k.key === "ctrl+alt+d", (k) => k.command === "cowriting.toggleDiffView",
); );
assert.ok(dKb, "the ctrl+alt+d toggleDiffView keybinding is declared"); assert.ok(!dKb, "the toggleDiffView keybinding is gone from package.json (#34)");
assert.strictEqual(dKb!.when, "false", "…but hidden (when:false) — F6 is a data layer, not a user surface"); // …but the F6 baseline data layer survives: pinDiffBaseline stays a real command.
assert.ok(all.includes("cowriting.pinDiffBaseline"), "pinDiffBaseline (baseline data layer) is kept");
void key; void key;
}); });
}); });