import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; const chat = readFileSync( new URL("../src/components/rectification-agentic-chat.tsx", import.meta.url), "utf8", ); const agentRun = readFileSync( new URL("../src/lib/rectification-agentic/v9/agent-run.ts", import.meta.url), "utf8", ); test("live and persisted assistant text stay verbatim after spoken-answer removal", () => { assert.match(chat, /const raw = failed \? "" : turn\.text \?\? ""/); assert.match(chat, /text: raw,/); assert.doesNotMatch(chat, /spoken-answer/); assert.doesNotMatch(chat, /splitRectificationSpokenAndThinking|settleRectificationSpokenAndThinking|finalizeRectificationSpokenAndThinking/); assert.match(agentRun, /answerText = visible;/); assert.doesNotMatch(agentRun, /splitRectificationSpokenAndThinking|settleRectificationSpokenAndThinking|finalizeRectificationSpokenAndThinking/); }); test("structured current_question, not model prose, owns the visible question slot", () => { assert.match(chat, /current_question\?: unknown/); assert.match(chat, /setCurrentQuestion\(nextQuestion\)/); assert.match(chat, /className="rectification-question-slot"/); assert.match(chat, /currentQuestion\?\.kind === "choice"/); assert.match(chat, /currentQuestion\?\.kind === "collect_spoken"/); assert.match(chat, / { assert.match(chat, /raw = event\.replace === true \? event\.text : raw \+ event\.text/); assert.match(chat, /text: raw,/); assert.doesNotMatch(chat, /splitRectificationSpokenAndThinking|settleRectificationSpokenAndThinking|finalizeRectificationSpokenAndThinking/); });