1import { assert } from "@effect/vitest";
2import type { ProviderReplayTranscript } from "@t3tools/contracts";
3
4import type { OrchestratorV2ScenarioResult } from "../../OrchestratorScenario.ts";
5import {
6 assertBaseProjection,
7 assertSemanticProjectionIntegrity,
8 assertUserMessagesInclude,
9 projectionFor,
10} from "../shared.ts";
11import { CLAUDE_IDLE_RESUME_PROMPT_1, CLAUDE_IDLE_RESUME_PROMPT_2 } from "./input.ts";
12
13export function assertClaudeIdleResumeOutput(
14 result: OrchestratorV2ScenarioResult,
15 transcript: ProviderReplayTranscript,
16) {
17 // The transcript itself enforces the regression: query.open:2 expects a
18 // `resume`-style open. A create-style reopen (the bug) fails the replay at
19 // the boundary before these assertions run. Both runs must complete — the
20 // pre-fix behavior burned the first post-idle message as a failed run.
21 assertBaseProjection({
22 result,
23 transcript,
24 runCount: 2,
25 runStatuses: ["completed", "completed"],
26 });
27
28 const projection = projectionFor(result, transcript.scenario);
29 assertSemanticProjectionIntegrity(projection);
30 assertUserMessagesInclude(projection, [CLAUDE_IDLE_RESUME_PROMPT_1, CLAUDE_IDLE_RESUME_PROMPT_2]);
31
32 const assistantTexts = projection.turnItems.flatMap((item) =>
33 item.type === "assistant_message" ? [item.text] : [],
34 );
35 assert.deepEqual(assistantTexts, [
36 "idle resume first turn complete",
37 "idle resume second turn complete",
38 ]);
39}