import { CommandId, DEFAULT_PROVIDER_INTERACTION_MODE, EventId, MessageId, ProjectId, ThreadId, ProviderInstanceId, type ProjectScript,} from "@t3tools/contracts";import { createModelSelection } from "@t3tools/shared/model";import { expect, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as NodeServices from "@effect/platform-node/NodeServices"; import { decideOrchestrationCommand } from "./decider.ts";import { createEmptyReadModel, projectEvent } from "./projector.ts"; const asEventId = (value: string): EventId => EventId.make(value);const asProjectId = (value: string): ProjectId => ProjectId.make(value);const asMessageId = (value: string): MessageId => MessageId.make(value);it.layer(NodeServices.layer)("decider project scripts", (it) => { it.effect("emits empty scripts on project.create", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const readModel = createEmptyReadModel(now); const result = yield* decideOrchestrationCommand({ command: { type: "project.create", commandId: CommandId.make("cmd-project-create-scripts"), projectId: asProjectId("project-scripts"), title: "Scripts", workspaceRoot: "/tmp/scripts", createdAt: now, }, readModel, }); const event = Array.isArray(result) ? result[0] : result; expect(event.type).toBe("project.created"); expect((event.payload as { scripts: unknown[] }).scripts).toEqual([]); }), ); it.effect("propagates scripts in project.meta.update payload", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const readModel = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create-scripts"), aggregateKind: "project", aggregateId: asProjectId("project-scripts"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-scripts"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-scripts"), metadata: {}, payload: { projectId: asProjectId("project-scripts"), title: "Scripts", workspaceRoot: "/tmp/scripts", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const scripts = [ { id: "lint", name: "Lint", command: "bun run lint", icon: "lint", runOnWorktreeCreate: false, }, ] as const; const result = yield* decideOrchestrationCommand({ command: { type: "project.meta.update", commandId: CommandId.make("cmd-project-update-scripts"), projectId: asProjectId("project-scripts"), scripts: Array.from(scripts), }, readModel, }); const event = Array.isArray(result) ? result[0] : result; expect(event.type).toBe("project.meta-updated"); expect((event.payload as { scripts?: unknown[] }).scripts).toEqual(scripts); }), ); const script = (id: string): ProjectScript => ({ id, name: "Install dependencies", command: "vp i", icon: "configure", runOnWorktreeCreate: false, }); const projectWithScripts = (scripts: ReadonlyArray<ProjectScript>) => { const now = "2026-01-01T00:00:00.000Z"; return projectEvent(createEmptyReadModel(now), { sequence: 1, eventId: asEventId("evt-legacy-scripts"), aggregateKind: "project", aggregateId: asProjectId("project-scripts"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-legacy-scripts"), causationEventId: null, correlationId: CommandId.make("cmd-legacy-scripts"), metadata: {}, payload: { projectId: asProjectId("project-scripts"), title: "Scripts", workspaceRoot: "/tmp/scripts", defaultModelSelection: null, scripts, createdAt: now, updatedAt: now, }, }); }; for (const id of ["install-javascript-dependencies", "A", "a.b", "a b", "-a", "a".repeat(25)]) { it.effect(`rejects a new script ID that cannot have a shortcut: ${id}`, () => Effect.gen(function* () { const readModel = yield* projectWithScripts([]); const failure = yield* Effect.flip( decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-invalid-script"), projectId: asProjectId("project-scripts"), scripts: [script("lint"), script(id)], }, }), ); expect(failure).toMatchObject({ _tag: "OrchestrationCommandInvariantError" }); expect(failure.message).toContain("Script ID"); expect(failure.message).toContain("24"); expect(readModel.projects[0]?.scripts).toEqual([]); }), ); } it.effect("accepts a script ID at the shortcut length limit", () => Effect.gen(function* () { const readModel = yield* projectWithScripts([]); const scripts = [script("a".repeat(24))]; const result = yield* decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-valid-script"), projectId: asProjectId("project-scripts"), scripts, }, }); const event = Array.isArray(result) ? result[0] : result; expect(event.payload).toMatchObject({ scripts }); }), ); it.effect( "keeps legacy scripts readable, editable and removable while allowing valid additions", () => Effect.gen(function* () { const legacy = script("install-javascript-dependencies"); const readModel = yield* projectWithScripts([legacy]); expect(readModel.projects[0]?.scripts).toEqual([legacy]); for (const scripts of [[{ ...legacy, command: "vp install" }, script("lint")], []]) { const result = yield* decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-repair-script"), projectId: asProjectId("project-scripts"), scripts, }, }); const event = Array.isArray(result) ? result[0] : result; expect(event.payload).toMatchObject({ scripts }); } const failure = yield* Effect.flip( decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-new-invalid-script"), projectId: asProjectId("project-scripts"), scripts: [legacy, script("another.invalid.id")], }, }), ); expect(failure).toMatchObject({ _tag: "OrchestrationCommandInvariantError" }); }), ); it.effect("propagates project icon metadata in project.meta.update", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const readModel = yield* projectEvent(createEmptyReadModel(now), { sequence: 1, eventId: asEventId("evt-project-create-favicon"), aggregateKind: "project", aggregateId: asProjectId("project-favicon"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-favicon"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-favicon"), metadata: {}, payload: { projectId: asProjectId("project-favicon"), title: "Favicon", workspaceRoot: "/tmp/favicon", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const result = yield* decideOrchestrationCommand({ command: { type: "project.meta.update", commandId: CommandId.make("cmd-project-update-favicon"), projectId: asProjectId("project-favicon"), faviconPath: "brand/icon.svg", projectIcon: { kind: "lucide", name: "alarm-clock", color: "violet" }, }, readModel, }); const event = Array.isArray(result) ? result[0] : result; expect(event.type).toBe("project.meta-updated"); expect((event.payload as { faviconPath?: string }).faviconPath).toBe("brand/icon.svg"); expect((event.payload as { projectIcon?: unknown }).projectIcon).toEqual({ kind: "lucide", name: "alarm-clock", color: "violet", }); }), ); it.effect("rejects project.create for an active workspace root that already exists", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const readModel = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create"), aggregateKind: "project", aggregateId: asProjectId("project-existing"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create"), causationEventId: null, correlationId: CommandId.make("cmd-project-create"), metadata: {}, payload: { projectId: asProjectId("project-existing"), title: "Project", workspaceRoot: "/tmp/project", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const failure = yield* Effect.flip( decideOrchestrationCommand({ command: { type: "project.create", commandId: CommandId.make("cmd-project-create-duplicate-root"), projectId: asProjectId("project-duplicate-root"), title: "Duplicate Project", workspaceRoot: "/tmp/project/", createdAt: now, }, readModel, }), ); expect(failure.message).toContain( "Active project 'project-existing' already exists for workspace root '/tmp/project'.", ); }), ); it.effect("rejects project.meta.update when moving onto another active workspace root", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const withFirstProject = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create-first"), aggregateKind: "project", aggregateId: asProjectId("project-first"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-first"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-first"), metadata: {}, payload: { projectId: asProjectId("project-first"), title: "First", workspaceRoot: "/tmp/project-first", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const readModel = yield* projectEvent(withFirstProject, { sequence: 2, eventId: asEventId("evt-project-create-second"), aggregateKind: "project", aggregateId: asProjectId("project-second"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-second"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-second"), metadata: {}, payload: { projectId: asProjectId("project-second"), title: "Second", workspaceRoot: "/tmp/project-second", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const failure = yield* Effect.flip( decideOrchestrationCommand({ command: { type: "project.meta.update", commandId: CommandId.make("cmd-project-update-duplicate-root"), projectId: asProjectId("project-second"), workspaceRoot: "/tmp/project-first", }, readModel, }), ); expect(failure.message).toContain( "Active project 'project-first' already exists for workspace root '/tmp/project-first'.", ); }), ); it.effect("emits user message and turn-start-requested events for thread.turn.start", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const withProject = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create"), aggregateKind: "project", aggregateId: asProjectId("project-1"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create"), causationEventId: null, correlationId: CommandId.make("cmd-project-create"), metadata: {}, payload: { projectId: asProjectId("project-1"), title: "Project", workspaceRoot: "/tmp/project", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const readModel = yield* projectEvent(withProject, { sequence: 2, eventId: asEventId("evt-thread-create"), aggregateKind: "thread", aggregateId: ThreadId.make("thread-1"), type: "thread.created", occurredAt: now, commandId: CommandId.make("cmd-thread-create"), causationEventId: null, correlationId: CommandId.make("cmd-thread-create"), metadata: {}, payload: { threadId: ThreadId.make("thread-1"), projectId: asProjectId("project-1"), title: "Thread", modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5-codex", }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", branch: null, worktreePath: null, createdAt: now, updatedAt: now, }, }); const result = yield* decideOrchestrationCommand({ command: { type: "thread.turn.start", commandId: CommandId.make("cmd-turn-start"), threadId: ThreadId.make("thread-1"), message: { messageId: asMessageId("message-user-1"), role: "user", text: "hello", attachments: [], }, modelSelection: createModelSelection(ProviderInstanceId.make("codex"), "gpt-5.3-codex", [ { id: "reasoningEffort", value: "high" }, { id: "fastMode", value: true }, ]), interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: now, }, readModel, }); expect(Array.isArray(result)).toBe(true); const events = Array.isArray(result) ? result : [result]; expect(events).toHaveLength(2); expect(events[0]?.type).toBe("thread.message-sent"); const turnStartEvent = events[1]; expect(turnStartEvent?.type).toBe("thread.turn-start-requested"); expect(turnStartEvent?.causationEventId).toBe(events[0]?.eventId ?? null); if (turnStartEvent?.type !== "thread.turn-start-requested") { return; } expect(turnStartEvent.payload).toMatchObject({ threadId: ThreadId.make("thread-1"), messageId: asMessageId("message-user-1"), modelSelection: createModelSelection(ProviderInstanceId.make("codex"), "gpt-5.3-codex", [ { id: "reasoningEffort", value: "high" }, { id: "fastMode", value: true }, ]), runtimeMode: "approval-required", }); }), ); it.effect("emits thread.runtime-mode-set from thread.runtime-mode.set", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const withProject = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create"), aggregateKind: "project", aggregateId: asProjectId("project-1"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create"), causationEventId: null, correlationId: CommandId.make("cmd-project-create"), metadata: {}, payload: { projectId: asProjectId("project-1"), title: "Project", workspaceRoot: "/tmp/project", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const readModel = yield* projectEvent(withProject, { sequence: 2, eventId: asEventId("evt-thread-create"), aggregateKind: "thread", aggregateId: ThreadId.make("thread-1"), type: "thread.created", occurredAt: now, commandId: CommandId.make("cmd-thread-create"), causationEventId: null, correlationId: CommandId.make("cmd-thread-create"), metadata: {}, payload: { threadId: ThreadId.make("thread-1"), projectId: asProjectId("project-1"),Lines 1–500 of 617. Load more
import { CommandId, DEFAULT_PROVIDER_INTERACTION_MODE, EventId, MessageId, ProjectId, ThreadId, ProviderInstanceId, type ProjectScript, } from "@t3tools/contracts"; import { createModelSelection } from "@t3tools/shared/model"; import { expect, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as NodeServices from "@effect/platform-node/NodeServices"; import { decideOrchestrationCommand } from "./decider.ts"; import { createEmptyReadModel, projectEvent } from "./projector.ts"; const asEventId = (value: string): EventId => EventId.make(value); const asProjectId = (value: string): ProjectId => ProjectId.make(value); const asMessageId = (value: string): MessageId => MessageId.make(value); it.layer(NodeServices.layer)("decider project scripts", (it) => { it.effect("emits empty scripts on project.create", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const readModel = createEmptyReadModel(now); const result = yield* decideOrchestrationCommand({ command: { type: "project.create", commandId: CommandId.make("cmd-project-create-scripts"), projectId: asProjectId("project-scripts"), title: "Scripts", workspaceRoot: "/tmp/scripts", createdAt: now, }, readModel, }); const event = Array.isArray(result) ? result[0] : result; expect(event.type).toBe("project.created"); expect((event.payload as { scripts: unknown[] }).scripts).toEqual([]); }), ); it.effect("propagates scripts in project.meta.update payload", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const readModel = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create-scripts"), aggregateKind: "project", aggregateId: asProjectId("project-scripts"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-scripts"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-scripts"), metadata: {}, payload: { projectId: asProjectId("project-scripts"), title: "Scripts", workspaceRoot: "/tmp/scripts", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const scripts = [ { id: "lint", name: "Lint", command: "bun run lint", icon: "lint", runOnWorktreeCreate: false, }, ] as const; const result = yield* decideOrchestrationCommand({ command: { type: "project.meta.update", commandId: CommandId.make("cmd-project-update-scripts"), projectId: asProjectId("project-scripts"), scripts: Array.from(scripts), }, readModel, }); const event = Array.isArray(result) ? result[0] : result; expect(event.type).toBe("project.meta-updated"); expect((event.payload as { scripts?: unknown[] }).scripts).toEqual(scripts); }), ); const script = (id: string): ProjectScript => ({ id, name: "Install dependencies", command: "vp i", icon: "configure", runOnWorktreeCreate: false, }); const projectWithScripts = (scripts: ReadonlyArray<ProjectScript>) => { const now = "2026-01-01T00:00:00.000Z"; return projectEvent(createEmptyReadModel(now), { sequence: 1, eventId: asEventId("evt-legacy-scripts"), aggregateKind: "project", aggregateId: asProjectId("project-scripts"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-legacy-scripts"), causationEventId: null, correlationId: CommandId.make("cmd-legacy-scripts"), metadata: {}, payload: { projectId: asProjectId("project-scripts"), title: "Scripts", workspaceRoot: "/tmp/scripts", defaultModelSelection: null, scripts, createdAt: now, updatedAt: now, }, }); }; for (const id of ["install-javascript-dependencies", "A", "a.b", "a b", "-a", "a".repeat(25)]) { it.effect(`rejects a new script ID that cannot have a shortcut: ${id}`, () => Effect.gen(function* () { const readModel = yield* projectWithScripts([]); const failure = yield* Effect.flip( decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-invalid-script"), projectId: asProjectId("project-scripts"), scripts: [script("lint"), script(id)], }, }), ); expect(failure).toMatchObject({ _tag: "OrchestrationCommandInvariantError" }); expect(failure.message).toContain("Script ID"); expect(failure.message).toContain("24"); expect(readModel.projects[0]?.scripts).toEqual([]); }), ); } it.effect("accepts a script ID at the shortcut length limit", () => Effect.gen(function* () { const readModel = yield* projectWithScripts([]); const scripts = [script("a".repeat(24))]; const result = yield* decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-valid-script"), projectId: asProjectId("project-scripts"), scripts, }, }); const event = Array.isArray(result) ? result[0] : result; expect(event.payload).toMatchObject({ scripts }); }), ); it.effect( "keeps legacy scripts readable, editable and removable while allowing valid additions", () => Effect.gen(function* () { const legacy = script("install-javascript-dependencies"); const readModel = yield* projectWithScripts([legacy]); expect(readModel.projects[0]?.scripts).toEqual([legacy]); for (const scripts of [[{ ...legacy, command: "vp install" }, script("lint")], []]) { const result = yield* decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-repair-script"), projectId: asProjectId("project-scripts"), scripts, }, }); const event = Array.isArray(result) ? result[0] : result; expect(event.payload).toMatchObject({ scripts }); } const failure = yield* Effect.flip( decideOrchestrationCommand({ readModel, command: { type: "project.meta.update", commandId: CommandId.make("cmd-new-invalid-script"), projectId: asProjectId("project-scripts"), scripts: [legacy, script("another.invalid.id")], }, }), ); expect(failure).toMatchObject({ _tag: "OrchestrationCommandInvariantError" }); }), ); it.effect("propagates project icon metadata in project.meta.update", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const readModel = yield* projectEvent(createEmptyReadModel(now), { sequence: 1, eventId: asEventId("evt-project-create-favicon"), aggregateKind: "project", aggregateId: asProjectId("project-favicon"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-favicon"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-favicon"), metadata: {}, payload: { projectId: asProjectId("project-favicon"), title: "Favicon", workspaceRoot: "/tmp/favicon", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const result = yield* decideOrchestrationCommand({ command: { type: "project.meta.update", commandId: CommandId.make("cmd-project-update-favicon"), projectId: asProjectId("project-favicon"), faviconPath: "brand/icon.svg", projectIcon: { kind: "lucide", name: "alarm-clock", color: "violet" }, }, readModel, }); const event = Array.isArray(result) ? result[0] : result; expect(event.type).toBe("project.meta-updated"); expect((event.payload as { faviconPath?: string }).faviconPath).toBe("brand/icon.svg"); expect((event.payload as { projectIcon?: unknown }).projectIcon).toEqual({ kind: "lucide", name: "alarm-clock", color: "violet", }); }), ); it.effect("rejects project.create for an active workspace root that already exists", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const readModel = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create"), aggregateKind: "project", aggregateId: asProjectId("project-existing"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create"), causationEventId: null, correlationId: CommandId.make("cmd-project-create"), metadata: {}, payload: { projectId: asProjectId("project-existing"), title: "Project", workspaceRoot: "/tmp/project", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const failure = yield* Effect.flip( decideOrchestrationCommand({ command: { type: "project.create", commandId: CommandId.make("cmd-project-create-duplicate-root"), projectId: asProjectId("project-duplicate-root"), title: "Duplicate Project", workspaceRoot: "/tmp/project/", createdAt: now, }, readModel, }), ); expect(failure.message).toContain( "Active project 'project-existing' already exists for workspace root '/tmp/project'.", ); }), ); it.effect("rejects project.meta.update when moving onto another active workspace root", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const withFirstProject = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create-first"), aggregateKind: "project", aggregateId: asProjectId("project-first"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-first"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-first"), metadata: {}, payload: { projectId: asProjectId("project-first"), title: "First", workspaceRoot: "/tmp/project-first", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const readModel = yield* projectEvent(withFirstProject, { sequence: 2, eventId: asEventId("evt-project-create-second"), aggregateKind: "project", aggregateId: asProjectId("project-second"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create-second"), causationEventId: null, correlationId: CommandId.make("cmd-project-create-second"), metadata: {}, payload: { projectId: asProjectId("project-second"), title: "Second", workspaceRoot: "/tmp/project-second", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const failure = yield* Effect.flip( decideOrchestrationCommand({ command: { type: "project.meta.update", commandId: CommandId.make("cmd-project-update-duplicate-root"), projectId: asProjectId("project-second"), workspaceRoot: "/tmp/project-first", }, readModel, }), ); expect(failure.message).toContain( "Active project 'project-first' already exists for workspace root '/tmp/project-first'.", ); }), ); it.effect("emits user message and turn-start-requested events for thread.turn.start", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const withProject = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create"), aggregateKind: "project", aggregateId: asProjectId("project-1"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create"), causationEventId: null, correlationId: CommandId.make("cmd-project-create"), metadata: {}, payload: { projectId: asProjectId("project-1"), title: "Project", workspaceRoot: "/tmp/project", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const readModel = yield* projectEvent(withProject, { sequence: 2, eventId: asEventId("evt-thread-create"), aggregateKind: "thread", aggregateId: ThreadId.make("thread-1"), type: "thread.created", occurredAt: now, commandId: CommandId.make("cmd-thread-create"), causationEventId: null, correlationId: CommandId.make("cmd-thread-create"), metadata: {}, payload: { threadId: ThreadId.make("thread-1"), projectId: asProjectId("project-1"), title: "Thread", modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5-codex", }, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", branch: null, worktreePath: null, createdAt: now, updatedAt: now, }, }); const result = yield* decideOrchestrationCommand({ command: { type: "thread.turn.start", commandId: CommandId.make("cmd-turn-start"), threadId: ThreadId.make("thread-1"), message: { messageId: asMessageId("message-user-1"), role: "user", text: "hello", attachments: [], }, modelSelection: createModelSelection(ProviderInstanceId.make("codex"), "gpt-5.3-codex", [ { id: "reasoningEffort", value: "high" }, { id: "fastMode", value: true }, ]), interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: now, }, readModel, }); expect(Array.isArray(result)).toBe(true); const events = Array.isArray(result) ? result : [result]; expect(events).toHaveLength(2); expect(events[0]?.type).toBe("thread.message-sent"); const turnStartEvent = events[1]; expect(turnStartEvent?.type).toBe("thread.turn-start-requested"); expect(turnStartEvent?.causationEventId).toBe(events[0]?.eventId ?? null); if (turnStartEvent?.type !== "thread.turn-start-requested") { return; } expect(turnStartEvent.payload).toMatchObject({ threadId: ThreadId.make("thread-1"), messageId: asMessageId("message-user-1"), modelSelection: createModelSelection(ProviderInstanceId.make("codex"), "gpt-5.3-codex", [ { id: "reasoningEffort", value: "high" }, { id: "fastMode", value: true }, ]), runtimeMode: "approval-required", }); }), ); it.effect("emits thread.runtime-mode-set from thread.runtime-mode.set", () => Effect.gen(function* () { const now = "2026-01-01T00:00:00.000Z"; const initial = createEmptyReadModel(now); const withProject = yield* projectEvent(initial, { sequence: 1, eventId: asEventId("evt-project-create"), aggregateKind: "project", aggregateId: asProjectId("project-1"), type: "project.created", occurredAt: now, commandId: CommandId.make("cmd-project-create"), causationEventId: null, correlationId: CommandId.make("cmd-project-create"), metadata: {}, payload: { projectId: asProjectId("project-1"), title: "Project", workspaceRoot: "/tmp/project", defaultModelSelection: null, scripts: [], createdAt: now, updatedAt: now, }, }); const readModel = yield* projectEvent(withProject, { sequence: 2, eventId: asEventId("evt-thread-create"), aggregateKind: "thread", aggregateId: ThreadId.make("thread-1"), type: "thread.created", occurredAt: now, commandId: CommandId.make("cmd-thread-create"), causationEventId: null, correlationId: CommandId.make("cmd-thread-create"), metadata: {}, payload: { threadId: ThreadId.make("thread-1"), projectId: asProjectId("project-1"),