// @effect-diagnostics nodeBuiltinImport:offimport * as NodeFS from "node:fs";import * as NodePath from "node:path"; import { ApprovalRequestId, CommandId, defaultInstanceIdForDriver, DEFAULT_PROVIDER_INTERACTION_MODE, DEFAULT_MODEL, DEFAULT_MODEL_BY_PROVIDER, EventId, MessageId, ProjectId, ProviderDriverKind, ThreadId, ModelSelection, ProviderInstanceId,} from "@t3tools/contracts";import { assert, it } from "@effect/vitest";import * as Clock from "effect/Clock";import * as Effect from "effect/Effect";import * as Option from "effect/Option";import * as Schema from "effect/Schema"; import type { TestTurnResponse } from "./TestProviderAdapter.integration.ts";import { gitRefExists, gitShowFileAtRef, makeOrchestrationIntegrationHarness, type OrchestrationIntegrationHarness,} from "./OrchestrationEngineHarness.integration.ts";import { checkpointRefForThreadTurn } from "../src/checkpointing/Utils.ts";import type { CheckpointDiffFinalizedReceipt, TurnProcessingQuiescedReceipt,} from "../src/orchestration/Services/RuntimeReceiptBus.ts";import * as NodeServices from "@effect/platform-node/NodeServices"; const asMessageId = (value: string): MessageId => MessageId.make(value);const asProjectId = (value: string): ProjectId => ProjectId.make(value);const asEventId = (value: string): EventId => EventId.make(value);const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value); const PROJECT_ID = asProjectId("project-1");const THREAD_ID = ThreadId.make("thread-1");const FIXTURE_TURN_ID = "fixture-turn";const APPROVAL_REQUEST_ID = asApprovalRequestId("req-approval-1");type IntegrationProvider = ProviderDriverKind;const CODEX_PROVIDER = ProviderDriverKind.make("codex");const CLAUDE_AGENT_PROVIDER = ProviderDriverKind.make("claudeAgent"); function nowIso() { return "2026-05-01T00:00:00.000Z";} class IntegrationWaitTimeoutError extends Schema.TaggedErrorClass<IntegrationWaitTimeoutError>()( "IntegrationWaitTimeoutError", { description: Schema.String, },) {} function waitForSync<A>( read: () => A, predicate: (value: A) => boolean, description: string, timeoutMs = 10_000,): Effect.Effect<A, never> { return Effect.gen(function* () { const deadline = (yield* Clock.currentTimeMillis) + timeoutMs; while (true) { const value = read(); if (predicate(value)) { return value; } if ((yield* Clock.currentTimeMillis) >= deadline) { return yield* Effect.die(new IntegrationWaitTimeoutError({ description })); } yield* Effect.sleep(10); } });} function runtimeBase( eventId: string, createdAt: string, provider: IntegrationProvider = CODEX_PROVIDER,) { return { eventId: asEventId(eventId), provider, createdAt, };} function withHarness<A, E>( use: (harness: OrchestrationIntegrationHarness) => Effect.Effect<A, E>, provider: IntegrationProvider = CODEX_PROVIDER,) { return Effect.acquireUseRelease( makeOrchestrationIntegrationHarness({ provider }), use, (harness) => harness.dispose, ).pipe(Effect.provide(NodeServices.layer));} function withRealCodexHarness<A, E>( use: (harness: OrchestrationIntegrationHarness) => Effect.Effect<A, E>,) { return Effect.acquireUseRelease( makeOrchestrationIntegrationHarness({ provider: CODEX_PROVIDER, realCodex: true }), use, (harness) => harness.dispose, ).pipe(Effect.provide(NodeServices.layer));} const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) => Effect.gen(function* () { const createdAt = nowIso(); const provider = harness.adapterHarness?.provider ?? CODEX_PROVIDER; const defaultModel = DEFAULT_MODEL_BY_PROVIDER[provider] ?? DEFAULT_MODEL; const instanceId = defaultInstanceIdForDriver(provider); yield* harness.engine.dispatch({ type: "project.create", commandId: CommandId.make("cmd-project-create"), projectId: PROJECT_ID, title: "Integration Project", workspaceRoot: harness.workspaceDir, defaultModelSelection: { instanceId, model: defaultModel, }, createdAt, }); yield* harness.engine.dispatch({ type: "thread.create", commandId: CommandId.make("cmd-thread-create"), threadId: THREAD_ID, projectId: PROJECT_ID, title: "Integration Thread", modelSelection: { instanceId, model: defaultModel, }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", branch: null, worktreePath: harness.workspaceDir, createdAt, }); }); const startTurn = (input: { readonly harness: OrchestrationIntegrationHarness; readonly commandId: string; readonly messageId: string; readonly text: string; readonly modelSelection?: ModelSelection; readonly createdAt?: string;}) => input.harness.engine.dispatch({ type: "thread.turn.start", commandId: CommandId.make(input.commandId), threadId: THREAD_ID, message: { messageId: asMessageId(input.messageId), role: "user", text: input.text, attachments: [], }, ...(input.modelSelection !== undefined ? { modelSelection: input.modelSelection, } : {}), interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: input.createdAt ?? nowIso(), }); it.live("runs a single turn end-to-end and persists checkpoint state in sqlite + git", () => withHarness((harness) => Effect.gen(function* () { yield* seedProjectAndThread(harness); const turnResponse: TestTurnResponse = { events: [ { type: "turn.started", ...runtimeBase("evt-single-1", "2026-02-24T10:00:00.000Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", ...runtimeBase("evt-single-2", "2026-02-24T10:00:00.100Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Single turn response.\n", }, { type: "turn.completed", ...runtimeBase("evt-single-3", "2026-02-24T10:00:00.200Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", }, ], }; yield* harness.adapterHarness!.queueTurnResponseForNextSession(turnResponse); yield* startTurn({ harness, commandId: "cmd-turn-start-single", messageId: "msg-user-single", text: "Say hello", }); const finalizedReceipt = yield* harness.waitForReceipt( (receipt): receipt is CheckpointDiffFinalizedReceipt => receipt.type === "checkpoint.diff.finalized" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 1, ); if (finalizedReceipt.type !== "checkpoint.diff.finalized") { throw new Error("Expected checkpoint.diff.finalized receipt."); } assert.equal(finalizedReceipt.status, "ready"); yield* harness.waitForReceipt( (receipt): receipt is TurnProcessingQuiescedReceipt => receipt.type === "turn.processing.quiesced" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 1, ); const thread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.session?.status === "ready" && entry.messages.some( (message) => message.role === "assistant" && message.streaming === false, ) && entry.checkpoints.length === 1, ); assert.equal(thread.checkpoints[0]?.status, "ready"); assert.equal(thread.checkpoints[0]?.checkpointTurnCount, 1); const checkpointRows = yield* harness.checkpointRepository.listByThreadId({ threadId: THREAD_ID, }); assert.equal(checkpointRows.length, 1); assert.equal(checkpointRows[0]?.checkpointTurnCount, 1); assert.equal(checkpointRows[0]?.status, "ready"); assert.deepEqual(checkpointRows[0]?.files, []); const ref0 = checkpointRefForThreadTurn(THREAD_ID, 0); const ref1 = checkpointRefForThreadTurn(THREAD_ID, 1); assert.equal(gitRefExists(harness.workspaceDir, ref0), true); assert.equal(gitRefExists(harness.workspaceDir, ref1), true); assert.equal(gitShowFileAtRef(harness.workspaceDir, ref0, "README.md"), "v1\n"); assert.equal(gitShowFileAtRef(harness.workspaceDir, ref1, "README.md"), "v1\n"); }), ),); it.live.skipIf(!process.env.CODEX_BINARY_PATH)( "keeps the same Codex provider thread across runtime mode switches", () => withRealCodexHarness((harness) => Effect.gen(function* () { const createdAt = nowIso(); yield* harness.engine.dispatch({ type: "project.create", commandId: CommandId.make("cmd-project-create-real-codex"), projectId: PROJECT_ID, title: "Integration Project", workspaceRoot: harness.workspaceDir, defaultModelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.3-codex", }, createdAt, }); yield* harness.engine.dispatch({ type: "thread.create", commandId: CommandId.make("cmd-thread-create-real-codex"), threadId: THREAD_ID, projectId: PROJECT_ID, title: "Integration Thread", modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.3-codex", }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "full-access", branch: null, worktreePath: harness.workspaceDir, createdAt, }); yield* harness.engine.dispatch({ type: "thread.turn.start", commandId: CommandId.make("cmd-turn-start-real-codex-1"), threadId: THREAD_ID, message: { messageId: asMessageId("msg-real-codex-1"), role: "user", text: "Reply with exactly ALPHA.", attachments: [], }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "full-access", createdAt: nowIso(), }); const firstThread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.session?.status === "ready" && entry.session.providerName === "codex" && entry.messages.some( (message) => message.role === "assistant" && message.streaming === false, ), 180_000, ); assert.equal(firstThread.session?.threadId, "thread-1"); yield* harness.engine.dispatch({ type: "thread.turn.start", commandId: CommandId.make("cmd-turn-start-real-codex-2"), threadId: THREAD_ID, message: { messageId: asMessageId("msg-real-codex-2"), role: "user", text: "Reply with exactly BETA.", attachments: [], }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: nowIso(), }); const secondThread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.session?.status === "ready" && entry.session.providerName === "codex" && entry.session.runtimeMode === "approval-required" && entry.messages.some( (message) => message.role === "assistant" && message.text.includes("BETA"), ), 180_000, ); assert.equal(secondThread.session?.threadId, "thread-1"); }), ),); it.live("runs multi-turn file edits and persists checkpoint diffs", () => withHarness((harness) => Effect.gen(function* () { yield* seedProjectAndThread(harness); yield* harness.adapterHarness!.queueTurnResponseForNextSession({ events: [ { type: "turn.started", ...runtimeBase("evt-multi-1", "2026-02-24T10:01:00.000Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "tool.started", ...runtimeBase("evt-multi-2", "2026-02-24T10:01:00.100Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, toolKind: "command", title: "Edit file", detail: "README.md", }, { type: "tool.completed", ...runtimeBase("evt-multi-3", "2026-02-24T10:01:00.200Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, toolKind: "command", title: "Edit file", detail: "README.md", }, { type: "message.delta", ...runtimeBase("evt-multi-4", "2026-02-24T10:01:00.300Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Updated README to v2.\n", }, { type: "turn.completed", ...runtimeBase("evt-multi-5", "2026-02-24T10:01:00.400Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", }, ], mutateWorkspace: ({ cwd }) => Effect.sync(() => { NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v2\n", "utf8"); }), }); yield* startTurn({ harness, commandId: "cmd-turn-start-multi-1", messageId: "msg-user-multi-1", text: "Make first edit", }); yield* harness.waitForReceipt( (receipt): receipt is CheckpointDiffFinalizedReceipt => receipt.type === "checkpoint.diff.finalized" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 1, ); yield* harness.waitForThread( THREAD_ID, (entry) => entry.checkpoints.length === 1 && entry.session?.threadId === "thread-1", ); yield* harness.adapterHarness!.queueTurnResponse(THREAD_ID, { events: [ { type: "turn.started", ...runtimeBase("evt-multi-6", "2026-02-24T10:02:00.000Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", ...runtimeBase("evt-multi-7", "2026-02-24T10:02:00.100Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Updated README to v3.\n", }, { type: "turn.completed", ...runtimeBase("evt-multi-8", "2026-02-24T10:02:00.200Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", }, ], mutateWorkspace: ({ cwd }) => Effect.sync(() => { NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v3\n", "utf8"); }), }); yield* startTurn({ harness, commandId: "cmd-turn-start-multi-2", messageId: "msg-user-multi-2", text: "Make second edit", }); const secondReceipt = yield* harness.waitForReceipt( (receipt): receipt is CheckpointDiffFinalizedReceipt => receipt.type === "checkpoint.diff.finalized" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 2, ); if (secondReceipt.type !== "checkpoint.diff.finalized") { throw new Error("Expected checkpoint.diff.finalized receipt."); } assert.equal(secondReceipt.status, "ready"); yield* harness.waitForReceipt( (receipt): receipt is TurnProcessingQuiescedReceipt => receipt.type === "turn.processing.quiesced" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 2, ); const secondTurnThread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.latestTurn?.turnId === "turn-2" && entry.checkpoints.length === 2 && entry.checkpoints.some((checkpoint) => checkpoint.checkpointTurnCount === 2), ); const secondCheckpoint = secondTurnThread.checkpoints.find( (checkpoint) => checkpoint.checkpointTurnCount === 2, ); assert.equal( secondCheckpoint?.files.some((file) => file.path === "README.md"), true, ); Lines 1–500 of 1441. Load more
// @effect-diagnostics nodeBuiltinImport:off import * as NodeFS from "node:fs"; import * as NodePath from "node:path"; import { ApprovalRequestId, CommandId, defaultInstanceIdForDriver, DEFAULT_PROVIDER_INTERACTION_MODE, DEFAULT_MODEL, DEFAULT_MODEL_BY_PROVIDER, EventId, MessageId, ProjectId, ProviderDriverKind, ThreadId, ModelSelection, ProviderInstanceId, } from "@t3tools/contracts"; import { assert, it } from "@effect/vitest"; import * as Clock from "effect/Clock"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import type { TestTurnResponse } from "./TestProviderAdapter.integration.ts"; import { gitRefExists, gitShowFileAtRef, makeOrchestrationIntegrationHarness, type OrchestrationIntegrationHarness, } from "./OrchestrationEngineHarness.integration.ts"; import { checkpointRefForThreadTurn } from "../src/checkpointing/Utils.ts"; import type { CheckpointDiffFinalizedReceipt, TurnProcessingQuiescedReceipt, } from "../src/orchestration/Services/RuntimeReceiptBus.ts"; import * as NodeServices from "@effect/platform-node/NodeServices"; const asMessageId = (value: string): MessageId => MessageId.make(value); const asProjectId = (value: string): ProjectId => ProjectId.make(value); const asEventId = (value: string): EventId => EventId.make(value); const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value); const PROJECT_ID = asProjectId("project-1"); const THREAD_ID = ThreadId.make("thread-1"); const FIXTURE_TURN_ID = "fixture-turn"; const APPROVAL_REQUEST_ID = asApprovalRequestId("req-approval-1"); type IntegrationProvider = ProviderDriverKind; const CODEX_PROVIDER = ProviderDriverKind.make("codex"); const CLAUDE_AGENT_PROVIDER = ProviderDriverKind.make("claudeAgent"); function nowIso() { return "2026-05-01T00:00:00.000Z"; } class IntegrationWaitTimeoutError extends Schema.TaggedErrorClass<IntegrationWaitTimeoutError>()( "IntegrationWaitTimeoutError", { description: Schema.String, }, ) {} function waitForSync<A>( read: () => A, predicate: (value: A) => boolean, description: string, timeoutMs = 10_000, ): Effect.Effect<A, never> { return Effect.gen(function* () { const deadline = (yield* Clock.currentTimeMillis) + timeoutMs; while (true) { const value = read(); if (predicate(value)) { return value; } if ((yield* Clock.currentTimeMillis) >= deadline) { return yield* Effect.die(new IntegrationWaitTimeoutError({ description })); } yield* Effect.sleep(10); } }); } function runtimeBase( eventId: string, createdAt: string, provider: IntegrationProvider = CODEX_PROVIDER, ) { return { eventId: asEventId(eventId), provider, createdAt, }; } function withHarness<A, E>( use: (harness: OrchestrationIntegrationHarness) => Effect.Effect<A, E>, provider: IntegrationProvider = CODEX_PROVIDER, ) { return Effect.acquireUseRelease( makeOrchestrationIntegrationHarness({ provider }), use, (harness) => harness.dispose, ).pipe(Effect.provide(NodeServices.layer)); } function withRealCodexHarness<A, E>( use: (harness: OrchestrationIntegrationHarness) => Effect.Effect<A, E>, ) { return Effect.acquireUseRelease( makeOrchestrationIntegrationHarness({ provider: CODEX_PROVIDER, realCodex: true }), use, (harness) => harness.dispose, ).pipe(Effect.provide(NodeServices.layer)); } const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) => Effect.gen(function* () { const createdAt = nowIso(); const provider = harness.adapterHarness?.provider ?? CODEX_PROVIDER; const defaultModel = DEFAULT_MODEL_BY_PROVIDER[provider] ?? DEFAULT_MODEL; const instanceId = defaultInstanceIdForDriver(provider); yield* harness.engine.dispatch({ type: "project.create", commandId: CommandId.make("cmd-project-create"), projectId: PROJECT_ID, title: "Integration Project", workspaceRoot: harness.workspaceDir, defaultModelSelection: { instanceId, model: defaultModel, }, createdAt, }); yield* harness.engine.dispatch({ type: "thread.create", commandId: CommandId.make("cmd-thread-create"), threadId: THREAD_ID, projectId: PROJECT_ID, title: "Integration Thread", modelSelection: { instanceId, model: defaultModel, }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", branch: null, worktreePath: harness.workspaceDir, createdAt, }); }); const startTurn = (input: { readonly harness: OrchestrationIntegrationHarness; readonly commandId: string; readonly messageId: string; readonly text: string; readonly modelSelection?: ModelSelection; readonly createdAt?: string; }) => input.harness.engine.dispatch({ type: "thread.turn.start", commandId: CommandId.make(input.commandId), threadId: THREAD_ID, message: { messageId: asMessageId(input.messageId), role: "user", text: input.text, attachments: [], }, ...(input.modelSelection !== undefined ? { modelSelection: input.modelSelection, } : {}), interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: input.createdAt ?? nowIso(), }); it.live("runs a single turn end-to-end and persists checkpoint state in sqlite + git", () => withHarness((harness) => Effect.gen(function* () { yield* seedProjectAndThread(harness); const turnResponse: TestTurnResponse = { events: [ { type: "turn.started", ...runtimeBase("evt-single-1", "2026-02-24T10:00:00.000Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", ...runtimeBase("evt-single-2", "2026-02-24T10:00:00.100Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Single turn response.\n", }, { type: "turn.completed", ...runtimeBase("evt-single-3", "2026-02-24T10:00:00.200Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", }, ], }; yield* harness.adapterHarness!.queueTurnResponseForNextSession(turnResponse); yield* startTurn({ harness, commandId: "cmd-turn-start-single", messageId: "msg-user-single", text: "Say hello", }); const finalizedReceipt = yield* harness.waitForReceipt( (receipt): receipt is CheckpointDiffFinalizedReceipt => receipt.type === "checkpoint.diff.finalized" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 1, ); if (finalizedReceipt.type !== "checkpoint.diff.finalized") { throw new Error("Expected checkpoint.diff.finalized receipt."); } assert.equal(finalizedReceipt.status, "ready"); yield* harness.waitForReceipt( (receipt): receipt is TurnProcessingQuiescedReceipt => receipt.type === "turn.processing.quiesced" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 1, ); const thread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.session?.status === "ready" && entry.messages.some( (message) => message.role === "assistant" && message.streaming === false, ) && entry.checkpoints.length === 1, ); assert.equal(thread.checkpoints[0]?.status, "ready"); assert.equal(thread.checkpoints[0]?.checkpointTurnCount, 1); const checkpointRows = yield* harness.checkpointRepository.listByThreadId({ threadId: THREAD_ID, }); assert.equal(checkpointRows.length, 1); assert.equal(checkpointRows[0]?.checkpointTurnCount, 1); assert.equal(checkpointRows[0]?.status, "ready"); assert.deepEqual(checkpointRows[0]?.files, []); const ref0 = checkpointRefForThreadTurn(THREAD_ID, 0); const ref1 = checkpointRefForThreadTurn(THREAD_ID, 1); assert.equal(gitRefExists(harness.workspaceDir, ref0), true); assert.equal(gitRefExists(harness.workspaceDir, ref1), true); assert.equal(gitShowFileAtRef(harness.workspaceDir, ref0, "README.md"), "v1\n"); assert.equal(gitShowFileAtRef(harness.workspaceDir, ref1, "README.md"), "v1\n"); }), ), ); it.live.skipIf(!process.env.CODEX_BINARY_PATH)( "keeps the same Codex provider thread across runtime mode switches", () => withRealCodexHarness((harness) => Effect.gen(function* () { const createdAt = nowIso(); yield* harness.engine.dispatch({ type: "project.create", commandId: CommandId.make("cmd-project-create-real-codex"), projectId: PROJECT_ID, title: "Integration Project", workspaceRoot: harness.workspaceDir, defaultModelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.3-codex", }, createdAt, }); yield* harness.engine.dispatch({ type: "thread.create", commandId: CommandId.make("cmd-thread-create-real-codex"), threadId: THREAD_ID, projectId: PROJECT_ID, title: "Integration Thread", modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.3-codex", }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "full-access", branch: null, worktreePath: harness.workspaceDir, createdAt, }); yield* harness.engine.dispatch({ type: "thread.turn.start", commandId: CommandId.make("cmd-turn-start-real-codex-1"), threadId: THREAD_ID, message: { messageId: asMessageId("msg-real-codex-1"), role: "user", text: "Reply with exactly ALPHA.", attachments: [], }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "full-access", createdAt: nowIso(), }); const firstThread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.session?.status === "ready" && entry.session.providerName === "codex" && entry.messages.some( (message) => message.role === "assistant" && message.streaming === false, ), 180_000, ); assert.equal(firstThread.session?.threadId, "thread-1"); yield* harness.engine.dispatch({ type: "thread.turn.start", commandId: CommandId.make("cmd-turn-start-real-codex-2"), threadId: THREAD_ID, message: { messageId: asMessageId("msg-real-codex-2"), role: "user", text: "Reply with exactly BETA.", attachments: [], }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: nowIso(), }); const secondThread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.session?.status === "ready" && entry.session.providerName === "codex" && entry.session.runtimeMode === "approval-required" && entry.messages.some( (message) => message.role === "assistant" && message.text.includes("BETA"), ), 180_000, ); assert.equal(secondThread.session?.threadId, "thread-1"); }), ), ); it.live("runs multi-turn file edits and persists checkpoint diffs", () => withHarness((harness) => Effect.gen(function* () { yield* seedProjectAndThread(harness); yield* harness.adapterHarness!.queueTurnResponseForNextSession({ events: [ { type: "turn.started", ...runtimeBase("evt-multi-1", "2026-02-24T10:01:00.000Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "tool.started", ...runtimeBase("evt-multi-2", "2026-02-24T10:01:00.100Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, toolKind: "command", title: "Edit file", detail: "README.md", }, { type: "tool.completed", ...runtimeBase("evt-multi-3", "2026-02-24T10:01:00.200Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, toolKind: "command", title: "Edit file", detail: "README.md", }, { type: "message.delta", ...runtimeBase("evt-multi-4", "2026-02-24T10:01:00.300Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Updated README to v2.\n", }, { type: "turn.completed", ...runtimeBase("evt-multi-5", "2026-02-24T10:01:00.400Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", }, ], mutateWorkspace: ({ cwd }) => Effect.sync(() => { NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v2\n", "utf8"); }), }); yield* startTurn({ harness, commandId: "cmd-turn-start-multi-1", messageId: "msg-user-multi-1", text: "Make first edit", }); yield* harness.waitForReceipt( (receipt): receipt is CheckpointDiffFinalizedReceipt => receipt.type === "checkpoint.diff.finalized" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 1, ); yield* harness.waitForThread( THREAD_ID, (entry) => entry.checkpoints.length === 1 && entry.session?.threadId === "thread-1", ); yield* harness.adapterHarness!.queueTurnResponse(THREAD_ID, { events: [ { type: "turn.started", ...runtimeBase("evt-multi-6", "2026-02-24T10:02:00.000Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", ...runtimeBase("evt-multi-7", "2026-02-24T10:02:00.100Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Updated README to v3.\n", }, { type: "turn.completed", ...runtimeBase("evt-multi-8", "2026-02-24T10:02:00.200Z"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", }, ], mutateWorkspace: ({ cwd }) => Effect.sync(() => { NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v3\n", "utf8"); }), }); yield* startTurn({ harness, commandId: "cmd-turn-start-multi-2", messageId: "msg-user-multi-2", text: "Make second edit", }); const secondReceipt = yield* harness.waitForReceipt( (receipt): receipt is CheckpointDiffFinalizedReceipt => receipt.type === "checkpoint.diff.finalized" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 2, ); if (secondReceipt.type !== "checkpoint.diff.finalized") { throw new Error("Expected checkpoint.diff.finalized receipt."); } assert.equal(secondReceipt.status, "ready"); yield* harness.waitForReceipt( (receipt): receipt is TurnProcessingQuiescedReceipt => receipt.type === "turn.processing.quiesced" && receipt.threadId === THREAD_ID && receipt.checkpointTurnCount === 2, ); const secondTurnThread = yield* harness.waitForThread( THREAD_ID, (entry) => entry.latestTurn?.turnId === "turn-2" && entry.checkpoints.length === 2 && entry.checkpoints.some((checkpoint) => checkpoint.checkpointTurnCount === 2), ); const secondCheckpoint = secondTurnThread.checkpoints.find( (checkpoint) => checkpoint.checkpointTurnCount === 2, ); assert.equal( secondCheckpoint?.files.some((file) => file.path === "README.md"), true, );