import { CheckpointRef, CommandId, CorrelationId, EventId, MessageId, ProviderSessionId, ProviderThreadId, ProjectId, ThreadId, TurnId, } from "@t3tools/contracts"; import { NodeServices } from "@effect/platform-node"; import { assert, it } from "@effect/vitest"; import { Effect, Layer } from "effect"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import * as SqlClient from "effect/unstable/sql/SqlClient"; import { OrchestrationCommandReceiptRepositoryLive } from "../../persistence/Layers/OrchestrationCommandReceipts.ts"; import { OrchestrationEventStoreLive } from "../../persistence/Layers/OrchestrationEventStore.ts"; import { makeSqlitePersistenceLive, SqlitePersistenceMemory, } from "../../persistence/Layers/Sqlite.ts"; import { OrchestrationEventStore } from "../../persistence/Services/OrchestrationEventStore.ts"; import { OrchestrationEngineLive } from "./OrchestrationEngine.ts"; import { ORCHESTRATION_PROJECTOR_NAMES, OrchestrationProjectionPipelineLive, } from "./ProjectionPipeline.ts"; import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; import { OrchestrationProjectionPipeline } from "../Services/ProjectionPipeline.ts"; const projectionLayer = it.layer( OrchestrationProjectionPipelineLive.pipe( Layer.provideMerge(OrchestrationEventStoreLive), Layer.provideMerge(SqlitePersistenceMemory), ), ); projectionLayer("OrchestrationProjectionPipeline", (it) => { it.effect("bootstraps all projection states and writes projection rows", () => Effect.gen(function* () { const projectionPipeline = yield* OrchestrationProjectionPipeline; const eventStore = yield* OrchestrationEventStore; const sql = yield* SqlClient.SqlClient; const now = new Date().toISOString(); yield* eventStore.append({ type: "project.created", eventId: EventId.makeUnsafe("evt-1"), aggregateKind: "project", aggregateId: ProjectId.makeUnsafe("project-1"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-1"), causationEventId: null, correlationId: CommandId.makeUnsafe("cmd-1"), metadata: {}, payload: { projectId: ProjectId.makeUnsafe("project-1"), title: "Project 1", workspaceRoot: "/tmp/project-1", defaultModel: null, scripts: [], createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.created", eventId: EventId.makeUnsafe("evt-2"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-1"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-2"), causationEventId: null, correlationId: CommandId.makeUnsafe("cmd-2"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-1"), projectId: ProjectId.makeUnsafe("project-1"), title: "Thread 1", model: "gpt-5-codex", branch: null, worktreePath: null, createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-3"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-1"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-3"), causationEventId: null, correlationId: CommandId.makeUnsafe("cmd-3"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-1"), messageId: MessageId.makeUnsafe("message-1"), role: "assistant", text: "hello", turnId: null, streaming: false, createdAt: now, updatedAt: now, }, }); yield* projectionPipeline.bootstrap; const projectRows = yield* sql<{ readonly projectId: string; readonly title: string; readonly scriptsJson: string; }>` SELECT project_id AS "projectId", title, scripts_json AS "scriptsJson" FROM projection_projects `; assert.deepEqual(projectRows, [ { projectId: "project-1", title: "Project 1", scriptsJson: "[]" }, ]); const messageRows = yield* sql<{ readonly messageId: string; readonly text: string; }>` SELECT message_id AS "messageId", text FROM projection_thread_messages `; assert.deepEqual(messageRows, [{ messageId: "message-1", text: "hello" }]); const stateRows = yield* sql<{ readonly projector: string; readonly lastAppliedSequence: number; }>` SELECT projector, last_applied_sequence AS "lastAppliedSequence" FROM projection_state ORDER BY projector ASC `; assert.equal(stateRows.length, Object.keys(ORCHESTRATION_PROJECTOR_NAMES).length); for (const row of stateRows) { assert.equal(row.lastAppliedSequence, 3); } }), ); it.effect("resumes from projector last_applied_sequence without replaying older events", () => Effect.gen(function* () { const projectionPipeline = yield* OrchestrationProjectionPipeline; const eventStore = yield* OrchestrationEventStore; const sql = yield* SqlClient.SqlClient; const now = new Date().toISOString(); yield* eventStore.append({ type: "project.created", eventId: EventId.makeUnsafe("evt-a1"), aggregateKind: "project", aggregateId: ProjectId.makeUnsafe("project-a"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-a1"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-a1"), metadata: {}, payload: { projectId: ProjectId.makeUnsafe("project-a"), title: "Project A", workspaceRoot: "/tmp/project-a", defaultModel: null, scripts: [], createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.created", eventId: EventId.makeUnsafe("evt-a2"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-a"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-a2"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-a2"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-a"), projectId: ProjectId.makeUnsafe("project-a"), title: "Thread A", model: "gpt-5-codex", branch: null, worktreePath: null, createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-a3"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-a"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-a3"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-a3"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-a"), messageId: MessageId.makeUnsafe("message-a"), role: "assistant", text: "hello", turnId: null, streaming: false, createdAt: now, updatedAt: now, }, }); yield* projectionPipeline.bootstrap; yield* eventStore.append({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-a4"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-a"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-a4"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-a4"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-a"), messageId: MessageId.makeUnsafe("message-a"), role: "assistant", text: " world", turnId: null, streaming: true, createdAt: now, updatedAt: now, }, }); yield* projectionPipeline.bootstrap; yield* projectionPipeline.bootstrap; const messageRows = yield* sql<{ readonly text: string }>` SELECT text FROM projection_thread_messages WHERE message_id = 'message-a' `; assert.deepEqual(messageRows, [{ text: "hello world" }]); const stateRows = yield* sql<{ readonly projector: string; readonly lastAppliedSequence: number; }>` SELECT projector, last_applied_sequence AS "lastAppliedSequence" FROM projection_state `; const maxSequenceRows = yield* sql<{ readonly maxSequence: number }>` SELECT MAX(sequence) AS "maxSequence" FROM orchestration_events `; const maxSequence = maxSequenceRows[0]?.maxSequence ?? 0; for (const row of stateRows) { assert.equal(row.lastAppliedSequence, maxSequence); } }), ); it.effect("keeps accumulated assistant text when completion payload text is empty", () => Effect.gen(function* () { const projectionPipeline = yield* OrchestrationProjectionPipeline; const eventStore = yield* OrchestrationEventStore; const sql = yield* SqlClient.SqlClient; const now = new Date().toISOString(); yield* eventStore.append({ type: "project.created", eventId: EventId.makeUnsafe("evt-empty-1"), aggregateKind: "project", aggregateId: ProjectId.makeUnsafe("project-empty"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-empty-1"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-empty-1"), metadata: {}, payload: { projectId: ProjectId.makeUnsafe("project-empty"), title: "Project Empty", workspaceRoot: "/tmp/project-empty", defaultModel: null, scripts: [], createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.created", eventId: EventId.makeUnsafe("evt-empty-2"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-empty"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-empty-2"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-empty-2"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-empty"), projectId: ProjectId.makeUnsafe("project-empty"), title: "Thread Empty", model: "gpt-5-codex", branch: null, worktreePath: null, createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-empty-3"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-empty"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-empty-3"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-empty-3"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-empty"), messageId: MessageId.makeUnsafe("assistant-empty"), role: "assistant", text: "Hello", turnId: null, streaming: true, createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-empty-4"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-empty"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-empty-4"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-empty-4"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-empty"), messageId: MessageId.makeUnsafe("assistant-empty"), role: "assistant", text: " world", turnId: null, streaming: true, createdAt: now, updatedAt: now, }, }); yield* eventStore.append({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-empty-5"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-empty"), occurredAt: now, commandId: CommandId.makeUnsafe("cmd-empty-5"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-empty-5"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-empty"), messageId: MessageId.makeUnsafe("assistant-empty"), role: "assistant", text: "", turnId: null, streaming: false, createdAt: now, updatedAt: now, }, }); yield* projectionPipeline.bootstrap; const messageRows = yield* sql<{ readonly text: string; readonly isStreaming: unknown }>` SELECT text, is_streaming AS "isStreaming" FROM projection_thread_messages WHERE message_id = 'assistant-empty' `; assert.equal(messageRows.length, 1); assert.equal(messageRows[0]?.text, "Hello world"); assert.isFalse(Boolean(messageRows[0]?.isStreaming)); }), ); it.effect("resolves turn-count conflicts when checkpoint completion rewrites provisional turns", () => Effect.gen(function* () { const projectionPipeline = yield* OrchestrationProjectionPipeline; const eventStore = yield* OrchestrationEventStore; const sql = yield* SqlClient.SqlClient; const appendAndProject = (event: Parameters[0]) => eventStore .append(event) .pipe(Effect.flatMap((savedEvent) => projectionPipeline.projectEvent(savedEvent))); yield* appendAndProject({ type: "project.created", eventId: EventId.makeUnsafe("evt-conflict-1"), aggregateKind: "project", aggregateId: ProjectId.makeUnsafe("project-conflict"), occurredAt: "2026-02-26T13:00:00.000Z", commandId: CommandId.makeUnsafe("cmd-conflict-1"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"), metadata: {}, payload: { projectId: ProjectId.makeUnsafe("project-conflict"), title: "Project Conflict", workspaceRoot: "/tmp/project-conflict", defaultModel: null, scripts: [], createdAt: "2026-02-26T13:00:00.000Z", updatedAt: "2026-02-26T13:00:00.000Z", }, }); yield* appendAndProject({ type: "thread.created", eventId: EventId.makeUnsafe("evt-conflict-2"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-conflict"), occurredAt: "2026-02-26T13:00:01.000Z", commandId: CommandId.makeUnsafe("cmd-conflict-2"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-conflict"), projectId: ProjectId.makeUnsafe("project-conflict"), title: "Thread Conflict", model: "gpt-5-codex", branch: null, worktreePath: null, createdAt: "2026-02-26T13:00:01.000Z", updatedAt: "2026-02-26T13:00:01.000Z", }, }); yield* appendAndProject({ type: "thread.turn-interrupt-requested", eventId: EventId.makeUnsafe("evt-conflict-3"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-conflict"), occurredAt: "2026-02-26T13:00:02.000Z", commandId: CommandId.makeUnsafe("cmd-conflict-3"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-conflict"), turnId: TurnId.makeUnsafe("turn-interrupted"), createdAt: "2026-02-26T13:00:02.000Z", }, }); yield* appendAndProject({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-conflict-4"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-conflict"), occurredAt: "2026-02-26T13:00:03.000Z", commandId: CommandId.makeUnsafe("cmd-conflict-4"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-conflict"), messageId: MessageId.makeUnsafe("assistant-conflict"), role: "assistant", text: "done", turnId: TurnId.makeUnsafe("turn-completed"), streaming: false, createdAt: "2026-02-26T13:00:03.000Z", updatedAt: "2026-02-26T13:00:03.000Z", }, }); yield* appendAndProject({ type: "thread.turn-diff-completed", eventId: EventId.makeUnsafe("evt-conflict-5"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-conflict"), occurredAt: "2026-02-26T13:00:04.000Z", commandId: CommandId.makeUnsafe("cmd-conflict-5"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-conflict"), turnId: TurnId.makeUnsafe("turn-completed"), checkpointTurnCount: 1, checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"), status: "ready", files: [], assistantMessageId: MessageId.makeUnsafe("assistant-conflict"), completedAt: "2026-02-26T13:00:04.000Z", }, }); const turnRows = yield* sql<{ readonly turnId: string; readonly checkpointTurnCount: number | null; readonly status: string; }>` SELECT turn_id AS "turnId", checkpoint_turn_count AS "checkpointTurnCount", state AS "status" FROM projection_turns WHERE thread_id = 'thread-conflict' ORDER BY CASE WHEN checkpoint_turn_count IS NULL THEN 1 ELSE 0 END ASC, checkpoint_turn_count ASC, requested_at ASC `; assert.deepEqual(turnRows, [ { turnId: "turn-completed", checkpointTurnCount: 1, status: "completed" }, { turnId: "turn-interrupted", checkpointTurnCount: null, status: "interrupted" }, ]); }), ); it.effect("does not fallback-retain messages whose turnId is removed by revert", () => Effect.gen(function* () { const projectionPipeline = yield* OrchestrationProjectionPipeline; const eventStore = yield* OrchestrationEventStore; const sql = yield* SqlClient.SqlClient; const appendAndProject = (event: Parameters[0]) => eventStore .append(event) .pipe(Effect.flatMap((savedEvent) => projectionPipeline.projectEvent(savedEvent))); yield* appendAndProject({ type: "project.created", eventId: EventId.makeUnsafe("evt-revert-1"), aggregateKind: "project", aggregateId: ProjectId.makeUnsafe("project-revert"), occurredAt: "2026-02-26T12:00:00.000Z", commandId: CommandId.makeUnsafe("cmd-revert-1"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-1"), metadata: {}, payload: { projectId: ProjectId.makeUnsafe("project-revert"), title: "Project Revert", workspaceRoot: "/tmp/project-revert", defaultModel: null, scripts: [], createdAt: "2026-02-26T12:00:00.000Z", updatedAt: "2026-02-26T12:00:00.000Z", }, }); yield* appendAndProject({ type: "thread.created", eventId: EventId.makeUnsafe("evt-revert-2"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:01.000Z", commandId: CommandId.makeUnsafe("cmd-revert-2"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-2"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), projectId: ProjectId.makeUnsafe("project-revert"), title: "Thread Revert", model: "gpt-5-codex", branch: null, worktreePath: null, createdAt: "2026-02-26T12:00:01.000Z", updatedAt: "2026-02-26T12:00:01.000Z", }, }); yield* appendAndProject({ type: "thread.turn-diff-completed", eventId: EventId.makeUnsafe("evt-revert-3"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:02.000Z", commandId: CommandId.makeUnsafe("cmd-revert-3"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-3"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), turnId: TurnId.makeUnsafe("turn-1"), checkpointTurnCount: 1, checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert/turn/1"), status: "ready", files: [], assistantMessageId: MessageId.makeUnsafe("assistant-keep"), completedAt: "2026-02-26T12:00:02.000Z", }, }); yield* appendAndProject({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-revert-4"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:02.100Z", commandId: CommandId.makeUnsafe("cmd-revert-4"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-4"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), messageId: MessageId.makeUnsafe("assistant-keep"), role: "assistant", text: "kept", turnId: TurnId.makeUnsafe("turn-1"), streaming: false, createdAt: "2026-02-26T12:00:02.100Z", updatedAt: "2026-02-26T12:00:02.100Z", }, }); yield* appendAndProject({ type: "thread.turn-diff-completed", eventId: EventId.makeUnsafe("evt-revert-5"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:03.000Z", commandId: CommandId.makeUnsafe("cmd-revert-5"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-5"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), turnId: TurnId.makeUnsafe("turn-2"), checkpointTurnCount: 2, checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert/turn/2"), status: "ready", files: [], assistantMessageId: MessageId.makeUnsafe("assistant-remove"), completedAt: "2026-02-26T12:00:03.000Z", }, }); yield* appendAndProject({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-revert-6"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:03.050Z", commandId: CommandId.makeUnsafe("cmd-revert-6"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-6"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), messageId: MessageId.makeUnsafe("user-remove"), role: "user", text: "removed", turnId: TurnId.makeUnsafe("turn-2"), streaming: false, createdAt: "2026-02-26T12:00:03.050Z", updatedAt: "2026-02-26T12:00:03.050Z", }, }); yield* appendAndProject({ type: "thread.message-sent", eventId: EventId.makeUnsafe("evt-revert-7"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:03.100Z", commandId: CommandId.makeUnsafe("cmd-revert-7"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-7"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), messageId: MessageId.makeUnsafe("assistant-remove"), role: "assistant", text: "removed", turnId: TurnId.makeUnsafe("turn-2"), streaming: false, createdAt: "2026-02-26T12:00:03.100Z", updatedAt: "2026-02-26T12:00:03.100Z", }, }); yield* appendAndProject({ type: "thread.reverted", eventId: EventId.makeUnsafe("evt-revert-8"), aggregateKind: "thread", aggregateId: ThreadId.makeUnsafe("thread-revert"), occurredAt: "2026-02-26T12:00:04.000Z", commandId: CommandId.makeUnsafe("cmd-revert-8"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-revert-8"), metadata: {}, payload: { threadId: ThreadId.makeUnsafe("thread-revert"), turnCount: 1, }, }); const messageRows = yield* sql<{ readonly messageId: string; readonly turnId: string | null; readonly role: string; }>` SELECT message_id AS "messageId", turn_id AS "turnId", role FROM projection_thread_messages WHERE thread_id = 'thread-revert' ORDER BY created_at ASC, message_id ASC `; assert.deepEqual(messageRows, [ { messageId: "assistant-keep", turnId: "turn-1", role: "assistant", }, ]); }), ); }); it.effect("restores pending turn-start metadata across projection pipeline restart", () => Effect.gen(function* () { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-projection-pipeline-restart-")); const dbPath = path.join(tempDir, "orchestration.sqlite"); const persistenceLayer = makeSqlitePersistenceLive(dbPath); const firstProjectionLayer = OrchestrationProjectionPipelineLive.pipe( Layer.provideMerge(OrchestrationEventStoreLive), Layer.provideMerge(persistenceLayer), ); const secondProjectionLayer = OrchestrationProjectionPipelineLive.pipe( Layer.provideMerge(OrchestrationEventStoreLive), Layer.provideMerge(persistenceLayer), ); const threadId = ThreadId.makeUnsafe("thread-restart"); const turnId = TurnId.makeUnsafe("turn-restart"); const messageId = MessageId.makeUnsafe("message-restart"); const turnStartedAt = "2026-02-26T14:00:00.000Z"; const sessionSetAt = "2026-02-26T14:00:05.000Z"; yield* Effect.gen(function* () { const eventStore = yield* OrchestrationEventStore; const projectionPipeline = yield* OrchestrationProjectionPipeline; yield* eventStore.append({ type: "thread.turn-start-requested", eventId: EventId.makeUnsafe("evt-restart-1"), aggregateKind: "thread", aggregateId: threadId, occurredAt: turnStartedAt, commandId: CommandId.makeUnsafe("cmd-restart-1"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-restart-1"), metadata: {}, payload: { threadId, messageId, createdAt: turnStartedAt, }, }); yield* projectionPipeline.bootstrap; }).pipe(Effect.provide(firstProjectionLayer)); const turnRows = yield* Effect.gen(function* () { const eventStore = yield* OrchestrationEventStore; const projectionPipeline = yield* OrchestrationProjectionPipeline; const sql = yield* SqlClient.SqlClient; yield* eventStore.append({ type: "thread.session-set", eventId: EventId.makeUnsafe("evt-restart-2"), aggregateKind: "thread", aggregateId: threadId, occurredAt: sessionSetAt, commandId: CommandId.makeUnsafe("cmd-restart-2"), causationEventId: null, correlationId: CorrelationId.makeUnsafe("cmd-restart-2"), metadata: { providerSessionId: ProviderSessionId.makeUnsafe("provider-session-restart"), providerThreadId: ProviderThreadId.makeUnsafe("provider-thread-restart"), }, payload: { threadId, session: { threadId, status: "running", providerName: "codex", providerSessionId: ProviderSessionId.makeUnsafe("provider-session-restart"), providerThreadId: ProviderThreadId.makeUnsafe("provider-thread-restart"), activeTurnId: turnId, lastError: null, updatedAt: sessionSetAt, }, }, }); yield* projectionPipeline.bootstrap; const pendingRows = yield* sql<{ readonly threadId: string }>` SELECT thread_id AS "threadId" FROM projection_turns WHERE thread_id = ${threadId} AND turn_id IS NULL AND state = 'pending' `; assert.deepEqual(pendingRows, []); return yield* sql<{ readonly turnId: string; readonly userMessageId: string | null; readonly startedAt: string; }>` SELECT turn_id AS "turnId", pending_message_id AS "userMessageId", started_at AS "startedAt" FROM projection_turns WHERE turn_id = ${turnId} `; }).pipe(Effect.provide(secondProjectionLayer)); assert.deepEqual(turnRows, [ { turnId: "turn-restart", userMessageId: "message-restart", startedAt: turnStartedAt, }, ]); fs.rmSync(tempDir, { recursive: true, force: true }); }).pipe(Effect.provide(NodeServices.layer)), ); const engineLayer = it.layer( OrchestrationEngineLive.pipe( Layer.provide(OrchestrationProjectionPipelineLive), Layer.provide(OrchestrationEventStoreLive), Layer.provide(OrchestrationCommandReceiptRepositoryLive), Layer.provideMerge(SqlitePersistenceMemory), ), ); engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => { it.effect("projects dispatched engine events immediately", () => Effect.gen(function* () { const engine = yield* OrchestrationEngineService; const sql = yield* SqlClient.SqlClient; const createdAt = new Date().toISOString(); yield* engine.dispatch({ type: "project.create", commandId: CommandId.makeUnsafe("cmd-live-project"), projectId: ProjectId.makeUnsafe("project-live"), title: "Live Project", workspaceRoot: "/tmp/project-live", defaultModel: "gpt-5-codex", createdAt, }); const projectRows = yield* sql<{ readonly title: string; readonly scriptsJson: string }>` SELECT title, scripts_json AS "scriptsJson" FROM projection_projects WHERE project_id = 'project-live' `; assert.deepEqual(projectRows, [{ title: "Live Project", scriptsJson: "[]" }]); const projectorRows = yield* sql<{ readonly lastAppliedSequence: number }>` SELECT last_applied_sequence AS "lastAppliedSequence" FROM projection_state WHERE projector = 'projection.projects' `; assert.deepEqual(projectorRows, [{ lastAppliedSequence: 1 }]); }), ); it.effect("projects persist updated scripts from project.meta.update", () => Effect.gen(function* () { const engine = yield* OrchestrationEngineService; const sql = yield* SqlClient.SqlClient; const createdAt = new Date().toISOString(); yield* engine.dispatch({ type: "project.create", commandId: CommandId.makeUnsafe("cmd-scripts-project-create"), projectId: ProjectId.makeUnsafe("project-scripts"), title: "Scripts Project", workspaceRoot: "/tmp/project-scripts", defaultModel: "gpt-5-codex", createdAt, }); yield* engine.dispatch({ type: "project.meta.update", commandId: CommandId.makeUnsafe("cmd-scripts-project-update"), projectId: ProjectId.makeUnsafe("project-scripts"), scripts: [ { id: "script-1", name: "Build", command: "bun run build", icon: "build", runOnWorktreeCreate: false, }, ], defaultModel: "gpt-5", }); const projectRows = yield* sql<{ readonly scriptsJson: string; readonly defaultModel: string; }>` SELECT scripts_json AS "scriptsJson", default_model AS "defaultModel" FROM projection_projects WHERE project_id = 'project-scripts' `; assert.deepEqual(projectRows, [ { scriptsJson: '[{"id":"script-1","name":"Build","command":"bun run build","icon":"build","runOnWorktreeCreate":false}]', defaultModel: "gpt-5", }, ]); }), ); });