import * as assert from "assert"; import * as vscode from "vscode"; import { activateApi, settleUntil } from "./helpers"; // Task 6 (D19/D10/D8, PUC-8): the comments-first ask + comment→reply→offer→ // proposal loop, with a stubbed reply turn (no real @cline/sdk call). Runs on // an untitled buffer (F8 routes it to the global sidecar) so this suite has no // workspace-folder dependency. suite("comment → reply → offer → proposal (PUC-8, D10/D19)", () => { test("reply on a coedited doc summons a machine reply + offer; accept lands pending proposals", async () => { const api = await activateApi(); const doc = await vscode.workspace.openTextDocument({ language: "markdown", content: "# T\n\nThe quick brown fox jumps over the lazy dog paragraph.\n", }); const ed = await vscode.window.showTextDocument(doc); await vscode.commands.executeCommand("cowriting.coeditDocument"); api.threadController.setTurnRunnerForTest(async () => ({ replacement: "I would tighten this sentence.", model: "stub", sessionId: "s1", })); api.editFlow.setEditTurnForTest(async () => ({ replacement: "The quick fox jumps the lazy dog.", model: "stub", sessionId: "s1", })); ed.selection = new vscode.Selection(2, 0, 2, 20); const threadId = (await api.threadController.createThreadOnSelection("tighten this"))!; // reply-loop fires on the human message; wait for the machine message to persist await settleUntil(() => { const t = api.sidecarRouter.load(api.proposalController.keyFor(doc))?.threads.find((x) => x.id === threadId); return (t?.messages.length ?? 0) >= 2 && t!.messages[1].author.kind === "agent"; }, 10000); const ids = await api.threadController.makeThreadEdit(threadId, api.proposalController.keyFor(doc)); assert.ok(ids.length >= 1); assert.ok(api.proposalController.listProposals(doc).length >= 1); // pending, INV-5 }); test("a comment on a NON-coedited doc summons nothing (INV-10)", async () => { const api = await activateApi(); const doc = await vscode.workspace.openTextDocument({ language: "markdown", content: "plain\n" }); await vscode.window.showTextDocument(doc); const id = await api.threadController.createThreadOnSelection("hello"); assert.strictEqual(id, undefined); // gate refuses thread creation entirely }); });