import * as assert from "assert"; import * as fs from "fs"; import * as path from "path"; import * as vscode from "vscode"; import type { CowritingApi } from "../../../src/extension"; const WS = process.env.E2E_WORKSPACE!; const settle = () => new Promise((r) => setTimeout(r, 300)); async function getApi(): Promise { const ext = vscode.extensions.getExtension("benstull.vscode-cowriting-plugin")!; const api = (await ext.activate()) as CowritingApi; assert.ok(api?.trackChangesPreviewController && api?.proposalController, "exports preview + proposal"); return api; } // F10 host E2E (no LLM): the rewrite of the obsolete F9 authorship-mode test. // F9's "authorship" mode / renderAuthorship is gone — the on-state renderReview // now author-colors Claude's landed prose. This suite confirms a Claude-landed // span renders as a cw-by-claude span in the on-state preview HTML. Owns its own // markdown doc, disjoint from the other suites' fixtures. suite("F10 review preview — Claude-authored prose is cw-by-claude in the on-state (host E2E, no LLM)", () => { const DOC_REL = "docs/f10claude.md"; const TARGET = "The sentence Claude will compose over."; const REPLACEMENT = "The sentence CLAUDE COMPOSED via the seam."; test("an accepted Claude edit author-colors as cw-by-claude in the on-state render; mode defaults to on", async () => { const abs = path.join(WS, DOC_REL); fs.mkdirSync(path.dirname(abs), { recursive: true }); fs.writeFileSync(abs, `# F10\n\n${TARGET}\n`, "utf8"); const uri = vscode.Uri.file(abs); const doc = await vscode.workspace.openTextDocument(uri); await vscode.window.showTextDocument(doc); await settle(); const api = await getApi(); const key = uri.toString(); // open the preview — annotations default ON (F10/INV-33) await vscode.commands.executeCommand("cowriting.showTrackChangesPreview"); await settle(); assert.ok(api.trackChangesPreviewController.isOpen(key), "preview open"); assert.strictEqual(api.trackChangesPreviewController.getMode(key), "on", "annotations default to on"); // Claude composes via the seam (propose → accept) const start = doc.getText().indexOf(TARGET); const id = await vscode.commands.executeCommand("cowriting.proposeAgentEdit", { uri: key, start, end: start + TARGET.length, newText: REPLACEMENT, model: "sonnet", sessionId: "e2e-f10", turnId: "turn-f10", }); assert.ok(await api.proposalController.acceptById(DOC_REL, id!), "accept applies via the seam"); await settle(); // attribution recorded a Claude (agent) span (data layer intact) const claudeSpan = api.attributionController.getSpans(DOC_REL).find((s) => s.authorKind === "agent"); assert.ok(claudeSpan, "Claude span recorded by F3"); const spans = api.attributionController.spansFor(doc); assert.ok(spans.some((s) => s.author === "claude"), "spansFor reports a Claude span for the preview"); // the on-state render author-colors the landed Claude text as cw-by-claude const html = api.trackChangesPreviewController.renderHtmlFor(key); assert.match(html, //, "landed Claude prose is author-colored in the on-state render"); }); });