From 807feaecf2b6c6e2a52f5c18dc868b05d7883054 Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 29 Sep 2026 12:18:56 -0500 Subject: [PATCH] test(runner): prove Pi editor canonical draft roundtrip Co-Authored-By: Paperclip --- .../src/drivers/acpx/pi-acp-runtime.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/paperclip-runner/src/drivers/acpx/pi-acp-runtime.test.ts b/packages/paperclip-runner/src/drivers/acpx/pi-acp-runtime.test.ts index 41ad10a0885..56945707e05 100644 --- a/packages/paperclip-runner/src/drivers/acpx/pi-acp-runtime.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/pi-acp-runtime.test.ts @@ -94,6 +94,23 @@ describe("Pi ACP bridge", () => { expect(f.process.sendExtensionUiResponse).toHaveBeenCalledExactlyOnceWith({ id: "canonical", value: "\nAccepted text\n" }); }); + it.each(["", " Draft\n界 🌒\n\\n literal "])("delivers editor prefill %j through canonical initialText and returns only the exact edited answer", async prefill => { + const f = fixture(); + const edited = " Revised\n界 🌒\n\\n stays literal "; + f.connection.unstable_createElicitation.mockImplementation(async request => { + const normalized = normalizeAcpFormElicitation(request)!; + const question = normalized.questionSet.questions[0]!; + expect(question).toMatchObject({ answerMode: "text", initialText: prefill, required: true }); + // Initial content is an editable draft, never an implicit answer. + expect(f.process.sendExtensionUiResponse).not.toHaveBeenCalled(); + expect(() => normalized.accept({ schema: "paperclip.question_response.v1", answers: {} })).toThrow(); + expect(() => normalized.accept({ schema: "paperclip.question_response.v1", answers: { [question.id]: { text: "" } } })).toThrow("is required"); + return normalized.accept({ schema: "paperclip.question_response.v1", answers: { [question.id]: { text: edited } } }); + }); + await f.bridge.handle({ id: "canonical-prefill", method: "editor", title: "Draft", prefill }); + expect(f.process.sendExtensionUiResponse).toHaveBeenCalledExactlyOnceWith({ id: "canonical-prefill", value: edited }); + }); + it.each(["a".repeat(1000), "界".repeat(1000), "🌒".repeat(500)])("passes the canonical character limit through the real form normalizer", async (label) => { const f = fixture(); f.connection.unstable_createElicitation.mockImplementation(async request => {