authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-04-10 01:51:31-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-04-10 01:51:31-07:00
log3405a64dd8fdf3affe14c057692484fffb63b0af
tree7a9d4be187f3f4b47e6108867bc917b71dca1886
parent1cba2f64d39073bb77faac7234e88f52aa395643
signature Signed by PGP key B5690EEEBB952194

bump effect to latest beta (#1866)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius@macmini.local> Co-authored-by: codex <codex@users.noreply.github.com>

174 files changed, 1853 insertions(+), 1870 deletions(-)

apps/desktop/src/clientPersistence.test.ts+1-1
......@@ -58,7 +58,7 @@ const clientSettings: ClientSettings = {
5858};
5959
6060const savedRegistryRecord: PersistedSavedEnvironmentRecord = {
61 environmentId: EnvironmentId.makeUnsafe("environment-1"),
61 environmentId: EnvironmentId.make("environment-1"),
6262 label: "Remote environment",
6363 httpBaseUrl: "https://remote.example.com/",
6464 wsBaseUrl: "wss://remote.example.com/",
apps/server/integration/OrchestrationEngineHarness.integration.ts+1-1
......@@ -438,7 +438,7 @@ export const makeOrchestrationIntegrationHarness = (
438438 ) =>
439439 waitFor(
440440 pendingApprovalRepository
441 .getByRequestId({ requestId: ApprovalRequestId.makeUnsafe(requestId) })
441 .getByRequestId({ requestId: ApprovalRequestId.make(requestId) })
442442 .pipe(
443443 Effect.map((row) =>
444444 Option.match(row, {
apps/server/integration/TestProviderAdapter.integration.ts+3-3
......@@ -289,7 +289,7 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter
289289
290290 state.turnCount += 1;
291291 const turnCount = state.turnCount;
292 const turnId = TurnId.makeUnsafe(`turn-${turnCount}`);
292 const turnId = TurnId.make(`turn-${turnCount}`);
293293
294294 const response = state.queuedResponses.shift();
295295 if (!response) {
......@@ -307,7 +307,7 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter
307307 ...(fixtureEvent as Record<string, unknown>),
308308 eventId: randomUUID(),
309309 provider,
310 sessionId: RuntimeSessionId.makeUnsafe(String(input.threadId)),
310 sessionId: RuntimeSessionId.make(String(input.threadId)),
311311 createdAt: nowIso(),
312312 };
313313 rawEvent.threadId = state.snapshot.threadId;
......@@ -363,7 +363,7 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter
363363 if (deferredTurnCompletedEvents.length === 0) {
364364 yield* emit({
365365 type: "turn.completed",
366 eventId: EventId.makeUnsafe(randomUUID()),
366 eventId: EventId.make(randomUUID()),
367367 provider,
368368 createdAt: nowIso(),
369369 threadId: state.snapshot.threadId,
apps/server/integration/fixtures/providerRuntime.ts+2-2
......@@ -5,14 +5,14 @@ const PROVIDER = "codex" as const;
55const SESSION_ID = "fixture-session";
66const THREAD_ID = "fixture-thread";
77const TURN_ID = "fixture-turn";
8const REQUEST_ID = RuntimeRequestId.makeUnsafe("req-1");
8const REQUEST_ID = RuntimeRequestId.make("req-1");
99
1010function baseEvent(
1111 eventId: string,
1212 createdAt: string,
1313): Pick<LegacyProviderRuntimeEvent, "eventId" | "provider" | "sessionId" | "createdAt"> {
1414 return {
15 eventId: EventId.makeUnsafe(eventId),
15 eventId: EventId.make(eventId),
1616 provider: PROVIDER,
1717 sessionId: SESSION_ID,
1818 createdAt,
apps/server/integration/orchestrationEngine.integration.test.ts+18-19
......@@ -30,14 +30,13 @@ import type {
3030} from "../src/orchestration/Services/RuntimeReceiptBus.ts";
3131import * as NodeServices from "@effect/platform-node/NodeServices";
3232
33const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
34const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
35const asEventId = (value: string): EventId => EventId.makeUnsafe(value);
36const asApprovalRequestId = (value: string): ApprovalRequestId =>
37 ApprovalRequestId.makeUnsafe(value);
33const asMessageId = (value: string): MessageId => MessageId.make(value);
34const asProjectId = (value: string): ProjectId => ProjectId.make(value);
35const asEventId = (value: string): EventId => EventId.make(value);
36const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value);
3837
3938const PROJECT_ID = asProjectId("project-1");
40const THREAD_ID = ThreadId.makeUnsafe("thread-1");
39const THREAD_ID = ThreadId.make("thread-1");
4140const FIXTURE_TURN_ID = "fixture-turn";
4241const APPROVAL_REQUEST_ID = asApprovalRequestId("req-approval-1");
4342type IntegrationProvider = ProviderKind;
......@@ -112,7 +111,7 @@ const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) =>
112111
113112 yield* harness.engine.dispatch({
114113 type: "project.create",
115 commandId: CommandId.makeUnsafe("cmd-project-create"),
114 commandId: CommandId.make("cmd-project-create"),
116115 projectId: PROJECT_ID,
117116 title: "Integration Project",
118117 workspaceRoot: harness.workspaceDir,
......@@ -125,7 +124,7 @@ const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) =>
125124
126125 yield* harness.engine.dispatch({
127126 type: "thread.create",
128 commandId: CommandId.makeUnsafe("cmd-thread-create"),
127 commandId: CommandId.make("cmd-thread-create"),
129128 threadId: THREAD_ID,
130129 projectId: PROJECT_ID,
131130 title: "Integration Thread",
......@@ -150,7 +149,7 @@ const startTurn = (input: {
150149}) =>
151150 input.harness.engine.dispatch({
152151 type: "thread.turn.start",
153 commandId: CommandId.makeUnsafe(input.commandId),
152 commandId: CommandId.make(input.commandId),
154153 threadId: THREAD_ID,
155154 message: {
156155 messageId: asMessageId(input.messageId),
......@@ -261,7 +260,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)(
261260
262261 yield* harness.engine.dispatch({
263262 type: "project.create",
264 commandId: CommandId.makeUnsafe("cmd-project-create-real-codex"),
263 commandId: CommandId.make("cmd-project-create-real-codex"),
265264 projectId: PROJECT_ID,
266265 title: "Integration Project",
267266 workspaceRoot: harness.workspaceDir,
......@@ -274,7 +273,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)(
274273
275274 yield* harness.engine.dispatch({
276275 type: "thread.create",
277 commandId: CommandId.makeUnsafe("cmd-thread-create-real-codex"),
276 commandId: CommandId.make("cmd-thread-create-real-codex"),
278277 threadId: THREAD_ID,
279278 projectId: PROJECT_ID,
280279 title: "Integration Thread",
......@@ -291,7 +290,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)(
291290
292291 yield* harness.engine.dispatch({
293292 type: "thread.turn.start",
294 commandId: CommandId.makeUnsafe("cmd-turn-start-real-codex-1"),
293 commandId: CommandId.make("cmd-turn-start-real-codex-1"),
295294 threadId: THREAD_ID,
296295 message: {
297296 messageId: asMessageId("msg-real-codex-1"),
......@@ -318,7 +317,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)(
318317
319318 yield* harness.engine.dispatch({
320319 type: "thread.turn.start",
321 commandId: CommandId.makeUnsafe("cmd-turn-start-real-codex-2"),
320 commandId: CommandId.make("cmd-turn-start-real-codex-2"),
322321 threadId: THREAD_ID,
323322 message: {
324323 messageId: asMessageId("msg-real-codex-2"),
......@@ -583,7 +582,7 @@ it.live("tracks approval requests and resolves pending approvals on user respons
583582
584583 yield* harness.engine.dispatch({
585584 type: "thread.approval.respond",
586 commandId: CommandId.makeUnsafe("cmd-approval-respond"),
585 commandId: CommandId.make("cmd-approval-respond"),
587586 threadId: THREAD_ID,
588587 requestId: APPROVAL_REQUEST_ID,
589588 decision: "accept",
......@@ -815,7 +814,7 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git
815814
816815 yield* harness.engine.dispatch({
817816 type: "thread.checkpoint.revert",
818 commandId: CommandId.makeUnsafe("cmd-checkpoint-revert"),
817 commandId: CommandId.make("cmd-checkpoint-revert"),
819818 threadId: THREAD_ID,
820819 turnCount: 1,
821820 createdAt: nowIso(),
......@@ -875,7 +874,7 @@ it.live(
875874
876875 yield* harness.engine.dispatch({
877876 type: "thread.checkpoint.revert",
878 commandId: CommandId.makeUnsafe("cmd-checkpoint-revert-no-session"),
877 commandId: CommandId.make("cmd-checkpoint-revert-no-session"),
879878 threadId: THREAD_ID,
880879 turnCount: 0,
881880 createdAt: nowIso(),
......@@ -1119,7 +1118,7 @@ it.live("forwards claudeAgent approval responses to the provider session", () =>
11191118
11201119 yield* harness.engine.dispatch({
11211120 type: "thread.approval.respond",
1122 commandId: CommandId.makeUnsafe("cmd-claude-approval-respond"),
1121 commandId: CommandId.make("cmd-claude-approval-respond"),
11231122 threadId: THREAD_ID,
11241123 requestId: APPROVAL_REQUEST_ID,
11251124 decision: "accept",
......@@ -1192,7 +1191,7 @@ it.live("forwards thread.turn.interrupt to claudeAgent provider sessions", () =>
11921191
11931192 yield* harness.engine.dispatch({
11941193 type: "thread.turn.interrupt",
1195 commandId: CommandId.makeUnsafe("cmd-turn-interrupt-claude"),
1194 commandId: CommandId.make("cmd-turn-interrupt-claude"),
11961195 threadId: THREAD_ID,
11971196 createdAt: nowIso(),
11981197 });
......@@ -1309,7 +1308,7 @@ it.live("reverts claudeAgent turns and rolls back provider conversation state",
13091308
13101309 yield* harness.engine.dispatch({
13111310 type: "thread.checkpoint.revert",
1312 commandId: CommandId.makeUnsafe("cmd-checkpoint-revert-claude"),
1311 commandId: CommandId.make("cmd-checkpoint-revert-claude"),
13131312 threadId: THREAD_ID,
13141313 turnCount: 1,
13151314 createdAt: nowIso(),
apps/server/integration/providerService.integration.test.ts+24-36
......@@ -122,15 +122,12 @@ it.live("replays typed runtime fixture events", () =>
122122
123123 yield* Effect.gen(function* () {
124124 const provider = yield* ProviderService;
125 const session = yield* provider.startSession(
126 ThreadId.makeUnsafe("thread-integration-typed"),
127 {
128 threadId: ThreadId.makeUnsafe("thread-integration-typed"),
129 provider: "codex",
130 cwd: fixture.cwd,
131 runtimeMode: "full-access",
132 },
133 );
125 const session = yield* provider.startSession(ThreadId.make("thread-integration-typed"), {
126 threadId: ThreadId.make("thread-integration-typed"),
127 provider: "codex",
128 cwd: fixture.cwd,
129 runtimeMode: "full-access",
130 });
134131 assert.equal((session.threadId ?? "").length > 0, true);
135132
136133 const observedEvents = yield* runTurn({
......@@ -157,15 +154,12 @@ it.live("replays file-changing fixture turn events", () =>
157154
158155 yield* Effect.gen(function* () {
159156 const provider = yield* ProviderService;
160 const session = yield* provider.startSession(
161 ThreadId.makeUnsafe("thread-integration-tools"),
162 {
163 threadId: ThreadId.makeUnsafe("thread-integration-tools"),
164 provider: "codex",
165 cwd: fixture.cwd,
166 runtimeMode: "full-access",
167 },
168 );
157 const session = yield* provider.startSession(ThreadId.make("thread-integration-tools"), {
158 threadId: ThreadId.make("thread-integration-tools"),
159 provider: "codex",
160 cwd: fixture.cwd,
161 runtimeMode: "full-access",
162 });
169163 assert.equal((session.threadId ?? "").length > 0, true);
170164
171165 const observedEvents = yield* runTurn({
......@@ -196,15 +190,12 @@ it.live("runs multi-turn tool/approval flow", () =>
196190
197191 yield* Effect.gen(function* () {
198192 const provider = yield* ProviderService;
199 const session = yield* provider.startSession(
200 ThreadId.makeUnsafe("thread-integration-multi"),
201 {
202 threadId: ThreadId.makeUnsafe("thread-integration-multi"),
203 provider: "codex",
204 cwd: fixture.cwd,
205 runtimeMode: "full-access",
206 },
207 );
193 const session = yield* provider.startSession(ThreadId.make("thread-integration-multi"), {
194 threadId: ThreadId.make("thread-integration-multi"),
195 provider: "codex",
196 cwd: fixture.cwd,
197 runtimeMode: "full-access",
198 });
208199 assert.equal((session.threadId ?? "").length > 0, true);
209200
210201 const firstTurnEvents = yield* runTurn({
......@@ -250,15 +241,12 @@ it.live("rolls back provider conversation state only", () =>
250241
251242 yield* Effect.gen(function* () {
252243 const provider = yield* ProviderService;
253 const session = yield* provider.startSession(
254 ThreadId.makeUnsafe("thread-integration-rollback"),
255 {
256 threadId: ThreadId.makeUnsafe("thread-integration-rollback"),
257 provider: "codex",
258 cwd: fixture.cwd,
259 runtimeMode: "full-access",
260 },
261 );
244 const session = yield* provider.startSession(ThreadId.make("thread-integration-rollback"), {
245 threadId: ThreadId.make("thread-integration-rollback"),
246 provider: "codex",
247 cwd: fixture.cwd,
248 runtimeMode: "full-access",
249 });
262250 assert.equal((session.threadId ?? "").length > 0, true);
263251
264252 yield* runTurn({
apps/server/src/auth/Layers/SessionCredentialService.ts+1-1
......@@ -188,7 +188,7 @@ export const makeSessionCredentialService = Effect.gen(function* () {
188188
189189 const issue: SessionCredentialServiceShape["issue"] = (input) =>
190190 Effect.gen(function* () {
191 const sessionId = AuthSessionId.makeUnsafe(crypto.randomUUID());
191 const sessionId = AuthSessionId.make(crypto.randomUUID());
192192 const issuedAt = yield* DateTime.now;
193193 const expiresAt = DateTime.add(issuedAt, {
194194 milliseconds: Duration.toMillis(input?.ttl ?? DEFAULT_SESSION_TTL),
apps/server/src/auth/Services/AuthControlPlane.ts+2-2
......@@ -4,7 +4,7 @@ import type {
44 AuthPairingLink,
55 AuthSessionId,
66} from "@t3tools/contracts";
7import { Data, DateTime, Duration, Effect, ServiceMap } from "effect";
7import { Data, DateTime, Duration, Effect, Context } from "effect";
88import { SessionRole } from "./SessionCredentialService";
99
1010export const DEFAULT_SESSION_SUBJECT = "cli-issued-session";
......@@ -64,6 +64,6 @@ export interface AuthControlPlaneShape {
6464 ) => Effect.Effect<number, AuthControlPlaneError>;
6565}
6666
67export class AuthControlPlane extends ServiceMap.Service<AuthControlPlane, AuthControlPlaneShape>()(
67export class AuthControlPlane extends Context.Service<AuthControlPlane, AuthControlPlaneShape>()(
6868 "t3/AuthControlPlane",
6969) {}
apps/server/src/auth/Services/BootstrapCredentialService.ts+2-2
......@@ -1,5 +1,5 @@
11import type { AuthPairingLink, ServerAuthBootstrapMethod } from "@t3tools/contracts";
2import { Data, DateTime, Duration, ServiceMap } from "effect";
2import { Data, DateTime, Duration, Context } from "effect";
33import type { Effect, Stream } from "effect";
44
55export type BootstrapCredentialRole = "owner" | "client";
......@@ -51,7 +51,7 @@ export interface BootstrapCredentialServiceShape {
5151 readonly consume: (credential: string) => Effect.Effect<BootstrapGrant, BootstrapCredentialError>;
5252}
5353
54export class BootstrapCredentialService extends ServiceMap.Service<
54export class BootstrapCredentialService extends Context.Service<
5555 BootstrapCredentialService,
5656 BootstrapCredentialServiceShape
5757>()("t3/auth/Services/BootstrapCredentialService") {}
apps/server/src/auth/Services/ServerAuth.ts+2-2
......@@ -12,7 +12,7 @@ import type {
1212 ServerAuthSessionMethod,
1313 AuthWebSocketTokenResult,
1414} from "@t3tools/contracts";
15import { Data, DateTime, ServiceMap } from "effect";
15import { Data, DateTime, Context } from "effect";
1616import type { Effect } from "effect";
1717import type * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
1818import type { SessionRole } from "./SessionCredentialService.ts";
......@@ -79,6 +79,6 @@ export interface ServerAuthShape {
7979 readonly issueStartupPairingUrl: (baseUrl: string) => Effect.Effect<string, AuthError>;
8080}
8181
82export class ServerAuth extends ServiceMap.Service<ServerAuth, ServerAuthShape>()(
82export class ServerAuth extends Context.Service<ServerAuth, ServerAuthShape>()(
8383 "t3/auth/Services/ServerAuth",
8484) {}
apps/server/src/auth/Services/ServerAuthPolicy.ts+2-2
......@@ -1,11 +1,11 @@
11import type { ServerAuthDescriptor } from "@t3tools/contracts";
2import { ServiceMap } from "effect";
2import { Context } from "effect";
33import type { Effect } from "effect";
44
55export interface ServerAuthPolicyShape {
66 readonly getDescriptor: () => Effect.Effect<ServerAuthDescriptor>;
77}
88
9export class ServerAuthPolicy extends ServiceMap.Service<ServerAuthPolicy, ServerAuthPolicyShape>()(
9export class ServerAuthPolicy extends Context.Service<ServerAuthPolicy, ServerAuthPolicyShape>()(
1010 "t3/auth/Services/ServerAuthPolicy",
1111) {}
apps/server/src/auth/Services/ServerSecretStore.ts+4-5
......@@ -1,4 +1,4 @@
1import { Data, ServiceMap } from "effect";
1import { Data, Context } from "effect";
22import type { Effect } from "effect";
33
44export class SecretStoreError extends Data.TaggedError("SecretStoreError")<{
......@@ -16,7 +16,6 @@ export interface ServerSecretStoreShape {
1616 readonly remove: (name: string) => Effect.Effect<void, SecretStoreError>;
1717}
1818
19export class ServerSecretStore extends ServiceMap.Service<
20 ServerSecretStore,
21 ServerSecretStoreShape
22>()("t3/auth/Services/ServerSecretStore") {}
19export class ServerSecretStore extends Context.Service<ServerSecretStore, ServerSecretStoreShape>()(
20 "t3/auth/Services/ServerSecretStore",
21) {}
apps/server/src/auth/Services/SessionCredentialService.ts+2-2
......@@ -4,7 +4,7 @@ import type {
44 AuthSessionId,
55 ServerAuthSessionMethod,
66} from "@t3tools/contracts";
7import { Data, DateTime, Duration, ServiceMap } from "effect";
7import { Data, DateTime, Duration, Context } from "effect";
88import type { Effect, Stream } from "effect";
99
1010export type SessionRole = "owner" | "client";
......@@ -81,7 +81,7 @@ export interface SessionCredentialServiceShape {
8181 readonly markDisconnected: (sessionId: AuthSessionId) => Effect.Effect<void, never>;
8282}
8383
84export class SessionCredentialService extends ServiceMap.Service<
84export class SessionCredentialService extends Context.Service<
8585 SessionCredentialService,
8686 SessionCredentialServiceShape
8787>()("t3/auth/Services/SessionCredentialService") {}
apps/server/src/checkpointing/Layers/CheckpointDiffQuery.test.ts+4-4
......@@ -26,7 +26,7 @@ function makeThreadCheckpointContext(input: {
2626 worktreePath: input.worktreePath,
2727 checkpoints: [
2828 {
29 turnId: TurnId.makeUnsafe("turn-1"),
29 turnId: TurnId.make("turn-1"),
3030 checkpointTurnCount: input.checkpointTurnCount,
3131 checkpointRef: input.checkpointRef,
3232 status: "ready",
......@@ -40,8 +40,8 @@ function makeThreadCheckpointContext(input: {
4040
4141describe("CheckpointDiffQueryLive", () => {
4242 it("computes diffs using canonical turn-0 checkpoint refs", async () => {
43 const projectId = ProjectId.makeUnsafe("project-1");
44 const threadId = ThreadId.makeUnsafe("thread-1");
43 const projectId = ProjectId.make("project-1");
44 const threadId = ThreadId.make("thread-1");
4545 const toCheckpointRef = checkpointRefForThreadTurn(threadId, 1);
4646 const hasCheckpointRefCalls: Array<CheckpointRef> = [];
4747 const diffCheckpointsCalls: Array<{
......@@ -119,7 +119,7 @@ describe("CheckpointDiffQueryLive", () => {
119119 });
120120
121121 it("fails when the thread is missing from the snapshot", async () => {
122 const threadId = ThreadId.makeUnsafe("thread-missing");
122 const threadId = ThreadId.make("thread-missing");
123123
124124 const checkpointStore: CheckpointStoreShape = {
125125 isGitRepository: () => Effect.succeed(true),
apps/server/src/checkpointing/Layers/CheckpointStore.test.ts+1-1
......@@ -93,7 +93,7 @@ it.layer(TestLayer)("CheckpointStoreLive", (it) => {
9393 const tmp = yield* makeTmpDir();
9494 yield* initRepoWithCommit(tmp);
9595 const checkpointStore = yield* CheckpointStore;
96 const threadId = ThreadId.makeUnsafe("thread-checkpoint-store");
96 const threadId = ThreadId.make("thread-checkpoint-store");
9797 const fromCheckpointRef = checkpointRefForThreadTurn(threadId, 0);
9898 const toCheckpointRef = checkpointRefForThreadTurn(threadId, 1);
9999
apps/server/src/checkpointing/Services/CheckpointDiffQuery.ts+2-2
......@@ -12,7 +12,7 @@ import type {
1212 OrchestrationGetTurnDiffInput,
1313 OrchestrationGetTurnDiffResult,
1414} from "@t3tools/contracts";
15import { ServiceMap } from "effect";
15import { Context } from "effect";
1616import type { Effect } from "effect";
1717
1818import type { CheckpointServiceError } from "../Errors.ts";
......@@ -43,7 +43,7 @@ export interface CheckpointDiffQueryShape {
4343/**
4444 * CheckpointDiffQuery - Service tag for checkpoint diff queries.
4545 */
46export class CheckpointDiffQuery extends ServiceMap.Service<
46export class CheckpointDiffQuery extends Context.Service<
4747 CheckpointDiffQuery,
4848 CheckpointDiffQueryShape
4949>()("t3/checkpointing/Services/CheckpointDiffQuery") {}
apps/server/src/checkpointing/Services/CheckpointStore.ts+3-3
......@@ -5,12 +5,12 @@
55 * workspace thread timeline. It does not store user-facing checkpoint metadata
66 * and does not coordinate provider conversation rollback.
77 *
8 * Uses Effect `ServiceMap.Service` for dependency injection and exposes typed
8 * Uses Effect `Context.Service` for dependency injection and exposes typed
99 * domain errors for checkpoint storage operations.
1010 *
1111 * @module CheckpointStore
1212 */
13import { ServiceMap } from "effect";
13import { Context } from "effect";
1414import type { Effect } from "effect";
1515
1616import type { CheckpointStoreError } from "../Errors.ts";
......@@ -95,6 +95,6 @@ export interface CheckpointStoreShape {
9595/**
9696 * CheckpointStore - Service tag for checkpoint persistence and restore operations.
9797 */
98export class CheckpointStore extends ServiceMap.Service<CheckpointStore, CheckpointStoreShape>()(
98export class CheckpointStore extends Context.Service<CheckpointStore, CheckpointStoreShape>()(
9999 "t3/checkpointing/Services/CheckpointStore",
100100) {}
apps/server/src/checkpointing/Utils.ts+1-1
......@@ -4,7 +4,7 @@ import { CheckpointRef, ProjectId, type ThreadId } from "@t3tools/contracts";
44export const CHECKPOINT_REFS_PREFIX = "refs/t3/checkpoints";
55
66export function checkpointRefForThreadTurn(threadId: ThreadId, turnCount: number): CheckpointRef {
7 return CheckpointRef.makeUnsafe(
7 return CheckpointRef.make(
88 `${CHECKPOINT_REFS_PREFIX}/${Encoding.encodeBase64Url(threadId)}/turn/${turnCount}`,
99 );
1010}
apps/server/src/cli-config.test.ts+63
......@@ -153,6 +153,69 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => {
153153 }),
154154 );
155155
156 it.effect("preserves explicit false CLI boolean flags over env and bootstrap values", () =>
157 Effect.gen(function* () {
158 const { join } = yield* Path.Path;
159 const baseDir = join(os.tmpdir(), "t3-cli-config-false-flags");
160 const fd = yield* openBootstrapFd({
161 noBrowser: true,
162 autoBootstrapProjectFromCwd: true,
163 logWebSocketEvents: true,
164 });
165 const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173"));
166
167 const resolved = yield* resolveServerConfig(
168 {
169 mode: Option.some("web"),
170 port: Option.some(8788),
171 host: Option.some("127.0.0.1"),
172 baseDir: Option.some(baseDir),
173 cwd: Option.none(),
174 devUrl: Option.some(new URL("http://127.0.0.1:4173")),
175 noBrowser: Option.some(false),
176 bootstrapFd: Option.none(),
177 autoBootstrapProjectFromCwd: Option.some(false),
178 logWebSocketEvents: Option.some(false),
179 },
180 Option.none(),
181 ).pipe(
182 Effect.provide(
183 Layer.mergeAll(
184 ConfigProvider.layer(
185 ConfigProvider.fromEnv({
186 env: {
187 T3CODE_BOOTSTRAP_FD: String(fd),
188 T3CODE_NO_BROWSER: "true",
189 T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "true",
190 T3CODE_LOG_WS_EVENTS: "true",
191 },
192 }),
193 ),
194 NetService.layer,
195 ),
196 ),
197 );
198
199 expect(resolved).toEqual({
200 logLevel: "Info",
201 ...defaultObservabilityConfig,
202 mode: "web",
203 port: 8788,
204 cwd: process.cwd(),
205 baseDir,
206 ...derivedPaths,
207 host: "127.0.0.1",
208 staticDir: undefined,
209 devUrl: new URL("http://127.0.0.1:4173"),
210 noBrowser: false,
211 startupPresentation: "browser",
212 desktopBootstrapToken: undefined,
213 autoBootstrapProjectFromCwd: false,
214 logWebSocketEvents: false,
215 });
216 }),
217 );
218
156219 it.effect("uses bootstrap envelope values as fallbacks when flags and env are absent", () =>
157220 Effect.gen(function* () {
158221 const { join } = yield* Path.Path;
apps/server/src/cli.test.ts+4
......@@ -152,6 +152,10 @@ it.layer(NodeServices.layer)("cli log-level parsing", (it) => {
152152 runCliWithRuntime(["--log-level", "debug", "--version"]),
153153 );
154154
155 it.effect("accepts canonical --no-<flag> boolean negation", () =>
156 runCliWithRuntime(["--no-log-websocket-events", "--version"]),
157 );
158
155159 it.effect("rejects invalid log-level casing before launching the server", () =>
156160 Effect.gen(function* () {
157161 const error = yield* runCliWithRuntime(["--log-level", "Debug"]).pipe(Effect.flip);
apps/server/src/cli.ts+37-68
......@@ -193,9 +193,6 @@ interface CliAuthLocationFlags {
193193 readonly devUrl?: Option.Option<URL>;
194194}
195195
196const resolveBooleanFlag = (flag: Option.Option<boolean>, envValue: boolean) =>
197 Option.getOrElse(Option.filter(flag, Boolean), () => envValue);
198
199196const resolveOptionPrecedence = <Value>(
200197 ...values: ReadonlyArray<Option.Option<Value>>
201198): Option.Option<Value> => Option.firstSomeOf(values);
......@@ -241,12 +238,13 @@ export const resolveServerConfig = (
241238 bootstrapFd !== undefined
242239 ? yield* readBootstrapEnvelope(BootstrapEnvelopeSchema, bootstrapFd)
243240 : Option.none();
241 const bootstrap = Option.getOrUndefined(bootstrapEnvelope);
244242
245243 const mode: RuntimeMode = Option.getOrElse(
246244 resolveOptionPrecedence(
247245 normalizedFlags.mode,
248246 Option.fromUndefinedOr(env.mode),
249 Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.mode)),
247 Option.fromUndefinedOr(bootstrap?.mode),
250248 ),
251249 () => "web",
252250 );
......@@ -255,7 +253,7 @@ export const resolveServerConfig = (
255253 resolveOptionPrecedence(
256254 normalizedFlags.port,
257255 Option.fromUndefinedOr(env.port),
258 Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.port)),
256 Option.fromUndefinedOr(bootstrap?.port),
259257 ),
260258 {
261259 onSome: (value) => Effect.succeed(value),
......@@ -271,7 +269,7 @@ export const resolveServerConfig = (
271269 resolveOptionPrecedence(
272270 normalizedFlags.devUrl,
273271 Option.fromUndefinedOr(env.devUrl),
274 Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.devUrl)),
272 Option.fromUndefinedOr(bootstrap?.devUrl),
275273 ),
276274 () => undefined,
277275 );
......@@ -280,9 +278,7 @@ export const resolveServerConfig = (
280278 resolveOptionPrecedence(
281279 normalizedFlags.baseDir,
282280 Option.fromUndefinedOr(env.t3Home),
283 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
284 Option.fromUndefinedOr(bootstrap.t3Home),
285 ),
281 Option.fromUndefinedOr(bootstrap?.t3Home),
286282 ),
287283 ),
288284 );
......@@ -297,60 +293,41 @@ export const resolveServerConfig = (
297293 const serverTracePath = env.traceFile ?? derivedPaths.serverTracePath;
298294 yield* fs.makeDirectory(path.dirname(serverTracePath), { recursive: true });
299295 const startupPresentation = options?.startupPresentation ?? "browser";
300 const noBrowser =
301 startupPresentation === "headless"
302 ? true
303 : resolveBooleanFlag(
304 normalizedFlags.noBrowser,
305 Option.getOrElse(
306 resolveOptionPrecedence(
307 Option.fromUndefinedOr(env.noBrowser),
308 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
309 Option.fromUndefinedOr(bootstrap.noBrowser),
310 ),
311 ),
312 () => mode === "desktop",
313 ),
314 );
315 const desktopBootstrapToken = Option.getOrUndefined(
316 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
317 Option.fromUndefinedOr(bootstrap.desktopBootstrapToken),
296 const isHeadlessStartup = startupPresentation === "headless";
297 const noBrowser = Option.getOrElse(
298 resolveOptionPrecedence(
299 isHeadlessStartup ? Option.some(true) : Option.none(),
300 normalizedFlags.noBrowser,
301 Option.fromUndefinedOr(env.noBrowser),
302 Option.fromUndefinedOr(bootstrap?.noBrowser),
318303 ),
304 () => mode === "desktop",
319305 );
320 const autoBootstrapProjectFromCwd =
321 options?.forceAutoBootstrapProjectFromCwd ??
322 (startupPresentation === "headless"
323 ? false
324 : resolveBooleanFlag(
325 normalizedFlags.autoBootstrapProjectFromCwd,
326 Option.getOrElse(
327 resolveOptionPrecedence(
328 Option.fromUndefinedOr(env.autoBootstrapProjectFromCwd),
329 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
330 Option.fromUndefinedOr(bootstrap.autoBootstrapProjectFromCwd),
331 ),
332 ),
333 () => mode === "web",
334 ),
335 ));
336 const logWebSocketEvents = resolveBooleanFlag(
337 normalizedFlags.logWebSocketEvents,
338 Option.getOrElse(
339 resolveOptionPrecedence(
340 Option.fromUndefinedOr(env.logWebSocketEvents),
341 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
342 Option.fromUndefinedOr(bootstrap.logWebSocketEvents),
343 ),
344 ),
345 () => Boolean(devUrl),
306 const desktopBootstrapToken = bootstrap?.desktopBootstrapToken;
307 const autoBootstrapProjectFromCwd = Option.getOrElse(
308 resolveOptionPrecedence(
309 Option.fromUndefinedOr(options?.forceAutoBootstrapProjectFromCwd),
310 isHeadlessStartup ? Option.some(false) : Option.none(),
311 normalizedFlags.autoBootstrapProjectFromCwd,
312 Option.fromUndefinedOr(env.autoBootstrapProjectFromCwd),
313 Option.fromUndefinedOr(bootstrap?.autoBootstrapProjectFromCwd),
314 ),
315 () => mode === "web",
316 );
317 const logWebSocketEvents = Option.getOrElse(
318 resolveOptionPrecedence(
319 normalizedFlags.logWebSocketEvents,
320 Option.fromUndefinedOr(env.logWebSocketEvents),
321 Option.fromUndefinedOr(bootstrap?.logWebSocketEvents),
346322 ),
323 () => Boolean(devUrl),
347324 );
348325 const staticDir = devUrl ? undefined : yield* resolveStaticDir();
349326 const host = Option.getOrElse(
350327 resolveOptionPrecedence(
351328 normalizedFlags.host,
352329 Option.fromUndefinedOr(env.host),
353 Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.host)),
330 Option.fromUndefinedOr(bootstrap?.host),
354331 ),
355332 () => (mode === "desktop" ? "127.0.0.1" : undefined),
356333 );
......@@ -365,19 +342,11 @@ export const resolveServerConfig = (
365342 traceMaxFiles: env.traceMaxFiles,
366343 otlpTracesUrl:
367344 env.otlpTracesUrl ??
368 Option.getOrUndefined(
369 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
370 Option.fromUndefinedOr(bootstrap.otlpTracesUrl),
371 ),
372 ) ??
345 bootstrap?.otlpTracesUrl ??
373346 persistedObservabilitySettings.otlpTracesUrl,
374347 otlpMetricsUrl:
375348 env.otlpMetricsUrl ??
376 Option.getOrUndefined(
377 Option.flatMap(bootstrapEnvelope, (bootstrap) =>
378 Option.fromUndefinedOr(bootstrap.otlpMetricsUrl),
379 ),
380 ) ??
349 bootstrap?.otlpMetricsUrl ??
381350 persistedObservabilitySettings.otlpMetricsUrl,
382351 otlpExportIntervalMs: env.otlpExportIntervalMs,
383352 otlpServiceName: env.otlpServiceName,
......@@ -1030,10 +999,10 @@ const projectAddCommand = Command.make("add", {
1030999 }
10311000
10321001 const title = yield* resolveProjectTitle(workspaceRoot, Option.getOrUndefined(flags.title));
1033 const projectId = ProjectId.makeUnsafe(crypto.randomUUID());
1002 const projectId = ProjectId.make(crypto.randomUUID());
10341003 yield* dispatch({
10351004 type: "project.create",
1036 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
1005 commandId: CommandId.make(crypto.randomUUID()),
10371006 projectId,
10381007 title,
10391008 workspaceRoot,
......@@ -1071,7 +1040,7 @@ const projectRemoveCommand = Command.make("remove", {
10711040 });
10721041 yield* dispatch({
10731042 type: "project.delete",
1074 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
1043 commandId: CommandId.make(crypto.randomUUID()),
10751044 projectId: project.id,
10761045 });
10771046 return `Removed project ${project.id} (${project.title}).`;
......@@ -1111,7 +1080,7 @@ const projectRenameCommand = Command.make("rename", {
11111080
11121081 yield* dispatch({
11131082 type: "project.meta.update",
1114 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
1083 commandId: CommandId.make(crypto.randomUUID()),
11151084 projectId: project.id,
11161085 title: nextTitle,
11171086 });
apps/server/src/codexAppServerManager.test.ts+5-5
......@@ -17,7 +17,7 @@ import {
1717 resolveCodexModelForAccount,
1818} from "./codexAppServerManager";
1919
20const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value);
20const asThreadId = (value: string): ThreadId => ThreadId.make(value);
2121
2222function createSendTurnHarness() {
2323 const manager = new CodexAppServerManager();
......@@ -111,9 +111,9 @@ function createPendingUserInputHarness() {
111111 },
112112 pendingUserInputs: new Map([
113113 [
114 ApprovalRequestId.makeUnsafe("req-user-input-1"),
114 ApprovalRequestId.make("req-user-input-1"),
115115 {
116 requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"),
116 requestId: ApprovalRequestId.make("req-user-input-1"),
117117 jsonRpcId: 42,
118118 threadId: asThreadId("thread_1"),
119119 },
......@@ -743,7 +743,7 @@ describe("respondToUserInput", () => {
743743
744744 await manager.respondToUserInput(
745745 asThreadId("thread_1"),
746 ApprovalRequestId.makeUnsafe("req-user-input-1"),
746 ApprovalRequestId.make("req-user-input-1"),
747747 {
748748 scope: "All request methods",
749749 compat: "Keep current envelope",
......@@ -780,7 +780,7 @@ describe("respondToUserInput", () => {
780780
781781 await manager.respondToUserInput(
782782 asThreadId("thread_1"),
783 ApprovalRequestId.makeUnsafe("req-user-input-1"),
783 ApprovalRequestId.make("req-user-input-1"),
784784 {
785785 scope: [],
786786 },
apps/server/src/codexAppServerManager.ts+16-16
......@@ -19,7 +19,7 @@ import {
1919 ProviderInteractionMode,
2020} from "@t3tools/contracts";
2121import { normalizeModelSlug } from "@t3tools/shared/model";
22import { Effect, ServiceMap } from "effect";
22import { Effect, Context } from "effect";
2323
2424import {
2525 formatCodexCliUpgradeMessage,
......@@ -439,7 +439,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
439439 private readonly sessions = new Map<ThreadId, CodexSessionContext>();
440440
441441 private runPromise: (effect: Effect.Effect<unknown, never>) => Promise<unknown>;
442 constructor(services?: ServiceMap.ServiceMap<never>) {
442 constructor(services?: Context.Context<never>) {
443443 super();
444444 this.runPromise = services ? Effect.runPromiseWith(services) : Effect.runPromise;
445445 }
......@@ -640,7 +640,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
640640 this.stopSession(threadId);
641641 } else {
642642 this.emitEvent({
643 id: EventId.makeUnsafe(randomUUID()),
643 id: EventId.make(randomUUID()),
644644 kind: "error",
645645 provider: "codex",
646646 threadId,
......@@ -739,7 +739,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
739739 if (!turnIdRaw) {
740740 throw new Error("turn/start response did not include a turn id.");
741741 }
742 const turnId = TurnId.makeUnsafe(turnIdRaw);
742 const turnId = TurnId.make(turnIdRaw);
743743
744744 this.updateSession(context, {
745745 status: "running",
......@@ -840,7 +840,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
840840 });
841841
842842 this.emitEvent({
843 id: EventId.makeUnsafe(randomUUID()),
843 id: EventId.make(randomUUID()),
844844 kind: "notification",
845845 provider: "codex",
846846 threadId: context.session.threadId,
......@@ -879,7 +879,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
879879 });
880880
881881 this.emitEvent({
882 id: EventId.makeUnsafe(randomUUID()),
882 id: EventId.make(randomUUID()),
883883 kind: "notification",
884884 provider: "codex",
885885 threadId: context.session.threadId,
......@@ -1061,7 +1061,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
10611061 : undefined;
10621062
10631063 this.emitEvent({
1064 id: EventId.makeUnsafe(randomUUID()),
1064 id: EventId.make(randomUUID()),
10651065 kind: "notification",
10661066 provider: "codex",
10671067 threadId: context.session.threadId,
......@@ -1134,7 +1134,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
11341134 const requestKind = this.requestKindForMethod(request.method);
11351135 let requestId: ApprovalRequestId | undefined;
11361136 if (requestKind) {
1137 requestId = ApprovalRequestId.makeUnsafe(randomUUID());
1137 requestId = ApprovalRequestId.make(randomUUID());
11381138 const pendingRequest: PendingApprovalRequest = {
11391139 requestId,
11401140 jsonRpcId: request.id,
......@@ -1153,7 +1153,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
11531153 }
11541154
11551155 if (request.method === "item/tool/requestUserInput") {
1156 requestId = ApprovalRequestId.makeUnsafe(randomUUID());
1156 requestId = ApprovalRequestId.make(randomUUID());
11571157 context.pendingUserInputs.set(requestId, {
11581158 requestId,
11591159 jsonRpcId: request.id,
......@@ -1164,7 +1164,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
11641164 }
11651165
11661166 this.emitEvent({
1167 id: EventId.makeUnsafe(randomUUID()),
1167 id: EventId.make(randomUUID()),
11681168 kind: "request",
11691169 provider: "codex",
11701170 threadId: context.session.threadId,
......@@ -1254,7 +1254,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
12541254
12551255 private emitLifecycleEvent(context: CodexSessionContext, method: string, message: string): void {
12561256 this.emitEvent({
1257 id: EventId.makeUnsafe(randomUUID()),
1257 id: EventId.make(randomUUID()),
12581258 kind: "session",
12591259 provider: "codex",
12601260 threadId: context.session.threadId,
......@@ -1266,7 +1266,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
12661266
12671267 private emitErrorEvent(context: CodexSessionContext, method: string, message: string): void {
12681268 this.emitEvent({
1269 id: EventId.makeUnsafe(randomUUID()),
1269 id: EventId.make(randomUUID()),
12701270 kind: "error",
12711271 provider: "codex",
12721272 threadId: context.session.threadId,
......@@ -1282,7 +1282,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
12821282 message: string,
12831283 ): void {
12841284 this.emitEvent({
1285 id: EventId.makeUnsafe(randomUUID()),
1285 id: EventId.make(randomUUID()),
12861286 kind: "notification",
12871287 provider: "codex",
12881288 threadId: context.session.threadId,
......@@ -1341,7 +1341,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
13411341 const turns = turnsRaw.map((turnValue, index) => {
13421342 const turn = this.readObject(turnValue);
13431343 const turnIdRaw = this.readString(turn, "id") ?? `${threadIdRaw}:turn:${index + 1}`;
1344 const turnId = TurnId.makeUnsafe(turnIdRaw);
1344 const turnId = TurnId.make(turnIdRaw);
13451345 const items = this.readArray(turn, "items") ?? [];
13461346 return {
13471347 id: turnId,
......@@ -1590,9 +1590,9 @@ function readResumeThreadId(input: {
15901590}
15911591
15921592function toTurnId(value: string | undefined): TurnId | undefined {
1593 return brandIfNonEmpty(value, TurnId.makeUnsafe);
1593 return brandIfNonEmpty(value, TurnId.make);
15941594}
15951595
15961596function toProviderItemId(value: string | undefined): ProviderItemId | undefined {
1597 return brandIfNonEmpty(value, ProviderItemId.makeUnsafe);
1597 return brandIfNonEmpty(value, ProviderItemId.make);
15981598}
apps/server/src/config.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module ServerConfig
88 */
9import { Effect, FileSystem, Layer, LogLevel, Path, Schema, ServiceMap } from "effect";
9import { Effect, FileSystem, Layer, LogLevel, Path, Schema, Context } from "effect";
1010
1111export const DEFAULT_PORT = 3773;
1212
......@@ -120,7 +120,7 @@ export const ensureServerDirectories = Effect.fn(function* (derivedPaths: Server
120120/**
121121 * ServerConfig - Service tag for server runtime configuration.
122122 */
123export class ServerConfig extends ServiceMap.Service<ServerConfig, ServerConfigShape>()(
123export class ServerConfig extends Context.Service<ServerConfig, ServerConfigShape>()(
124124 "t3/config/ServerConfig",
125125) {
126126 static readonly layerTest = (cwd: string, baseDirOrPrefix: string | { prefix: string }) =>
apps/server/src/environment/Layers/ServerEnvironment.ts+1-1
......@@ -64,7 +64,7 @@ export const makeServerEnvironment = Effect.fn("makeServerEnvironment")(function
6464 return generated;
6565 });
6666
67 const environmentId = EnvironmentId.makeUnsafe(environmentIdRaw);
67 const environmentId = EnvironmentId.make(environmentIdRaw);
6868 const cwdBaseName = path.basename(serverConfig.cwd).trim();
6969 const label = yield* resolveServerEnvironmentLabel({
7070 cwdBaseName,
apps/server/src/environment/Layers/ServerEnvironmentLabel.ts+7-5
......@@ -51,11 +51,13 @@ const runFriendlyLabelCommand = Effect.fn("runFriendlyLabelCommand")(function* (
5151 command: string,
5252 args: readonly string[],
5353) {
54 const result = yield* Effect.tryPromise(() =>
55 runProcess(command, args, {
56 allowNonZeroExit: true,
57 }),
58 ).pipe(Effect.orElseSucceed(() => null));
54 const result = yield* Effect.tryPromise({
55 try: () =>
56 runProcess(command, args, {
57 allowNonZeroExit: true,
58 }),
59 catch: () => null,
60 }).pipe(Effect.orElseSucceed(() => null));
5961
6062 if (!result || result.code !== 0) {
6163 return null;
apps/server/src/environment/Services/ServerEnvironment.ts+4-5
......@@ -1,5 +1,5 @@
11import type { EnvironmentId, ExecutionEnvironmentDescriptor } from "@t3tools/contracts";
2import { ServiceMap } from "effect";
2import { Context } from "effect";
33import type { Effect } from "effect";
44
55export interface ServerEnvironmentShape {
......@@ -7,7 +7,6 @@ export interface ServerEnvironmentShape {
77 readonly getDescriptor: Effect.Effect<ExecutionEnvironmentDescriptor>;
88}
99
10export class ServerEnvironment extends ServiceMap.Service<
11 ServerEnvironment,
12 ServerEnvironmentShape
13>()("t3/environment/Services/ServerEnvironment") {}
10export class ServerEnvironment extends Context.Service<ServerEnvironment, ServerEnvironmentShape>()(
11 "t3/environment/Services/ServerEnvironment",
12) {}
apps/server/src/git/Layers/GitCore.test.ts+2-2
......@@ -649,8 +649,8 @@ it.layer(TestLayer)("git integration", (it) => {
649649
650650 it.effect("refreshes upstream behind count after checkout when remote branch advanced", () =>
651651 Effect.gen(function* () {
652 const services = yield* Effect.services();
653 const runPromise = Effect.runPromiseWith(services);
652 const context = yield* Effect.context<never>();
653 const runPromise = Effect.runPromiseWith(context);
654654
655655 const remote = yield* makeTmpDir();
656656 const source = yield* makeTmpDir();
apps/server/src/git/Layers/GitCore.ts+1-2
......@@ -933,9 +933,8 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: {
933933 return true as const;
934934 });
935935
936 const statusUpstreamRefreshCache = yield* Cache.makeWith({
936 const statusUpstreamRefreshCache = yield* Cache.makeWith(refreshStatusUpstreamCacheEntry, {
937937 capacity: STATUS_UPSTREAM_REFRESH_CACHE_CAPACITY,
938 lookup: refreshStatusUpstreamCacheEntry,
939938 // Keep successful refreshes warm and briefly back off failed refreshes to avoid retry storms.
940939 timeToLive: (exit) =>
941940 Exit.isSuccess(exit)
apps/server/src/git/Layers/GitManager.ts+2-4
......@@ -731,9 +731,8 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () {
731731 workingTree: details.workingTree,
732732 } satisfies GitStatusLocalResult;
733733 });
734 const localStatusResultCache = yield* Cache.makeWith({
734 const localStatusResultCache = yield* Cache.makeWith(readLocalStatus, {
735735 capacity: STATUS_RESULT_CACHE_CAPACITY,
736 lookup: readLocalStatus,
737736 timeToLive: (exit) => (Exit.isSuccess(exit) ? STATUS_RESULT_CACHE_TTL : Duration.zero),
738737 });
739738 const invalidateLocalStatusResultCache = (cwd: string) =>
......@@ -764,9 +763,8 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () {
764763 pr,
765764 } satisfies GitStatusRemoteResult;
766765 });
767 const remoteStatusResultCache = yield* Cache.makeWith({
766 const remoteStatusResultCache = yield* Cache.makeWith(readRemoteStatus, {
768767 capacity: STATUS_RESULT_CACHE_CAPACITY,
769 lookup: readRemoteStatus,
770768 timeToLive: (exit) => (Exit.isSuccess(exit) ? STATUS_RESULT_CACHE_TTL : Duration.zero),
771769 });
772770 const invalidateRemoteStatusResultCache = (cwd: string) =>
apps/server/src/git/Layers/RoutingTextGeneration.ts+3-3
......@@ -9,7 +9,7 @@
99 *
1010 * @module RoutingTextGeneration
1111 */
12import { Effect, Layer, ServiceMap } from "effect";
12import { Effect, Layer, Context } from "effect";
1313
1414import {
1515 TextGeneration,
......@@ -23,11 +23,11 @@ import { ClaudeTextGenerationLive } from "./ClaudeTextGeneration.ts";
2323// Internal service tags so both concrete layers can coexist.
2424// ---------------------------------------------------------------------------
2525
26class CodexTextGen extends ServiceMap.Service<CodexTextGen, TextGenerationShape>()(
26class CodexTextGen extends Context.Service<CodexTextGen, TextGenerationShape>()(
2727 "t3/git/Layers/RoutingTextGeneration/CodexTextGen",
2828) {}
2929
30class ClaudeTextGen extends ServiceMap.Service<ClaudeTextGen, TextGenerationShape>()(
30class ClaudeTextGen extends Context.Service<ClaudeTextGen, TextGenerationShape>()(
3131 "t3/git/Layers/RoutingTextGeneration/ClaudeTextGen",
3232) {}
3333
apps/server/src/git/Services/GitCore.ts+2-4
......@@ -6,7 +6,7 @@
66 *
77 * @module GitCore
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect } from "effect";
1111import type {
1212 GitCheckoutInput,
......@@ -310,6 +310,4 @@ export interface GitCoreShape {
310310/**
311311 * GitCore - Service tag for low-level Git repository operations.
312312 */
313export class GitCore extends ServiceMap.Service<GitCore, GitCoreShape>()(
314 "t3/git/Services/GitCore",
315) {}
313export class GitCore extends Context.Service<GitCore, GitCoreShape>()("t3/git/Services/GitCore") {}
apps/server/src/git/Services/GitHubCli.ts+2-2
......@@ -5,7 +5,7 @@
55 *
66 * @module GitHubCli
77 */
8import { ServiceMap } from "effect";
8import { Context } from "effect";
99import type { Effect } from "effect";
1010
1111import type { ProcessRunResult } from "../../processRunner";
......@@ -98,6 +98,6 @@ export interface GitHubCliShape {
9898/**
9999 * GitHubCli - Service tag for GitHub CLI process execution.
100100 */
101export class GitHubCli extends ServiceMap.Service<GitHubCli, GitHubCliShape>()(
101export class GitHubCli extends Context.Service<GitHubCli, GitHubCliShape>()(
102102 "t3/git/Services/GitHubCli",
103103) {}
apps/server/src/git/Services/GitManager.ts+2-2
......@@ -19,7 +19,7 @@ import {
1919 GitStatusInput,
2020 GitStatusResult,
2121} from "@t3tools/contracts";
22import { ServiceMap } from "effect";
22import { Context } from "effect";
2323import type { Effect } from "effect";
2424import type { GitManagerServiceError } from "@t3tools/contracts";
2525
......@@ -99,6 +99,6 @@ export interface GitManagerShape {
9999/**
100100 * GitManager - Service tag for stacked Git workflow orchestration.
101101 */
102export class GitManager extends ServiceMap.Service<GitManager, GitManagerShape>()(
102export class GitManager extends Context.Service<GitManager, GitManagerShape>()(
103103 "t3/git/Services/GitManager",
104104) {}
apps/server/src/git/Services/GitStatusBroadcaster.ts+2-2
......@@ -1,4 +1,4 @@
1import { ServiceMap } from "effect";
1import { Context } from "effect";
22import type { Effect, Stream } from "effect";
33import type {
44 GitManagerServiceError,
......@@ -21,7 +21,7 @@ export interface GitStatusBroadcasterShape {
2121 ) => Stream.Stream<GitStatusStreamEvent, GitManagerServiceError>;
2222}
2323
24export class GitStatusBroadcaster extends ServiceMap.Service<
24export class GitStatusBroadcaster extends Context.Service<
2525 GitStatusBroadcaster,
2626 GitStatusBroadcasterShape
2727>()("t3/git/Services/GitStatusBroadcaster") {}
apps/server/src/git/Services/TextGeneration.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module TextGeneration
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect } from "effect";
1111import type { ChatAttachment, ModelSelection } from "@t3tools/contracts";
1212
......@@ -118,6 +118,6 @@ export interface TextGenerationShape {
118118/**
119119 * TextGeneration - Service tag for commit and PR text generation.
120120 */
121export class TextGeneration extends ServiceMap.Service<TextGeneration, TextGenerationShape>()(
121export class TextGeneration extends Context.Service<TextGeneration, TextGenerationShape>()(
122122 "t3/git/Services/TextGeneration",
123123) {}
apps/server/src/keybindings.ts+2-2
......@@ -39,7 +39,7 @@ import {
3939 SchemaIssue,
4040 SchemaTransformation,
4141 Ref,
42 ServiceMap,
42 Context,
4343 Scope,
4444 Stream,
4545} from "effect";
......@@ -521,7 +521,7 @@ export interface KeybindingsShape {
521521/**
522522 * Keybindings - Service tag for keybinding configuration operations.
523523 */
524export class Keybindings extends ServiceMap.Service<Keybindings, KeybindingsShape>()(
524export class Keybindings extends Context.Service<Keybindings, KeybindingsShape>()(
525525 "t3/keybindings",
526526) {}
527527
apps/server/src/observability/Services/BrowserTraceCollector.ts+2-2
......@@ -1,4 +1,4 @@
1import { ServiceMap } from "effect";
1import { Context } from "effect";
22import type { Effect } from "effect";
33
44import type { TraceRecord } from "../TraceRecord.ts";
......@@ -7,7 +7,7 @@ export interface BrowserTraceCollectorShape {
77 readonly record: (records: ReadonlyArray<TraceRecord>) => Effect.Effect<void>;
88}
99
10export class BrowserTraceCollector extends ServiceMap.Service<
10export class BrowserTraceCollector extends Context.Service<
1111 BrowserTraceCollector,
1212 BrowserTraceCollectorShape
1313>()("t3/observability/Services/BrowserTraceCollector") {}
apps/server/src/open.ts+2-2
......@@ -11,7 +11,7 @@ import { accessSync, constants, statSync } from "node:fs";
1111import { extname, join } from "node:path";
1212
1313import { EDITORS, OpenError, type EditorId } from "@t3tools/contracts";
14import { ServiceMap, Effect, Layer } from "effect";
14import { Context, Effect, Layer } from "effect";
1515
1616// ==============================
1717// Definitions
......@@ -247,7 +247,7 @@ export interface OpenShape {
247247/**
248248 * Open - Service tag for browser/editor launch operations.
249249 */
250export class Open extends ServiceMap.Service<Open, OpenShape>()("t3/open") {}
250export class Open extends Context.Service<Open, OpenShape>()("t3/open") {}
251251
252252// ==============================
253253// Implementations
apps/server/src/orchestration/Layers/CheckpointReactor.test.ts+118-120
......@@ -44,8 +44,8 @@ import { ServerConfig } from "../../config.ts";
4444import { WorkspaceEntriesLive } from "../../workspace/Layers/WorkspaceEntries.ts";
4545import { WorkspacePathsLive } from "../../workspace/Layers/WorkspacePaths.ts";
4646
47const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
48const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
47const asProjectId = (value: string): ProjectId => ProjectId.make(value);
48const asTurnId = (value: string): TurnId => TurnId.make(value);
4949
5050type LegacyProviderRuntimeEvent = {
5151 readonly type: string;
......@@ -81,7 +81,7 @@ function createProviderServiceHarness(
8181 provider: providerName,
8282 status: "ready",
8383 runtimeMode: "full-access",
84 threadId: ThreadId.makeUnsafe("thread-1"),
84 threadId: ThreadId.make("thread-1"),
8585 cwd: sessionCwd,
8686 createdAt: now,
8787 updatedAt: now,
......@@ -130,7 +130,7 @@ async function waitForThread(
130130 activities: ReadonlyArray<{ kind: string }>;
131131 }> => {
132132 const readModel = await Effect.runPromise(engine.getReadModel());
133 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
133 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
134134 if (thread && predicate(thread)) {
135135 return thread;
136136 }
......@@ -310,7 +310,7 @@ describe("CheckpointReactor", () => {
310310 await Effect.runPromise(
311311 engine.dispatch({
312312 type: "project.create",
313 commandId: CommandId.makeUnsafe("cmd-project-create"),
313 commandId: CommandId.make("cmd-project-create"),
314314 projectId: asProjectId("project-1"),
315315 title: "Test Project",
316316 workspaceRoot: options?.projectWorkspaceRoot ?? cwd,
......@@ -324,8 +324,8 @@ describe("CheckpointReactor", () => {
324324 await Effect.runPromise(
325325 engine.dispatch({
326326 type: "thread.create",
327 commandId: CommandId.makeUnsafe("cmd-thread-create"),
328 threadId: ThreadId.makeUnsafe("thread-1"),
327 commandId: CommandId.make("cmd-thread-create"),
328 threadId: ThreadId.make("thread-1"),
329329 projectId: asProjectId("project-1"),
330330 title: "Thread",
331331 modelSelection: {
......@@ -344,21 +344,21 @@ describe("CheckpointReactor", () => {
344344 await runtime.runPromise(
345345 checkpointStore.captureCheckpoint({
346346 cwd,
347 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
347 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
348348 }),
349349 );
350350 fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8");
351351 await runtime.runPromise(
352352 checkpointStore.captureCheckpoint({
353353 cwd,
354 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1),
354 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1),
355355 }),
356356 );
357357 fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8");
358358 await runtime.runPromise(
359359 checkpointStore.captureCheckpoint({
360360 cwd,
361 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2),
361 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2),
362362 }),
363363 );
364364 }
......@@ -378,10 +378,10 @@ describe("CheckpointReactor", () => {
378378 await Effect.runPromise(
379379 harness.engine.dispatch({
380380 type: "thread.session.set",
381 commandId: CommandId.makeUnsafe("cmd-session-set-capture"),
382 threadId: ThreadId.makeUnsafe("thread-1"),
381 commandId: CommandId.make("cmd-session-set-capture"),
382 threadId: ThreadId.make("thread-1"),
383383 session: {
384 threadId: ThreadId.makeUnsafe("thread-1"),
384 threadId: ThreadId.make("thread-1"),
385385 status: "ready",
386386 providerName: "codex",
387387 runtimeMode: "approval-required",
......@@ -395,26 +395,26 @@ describe("CheckpointReactor", () => {
395395
396396 harness.provider.emit({
397397 type: "turn.started",
398 eventId: EventId.makeUnsafe("evt-turn-started-1"),
398 eventId: EventId.make("evt-turn-started-1"),
399399 provider: "codex",
400400
401401 createdAt: new Date().toISOString(),
402 threadId: ThreadId.makeUnsafe("thread-1"),
402 threadId: ThreadId.make("thread-1"),
403403 turnId: asTurnId("turn-1"),
404404 });
405405 await waitForGitRefExists(
406406 harness.cwd,
407 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
407 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
408408 );
409409
410410 fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8");
411411 harness.provider.emit({
412412 type: "turn.completed",
413 eventId: EventId.makeUnsafe("evt-turn-completed-1"),
413 eventId: EventId.make("evt-turn-completed-1"),
414414 provider: "codex",
415415
416416 createdAt: new Date().toISOString(),
417 threadId: ThreadId.makeUnsafe("thread-1"),
417 threadId: ThreadId.make("thread-1"),
418418 turnId: asTurnId("turn-1"),
419419 payload: { state: "completed" },
420420 });
......@@ -426,22 +426,22 @@ describe("CheckpointReactor", () => {
426426 );
427427 expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1);
428428 expect(
429 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0)),
429 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0)),
430430 ).toBe(true);
431431 expect(
432 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1)),
432 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1)),
433433 ).toBe(true);
434434 expect(
435435 gitShowFileAtRef(
436436 harness.cwd,
437 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
437 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
438438 "README.md",
439439 ),
440440 ).toBe("v1\n");
441441 expect(
442442 gitShowFileAtRef(
443443 harness.cwd,
444 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1),
444 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1),
445445 "README.md",
446446 ),
447447 ).toBe("v2\n");
......@@ -456,10 +456,10 @@ describe("CheckpointReactor", () => {
456456
457457 harness.provider.emit({
458458 type: "turn.completed",
459 eventId: EventId.makeUnsafe("evt-turn-completed-refresh-local-status"),
459 eventId: EventId.make("evt-turn-completed-refresh-local-status"),
460460 provider: "codex",
461461 createdAt: new Date().toISOString(),
462 threadId: ThreadId.makeUnsafe("thread-1"),
462 threadId: ThreadId.make("thread-1"),
463463 turnId: asTurnId("turn-refresh-local-status"),
464464 payload: { state: "completed" },
465465 });
......@@ -476,10 +476,10 @@ describe("CheckpointReactor", () => {
476476 await Effect.runPromise(
477477 harness.engine.dispatch({
478478 type: "thread.session.set",
479 commandId: CommandId.makeUnsafe("cmd-session-set-primary-running"),
480 threadId: ThreadId.makeUnsafe("thread-1"),
479 commandId: CommandId.make("cmd-session-set-primary-running"),
480 threadId: ThreadId.make("thread-1"),
481481 session: {
482 threadId: ThreadId.makeUnsafe("thread-1"),
482 threadId: ThreadId.make("thread-1"),
483483 status: "running",
484484 providerName: "codex",
485485 runtimeMode: "approval-required",
......@@ -493,45 +493,43 @@ describe("CheckpointReactor", () => {
493493
494494 harness.provider.emit({
495495 type: "turn.started",
496 eventId: EventId.makeUnsafe("evt-turn-started-main"),
496 eventId: EventId.make("evt-turn-started-main"),
497497 provider: "codex",
498498
499499 createdAt: new Date().toISOString(),
500 threadId: ThreadId.makeUnsafe("thread-1"),
500 threadId: ThreadId.make("thread-1"),
501501 turnId: asTurnId("turn-main"),
502502 });
503503 await waitForGitRefExists(
504504 harness.cwd,
505 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
505 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
506506 );
507507
508508 fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8");
509509
510510 harness.provider.emit({
511511 type: "turn.completed",
512 eventId: EventId.makeUnsafe("evt-turn-completed-aux"),
512 eventId: EventId.make("evt-turn-completed-aux"),
513513 provider: "codex",
514514
515515 createdAt: new Date().toISOString(),
516 threadId: ThreadId.makeUnsafe("thread-1"),
516 threadId: ThreadId.make("thread-1"),
517517 turnId: asTurnId("turn-aux"),
518518 payload: { state: "completed" },
519519 });
520520
521521 await harness.drain();
522522 const midReadModel = await Effect.runPromise(harness.engine.getReadModel());
523 const midThread = midReadModel.threads.find(
524 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
525 );
523 const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
526524 expect(midThread?.checkpoints).toHaveLength(0);
527525
528526 harness.provider.emit({
529527 type: "turn.completed",
530 eventId: EventId.makeUnsafe("evt-turn-completed-main"),
528 eventId: EventId.make("evt-turn-completed-main"),
531529 provider: "codex",
532530
533531 createdAt: new Date().toISOString(),
534 threadId: ThreadId.makeUnsafe("thread-1"),
532 threadId: ThreadId.make("thread-1"),
535533 turnId: asTurnId("turn-main"),
536534 payload: { state: "completed" },
537535 });
......@@ -553,10 +551,10 @@ describe("CheckpointReactor", () => {
553551 await Effect.runPromise(
554552 harness.engine.dispatch({
555553 type: "thread.session.set",
556 commandId: CommandId.makeUnsafe("cmd-session-set-capture-claude"),
557 threadId: ThreadId.makeUnsafe("thread-1"),
554 commandId: CommandId.make("cmd-session-set-capture-claude"),
555 threadId: ThreadId.make("thread-1"),
558556 session: {
559 threadId: ThreadId.makeUnsafe("thread-1"),
557 threadId: ThreadId.make("thread-1"),
560558 status: "ready",
561559 providerName: "claudeAgent",
562560 runtimeMode: "approval-required",
......@@ -570,24 +568,24 @@ describe("CheckpointReactor", () => {
570568
571569 harness.provider.emit({
572570 type: "turn.started",
573 eventId: EventId.makeUnsafe("evt-turn-started-claude-1"),
571 eventId: EventId.make("evt-turn-started-claude-1"),
574572 provider: "claudeAgent",
575573 createdAt: new Date().toISOString(),
576 threadId: ThreadId.makeUnsafe("thread-1"),
574 threadId: ThreadId.make("thread-1"),
577575 turnId: asTurnId("turn-claude-1"),
578576 });
579577 await waitForGitRefExists(
580578 harness.cwd,
581 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
579 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
582580 );
583581
584582 fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8");
585583 harness.provider.emit({
586584 type: "turn.completed",
587 eventId: EventId.makeUnsafe("evt-turn-completed-claude-1"),
585 eventId: EventId.make("evt-turn-completed-claude-1"),
588586 provider: "claudeAgent",
589587 createdAt: new Date().toISOString(),
590 threadId: ThreadId.makeUnsafe("thread-1"),
588 threadId: ThreadId.make("thread-1"),
591589 turnId: asTurnId("turn-claude-1"),
592590 payload: { state: "completed" },
593591 });
......@@ -600,7 +598,7 @@ describe("CheckpointReactor", () => {
600598
601599 expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1);
602600 expect(
603 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1)),
601 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1)),
604602 ).toBe(true);
605603 });
606604
......@@ -611,10 +609,10 @@ describe("CheckpointReactor", () => {
611609 await Effect.runPromise(
612610 harness.engine.dispatch({
613611 type: "thread.session.set",
614 commandId: CommandId.makeUnsafe("cmd-session-set-missing-baseline-diff"),
615 threadId: ThreadId.makeUnsafe("thread-1"),
612 commandId: CommandId.make("cmd-session-set-missing-baseline-diff"),
613 threadId: ThreadId.make("thread-1"),
616614 session: {
617 threadId: ThreadId.makeUnsafe("thread-1"),
615 threadId: ThreadId.make("thread-1"),
618616 status: "ready",
619617 providerName: "codex",
620618 runtimeMode: "approval-required",
......@@ -628,11 +626,11 @@ describe("CheckpointReactor", () => {
628626
629627 harness.provider.emit({
630628 type: "turn.completed",
631 eventId: EventId.makeUnsafe("evt-turn-completed-missing-baseline"),
629 eventId: EventId.make("evt-turn-completed-missing-baseline"),
632630 provider: "codex",
633631
634632 createdAt: new Date().toISOString(),
635 threadId: ThreadId.makeUnsafe("thread-1"),
633 threadId: ThreadId.make("thread-1"),
636634 turnId: asTurnId("turn-missing-baseline"),
637635 payload: { state: "completed" },
638636 });
......@@ -661,10 +659,10 @@ describe("CheckpointReactor", () => {
661659 await Effect.runPromise(
662660 harness.engine.dispatch({
663661 type: "thread.turn.start",
664 commandId: CommandId.makeUnsafe("cmd-turn-start-for-baseline"),
665 threadId: ThreadId.makeUnsafe("thread-1"),
662 commandId: CommandId.make("cmd-turn-start-for-baseline"),
663 threadId: ThreadId.make("thread-1"),
666664 message: {
667 messageId: MessageId.makeUnsafe("message-user-1"),
665 messageId: MessageId.make("message-user-1"),
668666 role: "user",
669667 text: "start turn",
670668 attachments: [],
......@@ -677,12 +675,12 @@ describe("CheckpointReactor", () => {
677675
678676 await waitForGitRefExists(
679677 harness.cwd,
680 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
678 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
681679 );
682680 expect(
683681 gitShowFileAtRef(
684682 harness.cwd,
685 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
683 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
686684 "README.md",
687685 ),
688686 ).toBe("v1\n");
......@@ -699,10 +697,10 @@ describe("CheckpointReactor", () => {
699697 await Effect.runPromise(
700698 harness.engine.dispatch({
701699 type: "thread.session.set",
702 commandId: CommandId.makeUnsafe("cmd-session-set-missing-provider-cwd"),
703 threadId: ThreadId.makeUnsafe("thread-1"),
700 commandId: CommandId.make("cmd-session-set-missing-provider-cwd"),
701 threadId: ThreadId.make("thread-1"),
704702 session: {
705 threadId: ThreadId.makeUnsafe("thread-1"),
703 threadId: ThreadId.make("thread-1"),
706704 status: "running",
707705 providerName: "codex",
708706 runtimeMode: "approval-required",
......@@ -717,23 +715,23 @@ describe("CheckpointReactor", () => {
717715 fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8");
718716 harness.provider.emit({
719717 type: "turn.completed",
720 eventId: EventId.makeUnsafe("evt-turn-completed-missing-provider-cwd"),
718 eventId: EventId.make("evt-turn-completed-missing-provider-cwd"),
721719 provider: "codex",
722720
723721 createdAt: new Date().toISOString(),
724 threadId: ThreadId.makeUnsafe("thread-1"),
722 threadId: ThreadId.make("thread-1"),
725723 turnId: asTurnId("turn-missing-cwd"),
726724 payload: { state: "completed" },
727725 });
728726
729727 await waitForEvent(harness.engine, (event) => event.type === "thread.turn-diff-completed");
730728 expect(
731 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1)),
729 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1)),
732730 ).toBe(true);
733731 expect(
734732 gitShowFileAtRef(
735733 harness.cwd,
736 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1),
734 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1),
737735 "README.md",
738736 ),
739737 ).toBe("v2\n");
......@@ -746,10 +744,10 @@ describe("CheckpointReactor", () => {
746744 await Effect.runPromise(
747745 harness.engine.dispatch({
748746 type: "thread.session.set",
749 commandId: CommandId.makeUnsafe("cmd-session-set-checkpoint-captured"),
750 threadId: ThreadId.makeUnsafe("thread-1"),
747 commandId: CommandId.make("cmd-session-set-checkpoint-captured"),
748 threadId: ThreadId.make("thread-1"),
751749 session: {
752 threadId: ThreadId.makeUnsafe("thread-1"),
750 threadId: ThreadId.make("thread-1"),
753751 status: "ready",
754752 providerName: "codex",
755753 runtimeMode: "approval-required",
......@@ -763,11 +761,11 @@ describe("CheckpointReactor", () => {
763761
764762 harness.provider.emit({
765763 type: "checkpoint.captured",
766 eventId: EventId.makeUnsafe("evt-checkpoint-captured-3"),
764 eventId: EventId.make("evt-checkpoint-captured-3"),
767765 provider: "codex",
768766
769767 createdAt: new Date().toISOString(),
770 threadId: ThreadId.makeUnsafe("thread-1"),
768 threadId: ThreadId.make("thread-1"),
771769 turnId: asTurnId("turn-3"),
772770 turnCount: 3,
773771 status: "completed",
......@@ -775,7 +773,7 @@ describe("CheckpointReactor", () => {
775773
776774 await harness.drain();
777775 const readModel = await Effect.runPromise(harness.engine.getReadModel());
778 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
776 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
779777 expect(thread?.checkpoints.some((checkpoint) => checkpoint.checkpointTurnCount === 3)).toBe(
780778 false,
781779 );
......@@ -796,10 +794,10 @@ describe("CheckpointReactor", () => {
796794 await Effect.runPromise(
797795 harness.engine.dispatch({
798796 type: "thread.session.set",
799 commandId: CommandId.makeUnsafe("cmd-session-set-non-repo-runtime"),
800 threadId: ThreadId.makeUnsafe("thread-1"),
797 commandId: CommandId.make("cmd-session-set-non-repo-runtime"),
798 threadId: ThreadId.make("thread-1"),
801799 session: {
802 threadId: ThreadId.makeUnsafe("thread-1"),
800 threadId: ThreadId.make("thread-1"),
803801 status: "ready",
804802 providerName: "codex",
805803 runtimeMode: "approval-required",
......@@ -813,31 +811,31 @@ describe("CheckpointReactor", () => {
813811
814812 harness.provider.emit({
815813 type: "turn.completed",
816 eventId: EventId.makeUnsafe("evt-runtime-capture-failure"),
814 eventId: EventId.make("evt-runtime-capture-failure"),
817815 provider: "codex",
818816
819817 createdAt: new Date().toISOString(),
820 threadId: ThreadId.makeUnsafe("thread-1"),
818 threadId: ThreadId.make("thread-1"),
821819 turnId: asTurnId("turn-runtime-failure"),
822820 payload: { state: "completed" },
823821 });
824822
825823 harness.provider.emit({
826824 type: "turn.started",
827 eventId: EventId.makeUnsafe("evt-turn-started-after-runtime-failure"),
825 eventId: EventId.make("evt-turn-started-after-runtime-failure"),
828826 provider: "codex",
829827
830828 createdAt: new Date().toISOString(),
831 threadId: ThreadId.makeUnsafe("thread-1"),
829 threadId: ThreadId.make("thread-1"),
832830 turnId: asTurnId("turn-after-runtime-failure"),
833831 });
834832
835833 await waitForGitRefExists(
836834 harness.cwd,
837 checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0),
835 checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0),
838836 );
839837 expect(
840 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0)),
838 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0)),
841839 ).toBe(true);
842840 });
843841
......@@ -848,10 +846,10 @@ describe("CheckpointReactor", () => {
848846 await Effect.runPromise(
849847 harness.engine.dispatch({
850848 type: "thread.session.set",
851 commandId: CommandId.makeUnsafe("cmd-session-set"),
852 threadId: ThreadId.makeUnsafe("thread-1"),
849 commandId: CommandId.make("cmd-session-set"),
850 threadId: ThreadId.make("thread-1"),
853851 session: {
854 threadId: ThreadId.makeUnsafe("thread-1"),
852 threadId: ThreadId.make("thread-1"),
855853 status: "ready",
856854 providerName: "codex",
857855 runtimeMode: "approval-required",
......@@ -866,11 +864,11 @@ describe("CheckpointReactor", () => {
866864 await Effect.runPromise(
867865 harness.engine.dispatch({
868866 type: "thread.turn.diff.complete",
869 commandId: CommandId.makeUnsafe("cmd-diff-1"),
870 threadId: ThreadId.makeUnsafe("thread-1"),
867 commandId: CommandId.make("cmd-diff-1"),
868 threadId: ThreadId.make("thread-1"),
871869 turnId: asTurnId("turn-1"),
872870 completedAt: createdAt,
873 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1),
871 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1),
874872 status: "ready",
875873 files: [],
876874 checkpointTurnCount: 1,
......@@ -880,11 +878,11 @@ describe("CheckpointReactor", () => {
880878 await Effect.runPromise(
881879 harness.engine.dispatch({
882880 type: "thread.turn.diff.complete",
883 commandId: CommandId.makeUnsafe("cmd-diff-2"),
884 threadId: ThreadId.makeUnsafe("thread-1"),
881 commandId: CommandId.make("cmd-diff-2"),
882 threadId: ThreadId.make("thread-1"),
885883 turnId: asTurnId("turn-2"),
886884 completedAt: createdAt,
887 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2),
885 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2),
888886 status: "ready",
889887 files: [],
890888 checkpointTurnCount: 2,
......@@ -895,8 +893,8 @@ describe("CheckpointReactor", () => {
895893 await Effect.runPromise(
896894 harness.engine.dispatch({
897895 type: "thread.checkpoint.revert",
898 commandId: CommandId.makeUnsafe("cmd-revert-request"),
899 threadId: ThreadId.makeUnsafe("thread-1"),
896 commandId: CommandId.make("cmd-revert-request"),
897 threadId: ThreadId.make("thread-1"),
900898 turnCount: 1,
901899 createdAt,
902900 }),
......@@ -910,12 +908,12 @@ describe("CheckpointReactor", () => {
910908 expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1);
911909 expect(harness.provider.rollbackConversation).toHaveBeenCalledTimes(1);
912910 expect(harness.provider.rollbackConversation).toHaveBeenCalledWith({
913 threadId: ThreadId.makeUnsafe("thread-1"),
911 threadId: ThreadId.make("thread-1"),
914912 numTurns: 1,
915913 });
916914 expect(fs.readFileSync(path.join(harness.cwd, "README.md"), "utf8")).toBe("v2\n");
917915 expect(
918 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2)),
916 gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2)),
919917 ).toBe(false);
920918 });
921919
......@@ -926,10 +924,10 @@ describe("CheckpointReactor", () => {
926924 await Effect.runPromise(
927925 harness.engine.dispatch({
928926 type: "thread.session.set",
929 commandId: CommandId.makeUnsafe("cmd-session-set-claude"),
930 threadId: ThreadId.makeUnsafe("thread-1"),
927 commandId: CommandId.make("cmd-session-set-claude"),
928 threadId: ThreadId.make("thread-1"),
931929 session: {
932 threadId: ThreadId.makeUnsafe("thread-1"),
930 threadId: ThreadId.make("thread-1"),
933931 status: "ready",
934932 providerName: "claudeAgent",
935933 runtimeMode: "approval-required",
......@@ -944,11 +942,11 @@ describe("CheckpointReactor", () => {
944942 await Effect.runPromise(
945943 harness.engine.dispatch({
946944 type: "thread.turn.diff.complete",
947 commandId: CommandId.makeUnsafe("cmd-diff-claude-1"),
948 threadId: ThreadId.makeUnsafe("thread-1"),
945 commandId: CommandId.make("cmd-diff-claude-1"),
946 threadId: ThreadId.make("thread-1"),
949947 turnId: asTurnId("turn-claude-1"),
950948 completedAt: createdAt,
951 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1),
949 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1),
952950 status: "ready",
953951 files: [],
954952 checkpointTurnCount: 1,
......@@ -958,11 +956,11 @@ describe("CheckpointReactor", () => {
958956 await Effect.runPromise(
959957 harness.engine.dispatch({
960958 type: "thread.turn.diff.complete",
961 commandId: CommandId.makeUnsafe("cmd-diff-claude-2"),
962 threadId: ThreadId.makeUnsafe("thread-1"),
959 commandId: CommandId.make("cmd-diff-claude-2"),
960 threadId: ThreadId.make("thread-1"),
963961 turnId: asTurnId("turn-claude-2"),
964962 completedAt: createdAt,
965 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2),
963 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2),
966964 status: "ready",
967965 files: [],
968966 checkpointTurnCount: 2,
......@@ -973,8 +971,8 @@ describe("CheckpointReactor", () => {
973971 await Effect.runPromise(
974972 harness.engine.dispatch({
975973 type: "thread.checkpoint.revert",
976 commandId: CommandId.makeUnsafe("cmd-revert-request-claude"),
977 threadId: ThreadId.makeUnsafe("thread-1"),
974 commandId: CommandId.make("cmd-revert-request-claude"),
975 threadId: ThreadId.make("thread-1"),
978976 turnCount: 1,
979977 createdAt,
980978 }),
......@@ -983,7 +981,7 @@ describe("CheckpointReactor", () => {
983981 await waitForEvent(harness.engine, (event) => event.type === "thread.reverted");
984982 expect(harness.provider.rollbackConversation).toHaveBeenCalledTimes(1);
985983 expect(harness.provider.rollbackConversation).toHaveBeenCalledWith({
986 threadId: ThreadId.makeUnsafe("thread-1"),
984 threadId: ThreadId.make("thread-1"),
987985 numTurns: 1,
988986 });
989987 });
......@@ -995,10 +993,10 @@ describe("CheckpointReactor", () => {
995993 await Effect.runPromise(
996994 harness.engine.dispatch({
997995 type: "thread.session.set",
998 commandId: CommandId.makeUnsafe("cmd-session-set-inline-revert"),
999 threadId: ThreadId.makeUnsafe("thread-1"),
996 commandId: CommandId.make("cmd-session-set-inline-revert"),
997 threadId: ThreadId.make("thread-1"),
1000998 session: {
1001 threadId: ThreadId.makeUnsafe("thread-1"),
999 threadId: ThreadId.make("thread-1"),
10021000 status: "ready",
10031001 providerName: "codex",
10041002 runtimeMode: "approval-required",
......@@ -1013,11 +1011,11 @@ describe("CheckpointReactor", () => {
10131011 await Effect.runPromise(
10141012 harness.engine.dispatch({
10151013 type: "thread.turn.diff.complete",
1016 commandId: CommandId.makeUnsafe("cmd-inline-revert-diff-1"),
1017 threadId: ThreadId.makeUnsafe("thread-1"),
1014 commandId: CommandId.make("cmd-inline-revert-diff-1"),
1015 threadId: ThreadId.make("thread-1"),
10181016 turnId: asTurnId("turn-1"),
10191017 completedAt: createdAt,
1020 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1),
1018 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1),
10211019 status: "ready",
10221020 files: [],
10231021 checkpointTurnCount: 1,
......@@ -1027,11 +1025,11 @@ describe("CheckpointReactor", () => {
10271025 await Effect.runPromise(
10281026 harness.engine.dispatch({
10291027 type: "thread.turn.diff.complete",
1030 commandId: CommandId.makeUnsafe("cmd-inline-revert-diff-2"),
1031 threadId: ThreadId.makeUnsafe("thread-1"),
1028 commandId: CommandId.make("cmd-inline-revert-diff-2"),
1029 threadId: ThreadId.make("thread-1"),
10321030 turnId: asTurnId("turn-2"),
10331031 completedAt: createdAt,
1034 checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2),
1032 checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2),
10351033 status: "ready",
10361034 files: [],
10371035 checkpointTurnCount: 2,
......@@ -1042,8 +1040,8 @@ describe("CheckpointReactor", () => {
10421040 await Effect.runPromise(
10431041 harness.engine.dispatch({
10441042 type: "thread.checkpoint.revert",
1045 commandId: CommandId.makeUnsafe("cmd-sequenced-revert-request-1"),
1046 threadId: ThreadId.makeUnsafe("thread-1"),
1043 commandId: CommandId.make("cmd-sequenced-revert-request-1"),
1044 threadId: ThreadId.make("thread-1"),
10471045 turnCount: 1,
10481046 createdAt,
10491047 }),
......@@ -1051,8 +1049,8 @@ describe("CheckpointReactor", () => {
10511049 await Effect.runPromise(
10521050 harness.engine.dispatch({
10531051 type: "thread.checkpoint.revert",
1054 commandId: CommandId.makeUnsafe("cmd-sequenced-revert-request-0"),
1055 threadId: ThreadId.makeUnsafe("thread-1"),
1052 commandId: CommandId.make("cmd-sequenced-revert-request-0"),
1053 threadId: ThreadId.make("thread-1"),
10561054 turnCount: 0,
10571055 createdAt,
10581056 }),
......@@ -1062,11 +1060,11 @@ describe("CheckpointReactor", () => {
10621060
10631061 expect(harness.provider.rollbackConversation).toHaveBeenCalledTimes(2);
10641062 expect(harness.provider.rollbackConversation.mock.calls[0]?.[0]).toEqual({
1065 threadId: ThreadId.makeUnsafe("thread-1"),
1063 threadId: ThreadId.make("thread-1"),
10661064 numTurns: 1,
10671065 });
10681066 expect(harness.provider.rollbackConversation.mock.calls[1]?.[0]).toEqual({
1069 threadId: ThreadId.makeUnsafe("thread-1"),
1067 threadId: ThreadId.make("thread-1"),
10701068 numTurns: 1,
10711069 });
10721070 });
......@@ -1078,8 +1076,8 @@ describe("CheckpointReactor", () => {
10781076 await Effect.runPromise(
10791077 harness.engine.dispatch({
10801078 type: "thread.checkpoint.revert",
1081 commandId: CommandId.makeUnsafe("cmd-revert-no-session"),
1082 threadId: ThreadId.makeUnsafe("thread-1"),
1079 commandId: CommandId.make("cmd-revert-no-session"),
1080 threadId: ThreadId.make("thread-1"),
10831081 turnCount: 1,
10841082 createdAt,
10851083 }),
apps/server/src/orchestration/Layers/CheckpointReactor.ts+6-6
......@@ -38,7 +38,7 @@ type ReactorInput =
3838 };
3939
4040function toTurnId(value: string | undefined): TurnId | null {
41 return value === undefined ? null : TurnId.makeUnsafe(String(value));
41 return value === undefined ? null : TurnId.make(String(value));
4242}
4343
4444function sameId(left: string | null | undefined, right: string | null | undefined): boolean {
......@@ -62,7 +62,7 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis
6262}
6363
6464const serverCommandId = (tag: string): CommandId =>
65 CommandId.makeUnsafe(`server:${tag}:${crypto.randomUUID()}`);
65 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);
6666
6767const make = Effect.gen(function* () {
6868 const orchestrationEngine = yield* OrchestrationEngineService;
......@@ -83,7 +83,7 @@ const make = Effect.gen(function* () {
8383 commandId: serverCommandId("checkpoint-revert-failure"),
8484 threadId: input.threadId,
8585 activity: {
86 id: EventId.makeUnsafe(crypto.randomUUID()),
86 id: EventId.make(crypto.randomUUID()),
8787 tone: "error",
8888 kind: "checkpoint.revert.failed",
8989 summary: "Checkpoint revert failed",
......@@ -108,7 +108,7 @@ const make = Effect.gen(function* () {
108108 commandId: serverCommandId("checkpoint-capture-failure"),
109109 threadId: input.threadId,
110110 activity: {
111 id: EventId.makeUnsafe(crypto.randomUUID()),
111 id: EventId.make(crypto.randomUUID()),
112112 tone: "error",
113113 kind: "checkpoint.capture.failed",
114114 summary: "Checkpoint capture failed",
......@@ -270,7 +270,7 @@ const make = Effect.gen(function* () {
270270 input.thread.messages
271271 .toReversed()
272272 .find((entry) => entry.role === "assistant" && entry.turnId === input.turnId)?.id ??
273 MessageId.makeUnsafe(`assistant:${input.turnId}`);
273 MessageId.make(`assistant:${input.turnId}`);
274274
275275 yield* orchestrationEngine.dispatch({
276276 type: "thread.turn.diff.complete",
......@@ -307,7 +307,7 @@ const make = Effect.gen(function* () {
307307 commandId: serverCommandId("checkpoint-captured-activity"),
308308 threadId: input.threadId,
309309 activity: {
310 id: EventId.makeUnsafe(crypto.randomUUID()),
310 id: EventId.make(crypto.randomUUID()),
311311 tone: "info",
312312 kind: "checkpoint.captured",
313313 summary: "Checkpoint captured",
apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts+62-62
......@@ -32,10 +32,10 @@ import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts"
3232import { ServerConfig } from "../../config.ts";
3333import * as NodeServices from "@effect/platform-node/NodeServices";
3434
35const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
36const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
37const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
38const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.makeUnsafe(value);
35const asProjectId = (value: string): ProjectId => ProjectId.make(value);
36const asMessageId = (value: string): MessageId => MessageId.make(value);
37const asTurnId = (value: string): TurnId => TurnId.make(value);
38const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.make(value);
3939
4040async function createOrchestrationSystem() {
4141 const ServerConfigLayer = ServerConfig.layerTest(process.cwd(), {
......@@ -115,7 +115,7 @@ describe("OrchestrationEngine", () => {
115115 ],
116116 threads: [
117117 {
118 id: ThreadId.makeUnsafe("thread-bootstrap"),
118 id: ThreadId.make("thread-bootstrap"),
119119 projectId: asProjectId("project-bootstrap"),
120120 title: "Bootstrap Thread",
121121 modelSelection: {
......@@ -183,7 +183,7 @@ describe("OrchestrationEngine", () => {
183183 await system.run(
184184 engine.dispatch({
185185 type: "project.create",
186 commandId: CommandId.makeUnsafe("cmd-project-1-create"),
186 commandId: CommandId.make("cmd-project-1-create"),
187187 projectId: asProjectId("project-1"),
188188 title: "Project 1",
189189 workspaceRoot: "/tmp/project-1",
......@@ -197,8 +197,8 @@ describe("OrchestrationEngine", () => {
197197 await system.run(
198198 engine.dispatch({
199199 type: "thread.create",
200 commandId: CommandId.makeUnsafe("cmd-thread-1-create"),
201 threadId: ThreadId.makeUnsafe("thread-1"),
200 commandId: CommandId.make("cmd-thread-1-create"),
201 threadId: ThreadId.make("thread-1"),
202202 projectId: asProjectId("project-1"),
203203 title: "Thread",
204204 modelSelection: {
......@@ -215,8 +215,8 @@ describe("OrchestrationEngine", () => {
215215 await system.run(
216216 engine.dispatch({
217217 type: "thread.turn.start",
218 commandId: CommandId.makeUnsafe("cmd-turn-start-1"),
219 threadId: ThreadId.makeUnsafe("thread-1"),
218 commandId: CommandId.make("cmd-turn-start-1"),
219 threadId: ThreadId.make("thread-1"),
220220 message: {
221221 messageId: asMessageId("msg-1"),
222222 role: "user",
......@@ -243,7 +243,7 @@ describe("OrchestrationEngine", () => {
243243 await system.run(
244244 engine.dispatch({
245245 type: "project.create",
246 commandId: CommandId.makeUnsafe("cmd-project-archive-create"),
246 commandId: CommandId.make("cmd-project-archive-create"),
247247 projectId: asProjectId("project-archive"),
248248 title: "Project Archive",
249249 workspaceRoot: "/tmp/project-archive",
......@@ -257,8 +257,8 @@ describe("OrchestrationEngine", () => {
257257 await system.run(
258258 engine.dispatch({
259259 type: "thread.create",
260 commandId: CommandId.makeUnsafe("cmd-thread-archive-create"),
261 threadId: ThreadId.makeUnsafe("thread-archive"),
260 commandId: CommandId.make("cmd-thread-archive-create"),
261 threadId: ThreadId.make("thread-archive"),
262262 projectId: asProjectId("project-archive"),
263263 title: "Archive me",
264264 modelSelection: {
......@@ -276,8 +276,8 @@ describe("OrchestrationEngine", () => {
276276 await system.run(
277277 engine.dispatch({
278278 type: "thread.archive",
279 commandId: CommandId.makeUnsafe("cmd-thread-archive"),
280 threadId: ThreadId.makeUnsafe("thread-archive"),
279 commandId: CommandId.make("cmd-thread-archive"),
280 threadId: ThreadId.make("thread-archive"),
281281 }),
282282 );
283283 expect(
......@@ -289,8 +289,8 @@ describe("OrchestrationEngine", () => {
289289 await system.run(
290290 engine.dispatch({
291291 type: "thread.unarchive",
292 commandId: CommandId.makeUnsafe("cmd-thread-unarchive"),
293 threadId: ThreadId.makeUnsafe("thread-archive"),
292 commandId: CommandId.make("cmd-thread-unarchive"),
293 threadId: ThreadId.make("thread-archive"),
294294 }),
295295 );
296296 expect(
......@@ -310,7 +310,7 @@ describe("OrchestrationEngine", () => {
310310 await system.run(
311311 engine.dispatch({
312312 type: "project.create",
313 commandId: CommandId.makeUnsafe("cmd-project-replay-create"),
313 commandId: CommandId.make("cmd-project-replay-create"),
314314 projectId: asProjectId("project-replay"),
315315 title: "Replay Project",
316316 workspaceRoot: "/tmp/project-replay",
......@@ -324,8 +324,8 @@ describe("OrchestrationEngine", () => {
324324 await system.run(
325325 engine.dispatch({
326326 type: "thread.create",
327 commandId: CommandId.makeUnsafe("cmd-thread-replay-create"),
328 threadId: ThreadId.makeUnsafe("thread-replay"),
327 commandId: CommandId.make("cmd-thread-replay-create"),
328 threadId: ThreadId.make("thread-replay"),
329329 projectId: asProjectId("project-replay"),
330330 title: "replay",
331331 modelSelection: {
......@@ -342,8 +342,8 @@ describe("OrchestrationEngine", () => {
342342 await system.run(
343343 engine.dispatch({
344344 type: "thread.delete",
345 commandId: CommandId.makeUnsafe("cmd-thread-replay-delete"),
346 threadId: ThreadId.makeUnsafe("thread-replay"),
345 commandId: CommandId.make("cmd-thread-replay-delete"),
346 threadId: ThreadId.make("thread-replay"),
347347 }),
348348 );
349349
......@@ -368,7 +368,7 @@ describe("OrchestrationEngine", () => {
368368 await system.run(
369369 engine.dispatch({
370370 type: "project.create",
371 commandId: CommandId.makeUnsafe("cmd-project-stream-create"),
371 commandId: CommandId.make("cmd-project-stream-create"),
372372 projectId: asProjectId("project-stream"),
373373 title: "Stream Project",
374374 workspaceRoot: "/tmp/project-stream",
......@@ -392,8 +392,8 @@ describe("OrchestrationEngine", () => {
392392 yield* Effect.sleep("10 millis");
393393 yield* engine.dispatch({
394394 type: "thread.create",
395 commandId: CommandId.makeUnsafe("cmd-stream-thread-create"),
396 threadId: ThreadId.makeUnsafe("thread-stream"),
395 commandId: CommandId.make("cmd-stream-thread-create"),
396 threadId: ThreadId.make("thread-stream"),
397397 projectId: asProjectId("project-stream"),
398398 title: "domain-stream",
399399 modelSelection: {
......@@ -408,8 +408,8 @@ describe("OrchestrationEngine", () => {
408408 });
409409 yield* engine.dispatch({
410410 type: "thread.meta.update",
411 commandId: CommandId.makeUnsafe("cmd-stream-thread-update"),
412 threadId: ThreadId.makeUnsafe("thread-stream"),
411 commandId: CommandId.make("cmd-stream-thread-update"),
412 threadId: ThreadId.make("thread-stream"),
413413 title: "domain-stream-updated",
414414 });
415415 eventTypes.push((yield* Queue.take(eventQueue)).type);
......@@ -429,7 +429,7 @@ describe("OrchestrationEngine", () => {
429429 await system.run(
430430 engine.dispatch({
431431 type: "project.create",
432 commandId: CommandId.makeUnsafe("cmd-project-ack-create"),
432 commandId: CommandId.make("cmd-project-ack-create"),
433433 projectId: asProjectId("project-ack"),
434434 title: "Ack Project",
435435 workspaceRoot: "/tmp/project-ack",
......@@ -444,8 +444,8 @@ describe("OrchestrationEngine", () => {
444444 await system.run(
445445 engine.dispatch({
446446 type: "thread.create",
447 commandId: CommandId.makeUnsafe("cmd-thread-ack-create"),
448 threadId: ThreadId.makeUnsafe("thread-ack"),
447 commandId: CommandId.make("cmd-thread-ack-create"),
448 threadId: ThreadId.make("thread-ack"),
449449 projectId: asProjectId("project-ack"),
450450 title: "Ack Thread",
451451 modelSelection: {
......@@ -481,8 +481,8 @@ describe("OrchestrationEngine", () => {
481481 system.run(
482482 engine.dispatch({
483483 type: "thread.create",
484 commandId: CommandId.makeUnsafe("cmd-thread-missing-project"),
485 threadId: ThreadId.makeUnsafe("thread-missing-project"),
484 commandId: CommandId.make("cmd-thread-missing-project"),
485 threadId: ThreadId.make("thread-missing-project"),
486486 projectId: asProjectId("project-missing"),
487487 title: "Missing Project Thread",
488488 modelSelection: {
......@@ -518,7 +518,7 @@ describe("OrchestrationEngine", () => {
518518 await system.run(
519519 engine.dispatch({
520520 type: "project.create",
521 commandId: CommandId.makeUnsafe("cmd-project-turn-diff-create"),
521 commandId: CommandId.make("cmd-project-turn-diff-create"),
522522 projectId: asProjectId("project-turn-diff"),
523523 title: "Turn Diff Project",
524524 workspaceRoot: "/tmp/project-turn-diff",
......@@ -532,8 +532,8 @@ describe("OrchestrationEngine", () => {
532532 await system.run(
533533 engine.dispatch({
534534 type: "thread.create",
535 commandId: CommandId.makeUnsafe("cmd-thread-turn-diff-create"),
536 threadId: ThreadId.makeUnsafe("thread-turn-diff"),
535 commandId: CommandId.make("cmd-thread-turn-diff-create"),
536 threadId: ThreadId.make("thread-turn-diff"),
537537 projectId: asProjectId("project-turn-diff"),
538538 title: "Turn diff thread",
539539 modelSelection: {
......@@ -550,8 +550,8 @@ describe("OrchestrationEngine", () => {
550550 await system.run(
551551 engine.dispatch({
552552 type: "thread.turn.diff.complete",
553 commandId: CommandId.makeUnsafe("cmd-turn-diff-complete"),
554 threadId: ThreadId.makeUnsafe("thread-turn-diff"),
553 commandId: CommandId.make("cmd-turn-diff-complete"),
554 threadId: ThreadId.make("thread-turn-diff"),
555555 turnId: asTurnId("turn-1"),
556556 completedAt: createdAt,
557557 checkpointRef: asCheckpointRef("refs/t3/checkpoints/thread-turn-diff/turn/1"),
......@@ -590,7 +590,7 @@ describe("OrchestrationEngine", () => {
590590
591591 const flakyStore: OrchestrationEventStoreShape = {
592592 append(event) {
593 if (shouldFailFirstAppend && event.commandId === CommandId.makeUnsafe("cmd-flaky-1")) {
593 if (shouldFailFirstAppend && event.commandId === CommandId.make("cmd-flaky-1")) {
594594 shouldFailFirstAppend = false;
595595 return Effect.fail(
596596 new PersistenceSqlError({
......@@ -637,7 +637,7 @@ describe("OrchestrationEngine", () => {
637637 await runtime.runPromise(
638638 engine.dispatch({
639639 type: "project.create",
640 commandId: CommandId.makeUnsafe("cmd-project-flaky-create"),
640 commandId: CommandId.make("cmd-project-flaky-create"),
641641 projectId: asProjectId("project-flaky"),
642642 title: "Flaky Project",
643643 workspaceRoot: "/tmp/project-flaky",
......@@ -653,8 +653,8 @@ describe("OrchestrationEngine", () => {
653653 runtime.runPromise(
654654 engine.dispatch({
655655 type: "thread.create",
656 commandId: CommandId.makeUnsafe("cmd-flaky-1"),
657 threadId: ThreadId.makeUnsafe("thread-flaky-fail"),
656 commandId: CommandId.make("cmd-flaky-1"),
657 threadId: ThreadId.make("thread-flaky-fail"),
658658 projectId: asProjectId("project-flaky"),
659659 title: "flaky-fail",
660660 modelSelection: {
......@@ -673,8 +673,8 @@ describe("OrchestrationEngine", () => {
673673 const result = await runtime.runPromise(
674674 engine.dispatch({
675675 type: "thread.create",
676 commandId: CommandId.makeUnsafe("cmd-flaky-2"),
677 threadId: ThreadId.makeUnsafe("thread-flaky-ok"),
676 commandId: CommandId.make("cmd-flaky-2"),
677 threadId: ThreadId.make("thread-flaky-ok"),
678678 projectId: asProjectId("project-flaky"),
679679 title: "flaky-ok",
680680 modelSelection: {
......@@ -701,7 +701,7 @@ describe("OrchestrationEngine", () => {
701701 projectEvent: (event) => {
702702 if (
703703 shouldFailRequestedProjection &&
704 event.commandId === CommandId.makeUnsafe("cmd-turn-start-atomic") &&
704 event.commandId === CommandId.make("cmd-turn-start-atomic") &&
705705 event.type === "thread.turn-start-requested"
706706 ) {
707707 shouldFailRequestedProjection = false;
......@@ -732,7 +732,7 @@ describe("OrchestrationEngine", () => {
732732 await runtime.runPromise(
733733 engine.dispatch({
734734 type: "project.create",
735 commandId: CommandId.makeUnsafe("cmd-project-atomic-create"),
735 commandId: CommandId.make("cmd-project-atomic-create"),
736736 projectId: asProjectId("project-atomic"),
737737 title: "Atomic Project",
738738 workspaceRoot: "/tmp/project-atomic",
......@@ -746,8 +746,8 @@ describe("OrchestrationEngine", () => {
746746 await runtime.runPromise(
747747 engine.dispatch({
748748 type: "thread.create",
749 commandId: CommandId.makeUnsafe("cmd-thread-atomic-create"),
750 threadId: ThreadId.makeUnsafe("thread-atomic"),
749 commandId: CommandId.make("cmd-thread-atomic-create"),
750 threadId: ThreadId.make("thread-atomic"),
751751 projectId: asProjectId("project-atomic"),
752752 title: "atomic",
753753 modelSelection: {
......@@ -764,8 +764,8 @@ describe("OrchestrationEngine", () => {
764764
765765 const turnStartCommand = {
766766 type: "thread.turn.start" as const,
767 commandId: CommandId.makeUnsafe("cmd-turn-start-atomic"),
768 threadId: ThreadId.makeUnsafe("thread-atomic"),
767 commandId: CommandId.make("cmd-turn-start-atomic"),
768 threadId: ThreadId.make("thread-atomic"),
769769 message: {
770770 messageId: asMessageId("msg-atomic-1"),
771771 role: "user" as const,
......@@ -845,7 +845,7 @@ describe("OrchestrationEngine", () => {
845845 projectEvent: (event) => {
846846 if (
847847 shouldFailProjection &&
848 event.commandId === CommandId.makeUnsafe("cmd-thread-meta-sync-fail")
848 event.commandId === CommandId.make("cmd-thread-meta-sync-fail")
849849 ) {
850850 shouldFailProjection = false;
851851 return Effect.fail(
......@@ -875,7 +875,7 @@ describe("OrchestrationEngine", () => {
875875 await runtime.runPromise(
876876 engine.dispatch({
877877 type: "project.create",
878 commandId: CommandId.makeUnsafe("cmd-project-sync-create"),
878 commandId: CommandId.make("cmd-project-sync-create"),
879879 projectId: asProjectId("project-sync"),
880880 title: "Sync Project",
881881 workspaceRoot: "/tmp/project-sync",
......@@ -889,8 +889,8 @@ describe("OrchestrationEngine", () => {
889889 await runtime.runPromise(
890890 engine.dispatch({
891891 type: "thread.create",
892 commandId: CommandId.makeUnsafe("cmd-thread-sync-create"),
893 threadId: ThreadId.makeUnsafe("thread-sync"),
892 commandId: CommandId.make("cmd-thread-sync-create"),
893 threadId: ThreadId.make("thread-sync"),
894894 projectId: asProjectId("project-sync"),
895895 title: "sync-before",
896896 modelSelection: {
......@@ -909,8 +909,8 @@ describe("OrchestrationEngine", () => {
909909 runtime.runPromise(
910910 engine.dispatch({
911911 type: "thread.meta.update",
912 commandId: CommandId.makeUnsafe("cmd-thread-meta-sync-fail"),
913 threadId: ThreadId.makeUnsafe("thread-sync"),
912 commandId: CommandId.make("cmd-thread-meta-sync-fail"),
913 threadId: ThreadId.make("thread-sync"),
914914 title: "sync-after-failed-projection",
915915 }),
916916 ),
......@@ -934,8 +934,8 @@ describe("OrchestrationEngine", () => {
934934 system.run(
935935 engine.dispatch({
936936 type: "thread.turn.start",
937 commandId: CommandId.makeUnsafe("cmd-invariant-missing-thread"),
938 threadId: ThreadId.makeUnsafe("thread-missing"),
937 commandId: CommandId.make("cmd-invariant-missing-thread"),
938 threadId: ThreadId.make("thread-missing"),
939939 message: {
940940 messageId: asMessageId("msg-missing"),
941941 role: "user",
......@@ -960,7 +960,7 @@ describe("OrchestrationEngine", () => {
960960 await system.run(
961961 engine.dispatch({
962962 type: "project.create",
963 commandId: CommandId.makeUnsafe("cmd-project-duplicate-create"),
963 commandId: CommandId.make("cmd-project-duplicate-create"),
964964 projectId: asProjectId("project-duplicate"),
965965 title: "Duplicate Project",
966966 workspaceRoot: "/tmp/project-duplicate",
......@@ -975,8 +975,8 @@ describe("OrchestrationEngine", () => {
975975 await system.run(
976976 engine.dispatch({
977977 type: "thread.create",
978 commandId: CommandId.makeUnsafe("cmd-thread-duplicate-1"),
979 threadId: ThreadId.makeUnsafe("thread-duplicate"),
978 commandId: CommandId.make("cmd-thread-duplicate-1"),
979 threadId: ThreadId.make("thread-duplicate"),
980980 projectId: asProjectId("project-duplicate"),
981981 title: "duplicate",
982982 modelSelection: {
......@@ -995,8 +995,8 @@ describe("OrchestrationEngine", () => {
995995 system.run(
996996 engine.dispatch({
997997 type: "thread.create",
998 commandId: CommandId.makeUnsafe("cmd-thread-duplicate-2"),
999 threadId: ThreadId.makeUnsafe("thread-duplicate"),
998 commandId: CommandId.make("cmd-thread-duplicate-2"),
999 threadId: ThreadId.make("thread-duplicate"),
10001000 projectId: asProjectId("project-duplicate"),
10011001 title: "duplicate",
10021002 modelSelection: {
apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts+302-302
......@@ -58,16 +58,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
5858
5959 yield* eventStore.append({
6060 type: "project.created",
61 eventId: EventId.makeUnsafe("evt-1"),
61 eventId: EventId.make("evt-1"),
6262 aggregateKind: "project",
63 aggregateId: ProjectId.makeUnsafe("project-1"),
63 aggregateId: ProjectId.make("project-1"),
6464 occurredAt: now,
65 commandId: CommandId.makeUnsafe("cmd-1"),
65 commandId: CommandId.make("cmd-1"),
6666 causationEventId: null,
67 correlationId: CommandId.makeUnsafe("cmd-1"),
67 correlationId: CommandId.make("cmd-1"),
6868 metadata: {},
6969 payload: {
70 projectId: ProjectId.makeUnsafe("project-1"),
70 projectId: ProjectId.make("project-1"),
7171 title: "Project 1",
7272 workspaceRoot: "/tmp/project-1",
7373 defaultModelSelection: null,
......@@ -79,17 +79,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
7979
8080 yield* eventStore.append({
8181 type: "thread.created",
82 eventId: EventId.makeUnsafe("evt-2"),
82 eventId: EventId.make("evt-2"),
8383 aggregateKind: "thread",
84 aggregateId: ThreadId.makeUnsafe("thread-1"),
84 aggregateId: ThreadId.make("thread-1"),
8585 occurredAt: now,
86 commandId: CommandId.makeUnsafe("cmd-2"),
86 commandId: CommandId.make("cmd-2"),
8787 causationEventId: null,
88 correlationId: CommandId.makeUnsafe("cmd-2"),
88 correlationId: CommandId.make("cmd-2"),
8989 metadata: {},
9090 payload: {
91 threadId: ThreadId.makeUnsafe("thread-1"),
92 projectId: ProjectId.makeUnsafe("project-1"),
91 threadId: ThreadId.make("thread-1"),
92 projectId: ProjectId.make("project-1"),
9393 title: "Thread 1",
9494 modelSelection: {
9595 provider: "codex",
......@@ -105,17 +105,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
105105
106106 yield* eventStore.append({
107107 type: "thread.message-sent",
108 eventId: EventId.makeUnsafe("evt-3"),
108 eventId: EventId.make("evt-3"),
109109 aggregateKind: "thread",
110 aggregateId: ThreadId.makeUnsafe("thread-1"),
110 aggregateId: ThreadId.make("thread-1"),
111111 occurredAt: now,
112 commandId: CommandId.makeUnsafe("cmd-3"),
112 commandId: CommandId.make("cmd-3"),
113113 causationEventId: null,
114 correlationId: CommandId.makeUnsafe("cmd-3"),
114 correlationId: CommandId.make("cmd-3"),
115115 metadata: {},
116116 payload: {
117 threadId: ThreadId.makeUnsafe("thread-1"),
118 messageId: MessageId.makeUnsafe("message-1"),
117 threadId: ThreadId.make("thread-1"),
118 messageId: MessageId.make("message-1"),
119119 role: "assistant",
120120 text: "hello",
121121 turnId: null,
......@@ -183,17 +183,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-base-")))(
183183
184184 yield* eventStore.append({
185185 type: "thread.message-sent",
186 eventId: EventId.makeUnsafe("evt-attachments"),
186 eventId: EventId.make("evt-attachments"),
187187 aggregateKind: "thread",
188 aggregateId: ThreadId.makeUnsafe("thread-attachments"),
188 aggregateId: ThreadId.make("thread-attachments"),
189189 occurredAt: now,
190 commandId: CommandId.makeUnsafe("cmd-attachments"),
190 commandId: CommandId.make("cmd-attachments"),
191191 causationEventId: null,
192 correlationId: CommandId.makeUnsafe("cmd-attachments"),
192 correlationId: CommandId.make("cmd-attachments"),
193193 metadata: {},
194194 payload: {
195 threadId: ThreadId.makeUnsafe("thread-attachments"),
196 messageId: MessageId.makeUnsafe("message-attachments"),
195 threadId: ThreadId.make("thread-attachments"),
196 messageId: MessageId.make("message-attachments"),
197197 role: "user",
198198 text: "Inspect this",
199199 attachments: [
......@@ -249,17 +249,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
249249
250250 yield* eventStore.append({
251251 type: "thread.message-sent",
252 eventId: EventId.makeUnsafe("evt-attachments-safe"),
252 eventId: EventId.make("evt-attachments-safe"),
253253 aggregateKind: "thread",
254 aggregateId: ThreadId.makeUnsafe("thread-attachments-safe"),
254 aggregateId: ThreadId.make("thread-attachments-safe"),
255255 occurredAt: now,
256 commandId: CommandId.makeUnsafe("cmd-attachments-safe"),
256 commandId: CommandId.make("cmd-attachments-safe"),
257257 causationEventId: null,
258 correlationId: CommandId.makeUnsafe("cmd-attachments-safe"),
258 correlationId: CommandId.make("cmd-attachments-safe"),
259259 metadata: {},
260260 payload: {
261 threadId: ThreadId.makeUnsafe("thread-attachments-safe"),
262 messageId: MessageId.makeUnsafe("message-attachments-safe"),
261 threadId: ThreadId.make("thread-attachments-safe"),
262 messageId: MessageId.make("message-attachments-safe"),
263263 role: "user",
264264 text: "Inspect this",
265265 attachments: [
......@@ -330,16 +330,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
330330
331331 yield* eventStore.append({
332332 type: "project.created",
333 eventId: EventId.makeUnsafe("evt-clear-attachments-1"),
333 eventId: EventId.make("evt-clear-attachments-1"),
334334 aggregateKind: "project",
335 aggregateId: ProjectId.makeUnsafe("project-clear-attachments"),
335 aggregateId: ProjectId.make("project-clear-attachments"),
336336 occurredAt: now,
337 commandId: CommandId.makeUnsafe("cmd-clear-attachments-1"),
337 commandId: CommandId.make("cmd-clear-attachments-1"),
338338 causationEventId: null,
339 correlationId: CommandId.makeUnsafe("cmd-clear-attachments-1"),
339 correlationId: CommandId.make("cmd-clear-attachments-1"),
340340 metadata: {},
341341 payload: {
342 projectId: ProjectId.makeUnsafe("project-clear-attachments"),
342 projectId: ProjectId.make("project-clear-attachments"),
343343 title: "Project Clear Attachments",
344344 workspaceRoot: "/tmp/project-clear-attachments",
345345 defaultModelSelection: null,
......@@ -351,17 +351,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
351351
352352 yield* eventStore.append({
353353 type: "thread.created",
354 eventId: EventId.makeUnsafe("evt-clear-attachments-2"),
354 eventId: EventId.make("evt-clear-attachments-2"),
355355 aggregateKind: "thread",
356 aggregateId: ThreadId.makeUnsafe("thread-clear-attachments"),
356 aggregateId: ThreadId.make("thread-clear-attachments"),
357357 occurredAt: now,
358 commandId: CommandId.makeUnsafe("cmd-clear-attachments-2"),
358 commandId: CommandId.make("cmd-clear-attachments-2"),
359359 causationEventId: null,
360 correlationId: CommandId.makeUnsafe("cmd-clear-attachments-2"),
360 correlationId: CommandId.make("cmd-clear-attachments-2"),
361361 metadata: {},
362362 payload: {
363 threadId: ThreadId.makeUnsafe("thread-clear-attachments"),
364 projectId: ProjectId.makeUnsafe("project-clear-attachments"),
363 threadId: ThreadId.make("thread-clear-attachments"),
364 projectId: ProjectId.make("project-clear-attachments"),
365365 title: "Thread Clear Attachments",
366366 modelSelection: {
367367 provider: "codex",
......@@ -377,17 +377,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
377377
378378 yield* eventStore.append({
379379 type: "thread.message-sent",
380 eventId: EventId.makeUnsafe("evt-clear-attachments-3"),
380 eventId: EventId.make("evt-clear-attachments-3"),
381381 aggregateKind: "thread",
382 aggregateId: ThreadId.makeUnsafe("thread-clear-attachments"),
382 aggregateId: ThreadId.make("thread-clear-attachments"),
383383 occurredAt: now,
384 commandId: CommandId.makeUnsafe("cmd-clear-attachments-3"),
384 commandId: CommandId.make("cmd-clear-attachments-3"),
385385 causationEventId: null,
386 correlationId: CommandId.makeUnsafe("cmd-clear-attachments-3"),
386 correlationId: CommandId.make("cmd-clear-attachments-3"),
387387 metadata: {},
388388 payload: {
389 threadId: ThreadId.makeUnsafe("thread-clear-attachments"),
390 messageId: MessageId.makeUnsafe("message-clear-attachments"),
389 threadId: ThreadId.make("thread-clear-attachments"),
390 messageId: MessageId.make("message-clear-attachments"),
391391 role: "user",
392392 text: "Has attachments",
393393 attachments: [
......@@ -408,17 +408,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
408408
409409 yield* eventStore.append({
410410 type: "thread.message-sent",
411 eventId: EventId.makeUnsafe("evt-clear-attachments-4"),
411 eventId: EventId.make("evt-clear-attachments-4"),
412412 aggregateKind: "thread",
413 aggregateId: ThreadId.makeUnsafe("thread-clear-attachments"),
413 aggregateId: ThreadId.make("thread-clear-attachments"),
414414 occurredAt: later,
415 commandId: CommandId.makeUnsafe("cmd-clear-attachments-4"),
415 commandId: CommandId.make("cmd-clear-attachments-4"),
416416 causationEventId: null,
417 correlationId: CommandId.makeUnsafe("cmd-clear-attachments-4"),
417 correlationId: CommandId.make("cmd-clear-attachments-4"),
418418 metadata: {},
419419 payload: {
420 threadId: ThreadId.makeUnsafe("thread-clear-attachments"),
421 messageId: MessageId.makeUnsafe("message-clear-attachments"),
420 threadId: ThreadId.make("thread-clear-attachments"),
421 messageId: MessageId.make("message-clear-attachments"),
422422 role: "user",
423423 text: "",
424424 attachments: [],
......@@ -458,16 +458,16 @@ it.layer(
458458
459459 yield* eventStore.append({
460460 type: "project.created",
461 eventId: EventId.makeUnsafe("evt-overwrite-1"),
461 eventId: EventId.make("evt-overwrite-1"),
462462 aggregateKind: "project",
463 aggregateId: ProjectId.makeUnsafe("project-overwrite"),
463 aggregateId: ProjectId.make("project-overwrite"),
464464 occurredAt: now,
465 commandId: CommandId.makeUnsafe("cmd-overwrite-1"),
465 commandId: CommandId.make("cmd-overwrite-1"),
466466 causationEventId: null,
467 correlationId: CommandId.makeUnsafe("cmd-overwrite-1"),
467 correlationId: CommandId.make("cmd-overwrite-1"),
468468 metadata: {},
469469 payload: {
470 projectId: ProjectId.makeUnsafe("project-overwrite"),
470 projectId: ProjectId.make("project-overwrite"),
471471 title: "Project Overwrite",
472472 workspaceRoot: "/tmp/project-overwrite",
473473 defaultModelSelection: null,
......@@ -479,17 +479,17 @@ it.layer(
479479
480480 yield* eventStore.append({
481481 type: "thread.created",
482 eventId: EventId.makeUnsafe("evt-overwrite-2"),
482 eventId: EventId.make("evt-overwrite-2"),
483483 aggregateKind: "thread",
484 aggregateId: ThreadId.makeUnsafe("thread-overwrite"),
484 aggregateId: ThreadId.make("thread-overwrite"),
485485 occurredAt: now,
486 commandId: CommandId.makeUnsafe("cmd-overwrite-2"),
486 commandId: CommandId.make("cmd-overwrite-2"),
487487 causationEventId: null,
488 correlationId: CommandId.makeUnsafe("cmd-overwrite-2"),
488 correlationId: CommandId.make("cmd-overwrite-2"),
489489 metadata: {},
490490 payload: {
491 threadId: ThreadId.makeUnsafe("thread-overwrite"),
492 projectId: ProjectId.makeUnsafe("project-overwrite"),
491 threadId: ThreadId.make("thread-overwrite"),
492 projectId: ProjectId.make("project-overwrite"),
493493 title: "Thread Overwrite",
494494 modelSelection: {
495495 provider: "codex",
......@@ -505,17 +505,17 @@ it.layer(
505505
506506 yield* eventStore.append({
507507 type: "thread.message-sent",
508 eventId: EventId.makeUnsafe("evt-overwrite-3"),
508 eventId: EventId.make("evt-overwrite-3"),
509509 aggregateKind: "thread",
510 aggregateId: ThreadId.makeUnsafe("thread-overwrite"),
510 aggregateId: ThreadId.make("thread-overwrite"),
511511 occurredAt: now,
512 commandId: CommandId.makeUnsafe("cmd-overwrite-3"),
512 commandId: CommandId.make("cmd-overwrite-3"),
513513 causationEventId: null,
514 correlationId: CommandId.makeUnsafe("cmd-overwrite-3"),
514 correlationId: CommandId.make("cmd-overwrite-3"),
515515 metadata: {},
516516 payload: {
517 threadId: ThreadId.makeUnsafe("thread-overwrite"),
518 messageId: MessageId.makeUnsafe("message-overwrite"),
517 threadId: ThreadId.make("thread-overwrite"),
518 messageId: MessageId.make("message-overwrite"),
519519 role: "user",
520520 text: "first image",
521521 attachments: [
......@@ -536,17 +536,17 @@ it.layer(
536536
537537 yield* eventStore.append({
538538 type: "thread.message-sent",
539 eventId: EventId.makeUnsafe("evt-overwrite-4"),
539 eventId: EventId.make("evt-overwrite-4"),
540540 aggregateKind: "thread",
541 aggregateId: ThreadId.makeUnsafe("thread-overwrite"),
541 aggregateId: ThreadId.make("thread-overwrite"),
542542 occurredAt: later,
543 commandId: CommandId.makeUnsafe("cmd-overwrite-4"),
543 commandId: CommandId.make("cmd-overwrite-4"),
544544 causationEventId: null,
545 correlationId: CommandId.makeUnsafe("cmd-overwrite-4"),
545 correlationId: CommandId.make("cmd-overwrite-4"),
546546 metadata: {},
547547 payload: {
548 threadId: ThreadId.makeUnsafe("thread-overwrite"),
549 messageId: MessageId.makeUnsafe("message-overwrite"),
548 threadId: ThreadId.make("thread-overwrite"),
549 messageId: MessageId.make("message-overwrite"),
550550 role: "user",
551551 text: "",
552552 attachments: [
......@@ -606,16 +606,16 @@ it.layer(
606606
607607 yield* appendAndProject({
608608 type: "project.created",
609 eventId: EventId.makeUnsafe("evt-rollback-1"),
609 eventId: EventId.make("evt-rollback-1"),
610610 aggregateKind: "project",
611 aggregateId: ProjectId.makeUnsafe("project-rollback"),
611 aggregateId: ProjectId.make("project-rollback"),
612612 occurredAt: now,
613 commandId: CommandId.makeUnsafe("cmd-rollback-1"),
613 commandId: CommandId.make("cmd-rollback-1"),
614614 causationEventId: null,
615 correlationId: CorrelationId.makeUnsafe("cmd-rollback-1"),
615 correlationId: CorrelationId.make("cmd-rollback-1"),
616616 metadata: {},
617617 payload: {
618 projectId: ProjectId.makeUnsafe("project-rollback"),
618 projectId: ProjectId.make("project-rollback"),
619619 title: "Project Rollback",
620620 workspaceRoot: "/tmp/project-rollback",
621621 defaultModelSelection: null,
......@@ -627,17 +627,17 @@ it.layer(
627627
628628 yield* appendAndProject({
629629 type: "thread.created",
630 eventId: EventId.makeUnsafe("evt-rollback-2"),
630 eventId: EventId.make("evt-rollback-2"),
631631 aggregateKind: "thread",
632 aggregateId: ThreadId.makeUnsafe("thread-rollback"),
632 aggregateId: ThreadId.make("thread-rollback"),
633633 occurredAt: now,
634 commandId: CommandId.makeUnsafe("cmd-rollback-2"),
634 commandId: CommandId.make("cmd-rollback-2"),
635635 causationEventId: null,
636 correlationId: CorrelationId.makeUnsafe("cmd-rollback-2"),
636 correlationId: CorrelationId.make("cmd-rollback-2"),
637637 metadata: {},
638638 payload: {
639 threadId: ThreadId.makeUnsafe("thread-rollback"),
640 projectId: ProjectId.makeUnsafe("project-rollback"),
639 threadId: ThreadId.make("thread-rollback"),
640 projectId: ProjectId.make("project-rollback"),
641641 title: "Thread Rollback",
642642 modelSelection: {
643643 provider: "codex",
......@@ -663,17 +663,17 @@ it.layer(
663663 const result = yield* Effect.result(
664664 appendAndProject({
665665 type: "thread.message-sent",
666 eventId: EventId.makeUnsafe("evt-rollback-3"),
666 eventId: EventId.make("evt-rollback-3"),
667667 aggregateKind: "thread",
668 aggregateId: ThreadId.makeUnsafe("thread-rollback"),
668 aggregateId: ThreadId.make("thread-rollback"),
669669 occurredAt: now,
670 commandId: CommandId.makeUnsafe("cmd-rollback-3"),
670 commandId: CommandId.make("cmd-rollback-3"),
671671 causationEventId: null,
672 correlationId: CorrelationId.makeUnsafe("cmd-rollback-3"),
672 correlationId: CorrelationId.make("cmd-rollback-3"),
673673 metadata: {},
674674 payload: {
675 threadId: ThreadId.makeUnsafe("thread-rollback"),
676 messageId: MessageId.makeUnsafe("message-rollback"),
675 threadId: ThreadId.make("thread-rollback"),
676 messageId: MessageId.make("message-rollback"),
677677 role: "user",
678678 text: "Rollback me",
679679 attachments: [
......@@ -722,7 +722,7 @@ it.layer(
722722 const eventStore = yield* OrchestrationEventStore;
723723 const { attachmentsDir } = yield* ServerConfig;
724724 const now = new Date().toISOString();
725 const threadId = ThreadId.makeUnsafe("Thread Revert.Files");
725 const threadId = ThreadId.make("Thread Revert.Files");
726726 const keepAttachmentId = "thread-revert-files-00000000-0000-4000-8000-000000000001";
727727 const removeAttachmentId = "thread-revert-files-00000000-0000-4000-8000-000000000002";
728728 const otherThreadAttachmentId =
......@@ -735,16 +735,16 @@ it.layer(
735735
736736 yield* appendAndProject({
737737 type: "project.created",
738 eventId: EventId.makeUnsafe("evt-revert-files-1"),
738 eventId: EventId.make("evt-revert-files-1"),
739739 aggregateKind: "project",
740 aggregateId: ProjectId.makeUnsafe("project-revert-files"),
740 aggregateId: ProjectId.make("project-revert-files"),
741741 occurredAt: now,
742 commandId: CommandId.makeUnsafe("cmd-revert-files-1"),
742 commandId: CommandId.make("cmd-revert-files-1"),
743743 causationEventId: null,
744 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-1"),
744 correlationId: CorrelationId.make("cmd-revert-files-1"),
745745 metadata: {},
746746 payload: {
747 projectId: ProjectId.makeUnsafe("project-revert-files"),
747 projectId: ProjectId.make("project-revert-files"),
748748 title: "Project Revert Files",
749749 workspaceRoot: "/tmp/project-revert-files",
750750 defaultModelSelection: null,
......@@ -756,17 +756,17 @@ it.layer(
756756
757757 yield* appendAndProject({
758758 type: "thread.created",
759 eventId: EventId.makeUnsafe("evt-revert-files-2"),
759 eventId: EventId.make("evt-revert-files-2"),
760760 aggregateKind: "thread",
761761 aggregateId: threadId,
762762 occurredAt: now,
763 commandId: CommandId.makeUnsafe("cmd-revert-files-2"),
763 commandId: CommandId.make("cmd-revert-files-2"),
764764 causationEventId: null,
765 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-2"),
765 correlationId: CorrelationId.make("cmd-revert-files-2"),
766766 metadata: {},
767767 payload: {
768768 threadId,
769 projectId: ProjectId.makeUnsafe("project-revert-files"),
769 projectId: ProjectId.make("project-revert-files"),
770770 title: "Thread Revert Files",
771771 modelSelection: {
772772 provider: "codex",
......@@ -782,39 +782,39 @@ it.layer(
782782
783783 yield* appendAndProject({
784784 type: "thread.turn-diff-completed",
785 eventId: EventId.makeUnsafe("evt-revert-files-3"),
785 eventId: EventId.make("evt-revert-files-3"),
786786 aggregateKind: "thread",
787787 aggregateId: threadId,
788788 occurredAt: now,
789 commandId: CommandId.makeUnsafe("cmd-revert-files-3"),
789 commandId: CommandId.make("cmd-revert-files-3"),
790790 causationEventId: null,
791 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-3"),
791 correlationId: CorrelationId.make("cmd-revert-files-3"),
792792 metadata: {},
793793 payload: {
794794 threadId,
795 turnId: TurnId.makeUnsafe("turn-keep"),
795 turnId: TurnId.make("turn-keep"),
796796 checkpointTurnCount: 1,
797 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert-files/turn/1"),
797 checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert-files/turn/1"),
798798 status: "ready",
799799 files: [],
800 assistantMessageId: MessageId.makeUnsafe("message-keep"),
800 assistantMessageId: MessageId.make("message-keep"),
801801 completedAt: now,
802802 },
803803 });
804804
805805 yield* appendAndProject({
806806 type: "thread.message-sent",
807 eventId: EventId.makeUnsafe("evt-revert-files-4"),
807 eventId: EventId.make("evt-revert-files-4"),
808808 aggregateKind: "thread",
809809 aggregateId: threadId,
810810 occurredAt: now,
811 commandId: CommandId.makeUnsafe("cmd-revert-files-4"),
811 commandId: CommandId.make("cmd-revert-files-4"),
812812 causationEventId: null,
813 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-4"),
813 correlationId: CorrelationId.make("cmd-revert-files-4"),
814814 metadata: {},
815815 payload: {
816816 threadId,
817 messageId: MessageId.makeUnsafe("message-keep"),
817 messageId: MessageId.make("message-keep"),
818818 role: "assistant",
819819 text: "Keep",
820820 attachments: [
......@@ -826,7 +826,7 @@ it.layer(
826826 sizeBytes: 5,
827827 },
828828 ],
829 turnId: TurnId.makeUnsafe("turn-keep"),
829 turnId: TurnId.make("turn-keep"),
830830 streaming: false,
831831 createdAt: now,
832832 updatedAt: now,
......@@ -835,39 +835,39 @@ it.layer(
835835
836836 yield* appendAndProject({
837837 type: "thread.turn-diff-completed",
838 eventId: EventId.makeUnsafe("evt-revert-files-5"),
838 eventId: EventId.make("evt-revert-files-5"),
839839 aggregateKind: "thread",
840840 aggregateId: threadId,
841841 occurredAt: now,
842 commandId: CommandId.makeUnsafe("cmd-revert-files-5"),
842 commandId: CommandId.make("cmd-revert-files-5"),
843843 causationEventId: null,
844 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-5"),
844 correlationId: CorrelationId.make("cmd-revert-files-5"),
845845 metadata: {},
846846 payload: {
847847 threadId,
848 turnId: TurnId.makeUnsafe("turn-remove"),
848 turnId: TurnId.make("turn-remove"),
849849 checkpointTurnCount: 2,
850 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert-files/turn/2"),
850 checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert-files/turn/2"),
851851 status: "ready",
852852 files: [],
853 assistantMessageId: MessageId.makeUnsafe("message-remove"),
853 assistantMessageId: MessageId.make("message-remove"),
854854 completedAt: now,
855855 },
856856 });
857857
858858 yield* appendAndProject({
859859 type: "thread.message-sent",
860 eventId: EventId.makeUnsafe("evt-revert-files-6"),
860 eventId: EventId.make("evt-revert-files-6"),
861861 aggregateKind: "thread",
862862 aggregateId: threadId,
863863 occurredAt: now,
864 commandId: CommandId.makeUnsafe("cmd-revert-files-6"),
864 commandId: CommandId.make("cmd-revert-files-6"),
865865 causationEventId: null,
866 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-6"),
866 correlationId: CorrelationId.make("cmd-revert-files-6"),
867867 metadata: {},
868868 payload: {
869869 threadId,
870 messageId: MessageId.makeUnsafe("message-remove"),
870 messageId: MessageId.make("message-remove"),
871871 role: "assistant",
872872 text: "Remove",
873873 attachments: [
......@@ -879,7 +879,7 @@ it.layer(
879879 sizeBytes: 5,
880880 },
881881 ],
882 turnId: TurnId.makeUnsafe("turn-remove"),
882 turnId: TurnId.make("turn-remove"),
883883 streaming: false,
884884 createdAt: now,
885885 updatedAt: now,
......@@ -899,13 +899,13 @@ it.layer(
899899
900900 yield* appendAndProject({
901901 type: "thread.reverted",
902 eventId: EventId.makeUnsafe("evt-revert-files-7"),
902 eventId: EventId.make("evt-revert-files-7"),
903903 aggregateKind: "thread",
904904 aggregateId: threadId,
905905 occurredAt: now,
906 commandId: CommandId.makeUnsafe("cmd-revert-files-7"),
906 commandId: CommandId.make("cmd-revert-files-7"),
907907 causationEventId: null,
908 correlationId: CorrelationId.makeUnsafe("cmd-revert-files-7"),
908 correlationId: CorrelationId.make("cmd-revert-files-7"),
909909 metadata: {},
910910 payload: {
911911 threadId,
......@@ -931,7 +931,7 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
931931 const eventStore = yield* OrchestrationEventStore;
932932 const { attachmentsDir } = yield* ServerConfig;
933933 const now = new Date().toISOString();
934 const threadId = ThreadId.makeUnsafe("Thread Delete.Files");
934 const threadId = ThreadId.make("Thread Delete.Files");
935935 const attachmentId = "thread-delete-files-00000000-0000-4000-8000-000000000001";
936936 const otherThreadAttachmentId =
937937 "thread-delete-files-extra-00000000-0000-4000-8000-000000000002";
......@@ -943,16 +943,16 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
943943
944944 yield* appendAndProject({
945945 type: "project.created",
946 eventId: EventId.makeUnsafe("evt-delete-files-1"),
946 eventId: EventId.make("evt-delete-files-1"),
947947 aggregateKind: "project",
948 aggregateId: ProjectId.makeUnsafe("project-delete-files"),
948 aggregateId: ProjectId.make("project-delete-files"),
949949 occurredAt: now,
950 commandId: CommandId.makeUnsafe("cmd-delete-files-1"),
950 commandId: CommandId.make("cmd-delete-files-1"),
951951 causationEventId: null,
952 correlationId: CorrelationId.makeUnsafe("cmd-delete-files-1"),
952 correlationId: CorrelationId.make("cmd-delete-files-1"),
953953 metadata: {},
954954 payload: {
955 projectId: ProjectId.makeUnsafe("project-delete-files"),
955 projectId: ProjectId.make("project-delete-files"),
956956 title: "Project Delete Files",
957957 workspaceRoot: "/tmp/project-delete-files",
958958 defaultModelSelection: null,
......@@ -964,17 +964,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
964964
965965 yield* appendAndProject({
966966 type: "thread.created",
967 eventId: EventId.makeUnsafe("evt-delete-files-2"),
967 eventId: EventId.make("evt-delete-files-2"),
968968 aggregateKind: "thread",
969969 aggregateId: threadId,
970970 occurredAt: now,
971 commandId: CommandId.makeUnsafe("cmd-delete-files-2"),
971 commandId: CommandId.make("cmd-delete-files-2"),
972972 causationEventId: null,
973 correlationId: CorrelationId.makeUnsafe("cmd-delete-files-2"),
973 correlationId: CorrelationId.make("cmd-delete-files-2"),
974974 metadata: {},
975975 payload: {
976976 threadId,
977 projectId: ProjectId.makeUnsafe("project-delete-files"),
977 projectId: ProjectId.make("project-delete-files"),
978978 title: "Thread Delete Files",
979979 modelSelection: {
980980 provider: "codex",
......@@ -990,17 +990,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
990990
991991 yield* appendAndProject({
992992 type: "thread.message-sent",
993 eventId: EventId.makeUnsafe("evt-delete-files-3"),
993 eventId: EventId.make("evt-delete-files-3"),
994994 aggregateKind: "thread",
995995 aggregateId: threadId,
996996 occurredAt: now,
997 commandId: CommandId.makeUnsafe("cmd-delete-files-3"),
997 commandId: CommandId.make("cmd-delete-files-3"),
998998 causationEventId: null,
999 correlationId: CorrelationId.makeUnsafe("cmd-delete-files-3"),
999 correlationId: CorrelationId.make("cmd-delete-files-3"),
10001000 metadata: {},
10011001 payload: {
10021002 threadId,
1003 messageId: MessageId.makeUnsafe("message-delete-files"),
1003 messageId: MessageId.make("message-delete-files"),
10041004 role: "user",
10051005 text: "Delete",
10061006 attachments: [
......@@ -1032,13 +1032,13 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
10321032
10331033 yield* appendAndProject({
10341034 type: "thread.deleted",
1035 eventId: EventId.makeUnsafe("evt-delete-files-4"),
1035 eventId: EventId.make("evt-delete-files-4"),
10361036 aggregateKind: "thread",
10371037 aggregateId: threadId,
10381038 occurredAt: now,
1039 commandId: CommandId.makeUnsafe("cmd-delete-files-4"),
1039 commandId: CommandId.make("cmd-delete-files-4"),
10401040 causationEventId: null,
1041 correlationId: CorrelationId.makeUnsafe("cmd-delete-files-4"),
1041 correlationId: CorrelationId.make("cmd-delete-files-4"),
10421042 metadata: {},
10431043 payload: {
10441044 threadId,
......@@ -1072,16 +1072,16 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta
10721072
10731073 yield* eventStore.append({
10741074 type: "thread.deleted",
1075 eventId: EventId.makeUnsafe("evt-unsafe-thread-delete"),
1075 eventId: EventId.make("evt-unsafe-thread-delete"),
10761076 aggregateKind: "thread",
1077 aggregateId: ThreadId.makeUnsafe(".."),
1077 aggregateId: ThreadId.make(".."),
10781078 occurredAt: now,
1079 commandId: CommandId.makeUnsafe("cmd-unsafe-thread-delete"),
1079 commandId: CommandId.make("cmd-unsafe-thread-delete"),
10801080 causationEventId: null,
1081 correlationId: CorrelationId.makeUnsafe("cmd-unsafe-thread-delete"),
1081 correlationId: CorrelationId.make("cmd-unsafe-thread-delete"),
10821082 metadata: {},
10831083 payload: {
1084 threadId: ThreadId.makeUnsafe(".."),
1084 threadId: ThreadId.make(".."),
10851085 deletedAt: now,
10861086 },
10871087 });
......@@ -1106,16 +1106,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
11061106
11071107 yield* eventStore.append({
11081108 type: "project.created",
1109 eventId: EventId.makeUnsafe("evt-a1"),
1109 eventId: EventId.make("evt-a1"),
11101110 aggregateKind: "project",
1111 aggregateId: ProjectId.makeUnsafe("project-a"),
1111 aggregateId: ProjectId.make("project-a"),
11121112 occurredAt: now,
1113 commandId: CommandId.makeUnsafe("cmd-a1"),
1113 commandId: CommandId.make("cmd-a1"),
11141114 causationEventId: null,
1115 correlationId: CorrelationId.makeUnsafe("cmd-a1"),
1115 correlationId: CorrelationId.make("cmd-a1"),
11161116 metadata: {},
11171117 payload: {
1118 projectId: ProjectId.makeUnsafe("project-a"),
1118 projectId: ProjectId.make("project-a"),
11191119 title: "Project A",
11201120 workspaceRoot: "/tmp/project-a",
11211121 defaultModelSelection: null,
......@@ -1127,17 +1127,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
11271127
11281128 yield* eventStore.append({
11291129 type: "thread.created",
1130 eventId: EventId.makeUnsafe("evt-a2"),
1130 eventId: EventId.make("evt-a2"),
11311131 aggregateKind: "thread",
1132 aggregateId: ThreadId.makeUnsafe("thread-a"),
1132 aggregateId: ThreadId.make("thread-a"),
11331133 occurredAt: now,
1134 commandId: CommandId.makeUnsafe("cmd-a2"),
1134 commandId: CommandId.make("cmd-a2"),
11351135 causationEventId: null,
1136 correlationId: CorrelationId.makeUnsafe("cmd-a2"),
1136 correlationId: CorrelationId.make("cmd-a2"),
11371137 metadata: {},
11381138 payload: {
1139 threadId: ThreadId.makeUnsafe("thread-a"),
1140 projectId: ProjectId.makeUnsafe("project-a"),
1139 threadId: ThreadId.make("thread-a"),
1140 projectId: ProjectId.make("project-a"),
11411141 title: "Thread A",
11421142 modelSelection: {
11431143 provider: "codex",
......@@ -1153,17 +1153,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
11531153
11541154 yield* eventStore.append({
11551155 type: "thread.message-sent",
1156 eventId: EventId.makeUnsafe("evt-a3"),
1156 eventId: EventId.make("evt-a3"),
11571157 aggregateKind: "thread",
1158 aggregateId: ThreadId.makeUnsafe("thread-a"),
1158 aggregateId: ThreadId.make("thread-a"),
11591159 occurredAt: now,
1160 commandId: CommandId.makeUnsafe("cmd-a3"),
1160 commandId: CommandId.make("cmd-a3"),
11611161 causationEventId: null,
1162 correlationId: CorrelationId.makeUnsafe("cmd-a3"),
1162 correlationId: CorrelationId.make("cmd-a3"),
11631163 metadata: {},
11641164 payload: {
1165 threadId: ThreadId.makeUnsafe("thread-a"),
1166 messageId: MessageId.makeUnsafe("message-a"),
1165 threadId: ThreadId.make("thread-a"),
1166 messageId: MessageId.make("message-a"),
11671167 role: "assistant",
11681168 text: "hello",
11691169 turnId: null,
......@@ -1177,17 +1177,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
11771177
11781178 yield* eventStore.append({
11791179 type: "thread.message-sent",
1180 eventId: EventId.makeUnsafe("evt-a4"),
1180 eventId: EventId.make("evt-a4"),
11811181 aggregateKind: "thread",
1182 aggregateId: ThreadId.makeUnsafe("thread-a"),
1182 aggregateId: ThreadId.make("thread-a"),
11831183 occurredAt: now,
1184 commandId: CommandId.makeUnsafe("cmd-a4"),
1184 commandId: CommandId.make("cmd-a4"),
11851185 causationEventId: null,
1186 correlationId: CorrelationId.makeUnsafe("cmd-a4"),
1186 correlationId: CorrelationId.make("cmd-a4"),
11871187 metadata: {},
11881188 payload: {
1189 threadId: ThreadId.makeUnsafe("thread-a"),
1190 messageId: MessageId.makeUnsafe("message-a"),
1189 threadId: ThreadId.make("thread-a"),
1190 messageId: MessageId.make("message-a"),
11911191 role: "assistant",
11921192 text: " world",
11931193 turnId: null,
......@@ -1233,16 +1233,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
12331233
12341234 yield* eventStore.append({
12351235 type: "project.created",
1236 eventId: EventId.makeUnsafe("evt-empty-1"),
1236 eventId: EventId.make("evt-empty-1"),
12371237 aggregateKind: "project",
1238 aggregateId: ProjectId.makeUnsafe("project-empty"),
1238 aggregateId: ProjectId.make("project-empty"),
12391239 occurredAt: now,
1240 commandId: CommandId.makeUnsafe("cmd-empty-1"),
1240 commandId: CommandId.make("cmd-empty-1"),
12411241 causationEventId: null,
1242 correlationId: CorrelationId.makeUnsafe("cmd-empty-1"),
1242 correlationId: CorrelationId.make("cmd-empty-1"),
12431243 metadata: {},
12441244 payload: {
1245 projectId: ProjectId.makeUnsafe("project-empty"),
1245 projectId: ProjectId.make("project-empty"),
12461246 title: "Project Empty",
12471247 workspaceRoot: "/tmp/project-empty",
12481248 defaultModelSelection: null,
......@@ -1254,17 +1254,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
12541254
12551255 yield* eventStore.append({
12561256 type: "thread.created",
1257 eventId: EventId.makeUnsafe("evt-empty-2"),
1257 eventId: EventId.make("evt-empty-2"),
12581258 aggregateKind: "thread",
1259 aggregateId: ThreadId.makeUnsafe("thread-empty"),
1259 aggregateId: ThreadId.make("thread-empty"),
12601260 occurredAt: now,
1261 commandId: CommandId.makeUnsafe("cmd-empty-2"),
1261 commandId: CommandId.make("cmd-empty-2"),
12621262 causationEventId: null,
1263 correlationId: CorrelationId.makeUnsafe("cmd-empty-2"),
1263 correlationId: CorrelationId.make("cmd-empty-2"),
12641264 metadata: {},
12651265 payload: {
1266 threadId: ThreadId.makeUnsafe("thread-empty"),
1267 projectId: ProjectId.makeUnsafe("project-empty"),
1266 threadId: ThreadId.make("thread-empty"),
1267 projectId: ProjectId.make("project-empty"),
12681268 title: "Thread Empty",
12691269 modelSelection: {
12701270 provider: "codex",
......@@ -1280,17 +1280,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
12801280
12811281 yield* eventStore.append({
12821282 type: "thread.message-sent",
1283 eventId: EventId.makeUnsafe("evt-empty-3"),
1283 eventId: EventId.make("evt-empty-3"),
12841284 aggregateKind: "thread",
1285 aggregateId: ThreadId.makeUnsafe("thread-empty"),
1285 aggregateId: ThreadId.make("thread-empty"),
12861286 occurredAt: now,
1287 commandId: CommandId.makeUnsafe("cmd-empty-3"),
1287 commandId: CommandId.make("cmd-empty-3"),
12881288 causationEventId: null,
1289 correlationId: CorrelationId.makeUnsafe("cmd-empty-3"),
1289 correlationId: CorrelationId.make("cmd-empty-3"),
12901290 metadata: {},
12911291 payload: {
1292 threadId: ThreadId.makeUnsafe("thread-empty"),
1293 messageId: MessageId.makeUnsafe("assistant-empty"),
1292 threadId: ThreadId.make("thread-empty"),
1293 messageId: MessageId.make("assistant-empty"),
12941294 role: "assistant",
12951295 text: "Hello",
12961296 turnId: null,
......@@ -1302,17 +1302,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
13021302
13031303 yield* eventStore.append({
13041304 type: "thread.message-sent",
1305 eventId: EventId.makeUnsafe("evt-empty-4"),
1305 eventId: EventId.make("evt-empty-4"),
13061306 aggregateKind: "thread",
1307 aggregateId: ThreadId.makeUnsafe("thread-empty"),
1307 aggregateId: ThreadId.make("thread-empty"),
13081308 occurredAt: now,
1309 commandId: CommandId.makeUnsafe("cmd-empty-4"),
1309 commandId: CommandId.make("cmd-empty-4"),
13101310 causationEventId: null,
1311 correlationId: CorrelationId.makeUnsafe("cmd-empty-4"),
1311 correlationId: CorrelationId.make("cmd-empty-4"),
13121312 metadata: {},
13131313 payload: {
1314 threadId: ThreadId.makeUnsafe("thread-empty"),
1315 messageId: MessageId.makeUnsafe("assistant-empty"),
1314 threadId: ThreadId.make("thread-empty"),
1315 messageId: MessageId.make("assistant-empty"),
13161316 role: "assistant",
13171317 text: " world",
13181318 turnId: null,
......@@ -1324,17 +1324,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
13241324
13251325 yield* eventStore.append({
13261326 type: "thread.message-sent",
1327 eventId: EventId.makeUnsafe("evt-empty-5"),
1327 eventId: EventId.make("evt-empty-5"),
13281328 aggregateKind: "thread",
1329 aggregateId: ThreadId.makeUnsafe("thread-empty"),
1329 aggregateId: ThreadId.make("thread-empty"),
13301330 occurredAt: now,
1331 commandId: CommandId.makeUnsafe("cmd-empty-5"),
1331 commandId: CommandId.make("cmd-empty-5"),
13321332 causationEventId: null,
1333 correlationId: CorrelationId.makeUnsafe("cmd-empty-5"),
1333 correlationId: CorrelationId.make("cmd-empty-5"),
13341334 metadata: {},
13351335 payload: {
1336 threadId: ThreadId.makeUnsafe("thread-empty"),
1337 messageId: MessageId.makeUnsafe("assistant-empty"),
1336 threadId: ThreadId.make("thread-empty"),
1337 messageId: MessageId.make("assistant-empty"),
13381338 role: "assistant",
13391339 text: "",
13401340 turnId: null,
......@@ -1373,16 +1373,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
13731373
13741374 yield* appendAndProject({
13751375 type: "project.created",
1376 eventId: EventId.makeUnsafe("evt-conflict-1"),
1376 eventId: EventId.make("evt-conflict-1"),
13771377 aggregateKind: "project",
1378 aggregateId: ProjectId.makeUnsafe("project-conflict"),
1378 aggregateId: ProjectId.make("project-conflict"),
13791379 occurredAt: "2026-02-26T13:00:00.000Z",
1380 commandId: CommandId.makeUnsafe("cmd-conflict-1"),
1380 commandId: CommandId.make("cmd-conflict-1"),
13811381 causationEventId: null,
1382 correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"),
1382 correlationId: CorrelationId.make("cmd-conflict-1"),
13831383 metadata: {},
13841384 payload: {
1385 projectId: ProjectId.makeUnsafe("project-conflict"),
1385 projectId: ProjectId.make("project-conflict"),
13861386 title: "Project Conflict",
13871387 workspaceRoot: "/tmp/project-conflict",
13881388 defaultModelSelection: null,
......@@ -1394,17 +1394,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
13941394
13951395 yield* appendAndProject({
13961396 type: "thread.created",
1397 eventId: EventId.makeUnsafe("evt-conflict-2"),
1397 eventId: EventId.make("evt-conflict-2"),
13981398 aggregateKind: "thread",
1399 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
1399 aggregateId: ThreadId.make("thread-conflict"),
14001400 occurredAt: "2026-02-26T13:00:01.000Z",
1401 commandId: CommandId.makeUnsafe("cmd-conflict-2"),
1401 commandId: CommandId.make("cmd-conflict-2"),
14021402 causationEventId: null,
1403 correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"),
1403 correlationId: CorrelationId.make("cmd-conflict-2"),
14041404 metadata: {},
14051405 payload: {
1406 threadId: ThreadId.makeUnsafe("thread-conflict"),
1407 projectId: ProjectId.makeUnsafe("project-conflict"),
1406 threadId: ThreadId.make("thread-conflict"),
1407 projectId: ProjectId.make("project-conflict"),
14081408 title: "Thread Conflict",
14091409 modelSelection: {
14101410 provider: "codex",
......@@ -1420,37 +1420,37 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
14201420
14211421 yield* appendAndProject({
14221422 type: "thread.turn-interrupt-requested",
1423 eventId: EventId.makeUnsafe("evt-conflict-3"),
1423 eventId: EventId.make("evt-conflict-3"),
14241424 aggregateKind: "thread",
1425 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
1425 aggregateId: ThreadId.make("thread-conflict"),
14261426 occurredAt: "2026-02-26T13:00:02.000Z",
1427 commandId: CommandId.makeUnsafe("cmd-conflict-3"),
1427 commandId: CommandId.make("cmd-conflict-3"),
14281428 causationEventId: null,
1429 correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"),
1429 correlationId: CorrelationId.make("cmd-conflict-3"),
14301430 metadata: {},
14311431 payload: {
1432 threadId: ThreadId.makeUnsafe("thread-conflict"),
1433 turnId: TurnId.makeUnsafe("turn-interrupted"),
1432 threadId: ThreadId.make("thread-conflict"),
1433 turnId: TurnId.make("turn-interrupted"),
14341434 createdAt: "2026-02-26T13:00:02.000Z",
14351435 },
14361436 });
14371437
14381438 yield* appendAndProject({
14391439 type: "thread.message-sent",
1440 eventId: EventId.makeUnsafe("evt-conflict-4"),
1440 eventId: EventId.make("evt-conflict-4"),
14411441 aggregateKind: "thread",
1442 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
1442 aggregateId: ThreadId.make("thread-conflict"),
14431443 occurredAt: "2026-02-26T13:00:03.000Z",
1444 commandId: CommandId.makeUnsafe("cmd-conflict-4"),
1444 commandId: CommandId.make("cmd-conflict-4"),
14451445 causationEventId: null,
1446 correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"),
1446 correlationId: CorrelationId.make("cmd-conflict-4"),
14471447 metadata: {},
14481448 payload: {
1449 threadId: ThreadId.makeUnsafe("thread-conflict"),
1450 messageId: MessageId.makeUnsafe("assistant-conflict"),
1449 threadId: ThreadId.make("thread-conflict"),
1450 messageId: MessageId.make("assistant-conflict"),
14511451 role: "assistant",
14521452 text: "done",
1453 turnId: TurnId.makeUnsafe("turn-completed"),
1453 turnId: TurnId.make("turn-completed"),
14541454 streaming: false,
14551455 createdAt: "2026-02-26T13:00:03.000Z",
14561456 updatedAt: "2026-02-26T13:00:03.000Z",
......@@ -1459,22 +1459,22 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
14591459
14601460 yield* appendAndProject({
14611461 type: "thread.turn-diff-completed",
1462 eventId: EventId.makeUnsafe("evt-conflict-5"),
1462 eventId: EventId.make("evt-conflict-5"),
14631463 aggregateKind: "thread",
1464 aggregateId: ThreadId.makeUnsafe("thread-conflict"),
1464 aggregateId: ThreadId.make("thread-conflict"),
14651465 occurredAt: "2026-02-26T13:00:04.000Z",
1466 commandId: CommandId.makeUnsafe("cmd-conflict-5"),
1466 commandId: CommandId.make("cmd-conflict-5"),
14671467 causationEventId: null,
1468 correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"),
1468 correlationId: CorrelationId.make("cmd-conflict-5"),
14691469 metadata: {},
14701470 payload: {
1471 threadId: ThreadId.makeUnsafe("thread-conflict"),
1472 turnId: TurnId.makeUnsafe("turn-completed"),
1471 threadId: ThreadId.make("thread-conflict"),
1472 turnId: TurnId.make("turn-completed"),
14731473 checkpointTurnCount: 1,
1474 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"),
1474 checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-conflict/turn/1"),
14751475 status: "ready",
14761476 files: [],
1477 assistantMessageId: MessageId.makeUnsafe("assistant-conflict"),
1477 assistantMessageId: MessageId.make("assistant-conflict"),
14781478 completedAt: "2026-02-26T13:00:04.000Z",
14791479 },
14801480 });
......@@ -1517,16 +1517,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
15171517
15181518 yield* appendAndProject({
15191519 type: "project.created",
1520 eventId: EventId.makeUnsafe("evt-revert-1"),
1520 eventId: EventId.make("evt-revert-1"),
15211521 aggregateKind: "project",
1522 aggregateId: ProjectId.makeUnsafe("project-revert"),
1522 aggregateId: ProjectId.make("project-revert"),
15231523 occurredAt: "2026-02-26T12:00:00.000Z",
1524 commandId: CommandId.makeUnsafe("cmd-revert-1"),
1524 commandId: CommandId.make("cmd-revert-1"),
15251525 causationEventId: null,
1526 correlationId: CorrelationId.makeUnsafe("cmd-revert-1"),
1526 correlationId: CorrelationId.make("cmd-revert-1"),
15271527 metadata: {},
15281528 payload: {
1529 projectId: ProjectId.makeUnsafe("project-revert"),
1529 projectId: ProjectId.make("project-revert"),
15301530 title: "Project Revert",
15311531 workspaceRoot: "/tmp/project-revert",
15321532 defaultModelSelection: null,
......@@ -1538,17 +1538,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
15381538
15391539 yield* appendAndProject({
15401540 type: "thread.created",
1541 eventId: EventId.makeUnsafe("evt-revert-2"),
1541 eventId: EventId.make("evt-revert-2"),
15421542 aggregateKind: "thread",
1543 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1543 aggregateId: ThreadId.make("thread-revert"),
15441544 occurredAt: "2026-02-26T12:00:01.000Z",
1545 commandId: CommandId.makeUnsafe("cmd-revert-2"),
1545 commandId: CommandId.make("cmd-revert-2"),
15461546 causationEventId: null,
1547 correlationId: CorrelationId.makeUnsafe("cmd-revert-2"),
1547 correlationId: CorrelationId.make("cmd-revert-2"),
15481548 metadata: {},
15491549 payload: {
1550 threadId: ThreadId.makeUnsafe("thread-revert"),
1551 projectId: ProjectId.makeUnsafe("project-revert"),
1550 threadId: ThreadId.make("thread-revert"),
1551 projectId: ProjectId.make("project-revert"),
15521552 title: "Thread Revert",
15531553 modelSelection: {
15541554 provider: "codex",
......@@ -1564,42 +1564,42 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
15641564
15651565 yield* appendAndProject({
15661566 type: "thread.turn-diff-completed",
1567 eventId: EventId.makeUnsafe("evt-revert-3"),
1567 eventId: EventId.make("evt-revert-3"),
15681568 aggregateKind: "thread",
1569 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1569 aggregateId: ThreadId.make("thread-revert"),
15701570 occurredAt: "2026-02-26T12:00:02.000Z",
1571 commandId: CommandId.makeUnsafe("cmd-revert-3"),
1571 commandId: CommandId.make("cmd-revert-3"),
15721572 causationEventId: null,
1573 correlationId: CorrelationId.makeUnsafe("cmd-revert-3"),
1573 correlationId: CorrelationId.make("cmd-revert-3"),
15741574 metadata: {},
15751575 payload: {
1576 threadId: ThreadId.makeUnsafe("thread-revert"),
1577 turnId: TurnId.makeUnsafe("turn-1"),
1576 threadId: ThreadId.make("thread-revert"),
1577 turnId: TurnId.make("turn-1"),
15781578 checkpointTurnCount: 1,
1579 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert/turn/1"),
1579 checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert/turn/1"),
15801580 status: "ready",
15811581 files: [],
1582 assistantMessageId: MessageId.makeUnsafe("assistant-keep"),
1582 assistantMessageId: MessageId.make("assistant-keep"),
15831583 completedAt: "2026-02-26T12:00:02.000Z",
15841584 },
15851585 });
15861586
15871587 yield* appendAndProject({
15881588 type: "thread.message-sent",
1589 eventId: EventId.makeUnsafe("evt-revert-4"),
1589 eventId: EventId.make("evt-revert-4"),
15901590 aggregateKind: "thread",
1591 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1591 aggregateId: ThreadId.make("thread-revert"),
15921592 occurredAt: "2026-02-26T12:00:02.100Z",
1593 commandId: CommandId.makeUnsafe("cmd-revert-4"),
1593 commandId: CommandId.make("cmd-revert-4"),
15941594 causationEventId: null,
1595 correlationId: CorrelationId.makeUnsafe("cmd-revert-4"),
1595 correlationId: CorrelationId.make("cmd-revert-4"),
15961596 metadata: {},
15971597 payload: {
1598 threadId: ThreadId.makeUnsafe("thread-revert"),
1599 messageId: MessageId.makeUnsafe("assistant-keep"),
1598 threadId: ThreadId.make("thread-revert"),
1599 messageId: MessageId.make("assistant-keep"),
16001600 role: "assistant",
16011601 text: "kept",
1602 turnId: TurnId.makeUnsafe("turn-1"),
1602 turnId: TurnId.make("turn-1"),
16031603 streaming: false,
16041604 createdAt: "2026-02-26T12:00:02.100Z",
16051605 updatedAt: "2026-02-26T12:00:02.100Z",
......@@ -1608,42 +1608,42 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
16081608
16091609 yield* appendAndProject({
16101610 type: "thread.turn-diff-completed",
1611 eventId: EventId.makeUnsafe("evt-revert-5"),
1611 eventId: EventId.make("evt-revert-5"),
16121612 aggregateKind: "thread",
1613 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1613 aggregateId: ThreadId.make("thread-revert"),
16141614 occurredAt: "2026-02-26T12:00:03.000Z",
1615 commandId: CommandId.makeUnsafe("cmd-revert-5"),
1615 commandId: CommandId.make("cmd-revert-5"),
16161616 causationEventId: null,
1617 correlationId: CorrelationId.makeUnsafe("cmd-revert-5"),
1617 correlationId: CorrelationId.make("cmd-revert-5"),
16181618 metadata: {},
16191619 payload: {
1620 threadId: ThreadId.makeUnsafe("thread-revert"),
1621 turnId: TurnId.makeUnsafe("turn-2"),
1620 threadId: ThreadId.make("thread-revert"),
1621 turnId: TurnId.make("turn-2"),
16221622 checkpointTurnCount: 2,
1623 checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert/turn/2"),
1623 checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert/turn/2"),
16241624 status: "ready",
16251625 files: [],
1626 assistantMessageId: MessageId.makeUnsafe("assistant-remove"),
1626 assistantMessageId: MessageId.make("assistant-remove"),
16271627 completedAt: "2026-02-26T12:00:03.000Z",
16281628 },
16291629 });
16301630
16311631 yield* appendAndProject({
16321632 type: "thread.message-sent",
1633 eventId: EventId.makeUnsafe("evt-revert-6"),
1633 eventId: EventId.make("evt-revert-6"),
16341634 aggregateKind: "thread",
1635 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1635 aggregateId: ThreadId.make("thread-revert"),
16361636 occurredAt: "2026-02-26T12:00:03.050Z",
1637 commandId: CommandId.makeUnsafe("cmd-revert-6"),
1637 commandId: CommandId.make("cmd-revert-6"),
16381638 causationEventId: null,
1639 correlationId: CorrelationId.makeUnsafe("cmd-revert-6"),
1639 correlationId: CorrelationId.make("cmd-revert-6"),
16401640 metadata: {},
16411641 payload: {
1642 threadId: ThreadId.makeUnsafe("thread-revert"),
1643 messageId: MessageId.makeUnsafe("user-remove"),
1642 threadId: ThreadId.make("thread-revert"),
1643 messageId: MessageId.make("user-remove"),
16441644 role: "user",
16451645 text: "removed",
1646 turnId: TurnId.makeUnsafe("turn-2"),
1646 turnId: TurnId.make("turn-2"),
16471647 streaming: false,
16481648 createdAt: "2026-02-26T12:00:03.050Z",
16491649 updatedAt: "2026-02-26T12:00:03.050Z",
......@@ -1652,20 +1652,20 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
16521652
16531653 yield* appendAndProject({
16541654 type: "thread.message-sent",
1655 eventId: EventId.makeUnsafe("evt-revert-7"),
1655 eventId: EventId.make("evt-revert-7"),
16561656 aggregateKind: "thread",
1657 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1657 aggregateId: ThreadId.make("thread-revert"),
16581658 occurredAt: "2026-02-26T12:00:03.100Z",
1659 commandId: CommandId.makeUnsafe("cmd-revert-7"),
1659 commandId: CommandId.make("cmd-revert-7"),
16601660 causationEventId: null,
1661 correlationId: CorrelationId.makeUnsafe("cmd-revert-7"),
1661 correlationId: CorrelationId.make("cmd-revert-7"),
16621662 metadata: {},
16631663 payload: {
1664 threadId: ThreadId.makeUnsafe("thread-revert"),
1665 messageId: MessageId.makeUnsafe("assistant-remove"),
1664 threadId: ThreadId.make("thread-revert"),
1665 messageId: MessageId.make("assistant-remove"),
16661666 role: "assistant",
16671667 text: "removed",
1668 turnId: TurnId.makeUnsafe("turn-2"),
1668 turnId: TurnId.make("turn-2"),
16691669 streaming: false,
16701670 createdAt: "2026-02-26T12:00:03.100Z",
16711671 updatedAt: "2026-02-26T12:00:03.100Z",
......@@ -1674,16 +1674,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => {
16741674
16751675 yield* appendAndProject({
16761676 type: "thread.reverted",
1677 eventId: EventId.makeUnsafe("evt-revert-8"),
1677 eventId: EventId.make("evt-revert-8"),
16781678 aggregateKind: "thread",
1679 aggregateId: ThreadId.makeUnsafe("thread-revert"),
1679 aggregateId: ThreadId.make("thread-revert"),
16801680 occurredAt: "2026-02-26T12:00:04.000Z",
1681 commandId: CommandId.makeUnsafe("cmd-revert-8"),
1681 commandId: CommandId.make("cmd-revert-8"),
16821682 causationEventId: null,
1683 correlationId: CorrelationId.makeUnsafe("cmd-revert-8"),
1683 correlationId: CorrelationId.make("cmd-revert-8"),
16841684 metadata: {},
16851685 payload: {
1686 threadId: ThreadId.makeUnsafe("thread-revert"),
1686 threadId: ThreadId.make("thread-revert"),
16871687 turnCount: 1,
16881688 },
16891689 });
......@@ -1725,10 +1725,10 @@ it.effect("restores pending turn-start metadata across projection pipeline resta
17251725 Layer.provideMerge(persistenceLayer),
17261726 );
17271727
1728 const threadId = ThreadId.makeUnsafe("thread-restart");
1729 const turnId = TurnId.makeUnsafe("turn-restart");
1730 const messageId = MessageId.makeUnsafe("message-restart");
1731 const sourcePlanThreadId = ThreadId.makeUnsafe("thread-plan-source");
1728 const threadId = ThreadId.make("thread-restart");
1729 const turnId = TurnId.make("turn-restart");
1730 const messageId = MessageId.make("message-restart");
1731 const sourcePlanThreadId = ThreadId.make("thread-plan-source");
17321732 const sourcePlanId = "plan-source";
17331733 const turnStartedAt = "2026-02-26T14:00:00.000Z";
17341734 const sessionSetAt = "2026-02-26T14:00:05.000Z";
......@@ -1739,13 +1739,13 @@ it.effect("restores pending turn-start metadata across projection pipeline resta
17391739
17401740 yield* eventStore.append({
17411741 type: "thread.turn-start-requested",
1742 eventId: EventId.makeUnsafe("evt-restart-1"),
1742 eventId: EventId.make("evt-restart-1"),
17431743 aggregateKind: "thread",
17441744 aggregateId: threadId,
17451745 occurredAt: turnStartedAt,
1746 commandId: CommandId.makeUnsafe("cmd-restart-1"),
1746 commandId: CommandId.make("cmd-restart-1"),
17471747 causationEventId: null,
1748 correlationId: CorrelationId.makeUnsafe("cmd-restart-1"),
1748 correlationId: CorrelationId.make("cmd-restart-1"),
17491749 metadata: {},
17501750 payload: {
17511751 threadId,
......@@ -1769,13 +1769,13 @@ it.effect("restores pending turn-start metadata across projection pipeline resta
17691769
17701770 yield* eventStore.append({
17711771 type: "thread.session-set",
1772 eventId: EventId.makeUnsafe("evt-restart-2"),
1772 eventId: EventId.make("evt-restart-2"),
17731773 aggregateKind: "thread",
17741774 aggregateId: threadId,
17751775 occurredAt: sessionSetAt,
1776 commandId: CommandId.makeUnsafe("cmd-restart-2"),
1776 commandId: CommandId.make("cmd-restart-2"),
17771777 causationEventId: null,
1778 correlationId: CorrelationId.makeUnsafe("cmd-restart-2"),
1778 correlationId: CorrelationId.make("cmd-restart-2"),
17791779 metadata: {},
17801780 payload: {
17811781 threadId,
......@@ -1867,8 +1867,8 @@ engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => {
18671867
18681868 yield* engine.dispatch({
18691869 type: "project.create",
1870 commandId: CommandId.makeUnsafe("cmd-live-project"),
1871 projectId: ProjectId.makeUnsafe("project-live"),
1870 commandId: CommandId.make("cmd-live-project"),
1871 projectId: ProjectId.make("project-live"),
18721872 title: "Live Project",
18731873 workspaceRoot: "/tmp/project-live",
18741874 defaultModelSelection: {
......@@ -1905,8 +1905,8 @@ engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => {
19051905
19061906 yield* engine.dispatch({
19071907 type: "project.create",
1908 commandId: CommandId.makeUnsafe("cmd-scripts-project-create"),
1909 projectId: ProjectId.makeUnsafe("project-scripts"),
1908 commandId: CommandId.make("cmd-scripts-project-create"),
1909 projectId: ProjectId.make("project-scripts"),
19101910 title: "Scripts Project",
19111911 workspaceRoot: "/tmp/project-scripts",
19121912 defaultModelSelection: {
......@@ -1918,8 +1918,8 @@ engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => {
19181918
19191919 yield* engine.dispatch({
19201920 type: "project.meta.update",
1921 commandId: CommandId.makeUnsafe("cmd-scripts-project-update"),
1922 projectId: ProjectId.makeUnsafe("project-scripts"),
1921 commandId: CommandId.make("cmd-scripts-project-update"),
1922 projectId: ProjectId.make("project-scripts"),
19231923 scripts: [
19241924 {
19251925 id: "script-1",
apps/server/src/orchestration/Layers/ProjectionPipeline.ts+1-1
......@@ -86,7 +86,7 @@ function extractActivityRequestId(payload: unknown): ApprovalRequestId | null {
8686 return null;
8787 }
8888 const requestId = (payload as Record<string, unknown>).requestId;
89 return typeof requestId === "string" ? ApprovalRequestId.makeUnsafe(requestId) : null;
89 return typeof requestId === "string" ? ApprovalRequestId.make(requestId) : null;
9090}
9191
9292function retainProjectionMessagesAfterRevert(
apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts+12-12
......@@ -9,11 +9,11 @@ import { ORCHESTRATION_PROJECTOR_NAMES } from "./ProjectionPipeline.ts";
99import { OrchestrationProjectionSnapshotQueryLive } from "./ProjectionSnapshotQuery.ts";
1010import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts";
1111
12const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
13const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
14const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
15const asEventId = (value: string): EventId => EventId.makeUnsafe(value);
16const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.makeUnsafe(value);
12const asProjectId = (value: string): ProjectId => ProjectId.make(value);
13const asTurnId = (value: string): TurnId => TurnId.make(value);
14const asMessageId = (value: string): MessageId => MessageId.make(value);
15const asEventId = (value: string): EventId => EventId.make(value);
16const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.make(value);
1717
1818const projectionSnapshotLayer = it.layer(
1919 OrchestrationProjectionSnapshotQueryLive.pipe(
......@@ -259,7 +259,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
259259 ]);
260260 assert.deepEqual(snapshot.threads, [
261261 {
262 id: ThreadId.makeUnsafe("thread-1"),
262 id: ThreadId.make("thread-1"),
263263 projectId: asProjectId("project-1"),
264264 title: "Thread 1",
265265 modelSelection: {
......@@ -278,7 +278,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
278278 completedAt: "2026-02-24T00:00:08.000Z",
279279 assistantMessageId: asMessageId("message-1"),
280280 sourceProposedPlan: {
281 threadId: ThreadId.makeUnsafe("thread-1"),
281 threadId: ThreadId.make("thread-1"),
282282 planId: "plan-1",
283283 },
284284 },
......@@ -303,7 +303,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
303303 turnId: asTurnId("turn-1"),
304304 planMarkdown: "# Ship it",
305305 implementedAt: "2026-02-24T00:00:05.500Z",
306 implementationThreadId: ThreadId.makeUnsafe("thread-2"),
306 implementationThreadId: ThreadId.make("thread-2"),
307307 createdAt: "2026-02-24T00:00:05.000Z",
308308 updatedAt: "2026-02-24T00:00:05.500Z",
309309 },
......@@ -331,7 +331,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
331331 },
332332 ],
333333 session: {
334 threadId: ThreadId.makeUnsafe("thread-1"),
334 threadId: ThreadId.make("thread-1"),
335335 status: "running",
336336 providerName: "codex",
337337 runtimeMode: "approval-required",
......@@ -473,7 +473,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
473473 );
474474 assert.equal(firstThreadId._tag, "Some");
475475 if (firstThreadId._tag === "Some") {
476 assert.equal(firstThreadId.value, ThreadId.makeUnsafe("thread-first"));
476 assert.equal(firstThreadId.value, ThreadId.make("thread-first"));
477477 }
478478 }),
479479 );
......@@ -596,12 +596,12 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
596596 `;
597597
598598 const context = yield* snapshotQuery.getThreadCheckpointContext(
599 ThreadId.makeUnsafe("thread-context"),
599 ThreadId.make("thread-context"),
600600 );
601601 assert.equal(context._tag, "Some");
602602 if (context._tag === "Some") {
603603 assert.deepEqual(context.value, {
604 threadId: ThreadId.makeUnsafe("thread-context"),
604 threadId: ThreadId.make("thread-context"),
605605 projectId: asProjectId("project-context"),
606606 workspaceRoot: "/tmp/context-workspace",
607607 worktreePath: "/tmp/context-worktree",
apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts+138-151
......@@ -38,11 +38,10 @@ import { ProviderCommandReactor } from "../Services/ProviderCommandReactor.ts";
3838import * as NodeServices from "@effect/platform-node/NodeServices";
3939import { ServerSettingsService } from "../../serverSettings.ts";
4040
41const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
42const asApprovalRequestId = (value: string): ApprovalRequestId =>
43 ApprovalRequestId.makeUnsafe(value);
44const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
45const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
41const asProjectId = (value: string): ProjectId => ProjectId.make(value);
42const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value);
43const asMessageId = (value: string): MessageId => MessageId.make(value);
44const asTurnId = (value: string): TurnId => TurnId.make(value);
4645
4746const deriveServerPathsSync = (baseDir: string, devUrl: URL | undefined) =>
4847 Effect.runSync(deriveServerPaths(baseDir, devUrl).pipe(Effect.provide(NodeServices.layer)));
......@@ -122,8 +121,8 @@ describe("ProviderCommandReactor", () => {
122121 input !== null &&
123122 "threadId" in input &&
124123 typeof input.threadId === "string"
125 ? ThreadId.makeUnsafe(input.threadId)
126 : ThreadId.makeUnsafe(`thread-${sessionIndex}`);
124 ? ThreadId.make(input.threadId)
125 : ThreadId.make(`thread-${sessionIndex}`);
127126 const session: ProviderSession = {
128127 provider: modelSelection.provider,
129128 status: "ready" as const,
......@@ -145,7 +144,7 @@ describe("ProviderCommandReactor", () => {
145144 });
146145 const sendTurn = vi.fn((_: unknown) =>
147146 Effect.succeed({
148 threadId: ThreadId.makeUnsafe("thread-1"),
147 threadId: ThreadId.make("thread-1"),
149148 turnId: asTurnId("turn-1"),
150149 }),
151150 );
......@@ -247,7 +246,7 @@ describe("ProviderCommandReactor", () => {
247246 await Effect.runPromise(
248247 engine.dispatch({
249248 type: "project.create",
250 commandId: CommandId.makeUnsafe("cmd-project-create"),
249 commandId: CommandId.make("cmd-project-create"),
251250 projectId: asProjectId("project-1"),
252251 title: "Provider Project",
253252 workspaceRoot: "/tmp/provider-project",
......@@ -258,8 +257,8 @@ describe("ProviderCommandReactor", () => {
258257 await Effect.runPromise(
259258 engine.dispatch({
260259 type: "thread.create",
261 commandId: CommandId.makeUnsafe("cmd-thread-create"),
262 threadId: ThreadId.makeUnsafe("thread-1"),
260 commandId: CommandId.make("cmd-thread-create"),
261 threadId: ThreadId.make("thread-1"),
263262 projectId: asProjectId("project-1"),
264263 title: "Thread",
265264 modelSelection: modelSelection,
......@@ -294,8 +293,8 @@ describe("ProviderCommandReactor", () => {
294293 await Effect.runPromise(
295294 harness.engine.dispatch({
296295 type: "thread.turn.start",
297 commandId: CommandId.makeUnsafe("cmd-turn-start-1"),
298 threadId: ThreadId.makeUnsafe("thread-1"),
296 commandId: CommandId.make("cmd-turn-start-1"),
297 threadId: ThreadId.make("thread-1"),
299298 message: {
300299 messageId: asMessageId("user-message-1"),
301300 role: "user",
......@@ -310,7 +309,7 @@ describe("ProviderCommandReactor", () => {
310309
311310 await waitFor(() => harness.startSession.mock.calls.length === 1);
312311 await waitFor(() => harness.sendTurn.mock.calls.length === 1);
313 expect(harness.startSession.mock.calls[0]?.[0]).toEqual(ThreadId.makeUnsafe("thread-1"));
312 expect(harness.startSession.mock.calls[0]?.[0]).toEqual(ThreadId.make("thread-1"));
314313 expect(harness.startSession.mock.calls[0]?.[1]).toMatchObject({
315314 cwd: "/tmp/provider-project",
316315 modelSelection: {
......@@ -321,7 +320,7 @@ describe("ProviderCommandReactor", () => {
321320 });
322321
323322 const readModel = await Effect.runPromise(harness.engine.getReadModel());
324 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
323 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
325324 expect(thread?.session?.threadId).toBe("thread-1");
326325 expect(thread?.session?.runtimeMode).toBe("approval-required");
327326 });
......@@ -335,8 +334,8 @@ describe("ProviderCommandReactor", () => {
335334 await Effect.runPromise(
336335 harness.engine.dispatch({
337336 type: "thread.meta.update",
338 commandId: CommandId.makeUnsafe("cmd-thread-title-seed"),
339 threadId: ThreadId.makeUnsafe("thread-1"),
337 commandId: CommandId.make("cmd-thread-title-seed"),
338 threadId: ThreadId.make("thread-1"),
340339 title: seededTitle,
341340 }),
342341 );
......@@ -344,8 +343,8 @@ describe("ProviderCommandReactor", () => {
344343 await Effect.runPromise(
345344 harness.engine.dispatch({
346345 type: "thread.turn.start",
347 commandId: CommandId.makeUnsafe("cmd-turn-start-title"),
348 threadId: ThreadId.makeUnsafe("thread-1"),
346 commandId: CommandId.make("cmd-turn-start-title"),
347 threadId: ThreadId.make("thread-1"),
349348 message: {
350349 messageId: asMessageId("user-message-title"),
351350 role: "user",
......@@ -367,12 +366,12 @@ describe("ProviderCommandReactor", () => {
367366 await waitFor(async () => {
368367 const readModel = await Effect.runPromise(harness.engine.getReadModel());
369368 return (
370 readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"))?.title ===
369 readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.title ===
371370 "Generated title"
372371 );
373372 });
374373 const readModel = await Effect.runPromise(harness.engine.getReadModel());
375 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
374 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
376375 expect(thread?.title).toBe("Generated title");
377376 });
378377
......@@ -384,8 +383,8 @@ describe("ProviderCommandReactor", () => {
384383 await Effect.runPromise(
385384 harness.engine.dispatch({
386385 type: "thread.meta.update",
387 commandId: CommandId.makeUnsafe("cmd-thread-title-custom"),
388 threadId: ThreadId.makeUnsafe("thread-1"),
386 commandId: CommandId.make("cmd-thread-title-custom"),
387 threadId: ThreadId.make("thread-1"),
389388 title: "Keep this custom title",
390389 }),
391390 );
......@@ -393,8 +392,8 @@ describe("ProviderCommandReactor", () => {
393392 await Effect.runPromise(
394393 harness.engine.dispatch({
395394 type: "thread.turn.start",
396 commandId: CommandId.makeUnsafe("cmd-turn-start-title-preserve"),
397 threadId: ThreadId.makeUnsafe("thread-1"),
395 commandId: CommandId.make("cmd-turn-start-title-preserve"),
396 threadId: ThreadId.make("thread-1"),
398397 message: {
399398 messageId: asMessageId("user-message-title-preserve"),
400399 role: "user",
......@@ -412,7 +411,7 @@ describe("ProviderCommandReactor", () => {
412411 expect(harness.generateThreadTitle).not.toHaveBeenCalled();
413412
414413 const readModel = await Effect.runPromise(harness.engine.getReadModel());
415 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
414 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
416415 expect(thread?.title).toBe("Keep this custom title");
417416 });
418417
......@@ -429,8 +428,8 @@ describe("ProviderCommandReactor", () => {
429428 await Effect.runPromise(
430429 harness.engine.dispatch({
431430 type: "thread.meta.update",
432 commandId: CommandId.makeUnsafe("cmd-thread-title-formatted-seed"),
433 threadId: ThreadId.makeUnsafe("thread-1"),
431 commandId: CommandId.make("cmd-thread-title-formatted-seed"),
432 threadId: ThreadId.make("thread-1"),
434433 title: seededTitle,
435434 }),
436435 );
......@@ -438,8 +437,8 @@ describe("ProviderCommandReactor", () => {
438437 await Effect.runPromise(
439438 harness.engine.dispatch({
440439 type: "thread.turn.start",
441 commandId: CommandId.makeUnsafe("cmd-turn-start-title-formatted"),
442 threadId: ThreadId.makeUnsafe("thread-1"),
440 commandId: CommandId.make("cmd-turn-start-title-formatted"),
441 threadId: ThreadId.make("thread-1"),
443442 message: {
444443 messageId: asMessageId("user-message-title-formatted"),
445444 role: "user",
......@@ -457,13 +456,13 @@ describe("ProviderCommandReactor", () => {
457456 await waitFor(async () => {
458457 const readModel = await Effect.runPromise(harness.engine.getReadModel());
459458 return (
460 readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"))?.title ===
459 readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.title ===
461460 "Reconnect spinner resume bug"
462461 );
463462 });
464463
465464 const readModel = await Effect.runPromise(harness.engine.getReadModel());
466 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
465 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
467466 expect(thread?.title).toBe("Reconnect spinner resume bug");
468467 });
469468
......@@ -474,8 +473,8 @@ describe("ProviderCommandReactor", () => {
474473 await Effect.runPromise(
475474 harness.engine.dispatch({
476475 type: "thread.meta.update",
477 commandId: CommandId.makeUnsafe("cmd-thread-branch"),
478 threadId: ThreadId.makeUnsafe("thread-1"),
476 commandId: CommandId.make("cmd-thread-branch"),
477 threadId: ThreadId.make("thread-1"),
479478 branch: "t3code/1234abcd",
480479 worktreePath: "/tmp/provider-project-worktree",
481480 }),
......@@ -499,8 +498,8 @@ describe("ProviderCommandReactor", () => {
499498 await Effect.runPromise(
500499 harness.engine.dispatch({
501500 type: "thread.turn.start",
502 commandId: CommandId.makeUnsafe("cmd-turn-start-branch-model"),
503 threadId: ThreadId.makeUnsafe("thread-1"),
501 commandId: CommandId.make("cmd-turn-start-branch-model"),
502 threadId: ThreadId.make("thread-1"),
504503 message: {
505504 messageId: asMessageId("user-message-branch-model"),
506505 role: "user",
......@@ -526,8 +525,8 @@ describe("ProviderCommandReactor", () => {
526525 await Effect.runPromise(
527526 harness.engine.dispatch({
528527 type: "thread.turn.start",
529 commandId: CommandId.makeUnsafe("cmd-turn-start-fast"),
530 threadId: ThreadId.makeUnsafe("thread-1"),
528 commandId: CommandId.make("cmd-turn-start-fast"),
529 threadId: ThreadId.make("thread-1"),
531530 message: {
532531 messageId: asMessageId("user-message-fast"),
533532 role: "user",
......@@ -561,7 +560,7 @@ describe("ProviderCommandReactor", () => {
561560 },
562561 });
563562 expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({
564 threadId: ThreadId.makeUnsafe("thread-1"),
563 threadId: ThreadId.make("thread-1"),
565564 modelSelection: {
566565 provider: "codex",
567566 model: "gpt-5.3-codex",
......@@ -582,8 +581,8 @@ describe("ProviderCommandReactor", () => {
582581 await Effect.runPromise(
583582 harness.engine.dispatch({
584583 type: "thread.turn.start",
585 commandId: CommandId.makeUnsafe("cmd-turn-start-claude-effort"),
586 threadId: ThreadId.makeUnsafe("thread-1"),
584 commandId: CommandId.make("cmd-turn-start-claude-effort"),
585 threadId: ThreadId.make("thread-1"),
587586 message: {
588587 messageId: asMessageId("user-message-claude-effort"),
589588 role: "user",
......@@ -615,7 +614,7 @@ describe("ProviderCommandReactor", () => {
615614 },
616615 });
617616 expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({
618 threadId: ThreadId.makeUnsafe("thread-1"),
617 threadId: ThreadId.make("thread-1"),
619618 modelSelection: {
620619 provider: "claudeAgent",
621620 model: "claude-sonnet-4-6",
......@@ -635,8 +634,8 @@ describe("ProviderCommandReactor", () => {
635634 await Effect.runPromise(
636635 harness.engine.dispatch({
637636 type: "thread.turn.start",
638 commandId: CommandId.makeUnsafe("cmd-turn-start-claude-fast-mode"),
639 threadId: ThreadId.makeUnsafe("thread-1"),
637 commandId: CommandId.make("cmd-turn-start-claude-fast-mode"),
638 threadId: ThreadId.make("thread-1"),
640639 message: {
641640 messageId: asMessageId("user-message-claude-fast-mode"),
642641 role: "user",
......@@ -668,7 +667,7 @@ describe("ProviderCommandReactor", () => {
668667 },
669668 });
670669 expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({
671 threadId: ThreadId.makeUnsafe("thread-1"),
670 threadId: ThreadId.make("thread-1"),
672671 modelSelection: {
673672 provider: "claudeAgent",
674673 model: "claude-opus-4-6",
......@@ -686,8 +685,8 @@ describe("ProviderCommandReactor", () => {
686685 await Effect.runPromise(
687686 harness.engine.dispatch({
688687 type: "thread.interaction-mode.set",
689 commandId: CommandId.makeUnsafe("cmd-interaction-mode-set-plan"),
690 threadId: ThreadId.makeUnsafe("thread-1"),
688 commandId: CommandId.make("cmd-interaction-mode-set-plan"),
689 threadId: ThreadId.make("thread-1"),
691690 interactionMode: "plan",
692691 createdAt: now,
693692 }),
......@@ -696,8 +695,8 @@ describe("ProviderCommandReactor", () => {
696695 await Effect.runPromise(
697696 harness.engine.dispatch({
698697 type: "thread.turn.start",
699 commandId: CommandId.makeUnsafe("cmd-turn-start-plan"),
700 threadId: ThreadId.makeUnsafe("thread-1"),
698 commandId: CommandId.make("cmd-turn-start-plan"),
699 threadId: ThreadId.make("thread-1"),
701700 message: {
702701 messageId: asMessageId("user-message-plan"),
703702 role: "user",
......@@ -712,7 +711,7 @@ describe("ProviderCommandReactor", () => {
712711
713712 await waitFor(() => harness.sendTurn.mock.calls.length === 1);
714713 expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({
715 threadId: ThreadId.makeUnsafe("thread-1"),
714 threadId: ThreadId.make("thread-1"),
716715 interactionMode: "plan",
717716 });
718717 });
......@@ -726,8 +725,8 @@ describe("ProviderCommandReactor", () => {
726725 await Effect.runPromise(
727726 harness.engine.dispatch({
728727 type: "thread.turn.start",
729 commandId: CommandId.makeUnsafe("cmd-turn-start-provider-first"),
730 threadId: ThreadId.makeUnsafe("thread-1"),
728 commandId: CommandId.make("cmd-turn-start-provider-first"),
729 threadId: ThreadId.make("thread-1"),
731730 message: {
732731 messageId: asMessageId("user-message-provider-first"),
733732 role: "user",
......@@ -746,9 +745,7 @@ describe("ProviderCommandReactor", () => {
746745
747746 await waitFor(async () => {
748747 const readModel = await Effect.runPromise(harness.engine.getReadModel());
749 const thread = readModel.threads.find(
750 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
751 );
748 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
752749 return (
753750 thread?.activities.some((activity) => activity.kind === "provider.turn.start.failed") ??
754751 false
......@@ -759,7 +756,7 @@ describe("ProviderCommandReactor", () => {
759756 expect(harness.sendTurn).not.toHaveBeenCalled();
760757
761758 const readModel = await Effect.runPromise(harness.engine.getReadModel());
762 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
759 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
763760 expect(thread?.session).toBeNull();
764761 expect(
765762 thread?.activities.find((activity) => activity.kind === "provider.turn.start.failed"),
......@@ -778,8 +775,8 @@ describe("ProviderCommandReactor", () => {
778775 await Effect.runPromise(
779776 harness.engine.dispatch({
780777 type: "thread.turn.start",
781 commandId: CommandId.makeUnsafe("cmd-turn-start-unsupported-1"),
782 threadId: ThreadId.makeUnsafe("thread-1"),
778 commandId: CommandId.make("cmd-turn-start-unsupported-1"),
779 threadId: ThreadId.make("thread-1"),
783780 message: {
784781 messageId: asMessageId("user-message-unsupported-1"),
785782 role: "user",
......@@ -797,8 +794,8 @@ describe("ProviderCommandReactor", () => {
797794 await Effect.runPromise(
798795 harness.engine.dispatch({
799796 type: "thread.turn.start",
800 commandId: CommandId.makeUnsafe("cmd-turn-start-unsupported-2"),
801 threadId: ThreadId.makeUnsafe("thread-1"),
797 commandId: CommandId.make("cmd-turn-start-unsupported-2"),
798 threadId: ThreadId.make("thread-1"),
802799 message: {
803800 messageId: asMessageId("user-message-unsupported-2"),
804801 role: "user",
......@@ -814,7 +811,7 @@ describe("ProviderCommandReactor", () => {
814811 await waitFor(() => harness.sendTurn.mock.calls.length === 2);
815812
816813 expect(harness.sendTurn.mock.calls[1]?.[0]).toMatchObject({
817 threadId: ThreadId.makeUnsafe("thread-1"),
814 threadId: ThreadId.make("thread-1"),
818815 modelSelection: {
819816 provider: "codex",
820817 model: "gpt-5-codex",
......@@ -829,8 +826,8 @@ describe("ProviderCommandReactor", () => {
829826 await Effect.runPromise(
830827 harness.engine.dispatch({
831828 type: "thread.turn.start",
832 commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-1"),
833 threadId: ThreadId.makeUnsafe("thread-1"),
829 commandId: CommandId.make("cmd-turn-start-unchanged-1"),
830 threadId: ThreadId.make("thread-1"),
834831 message: {
835832 messageId: asMessageId("user-message-unchanged-1"),
836833 role: "user",
......@@ -849,8 +846,8 @@ describe("ProviderCommandReactor", () => {
849846 await Effect.runPromise(
850847 harness.engine.dispatch({
851848 type: "thread.turn.start",
852 commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-2"),
853 threadId: ThreadId.makeUnsafe("thread-1"),
849 commandId: CommandId.make("cmd-turn-start-unchanged-2"),
850 threadId: ThreadId.make("thread-1"),
854851 message: {
855852 messageId: asMessageId("user-message-unchanged-2"),
856853 role: "user",
......@@ -877,8 +874,8 @@ describe("ProviderCommandReactor", () => {
877874 await Effect.runPromise(
878875 harness.engine.dispatch({
879876 type: "thread.turn.start",
880 commandId: CommandId.makeUnsafe("cmd-turn-start-claude-effort-1"),
881 threadId: ThreadId.makeUnsafe("thread-1"),
877 commandId: CommandId.make("cmd-turn-start-claude-effort-1"),
878 threadId: ThreadId.make("thread-1"),
882879 message: {
883880 messageId: asMessageId("user-message-claude-effort-1"),
884881 role: "user",
......@@ -904,8 +901,8 @@ describe("ProviderCommandReactor", () => {
904901 await Effect.runPromise(
905902 harness.engine.dispatch({
906903 type: "thread.turn.start",
907 commandId: CommandId.makeUnsafe("cmd-turn-start-claude-effort-2"),
908 threadId: ThreadId.makeUnsafe("thread-1"),
904 commandId: CommandId.make("cmd-turn-start-claude-effort-2"),
905 threadId: ThreadId.make("thread-1"),
909906 message: {
910907 messageId: asMessageId("user-message-claude-effort-2"),
911908 role: "user",
......@@ -946,8 +943,8 @@ describe("ProviderCommandReactor", () => {
946943 await Effect.runPromise(
947944 harness.engine.dispatch({
948945 type: "thread.runtime-mode.set",
949 commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-initial-full-access"),
950 threadId: ThreadId.makeUnsafe("thread-1"),
946 commandId: CommandId.make("cmd-runtime-mode-set-initial-full-access"),
947 threadId: ThreadId.make("thread-1"),
951948 runtimeMode: "full-access",
952949 createdAt: now,
953950 }),
......@@ -956,8 +953,8 @@ describe("ProviderCommandReactor", () => {
956953 await Effect.runPromise(
957954 harness.engine.dispatch({
958955 type: "thread.turn.start",
959 commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-1"),
960 threadId: ThreadId.makeUnsafe("thread-1"),
956 commandId: CommandId.make("cmd-turn-start-runtime-mode-1"),
957 threadId: ThreadId.make("thread-1"),
961958 message: {
962959 messageId: asMessageId("user-message-runtime-mode-1"),
963960 role: "user",
......@@ -976,8 +973,8 @@ describe("ProviderCommandReactor", () => {
976973 await Effect.runPromise(
977974 harness.engine.dispatch({
978975 type: "thread.runtime-mode.set",
979 commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-1"),
980 threadId: ThreadId.makeUnsafe("thread-1"),
976 commandId: CommandId.make("cmd-runtime-mode-set-1"),
977 threadId: ThreadId.make("thread-1"),
981978 runtimeMode: "approval-required",
982979 createdAt: now,
983980 }),
......@@ -985,17 +982,15 @@ describe("ProviderCommandReactor", () => {
985982
986983 await waitFor(async () => {
987984 const readModel = await Effect.runPromise(harness.engine.getReadModel());
988 const thread = readModel.threads.find(
989 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
990 );
985 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
991986 return thread?.runtimeMode === "approval-required";
992987 });
993988 await waitFor(() => harness.startSession.mock.calls.length === 2);
994989 await Effect.runPromise(
995990 harness.engine.dispatch({
996991 type: "thread.turn.start",
997 commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-2"),
998 threadId: ThreadId.makeUnsafe("thread-1"),
992 commandId: CommandId.make("cmd-turn-start-runtime-mode-2"),
993 threadId: ThreadId.make("thread-1"),
999994 message: {
1000995 messageId: asMessageId("user-message-runtime-mode-2"),
1001996 role: "user",
......@@ -1012,16 +1007,16 @@ describe("ProviderCommandReactor", () => {
10121007
10131008 expect(harness.stopSession.mock.calls.length).toBe(0);
10141009 expect(harness.startSession.mock.calls[1]?.[1]).toMatchObject({
1015 threadId: ThreadId.makeUnsafe("thread-1"),
1010 threadId: ThreadId.make("thread-1"),
10161011 resumeCursor: { opaque: "resume-1" },
10171012 runtimeMode: "approval-required",
10181013 });
10191014 expect(harness.sendTurn.mock.calls[1]?.[0]).toMatchObject({
1020 threadId: ThreadId.makeUnsafe("thread-1"),
1015 threadId: ThreadId.make("thread-1"),
10211016 });
10221017
10231018 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1024 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1019 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
10251020 expect(thread?.session?.threadId).toBe("thread-1");
10261021 expect(thread?.session?.runtimeMode).toBe("approval-required");
10271022 });
......@@ -1035,10 +1030,10 @@ describe("ProviderCommandReactor", () => {
10351030 await Effect.runPromise(
10361031 harness.engine.dispatch({
10371032 type: "thread.session.set",
1038 commandId: CommandId.makeUnsafe("cmd-session-set-runtime-mode-claude"),
1039 threadId: ThreadId.makeUnsafe("thread-1"),
1033 commandId: CommandId.make("cmd-session-set-runtime-mode-claude"),
1034 threadId: ThreadId.make("thread-1"),
10401035 session: {
1041 threadId: ThreadId.makeUnsafe("thread-1"),
1036 threadId: ThreadId.make("thread-1"),
10421037 status: "ready",
10431038 providerName: "claudeAgent",
10441039 runtimeMode: "full-access",
......@@ -1053,8 +1048,8 @@ describe("ProviderCommandReactor", () => {
10531048 await Effect.runPromise(
10541049 harness.engine.dispatch({
10551050 type: "thread.runtime-mode.set",
1056 commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-claude-no-options"),
1057 threadId: ThreadId.makeUnsafe("thread-1"),
1051 commandId: CommandId.make("cmd-runtime-mode-set-claude-no-options"),
1052 threadId: ThreadId.make("thread-1"),
10581053 runtimeMode: "approval-required",
10591054 createdAt: now,
10601055 }),
......@@ -1078,8 +1073,8 @@ describe("ProviderCommandReactor", () => {
10781073 await Effect.runPromise(
10791074 harness.engine.dispatch({
10801075 type: "thread.turn.start",
1081 commandId: CommandId.makeUnsafe("cmd-turn-start-provider-switch-1"),
1082 threadId: ThreadId.makeUnsafe("thread-1"),
1076 commandId: CommandId.make("cmd-turn-start-provider-switch-1"),
1077 threadId: ThreadId.make("thread-1"),
10831078 message: {
10841079 messageId: asMessageId("user-message-provider-switch-1"),
10851080 role: "user",
......@@ -1098,8 +1093,8 @@ describe("ProviderCommandReactor", () => {
10981093 await Effect.runPromise(
10991094 harness.engine.dispatch({
11001095 type: "thread.turn.start",
1101 commandId: CommandId.makeUnsafe("cmd-turn-start-provider-switch-2"),
1102 threadId: ThreadId.makeUnsafe("thread-1"),
1096 commandId: CommandId.make("cmd-turn-start-provider-switch-2"),
1097 threadId: ThreadId.make("thread-1"),
11031098 message: {
11041099 messageId: asMessageId("user-message-provider-switch-2"),
11051100 role: "user",
......@@ -1118,9 +1113,7 @@ describe("ProviderCommandReactor", () => {
11181113
11191114 await waitFor(async () => {
11201115 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1121 const thread = readModel.threads.find(
1122 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
1123 );
1116 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
11241117 return (
11251118 thread?.activities.some((activity) => activity.kind === "provider.turn.start.failed") ??
11261119 false
......@@ -1132,7 +1125,7 @@ describe("ProviderCommandReactor", () => {
11321125 expect(harness.stopSession.mock.calls.length).toBe(0);
11331126
11341127 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1135 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1128 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
11361129 expect(thread?.session?.threadId).toBe("thread-1");
11371130 expect(thread?.session?.providerName).toBe("codex");
11381131 expect(thread?.session?.runtimeMode).toBe("approval-required");
......@@ -1152,8 +1145,8 @@ describe("ProviderCommandReactor", () => {
11521145 await Effect.runPromise(
11531146 harness.engine.dispatch({
11541147 type: "thread.runtime-mode.set",
1155 commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-initial-full-access-2"),
1156 threadId: ThreadId.makeUnsafe("thread-1"),
1148 commandId: CommandId.make("cmd-runtime-mode-set-initial-full-access-2"),
1149 threadId: ThreadId.make("thread-1"),
11571150 runtimeMode: "full-access",
11581151 createdAt: now,
11591152 }),
......@@ -1162,8 +1155,8 @@ describe("ProviderCommandReactor", () => {
11621155 await Effect.runPromise(
11631156 harness.engine.dispatch({
11641157 type: "thread.turn.start",
1165 commandId: CommandId.makeUnsafe("cmd-turn-start-restart-failure-1"),
1166 threadId: ThreadId.makeUnsafe("thread-1"),
1158 commandId: CommandId.make("cmd-turn-start-restart-failure-1"),
1159 threadId: ThreadId.make("thread-1"),
11671160 message: {
11681161 messageId: asMessageId("user-message-restart-failure-1"),
11691162 role: "user",
......@@ -1186,8 +1179,8 @@ describe("ProviderCommandReactor", () => {
11861179 await Effect.runPromise(
11871180 harness.engine.dispatch({
11881181 type: "thread.runtime-mode.set",
1189 commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-restart-failure"),
1190 threadId: ThreadId.makeUnsafe("thread-1"),
1182 commandId: CommandId.make("cmd-runtime-mode-set-restart-failure"),
1183 threadId: ThreadId.make("thread-1"),
11911184 runtimeMode: "approval-required",
11921185 createdAt: now,
11931186 }),
......@@ -1195,9 +1188,7 @@ describe("ProviderCommandReactor", () => {
11951188
11961189 await waitFor(async () => {
11971190 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1198 const thread = readModel.threads.find(
1199 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
1200 );
1191 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
12011192 return thread?.runtimeMode === "approval-required";
12021193 });
12031194 await waitFor(() => harness.startSession.mock.calls.length === 2);
......@@ -1207,7 +1198,7 @@ describe("ProviderCommandReactor", () => {
12071198 expect(harness.sendTurn.mock.calls.length).toBe(1);
12081199
12091200 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1210 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1201 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
12111202 expect(thread?.session?.threadId).toBe("thread-1");
12121203 expect(thread?.session?.runtimeMode).toBe("full-access");
12131204 });
......@@ -1219,10 +1210,10 @@ describe("ProviderCommandReactor", () => {
12191210 await Effect.runPromise(
12201211 harness.engine.dispatch({
12211212 type: "thread.session.set",
1222 commandId: CommandId.makeUnsafe("cmd-session-set"),
1223 threadId: ThreadId.makeUnsafe("thread-1"),
1213 commandId: CommandId.make("cmd-session-set"),
1214 threadId: ThreadId.make("thread-1"),
12241215 session: {
1225 threadId: ThreadId.makeUnsafe("thread-1"),
1216 threadId: ThreadId.make("thread-1"),
12261217 status: "running",
12271218 providerName: "codex",
12281219 runtimeMode: "approval-required",
......@@ -1237,8 +1228,8 @@ describe("ProviderCommandReactor", () => {
12371228 await Effect.runPromise(
12381229 harness.engine.dispatch({
12391230 type: "thread.turn.interrupt",
1240 commandId: CommandId.makeUnsafe("cmd-turn-interrupt"),
1241 threadId: ThreadId.makeUnsafe("thread-1"),
1231 commandId: CommandId.make("cmd-turn-interrupt"),
1232 threadId: ThreadId.make("thread-1"),
12421233 turnId: asTurnId("turn-1"),
12431234 createdAt: now,
12441235 }),
......@@ -1257,10 +1248,10 @@ describe("ProviderCommandReactor", () => {
12571248 await Effect.runPromise(
12581249 harness.engine.dispatch({
12591250 type: "thread.session.set",
1260 commandId: CommandId.makeUnsafe("cmd-session-set-for-approval"),
1261 threadId: ThreadId.makeUnsafe("thread-1"),
1251 commandId: CommandId.make("cmd-session-set-for-approval"),
1252 threadId: ThreadId.make("thread-1"),
12621253 session: {
1263 threadId: ThreadId.makeUnsafe("thread-1"),
1254 threadId: ThreadId.make("thread-1"),
12641255 status: "running",
12651256 providerName: "codex",
12661257 runtimeMode: "approval-required",
......@@ -1275,8 +1266,8 @@ describe("ProviderCommandReactor", () => {
12751266 await Effect.runPromise(
12761267 harness.engine.dispatch({
12771268 type: "thread.approval.respond",
1278 commandId: CommandId.makeUnsafe("cmd-approval-respond"),
1279 threadId: ThreadId.makeUnsafe("thread-1"),
1269 commandId: CommandId.make("cmd-approval-respond"),
1270 threadId: ThreadId.make("thread-1"),
12801271 requestId: asApprovalRequestId("approval-request-1"),
12811272 decision: "accept",
12821273 createdAt: now,
......@@ -1298,10 +1289,10 @@ describe("ProviderCommandReactor", () => {
12981289 await Effect.runPromise(
12991290 harness.engine.dispatch({
13001291 type: "thread.session.set",
1301 commandId: CommandId.makeUnsafe("cmd-session-set-for-user-input"),
1302 threadId: ThreadId.makeUnsafe("thread-1"),
1292 commandId: CommandId.make("cmd-session-set-for-user-input"),
1293 threadId: ThreadId.make("thread-1"),
13031294 session: {
1304 threadId: ThreadId.makeUnsafe("thread-1"),
1295 threadId: ThreadId.make("thread-1"),
13051296 status: "running",
13061297 providerName: "codex",
13071298 runtimeMode: "approval-required",
......@@ -1316,8 +1307,8 @@ describe("ProviderCommandReactor", () => {
13161307 await Effect.runPromise(
13171308 harness.engine.dispatch({
13181309 type: "thread.user-input.respond",
1319 commandId: CommandId.makeUnsafe("cmd-user-input-respond"),
1320 threadId: ThreadId.makeUnsafe("thread-1"),
1310 commandId: CommandId.make("cmd-user-input-respond"),
1311 threadId: ThreadId.make("thread-1"),
13211312 requestId: asApprovalRequestId("user-input-request-1"),
13221313 answers: {
13231314 sandbox_mode: "workspace-write",
......@@ -1352,10 +1343,10 @@ describe("ProviderCommandReactor", () => {
13521343 await Effect.runPromise(
13531344 harness.engine.dispatch({
13541345 type: "thread.session.set",
1355 commandId: CommandId.makeUnsafe("cmd-session-set-for-approval-error"),
1356 threadId: ThreadId.makeUnsafe("thread-1"),
1346 commandId: CommandId.make("cmd-session-set-for-approval-error"),
1347 threadId: ThreadId.make("thread-1"),
13571348 session: {
1358 threadId: ThreadId.makeUnsafe("thread-1"),
1349 threadId: ThreadId.make("thread-1"),
13591350 status: "running",
13601351 providerName: "codex",
13611352 runtimeMode: "approval-required",
......@@ -1370,10 +1361,10 @@ describe("ProviderCommandReactor", () => {
13701361 await Effect.runPromise(
13711362 harness.engine.dispatch({
13721363 type: "thread.activity.append",
1373 commandId: CommandId.makeUnsafe("cmd-approval-requested"),
1374 threadId: ThreadId.makeUnsafe("thread-1"),
1364 commandId: CommandId.make("cmd-approval-requested"),
1365 threadId: ThreadId.make("thread-1"),
13751366 activity: {
1376 id: EventId.makeUnsafe("activity-approval-requested"),
1367 id: EventId.make("activity-approval-requested"),
13771368 tone: "approval",
13781369 kind: "approval.requested",
13791370 summary: "Command approval requested",
......@@ -1391,8 +1382,8 @@ describe("ProviderCommandReactor", () => {
13911382 await Effect.runPromise(
13921383 harness.engine.dispatch({
13931384 type: "thread.approval.respond",
1394 commandId: CommandId.makeUnsafe("cmd-approval-respond-stale"),
1395 threadId: ThreadId.makeUnsafe("thread-1"),
1385 commandId: CommandId.make("cmd-approval-respond-stale"),
1386 threadId: ThreadId.make("thread-1"),
13961387 requestId: asApprovalRequestId("approval-request-1"),
13971388 decision: "acceptForSession",
13981389 createdAt: now,
......@@ -1401,9 +1392,7 @@ describe("ProviderCommandReactor", () => {
14011392
14021393 await waitFor(async () => {
14031394 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1404 const thread = readModel.threads.find(
1405 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
1406 );
1395 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
14071396 if (!thread) return false;
14081397 return thread.activities.some(
14091398 (activity) => activity.kind === "provider.approval.respond.failed",
......@@ -1411,7 +1400,7 @@ describe("ProviderCommandReactor", () => {
14111400 });
14121401
14131402 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1414 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1403 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
14151404 expect(thread).toBeDefined();
14161405
14171406 const failureActivity = thread?.activities.find(
......@@ -1449,10 +1438,10 @@ describe("ProviderCommandReactor", () => {
14491438 await Effect.runPromise(
14501439 harness.engine.dispatch({
14511440 type: "thread.session.set",
1452 commandId: CommandId.makeUnsafe("cmd-session-set-for-user-input-error"),
1453 threadId: ThreadId.makeUnsafe("thread-1"),
1441 commandId: CommandId.make("cmd-session-set-for-user-input-error"),
1442 threadId: ThreadId.make("thread-1"),
14541443 session: {
1455 threadId: ThreadId.makeUnsafe("thread-1"),
1444 threadId: ThreadId.make("thread-1"),
14561445 status: "running",
14571446 providerName: "claudeAgent",
14581447 runtimeMode: "approval-required",
......@@ -1467,10 +1456,10 @@ describe("ProviderCommandReactor", () => {
14671456 await Effect.runPromise(
14681457 harness.engine.dispatch({
14691458 type: "thread.activity.append",
1470 commandId: CommandId.makeUnsafe("cmd-user-input-requested"),
1471 threadId: ThreadId.makeUnsafe("thread-1"),
1459 commandId: CommandId.make("cmd-user-input-requested"),
1460 threadId: ThreadId.make("thread-1"),
14721461 activity: {
1473 id: EventId.makeUnsafe("activity-user-input-requested"),
1462 id: EventId.make("activity-user-input-requested"),
14741463 tone: "info",
14751464 kind: "user-input.requested",
14761465 summary: "User input requested",
......@@ -1500,8 +1489,8 @@ describe("ProviderCommandReactor", () => {
15001489 await Effect.runPromise(
15011490 harness.engine.dispatch({
15021491 type: "thread.user-input.respond",
1503 commandId: CommandId.makeUnsafe("cmd-user-input-respond-stale"),
1504 threadId: ThreadId.makeUnsafe("thread-1"),
1492 commandId: CommandId.make("cmd-user-input-respond-stale"),
1493 threadId: ThreadId.make("thread-1"),
15051494 requestId: asApprovalRequestId("user-input-request-1"),
15061495 answers: {
15071496 sandbox_mode: "workspace-write",
......@@ -1512,9 +1501,7 @@ describe("ProviderCommandReactor", () => {
15121501
15131502 await waitFor(async () => {
15141503 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1515 const thread = readModel.threads.find(
1516 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
1517 );
1504 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
15181505 if (!thread) return false;
15191506 return thread.activities.some(
15201507 (activity) => activity.kind === "provider.user-input.respond.failed",
......@@ -1522,7 +1509,7 @@ describe("ProviderCommandReactor", () => {
15221509 });
15231510
15241511 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1525 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1512 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
15261513 expect(thread).toBeDefined();
15271514
15281515 const failureActivity = thread?.activities.find(
......@@ -1551,10 +1538,10 @@ describe("ProviderCommandReactor", () => {
15511538 await Effect.runPromise(
15521539 harness.engine.dispatch({
15531540 type: "thread.session.set",
1554 commandId: CommandId.makeUnsafe("cmd-session-set-for-stop"),
1555 threadId: ThreadId.makeUnsafe("thread-1"),
1541 commandId: CommandId.make("cmd-session-set-for-stop"),
1542 threadId: ThreadId.make("thread-1"),
15561543 session: {
1557 threadId: ThreadId.makeUnsafe("thread-1"),
1544 threadId: ThreadId.make("thread-1"),
15581545 status: "ready",
15591546 providerName: "codex",
15601547 runtimeMode: "approval-required",
......@@ -1569,15 +1556,15 @@ describe("ProviderCommandReactor", () => {
15691556 await Effect.runPromise(
15701557 harness.engine.dispatch({
15711558 type: "thread.session.stop",
1572 commandId: CommandId.makeUnsafe("cmd-session-stop"),
1573 threadId: ThreadId.makeUnsafe("thread-1"),
1559 commandId: CommandId.make("cmd-session-stop"),
1560 threadId: ThreadId.make("thread-1"),
15741561 createdAt: now,
15751562 }),
15761563 );
15771564
15781565 await waitFor(() => harness.stopSession.mock.calls.length === 1);
15791566 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1580 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1567 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
15811568 expect(thread?.session).not.toBeNull();
15821569 expect(thread?.session?.status).toBe("stopped");
15831570 expect(thread?.session?.threadId).toBe("thread-1");
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+2-2
......@@ -67,7 +67,7 @@ const turnStartKeyForEvent = (event: ProviderIntentEvent): string =>
6767 event.commandId !== null ? `command:${event.commandId}` : `event:${event.eventId}`;
6868
6969const serverCommandId = (tag: string): CommandId =>
70 CommandId.makeUnsafe(`server:${tag}:${crypto.randomUUID()}`);
70 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);
7171
7272const HANDLED_TURN_START_KEY_MAX = 10_000;
7373const HANDLED_TURN_START_KEY_TTL = Duration.minutes(30);
......@@ -186,7 +186,7 @@ const make = Effect.gen(function* () {
186186 commandId: serverCommandId("provider-failure-activity"),
187187 threadId: input.threadId,
188188 activity: {
189 id: EventId.makeUnsafe(crypto.randomUUID()),
189 id: EventId.make(crypto.randomUUID()),
190190 tone: "error",
191191 kind: input.kind,
192192 summary: input.summary,
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts+40-48
......@@ -47,12 +47,12 @@ function makeTestServerSettingsLayer(overrides: Partial<ServerSettings> = {}) {
4747 return ServerSettingsService.layerTest(overrides);
4848}
4949
50const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
51const asItemId = (value: string): ProviderItemId => ProviderItemId.makeUnsafe(value);
52const asEventId = (value: string): EventId => EventId.makeUnsafe(value);
53const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
54const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value);
55const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
50const asProjectId = (value: string): ProjectId => ProjectId.make(value);
51const asItemId = (value: string): ProviderItemId => ProviderItemId.make(value);
52const asEventId = (value: string): EventId => EventId.make(value);
53const asMessageId = (value: string): MessageId => MessageId.make(value);
54const asThreadId = (value: string): ThreadId => ThreadId.make(value);
55const asTurnId = (value: string): TurnId => TurnId.make(value);
5656
5757type LegacyProviderRuntimeEvent = {
5858 readonly type: string;
......@@ -227,7 +227,7 @@ describe("ProviderRuntimeIngestion", () => {
227227 await Effect.runPromise(
228228 engine.dispatch({
229229 type: "project.create",
230 commandId: CommandId.makeUnsafe("cmd-provider-project-create"),
230 commandId: CommandId.make("cmd-provider-project-create"),
231231 projectId: asProjectId("project-1"),
232232 title: "Provider Project",
233233 workspaceRoot,
......@@ -241,8 +241,8 @@ describe("ProviderRuntimeIngestion", () => {
241241 await Effect.runPromise(
242242 engine.dispatch({
243243 type: "thread.create",
244 commandId: CommandId.makeUnsafe("cmd-thread-create"),
245 threadId: ThreadId.makeUnsafe("thread-1"),
244 commandId: CommandId.make("cmd-thread-create"),
245 threadId: ThreadId.make("thread-1"),
246246 projectId: asProjectId("project-1"),
247247 title: "Thread",
248248 modelSelection: {
......@@ -259,10 +259,10 @@ describe("ProviderRuntimeIngestion", () => {
259259 await Effect.runPromise(
260260 engine.dispatch({
261261 type: "thread.session.set",
262 commandId: CommandId.makeUnsafe("cmd-session-seed"),
263 threadId: ThreadId.makeUnsafe("thread-1"),
262 commandId: CommandId.make("cmd-session-seed"),
263 threadId: ThreadId.make("thread-1"),
264264 session: {
265 threadId: ThreadId.makeUnsafe("thread-1"),
265 threadId: ThreadId.make("thread-1"),
266266 status: "ready",
267267 providerName: "codex",
268268 runtimeMode: "approval-required",
......@@ -277,7 +277,7 @@ describe("ProviderRuntimeIngestion", () => {
277277 provider: "codex",
278278 status: "ready",
279279 runtimeMode: "approval-required",
280 threadId: ThreadId.makeUnsafe("thread-1"),
280 threadId: ThreadId.make("thread-1"),
281281 createdAt,
282282 updatedAt: createdAt,
283283 });
......@@ -457,9 +457,7 @@ describe("ProviderRuntimeIngestion", () => {
457457
458458 await harness.drain();
459459 const midReadModel = await Effect.runPromise(harness.engine.getReadModel());
460 const midThread = midReadModel.threads.find(
461 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
462 );
460 const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
463461 expect(midThread?.session?.status).toBe("running");
464462 expect(midThread?.session?.activeTurnId).toBe("turn-midturn-lifecycle");
465463
......@@ -486,10 +484,10 @@ describe("ProviderRuntimeIngestion", () => {
486484 await Effect.runPromise(
487485 harness.engine.dispatch({
488486 type: "thread.session.set",
489 commandId: CommandId.makeUnsafe("cmd-session-seed-claude-placeholder"),
490 threadId: ThreadId.makeUnsafe("thread-1"),
487 commandId: CommandId.make("cmd-session-seed-claude-placeholder"),
488 threadId: ThreadId.make("thread-1"),
491489 session: {
492 threadId: ThreadId.makeUnsafe("thread-1"),
490 threadId: ThreadId.make("thread-1"),
493491 status: "ready",
494492 providerName: "claudeAgent",
495493 runtimeMode: "approval-required",
......@@ -564,9 +562,7 @@ describe("ProviderRuntimeIngestion", () => {
564562
565563 await harness.drain();
566564 const midReadModel = await Effect.runPromise(harness.engine.getReadModel());
567 const midThread = midReadModel.threads.find(
568 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
569 );
565 const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
570566 expect(midThread?.session?.status).toBe("running");
571567 expect(midThread?.session?.activeTurnId).toBe("turn-primary");
572568
......@@ -618,9 +614,7 @@ describe("ProviderRuntimeIngestion", () => {
618614
619615 await harness.drain();
620616 const midReadModel = await Effect.runPromise(harness.engine.getReadModel());
621 const midThread = midReadModel.threads.find(
622 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
623 );
617 const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
624618 expect(midThread?.session?.status).toBe("running");
625619 expect(midThread?.session?.activeTurnId).toBe("turn-guarded-main");
626620
......@@ -770,7 +764,7 @@ describe("ProviderRuntimeIngestion", () => {
770764 await Effect.runPromise(
771765 harness.engine.dispatch({
772766 type: "thread.create",
773 commandId: CommandId.makeUnsafe("cmd-thread-create-plan-source"),
767 commandId: CommandId.make("cmd-thread-create-plan-source"),
774768 threadId: sourceThreadId,
775769 projectId: asProjectId("project-1"),
776770 title: "Plan Source",
......@@ -788,7 +782,7 @@ describe("ProviderRuntimeIngestion", () => {
788782 await Effect.runPromise(
789783 harness.engine.dispatch({
790784 type: "thread.session.set",
791 commandId: CommandId.makeUnsafe("cmd-session-set-plan-source"),
785 commandId: CommandId.make("cmd-session-set-plan-source"),
792786 threadId: sourceThreadId,
793787 session: {
794788 threadId: sourceThreadId,
......@@ -805,7 +799,7 @@ describe("ProviderRuntimeIngestion", () => {
805799 await Effect.runPromise(
806800 harness.engine.dispatch({
807801 type: "thread.create",
808 commandId: CommandId.makeUnsafe("cmd-thread-create-plan-target"),
802 commandId: CommandId.make("cmd-thread-create-plan-target"),
809803 threadId: targetThreadId,
810804 projectId: asProjectId("project-1"),
811805 title: "Plan Target",
......@@ -823,7 +817,7 @@ describe("ProviderRuntimeIngestion", () => {
823817 await Effect.runPromise(
824818 harness.engine.dispatch({
825819 type: "thread.session.set",
826 commandId: CommandId.makeUnsafe("cmd-session-set-plan-target"),
820 commandId: CommandId.make("cmd-session-set-plan-target"),
827821 threadId: targetThreadId,
828822 session: {
829823 threadId: targetThreadId,
......@@ -882,7 +876,7 @@ describe("ProviderRuntimeIngestion", () => {
882876 await Effect.runPromise(
883877 harness.engine.dispatch({
884878 type: "thread.turn.start",
885 commandId: CommandId.makeUnsafe("cmd-turn-start-plan-target"),
879 commandId: CommandId.make("cmd-turn-start-plan-target"),
886880 threadId: targetThreadId,
887881 message: {
888882 messageId: asMessageId("msg-plan-target"),
......@@ -957,7 +951,7 @@ describe("ProviderRuntimeIngestion", () => {
957951 await Effect.runPromise(
958952 harness.engine.dispatch({
959953 type: "thread.create",
960 commandId: CommandId.makeUnsafe("cmd-thread-create-plan-source-guarded"),
954 commandId: CommandId.make("cmd-thread-create-plan-source-guarded"),
961955 threadId: sourceThreadId,
962956 projectId: asProjectId("project-1"),
963957 title: "Plan Source",
......@@ -975,7 +969,7 @@ describe("ProviderRuntimeIngestion", () => {
975969 await Effect.runPromise(
976970 harness.engine.dispatch({
977971 type: "thread.session.set",
978 commandId: CommandId.makeUnsafe("cmd-session-set-plan-source-guarded"),
972 commandId: CommandId.make("cmd-session-set-plan-source-guarded"),
979973 threadId: sourceThreadId,
980974 session: {
981975 threadId: sourceThreadId,
......@@ -1051,7 +1045,7 @@ describe("ProviderRuntimeIngestion", () => {
10511045 await Effect.runPromise(
10521046 harness.engine.dispatch({
10531047 type: "thread.turn.start",
1054 commandId: CommandId.makeUnsafe("cmd-turn-start-plan-target-guarded"),
1048 commandId: CommandId.make("cmd-turn-start-plan-target-guarded"),
10551049 threadId: targetThreadId,
10561050 message: {
10571051 messageId: asMessageId("msg-plan-target-guarded"),
......@@ -1110,7 +1104,7 @@ describe("ProviderRuntimeIngestion", () => {
11101104 await Effect.runPromise(
11111105 harness.engine.dispatch({
11121106 type: "thread.create",
1113 commandId: CommandId.makeUnsafe("cmd-thread-create-plan-source-unrelated"),
1107 commandId: CommandId.make("cmd-thread-create-plan-source-unrelated"),
11141108 threadId: sourceThreadId,
11151109 projectId: asProjectId("project-1"),
11161110 title: "Plan Source",
......@@ -1128,7 +1122,7 @@ describe("ProviderRuntimeIngestion", () => {
11281122 await Effect.runPromise(
11291123 harness.engine.dispatch({
11301124 type: "thread.session.set",
1131 commandId: CommandId.makeUnsafe("cmd-session-set-plan-source-unrelated"),
1125 commandId: CommandId.make("cmd-session-set-plan-source-unrelated"),
11321126 threadId: sourceThreadId,
11331127 session: {
11341128 threadId: sourceThreadId,
......@@ -1145,7 +1139,7 @@ describe("ProviderRuntimeIngestion", () => {
11451139 await Effect.runPromise(
11461140 harness.engine.dispatch({
11471141 type: "thread.create",
1148 commandId: CommandId.makeUnsafe("cmd-thread-create-plan-target-unrelated"),
1142 commandId: CommandId.make("cmd-thread-create-plan-target-unrelated"),
11491143 threadId: targetThreadId,
11501144 projectId: asProjectId("project-1"),
11511145 title: "Plan Target",
......@@ -1163,7 +1157,7 @@ describe("ProviderRuntimeIngestion", () => {
11631157 await Effect.runPromise(
11641158 harness.engine.dispatch({
11651159 type: "thread.session.set",
1166 commandId: CommandId.makeUnsafe("cmd-session-set-plan-target-unrelated"),
1160 commandId: CommandId.make("cmd-session-set-plan-target-unrelated"),
11671161 threadId: targetThreadId,
11681162 session: {
11691163 threadId: targetThreadId,
......@@ -1213,7 +1207,7 @@ describe("ProviderRuntimeIngestion", () => {
12131207 await Effect.runPromise(
12141208 harness.engine.dispatch({
12151209 type: "thread.turn.start",
1216 commandId: CommandId.makeUnsafe("cmd-turn-start-plan-target-unrelated"),
1210 commandId: CommandId.make("cmd-turn-start-plan-target-unrelated"),
12171211 threadId: targetThreadId,
12181212 message: {
12191213 messageId: asMessageId("msg-plan-target-unrelated"),
......@@ -1364,9 +1358,7 @@ describe("ProviderRuntimeIngestion", () => {
13641358
13651359 await harness.drain();
13661360 const midReadModel = await Effect.runPromise(harness.engine.getReadModel());
1367 const midThread = midReadModel.threads.find(
1368 (entry) => entry.id === ThreadId.makeUnsafe("thread-1"),
1369 );
1361 const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
13701362 expect(
13711363 midThread?.messages.some(
13721364 (message: ProviderRuntimeTestMessage) => message.id === "assistant:item-buffered",
......@@ -1407,8 +1399,8 @@ describe("ProviderRuntimeIngestion", () => {
14071399 await Effect.runPromise(
14081400 harness.engine.dispatch({
14091401 type: "thread.turn.start",
1410 commandId: CommandId.makeUnsafe("cmd-turn-start-streaming-mode"),
1411 threadId: ThreadId.makeUnsafe("thread-1"),
1402 commandId: CommandId.make("cmd-turn-start-streaming-mode"),
1403 threadId: ThreadId.make("thread-1"),
14121404 message: {
14131405 messageId: asMessageId("message-streaming-mode"),
14141406 role: "user",
......@@ -1649,7 +1641,7 @@ describe("ProviderRuntimeIngestion", () => {
16491641 provider: "codex",
16501642 createdAt: now,
16511643 threadId: asThreadId("thread-1"),
1652 requestId: ApprovalRequestId.makeUnsafe("req-open"),
1644 requestId: ApprovalRequestId.make("req-open"),
16531645 payload: {
16541646 requestType: "command_execution_approval",
16551647 detail: "pwd",
......@@ -1662,7 +1654,7 @@ describe("ProviderRuntimeIngestion", () => {
16621654 provider: "codex",
16631655 createdAt: now,
16641656 threadId: asThreadId("thread-1"),
1665 requestId: ApprovalRequestId.makeUnsafe("req-open"),
1657 requestId: ApprovalRequestId.make("req-open"),
16661658 payload: {
16671659 requestType: "command_execution_approval",
16681660 decision: "accept",
......@@ -1681,7 +1673,7 @@ describe("ProviderRuntimeIngestion", () => {
16811673 );
16821674
16831675 const readModel = await Effect.runPromise(harness.engine.getReadModel());
1684 const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"));
1676 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
16851677 expect(thread).toBeDefined();
16861678
16871679 const requested = thread?.activities.find(
......@@ -2286,7 +2278,7 @@ describe("ProviderRuntimeIngestion", () => {
22862278 createdAt: now,
22872279 threadId: asThreadId("thread-1"),
22882280 turnId: asTurnId("turn-user-input"),
2289 requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"),
2281 requestId: ApprovalRequestId.make("req-user-input-1"),
22902282 payload: {
22912283 questions: [
22922284 {
......@@ -2311,7 +2303,7 @@ describe("ProviderRuntimeIngestion", () => {
23112303 createdAt: new Date().toISOString(),
23122304 threadId: asThreadId("thread-1"),
23132305 turnId: asTurnId("turn-user-input"),
2314 requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"),
2306 requestId: ApprovalRequestId.make("req-user-input-1"),
23152307 payload: {
23162308 answers: {
23172309 sandbox_mode: "workspace-write",
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts+8-10
......@@ -30,7 +30,7 @@ import { ServerSettingsService } from "../../serverSettings.ts";
3030
3131const providerTurnKey = (threadId: ThreadId, turnId: TurnId) => `${threadId}:${turnId}`;
3232const providerCommandId = (event: ProviderRuntimeEvent, tag: string): CommandId =>
33 CommandId.makeUnsafe(`provider:${event.eventId}:${tag}:${crypto.randomUUID()}`);
33 CommandId.make(`provider:${event.eventId}:${tag}:${crypto.randomUUID()}`);
3434
3535const TURN_MESSAGE_IDS_BY_TURN_CACHE_CAPACITY = 10_000;
3636const TURN_MESSAGE_IDS_BY_TURN_TTL = Duration.minutes(120);
......@@ -57,11 +57,11 @@ type RuntimeIngestionInput =
5757 };
5858
5959function toTurnId(value: TurnId | string | undefined): TurnId | undefined {
60 return value === undefined ? undefined : TurnId.makeUnsafe(String(value));
60 return value === undefined ? undefined : TurnId.make(String(value));
6161}
6262
6363function toApprovalRequestId(value: string | undefined): ApprovalRequestId | undefined {
64 return value === undefined ? undefined : ApprovalRequestId.makeUnsafe(value);
64 return value === undefined ? undefined : ApprovalRequestId.make(value);
6565}
6666
6767function sameId(left: string | null | undefined, right: string | null | undefined): boolean {
......@@ -857,7 +857,7 @@ const make = Effect.fn("make")(function* () {
857857
858858 yield* orchestrationEngine.dispatch({
859859 type: "thread.proposed-plan.upsert",
860 commandId: CommandId.makeUnsafe(
860 commandId: CommandId.make(
861861 `provider:source-proposed-plan-implemented:${implementationThreadId}:${crypto.randomUUID()}`,
862862 ),
863863 threadId: sourceThread.id,
......@@ -1003,7 +1003,7 @@ const make = Effect.fn("make")(function* () {
10031003 event.type === "turn.proposed.delta" ? event.payload.delta : undefined;
10041004
10051005 if (assistantDelta && assistantDelta.length > 0) {
1006 const assistantMessageId = MessageId.makeUnsafe(
1006 const assistantMessageId = MessageId.make(
10071007 `assistant:${event.itemId ?? event.turnId ?? event.eventId}`,
10081008 );
10091009 const turnId = toTurnId(event.turnId);
......@@ -1049,9 +1049,7 @@ const make = Effect.fn("make")(function* () {
10491049 const assistantCompletion =
10501050 event.type === "item.completed" && event.payload.itemType === "assistant_message"
10511051 ? {
1052 messageId: MessageId.makeUnsafe(
1053 `assistant:${event.itemId ?? event.turnId ?? event.eventId}`,
1054 ),
1052 messageId: MessageId.make(`assistant:${event.itemId ?? event.turnId ?? event.eventId}`),
10551053 fallbackText: event.payload.detail,
10561054 }
10571055 : undefined;
......@@ -1186,7 +1184,7 @@ const make = Effect.fn("make")(function* () {
11861184 if (thread.checkpoints.some((c) => c.turnId === turnId)) {
11871185 // Already tracked; no-op.
11881186 } else {
1189 const assistantMessageId = MessageId.makeUnsafe(
1187 const assistantMessageId = MessageId.make(
11901188 `assistant:${event.itemId ?? event.turnId ?? event.eventId}`,
11911189 );
11921190 const maxTurnCount = thread.checkpoints.reduce(
......@@ -1199,7 +1197,7 @@ const make = Effect.fn("make")(function* () {
11991197 threadId: thread.id,
12001198 turnId,
12011199 completedAt: now,
1202 checkpointRef: CheckpointRef.makeUnsafe(`provider-diff:${event.eventId}`),
1200 checkpointRef: CheckpointRef.make(`provider-diff:${event.eventId}`),
12031201 status: "missing",
12041202 files: [],
12051203 assistantMessageId,
apps/server/src/orchestration/Services/CheckpointReactor.ts+4-5
......@@ -6,7 +6,7 @@
66 *
77 * @module CheckpointReactor
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect, Scope } from "effect";
1111
1212/**
......@@ -34,7 +34,6 @@ export interface CheckpointReactorShape {
3434/**
3535 * CheckpointReactor - Service tag for checkpoint reactor workers.
3636 */
37export class CheckpointReactor extends ServiceMap.Service<
38 CheckpointReactor,
39 CheckpointReactorShape
40>()("t3/orchestration/Services/CheckpointReactor") {}
37export class CheckpointReactor extends Context.Service<CheckpointReactor, CheckpointReactorShape>()(
38 "t3/orchestration/Services/CheckpointReactor",
39) {}
apps/server/src/orchestration/Services/OrchestrationEngine.ts+3-3
......@@ -5,7 +5,7 @@
55 * `OrchestrationEventStore` persistence. It does not own provider process
66 * management or transport concerns (e.g. websocket request parsing).
77 *
8 * Uses Effect `ServiceMap.Service` for dependency injection. Command dispatch,
8 * Uses Effect `Context.Service` for dependency injection. Command dispatch,
99 * replay, and unknown-input decoding all return typed domain errors.
1010 *
1111 * @module OrchestrationEngineService
......@@ -15,7 +15,7 @@ import type {
1515 OrchestrationEvent,
1616 OrchestrationReadModel,
1717} from "@t3tools/contracts";
18import { ServiceMap } from "effect";
18import { Context } from "effect";
1919import type { Effect, Stream } from "effect";
2020
2121import type { OrchestrationDispatchError } from "../Errors.ts";
......@@ -74,7 +74,7 @@ export interface OrchestrationEngineShape {
7474 * })
7575 * ```
7676 */
77export class OrchestrationEngineService extends ServiceMap.Service<
77export class OrchestrationEngineService extends Context.Service<
7878 OrchestrationEngineService,
7979 OrchestrationEngineShape
8080>()("t3/orchestration/Services/OrchestrationEngine/OrchestrationEngineService") {}
apps/server/src/orchestration/Services/OrchestrationReactor.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module OrchestrationReactor
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect, Scope } from "effect";
1111
1212/**
......@@ -25,7 +25,7 @@ export interface OrchestrationReactorShape {
2525/**
2626 * OrchestrationReactor - Service tag for orchestration reactor coordination.
2727 */
28export class OrchestrationReactor extends ServiceMap.Service<
28export class OrchestrationReactor extends Context.Service<
2929 OrchestrationReactor,
3030 OrchestrationReactorShape
3131>()("t3/orchestration/Services/OrchestrationReactor") {}
apps/server/src/orchestration/Services/ProjectionPipeline.ts+2-2
......@@ -7,7 +7,7 @@
77 * @module OrchestrationProjectionPipeline
88 */
99import type { OrchestrationEvent } from "@t3tools/contracts";
10import { ServiceMap } from "effect";
10import { Context } from "effect";
1111import type { Effect } from "effect";
1212
1313import type { ProjectionRepositoryError } from "../../persistence/Errors.ts";
......@@ -36,7 +36,7 @@ export interface OrchestrationProjectionPipelineShape {
3636/**
3737 * OrchestrationProjectionPipeline - Service tag for orchestration projections.
3838 */
39export class OrchestrationProjectionPipeline extends ServiceMap.Service<
39export class OrchestrationProjectionPipeline extends Context.Service<
4040 OrchestrationProjectionPipeline,
4141 OrchestrationProjectionPipelineShape
4242>()("t3/orchestration/Services/ProjectionPipeline/OrchestrationProjectionPipeline") {}
apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts+2-2
......@@ -13,7 +13,7 @@ import type {
1313 ProjectId,
1414 ThreadId,
1515} from "@t3tools/contracts";
16import { ServiceMap } from "effect";
16import { Context } from "effect";
1717import type { Option } from "effect";
1818import type { Effect } from "effect";
1919
......@@ -74,7 +74,7 @@ export interface ProjectionSnapshotQueryShape {
7474/**
7575 * ProjectionSnapshotQuery - Service tag for projection snapshot queries.
7676 */
77export class ProjectionSnapshotQuery extends ServiceMap.Service<
77export class ProjectionSnapshotQuery extends Context.Service<
7878 ProjectionSnapshotQuery,
7979 ProjectionSnapshotQueryShape
8080>()("t3/orchestration/Services/ProjectionSnapshotQuery") {}
apps/server/src/orchestration/Services/ProviderCommandReactor.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module ProviderCommandReactor
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect, Scope } from "effect";
1111
1212/**
......@@ -34,7 +34,7 @@ export interface ProviderCommandReactorShape {
3434/**
3535 * ProviderCommandReactor - Service tag for provider command reaction workers.
3636 */
37export class ProviderCommandReactor extends ServiceMap.Service<
37export class ProviderCommandReactor extends Context.Service<
3838 ProviderCommandReactor,
3939 ProviderCommandReactorShape
4040>()("t3/orchestration/Services/ProviderCommandReactor") {}
apps/server/src/orchestration/Services/ProviderRuntimeIngestion.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module ProviderRuntimeIngestionService
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect, Scope } from "effect";
1111
1212/**
......@@ -34,7 +34,7 @@ export interface ProviderRuntimeIngestionShape {
3434/**
3535 * ProviderRuntimeIngestionService - Service tag for runtime ingestion workers.
3636 */
37export class ProviderRuntimeIngestionService extends ServiceMap.Service<
37export class ProviderRuntimeIngestionService extends Context.Service<
3838 ProviderRuntimeIngestionService,
3939 ProviderRuntimeIngestionShape
4040>()("t3/orchestration/Services/ProviderRuntimeIngestion/ProviderRuntimeIngestionService") {}
apps/server/src/orchestration/Services/RuntimeReceiptBus.ts+4-5
......@@ -15,7 +15,7 @@
1515 * @module RuntimeReceiptBus
1616 */
1717import { CheckpointRef, IsoDateTime, NonNegativeInt, ThreadId, TurnId } from "@t3tools/contracts";
18import { Schema, ServiceMap } from "effect";
18import { Schema, Context } from "effect";
1919import type { Effect, Stream } from "effect";
2020
2121export const CheckpointBaselineCapturedReceipt = Schema.Struct({
......@@ -59,7 +59,6 @@ export interface RuntimeReceiptBusShape {
5959 readonly streamEventsForTest: Stream.Stream<OrchestrationRuntimeReceipt>;
6060}
6161
62export class RuntimeReceiptBus extends ServiceMap.Service<
63 RuntimeReceiptBus,
64 RuntimeReceiptBusShape
65>()("t3/orchestration/Services/RuntimeReceiptBus") {}
62export class RuntimeReceiptBus extends Context.Service<RuntimeReceiptBus, RuntimeReceiptBusShape>()(
63 "t3/orchestration/Services/RuntimeReceiptBus",
64) {}
apps/server/src/orchestration/commandInvariants.test.ts+24-26
......@@ -25,7 +25,7 @@ const readModel: OrchestrationReadModel = {
2525 updatedAt: now,
2626 projects: [
2727 {
28 id: ProjectId.makeUnsafe("project-a"),
28 id: ProjectId.make("project-a"),
2929 title: "Project A",
3030 workspaceRoot: "/tmp/project-a",
3131 defaultModelSelection: {
......@@ -38,7 +38,7 @@ const readModel: OrchestrationReadModel = {
3838 deletedAt: null,
3939 },
4040 {
41 id: ProjectId.makeUnsafe("project-b"),
41 id: ProjectId.make("project-b"),
4242 title: "Project B",
4343 workspaceRoot: "/tmp/project-b",
4444 defaultModelSelection: {
......@@ -53,8 +53,8 @@ const readModel: OrchestrationReadModel = {
5353 ],
5454 threads: [
5555 {
56 id: ThreadId.makeUnsafe("thread-1"),
57 projectId: ProjectId.makeUnsafe("project-a"),
56 id: ThreadId.make("thread-1"),
57 projectId: ProjectId.make("project-a"),
5858 title: "Thread A",
5959 modelSelection: {
6060 provider: "codex",
......@@ -76,8 +76,8 @@ const readModel: OrchestrationReadModel = {
7676 deletedAt: null,
7777 },
7878 {
79 id: ThreadId.makeUnsafe("thread-2"),
80 projectId: ProjectId.makeUnsafe("project-b"),
79 id: ThreadId.make("thread-2"),
80 projectId: ProjectId.make("project-b"),
8181 title: "Thread B",
8282 modelSelection: {
8383 provider: "codex",
......@@ -103,10 +103,10 @@ const readModel: OrchestrationReadModel = {
103103
104104const messageSendCommand: OrchestrationCommand = {
105105 type: "thread.turn.start",
106 commandId: CommandId.makeUnsafe("cmd-1"),
107 threadId: ThreadId.makeUnsafe("thread-1"),
106 commandId: CommandId.make("cmd-1"),
107 threadId: ThreadId.make("thread-1"),
108108 message: {
109 messageId: MessageId.makeUnsafe("msg-1"),
109 messageId: MessageId.make("msg-1"),
110110 role: "user",
111111 text: "hello",
112112 attachments: [],
......@@ -118,13 +118,11 @@ const messageSendCommand: OrchestrationCommand = {
118118
119119describe("commandInvariants", () => {
120120 it("finds threads by id and project", () => {
121 expect(findThreadById(readModel, ThreadId.makeUnsafe("thread-1"))?.projectId).toBe("project-a");
122 expect(findThreadById(readModel, ThreadId.makeUnsafe("missing"))).toBeUndefined();
121 expect(findThreadById(readModel, ThreadId.make("thread-1"))?.projectId).toBe("project-a");
122 expect(findThreadById(readModel, ThreadId.make("missing"))).toBeUndefined();
123123 expect(
124 listThreadsByProjectId(readModel, ProjectId.makeUnsafe("project-b")).map(
125 (thread) => thread.id,
126 ),
127 ).toEqual([ThreadId.makeUnsafe("thread-2")]);
124 listThreadsByProjectId(readModel, ProjectId.make("project-b")).map((thread) => thread.id),
125 ).toEqual([ThreadId.make("thread-2")]);
128126 });
129127
130128 it("requires existing thread", async () => {
......@@ -132,17 +130,17 @@ describe("commandInvariants", () => {
132130 requireThread({
133131 readModel,
134132 command: messageSendCommand,
135 threadId: ThreadId.makeUnsafe("thread-1"),
133 threadId: ThreadId.make("thread-1"),
136134 }),
137135 );
138 expect(thread.id).toBe(ThreadId.makeUnsafe("thread-1"));
136 expect(thread.id).toBe(ThreadId.make("thread-1"));
139137
140138 await expect(
141139 Effect.runPromise(
142140 requireThread({
143141 readModel,
144142 command: messageSendCommand,
145 threadId: ThreadId.makeUnsafe("missing"),
143 threadId: ThreadId.make("missing"),
146144 }),
147145 ),
148146 ).rejects.toThrow("does not exist");
......@@ -154,9 +152,9 @@ describe("commandInvariants", () => {
154152 readModel,
155153 command: {
156154 type: "thread.create",
157 commandId: CommandId.makeUnsafe("cmd-2"),
158 threadId: ThreadId.makeUnsafe("thread-3"),
159 projectId: ProjectId.makeUnsafe("project-a"),
155 commandId: CommandId.make("cmd-2"),
156 threadId: ThreadId.make("thread-3"),
157 projectId: ProjectId.make("project-a"),
160158 title: "new",
161159 modelSelection: {
162160 provider: "codex",
......@@ -168,7 +166,7 @@ describe("commandInvariants", () => {
168166 worktreePath: null,
169167 createdAt: now,
170168 },
171 threadId: ThreadId.makeUnsafe("thread-3"),
169 threadId: ThreadId.make("thread-3"),
172170 }),
173171 );
174172
......@@ -178,9 +176,9 @@ describe("commandInvariants", () => {
178176 readModel,
179177 command: {
180178 type: "thread.create",
181 commandId: CommandId.makeUnsafe("cmd-3"),
182 threadId: ThreadId.makeUnsafe("thread-1"),
183 projectId: ProjectId.makeUnsafe("project-a"),
179 commandId: CommandId.make("cmd-3"),
180 threadId: ThreadId.make("thread-1"),
181 projectId: ProjectId.make("project-a"),
184182 title: "dup",
185183 modelSelection: {
186184 provider: "codex",
......@@ -192,7 +190,7 @@ describe("commandInvariants", () => {
192190 worktreePath: null,
193191 createdAt: now,
194192 },
195 threadId: ThreadId.makeUnsafe("thread-1"),
193 threadId: ThreadId.make("thread-1"),
196194 }),
197195 ),
198196 ).rejects.toThrow("already exists");
apps/server/src/orchestration/decider.projectScripts.test.ts+34-34
......@@ -12,9 +12,9 @@ import { Effect } from "effect";
1212import { decideOrchestrationCommand } from "./decider.ts";
1313import { createEmptyReadModel, projectEvent } from "./projector.ts";
1414
15const asEventId = (value: string): EventId => EventId.makeUnsafe(value);
16const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);
17const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
15const asEventId = (value: string): EventId => EventId.make(value);
16const asProjectId = (value: string): ProjectId => ProjectId.make(value);
17const asMessageId = (value: string): MessageId => MessageId.make(value);
1818
1919describe("decider project scripts", () => {
2020 it("emits empty scripts on project.create", async () => {
......@@ -25,7 +25,7 @@ describe("decider project scripts", () => {
2525 decideOrchestrationCommand({
2626 command: {
2727 type: "project.create",
28 commandId: CommandId.makeUnsafe("cmd-project-create-scripts"),
28 commandId: CommandId.make("cmd-project-create-scripts"),
2929 projectId: asProjectId("project-scripts"),
3030 title: "Scripts",
3131 workspaceRoot: "/tmp/scripts",
......@@ -51,9 +51,9 @@ describe("decider project scripts", () => {
5151 aggregateId: asProjectId("project-scripts"),
5252 type: "project.created",
5353 occurredAt: now,
54 commandId: CommandId.makeUnsafe("cmd-project-create-scripts"),
54 commandId: CommandId.make("cmd-project-create-scripts"),
5555 causationEventId: null,
56 correlationId: CommandId.makeUnsafe("cmd-project-create-scripts"),
56 correlationId: CommandId.make("cmd-project-create-scripts"),
5757 metadata: {},
5858 payload: {
5959 projectId: asProjectId("project-scripts"),
......@@ -81,7 +81,7 @@ describe("decider project scripts", () => {
8181 decideOrchestrationCommand({
8282 command: {
8383 type: "project.meta.update",
84 commandId: CommandId.makeUnsafe("cmd-project-update-scripts"),
84 commandId: CommandId.make("cmd-project-update-scripts"),
8585 projectId: asProjectId("project-scripts"),
8686 scripts: Array.from(scripts),
8787 },
......@@ -105,9 +105,9 @@ describe("decider project scripts", () => {
105105 aggregateId: asProjectId("project-1"),
106106 type: "project.created",
107107 occurredAt: now,
108 commandId: CommandId.makeUnsafe("cmd-project-create"),
108 commandId: CommandId.make("cmd-project-create"),
109109 causationEventId: null,
110 correlationId: CommandId.makeUnsafe("cmd-project-create"),
110 correlationId: CommandId.make("cmd-project-create"),
111111 metadata: {},
112112 payload: {
113113 projectId: asProjectId("project-1"),
......@@ -125,15 +125,15 @@ describe("decider project scripts", () => {
125125 sequence: 2,
126126 eventId: asEventId("evt-thread-create"),
127127 aggregateKind: "thread",
128 aggregateId: ThreadId.makeUnsafe("thread-1"),
128 aggregateId: ThreadId.make("thread-1"),
129129 type: "thread.created",
130130 occurredAt: now,
131 commandId: CommandId.makeUnsafe("cmd-thread-create"),
131 commandId: CommandId.make("cmd-thread-create"),
132132 causationEventId: null,
133 correlationId: CommandId.makeUnsafe("cmd-thread-create"),
133 correlationId: CommandId.make("cmd-thread-create"),
134134 metadata: {},
135135 payload: {
136 threadId: ThreadId.makeUnsafe("thread-1"),
136 threadId: ThreadId.make("thread-1"),
137137 projectId: asProjectId("project-1"),
138138 title: "Thread",
139139 modelSelection: {
......@@ -154,8 +154,8 @@ describe("decider project scripts", () => {
154154 decideOrchestrationCommand({
155155 command: {
156156 type: "thread.turn.start",
157 commandId: CommandId.makeUnsafe("cmd-turn-start"),
158 threadId: ThreadId.makeUnsafe("thread-1"),
157 commandId: CommandId.make("cmd-turn-start"),
158 threadId: ThreadId.make("thread-1"),
159159 message: {
160160 messageId: asMessageId("message-user-1"),
161161 role: "user",
......@@ -189,7 +189,7 @@ describe("decider project scripts", () => {
189189 return;
190190 }
191191 expect(turnStartEvent.payload).toMatchObject({
192 threadId: ThreadId.makeUnsafe("thread-1"),
192 threadId: ThreadId.make("thread-1"),
193193 messageId: asMessageId("message-user-1"),
194194 modelSelection: {
195195 provider: "codex",
......@@ -214,9 +214,9 @@ describe("decider project scripts", () => {
214214 aggregateId: asProjectId("project-1"),
215215 type: "project.created",
216216 occurredAt: now,
217 commandId: CommandId.makeUnsafe("cmd-project-create"),
217 commandId: CommandId.make("cmd-project-create"),
218218 causationEventId: null,
219 correlationId: CommandId.makeUnsafe("cmd-project-create"),
219 correlationId: CommandId.make("cmd-project-create"),
220220 metadata: {},
221221 payload: {
222222 projectId: asProjectId("project-1"),
......@@ -234,15 +234,15 @@ describe("decider project scripts", () => {
234234 sequence: 2,
235235 eventId: asEventId("evt-thread-create"),
236236 aggregateKind: "thread",
237 aggregateId: ThreadId.makeUnsafe("thread-1"),
237 aggregateId: ThreadId.make("thread-1"),
238238 type: "thread.created",
239239 occurredAt: now,
240 commandId: CommandId.makeUnsafe("cmd-thread-create"),
240 commandId: CommandId.make("cmd-thread-create"),
241241 causationEventId: null,
242 correlationId: CommandId.makeUnsafe("cmd-thread-create"),
242 correlationId: CommandId.make("cmd-thread-create"),
243243 metadata: {},
244244 payload: {
245 threadId: ThreadId.makeUnsafe("thread-1"),
245 threadId: ThreadId.make("thread-1"),
246246 projectId: asProjectId("project-1"),
247247 title: "Thread",
248248 modelSelection: {
......@@ -263,8 +263,8 @@ describe("decider project scripts", () => {
263263 decideOrchestrationCommand({
264264 command: {
265265 type: "thread.runtime-mode.set",
266 commandId: CommandId.makeUnsafe("cmd-runtime-mode-set"),
267 threadId: ThreadId.makeUnsafe("thread-1"),
266 commandId: CommandId.make("cmd-runtime-mode-set"),
267 threadId: ThreadId.make("thread-1"),
268268 runtimeMode: "approval-required",
269269 createdAt: now,
270270 },
......@@ -279,7 +279,7 @@ describe("decider project scripts", () => {
279279 expect(singleResult).toMatchObject({
280280 type: "thread.runtime-mode-set",
281281 payload: {
282 threadId: ThreadId.makeUnsafe("thread-1"),
282 threadId: ThreadId.make("thread-1"),
283283 runtimeMode: "approval-required",
284284 },
285285 });
......@@ -296,9 +296,9 @@ describe("decider project scripts", () => {
296296 aggregateId: asProjectId("project-1"),
297297 type: "project.created",
298298 occurredAt: now,
299 commandId: CommandId.makeUnsafe("cmd-project-create"),
299 commandId: CommandId.make("cmd-project-create"),
300300 causationEventId: null,
301 correlationId: CommandId.makeUnsafe("cmd-project-create"),
301 correlationId: CommandId.make("cmd-project-create"),
302302 metadata: {},
303303 payload: {
304304 projectId: asProjectId("project-1"),
......@@ -316,15 +316,15 @@ describe("decider project scripts", () => {
316316 sequence: 2,
317317 eventId: asEventId("evt-thread-create"),
318318 aggregateKind: "thread",
319 aggregateId: ThreadId.makeUnsafe("thread-1"),
319 aggregateId: ThreadId.make("thread-1"),
320320 type: "thread.created",
321321 occurredAt: now,
322 commandId: CommandId.makeUnsafe("cmd-thread-create"),
322 commandId: CommandId.make("cmd-thread-create"),
323323 causationEventId: null,
324 correlationId: CommandId.makeUnsafe("cmd-thread-create"),
324 correlationId: CommandId.make("cmd-thread-create"),
325325 metadata: {},
326326 payload: {
327 threadId: ThreadId.makeUnsafe("thread-1"),
327 threadId: ThreadId.make("thread-1"),
328328 projectId: asProjectId("project-1"),
329329 title: "Thread",
330330 modelSelection: {
......@@ -345,8 +345,8 @@ describe("decider project scripts", () => {
345345 decideOrchestrationCommand({
346346 command: {
347347 type: "thread.interaction-mode.set",
348 commandId: CommandId.makeUnsafe("cmd-interaction-mode-set"),
349 threadId: ThreadId.makeUnsafe("thread-1"),
348 commandId: CommandId.make("cmd-interaction-mode-set"),
349 threadId: ThreadId.make("thread-1"),
350350 interactionMode: "plan",
351351 createdAt: now,
352352 },
......@@ -361,7 +361,7 @@ describe("decider project scripts", () => {
361361 expect(singleResult).toMatchObject({
362362 type: "thread.interaction-mode-set",
363363 payload: {
364 threadId: ThreadId.makeUnsafe("thread-1"),
364 threadId: ThreadId.make("thread-1"),
365365 interactionMode: "plan",
366366 },
367367 });
apps/server/src/orchestration/projector.test.ts+4-4
......@@ -21,15 +21,15 @@ function makeEvent(input: {
2121}): OrchestrationEvent {
2222 return {
2323 sequence: input.sequence,
24 eventId: EventId.makeUnsafe(`event-${input.sequence}`),
24 eventId: EventId.make(`event-${input.sequence}`),
2525 type: input.type,
2626 aggregateKind: input.aggregateKind,
2727 aggregateId:
2828 input.aggregateKind === "project"
29 ? ProjectId.makeUnsafe(input.aggregateId)
30 : ThreadId.makeUnsafe(input.aggregateId),
29 ? ProjectId.make(input.aggregateId)
30 : ThreadId.make(input.aggregateId),
3131 occurredAt: input.occurredAt,
32 commandId: input.commandId === null ? null : CommandId.makeUnsafe(input.commandId),
32 commandId: input.commandId === null ? null : CommandId.make(input.commandId),
3333 causationEventId: null,
3434 correlationId: null,
3535 metadata: {},
apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts+8-8
......@@ -21,18 +21,18 @@ layer("OrchestrationEventStore", (it) => {
2121
2222 const appended = yield* eventStore.append({
2323 type: "project.created",
24 eventId: EventId.makeUnsafe("evt-store-roundtrip"),
24 eventId: EventId.make("evt-store-roundtrip"),
2525 aggregateKind: "project",
26 aggregateId: ProjectId.makeUnsafe("project-roundtrip"),
26 aggregateId: ProjectId.make("project-roundtrip"),
2727 occurredAt: now,
28 commandId: CommandId.makeUnsafe("cmd-store-roundtrip"),
28 commandId: CommandId.make("cmd-store-roundtrip"),
2929 causationEventId: null,
30 correlationId: CommandId.makeUnsafe("cmd-store-roundtrip"),
30 correlationId: CommandId.make("cmd-store-roundtrip"),
3131 metadata: {
3232 adapterKey: "codex",
3333 },
3434 payload: {
35 projectId: ProjectId.makeUnsafe("project-roundtrip"),
35 projectId: ProjectId.make("project-roundtrip"),
3636 title: "Roundtrip Project",
3737 workspaceRoot: "/tmp/project-roundtrip",
3838 defaultModelSelection: null,
......@@ -87,13 +87,13 @@ layer("OrchestrationEventStore", (it) => {
8787 metadata_json
8888 )
8989 VALUES (
90 ${EventId.makeUnsafe("evt-store-invalid-json")},
90 ${EventId.make("evt-store-invalid-json")},
9191 ${"project"},
92 ${ProjectId.makeUnsafe("project-invalid-json")},
92 ${ProjectId.make("project-invalid-json")},
9393 ${0},
9494 ${"project.created"},
9595 ${now},
96 ${CommandId.makeUnsafe("cmd-store-invalid-json")},
96 ${CommandId.make("cmd-store-invalid-json")},
9797 ${null},
9898 ${null},
9999 ${"server"},
apps/server/src/persistence/Layers/ProjectionRepositories.test.ts+5-5
......@@ -24,7 +24,7 @@ projectionRepositoriesLayer("Projection repositories", (it) => {
2424 const sql = yield* SqlClient.SqlClient;
2525
2626 yield* projects.upsert({
27 projectId: ProjectId.makeUnsafe("project-null-options"),
27 projectId: ProjectId.make("project-null-options"),
2828 title: "Null options project",
2929 workspaceRoot: "/tmp/project-null-options",
3030 defaultModelSelection: {
......@@ -58,7 +58,7 @@ projectionRepositoriesLayer("Projection repositories", (it) => {
5858 );
5959
6060 const persisted = yield* projects.getById({
61 projectId: ProjectId.makeUnsafe("project-null-options"),
61 projectId: ProjectId.make("project-null-options"),
6262 });
6363 assert.deepStrictEqual(Option.getOrNull(persisted)?.defaultModelSelection, {
6464 provider: "codex",
......@@ -73,8 +73,8 @@ projectionRepositoriesLayer("Projection repositories", (it) => {
7373 const sql = yield* SqlClient.SqlClient;
7474
7575 yield* threads.upsert({
76 threadId: ThreadId.makeUnsafe("thread-null-options"),
77 projectId: ProjectId.makeUnsafe("project-null-options"),
76 threadId: ThreadId.make("thread-null-options"),
77 projectId: ProjectId.make("project-null-options"),
7878 title: "Null options thread",
7979 modelSelection: {
8080 provider: "claudeAgent",
......@@ -112,7 +112,7 @@ projectionRepositoriesLayer("Projection repositories", (it) => {
112112 );
113113
114114 const persisted = yield* threads.getById({
115 threadId: ThreadId.makeUnsafe("thread-null-options"),
115 threadId: ThreadId.make("thread-null-options"),
116116 });
117117 assert.deepStrictEqual(Option.getOrNull(persisted)?.modelSelection, {
118118 provider: "claudeAgent",
apps/server/src/persistence/Layers/ProjectionThreadMessages.test.ts+4-4
......@@ -14,8 +14,8 @@ layer("ProjectionThreadMessageRepository", (it) => {
1414 it.effect("preserves existing attachments when upsert omits attachments", () =>
1515 Effect.gen(function* () {
1616 const repository = yield* ProjectionThreadMessageRepository;
17 const threadId = ThreadId.makeUnsafe("thread-preserve-attachments");
18 const messageId = MessageId.makeUnsafe("message-preserve-attachments");
17 const threadId = ThreadId.make("thread-preserve-attachments");
18 const messageId = MessageId.make("message-preserve-attachments");
1919 const createdAt = "2026-02-28T19:00:00.000Z";
2020 const updatedAt = "2026-02-28T19:00:01.000Z";
2121 const persistedAttachments = [
......@@ -68,8 +68,8 @@ layer("ProjectionThreadMessageRepository", (it) => {
6868 it.effect("allows explicit attachment clearing with an empty array", () =>
6969 Effect.gen(function* () {
7070 const repository = yield* ProjectionThreadMessageRepository;
71 const threadId = ThreadId.makeUnsafe("thread-clear-attachments");
72 const messageId = MessageId.makeUnsafe("message-clear-attachments");
71 const threadId = ThreadId.make("thread-clear-attachments");
72 const messageId = MessageId.make("message-clear-attachments");
7373 const createdAt = "2026-02-28T19:10:00.000Z";
7474
7575 yield* repository.upsert({
apps/server/src/persistence/NodeSqliteClient.ts+10-10
......@@ -15,7 +15,7 @@ import { identity } from "effect/Function";
1515import * as Layer from "effect/Layer";
1616import * as Scope from "effect/Scope";
1717import * as Semaphore from "effect/Semaphore";
18import * as ServiceMap from "effect/ServiceMap";
18import * as Context from "effect/Context";
1919import * as Stream from "effect/Stream";
2020import * as Reactivity from "effect/unstable/reactivity/Reactivity";
2121import * as Client from "effect/unstable/sql/SqlClient";
......@@ -32,7 +32,7 @@ export type TypeId = "~local/sqlite-node/SqliteClient";
3232/**
3333 * SqliteClient - Effect service tag for the sqlite SQL client.
3434 */
35export const SqliteClient = ServiceMap.Service<Client.SqlClient>("t3/persistence/NodeSqliteClient");
35export const SqliteClient = Context.Service<Client.SqlClient>("t3/persistence/NodeSqliteClient");
3636
3737export interface SqliteClientConfig {
3838 readonly filename: string;
......@@ -120,7 +120,7 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* (
120120
121121 const runStatement = (statement: StatementSync, params: ReadonlyArray<unknown>, raw: boolean) =>
122122 Effect.withFiber<ReadonlyArray<any>, SqlError>((fiber) => {
123 statement.setReadBigInts(Boolean(ServiceMap.get(fiber.services, Client.SafeIntegers)));
123 statement.setReadBigInts(Boolean(Context.get(fiber.context, Client.SafeIntegers)));
124124 try {
125125 if (hasRows(statement)) {
126126 return Effect.succeed(statement.all(...(params as any)));
......@@ -200,7 +200,7 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* (
200200 const acquirer = semaphore.withPermits(1)(Effect.succeed(connection));
201201 const transactionAcquirer = Effect.uninterruptibleMask((restore) => {
202202 const fiber = Fiber.getCurrent()!;
203 const scope = ServiceMap.getUnsafe(fiber.services, Scope.Scope);
203 const scope = Context.getUnsafe(fiber.context, Scope.Scope);
204204 return Effect.as(
205205 Effect.tap(restore(semaphore.take(1)), () => Scope.addFinalizer(scope, semaphore.release(1))),
206206 connection,
......@@ -251,27 +251,27 @@ const makeMemory = (
251251export const layerConfig = (
252252 config: Config.Wrap<SqliteClientConfig>,
253253): Layer.Layer<Client.SqlClient, Config.ConfigError> =>
254 Layer.effectServices(
254 Layer.effectContext(
255255 Config.unwrap(config)
256256 .asEffect()
257257 .pipe(
258258 Effect.flatMap(make),
259259 Effect.map((client) =>
260 ServiceMap.make(SqliteClient, client).pipe(ServiceMap.add(Client.SqlClient, client)),
260 Context.make(SqliteClient, client).pipe(Context.add(Client.SqlClient, client)),
261261 ),
262262 ),
263263 ).pipe(Layer.provide(Reactivity.layer));
264264
265265export const layer = (config: SqliteClientConfig): Layer.Layer<Client.SqlClient> =>
266 Layer.effectServices(
266 Layer.effectContext(
267267 Effect.map(make(config), (client) =>
268 ServiceMap.make(SqliteClient, client).pipe(ServiceMap.add(Client.SqlClient, client)),
268 Context.make(SqliteClient, client).pipe(Context.add(Client.SqlClient, client)),
269269 ),
270270 ).pipe(Layer.provide(Reactivity.layer));
271271
272272export const layerMemory = (config: SqliteMemoryClientConfig = {}): Layer.Layer<Client.SqlClient> =>
273 Layer.effectServices(
273 Layer.effectContext(
274274 Effect.map(makeMemory(config), (client) =>
275 ServiceMap.make(SqliteClient, client).pipe(ServiceMap.add(Client.SqlClient, client)),
275 Context.make(SqliteClient, client).pipe(Context.add(Client.SqlClient, client)),
276276 ),
277277 ).pipe(Layer.provide(Reactivity.layer));
apps/server/src/persistence/Services/AuthPairingLinks.ts+2-2
......@@ -1,4 +1,4 @@
1import { Option, Schema, ServiceMap } from "effect";
1import { Option, Schema, Context } from "effect";
22import type { Effect } from "effect";
33
44import type { AuthPairingLinkRepositoryError } from "../Errors.ts";
......@@ -70,7 +70,7 @@ export interface AuthPairingLinkRepositoryShape {
7070 ) => Effect.Effect<Option.Option<AuthPairingLinkRecord>, AuthPairingLinkRepositoryError>;
7171}
7272
73export class AuthPairingLinkRepository extends ServiceMap.Service<
73export class AuthPairingLinkRepository extends Context.Service<
7474 AuthPairingLinkRepository,
7575 AuthPairingLinkRepositoryShape
7676>()("t3/persistence/Services/AuthPairingLinks/AuthPairingLinkRepository") {}
apps/server/src/persistence/Services/AuthSessions.ts+2-2
......@@ -1,5 +1,5 @@
11import { AuthClientMetadataDeviceType, AuthSessionId } from "@t3tools/contracts";
2import { Option, Schema, ServiceMap } from "effect";
2import { Option, Schema, Context } from "effect";
33import type { Effect } from "effect";
44
55import type { AuthSessionRepositoryError } from "../Errors.ts";
......@@ -87,7 +87,7 @@ export interface AuthSessionRepositoryShape {
8787 ) => Effect.Effect<void, AuthSessionRepositoryError>;
8888}
8989
90export class AuthSessionRepository extends ServiceMap.Service<
90export class AuthSessionRepository extends Context.Service<
9191 AuthSessionRepository,
9292 AuthSessionRepositoryShape
9393>()("t3/persistence/Services/AuthSessions/AuthSessionRepository") {}
apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts+2-2
......@@ -15,7 +15,7 @@ import {
1515 ProjectId,
1616 ThreadId,
1717} from "@t3tools/contracts";
18import { Option, Schema, ServiceMap } from "effect";
18import { Option, Schema, Context } from "effect";
1919import type { Effect } from "effect";
2020
2121import type { OrchestrationCommandReceiptRepositoryError } from "../Errors.ts";
......@@ -63,7 +63,7 @@ export interface OrchestrationCommandReceiptRepositoryShape {
6363/**
6464 * OrchestrationCommandReceiptRepository - Service tag for command receipt persistence.
6565 */
66export class OrchestrationCommandReceiptRepository extends ServiceMap.Service<
66export class OrchestrationCommandReceiptRepository extends Context.Service<
6767 OrchestrationCommandReceiptRepository,
6868 OrchestrationCommandReceiptRepositoryShape
6969>()("t3/persistence/Services/OrchestrationCommandReceipts/OrchestrationCommandReceiptRepository") {}
apps/server/src/persistence/Services/OrchestrationEventStore.ts+3-3
......@@ -4,13 +4,13 @@
44 * Owns durable append/replay access to the orchestration event stream. It does
55 * not reduce events into read models or apply command validation rules.
66 *
7 * Uses Effect `ServiceMap.Service` for dependency injection and exposes typed
7 * Uses Effect `Context.Service` for dependency injection and exposes typed
88 * persistence/decode errors for event append and replay operations.
99 *
1010 * @module OrchestrationEventStore
1111 */
1212import { OrchestrationEvent } from "@t3tools/contracts";
13import { ServiceMap } from "effect";
13import { Context } from "effect";
1414import type { Effect, Stream } from "effect";
1515
1616import type { OrchestrationEventStoreError } from "../Errors.ts";
......@@ -64,7 +64,7 @@ export interface OrchestrationEventStoreShape {
6464 * })
6565 * ```
6666 */
67export class OrchestrationEventStore extends ServiceMap.Service<
67export class OrchestrationEventStore extends Context.Service<
6868 OrchestrationEventStore,
6969 OrchestrationEventStoreShape
7070>()("t3/persistence/Services/OrchestrationEventStore") {}
apps/server/src/persistence/Services/ProjectionCheckpoints.ts+2-2
......@@ -16,7 +16,7 @@ import {
1616 ThreadId,
1717 TurnId,
1818} from "@t3tools/contracts";
19import { Option, ServiceMap, Schema } from "effect";
19import { Option, Context, Schema } from "effect";
2020import type { Effect } from "effect";
2121
2222import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -87,7 +87,7 @@ export interface ProjectionCheckpointRepositoryShape {
8787/**
8888 * ProjectionCheckpointRepository - Service tag for checkpoint projection persistence.
8989 */
90export class ProjectionCheckpointRepository extends ServiceMap.Service<
90export class ProjectionCheckpointRepository extends Context.Service<
9191 ProjectionCheckpointRepository,
9292 ProjectionCheckpointRepositoryShape
9393>()("t3/persistence/Services/ProjectionCheckpoints/ProjectionCheckpointRepository") {}
apps/server/src/persistence/Services/ProjectionPendingApprovals.ts+2-2
......@@ -14,7 +14,7 @@ import {
1414 ThreadId,
1515 TurnId,
1616} from "@t3tools/contracts";
17import { Option, Schema, ServiceMap } from "effect";
17import { Option, Schema, Context } from "effect";
1818import type { Effect } from "effect";
1919
2020import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -85,7 +85,7 @@ export interface ProjectionPendingApprovalRepositoryShape {
8585/**
8686 * ProjectionPendingApprovalRepository - Service tag for pending approval persistence.
8787 */
88export class ProjectionPendingApprovalRepository extends ServiceMap.Service<
88export class ProjectionPendingApprovalRepository extends Context.Service<
8989 ProjectionPendingApprovalRepository,
9090 ProjectionPendingApprovalRepositoryShape
9191>()("t3/persistence/Services/ProjectionPendingApprovals/ProjectionPendingApprovalRepository") {}
apps/server/src/persistence/Services/ProjectionProjects.ts+2-2
......@@ -7,7 +7,7 @@
77 * @module ProjectionProjectRepository
88 */
99import { IsoDateTime, ModelSelection, ProjectId, ProjectScript } from "@t3tools/contracts";
10import { Option, Schema, ServiceMap } from "effect";
10import { Option, Schema, Context } from "effect";
1111import type { Effect } from "effect";
1212
1313import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -73,7 +73,7 @@ export interface ProjectionProjectRepositoryShape {
7373/**
7474 * ProjectionProjectRepository - Service tag for project projection persistence.
7575 */
76export class ProjectionProjectRepository extends ServiceMap.Service<
76export class ProjectionProjectRepository extends Context.Service<
7777 ProjectionProjectRepository,
7878 ProjectionProjectRepositoryShape
7979>()("t3/persistence/Services/ProjectionProjects/ProjectionProjectRepository") {}
apps/server/src/persistence/Services/ProjectionState.ts+2-2
......@@ -7,7 +7,7 @@
77 * @module ProjectionStateRepository
88 */
99import { IsoDateTime, NonNegativeInt } from "@t3tools/contracts";
10import { Option, Schema, ServiceMap } from "effect";
10import { Option, Schema, Context } from "effect";
1111import type { Effect } from "effect";
1212
1313import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -58,7 +58,7 @@ export interface ProjectionStateRepositoryShape {
5858/**
5959 * ProjectionStateRepository - Service tag for projection cursor persistence.
6060 */
61export class ProjectionStateRepository extends ServiceMap.Service<
61export class ProjectionStateRepository extends Context.Service<
6262 ProjectionStateRepository,
6363 ProjectionStateRepositoryShape
6464>()("t3/persistence/Services/ProjectionState/ProjectionStateRepository") {}
apps/server/src/persistence/Services/ProjectionThreadActivities.ts+2-2
......@@ -14,7 +14,7 @@ import {
1414 ThreadId,
1515 TurnId,
1616} from "@t3tools/contracts";
17import { Schema, ServiceMap } from "effect";
17import { Schema, Context } from "effect";
1818import type { Effect } from "effect";
1919
2020import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -77,7 +77,7 @@ export interface ProjectionThreadActivityRepositoryShape {
7777/**
7878 * ProjectionThreadActivityRepository - Service tag for thread activity persistence.
7979 */
80export class ProjectionThreadActivityRepository extends ServiceMap.Service<
80export class ProjectionThreadActivityRepository extends Context.Service<
8181 ProjectionThreadActivityRepository,
8282 ProjectionThreadActivityRepositoryShape
8383>()("t3/persistence/Services/ProjectionThreadActivities/ProjectionThreadActivityRepository") {}
apps/server/src/persistence/Services/ProjectionThreadMessages.ts+2-2
......@@ -14,7 +14,7 @@ import {
1414 TurnId,
1515 IsoDateTime,
1616} from "@t3tools/contracts";
17import { Schema, ServiceMap } from "effect";
17import { Schema, Context } from "effect";
1818import type { Option } from "effect";
1919import type { Effect } from "effect";
2020
......@@ -88,7 +88,7 @@ export interface ProjectionThreadMessageRepositoryShape {
8888/**
8989 * ProjectionThreadMessageRepository - Service tag for message projection persistence.
9090 */
91export class ProjectionThreadMessageRepository extends ServiceMap.Service<
91export class ProjectionThreadMessageRepository extends Context.Service<
9292 ProjectionThreadMessageRepository,
9393 ProjectionThreadMessageRepositoryShape
9494>()("t3/persistence/Services/ProjectionThreadMessages/ProjectionThreadMessageRepository") {}
apps/server/src/persistence/Services/ProjectionThreadProposedPlans.ts+2-2
......@@ -5,7 +5,7 @@ import {
55 TrimmedNonEmptyString,
66 TurnId,
77} from "@t3tools/contracts";
8import { Schema, ServiceMap } from "effect";
8import { Schema, Context } from "effect";
99import type { Effect } from "effect";
1010
1111import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -46,7 +46,7 @@ export interface ProjectionThreadProposedPlanRepositoryShape {
4646 ) => Effect.Effect<void, ProjectionRepositoryError>;
4747}
4848
49export class ProjectionThreadProposedPlanRepository extends ServiceMap.Service<
49export class ProjectionThreadProposedPlanRepository extends Context.Service<
5050 ProjectionThreadProposedPlanRepository,
5151 ProjectionThreadProposedPlanRepositoryShape
5252>()(
apps/server/src/persistence/Services/ProjectionThreadSessions.ts+2-2
......@@ -13,7 +13,7 @@ import {
1313 ThreadId,
1414 TurnId,
1515} from "@t3tools/contracts";
16import { Option, Schema, ServiceMap } from "effect";
16import { Option, Schema, Context } from "effect";
1717import type { Effect } from "effect";
1818
1919import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -68,7 +68,7 @@ export interface ProjectionThreadSessionRepositoryShape {
6868/**
6969 * ProjectionThreadSessionRepository - Service tag for thread-session persistence.
7070 */
71export class ProjectionThreadSessionRepository extends ServiceMap.Service<
71export class ProjectionThreadSessionRepository extends Context.Service<
7272 ProjectionThreadSessionRepository,
7373 ProjectionThreadSessionRepositoryShape
7474>()("t3/persistence/Services/ProjectionThreadSessions/ProjectionThreadSessionRepository") {}
apps/server/src/persistence/Services/ProjectionThreads.ts+2-2
......@@ -15,7 +15,7 @@ import {
1515 ThreadId,
1616 TurnId,
1717} from "@t3tools/contracts";
18import { Option, Schema, ServiceMap } from "effect";
18import { Option, Schema, Context } from "effect";
1919import type { Effect } from "effect";
2020
2121import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -90,7 +90,7 @@ export interface ProjectionThreadRepositoryShape {
9090/**
9191 * ProjectionThreadRepository - Service tag for thread projection persistence.
9292 */
93export class ProjectionThreadRepository extends ServiceMap.Service<
93export class ProjectionThreadRepository extends Context.Service<
9494 ProjectionThreadRepository,
9595 ProjectionThreadRepositoryShape
9696>()("t3/persistence/Services/ProjectionThreads/ProjectionThreadRepository") {}
apps/server/src/persistence/Services/ProjectionTurns.ts+2-2
......@@ -17,7 +17,7 @@ import {
1717 ThreadId,
1818 TurnId,
1919} from "@t3tools/contracts";
20import { Option, Schema, ServiceMap } from "effect";
20import { Option, Schema, Context } from "effect";
2121import type { Effect } from "effect";
2222
2323import type { ProjectionRepositoryError } from "../Errors.ts";
......@@ -162,7 +162,7 @@ export interface ProjectionTurnRepositoryShape {
162162 ) => Effect.Effect<void, ProjectionRepositoryError>;
163163}
164164
165export class ProjectionTurnRepository extends ServiceMap.Service<
165export class ProjectionTurnRepository extends Context.Service<
166166 ProjectionTurnRepository,
167167 ProjectionTurnRepositoryShape
168168>()("t3/persistence/Services/ProjectionTurns/ProjectionTurnRepository") {}
apps/server/src/persistence/Services/ProviderSessionRuntime.ts+2-2
......@@ -11,7 +11,7 @@ import {
1111 RuntimeMode,
1212 ThreadId,
1313} from "@t3tools/contracts";
14import { Option, Schema, ServiceMap } from "effect";
14import { Option, Schema, Context } from "effect";
1515import type { Effect } from "effect";
1616
1717import type { ProviderSessionRuntimeRepositoryError } from "../Errors.ts";
......@@ -75,7 +75,7 @@ export interface ProviderSessionRuntimeRepositoryShape {
7575/**
7676 * ProviderSessionRuntimeRepository - Service tag for provider runtime persistence.
7777 */
78export class ProviderSessionRuntimeRepository extends ServiceMap.Service<
78export class ProviderSessionRuntimeRepository extends Context.Service<
7979 ProviderSessionRuntimeRepository,
8080 ProviderSessionRuntimeRepositoryShape
8181>()("t3/persistence/Services/ProviderSessionRuntime/ProviderSessionRuntimeRepository") {}
apps/server/src/project/Layers/RepositoryIdentityResolver.ts+13-11
......@@ -116,17 +116,19 @@ async function resolveRepositoryIdentityFromCacheKey(
116116
117117export const makeRepositoryIdentityResolver = Effect.fn("makeRepositoryIdentityResolver")(
118118 function* (options: RepositoryIdentityResolverOptions = {}) {
119 const repositoryIdentityCache = yield* Cache.makeWith<string, RepositoryIdentity | null>({
120 capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
121 lookup: (cacheKey) => Effect.promise(() => resolveRepositoryIdentityFromCacheKey(cacheKey)),
122 timeToLive: Exit.match({
123 onSuccess: (value) =>
124 value === null
125 ? (options.negativeCacheTtl ?? DEFAULT_NEGATIVE_CACHE_TTL)
126 : (options.positiveCacheTtl ?? DEFAULT_POSITIVE_CACHE_TTL),
127 onFailure: () => Duration.zero,
128 }),
129 });
119 const repositoryIdentityCache = yield* Cache.makeWith<string, RepositoryIdentity | null>(
120 (cacheKey) => Effect.promise(() => resolveRepositoryIdentityFromCacheKey(cacheKey)),
121 {
122 capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
123 timeToLive: Exit.match({
124 onSuccess: (value) =>
125 value === null
126 ? (options.negativeCacheTtl ?? DEFAULT_NEGATIVE_CACHE_TTL)
127 : (options.positiveCacheTtl ?? DEFAULT_POSITIVE_CACHE_TTL),
128 onFailure: () => Duration.zero,
129 }),
130 },
131 );
130132
131133 const resolve: RepositoryIdentityResolverShape["resolve"] = Effect.fn(
132134 "RepositoryIdentityResolver.resolve",
apps/server/src/project/Services/ProjectFaviconResolver.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module ProjectFaviconResolver
88 */
9import { ServiceMap } from "effect";
9import { Context } from "effect";
1010import type { Effect } from "effect";
1111
1212/**
......@@ -24,7 +24,7 @@ export interface ProjectFaviconResolverShape {
2424/**
2525 * ProjectFaviconResolver - Service tag for project favicon resolution.
2626 */
27export class ProjectFaviconResolver extends ServiceMap.Service<
27export class ProjectFaviconResolver extends Context.Service<
2828 ProjectFaviconResolver,
2929 ProjectFaviconResolverShape
3030>()("t3/project/Services/ProjectFaviconResolver") {}
apps/server/src/project/Services/ProjectSetupScriptRunner.ts+2-2
......@@ -1,4 +1,4 @@
1import { ServiceMap } from "effect";
1import { Context } from "effect";
22import type { Effect } from "effect";
33
44export interface ProjectSetupScriptRunnerResultNoScript {
......@@ -31,7 +31,7 @@ export interface ProjectSetupScriptRunnerShape {
3131 ) => Effect.Effect<ProjectSetupScriptRunnerResult, Error>;
3232}
3333
34export class ProjectSetupScriptRunner extends ServiceMap.Service<
34export class ProjectSetupScriptRunner extends Context.Service<
3535 ProjectSetupScriptRunner,
3636 ProjectSetupScriptRunnerShape
3737>()("t3/project/ProjectSetupScriptRunner") {}
apps/server/src/project/Services/RepositoryIdentityResolver.ts+2-2
......@@ -1,12 +1,12 @@
11import type { RepositoryIdentity } from "@t3tools/contracts";
2import { ServiceMap } from "effect";
2import { Context } from "effect";
33import type { Effect } from "effect";
44
55export interface RepositoryIdentityResolverShape {
66 readonly resolve: (cwd: string) => Effect.Effect<RepositoryIdentity | null>;
77}
88
9export class RepositoryIdentityResolver extends ServiceMap.Service<
9export class RepositoryIdentityResolver extends Context.Service<
1010 RepositoryIdentityResolver,
1111 RepositoryIdentityResolverShape
1212>()("t3/project/Services/RepositoryIdentityResolver") {}
apps/server/src/provider/Layers/ClaudeAdapter.test.ts+21-25
......@@ -237,8 +237,8 @@ async function readFirstPromptMessage(
237237 return next.value;
238238}
239239
240const THREAD_ID = ThreadId.makeUnsafe("thread-claude-1");
241const RESUME_THREAD_ID = ThreadId.makeUnsafe("thread-claude-resume");
240const THREAD_ID = ThreadId.make("thread-claude-1");
241const RESUME_THREAD_ID = ThreadId.make("thread-claude-resume");
242242
243243describe("ClaudeAdapterLive", () => {
244244 it.effect("returns validation error for non-claude provider on startSession", () => {
......@@ -1104,8 +1104,8 @@ describe("ClaudeAdapterLive", () => {
11041104 it.effect("closes the session when the Claude stream aborts after a turn starts", () => {
11051105 const harness = makeHarness();
11061106 return Effect.gen(function* () {
1107 const services = yield* Effect.services();
1108 const runFork = Effect.runForkWith(services);
1107 const context = yield* Effect.context<never>();
1108 const runFork = Effect.runForkWith(context);
11091109
11101110 const adapter = yield* ClaudeAdapter;
11111111 const runtimeEvents: Array<ProviderRuntimeEvent> = [];
......@@ -1204,8 +1204,8 @@ describe("ClaudeAdapterLive", () => {
12041204 );
12051205
12061206 return Effect.gen(function* () {
1207 const services = yield* Effect.services();
1208 const runFork = Effect.runForkWith(services);
1207 const context = yield* Effect.context<never>();
1208 const runFork = Effect.runForkWith(context);
12091209
12101210 const adapter = yield* ClaudeAdapter;
12111211
......@@ -2108,7 +2108,7 @@ describe("ClaudeAdapterLive", () => {
21082108 return;
21092109 }
21102110 assert.deepEqual(requested.value.providerRefs, {
2111 providerItemId: ProviderItemId.makeUnsafe("tool-use-1"),
2111 providerItemId: ProviderItemId.make("tool-use-1"),
21122112 });
21132113 const runtimeRequestId = requested.value.requestId;
21142114 assert.equal(typeof runtimeRequestId, "string");
......@@ -2118,7 +2118,7 @@ describe("ClaudeAdapterLive", () => {
21182118
21192119 yield* adapter.respondToRequest(
21202120 session.threadId,
2121 ApprovalRequestId.makeUnsafe(runtimeRequestId),
2121 ApprovalRequestId.make(runtimeRequestId),
21222122 "accept",
21232123 );
21242124
......@@ -2134,7 +2134,7 @@ describe("ClaudeAdapterLive", () => {
21342134 assert.equal(resolved.value.requestId, requested.value.requestId);
21352135 assert.equal(resolved.value.payload.decision, "accept");
21362136 assert.deepEqual(resolved.value.providerRefs, {
2137 providerItemId: ProviderItemId.makeUnsafe("tool-use-1"),
2137 providerItemId: ProviderItemId.make("tool-use-1"),
21382138 });
21392139
21402140 const permissionResult = yield* Effect.promise(() => permissionPromise);
......@@ -2183,7 +2183,7 @@ describe("ClaudeAdapterLive", () => {
21832183
21842184 yield* adapter.respondToRequest(
21852185 session.threadId,
2186 ApprovalRequestId.makeUnsafe(String(agentRequested.value.requestId)),
2186 ApprovalRequestId.make(String(agentRequested.value.requestId)),
21872187 "accept",
21882188 );
21892189 yield* Stream.runHead(adapter.streamEvents);
......@@ -2207,7 +2207,7 @@ describe("ClaudeAdapterLive", () => {
22072207
22082208 yield* adapter.respondToRequest(
22092209 session.threadId,
2210 ApprovalRequestId.makeUnsafe(String(grepRequested.value.requestId)),
2210 ApprovalRequestId.make(String(grepRequested.value.requestId)),
22112211 "accept",
22122212 );
22132213 yield* Stream.runHead(adapter.streamEvents);
......@@ -2629,7 +2629,7 @@ describe("ClaudeAdapterLive", () => {
26292629 }
26302630 assert.equal(proposedEvent.value.payload.planMarkdown, "# Ship it\n\n- one\n- two");
26312631 assert.deepEqual(proposedEvent.value.providerRefs, {
2632 providerItemId: ProviderItemId.makeUnsafe("tool-exit-1"),
2632 providerItemId: ProviderItemId.make("tool-exit-1"),
26332633 });
26342634
26352635 const permissionResult = yield* Effect.promise(() => permissionPromise);
......@@ -2707,7 +2707,7 @@ describe("ClaudeAdapterLive", () => {
27072707 }
27082708 assert.equal(proposedEvent.value.payload.planMarkdown, "# Final plan\n\n- capture it");
27092709 assert.deepEqual(proposedEvent.value.providerRefs, {
2710 providerItemId: ProviderItemId.makeUnsafe("tool-exit-2"),
2710 providerItemId: ProviderItemId.make("tool-exit-2"),
27112711 });
27122712 }).pipe(
27132713 Effect.provideService(Random.Random, makeDeterministicRandomService()),
......@@ -2798,15 +2798,13 @@ describe("ClaudeAdapterLive", () => {
27982798 assert.equal(requestedEvent.value.payload.questions.length, 1);
27992799 assert.equal(requestedEvent.value.payload.questions[0]?.question, "Which framework?");
28002800 assert.deepEqual(requestedEvent.value.providerRefs, {
2801 providerItemId: ProviderItemId.makeUnsafe("tool-ask-1"),
2801 providerItemId: ProviderItemId.make("tool-ask-1"),
28022802 });
28032803
28042804 // Respond with the user's answers.
2805 yield* adapter.respondToUserInput(
2806 session.threadId,
2807 ApprovalRequestId.makeUnsafe(requestId!),
2808 { "Which framework?": "React" },
2809 );
2805 yield* adapter.respondToUserInput(session.threadId, ApprovalRequestId.make(requestId!), {
2806 "Which framework?": "React",
2807 });
28102808
28112809 // The adapter should emit a user-input.resolved event.
28122810 const resolvedEvent = yield* Stream.runHead(adapter.streamEvents);
......@@ -2822,7 +2820,7 @@ describe("ClaudeAdapterLive", () => {
28222820 "Which framework?": "React",
28232821 });
28242822 assert.deepEqual(resolvedEvent.value.providerRefs, {
2825 providerItemId: ProviderItemId.makeUnsafe("tool-ask-1"),
2823 providerItemId: ProviderItemId.make("tool-ask-1"),
28262824 });
28272825
28282826 // The canUseTool promise should resolve with the answers in SDK format.
......@@ -2889,11 +2887,9 @@ describe("ClaudeAdapterLive", () => {
28892887 }
28902888 const requestId = requestedEvent.value.requestId;
28912889
2892 yield* adapter.respondToUserInput(
2893 session.threadId,
2894 ApprovalRequestId.makeUnsafe(requestId!),
2895 { "Deploy to which env?": "Staging" },
2896 );
2890 yield* adapter.respondToUserInput(session.threadId, ApprovalRequestId.make(requestId!), {
2891 "Deploy to which env?": "Staging",
2892 });
28972893
28982894 // Drain the resolved event.
28992895 yield* Stream.runHead(adapter.streamEvents);
apps/server/src/provider/Layers/ClaudeAdapter.ts+16-16
......@@ -269,7 +269,7 @@ function isInterruptedResult(result: SDKResultMessage): boolean {
269269}
270270
271271function asRuntimeItemId(value: string): RuntimeItemId {
272 return RuntimeItemId.makeUnsafe(value);
272 return RuntimeItemId.make(value);
273273}
274274
275275function maxClaudeContextWindowFromModelUsage(modelUsage: unknown): number | undefined {
......@@ -353,7 +353,7 @@ function asCanonicalTurnId(value: TurnId): TurnId {
353353}
354354
355355function asRuntimeRequestId(value: ApprovalRequestId): RuntimeRequestId {
356 return RuntimeRequestId.makeUnsafe(value);
356 return RuntimeRequestId.make(value);
357357}
358358
359359function readClaudeResumeState(resumeCursor: unknown): ClaudeResumeState | undefined {
......@@ -371,7 +371,7 @@ function readClaudeResumeState(resumeCursor: unknown): ClaudeResumeState | undef
371371 const threadIdCandidate = typeof cursor.threadId === "string" ? cursor.threadId : undefined;
372372 const threadId =
373373 threadIdCandidate && !isSyntheticClaudeThreadId(threadIdCandidate)
374 ? ThreadId.makeUnsafe(threadIdCandidate)
374 ? ThreadId.make(threadIdCandidate)
375375 : undefined;
376376 const resumeCandidate =
377377 typeof cursor.resume === "string"
......@@ -641,7 +641,7 @@ function nativeProviderRefs(
641641): NonNullable<ProviderRuntimeEvent["providerRefs"]> {
642642 if (options?.providerItemId) {
643643 return {
644 providerItemId: ProviderItemId.makeUnsafe(options.providerItemId),
644 providerItemId: ProviderItemId.make(options.providerItemId),
645645 };
646646 }
647647 return {};
......@@ -934,7 +934,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
934934 const serverSettingsService = yield* ServerSettingsService;
935935
936936 const nowIso = Effect.map(DateTime.now, DateTime.formatIso);
937 const nextEventId = Effect.map(Random.nextUUIDv4, (id) => EventId.makeUnsafe(id));
937 const nextEventId = Effect.map(Random.nextUUIDv4, (id) => EventId.make(id));
938938 const makeEventStamp = () => Effect.all({ eventId: nextEventId, createdAt: nowIso });
939939
940940 const offerRuntimeEvent = (event: ProviderRuntimeEvent): Effect.Effect<void> =>
......@@ -967,7 +967,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
967967 ? { providerThreadId: message.session_id }
968968 : {}),
969969 ...(context.turnState ? { turnId: asCanonicalTurnId(context.turnState.turnId) } : {}),
970 ...(itemId ? { itemId: ProviderItemId.makeUnsafe(itemId) } : {}),
970 ...(itemId ? { itemId: ProviderItemId.make(itemId) } : {}),
971971 payload: message,
972972 },
973973 },
......@@ -1822,7 +1822,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
18221822 // Auto-start a synthetic turn for assistant messages that arrive without
18231823 // an active turn (e.g., background agent/subagent responses between user prompts).
18241824 if (!context.turnState) {
1825 const turnId = TurnId.makeUnsafe(yield* Random.nextUUIDv4);
1825 const turnId = TurnId.make(yield* Random.nextUUIDv4);
18261826 const startedAt = yield* nowIso;
18271827 context.turnState = {
18281828 turnId,
......@@ -2013,7 +2013,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
20132013 ...base,
20142014 type: "task.started",
20152015 payload: {
2016 taskId: RuntimeTaskId.makeUnsafe(message.task_id),
2016 taskId: RuntimeTaskId.make(message.task_id),
20172017 description: message.description,
20182018 ...(message.task_type ? { taskType: message.task_type } : {}),
20192019 },
......@@ -2043,7 +2043,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
20432043 ...base,
20442044 type: "task.progress",
20452045 payload: {
2046 taskId: RuntimeTaskId.makeUnsafe(message.task_id),
2046 taskId: RuntimeTaskId.make(message.task_id),
20472047 description: message.description,
20482048 ...(message.summary ? { summary: message.summary } : {}),
20492049 ...(message.usage ? { usage: message.usage } : {}),
......@@ -2075,7 +2075,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
20752075 ...base,
20762076 type: "task.completed",
20772077 payload: {
2078 taskId: RuntimeTaskId.makeUnsafe(message.task_id),
2078 taskId: RuntimeTaskId.make(message.task_id),
20792079 status: message.status,
20802080 ...(message.summary ? { summary: message.summary } : {}),
20812081 ...(message.usage ? { usage: message.usage } : {}),
......@@ -2380,9 +2380,9 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
23802380 existingResumeSessionId === undefined ? yield* Random.nextUUIDv4 : undefined;
23812381 const sessionId = existingResumeSessionId ?? newSessionId;
23822382
2383 const services = yield* Effect.services();
2384 const runFork = Effect.runForkWith(services);
2385 const runPromise = Effect.runPromiseWith(services);
2383 const runtimeContext = yield* Effect.context<never>();
2384 const runFork = Effect.runForkWith(runtimeContext);
2385 const runPromise = Effect.runPromiseWith(runtimeContext);
23862386
23872387 const promptQueue = yield* Queue.unbounded<PromptQueueItem>();
23882388 const prompt = Stream.fromQueue(promptQueue).pipe(
......@@ -2409,7 +2409,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
24092409 toolInput: Record<string, unknown>,
24102410 callbackOptions: { readonly signal: AbortSignal; readonly toolUseID?: string },
24112411 ) {
2412 const requestId = ApprovalRequestId.makeUnsafe(yield* Random.nextUUIDv4);
2412 const requestId = ApprovalRequestId.make(yield* Random.nextUUIDv4);
24132413
24142414 // Parse questions from the SDK's AskUserQuestion input.
24152415 const rawQuestions = Array.isArray(toolInput.questions) ? toolInput.questions : [];
......@@ -2562,7 +2562,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
25622562 } satisfies PermissionResult;
25632563 }
25642564
2565 const requestId = ApprovalRequestId.makeUnsafe(yield* Random.nextUUIDv4);
2565 const requestId = ApprovalRequestId.make(yield* Random.nextUUIDv4);
25662566 const requestType = classifyRequestType(toolName);
25672567 const detail = summarizeToolRequest(toolName, toolInput);
25682568 const decisionDeferred = yield* Deferred.make<ProviderApprovalDecision>();
......@@ -2890,7 +2890,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (
28902890 });
28912891 }
28922892
2893 const turnId = TurnId.makeUnsafe(yield* Random.nextUUIDv4);
2893 const turnId = TurnId.make(yield* Random.nextUUIDv4);
28942894 const turnState: ClaudeTurnState = {
28952895 turnId,
28962896 startedAt: yield* nowIso,
apps/server/src/provider/Layers/CodexAdapter.test.ts+8-8
......@@ -28,10 +28,10 @@ import { CodexAdapter } from "../Services/CodexAdapter.ts";
2828import { ProviderSessionDirectory } from "../Services/ProviderSessionDirectory.ts";
2929import { makeCodexAdapterLive } from "./CodexAdapter.ts";
3030
31const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value);
32const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
33const asEventId = (value: string): EventId => EventId.makeUnsafe(value);
34const asItemId = (value: string): ProviderItemId => ProviderItemId.makeUnsafe(value);
31const asThreadId = (value: string): ThreadId => ThreadId.make(value);
32const asTurnId = (value: string): TurnId => TurnId.make(value);
33const asEventId = (value: string): EventId => EventId.make(value);
34const asItemId = (value: string): ProviderItemId => ProviderItemId.make(value);
3535
3636class FakeCodexManager extends CodexAppServerManager {
3737 public startSessionImpl = vi.fn(
......@@ -556,7 +556,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => {
556556 threadId: asThreadId("thread-1"),
557557 createdAt: new Date().toISOString(),
558558 method: "serverRequest/resolved",
559 requestId: ApprovalRequestId.makeUnsafe("req-1"),
559 requestId: ApprovalRequestId.make("req-1"),
560560 payload: {
561561 request: {
562562 method: "item/commandExecution/requestApproval",
......@@ -592,7 +592,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => {
592592 threadId: asThreadId("thread-1"),
593593 createdAt: new Date().toISOString(),
594594 method: "serverRequest/resolved",
595 requestId: ApprovalRequestId.makeUnsafe("req-file-read-1"),
595 requestId: ApprovalRequestId.make("req-file-read-1"),
596596 payload: {
597597 request: {
598598 method: "item/fileRead/requestApproval",
......@@ -710,7 +710,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => {
710710 threadId: asThreadId("thread-1"),
711711 createdAt: new Date().toISOString(),
712712 method: "item/tool/requestUserInput",
713 requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"),
713 requestId: ApprovalRequestId.make("req-user-input-1"),
714714 payload: {
715715 questions: [
716716 {
......@@ -735,7 +735,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => {
735735 threadId: asThreadId("thread-1"),
736736 createdAt: new Date().toISOString(),
737737 method: "item/tool/requestUserInput/answered",
738 requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"),
738 requestId: ApprovalRequestId.make("req-user-input-1"),
739739 payload: {
740740 answers: {
741741 sandbox_mode: {
apps/server/src/provider/Layers/CodexAdapter.ts+9-9
......@@ -22,7 +22,7 @@ import {
2222 TurnId,
2323 ProviderSendTurnInput,
2424} from "@t3tools/contracts";
25import { Effect, FileSystem, Layer, Queue, Schema, ServiceMap, Stream } from "effect";
25import { Effect, FileSystem, Layer, Queue, Schema, Context, Stream } from "effect";
2626
2727import {
2828 ProviderAdapterProcessError,
......@@ -46,7 +46,7 @@ const PROVIDER = "codex" as const;
4646
4747export interface CodexAdapterLiveOptions {
4848 readonly manager?: CodexAppServerManager;
49 readonly makeManager?: (services?: ServiceMap.ServiceMap<never>) => CodexAppServerManager;
49 readonly makeManager?: (services?: Context.Context<never>) => CodexAppServerManager;
5050 readonly nativeEventLogPath?: string;
5151 readonly nativeEventLogger?: EventNdjsonLogger;
5252}
......@@ -162,11 +162,11 @@ function normalizeCodexTokenUsage(value: unknown): ThreadTokenUsageSnapshot | un
162162}
163163
164164function toTurnId(value: string | undefined): TurnId | undefined {
165 return value?.trim() ? TurnId.makeUnsafe(value) : undefined;
165 return value?.trim() ? TurnId.make(value) : undefined;
166166}
167167
168168function toProviderItemId(value: string | undefined): ProviderItemId | undefined {
169 return value?.trim() ? ProviderItemId.makeUnsafe(value) : undefined;
169 return value?.trim() ? ProviderItemId.make(value) : undefined;
170170}
171171
172172function toTurnStatus(value: unknown): "completed" | "failed" | "cancelled" | "interrupted" {
......@@ -454,15 +454,15 @@ function extractProposedPlanMarkdown(text: string | undefined): string | undefin
454454}
455455
456456function asRuntimeItemId(itemId: ProviderItemId): RuntimeItemId {
457 return RuntimeItemId.makeUnsafe(itemId);
457 return RuntimeItemId.make(itemId);
458458}
459459
460460function asRuntimeRequestId(requestId: string): RuntimeRequestId {
461 return RuntimeRequestId.makeUnsafe(requestId);
461 return RuntimeRequestId.make(requestId);
462462}
463463
464464function asRuntimeTaskId(taskId: string): RuntimeTaskId {
465 return RuntimeTaskId.makeUnsafe(taskId);
465 return RuntimeTaskId.make(taskId);
466466}
467467
468468function codexEventMessage(
......@@ -1366,7 +1366,7 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* (
13661366 if (options?.manager) {
13671367 return options.manager;
13681368 }
1369 const services = yield* Effect.services<never>();
1369 const services = yield* Effect.context<never>();
13701370 return options?.makeManager?.(services) ?? new CodexAppServerManager(services);
13711371 });
13721372
......@@ -1585,7 +1585,7 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* (
15851585 });
15861586
15871587 const registerListener = Effect.fn("registerListener")(function* () {
1588 const services = yield* Effect.services<never>();
1588 const services = yield* Effect.context<never>();
15891589 const listenerEffect = Effect.fn("listener")(function* (event: ProviderEvent) {
15901590 yield* writeNativeEvent(event);
15911591 const runtimeEvents = mapToRuntimeEvents(event, event.threadId);
apps/server/src/provider/Layers/EventNdjsonLogger.test.ts+3-3
......@@ -42,11 +42,11 @@ describe("EventNdjsonLogger", () => {
4242
4343 yield* logger.write(
4444 { threadId: "provider-thread-1", id: "evt-1" },
45 ThreadId.makeUnsafe("thread-1"),
45 ThreadId.make("thread-1"),
4646 );
4747 yield* logger.write(
4848 { type: "turn.completed", threadId: "provider-thread-2", id: "evt-2" },
49 ThreadId.makeUnsafe("thread-2"),
49 ThreadId.make("thread-2"),
5050 );
5151 yield* logger.close();
5252
......@@ -178,7 +178,7 @@ describe("EventNdjsonLogger", () => {
178178 id: `evt-${index}`,
179179 payload: "x".repeat(40),
180180 },
181 ThreadId.makeUnsafe("thread-rotate"),
181 ThreadId.make("thread-rotate"),
182182 );
183183 }
184184 yield* logger.close();
apps/server/src/provider/Layers/ProviderRegistry.test.ts+1
......@@ -44,6 +44,7 @@ function mockHandle(result: { stdout: string; stderr: string; code: number }) {
4444 exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(result.code)),
4545 isRunning: Effect.succeed(false),
4646 kill: () => Effect.void,
47 unref: Effect.succeed(Effect.void),
4748 stdin: Sink.drain,
4849 stdout: Stream.make(encoder.encode(result.stdout)),
4950 stderr: Stream.make(encoder.encode(result.stderr)),
apps/server/src/provider/Layers/ProviderService.test.ts+6-6
......@@ -47,10 +47,10 @@ import { AnalyticsService } from "../../telemetry/Services/AnalyticsService.ts";
4747
4848const defaultServerSettingsLayer = ServerSettingsService.layerTest();
4949
50const asRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.makeUnsafe(value);
51const asEventId = (value: string): EventId => EventId.makeUnsafe(value);
52const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value);
53const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value);
50const asRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value);
51const asEventId = (value: string): EventId => EventId.make(value);
52const asThreadId = (value: string): ThreadId => ThreadId.make(value);
53const asTurnId = (value: string): TurnId => TurnId.make(value);
5454
5555type LegacyProviderRuntimeEvent = {
5656 readonly type: string;
......@@ -102,7 +102,7 @@ function makeFakeCodexAdapter(provider: ProviderKind = "codex") {
102102
103103 return Effect.succeed({
104104 threadId: input.threadId,
105 turnId: TurnId.makeUnsafe(`turn-${String(input.threadId)}`),
105 turnId: TurnId.make(`turn-${String(input.threadId)}`),
106106 });
107107 },
108108 );
......@@ -358,7 +358,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", (
358358 const directory = yield* ProviderSessionDirectory;
359359 yield* directory.upsert({
360360 provider: "codex",
361 threadId: ThreadId.makeUnsafe("thread-stale"),
361 threadId: ThreadId.make("thread-stale"),
362362 });
363363 }).pipe(Effect.provide(directoryLayer));
364364
apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts+5-5
......@@ -36,7 +36,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL
3636 const directory = yield* ProviderSessionDirectory;
3737 const runtimeRepository = yield* ProviderSessionRuntimeRepository;
3838
39 const initialThreadId = ThreadId.makeUnsafe("thread-1");
39 const initialThreadId = ThreadId.make("thread-1");
4040
4141 yield* directory.upsert({
4242 provider: "codex",
......@@ -54,7 +54,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL
5454 assert.equal(resolvedBinding.value.threadId, initialThreadId);
5555 }
5656
57 const nextThreadId = ThreadId.makeUnsafe("thread-2");
57 const nextThreadId = ThreadId.make("thread-2");
5858
5959 yield* directory.upsert({
6060 provider: "codex",
......@@ -93,7 +93,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL
9393 const directory = yield* ProviderSessionDirectory;
9494 const runtimeRepository = yield* ProviderSessionRuntimeRepository;
9595
96 const threadId = ThreadId.makeUnsafe("thread-runtime");
96 const threadId = ThreadId.make("thread-runtime");
9797
9898 yield* directory.upsert({
9999 provider: "codex",
......@@ -137,7 +137,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL
137137 Effect.gen(function* () {
138138 const directory = yield* ProviderSessionDirectory;
139139 const runtimeRepository = yield* ProviderSessionRuntimeRepository;
140 const threadId = ThreadId.makeUnsafe("thread-provider-change");
140 const threadId = ThreadId.make("thread-provider-change");
141141
142142 yield* runtimeRepository.upsert({
143143 threadId,
......@@ -169,7 +169,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL
169169 const dbPath = path.join(tempDir, "orchestration.sqlite");
170170 const directoryLayer = makeDirectoryLayer(makeSqlitePersistenceLive(dbPath));
171171
172 const threadId = ThreadId.makeUnsafe("thread-restart");
172 const threadId = ThreadId.make("thread-restart");
173173
174174 yield* Effect.gen(function* () {
175175 const directory = yield* ProviderSessionDirectory;
apps/server/src/provider/Services/ClaudeAdapter.ts+3-3
......@@ -5,12 +5,12 @@
55 * provider runtime events. It does not perform cross-provider routing, shared
66 * event fan-out, or checkpoint orchestration.
77 *
8 * Uses Effect `ServiceMap.Service` for dependency injection and returns the
8 * Uses Effect `Context.Service` for dependency injection and returns the
99 * shared provider-adapter error channel with `provider: "claudeAgent"` context.
1010 *
1111 * @module ClaudeAdapter
1212 */
13import { ServiceMap } from "effect";
13import { Context } from "effect";
1414
1515import type { ProviderAdapterError } from "../Errors.ts";
1616import type { ProviderAdapterShape } from "./ProviderAdapter.ts";
......@@ -25,6 +25,6 @@ export interface ClaudeAdapterShape extends ProviderAdapterShape<ProviderAdapter
2525/**
2626 * ClaudeAdapter - Service tag for Claude Agent provider adapter operations.
2727 */
28export class ClaudeAdapter extends ServiceMap.Service<ClaudeAdapter, ClaudeAdapterShape>()(
28export class ClaudeAdapter extends Context.Service<ClaudeAdapter, ClaudeAdapterShape>()(
2929 "t3/provider/Services/ClaudeAdapter",
3030) {}
apps/server/src/provider/Services/ClaudeProvider.ts+2-2
......@@ -1,9 +1,9 @@
1import { ServiceMap } from "effect";
1import { Context } from "effect";
22
33import type { ServerProviderShape } from "./ServerProvider";
44
55export interface ClaudeProviderShape extends ServerProviderShape {}
66
7export class ClaudeProvider extends ServiceMap.Service<ClaudeProvider, ClaudeProviderShape>()(
7export class ClaudeProvider extends Context.Service<ClaudeProvider, ClaudeProviderShape>()(
88 "t3/provider/Services/ClaudeProvider",
99) {}
apps/server/src/provider/Services/CodexAdapter.ts+3-3
......@@ -5,12 +5,12 @@
55 * Codex provider events. It does not perform cross-provider routing, shared
66 * event fan-out, or checkpoint orchestration.
77 *
8 * Uses Effect `ServiceMap.Service` for dependency injection and returns the
8 * Uses Effect `Context.Service` for dependency injection and returns the
99 * shared provider-adapter error channel with `provider: "codex"` context.
1010 *
1111 * @module CodexAdapter
1212 */
13import { ServiceMap } from "effect";
13import { Context } from "effect";
1414
1515import type { ProviderAdapterError } from "../Errors.ts";
1616import type { ProviderAdapterShape } from "./ProviderAdapter.ts";
......@@ -25,6 +25,6 @@ export interface CodexAdapterShape extends ProviderAdapterShape<ProviderAdapterE
2525/**
2626 * CodexAdapter - Service tag for Codex provider adapter operations.
2727 */
28export class CodexAdapter extends ServiceMap.Service<CodexAdapter, CodexAdapterShape>()(
28export class CodexAdapter extends Context.Service<CodexAdapter, CodexAdapterShape>()(
2929 "t3/provider/Services/CodexAdapter",
3030) {}
apps/server/src/provider/Services/CodexProvider.ts+2-2
......@@ -1,9 +1,9 @@
1import { ServiceMap } from "effect";
1import { Context } from "effect";
22
33import type { ServerProviderShape } from "./ServerProvider";
44
55export interface CodexProviderShape extends ServerProviderShape {}
66
7export class CodexProvider extends ServiceMap.Service<CodexProvider, CodexProviderShape>()(
7export class CodexProvider extends Context.Service<CodexProvider, CodexProviderShape>()(
88 "t3/provider/Services/CodexProvider",
99) {}
apps/server/src/provider/Services/ProviderAdapterRegistry.ts+2-2
......@@ -8,7 +8,7 @@
88 * @module ProviderAdapterRegistry
99 */
1010import type { ProviderKind } from "@t3tools/contracts";
11import { ServiceMap } from "effect";
11import { Context } from "effect";
1212import type { Effect } from "effect";
1313
1414import type { ProviderAdapterError, ProviderUnsupportedError } from "../Errors.ts";
......@@ -34,7 +34,7 @@ export interface ProviderAdapterRegistryShape {
3434/**
3535 * ProviderAdapterRegistry - Service tag for provider adapter lookup.
3636 */
37export class ProviderAdapterRegistry extends ServiceMap.Service<
37export class ProviderAdapterRegistry extends Context.Service<
3838 ProviderAdapterRegistry,
3939 ProviderAdapterRegistryShape
4040>()("t3/provider/Services/ProviderAdapterRegistry") {}
apps/server/src/provider/Services/ProviderRegistry.ts+2-2
......@@ -7,7 +7,7 @@
77 * @module ProviderRegistry
88 */
99import type { ProviderKind, ServerProvider } from "@t3tools/contracts";
10import { ServiceMap } from "effect";
10import { Context } from "effect";
1111import type { Effect, Stream } from "effect";
1212
1313export interface ProviderRegistryShape {
......@@ -27,6 +27,6 @@ export interface ProviderRegistryShape {
2727 readonly streamChanges: Stream.Stream<ReadonlyArray<ServerProvider>>;
2828}
2929
30export class ProviderRegistry extends ServiceMap.Service<ProviderRegistry, ProviderRegistryShape>()(
30export class ProviderRegistry extends Context.Service<ProviderRegistry, ProviderRegistryShape>()(
3131 "t3/provider/Services/ProviderRegistry",
3232) {}
apps/server/src/provider/Services/ProviderService.ts+3-3
......@@ -6,7 +6,7 @@
66 * session-scoped calls via `ProviderSessionDirectory`, and exposes one unified
77 * provider event stream to callers.
88 *
9 * Uses Effect `ServiceMap.Service` for dependency injection and returns typed
9 * Uses Effect `Context.Service` for dependency injection and returns typed
1010 * domain errors for validation, session, codex, and checkpoint workflows.
1111 *
1212 * @module ProviderService
......@@ -24,7 +24,7 @@ import type {
2424 ThreadId,
2525 ProviderTurnStartResult,
2626} from "@t3tools/contracts";
27import { ServiceMap } from "effect";
27import { Context } from "effect";
2828import type { Effect, Stream } from "effect";
2929
3030import type { ProviderServiceError } from "../Errors.ts";
......@@ -110,6 +110,6 @@ export interface ProviderServiceShape {
110110/**
111111 * ProviderService - Service tag for provider orchestration.
112112 */
113export class ProviderService extends ServiceMap.Service<ProviderService, ProviderServiceShape>()(
113export class ProviderService extends Context.Service<ProviderService, ProviderServiceShape>()(
114114 "t3/provider/Services/ProviderService",
115115) {}
apps/server/src/provider/Services/ProviderSessionDirectory.ts+2-2
......@@ -4,7 +4,7 @@ import type {
44 RuntimeMode,
55 ThreadId,
66} from "@t3tools/contracts";
7import { Option, ServiceMap } from "effect";
7import { Option, Context } from "effect";
88import type { Effect } from "effect";
99
1010import type {
......@@ -51,7 +51,7 @@ export interface ProviderSessionDirectoryShape {
5151 >;
5252}
5353
54export class ProviderSessionDirectory extends ServiceMap.Service<
54export class ProviderSessionDirectory extends Context.Service<
5555 ProviderSessionDirectory,
5656 ProviderSessionDirectoryShape
5757>()("t3/provider/Services/ProviderSessionDirectory") {}
apps/server/src/server.test.ts+32-32
......@@ -101,15 +101,15 @@ import { WorkspacePathsLive } from "./workspace/Layers/WorkspacePaths.ts";
101101import { ServerSecretStoreLive } from "./auth/Layers/ServerSecretStore.ts";
102102import { ServerAuthLive } from "./auth/Layers/ServerAuth.ts";
103103
104const defaultProjectId = ProjectId.makeUnsafe("project-default");
105const defaultThreadId = ThreadId.makeUnsafe("thread-default");
104const defaultProjectId = ProjectId.make("project-default");
105const defaultThreadId = ThreadId.make("thread-default");
106106const defaultDesktopBootstrapToken = "test-desktop-bootstrap-token";
107107const defaultModelSelection = {
108108 provider: "codex",
109109 model: "gpt-5-codex",
110110} as const;
111111const testEnvironmentDescriptor = {
112 environmentId: EnvironmentId.makeUnsafe("environment-test"),
112 environmentId: EnvironmentId.make("environment-test"),
113113 label: "Test environment",
114114 platform: {
115115 os: "darwin" as const,
......@@ -1307,7 +1307,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
13071307 );
13081308
13091309 assert.equal(error._tag, "RpcClientError");
1310 assertInclude(String(error), "401");
1310 assertInclude(String(error), "SocketOpenError");
13111311 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
13121312 );
13131313
......@@ -2685,7 +2685,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
26852685 updatedAt: now,
26862686 projects: [
26872687 {
2688 id: ProjectId.makeUnsafe("project-a"),
2688 id: ProjectId.make("project-a"),
26892689 title: "Project A",
26902690 workspaceRoot: "/tmp/project-a",
26912691 defaultModelSelection,
......@@ -2697,8 +2697,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
26972697 ],
26982698 threads: [
26992699 {
2700 id: ThreadId.makeUnsafe("thread-1"),
2701 projectId: ProjectId.makeUnsafe("project-a"),
2700 id: ThreadId.make("thread-1"),
2701 projectId: ProjectId.make("project-a"),
27022702 title: "Thread A",
27032703 modelSelection: defaultModelSelection,
27042704 interactionMode: "default" as const,
......@@ -2731,14 +2731,14 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
27312731 checkpointDiffQuery: {
27322732 getTurnDiff: () =>
27332733 Effect.succeed({
2734 threadId: ThreadId.makeUnsafe("thread-1"),
2734 threadId: ThreadId.make("thread-1"),
27352735 fromTurnCount: 0,
27362736 toTurnCount: 1,
27372737 diff: "turn-diff",
27382738 }),
27392739 getFullThreadDiff: () =>
27402740 Effect.succeed({
2741 threadId: ThreadId.makeUnsafe("thread-1"),
2741 threadId: ThreadId.make("thread-1"),
27422742 fromTurnCount: 0,
27432743 toTurnCount: 1,
27442744 diff: "full-diff",
......@@ -2757,8 +2757,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
27572757 withWsRpcClient(wsUrl, (client) =>
27582758 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
27592759 type: "thread.session.stop",
2760 commandId: CommandId.makeUnsafe("cmd-1"),
2761 threadId: ThreadId.makeUnsafe("thread-1"),
2760 commandId: CommandId.make("cmd-1"),
2761 threadId: ThreadId.make("thread-1"),
27622762 createdAt: now,
27632763 }),
27642764 ),
......@@ -2768,7 +2768,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
27682768 const turnDiffResult = yield* Effect.scoped(
27692769 withWsRpcClient(wsUrl, (client) =>
27702770 client[ORCHESTRATION_WS_METHODS.getTurnDiff]({
2771 threadId: ThreadId.makeUnsafe("thread-1"),
2771 threadId: ThreadId.make("thread-1"),
27722772 fromTurnCount: 0,
27732773 toTurnCount: 1,
27742774 }),
......@@ -2779,7 +2779,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
27792779 const fullDiffResult = yield* Effect.scoped(
27802780 withWsRpcClient(wsUrl, (client) =>
27812781 client[ORCHESTRATION_WS_METHODS.getFullThreadDiff]({
2782 threadId: ThreadId.makeUnsafe("thread-1"),
2782 threadId: ThreadId.make("thread-1"),
27832783 toTurnCount: 1,
27842784 }),
27852785 ),
......@@ -2818,7 +2818,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
28182818 readEvents: (_fromSequenceExclusive) =>
28192819 Stream.make({
28202820 sequence: 1,
2821 eventId: EventId.makeUnsafe("event-1"),
2821 eventId: EventId.make("event-1"),
28222822 aggregateKind: "project",
28232823 aggregateId: defaultProjectId,
28242824 occurredAt: "2026-04-05T00:00:00.000Z",
......@@ -2866,7 +2866,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
28662866
28672867 it.effect("closes thread terminals after a successful archive command", () =>
28682868 Effect.gen(function* () {
2869 const threadId = ThreadId.makeUnsafe("thread-archive");
2869 const threadId = ThreadId.make("thread-archive");
28702870 const closeInputs: Array<Parameters<TerminalManagerShape["close"]>[0]> = [];
28712871
28722872 yield* buildAppUnderTest({
......@@ -2888,7 +2888,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
28882888 withWsRpcClient(wsUrl, (client) =>
28892889 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
28902890 type: "thread.archive",
2891 commandId: CommandId.makeUnsafe("cmd-thread-archive"),
2891 commandId: CommandId.make("cmd-thread-archive"),
28922892 threadId,
28932893 }),
28942894 ),
......@@ -2948,10 +2948,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
29482948 withWsRpcClient(wsUrl, (client) =>
29492949 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
29502950 type: "thread.turn.start",
2951 commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start"),
2952 threadId: ThreadId.makeUnsafe("thread-bootstrap"),
2951 commandId: CommandId.make("cmd-bootstrap-turn-start"),
2952 threadId: ThreadId.make("thread-bootstrap"),
29532953 message: {
2954 messageId: MessageId.makeUnsafe("msg-bootstrap"),
2954 messageId: MessageId.make("msg-bootstrap"),
29552955 role: "user",
29562956 text: "hello",
29572957 attachments: [],
......@@ -3000,7 +3000,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
30003000 path: null,
30013001 });
30023002 assert.deepEqual(runForThread.mock.calls[0]?.[0], {
3003 threadId: ThreadId.makeUnsafe("thread-bootstrap"),
3003 threadId: ThreadId.make("thread-bootstrap"),
30043004 projectId: defaultProjectId,
30053005 projectCwd: "/tmp/project",
30063006 worktreePath: "/tmp/bootstrap-worktree",
......@@ -3063,10 +3063,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
30633063 withWsRpcClient(wsUrl, (client) =>
30643064 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
30653065 type: "thread.turn.start",
3066 commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start-setup-failure"),
3067 threadId: ThreadId.makeUnsafe("thread-bootstrap-setup-failure"),
3066 commandId: CommandId.make("cmd-bootstrap-turn-start-setup-failure"),
3067 threadId: ThreadId.make("thread-bootstrap-setup-failure"),
30683068 message: {
3069 messageId: MessageId.makeUnsafe("msg-bootstrap-setup-failure"),
3069 messageId: MessageId.make("msg-bootstrap-setup-failure"),
30703070 role: "user",
30713071 text: "hello",
30723072 attachments: [],
......@@ -3179,10 +3179,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
31793179 withWsRpcClient(wsUrl, (client) =>
31803180 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
31813181 type: "thread.turn.start",
3182 commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start-setup-activity-failure"),
3183 threadId: ThreadId.makeUnsafe("thread-bootstrap-setup-activity-failure"),
3182 commandId: CommandId.make("cmd-bootstrap-turn-start-setup-activity-failure"),
3183 threadId: ThreadId.make("thread-bootstrap-setup-activity-failure"),
31843184 message: {
3185 messageId: MessageId.makeUnsafe("msg-bootstrap-setup-activity-failure"),
3185 messageId: MessageId.make("msg-bootstrap-setup-activity-failure"),
31863186 role: "user",
31873187 text: "hello",
31883188 attachments: [],
......@@ -3262,10 +3262,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
32623262 withWsRpcClient(wsUrl, (client) =>
32633263 client[ORCHESTRATION_WS_METHODS.dispatchCommand]({
32643264 type: "thread.turn.start",
3265 commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start-defect"),
3266 threadId: ThreadId.makeUnsafe("thread-bootstrap-defect"),
3265 commandId: CommandId.make("cmd-bootstrap-turn-start-defect"),
3266 threadId: ThreadId.make("thread-bootstrap-defect"),
32673267 message: {
3268 messageId: MessageId.makeUnsafe("msg-bootstrap-defect"),
3268 messageId: MessageId.make("msg-bootstrap-defect"),
32693269 role: "user",
32703270 text: "hello",
32713271 attachments: [],
......@@ -3311,7 +3311,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
33113311 () =>
33123312 Effect.gen(function* () {
33133313 const now = new Date().toISOString();
3314 const threadId = ThreadId.makeUnsafe("thread-1");
3314 const threadId = ThreadId.make("thread-1");
33153315 let replayCursor: number | null = null;
33163316 const makeEvent = (sequence: number): OrchestrationEvent =>
33173317 ({
......@@ -3393,7 +3393,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
33933393 readEvents: () =>
33943394 Stream.make({
33953395 sequence: 1,
3396 eventId: EventId.makeUnsafe("event-1"),
3396 eventId: EventId.make("event-1"),
33973397 aggregateKind: "project",
33983398 aggregateId: defaultProjectId,
33993399 occurredAt: "2026-04-06T00:00:00.000Z",
......@@ -3464,7 +3464,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
34643464 }),
34653465 streamDomainEvents: Stream.make({
34663466 sequence: 1,
3467 eventId: EventId.makeUnsafe("event-1"),
3467 eventId: EventId.make("event-1"),
34683468 aggregateKind: "project",
34693469 aggregateId: defaultProjectId,
34703470 occurredAt: "2026-04-05T00:00:00.000Z",
apps/server/src/serverLifecycleEvents.test.ts+1-1
......@@ -11,7 +11,7 @@ it.effect(
1111 Effect.gen(function* () {
1212 const lifecycleEvents = yield* ServerLifecycleEvents;
1313 const environment = {
14 environmentId: EnvironmentId.makeUnsafe("environment-test"),
14 environmentId: EnvironmentId.make("environment-test"),
1515 label: "Test environment",
1616 platform: { os: "darwin" as const, arch: "arm64" as const },
1717 serverVersion: "0.0.0-test",
apps/server/src/serverLifecycleEvents.ts+2-2
......@@ -1,5 +1,5 @@
11import type { ServerLifecycleStreamEvent } from "@t3tools/contracts";
2import { Effect, Layer, PubSub, Ref, ServiceMap, Stream } from "effect";
2import { Effect, Layer, PubSub, Ref, Context, Stream } from "effect";
33
44type LifecycleEventInput =
55 | Omit<Extract<ServerLifecycleStreamEvent, { type: "welcome" }>, "sequence">
......@@ -16,7 +16,7 @@ export interface ServerLifecycleEventsShape {
1616 readonly stream: Stream.Stream<ServerLifecycleStreamEvent>;
1717}
1818
19export class ServerLifecycleEvents extends ServiceMap.Service<
19export class ServerLifecycleEvents extends Context.Service<
2020 ServerLifecycleEvents,
2121 ServerLifecycleEventsShape
2222>()("t3/serverLifecycleEvents") {}
apps/server/src/serverRuntimeStartup.ts+6-6
......@@ -17,7 +17,7 @@ import {
1717 Queue,
1818 Ref,
1919 Scope,
20 ServiceMap,
20 Context,
2121 Console,
2222} from "effect";
2323
......@@ -52,7 +52,7 @@ export interface ServerRuntimeStartupShape {
5252 ) => Effect.Effect<A, E | ServerRuntimeStartupError>;
5353}
5454
55export class ServerRuntimeStartup extends ServiceMap.Service<
55export class ServerRuntimeStartup extends Context.Service<
5656 ServerRuntimeStartup,
5757 ServerRuntimeStartupShape
5858>()("t3/serverRuntimeStartup") {}
......@@ -176,12 +176,12 @@ const autoBootstrapWelcome = Effect.gen(function* () {
176176
177177 if (Option.isNone(existingProject)) {
178178 const createdAt = new Date().toISOString();
179 nextProjectId = ProjectId.makeUnsafe(crypto.randomUUID());
179 nextProjectId = ProjectId.make(crypto.randomUUID());
180180 const bootstrapProjectTitle = path.basename(serverConfig.cwd) || "project";
181181 nextProjectDefaultModelSelection = getAutoBootstrapDefaultModelSelection();
182182 yield* orchestrationEngine.dispatch({
183183 type: "project.create",
184 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
184 commandId: CommandId.make(crypto.randomUUID()),
185185 projectId: nextProjectId,
186186 title: bootstrapProjectTitle,
187187 workspaceRoot: serverConfig.cwd,
......@@ -198,10 +198,10 @@ const autoBootstrapWelcome = Effect.gen(function* () {
198198 yield* projectionReadModelQuery.getFirstActiveThreadIdByProjectId(nextProjectId);
199199 if (Option.isNone(existingThreadId)) {
200200 const createdAt = new Date().toISOString();
201 const createdThreadId = ThreadId.makeUnsafe(crypto.randomUUID());
201 const createdThreadId = ThreadId.make(crypto.randomUUID());
202202 yield* orchestrationEngine.dispatch({
203203 type: "thread.create",
204 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
204 commandId: CommandId.make(crypto.randomUUID()),
205205 threadId: createdThreadId,
206206 projectId: nextProjectId,
207207 title: "New thread",
apps/server/src/serverSettings.ts+2-2
......@@ -34,7 +34,7 @@ import {
3434 Schema,
3535 SchemaIssue,
3636 Scope,
37 ServiceMap,
37 Context,
3838 Stream,
3939 Cause,
4040} from "effect";
......@@ -62,7 +62,7 @@ export interface ServerSettingsShape {
6262 readonly streamChanges: Stream.Stream<ServerSettings>;
6363}
6464
65export class ServerSettingsService extends ServiceMap.Service<
65export class ServerSettingsService extends Context.Service<
6666 ServerSettingsService,
6767 ServerSettingsShape
6868>()("t3/serverSettings/ServerSettingsService") {
apps/server/src/telemetry/Services/AnalyticsService.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module AnalyticsService
88 */
9import { Effect, Layer, ServiceMap } from "effect";
9import { Effect, Layer, Context } from "effect";
1010
1111export interface AnalyticsServiceShape {
1212 /**
......@@ -23,7 +23,7 @@ export interface AnalyticsServiceShape {
2323 readonly flush: Effect.Effect<void, never>;
2424}
2525
26export class AnalyticsService extends ServiceMap.Service<AnalyticsService, AnalyticsServiceShape>()(
26export class AnalyticsService extends Context.Service<AnalyticsService, AnalyticsServiceShape>()(
2727 "t3/telemetry/Services/AnalyticsService",
2828) {
2929 static readonly layerTest = Layer.succeed(AnalyticsService, {
apps/server/src/terminal/Layers/Manager.ts+2-2
......@@ -664,8 +664,8 @@ const makeTerminalManager = Effect.fn("makeTerminalManager")(function* () {
664664export const makeTerminalManagerWithOptions = Effect.fn("makeTerminalManagerWithOptions")(
665665 function* (options: TerminalManagerOptions) {
666666 const fileSystem = yield* FileSystem.FileSystem;
667 const services = yield* Effect.services();
668 const runFork = Effect.runForkWith(services);
667 const context = yield* Effect.context<never>();
668 const runFork = Effect.runForkWith(context);
669669
670670 const logsDir = options.logsDir;
671671 const historyLineLimit = options.historyLineLimit ?? DEFAULT_HISTORY_LINE_LIMIT;
apps/server/src/terminal/Services/Manager.ts+2-2
......@@ -23,7 +23,7 @@ import {
2323 TerminalWriteInput,
2424} from "@t3tools/contracts";
2525import { PtyProcess } from "./PTY";
26import { Effect, ServiceMap } from "effect";
26import { Effect, Context } from "effect";
2727
2828export {
2929 TerminalCwdError,
......@@ -122,6 +122,6 @@ export interface TerminalManagerShape {
122122/**
123123 * TerminalManager - Service tag for terminal session orchestration.
124124 */
125export class TerminalManager extends ServiceMap.Service<TerminalManager, TerminalManagerShape>()(
125export class TerminalManager extends Context.Service<TerminalManager, TerminalManagerShape>()(
126126 "t3/terminal/Services/Manager/TerminalManager",
127127) {}
apps/server/src/terminal/Services/PTY.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module PtyAdapter
88 */
9import { Effect, Schema, ServiceMap } from "effect";
9import { Effect, Schema, Context } from "effect";
1010
1111/**
1212 * PtyError - Error type for PTY adapter operations.
......@@ -53,6 +53,6 @@ export interface PtyAdapterShape {
5353/**
5454 * PtyAdapter - Service tag for PTY process integration.
5555 */
56export class PtyAdapter extends ServiceMap.Service<PtyAdapter, PtyAdapterShape>()(
56export class PtyAdapter extends Context.Service<PtyAdapter, PtyAdapterShape>()(
5757 "t3/terminal/Services/PTY/PtyAdapter",
5858) {}
apps/server/src/workspace/Layers/WorkspaceEntries.ts+8-6
......@@ -430,12 +430,14 @@ export const makeWorkspaceEntries = Effect.gen(function* () {
430430 return yield* buildWorkspaceIndexFromFilesystem(cwd);
431431 });
432432
433 const workspaceIndexCache = yield* Cache.makeWith<string, WorkspaceIndex, WorkspaceEntriesError>({
434 capacity: WORKSPACE_CACHE_MAX_KEYS,
435 lookup: buildWorkspaceIndex,
436 timeToLive: (exit) =>
437 Exit.isSuccess(exit) ? Duration.millis(WORKSPACE_CACHE_TTL_MS) : Duration.zero,
438 });
433 const workspaceIndexCache = yield* Cache.makeWith<string, WorkspaceIndex, WorkspaceEntriesError>(
434 buildWorkspaceIndex,
435 {
436 capacity: WORKSPACE_CACHE_MAX_KEYS,
437 timeToLive: (exit) =>
438 Exit.isSuccess(exit) ? Duration.millis(WORKSPACE_CACHE_TTL_MS) : Duration.zero,
439 },
440 );
439441
440442 const normalizeWorkspaceRoot = Effect.fn("WorkspaceEntries.normalizeWorkspaceRoot")(function* (
441443 cwd: string,
apps/server/src/workspace/Services/WorkspaceEntries.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module WorkspaceEntries
88 */
9import { Schema, ServiceMap } from "effect";
9import { Schema, Context } from "effect";
1010import type { Effect } from "effect";
1111
1212import type { ProjectSearchEntriesInput, ProjectSearchEntriesResult } from "@t3tools/contracts";
......@@ -43,6 +43,6 @@ export interface WorkspaceEntriesShape {
4343/**
4444 * WorkspaceEntries - Service tag for cached workspace entry search.
4545 */
46export class WorkspaceEntries extends ServiceMap.Service<WorkspaceEntries, WorkspaceEntriesShape>()(
46export class WorkspaceEntries extends Context.Service<WorkspaceEntries, WorkspaceEntriesShape>()(
4747 "t3/workspace/Services/WorkspaceEntries",
4848) {}
apps/server/src/workspace/Services/WorkspaceFileSystem.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module WorkspaceFileSystem
88 */
9import { Schema, ServiceMap } from "effect";
9import { Schema, Context } from "effect";
1010import type { Effect } from "effect";
1111
1212import type { ProjectWriteFileInput, ProjectWriteFileResult } from "@t3tools/contracts";
......@@ -44,7 +44,7 @@ export interface WorkspaceFileSystemShape {
4444/**
4545 * WorkspaceFileSystem - Service tag for workspace file operations.
4646 */
47export class WorkspaceFileSystem extends ServiceMap.Service<
47export class WorkspaceFileSystem extends Context.Service<
4848 WorkspaceFileSystem,
4949 WorkspaceFileSystemShape
5050>()("t3/workspace/Services/WorkspaceFileSystem") {}
apps/server/src/workspace/Services/WorkspacePaths.ts+2-2
......@@ -6,7 +6,7 @@
66 *
77 * @module WorkspacePaths
88 */
9import { Schema, ServiceMap } from "effect";
9import { Schema, Context } from "effect";
1010import type { Effect } from "effect";
1111
1212export class WorkspaceRootNotExistsError extends Schema.TaggedErrorClass<WorkspaceRootNotExistsError>()(
......@@ -80,6 +80,6 @@ export interface WorkspacePathsShape {
8080/**
8181 * WorkspacePaths - Service tag for workspace path normalization and resolution.
8282 */
83export class WorkspacePaths extends ServiceMap.Service<WorkspacePaths, WorkspacePathsShape>()(
83export class WorkspacePaths extends Context.Service<WorkspacePaths, WorkspacePathsShape>()(
8484 "t3/workspace/Services/WorkspacePaths",
8585) {}
apps/server/src/ws.ts+2-2
......@@ -128,7 +128,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
128128 const bootstrapCredentials = yield* BootstrapCredentialService;
129129 const sessions = yield* SessionCredentialService;
130130 const serverCommandId = (tag: string) =>
131 CommandId.makeUnsafe(`server:${tag}:${crypto.randomUUID()}`);
131 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);
132132
133133 const loadAuthAccessSnapshot = () =>
134134 Effect.all({
......@@ -149,7 +149,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
149149 commandId: serverCommandId("setup-script-activity"),
150150 threadId: input.threadId,
151151 activity: {
152 id: EventId.makeUnsafe(crypto.randomUUID()),
152 id: EventId.make(crypto.randomUUID()),
153153 tone: input.tone,
154154 kind: input.kind,
155155 summary: input.summary,
apps/web/src/clientPersistenceStorage.test.ts+1-1
......@@ -1,7 +1,7 @@
11import { EnvironmentId, type PersistedSavedEnvironmentRecord } from "@t3tools/contracts";
22import { afterEach, describe, expect, it, vi } from "vitest";
33
4const testEnvironmentId = EnvironmentId.makeUnsafe("environment-1");
4const testEnvironmentId = EnvironmentId.make("environment-1");
55
66const savedRegistryRecord: PersistedSavedEnvironmentRecord = {
77 environmentId: testEnvironmentId,
apps/web/src/components/BranchToolbar.logic.test.ts+2-2
......@@ -13,8 +13,8 @@ import {
1313 shouldIncludeBranchPickerItem,
1414} from "./BranchToolbar.logic";
1515
16const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local");
17const remoteEnvironmentId = EnvironmentId.makeUnsafe("environment-remote");
16const localEnvironmentId = EnvironmentId.make("environment-local");
17const remoteEnvironmentId = EnvironmentId.make("environment-remote");
1818
1919describe("resolveDraftEnvModeAfterBranchChange", () => {
2020 it("switches to local mode when returning from an existing worktree to the main worktree", () => {
apps/web/src/components/ChatView.browser.tsx+7-7
......@@ -58,7 +58,7 @@ vi.mock("../lib/gitStatusState", () => ({
5858
5959const THREAD_ID = "thread-browser-test" as ThreadId;
6060const PROJECT_ID = "project-1" as ProjectId;
61const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local");
61const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local");
6262const THREAD_REF = scopeThreadRef(LOCAL_ENVIRONMENT_ID, THREAD_ID);
6363const THREAD_KEY = scopedThreadKey(THREAD_REF);
6464const UUID_ROUTE_RE = /^\/draft\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
......@@ -143,7 +143,7 @@ function isoAt(offsetSeconds: number): string {
143143function createBaseServerConfig(): ServerConfig {
144144 return {
145145 environment: {
146 environmentId: EnvironmentId.makeUnsafe("environment-local"),
146 environmentId: EnvironmentId.make("environment-local"),
147147 label: "Local environment",
148148 platform: { os: "darwin" as const, arch: "arm64" as const },
149149 serverVersion: "0.0.0-test",
......@@ -341,7 +341,7 @@ function buildFixture(snapshot: OrchestrationReadModel): TestFixture {
341341 serverConfig: createBaseServerConfig(),
342342 welcome: {
343343 environment: {
344 environmentId: EnvironmentId.makeUnsafe("environment-local"),
344 environmentId: EnvironmentId.make("environment-local"),
345345 label: "Local environment",
346346 platform: { os: "darwin" as const, arch: "arm64" as const },
347347 serverVersion: "0.0.0-test",
......@@ -402,7 +402,7 @@ function addThreadToSnapshot(
402402function createThreadCreatedEvent(threadId: ThreadId, sequence: number): OrchestrationEvent {
403403 return {
404404 sequence,
405 eventId: EventId.makeUnsafe(`event-thread-created-${sequence}`),
405 eventId: EventId.make(`event-thread-created-${sequence}`),
406406 aggregateKind: "thread",
407407 aggregateId: threadId,
408408 occurredAt: NOW_ISO,
......@@ -432,7 +432,7 @@ function createThreadCreatedEvent(threadId: ThreadId, sequence: number): Orchest
432432function createThreadSessionSetEvent(threadId: ThreadId, sequence: number): OrchestrationEvent {
433433 return {
434434 sequence,
435 eventId: EventId.makeUnsafe(`event-thread-session-set-${sequence}`),
435 eventId: EventId.make(`event-thread-session-set-${sequence}`),
436436 aggregateKind: "thread",
437437 aggregateId: threadId,
438438 occurredAt: NOW_ISO,
......@@ -498,7 +498,7 @@ function draftIdFromPath(pathname: string) {
498498 if (!draftId) {
499499 throw new Error(`Expected thread path, received "${pathname}".`);
500500 }
501 return DraftId.makeUnsafe(draftId);
501 return DraftId.make(draftId);
502502}
503503
504504function draftThreadIdFor(draftId: ReturnType<typeof draftIdFromPath>): ThreadId {
......@@ -666,7 +666,7 @@ function createSnapshotWithPendingUserInput(): OrchestrationReadModel {
666666 interactionMode: "plan",
667667 activities: [
668668 {
669 id: EventId.makeUnsafe("activity-user-input-requested"),
669 id: EventId.make("activity-user-input-requested"),
670670 tone: "info",
671671 kind: "user-input.requested",
672672 summary: "User input requested",
apps/web/src/components/ChatView.logic.test.ts+45-56
......@@ -15,7 +15,7 @@ import {
1515 waitForStartedServerThread,
1616} from "./ChatView.logic";
1717
18const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local");
18const localEnvironmentId = EnvironmentId.make("environment-local");
1919
2020describe("deriveComposerSendState", () => {
2121 it("treats expired terminal pills as non-sendable content", () => {
......@@ -25,7 +25,7 @@ describe("deriveComposerSendState", () => {
2525 terminalContexts: [
2626 {
2727 id: "ctx-expired",
28 threadId: ThreadId.makeUnsafe("thread-1"),
28 threadId: ThreadId.make("thread-1"),
2929 terminalId: "default",
3030 terminalLabel: "Terminal 1",
3131 lineStart: 4,
......@@ -49,7 +49,7 @@ describe("deriveComposerSendState", () => {
4949 terminalContexts: [
5050 {
5151 id: "ctx-expired",
52 threadId: ThreadId.makeUnsafe("thread-1"),
52 threadId: ThreadId.make("thread-1"),
5353 terminalId: "default",
5454 terminalLabel: "Terminal 1",
5555 lineStart: 4,
......@@ -86,23 +86,20 @@ describe("reconcileMountedTerminalThreadIds", () => {
8686 it("keeps previously mounted open threads and adds the active open thread", () => {
8787 expect(
8888 reconcileMountedTerminalThreadIds({
89 currentThreadIds: [
90 ThreadId.makeUnsafe("thread-hidden"),
91 ThreadId.makeUnsafe("thread-stale"),
92 ],
93 openThreadIds: [ThreadId.makeUnsafe("thread-hidden"), ThreadId.makeUnsafe("thread-active")],
94 activeThreadId: ThreadId.makeUnsafe("thread-active"),
89 currentThreadIds: [ThreadId.make("thread-hidden"), ThreadId.make("thread-stale")],
90 openThreadIds: [ThreadId.make("thread-hidden"), ThreadId.make("thread-active")],
91 activeThreadId: ThreadId.make("thread-active"),
9592 activeThreadTerminalOpen: true,
9693 }),
97 ).toEqual([ThreadId.makeUnsafe("thread-hidden"), ThreadId.makeUnsafe("thread-active")]);
94 ).toEqual([ThreadId.make("thread-hidden"), ThreadId.make("thread-active")]);
9895 });
9996
10097 it("drops mounted threads once their terminal drawer is no longer open", () => {
10198 expect(
10299 reconcileMountedTerminalThreadIds({
103 currentThreadIds: [ThreadId.makeUnsafe("thread-closed")],
100 currentThreadIds: [ThreadId.make("thread-closed")],
104101 openThreadIds: [],
105 activeThreadId: ThreadId.makeUnsafe("thread-closed"),
102 activeThreadId: ThreadId.make("thread-closed"),
106103 activeThreadTerminalOpen: false,
107104 }),
108105 ).toEqual([]);
......@@ -112,55 +109,47 @@ describe("reconcileMountedTerminalThreadIds", () => {
112109 expect(
113110 reconcileMountedTerminalThreadIds({
114111 currentThreadIds: [
115 ThreadId.makeUnsafe("thread-1"),
116 ThreadId.makeUnsafe("thread-2"),
117 ThreadId.makeUnsafe("thread-3"),
112 ThreadId.make("thread-1"),
113 ThreadId.make("thread-2"),
114 ThreadId.make("thread-3"),
118115 ],
119116 openThreadIds: [
120 ThreadId.makeUnsafe("thread-1"),
121 ThreadId.makeUnsafe("thread-2"),
122 ThreadId.makeUnsafe("thread-3"),
123 ThreadId.makeUnsafe("thread-4"),
117 ThreadId.make("thread-1"),
118 ThreadId.make("thread-2"),
119 ThreadId.make("thread-3"),
120 ThreadId.make("thread-4"),
124121 ],
125 activeThreadId: ThreadId.makeUnsafe("thread-4"),
122 activeThreadId: ThreadId.make("thread-4"),
126123 activeThreadTerminalOpen: true,
127124 maxHiddenThreadCount: 2,
128125 }),
129 ).toEqual([
130 ThreadId.makeUnsafe("thread-2"),
131 ThreadId.makeUnsafe("thread-3"),
132 ThreadId.makeUnsafe("thread-4"),
133 ]);
126 ).toEqual([ThreadId.make("thread-2"), ThreadId.make("thread-3"), ThreadId.make("thread-4")]);
134127 });
135128
136129 it("moves the active thread to the end so it is treated as most recently used", () => {
137130 expect(
138131 reconcileMountedTerminalThreadIds({
139132 currentThreadIds: [
140 ThreadId.makeUnsafe("thread-a"),
141 ThreadId.makeUnsafe("thread-b"),
142 ThreadId.makeUnsafe("thread-c"),
133 ThreadId.make("thread-a"),
134 ThreadId.make("thread-b"),
135 ThreadId.make("thread-c"),
143136 ],
144137 openThreadIds: [
145 ThreadId.makeUnsafe("thread-a"),
146 ThreadId.makeUnsafe("thread-b"),
147 ThreadId.makeUnsafe("thread-c"),
138 ThreadId.make("thread-a"),
139 ThreadId.make("thread-b"),
140 ThreadId.make("thread-c"),
148141 ],
149 activeThreadId: ThreadId.makeUnsafe("thread-a"),
142 activeThreadId: ThreadId.make("thread-a"),
150143 activeThreadTerminalOpen: true,
151144 maxHiddenThreadCount: 2,
152145 }),
153 ).toEqual([
154 ThreadId.makeUnsafe("thread-b"),
155 ThreadId.makeUnsafe("thread-c"),
156 ThreadId.makeUnsafe("thread-a"),
157 ]);
146 ).toEqual([ThreadId.make("thread-b"), ThreadId.make("thread-c"), ThreadId.make("thread-a")]);
158147 });
159148
160149 it("defaults to the hidden mounted terminal cap", () => {
161150 const currentThreadIds = Array.from(
162151 { length: MAX_HIDDEN_MOUNTED_TERMINAL_THREADS + 2 },
163 (_, index) => ThreadId.makeUnsafe(`thread-${index + 1}`),
152 (_, index) => ThreadId.make(`thread-${index + 1}`),
164153 );
165154
166155 expect(
......@@ -176,7 +165,7 @@ describe("reconcileMountedTerminalThreadIds", () => {
176165
177166describe("shouldWriteThreadErrorToCurrentServerThread", () => {
178167 it("routes errors to the active server thread when route and target match", () => {
179 const threadId = ThreadId.makeUnsafe("thread-1");
168 const threadId = ThreadId.make("thread-1");
180169 const routeThreadRef = scopeThreadRef(localEnvironmentId, threadId);
181170
182171 expect(
......@@ -192,7 +181,7 @@ describe("shouldWriteThreadErrorToCurrentServerThread", () => {
192181 });
193182
194183 it("does not route draft-thread errors into server-backed state", () => {
195 const threadId = ThreadId.makeUnsafe("thread-1");
184 const threadId = ThreadId.make("thread-1");
196185
197186 expect(
198187 shouldWriteThreadErrorToCurrentServerThread({
......@@ -214,10 +203,10 @@ const makeThread = (input?: {
214203 completedAt: string | null;
215204 } | null;
216205}): Thread => ({
217 id: input?.id ?? ThreadId.makeUnsafe("thread-1"),
206 id: input?.id ?? ThreadId.make("thread-1"),
218207 environmentId: localEnvironmentId,
219208 codexThreadId: null,
220 projectId: ProjectId.makeUnsafe("project-1"),
209 projectId: ProjectId.make("project-1"),
221210 title: "Thread",
222211 modelSelection: { provider: "codex" as const, model: "gpt-5.4" },
223212 runtimeMode: "full-access" as const,
......@@ -242,7 +231,7 @@ const makeThread = (input?: {
242231});
243232
244233function setStoreThreads(threads: ReadonlyArray<ReturnType<typeof makeThread>>) {
245 const projectId = ProjectId.makeUnsafe("project-1");
234 const projectId = ProjectId.make("project-1");
246235 const environmentState: EnvironmentState = {
247236 projectIds: [projectId],
248237 projectById: {
......@@ -355,12 +344,12 @@ afterEach(() => {
355344
356345describe("waitForStartedServerThread", () => {
357346 it("resolves immediately when the thread is already started", async () => {
358 const threadId = ThreadId.makeUnsafe("thread-started");
347 const threadId = ThreadId.make("thread-started");
359348 setStoreThreads([
360349 makeThread({
361350 id: threadId,
362351 latestTurn: {
363 turnId: TurnId.makeUnsafe("turn-started"),
352 turnId: TurnId.make("turn-started"),
364353 state: "running",
365354 requestedAt: "2026-03-29T00:00:01.000Z",
366355 startedAt: "2026-03-29T00:00:01.000Z",
......@@ -375,7 +364,7 @@ describe("waitForStartedServerThread", () => {
375364 });
376365
377366 it("waits for the thread to start via subscription updates", async () => {
378 const threadId = ThreadId.makeUnsafe("thread-wait");
367 const threadId = ThreadId.make("thread-wait");
379368 setStoreThreads([makeThread({ id: threadId })]);
380369
381370 const promise = waitForStartedServerThread(scopeThreadRef(localEnvironmentId, threadId), 500);
......@@ -384,7 +373,7 @@ describe("waitForStartedServerThread", () => {
384373 makeThread({
385374 id: threadId,
386375 latestTurn: {
387 turnId: TurnId.makeUnsafe("turn-started"),
376 turnId: TurnId.make("turn-started"),
388377 state: "running",
389378 requestedAt: "2026-03-29T00:00:01.000Z",
390379 startedAt: "2026-03-29T00:00:01.000Z",
......@@ -397,7 +386,7 @@ describe("waitForStartedServerThread", () => {
397386 });
398387
399388 it("handles the thread starting between the initial read and subscription setup", async () => {
400 const threadId = ThreadId.makeUnsafe("thread-race");
389 const threadId = ThreadId.make("thread-race");
401390 setStoreThreads([makeThread({ id: threadId })]);
402391
403392 const originalSubscribe = useStore.subscribe.bind(useStore);
......@@ -409,7 +398,7 @@ describe("waitForStartedServerThread", () => {
409398 makeThread({
410399 id: threadId,
411400 latestTurn: {
412 turnId: TurnId.makeUnsafe("turn-race"),
401 turnId: TurnId.make("turn-race"),
413402 state: "running",
414403 requestedAt: "2026-03-29T00:00:01.000Z",
415404 startedAt: "2026-03-29T00:00:01.000Z",
......@@ -429,7 +418,7 @@ describe("waitForStartedServerThread", () => {
429418 it("returns false after the timeout when the thread never starts", async () => {
430419 vi.useFakeTimers();
431420
432 const threadId = ThreadId.makeUnsafe("thread-timeout");
421 const threadId = ThreadId.make("thread-timeout");
433422 setStoreThreads([makeThread({ id: threadId })]);
434423 const promise = waitForStartedServerThread(scopeThreadRef(localEnvironmentId, threadId), 500);
435424
......@@ -440,9 +429,9 @@ describe("waitForStartedServerThread", () => {
440429});
441430
442431describe("hasServerAcknowledgedLocalDispatch", () => {
443 const projectId = ProjectId.makeUnsafe("project-1");
432 const projectId = ProjectId.make("project-1");
444433 const previousLatestTurn = {
445 turnId: TurnId.makeUnsafe("turn-1"),
434 turnId: TurnId.make("turn-1"),
446435 state: "completed" as const,
447436 requestedAt: "2026-03-29T00:00:00.000Z",
448437 startedAt: "2026-03-29T00:00:01.000Z",
......@@ -460,7 +449,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => {
460449
461450 it("does not clear local dispatch before server state changes", () => {
462451 const localDispatch = createLocalDispatchSnapshot({
463 id: ThreadId.makeUnsafe("thread-1"),
452 id: ThreadId.make("thread-1"),
464453 environmentId: localEnvironmentId,
465454 codexThreadId: null,
466455 projectId,
......@@ -497,7 +486,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => {
497486
498487 it("clears local dispatch when a new turn is already settled", () => {
499488 const localDispatch = createLocalDispatchSnapshot({
500 id: ThreadId.makeUnsafe("thread-1"),
489 id: ThreadId.make("thread-1"),
501490 environmentId: localEnvironmentId,
502491 codexThreadId: null,
503492 projectId,
......@@ -525,7 +514,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => {
525514 phase: "ready",
526515 latestTurn: {
527516 ...previousLatestTurn,
528 turnId: TurnId.makeUnsafe("turn-2"),
517 turnId: TurnId.make("turn-2"),
529518 requestedAt: "2026-03-29T00:01:00.000Z",
530519 startedAt: "2026-03-29T00:01:01.000Z",
531520 completedAt: "2026-03-29T00:01:30.000Z",
......@@ -543,7 +532,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => {
543532
544533 it("clears local dispatch when the session changes without an observed running phase", () => {
545534 const localDispatch = createLocalDispatchSnapshot({
546 id: ThreadId.makeUnsafe("thread-1"),
535 id: ThreadId.make("thread-1"),
547536 environmentId: localEnvironmentId,
548537 codexThreadId: null,
549538 projectId,
apps/web/src/components/GitActionsControl.browser.tsx+1-1
......@@ -4,7 +4,7 @@ import { useState } from "react";
44import { afterEach, describe, expect, it, vi } from "vitest";
55import { render } from "vitest-browser-react";
66
7const SHARED_THREAD_ID = ThreadId.makeUnsafe("thread-shared");
7const SHARED_THREAD_ID = ThreadId.make("thread-shared");
88const ENVIRONMENT_A = "environment-local" as never;
99const ENVIRONMENT_B = "environment-remote" as never;
1010const GIT_CWD = "/repo/project";
apps/web/src/components/KeybindingsToast.browser.tsx+1-1
......@@ -37,7 +37,7 @@ vi.mock("../lib/gitStatusState", () => ({
3737
3838const THREAD_ID = "thread-kb-toast-test" as ThreadId;
3939const PROJECT_ID = "project-1" as ProjectId;
40const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local");
40const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local");
4141const NOW_ISO = "2026-03-04T12:00:00.000Z";
4242
4343interface TestFixture {
apps/web/src/components/Sidebar.logic.test.ts+109-117
......@@ -28,7 +28,7 @@ import {
2828 type Thread,
2929} from "../types";
3030
31const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local");
31const localEnvironmentId = EnvironmentId.make("environment-local");
3232
3333function makeLatestTurn(overrides?: {
3434 completedAt?: string | null;
......@@ -235,42 +235,42 @@ describe("orderItemsByPreferredIds", () => {
235235 it("keeps preferred ids first, skips stale ids, and preserves the relative order of remaining items", () => {
236236 const ordered = orderItemsByPreferredIds({
237237 items: [
238 { id: ProjectId.makeUnsafe("project-1"), name: "One" },
239 { id: ProjectId.makeUnsafe("project-2"), name: "Two" },
240 { id: ProjectId.makeUnsafe("project-3"), name: "Three" },
238 { id: ProjectId.make("project-1"), name: "One" },
239 { id: ProjectId.make("project-2"), name: "Two" },
240 { id: ProjectId.make("project-3"), name: "Three" },
241241 ],
242242 preferredIds: [
243 ProjectId.makeUnsafe("project-3"),
244 ProjectId.makeUnsafe("project-missing"),
245 ProjectId.makeUnsafe("project-1"),
243 ProjectId.make("project-3"),
244 ProjectId.make("project-missing"),
245 ProjectId.make("project-1"),
246246 ],
247247 getId: (project) => project.id,
248248 });
249249
250250 expect(ordered.map((project) => project.id)).toEqual([
251 ProjectId.makeUnsafe("project-3"),
252 ProjectId.makeUnsafe("project-1"),
253 ProjectId.makeUnsafe("project-2"),
251 ProjectId.make("project-3"),
252 ProjectId.make("project-1"),
253 ProjectId.make("project-2"),
254254 ]);
255255 });
256256
257257 it("does not duplicate items when preferred ids repeat", () => {
258258 const ordered = orderItemsByPreferredIds({
259259 items: [
260 { id: ProjectId.makeUnsafe("project-1"), name: "One" },
261 { id: ProjectId.makeUnsafe("project-2"), name: "Two" },
260 { id: ProjectId.make("project-1"), name: "One" },
261 { id: ProjectId.make("project-2"), name: "Two" },
262262 ],
263263 preferredIds: [
264 ProjectId.makeUnsafe("project-2"),
265 ProjectId.makeUnsafe("project-1"),
266 ProjectId.makeUnsafe("project-2"),
264 ProjectId.make("project-2"),
265 ProjectId.make("project-1"),
266 ProjectId.make("project-2"),
267267 ],
268268 getId: (project) => project.id,
269269 });
270270
271271 expect(ordered.map((project) => project.id)).toEqual([
272 ProjectId.makeUnsafe("project-2"),
273 ProjectId.makeUnsafe("project-1"),
272 ProjectId.make("project-2"),
273 ProjectId.make("project-1"),
274274 ]);
275275 });
276276});
......@@ -278,9 +278,9 @@ describe("orderItemsByPreferredIds", () => {
278278describe("resolveAdjacentThreadId", () => {
279279 it("resolves adjacent thread ids in ordered sidebar traversal", () => {
280280 const threads = [
281 ThreadId.makeUnsafe("thread-1"),
282 ThreadId.makeUnsafe("thread-2"),
283 ThreadId.makeUnsafe("thread-3"),
281 ThreadId.make("thread-1"),
282 ThreadId.make("thread-2"),
283 ThreadId.make("thread-3"),
284284 ];
285285
286286 expect(
......@@ -327,21 +327,21 @@ describe("getVisibleSidebarThreadIds", () => {
327327 getVisibleSidebarThreadIds([
328328 {
329329 renderedThreadIds: [
330 ThreadId.makeUnsafe("thread-12"),
331 ThreadId.makeUnsafe("thread-11"),
332 ThreadId.makeUnsafe("thread-10"),
330 ThreadId.make("thread-12"),
331 ThreadId.make("thread-11"),
332 ThreadId.make("thread-10"),
333333 ],
334334 },
335335 {
336 renderedThreadIds: [ThreadId.makeUnsafe("thread-8"), ThreadId.makeUnsafe("thread-6")],
336 renderedThreadIds: [ThreadId.make("thread-8"), ThreadId.make("thread-6")],
337337 },
338338 ]),
339339 ).toEqual([
340 ThreadId.makeUnsafe("thread-12"),
341 ThreadId.makeUnsafe("thread-11"),
342 ThreadId.makeUnsafe("thread-10"),
343 ThreadId.makeUnsafe("thread-8"),
344 ThreadId.makeUnsafe("thread-6"),
340 ThreadId.make("thread-12"),
341 ThreadId.make("thread-11"),
342 ThreadId.make("thread-10"),
343 ThreadId.make("thread-8"),
344 ThreadId.make("thread-6"),
345345 ]);
346346 });
347347
......@@ -350,17 +350,14 @@ describe("getVisibleSidebarThreadIds", () => {
350350 getVisibleSidebarThreadIds([
351351 {
352352 shouldShowThreadPanel: false,
353 renderedThreadIds: [
354 ThreadId.makeUnsafe("thread-hidden-2"),
355 ThreadId.makeUnsafe("thread-hidden-1"),
356 ],
353 renderedThreadIds: [ThreadId.make("thread-hidden-2"), ThreadId.make("thread-hidden-1")],
357354 },
358355 {
359356 shouldShowThreadPanel: true,
360 renderedThreadIds: [ThreadId.makeUnsafe("thread-12"), ThreadId.makeUnsafe("thread-11")],
357 renderedThreadIds: [ThreadId.make("thread-12"), ThreadId.make("thread-11")],
361358 },
362359 ]),
363 ).toEqual([ThreadId.makeUnsafe("thread-12"), ThreadId.makeUnsafe("thread-11")]);
360 ).toEqual([ThreadId.make("thread-12"), ThreadId.make("thread-11")]);
364361 });
365362});
366363
......@@ -574,43 +571,41 @@ describe("getVisibleThreadsForProject", () => {
574571 it("includes the active thread even when it falls below the folded preview", () => {
575572 const threads = Array.from({ length: 8 }, (_, index) =>
576573 makeThread({
577 id: ThreadId.makeUnsafe(`thread-${index + 1}`),
574 id: ThreadId.make(`thread-${index + 1}`),
578575 title: `Thread ${index + 1}`,
579576 }),
580577 );
581578
582579 const result = getVisibleThreadsForProject({
583580 threads,
584 activeThreadId: ThreadId.makeUnsafe("thread-8"),
581 activeThreadId: ThreadId.make("thread-8"),
585582 isThreadListExpanded: false,
586583 previewLimit: 6,
587584 });
588585
589586 expect(result.hasHiddenThreads).toBe(true);
590587 expect(result.visibleThreads.map((thread) => thread.id)).toEqual([
591 ThreadId.makeUnsafe("thread-1"),
592 ThreadId.makeUnsafe("thread-2"),
593 ThreadId.makeUnsafe("thread-3"),
594 ThreadId.makeUnsafe("thread-4"),
595 ThreadId.makeUnsafe("thread-5"),
596 ThreadId.makeUnsafe("thread-6"),
597 ThreadId.makeUnsafe("thread-8"),
598 ]);
599 expect(result.hiddenThreads.map((thread) => thread.id)).toEqual([
600 ThreadId.makeUnsafe("thread-7"),
588 ThreadId.make("thread-1"),
589 ThreadId.make("thread-2"),
590 ThreadId.make("thread-3"),
591 ThreadId.make("thread-4"),
592 ThreadId.make("thread-5"),
593 ThreadId.make("thread-6"),
594 ThreadId.make("thread-8"),
601595 ]);
596 expect(result.hiddenThreads.map((thread) => thread.id)).toEqual([ThreadId.make("thread-7")]);
602597 });
603598
604599 it("returns all threads when the list is expanded", () => {
605600 const threads = Array.from({ length: 8 }, (_, index) =>
606601 makeThread({
607 id: ThreadId.makeUnsafe(`thread-${index + 1}`),
602 id: ThreadId.make(`thread-${index + 1}`),
608603 }),
609604 );
610605
611606 const result = getVisibleThreadsForProject({
612607 threads,
613 activeThreadId: ThreadId.makeUnsafe("thread-8"),
608 activeThreadId: ThreadId.make("thread-8"),
614609 isThreadListExpanded: true,
615610 previewLimit: 6,
616611 });
......@@ -626,7 +621,7 @@ describe("getVisibleThreadsForProject", () => {
626621function makeProject(overrides: Partial<Project> = {}): Project {
627622 const { defaultModelSelection, ...rest } = overrides;
628623 return {
629 id: ProjectId.makeUnsafe("project-1"),
624 id: ProjectId.make("project-1"),
630625 environmentId: localEnvironmentId,
631626 name: "Project",
632627 cwd: "/tmp/project",
......@@ -644,10 +639,10 @@ function makeProject(overrides: Partial<Project> = {}): Project {
644639
645640function makeThread(overrides: Partial<Thread> = {}): Thread {
646641 return {
647 id: ThreadId.makeUnsafe("thread-1"),
642 id: ThreadId.make("thread-1"),
648643 environmentId: localEnvironmentId,
649644 codexThreadId: null,
650 projectId: ProjectId.makeUnsafe("project-1"),
645 projectId: ProjectId.make("project-1"),
651646 title: "Thread",
652647 modelSelection: {
653648 provider: "codex",
......@@ -677,7 +672,7 @@ describe("sortThreadsForSidebar", () => {
677672 const sorted = sortThreadsForSidebar(
678673 [
679674 makeThread({
680 id: ThreadId.makeUnsafe("thread-1"),
675 id: ThreadId.make("thread-1"),
681676 createdAt: "2026-03-09T10:00:00.000Z",
682677 updatedAt: "2026-03-09T10:10:00.000Z",
683678 messages: [
......@@ -692,7 +687,7 @@ describe("sortThreadsForSidebar", () => {
692687 ],
693688 }),
694689 makeThread({
695 id: ThreadId.makeUnsafe("thread-2"),
690 id: ThreadId.make("thread-2"),
696691 createdAt: "2026-03-09T10:05:00.000Z",
697692 updatedAt: "2026-03-09T10:05:00.000Z",
698693 messages: [
......@@ -711,8 +706,8 @@ describe("sortThreadsForSidebar", () => {
711706 );
712707
713708 expect(sorted.map((thread) => thread.id)).toEqual([
714 ThreadId.makeUnsafe("thread-2"),
715 ThreadId.makeUnsafe("thread-1"),
709 ThreadId.make("thread-2"),
710 ThreadId.make("thread-1"),
716711 ]);
717712 });
718713
......@@ -720,7 +715,7 @@ describe("sortThreadsForSidebar", () => {
720715 const sorted = sortThreadsForSidebar(
721716 [
722717 makeThread({
723 id: ThreadId.makeUnsafe("thread-1"),
718 id: ThreadId.make("thread-1"),
724719 createdAt: "2026-03-09T10:00:00.000Z",
725720 updatedAt: "2026-03-09T10:01:00.000Z",
726721 messages: [
......@@ -735,7 +730,7 @@ describe("sortThreadsForSidebar", () => {
735730 ],
736731 }),
737732 makeThread({
738 id: ThreadId.makeUnsafe("thread-2"),
733 id: ThreadId.make("thread-2"),
739734 createdAt: "2026-03-09T10:05:00.000Z",
740735 updatedAt: "2026-03-09T10:05:00.000Z",
741736 messages: [],
......@@ -745,8 +740,8 @@ describe("sortThreadsForSidebar", () => {
745740 );
746741
747742 expect(sorted.map((thread) => thread.id)).toEqual([
748 ThreadId.makeUnsafe("thread-2"),
749 ThreadId.makeUnsafe("thread-1"),
743 ThreadId.make("thread-2"),
744 ThreadId.make("thread-1"),
750745 ]);
751746 });
752747
......@@ -754,13 +749,13 @@ describe("sortThreadsForSidebar", () => {
754749 const sorted = sortThreadsForSidebar(
755750 [
756751 makeThread({
757 id: ThreadId.makeUnsafe("thread-1"),
752 id: ThreadId.make("thread-1"),
758753 createdAt: "" as never,
759754 updatedAt: undefined,
760755 messages: [],
761756 }),
762757 makeThread({
763 id: ThreadId.makeUnsafe("thread-2"),
758 id: ThreadId.make("thread-2"),
764759 createdAt: "" as never,
765760 updatedAt: undefined,
766761 messages: [],
......@@ -770,8 +765,8 @@ describe("sortThreadsForSidebar", () => {
770765 );
771766
772767 expect(sorted.map((thread) => thread.id)).toEqual([
773 ThreadId.makeUnsafe("thread-2"),
774 ThreadId.makeUnsafe("thread-1"),
768 ThreadId.make("thread-2"),
769 ThreadId.make("thread-1"),
775770 ]);
776771 });
777772
......@@ -779,12 +774,12 @@ describe("sortThreadsForSidebar", () => {
779774 const sorted = sortThreadsForSidebar(
780775 [
781776 makeThread({
782 id: ThreadId.makeUnsafe("thread-1"),
777 id: ThreadId.make("thread-1"),
783778 createdAt: "2026-03-09T10:05:00.000Z",
784779 updatedAt: "2026-03-09T10:05:00.000Z",
785780 }),
786781 makeThread({
787 id: ThreadId.makeUnsafe("thread-2"),
782 id: ThreadId.make("thread-2"),
788783 createdAt: "2026-03-09T10:00:00.000Z",
789784 updatedAt: "2026-03-09T10:10:00.000Z",
790785 }),
......@@ -793,8 +788,8 @@ describe("sortThreadsForSidebar", () => {
793788 );
794789
795790 expect(sorted.map((thread) => thread.id)).toEqual([
796 ThreadId.makeUnsafe("thread-1"),
797 ThreadId.makeUnsafe("thread-2"),
791 ThreadId.make("thread-1"),
792 ThreadId.make("thread-2"),
798793 ]);
799794 });
800795});
......@@ -804,80 +799,77 @@ describe("getFallbackThreadIdAfterDelete", () => {
804799 const fallbackThreadId = getFallbackThreadIdAfterDelete({
805800 threads: [
806801 makeThread({
807 id: ThreadId.makeUnsafe("thread-oldest"),
808 projectId: ProjectId.makeUnsafe("project-1"),
802 id: ThreadId.make("thread-oldest"),
803 projectId: ProjectId.make("project-1"),
809804 createdAt: "2026-03-09T10:00:00.000Z",
810805 messages: [],
811806 }),
812807 makeThread({
813 id: ThreadId.makeUnsafe("thread-active"),
814 projectId: ProjectId.makeUnsafe("project-1"),
808 id: ThreadId.make("thread-active"),
809 projectId: ProjectId.make("project-1"),
815810 createdAt: "2026-03-09T10:05:00.000Z",
816811 messages: [],
817812 }),
818813 makeThread({
819 id: ThreadId.makeUnsafe("thread-newest"),
820 projectId: ProjectId.makeUnsafe("project-1"),
814 id: ThreadId.make("thread-newest"),
815 projectId: ProjectId.make("project-1"),
821816 createdAt: "2026-03-09T10:10:00.000Z",
822817 messages: [],
823818 }),
824819 makeThread({
825 id: ThreadId.makeUnsafe("thread-other-project"),
826 projectId: ProjectId.makeUnsafe("project-2"),
820 id: ThreadId.make("thread-other-project"),
821 projectId: ProjectId.make("project-2"),
827822 createdAt: "2026-03-09T10:20:00.000Z",
828823 messages: [],
829824 }),
830825 ],
831 deletedThreadId: ThreadId.makeUnsafe("thread-active"),
826 deletedThreadId: ThreadId.make("thread-active"),
832827 sortOrder: "created_at",
833828 });
834829
835 expect(fallbackThreadId).toBe(ThreadId.makeUnsafe("thread-newest"));
830 expect(fallbackThreadId).toBe(ThreadId.make("thread-newest"));
836831 });
837832
838833 it("skips other threads being deleted in the same action", () => {
839834 const fallbackThreadId = getFallbackThreadIdAfterDelete({
840835 threads: [
841836 makeThread({
842 id: ThreadId.makeUnsafe("thread-active"),
843 projectId: ProjectId.makeUnsafe("project-1"),
837 id: ThreadId.make("thread-active"),
838 projectId: ProjectId.make("project-1"),
844839 createdAt: "2026-03-09T10:05:00.000Z",
845840 messages: [],
846841 }),
847842 makeThread({
848 id: ThreadId.makeUnsafe("thread-newest"),
849 projectId: ProjectId.makeUnsafe("project-1"),
843 id: ThreadId.make("thread-newest"),
844 projectId: ProjectId.make("project-1"),
850845 createdAt: "2026-03-09T10:10:00.000Z",
851846 messages: [],
852847 }),
853848 makeThread({
854 id: ThreadId.makeUnsafe("thread-next"),
855 projectId: ProjectId.makeUnsafe("project-1"),
849 id: ThreadId.make("thread-next"),
850 projectId: ProjectId.make("project-1"),
856851 createdAt: "2026-03-09T10:07:00.000Z",
857852 messages: [],
858853 }),
859854 ],
860 deletedThreadId: ThreadId.makeUnsafe("thread-active"),
861 deletedThreadIds: new Set([
862 ThreadId.makeUnsafe("thread-active"),
863 ThreadId.makeUnsafe("thread-newest"),
864 ]),
855 deletedThreadId: ThreadId.make("thread-active"),
856 deletedThreadIds: new Set([ThreadId.make("thread-active"), ThreadId.make("thread-newest")]),
865857 sortOrder: "created_at",
866858 });
867859
868 expect(fallbackThreadId).toBe(ThreadId.makeUnsafe("thread-next"));
860 expect(fallbackThreadId).toBe(ThreadId.make("thread-next"));
869861 });
870862});
871863
872864describe("sortProjectsForSidebar", () => {
873865 it("sorts projects by the most recent user message across their threads", () => {
874866 const projects = [
875 makeProject({ id: ProjectId.makeUnsafe("project-1"), name: "Older project" }),
876 makeProject({ id: ProjectId.makeUnsafe("project-2"), name: "Newer project" }),
867 makeProject({ id: ProjectId.make("project-1"), name: "Older project" }),
868 makeProject({ id: ProjectId.make("project-2"), name: "Newer project" }),
877869 ];
878870 const threads = [
879871 makeThread({
880 projectId: ProjectId.makeUnsafe("project-1"),
872 projectId: ProjectId.make("project-1"),
881873 updatedAt: "2026-03-09T10:20:00.000Z",
882874 messages: [
883875 {
......@@ -891,8 +883,8 @@ describe("sortProjectsForSidebar", () => {
891883 ],
892884 }),
893885 makeThread({
894 id: ThreadId.makeUnsafe("thread-2"),
895 projectId: ProjectId.makeUnsafe("project-2"),
886 id: ThreadId.make("thread-2"),
887 projectId: ProjectId.make("project-2"),
896888 updatedAt: "2026-03-09T10:05:00.000Z",
897889 messages: [
898890 {
......@@ -910,8 +902,8 @@ describe("sortProjectsForSidebar", () => {
910902 const sorted = sortProjectsForSidebar(projects, threads, "updated_at");
911903
912904 expect(sorted.map((project) => project.id)).toEqual([
913 ProjectId.makeUnsafe("project-2"),
914 ProjectId.makeUnsafe("project-1"),
905 ProjectId.make("project-2"),
906 ProjectId.make("project-1"),
915907 ]);
916908 });
917909
......@@ -919,12 +911,12 @@ describe("sortProjectsForSidebar", () => {
919911 const sorted = sortProjectsForSidebar(
920912 [
921913 makeProject({
922 id: ProjectId.makeUnsafe("project-1"),
914 id: ProjectId.make("project-1"),
923915 name: "Older project",
924916 updatedAt: "2026-03-09T10:01:00.000Z",
925917 }),
926918 makeProject({
927 id: ProjectId.makeUnsafe("project-2"),
919 id: ProjectId.make("project-2"),
928920 name: "Newer project",
929921 updatedAt: "2026-03-09T10:05:00.000Z",
930922 }),
......@@ -934,8 +926,8 @@ describe("sortProjectsForSidebar", () => {
934926 );
935927
936928 expect(sorted.map((project) => project.id)).toEqual([
937 ProjectId.makeUnsafe("project-2"),
938 ProjectId.makeUnsafe("project-1"),
929 ProjectId.make("project-2"),
930 ProjectId.make("project-1"),
939931 ]);
940932 });
941933
......@@ -943,13 +935,13 @@ describe("sortProjectsForSidebar", () => {
943935 const sorted = sortProjectsForSidebar(
944936 [
945937 makeProject({
946 id: ProjectId.makeUnsafe("project-2"),
938 id: ProjectId.make("project-2"),
947939 name: "Beta",
948940 createdAt: undefined,
949941 updatedAt: undefined,
950942 }),
951943 makeProject({
952 id: ProjectId.makeUnsafe("project-1"),
944 id: ProjectId.make("project-1"),
953945 name: "Alpha",
954946 createdAt: undefined,
955947 updatedAt: undefined,
......@@ -960,22 +952,22 @@ describe("sortProjectsForSidebar", () => {
960952 );
961953
962954 expect(sorted.map((project) => project.id)).toEqual([
963 ProjectId.makeUnsafe("project-1"),
964 ProjectId.makeUnsafe("project-2"),
955 ProjectId.make("project-1"),
956 ProjectId.make("project-2"),
965957 ]);
966958 });
967959
968960 it("preserves manual project ordering", () => {
969961 const projects = [
970 makeProject({ id: ProjectId.makeUnsafe("project-2"), name: "Second" }),
971 makeProject({ id: ProjectId.makeUnsafe("project-1"), name: "First" }),
962 makeProject({ id: ProjectId.make("project-2"), name: "Second" }),
963 makeProject({ id: ProjectId.make("project-1"), name: "First" }),
972964 ];
973965
974966 const sorted = sortProjectsForSidebar(projects, [], "manual");
975967
976968 expect(sorted.map((project) => project.id)).toEqual([
977 ProjectId.makeUnsafe("project-2"),
978 ProjectId.makeUnsafe("project-1"),
969 ProjectId.make("project-2"),
970 ProjectId.make("project-1"),
979971 ]);
980972 });
981973
......@@ -983,26 +975,26 @@ describe("sortProjectsForSidebar", () => {
983975 const sorted = sortProjectsForSidebar(
984976 [
985977 makeProject({
986 id: ProjectId.makeUnsafe("project-1"),
978 id: ProjectId.make("project-1"),
987979 name: "Visible project",
988980 updatedAt: "2026-03-09T10:01:00.000Z",
989981 }),
990982 makeProject({
991 id: ProjectId.makeUnsafe("project-2"),
983 id: ProjectId.make("project-2"),
992984 name: "Archived-only project",
993985 updatedAt: "2026-03-09T10:00:00.000Z",
994986 }),
995987 ],
996988 [
997989 makeThread({
998 id: ThreadId.makeUnsafe("thread-visible"),
999 projectId: ProjectId.makeUnsafe("project-1"),
990 id: ThreadId.make("thread-visible"),
991 projectId: ProjectId.make("project-1"),
1000992 updatedAt: "2026-03-09T10:02:00.000Z",
1001993 archivedAt: null,
1002994 }),
1003995 makeThread({
1004 id: ThreadId.makeUnsafe("thread-archived"),
1005 projectId: ProjectId.makeUnsafe("project-2"),
996 id: ThreadId.make("thread-archived"),
997 projectId: ProjectId.make("project-2"),
1006998 updatedAt: "2026-03-09T10:10:00.000Z",
1007999 archivedAt: "2026-03-09T10:11:00.000Z",
10081000 }),
......@@ -1011,8 +1003,8 @@ describe("sortProjectsForSidebar", () => {
10111003 );
10121004
10131005 expect(sorted.map((project) => project.id)).toEqual([
1014 ProjectId.makeUnsafe("project-1"),
1015 ProjectId.makeUnsafe("project-2"),
1006 ProjectId.make("project-1"),
1007 ProjectId.make("project-2"),
10161008 ]);
10171009 });
10181010
apps/web/src/components/ThreadTerminalDrawer.browser.tsx+1-1
......@@ -121,7 +121,7 @@ vi.mock("~/localApi", () => ({
121121
122122import { TerminalViewport } from "./ThreadTerminalDrawer";
123123
124const THREAD_ID = ThreadId.makeUnsafe("thread-terminal-browser");
124const THREAD_ID = ThreadId.make("thread-terminal-browser");
125125
126126function createEnvironmentApi() {
127127 return {
apps/web/src/components/chat/ChangedFilesTree.test.tsx+2-2
......@@ -39,7 +39,7 @@ describe("ChangedFilesTree", () => {
3939 ({ files, visibleLabels, hiddenLabels }) => {
4040 const markup = renderToStaticMarkup(
4141 <ChangedFilesTree
42 turnId={TurnId.makeUnsafe("turn-1")}
42 turnId={TurnId.make("turn-1")}
4343 files={files}
4444 allDirectoriesExpanded={false}
4545 resolvedTheme="light"
......@@ -100,7 +100,7 @@ describe("ChangedFilesTree", () => {
100100 ({ files, visibleLabels }) => {
101101 const markup = renderToStaticMarkup(
102102 <ChangedFilesTree
103 turnId={TurnId.makeUnsafe("turn-1")}
103 turnId={TurnId.make("turn-1")}
104104 files={files}
105105 allDirectoriesExpanded
106106 resolvedTheme="light"
apps/web/src/components/chat/CompactComposerControlsMenu.browser.tsx+2-2
......@@ -15,10 +15,10 @@ import { CompactComposerControlsMenu } from "./CompactComposerControlsMenu";
1515import { TraitsMenuContent } from "./TraitsPicker";
1616import { useComposerDraftStore } from "../../composerDraftStore";
1717
18const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local");
18const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local");
1919
2020async function mountMenu(props?: { modelSelection?: ModelSelection; prompt?: string }) {
21 const threadId = ThreadId.makeUnsafe("thread-compact-menu");
21 const threadId = ThreadId.make("thread-compact-menu");
2222 const threadRef = scopeThreadRef(LOCAL_ENVIRONMENT_ID, threadId);
2323 const threadKey = scopedThreadKey(threadRef);
2424 const provider = props?.modelSelection?.provider ?? "claudeAgent";
apps/web/src/components/chat/ComposerPendingTerminalContexts.test.tsx+1-1
......@@ -10,7 +10,7 @@ describe("ComposerPendingTerminalContextChip", () => {
1010 <ComposerPendingTerminalContextChip
1111 context={{
1212 id: "ctx-expired",
13 threadId: ThreadId.makeUnsafe("thread-1"),
13 threadId: ThreadId.make("thread-1"),
1414 terminalId: "default",
1515 terminalLabel: "Terminal 1",
1616 lineStart: 2,
apps/web/src/components/chat/MessagesTimeline.test.tsx+1-1
......@@ -60,7 +60,7 @@ describe("MessagesTimeline", () => {
6060 kind: "message",
6161 createdAt: "2026-03-17T19:12:28.000Z",
6262 message: {
63 id: MessageId.makeUnsafe("message-2"),
63 id: MessageId.make("message-2"),
6464 role: "user",
6565 text: [
6666 "yoo what's @terminal-1:1-5 mean",
apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx+1-1
......@@ -101,7 +101,7 @@ function createMessage(input: {
101101 attachments?: ChatMessage["attachments"];
102102}): ChatMessage {
103103 return {
104 id: MessageId.makeUnsafe(input.id),
104 id: MessageId.make(input.id),
105105 role: input.role,
106106 text: input.text,
107107 ...(input.attachments ? { attachments: input.attachments } : {}),
apps/web/src/components/chat/TraitsPicker.browser.tsx+3-3
......@@ -28,11 +28,11 @@ import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
2828
2929// ── Claude TraitsPicker tests ─────────────────────────────────────────
3030
31const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local");
32const CLAUDE_THREAD_ID = ThreadId.makeUnsafe("thread-claude-traits");
31const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local");
32const CLAUDE_THREAD_ID = ThreadId.make("thread-claude-traits");
3333const CLAUDE_THREAD_REF = scopeThreadRef(LOCAL_ENVIRONMENT_ID, CLAUDE_THREAD_ID);
3434const CLAUDE_THREAD_KEY = scopedThreadKey(CLAUDE_THREAD_REF);
35const CODEX_THREAD_ID = ThreadId.makeUnsafe("thread-codex-traits");
35const CODEX_THREAD_ID = ThreadId.make("thread-codex-traits");
3636const CODEX_THREAD_REF = scopeThreadRef(LOCAL_ENVIRONMENT_ID, CODEX_THREAD_ID);
3737const CODEX_THREAD_KEY = scopedThreadKey(CODEX_THREAD_REF);
3838const TEST_PROVIDERS: ReadonlyArray<ServerProvider> = [
apps/web/src/components/settings/SettingsPanels.browser.tsx+5-5
......@@ -92,7 +92,7 @@ const authAccessHarness = vi.hoisted(() => {
9292 revision,
9393 type: "clientRemoved",
9494 payload: {
95 sessionId: AuthSessionId.makeUnsafe(sessionId),
95 sessionId: AuthSessionId.make(sessionId),
9696 },
9797 });
9898 revision += 1;
......@@ -119,13 +119,13 @@ vi.mock("../../environments/runtime", () => {
119119 id: "environment-local",
120120 label: "Local environment",
121121 source: "manual" as const,
122 environmentId: EnvironmentId.makeUnsafe("environment-local"),
122 environmentId: EnvironmentId.make("environment-local"),
123123 target: {
124124 httpBaseUrl: "http://localhost:3000",
125125 wsBaseUrl: "ws://localhost:3000",
126126 },
127127 },
128 environmentId: EnvironmentId.makeUnsafe("environment-local"),
128 environmentId: EnvironmentId.make("environment-local"),
129129 client: {
130130 server: {
131131 subscribeAuthAccess: (listener: Parameters<typeof authAccessHarness.subscribe>[0]) =>
......@@ -171,7 +171,7 @@ vi.mock("../../environments/runtime", () => {
171171function createBaseServerConfig(): ServerConfig {
172172 return {
173173 environment: {
174 environmentId: EnvironmentId.makeUnsafe("environment-local"),
174 environmentId: EnvironmentId.make("environment-local"),
175175 label: "Local environment",
176176 platform: { os: "darwin" as const, arch: "arm64" as const },
177177 serverVersion: "0.0.0-test",
......@@ -245,7 +245,7 @@ function makeClientSession(input: {
245245 deviceType: "unknown",
246246 ...input.client,
247247 },
248 sessionId: AuthSessionId.makeUnsafe(input.sessionId),
248 sessionId: AuthSessionId.make(input.sessionId),
249249 issuedAt: makeUtc(input.issuedAt),
250250 expiresAt: makeUtc(input.expiresAt),
251251 lastConnectedAt:
apps/web/src/composerDraftStore.test.ts+22-22
......@@ -70,7 +70,7 @@ function makeTerminalContext(input: {
7070}): TerminalContextDraft {
7171 return {
7272 id: input.id,
73 threadId: ThreadId.makeUnsafe("thread-dedupe"),
73 threadId: ThreadId.make("thread-dedupe"),
7474 terminalId: input.terminalId ?? "default",
7575 terminalLabel: input.terminalLabel ?? "Terminal 1",
7676 lineStart: input.lineStart ?? 4,
......@@ -106,9 +106,9 @@ function providerModelOptions(options: ProviderModelOptions): ProviderModelOptio
106106 return options;
107107}
108108
109const TEST_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local");
110const OTHER_TEST_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-remote");
111const LEGACY_TEST_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("__legacy__");
109const TEST_ENVIRONMENT_ID = EnvironmentId.make("environment-local");
110const OTHER_TEST_ENVIRONMENT_ID = EnvironmentId.make("environment-remote");
111const LEGACY_TEST_ENVIRONMENT_ID = EnvironmentId.make("__legacy__");
112112
113113function threadKeyFor(
114114 threadId: ThreadId,
......@@ -130,7 +130,7 @@ function draftByKey(key: string) {
130130}
131131
132132describe("composerDraftStore addImages", () => {
133 const threadId = ThreadId.makeUnsafe("thread-dedupe");
133 const threadId = ThreadId.make("thread-dedupe");
134134 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
135135 let originalRevokeObjectUrl: typeof URL.revokeObjectURL;
136136 let revokeSpy: ReturnType<typeof vi.fn<(url: string) => void>>;
......@@ -216,7 +216,7 @@ describe("composerDraftStore addImages", () => {
216216});
217217
218218describe("composerDraftStore clearComposerContent", () => {
219 const threadId = ThreadId.makeUnsafe("thread-clear");
219 const threadId = ThreadId.make("thread-clear");
220220 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
221221 let originalRevokeObjectUrl: typeof URL.revokeObjectURL;
222222 let revokeSpy: ReturnType<typeof vi.fn<(url: string) => void>>;
......@@ -248,7 +248,7 @@ describe("composerDraftStore clearComposerContent", () => {
248248});
249249
250250describe("composerDraftStore syncPersistedAttachments", () => {
251 const threadId = ThreadId.makeUnsafe("thread-sync-persisted");
251 const threadId = ThreadId.make("thread-sync-persisted");
252252 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
253253
254254 beforeEach(() => {
......@@ -304,7 +304,7 @@ describe("composerDraftStore syncPersistedAttachments", () => {
304304});
305305
306306describe("composerDraftStore terminal contexts", () => {
307 const threadId = ThreadId.makeUnsafe("thread-dedupe");
307 const threadId = ThreadId.make("thread-dedupe");
308308 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
309309
310310 beforeEach(() => {
......@@ -482,18 +482,18 @@ describe("composerDraftStore terminal contexts", () => {
482482});
483483
484484describe("composerDraftStore project draft thread mapping", () => {
485 const projectId = ProjectId.makeUnsafe("project-a");
486 const otherProjectId = ProjectId.makeUnsafe("project-b");
485 const projectId = ProjectId.make("project-a");
486 const otherProjectId = ProjectId.make("project-b");
487487 const projectRef = scopeProjectRef(TEST_ENVIRONMENT_ID, projectId);
488488 const otherProjectRef = scopeProjectRef(TEST_ENVIRONMENT_ID, otherProjectId);
489489 const remoteProjectRef = scopeProjectRef(OTHER_TEST_ENVIRONMENT_ID, projectId);
490 const threadId = ThreadId.makeUnsafe("thread-a");
491 const otherThreadId = ThreadId.makeUnsafe("thread-b");
492 const draftId = DraftId.makeUnsafe("draft-a");
493 const otherDraftId = DraftId.makeUnsafe("draft-b");
494 const sharedDraftId = DraftId.makeUnsafe("draft-shared");
495 const localDraftId = DraftId.makeUnsafe("draft-local");
496 const remoteDraftId = DraftId.makeUnsafe("draft-remote");
490 const threadId = ThreadId.make("thread-a");
491 const otherThreadId = ThreadId.make("thread-b");
492 const draftId = DraftId.make("draft-a");
493 const otherDraftId = DraftId.make("draft-b");
494 const sharedDraftId = DraftId.make("draft-shared");
495 const localDraftId = DraftId.make("draft-local");
496 const remoteDraftId = DraftId.make("draft-remote");
497497
498498 beforeEach(() => {
499499 resetComposerDraftStore();
......@@ -847,7 +847,7 @@ describe("composerDraftStore project draft thread mapping", () => {
847847});
848848
849849describe("composerDraftStore modelSelection", () => {
850 const threadId = ThreadId.makeUnsafe("thread-model-options");
850 const threadId = ThreadId.make("thread-model-options");
851851 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
852852
853853 beforeEach(() => {
......@@ -1078,7 +1078,7 @@ describe("composerDraftStore modelSelection", () => {
10781078});
10791079
10801080describe("composerDraftStore setModelSelection", () => {
1081 const threadId = ThreadId.makeUnsafe("thread-model");
1081 const threadId = ThreadId.make("thread-model");
10821082 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
10831083
10841084 beforeEach(() => {
......@@ -1133,7 +1133,7 @@ describe("composerDraftStore sticky composer settings", () => {
11331133
11341134 it("applies sticky activeProvider to new drafts", () => {
11351135 const store = useComposerDraftStore.getState();
1136 const threadId = ThreadId.makeUnsafe("thread-sticky-active-provider");
1136 const threadId = ThreadId.make("thread-sticky-active-provider");
11371137 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
11381138
11391139 store.setStickyModelSelection(modelSelection("claudeAgent", "claude-opus-4-6"));
......@@ -1149,7 +1149,7 @@ describe("composerDraftStore sticky composer settings", () => {
11491149});
11501150
11511151describe("composerDraftStore provider-scoped option updates", () => {
1152 const threadId = ThreadId.makeUnsafe("thread-provider");
1152 const threadId = ThreadId.make("thread-provider");
11531153 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
11541154
11551155 beforeEach(() => {
......@@ -1175,7 +1175,7 @@ describe("composerDraftStore provider-scoped option updates", () => {
11751175});
11761176
11771177describe("composerDraftStore runtime and interaction settings", () => {
1178 const threadId = ThreadId.makeUnsafe("thread-settings");
1178 const threadId = ThreadId.make("thread-settings");
11791179 const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId);
11801180
11811181 beforeEach(() => {
apps/web/src/composerDraftStore.ts+13-16
......@@ -926,7 +926,7 @@ function normalizeComposerTarget(
926926): ComposerThreadTarget | null {
927927 if (typeof target === "string") {
928928 const draftId = target.trim();
929 return draftId.length > 0 ? DraftId.makeUnsafe(draftId) : null;
929 return draftId.length > 0 ? DraftId.make(draftId) : null;
930930 }
931931 return target;
932932}
......@@ -1804,7 +1804,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()(
18041804 if (!draftThread || isDraftThreadPromoting(draftThread)) {
18051805 return null;
18061806 }
1807 return toProjectDraftSession(DraftId.makeUnsafe(draftId), draftThread);
1807 return toProjectDraftSession(DraftId.make(draftId), draftThread);
18081808 },
18091809 getDraftThreadByProjectRef: (projectRef) => {
18101810 return get().getDraftSessionByProjectRef(projectRef);
......@@ -1818,7 +1818,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()(
18181818 draftThread.projectId === projectRef.projectId &&
18191819 draftThread.environmentId === projectRef.environmentId
18201820 ) {
1821 return toProjectDraftSession(DraftId.makeUnsafe(draftId), draftThread);
1821 return toProjectDraftSession(DraftId.make(draftId), draftThread);
18221822 }
18231823 }
18241824 return null;
......@@ -1837,7 +1837,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()(
18371837 },
18381838 getDraftThread: (threadRef) => {
18391839 if (typeof threadRef === "string") {
1840 return get().getDraftSession(DraftId.makeUnsafe(threadRef));
1840 return get().getDraftSession(DraftId.make(threadRef));
18411841 }
18421842 return get().getDraftSessionByRef(threadRef);
18431843 },
......@@ -1863,7 +1863,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()(
18631863 state.logicalProjectDraftThreadKeyByLogicalProjectKey[normalizedLogicalProjectKey];
18641864 const nextDraftThread = createDraftThreadState(
18651865 projectRef,
1866 options?.threadId ?? existingThread?.threadId ?? ThreadId.makeUnsafe(draftId),
1866 options?.threadId ?? existingThread?.threadId ?? ThreadId.make(draftId),
18671867 normalizedLogicalProjectKey,
18681868 existingThread,
18691869 options,
......@@ -2438,10 +2438,9 @@ const composerDraftStore = create<ComposerDraftStoreState>()(
24382438 if (!threadKey || !threadId) {
24392439 return;
24402440 }
2441 get().addImages(
2442 typeof threadRef === "string" ? DraftId.makeUnsafe(threadKey) : threadRef,
2443 [image],
2444 );
2441 get().addImages(typeof threadRef === "string" ? DraftId.make(threadKey) : threadRef, [
2442 image,
2443 ]);
24452444 },
24462445 addImages: (threadRef, images) => {
24472446 const threadKey = resolveComposerDraftKey(get(), threadRef) ?? "";
......@@ -2566,7 +2565,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()(
25662565 return;
25672566 }
25682567 get().addTerminalContexts(
2569 typeof threadRef === "string" ? DraftId.makeUnsafe(threadKey) : threadRef,
2568 typeof threadRef === "string" ? DraftId.make(threadKey) : threadRef,
25702569 [context],
25712570 );
25722571 },
......@@ -2799,9 +2798,7 @@ export function useEffectiveComposerModelState(input: {
27992798 projectModelSelection: ModelSelection | null | undefined;
28002799 settings: UnifiedSettings;
28012800}): EffectiveComposerModelState {
2802 const draft = useComposerDraftModelState(
2803 input.threadRef ?? input.draftId ?? DraftId.makeUnsafe(""),
2804 );
2801 const draft = useComposerDraftModelState(input.threadRef ?? input.draftId ?? DraftId.make(""));
28052802
28062803 return useMemo(
28072804 () =>
......@@ -2836,7 +2833,7 @@ export function markPromotedDraftThread(threadId: ThreadId): void {
28362833 const draftThreadTargets: ComposerThreadTarget[] = [];
28372834 for (const [draftId, draftThread] of Object.entries(store.draftThreadsByThreadKey)) {
28382835 if (draftThread.threadId === threadId) {
2839 draftThreadTargets.push(DraftId.makeUnsafe(draftId));
2836 draftThreadTargets.push(DraftId.make(draftId));
28402837 }
28412838 }
28422839 if (draftThreadTargets.length === 0) {
......@@ -2854,7 +2851,7 @@ export function markPromotedDraftThreadByRef(threadRef: ScopedThreadRef): void {
28542851 draftThread.environmentId === threadRef.environmentId &&
28552852 draftThread.threadId === threadRef.threadId
28562853 ) {
2857 draftStore.markDraftThreadPromoting(DraftId.makeUnsafe(draftId), threadRef);
2854 draftStore.markDraftThreadPromoting(DraftId.make(draftId), threadRef);
28582855 }
28592856 }
28602857}
......@@ -2879,7 +2876,7 @@ export function finalizePromotedDraftThreadByRef(threadRef: ScopedThreadRef): vo
28792876 draftThread.promotedTo.environmentId === threadRef.environmentId &&
28802877 draftThread.promotedTo.threadId === threadRef.threadId
28812878 ) {
2882 draftStore.finalizePromotedDraftThread(DraftId.makeUnsafe(draftId));
2879 draftStore.finalizePromotedDraftThread(DraftId.make(draftId));
28832880 }
28842881 }
28852882}
apps/web/src/diffRouteSearch.ts+1-1
......@@ -28,7 +28,7 @@ export function stripDiffSearchParams<T extends Record<string, unknown>>(
2828export function parseDiffRouteSearch(search: Record<string, unknown>): DiffRouteSearch {
2929 const diff = isDiffOpenValue(search.diff) ? "1" : undefined;
3030 const diffTurnIdRaw = diff ? normalizeSearchString(search.diffTurnId) : undefined;
31 const diffTurnId = diffTurnIdRaw ? TurnId.makeUnsafe(diffTurnIdRaw) : undefined;
31 const diffTurnId = diffTurnIdRaw ? TurnId.make(diffTurnIdRaw) : undefined;
3232 const diffFilePath = diff && diffTurnId ? normalizeSearchString(search.diffFilePath) : undefined;
3333
3434 return {
apps/web/src/environmentGrouping.test.ts+13-13
......@@ -16,19 +16,19 @@ import { DEFAULT_INTERACTION_MODE } from "./types";
1616
1717// ── Fixture Identifiers ──────────────────────────────────────────────
1818
19const primaryEnvId = EnvironmentId.makeUnsafe("env-primary");
20const remoteEnvId = EnvironmentId.makeUnsafe("env-remote");
19const primaryEnvId = EnvironmentId.make("env-primary");
20const remoteEnvId = EnvironmentId.make("env-remote");
2121
22const sharedProjectPrimaryId = ProjectId.makeUnsafe("shared-proj-primary");
23const sharedProjectRemoteId = ProjectId.makeUnsafe("shared-proj-remote");
24const localOnlyProjectId = ProjectId.makeUnsafe("local-only-proj");
25const remoteOnlyProjectId = ProjectId.makeUnsafe("remote-only-proj");
22const sharedProjectPrimaryId = ProjectId.make("shared-proj-primary");
23const sharedProjectRemoteId = ProjectId.make("shared-proj-remote");
24const localOnlyProjectId = ProjectId.make("local-only-proj");
25const remoteOnlyProjectId = ProjectId.make("remote-only-proj");
2626
27const threadP1 = ThreadId.makeUnsafe("thread-shared-primary-1");
28const threadP2 = ThreadId.makeUnsafe("thread-shared-primary-2");
29const threadR1 = ThreadId.makeUnsafe("thread-shared-remote-1");
30const threadL1 = ThreadId.makeUnsafe("thread-local-only-1");
31const threadRO1 = ThreadId.makeUnsafe("thread-remote-only-1");
27const threadP1 = ThreadId.make("thread-shared-primary-1");
28const threadP2 = ThreadId.make("thread-shared-primary-2");
29const threadR1 = ThreadId.make("thread-shared-remote-1");
30const threadL1 = ThreadId.make("thread-local-only-1");
31const threadRO1 = ThreadId.make("thread-remote-only-1");
3232
3333const SHARED_REPO_CANONICAL_KEY = "github.com/example/shared-repo";
3434
......@@ -328,7 +328,7 @@ describe("environment grouping", () => {
328328
329329 it("returns empty array for nonexistent environment", () => {
330330 const state = makeFixtureState();
331 const ref = scopeProjectRef(EnvironmentId.makeUnsafe("nonexistent"), sharedProjectPrimaryId);
331 const ref = scopeProjectRef(EnvironmentId.make("nonexistent"), sharedProjectPrimaryId);
332332 expect(selectSidebarThreadsForProjectRef(state, ref)).toEqual([]);
333333 });
334334 });
......@@ -381,7 +381,7 @@ describe("environment grouping", () => {
381381 const state = makeFixtureState();
382382 const refs = [
383383 scopeProjectRef(primaryEnvId, sharedProjectPrimaryId),
384 scopeProjectRef(EnvironmentId.makeUnsafe("nonexistent"), ProjectId.makeUnsafe("nope")),
384 scopeProjectRef(EnvironmentId.make("nonexistent"), ProjectId.make("nope")),
385385 ];
386386 const threads = selectSidebarThreadsForProjectRefs(state, refs);
387387 // Only returns threads from the valid ref
apps/web/src/environments/primary/bootstrap.test.ts+1-1
......@@ -63,7 +63,7 @@ describe("environmentBootstrap", () => {
6363 desktopBridge: undefined,
6464 });
6565 writePrimaryEnvironmentDescriptor({
66 environmentId: EnvironmentId.makeUnsafe("environment-local"),
66 environmentId: EnvironmentId.make("environment-local"),
6767 label: "Bootstrapped environment",
6868 platform: {
6969 os: "darwin",
apps/web/src/environments/runtime/catalog.test.ts+4-4
......@@ -41,7 +41,7 @@ describe("environment runtime catalog stores", () => {
4141 });
4242
4343 it("resets the saved environment registry store state", () => {
44 const environmentId = EnvironmentId.makeUnsafe("environment-1");
44 const environmentId = EnvironmentId.make("environment-1");
4545
4646 useSavedEnvironmentRegistryStore.getState().upsert({
4747 environmentId,
......@@ -60,7 +60,7 @@ describe("environment runtime catalog stores", () => {
6060 });
6161
6262 it("resets the saved environment runtime store state", () => {
63 const environmentId = EnvironmentId.makeUnsafe("environment-1");
63 const environmentId = EnvironmentId.make("environment-1");
6464
6565 useSavedEnvironmentRuntimeStore.getState().patch(environmentId, {
6666 connectionState: "connected",
......@@ -82,7 +82,7 @@ describe("environment runtime catalog stores", () => {
8282
8383 expect(() =>
8484 useSavedEnvironmentRegistryStore.getState().upsert({
85 environmentId: EnvironmentId.makeUnsafe("environment-1"),
85 environmentId: EnvironmentId.make("environment-1"),
8686 label: "Remote environment",
8787 httpBaseUrl: "https://remote.example.com/",
8888 wsBaseUrl: "wss://remote.example.com/",
......@@ -121,7 +121,7 @@ describe("environment runtime catalog stores", () => {
121121
122122 const hydrationPromise = waitForSavedEnvironmentRegistryHydration();
123123
124 const environmentId = EnvironmentId.makeUnsafe("environment-1");
124 const environmentId = EnvironmentId.make("environment-1");
125125 const record = {
126126 environmentId,
127127 label: "Remote environment",
apps/web/src/environments/runtime/connection.test.ts+7-7
......@@ -30,7 +30,7 @@ function createTestClient(options?: {
3030 server: {
3131 getConfig: vi.fn(async () => ({
3232 environment: {
33 environmentId: EnvironmentId.makeUnsafe("env-1"),
33 environmentId: EnvironmentId.make("env-1"),
3434 },
3535 })),
3636 subscribeConfig: (listener: (event: any) => void) => {
......@@ -133,7 +133,7 @@ function createTestClient(options?: {
133133
134134describe("createEnvironmentConnection", () => {
135135 it("bootstraps a snapshot immediately for a new connection", async () => {
136 const environmentId = EnvironmentId.makeUnsafe("env-1");
136 const environmentId = EnvironmentId.make("env-1");
137137 const { client, getSnapshot } = createTestClient();
138138 const syncSnapshot = vi.fn();
139139
......@@ -168,7 +168,7 @@ describe("createEnvironmentConnection", () => {
168168 });
169169
170170 it("rejects welcome/config identity drift", async () => {
171 const environmentId = EnvironmentId.makeUnsafe("env-1");
171 const environmentId = EnvironmentId.make("env-1");
172172 const { client, emitWelcome } = createTestClient();
173173
174174 const connection = createEnvironmentConnection({
......@@ -189,7 +189,7 @@ describe("createEnvironmentConnection", () => {
189189 applyTerminalEvent: vi.fn(),
190190 });
191191
192 expect(() => emitWelcome(EnvironmentId.makeUnsafe("env-2"))).toThrow(
192 expect(() => emitWelcome(EnvironmentId.make("env-2"))).toThrow(
193193 "Environment connection env-1 changed identity to env-2 via server lifecycle welcome.",
194194 );
195195
......@@ -197,7 +197,7 @@ describe("createEnvironmentConnection", () => {
197197 });
198198
199199 it("rejects ensureBootstrapped when snapshot recovery fails", async () => {
200 const environmentId = EnvironmentId.makeUnsafe("env-1");
200 const environmentId = EnvironmentId.make("env-1");
201201 const snapshotError = new Error("snapshot failed");
202202 const { client } = createTestClient({
203203 getSnapshot: async () => {
......@@ -229,7 +229,7 @@ describe("createEnvironmentConnection", () => {
229229 });
230230
231231 it("retries replay recovery after transport disconnects during resubscribe", async () => {
232 const environmentId = EnvironmentId.makeUnsafe("env-1");
232 const environmentId = EnvironmentId.make("env-1");
233233 let replayAttempts = 0;
234234 const applyEventBatch = vi.fn();
235235 const { client, replayEvents, triggerDomainResubscribe } = createTestClient({
......@@ -287,7 +287,7 @@ describe("createEnvironmentConnection", () => {
287287 await connection.dispose();
288288 });
289289 it("swallows replay recovery failures triggered by resubscribe", async () => {
290 const environmentId = EnvironmentId.makeUnsafe("env-1");
290 const environmentId = EnvironmentId.make("env-1");
291291 const snapshotError = new Error("snapshot failed");
292292 let snapshotCalls = 0;
293293 const { client, triggerDomainResubscribe } = createTestClient({
apps/web/src/environments/runtime/service.addSavedEnvironment.test.ts+2-2
......@@ -68,7 +68,7 @@ describe("addSavedEnvironment", () => {
6868 credential: "pairing-code",
6969 });
7070 mockFetchRemoteEnvironmentDescriptor.mockResolvedValue({
71 environmentId: EnvironmentId.makeUnsafe("environment-1"),
71 environmentId: EnvironmentId.make("environment-1"),
7272 label: "Remote environment",
7373 });
7474 mockBootstrapRemoteBearerSession.mockResolvedValue({
......@@ -94,7 +94,7 @@ describe("addSavedEnvironment", () => {
9494
9595 expect(mockPersistSavedEnvironmentRecord).toHaveBeenCalledTimes(1);
9696 expect(mockWriteSavedEnvironmentBearerToken).toHaveBeenCalledWith(
97 EnvironmentId.makeUnsafe("environment-1"),
97 EnvironmentId.make("environment-1"),
9898 "bearer-token",
9999 );
100100 expect(mockSetSavedEnvironmentRegistry).toHaveBeenCalledWith([]);
apps/web/src/environments/runtime/service.ts+1-1
......@@ -281,7 +281,7 @@ function createEnvironmentConnectionHandlers() {
281281 reconcileSnapshotDerivedState();
282282 },
283283 applyTerminalEvent: (event: TerminalEvent, environmentId: EnvironmentId) => {
284 const threadRef = scopeThreadRef(environmentId, ThreadId.makeUnsafe(event.threadId));
284 const threadRef = scopeThreadRef(environmentId, ThreadId.make(event.threadId));
285285 const serverThread = selectThreadByRef(useStore.getState(), threadRef);
286286 const hasDraftThread =
287287 useComposerDraftStore.getState().getDraftThreadByRef(threadRef) !== null;
apps/web/src/historyBootstrap.test.ts+1-1
......@@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest";
33
44import { buildBootstrapInput } from "./historyBootstrap";
55
6const messageId = (value: string) => MessageId.makeUnsafe(value);
6const messageId = (value: string) => MessageId.make(value);
77
88describe("buildBootstrapInput", () => {
99 it("includes full transcript when under budget", () => {
apps/web/src/lib/contextWindow.test.ts+2-2
......@@ -5,12 +5,12 @@ import { deriveLatestContextWindowSnapshot, formatContextWindowTokens } from "./
55
66function makeActivity(id: string, kind: string, payload: unknown): OrchestrationThreadActivity {
77 return {
8 id: EventId.makeUnsafe(id),
8 id: EventId.make(id),
99 tone: "info",
1010 kind,
1111 summary: kind,
1212 payload,
13 turnId: TurnId.makeUnsafe("turn-1"),
13 turnId: TurnId.make("turn-1"),
1414 createdAt: "2026-03-23T00:00:00.000Z",
1515 };
1616}
apps/web/src/lib/gitReactQuery.test.ts+2-2
......@@ -34,8 +34,8 @@ const BRANCH_SEARCH_RESULT: InfiniteData<GitListBranchesResult, number> = {
3434 pages: [BRANCH_QUERY_RESULT],
3535 pageParams: [0],
3636};
37const ENVIRONMENT_A = EnvironmentId.makeUnsafe("environment-a");
38const ENVIRONMENT_B = EnvironmentId.makeUnsafe("environment-b");
37const ENVIRONMENT_A = EnvironmentId.make("environment-a");
38const ENVIRONMENT_B = EnvironmentId.make("environment-b");
3939
4040describe("gitMutationKeys", () => {
4141 it("scopes stacked action keys by cwd", () => {
apps/web/src/lib/gitStatusState.test.ts+2-2
......@@ -34,8 +34,8 @@ function registerListener<T>(listeners: Set<(event: T) => void>, listener: (even
3434}
3535
3636const gitStatusListeners = new Set<(event: GitStatusResult) => void>();
37const ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local");
38const OTHER_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-remote");
37const ENVIRONMENT_ID = EnvironmentId.make("environment-local");
38const OTHER_ENVIRONMENT_ID = EnvironmentId.make("environment-remote");
3939const TARGET = { environmentId: ENVIRONMENT_ID, cwd: "/repo" } as const;
4040const FRESH_TARGET = { environmentId: ENVIRONMENT_ID, cwd: "/fresh" } as const;
4141
apps/web/src/lib/providerReactQuery.test.ts+2-2
......@@ -4,8 +4,8 @@ import { afterEach, describe, expect, it, vi } from "vitest";
44import { checkpointDiffQueryOptions, providerQueryKeys } from "./providerReactQuery";
55import * as environmentApi from "../environmentApi";
66
7const threadId = ThreadId.makeUnsafe("thread-id");
8const environmentId = EnvironmentId.makeUnsafe("environment-local");
7const threadId = ThreadId.make("thread-id");
8const environmentId = EnvironmentId.make("environment-local");
99
1010function mockNativeApi(input: {
1111 getTurnDiff: ReturnType<typeof vi.fn>;
apps/web/src/lib/terminalContext.test.ts+1-1
......@@ -25,7 +25,7 @@ import {
2525function makeContext(overrides?: Partial<TerminalContextDraft>): TerminalContextDraft {
2626 return {
2727 id: "context-1",
28 threadId: ThreadId.makeUnsafe("thread-1"),
28 threadId: ThreadId.make("thread-1"),
2929 terminalId: "default",
3030 terminalLabel: "Terminal 1",
3131 lineStart: 12,
apps/web/src/lib/terminalStateCleanup.test.ts+1-1
......@@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest";
44
55import { collectActiveTerminalThreadIds } from "./terminalStateCleanup";
66
7const threadId = (id: string): ThreadId => ThreadId.makeUnsafe(id);
7const threadId = (id: string): ThreadId => ThreadId.make(id);
88const threadKey = (environmentId: string, id: string): string =>
99 scopedThreadKey(scopeThreadRef(environmentId as never, threadId(id)));
1010
apps/web/src/lib/utils.ts+5-5
......@@ -28,12 +28,12 @@ export function randomUUID(): string {
2828 return Effect.runSync(Random.nextUUIDv4);
2929}
3030
31export const newCommandId = (): CommandId => CommandId.makeUnsafe(randomUUID());
31export const newCommandId = (): CommandId => CommandId.make(randomUUID());
3232
33export const newProjectId = (): ProjectId => ProjectId.makeUnsafe(randomUUID());
33export const newProjectId = (): ProjectId => ProjectId.make(randomUUID());
3434
35export const newThreadId = (): ThreadId => ThreadId.makeUnsafe(randomUUID());
35export const newThreadId = (): ThreadId => ThreadId.make(randomUUID());
3636
37export const newDraftId = (): DraftId => DraftId.makeUnsafe(randomUUID());
37export const newDraftId = (): DraftId => DraftId.make(randomUUID());
3838
39export const newMessageId = (): MessageId => MessageId.makeUnsafe(randomUUID());
39export const newMessageId = (): MessageId => MessageId.make(randomUUID());
apps/web/src/localApi.test.ts+18-22
......@@ -104,10 +104,10 @@ vi.mock("./environments/runtime", () => ({
104104 httpBaseUrl: "http://localhost:3000",
105105 wsBaseUrl: "ws://localhost:3000",
106106 },
107 environmentId: EnvironmentId.makeUnsafe("environment-local"),
107 environmentId: EnvironmentId.make("environment-local"),
108108 },
109109 client: rpcClientMock,
110 environmentId: EnvironmentId.makeUnsafe("environment-local"),
110 environmentId: EnvironmentId.make("environment-local"),
111111 ensureBootstrapped: async () => undefined,
112112 reconnect: async () => undefined,
113113 dispose: async () => undefined,
......@@ -214,7 +214,7 @@ const defaultProviders: ReadonlyArray<ServerProvider> = [
214214];
215215
216216const baseEnvironment = {
217 environmentId: EnvironmentId.makeUnsafe("environment-local"),
217 environmentId: EnvironmentId.make("environment-local"),
218218 label: "Local environment",
219219 platform: {
220220 os: "darwin" as const,
......@@ -315,9 +315,9 @@ describe("wsApi", () => {
315315
316316 const orchestrationEvent = {
317317 sequence: 1,
318 eventId: EventId.makeUnsafe("event-1"),
318 eventId: EventId.make("event-1"),
319319 aggregateKind: "project",
320 aggregateId: ProjectId.makeUnsafe("project-1"),
320 aggregateId: ProjectId.make("project-1"),
321321 occurredAt: "2026-02-24T00:00:00.000Z",
322322 commandId: null,
323323 causationEventId: null,
......@@ -325,7 +325,7 @@ describe("wsApi", () => {
325325 metadata: {},
326326 type: "project.created",
327327 payload: {
328 projectId: ProjectId.makeUnsafe("project-1"),
328 projectId: ProjectId.make("project-1"),
329329 title: "Project",
330330 workspaceRoot: "/tmp/workspace",
331331 defaultModelSelection: {
......@@ -390,8 +390,8 @@ describe("wsApi", () => {
390390 const api = createEnvironmentApi(rpcClientMock as never);
391391 const command = {
392392 type: "project.create",
393 commandId: CommandId.makeUnsafe("cmd-1"),
394 projectId: ProjectId.makeUnsafe("project-1"),
393 commandId: CommandId.make("cmd-1"),
394 projectId: ProjectId.make("project-1"),
395395 title: "Project",
396396 workspaceRoot: "/tmp/project",
397397 defaultModelSelection: {
......@@ -429,7 +429,7 @@ describe("wsApi", () => {
429429
430430 const api = createEnvironmentApi(rpcClientMock as never);
431431 await api.orchestration.getFullThreadDiff({
432 threadId: ThreadId.makeUnsafe("thread-1"),
432 threadId: ThreadId.make("thread-1"),
433433 toTurnCount: 1,
434434 });
435435
......@@ -535,14 +535,12 @@ describe("wsApi", () => {
535535 });
536536 await api.persistence.getSavedEnvironmentRegistry();
537537 await api.persistence.setSavedEnvironmentRegistry([]);
538 await api.persistence.getSavedEnvironmentSecret(EnvironmentId.makeUnsafe("environment-local"));
538 await api.persistence.getSavedEnvironmentSecret(EnvironmentId.make("environment-local"));
539539 await api.persistence.setSavedEnvironmentSecret(
540 EnvironmentId.makeUnsafe("environment-local"),
540 EnvironmentId.make("environment-local"),
541541 "bearer-token",
542542 );
543 await api.persistence.removeSavedEnvironmentSecret(
544 EnvironmentId.makeUnsafe("environment-local"),
545 );
543 await api.persistence.removeSavedEnvironmentSecret(EnvironmentId.make("environment-local"));
546544
547545 expect(getClientSettings).toHaveBeenCalledWith();
548546 expect(setClientSettings).toHaveBeenCalledWith({
......@@ -574,7 +572,7 @@ describe("wsApi", () => {
574572 });
575573 await api.persistence.setSavedEnvironmentRegistry([
576574 {
577 environmentId: EnvironmentId.makeUnsafe("environment-local"),
575 environmentId: EnvironmentId.make("environment-local"),
578576 label: "Primary",
579577 httpBaseUrl: "http://localhost:3000",
580578 wsBaseUrl: "ws://localhost:3000",
......@@ -583,7 +581,7 @@ describe("wsApi", () => {
583581 },
584582 ]);
585583 await api.persistence.setSavedEnvironmentSecret(
586 EnvironmentId.makeUnsafe("environment-local"),
584 EnvironmentId.make("environment-local"),
587585 "bearer-token",
588586 );
589587
......@@ -597,7 +595,7 @@ describe("wsApi", () => {
597595 });
598596 await expect(api.persistence.getSavedEnvironmentRegistry()).resolves.toEqual([
599597 {
600 environmentId: EnvironmentId.makeUnsafe("environment-local"),
598 environmentId: EnvironmentId.make("environment-local"),
601599 label: "Primary",
602600 httpBaseUrl: "http://localhost:3000",
603601 wsBaseUrl: "ws://localhost:3000",
......@@ -606,15 +604,13 @@ describe("wsApi", () => {
606604 },
607605 ]);
608606 await expect(
609 api.persistence.getSavedEnvironmentSecret(EnvironmentId.makeUnsafe("environment-local")),
607 api.persistence.getSavedEnvironmentSecret(EnvironmentId.make("environment-local")),
610608 ).resolves.toBe("bearer-token");
611609
612 await api.persistence.removeSavedEnvironmentSecret(
613 EnvironmentId.makeUnsafe("environment-local"),
614 );
610 await api.persistence.removeSavedEnvironmentSecret(EnvironmentId.make("environment-local"));
615611
616612 await expect(
617 api.persistence.getSavedEnvironmentSecret(EnvironmentId.makeUnsafe("environment-local")),
613 api.persistence.getSavedEnvironmentSecret(EnvironmentId.make("environment-local")),
618614 ).resolves.toBeNull();
619615 });
620616});
apps/web/src/orchestrationEventEffects.test.ts+12-12
......@@ -19,14 +19,14 @@ function makeEvent<T extends OrchestrationEvent["type"]>(
1919 const sequence = overrides.sequence ?? 1;
2020 return {
2121 sequence,
22 eventId: EventId.makeUnsafe(`event-${sequence}`),
22 eventId: EventId.make(`event-${sequence}`),
2323 aggregateKind: "thread",
2424 aggregateId:
2525 "threadId" in payload
2626 ? payload.threadId
2727 : "projectId" in payload
2828 ? payload.projectId
29 : ProjectId.makeUnsafe("project-1"),
29 : ProjectId.make("project-1"),
3030 occurredAt: "2026-02-27T00:00:00.000Z",
3131 commandId: null,
3232 causationEventId: null,
......@@ -40,14 +40,14 @@ function makeEvent<T extends OrchestrationEvent["type"]>(
4040
4141describe("deriveOrchestrationBatchEffects", () => {
4242 it("targets draft promotion and terminal cleanup from thread lifecycle events", () => {
43 const createdThreadId = ThreadId.makeUnsafe("thread-created");
44 const deletedThreadId = ThreadId.makeUnsafe("thread-deleted");
45 const archivedThreadId = ThreadId.makeUnsafe("thread-archived");
43 const createdThreadId = ThreadId.make("thread-created");
44 const deletedThreadId = ThreadId.make("thread-deleted");
45 const archivedThreadId = ThreadId.make("thread-archived");
4646
4747 const effects = deriveOrchestrationBatchEffects([
4848 makeEvent("thread.created", {
4949 threadId: createdThreadId,
50 projectId: ProjectId.makeUnsafe("project-1"),
50 projectId: ProjectId.make("project-1"),
5151 title: "Created thread",
5252 modelSelection: { provider: "codex", model: "gpt-5-codex" },
5353 runtimeMode: "full-access",
......@@ -75,7 +75,7 @@ describe("deriveOrchestrationBatchEffects", () => {
7575 });
7676
7777 it("keeps only the final lifecycle outcome for a thread within one batch", () => {
78 const threadId = ThreadId.makeUnsafe("thread-1");
78 const threadId = ThreadId.make("thread-1");
7979
8080 const effects = deriveOrchestrationBatchEffects([
8181 makeEvent("thread.deleted", {
......@@ -84,7 +84,7 @@ describe("deriveOrchestrationBatchEffects", () => {
8484 }),
8585 makeEvent("thread.created", {
8686 threadId,
87 projectId: ProjectId.makeUnsafe("project-1"),
87 projectId: ProjectId.make("project-1"),
8888 title: "Recreated thread",
8989 modelSelection: { provider: "codex", model: "gpt-5-codex" },
9090 runtimeMode: "full-access",
......@@ -96,12 +96,12 @@ describe("deriveOrchestrationBatchEffects", () => {
9696 }),
9797 makeEvent("thread.turn-diff-completed", {
9898 threadId,
99 turnId: TurnId.makeUnsafe("turn-1"),
99 turnId: TurnId.make("turn-1"),
100100 checkpointTurnCount: 1,
101 checkpointRef: CheckpointRef.makeUnsafe("checkpoint-1"),
101 checkpointRef: CheckpointRef.make("checkpoint-1"),
102102 status: "ready",
103103 files: [],
104 assistantMessageId: MessageId.makeUnsafe("assistant-1"),
104 assistantMessageId: MessageId.make("assistant-1"),
105105 completedAt: "2026-02-27T00:00:03.000Z",
106106 }),
107107 ]);
......@@ -113,7 +113,7 @@ describe("deriveOrchestrationBatchEffects", () => {
113113 });
114114
115115 it("does not retain archive cleanup when a thread is unarchived later in the same batch", () => {
116 const threadId = ThreadId.makeUnsafe("thread-1");
116 const threadId = ThreadId.make("thread-1");
117117
118118 const effects = deriveOrchestrationBatchEffects([
119119 makeEvent("thread.archived", {
apps/web/src/projectScripts.ts+1-1
......@@ -22,7 +22,7 @@ function normalizeScriptId(value: string): string {
2222}
2323
2424export const commandForProjectScript = (scriptId: string): KeybindingCommand =>
25 SCRIPT_RUN_COMMAND_PATTERN.makeUnsafe(`script.${scriptId}.run`);
25 SCRIPT_RUN_COMMAND_PATTERN.make(`script.${scriptId}.run`);
2626
2727export function projectScriptIdFromCommand(command: string): string | null {
2828 const trimmed = command.trim();
apps/web/src/routes/_chat.draft.$draftId.tsx+1-1
......@@ -11,7 +11,7 @@ import { buildThreadRouteParams } from "../threadRoutes";
1111function DraftChatThreadRouteView() {
1212 const navigate = useNavigate();
1313 const { draftId: rawDraftId } = Route.useParams();
14 const draftId = DraftId.makeUnsafe(rawDraftId);
14 const draftId = DraftId.make(rawDraftId);
1515 const draftSession = useComposerDraftStore((store) => store.getDraftSession(draftId));
1616 const serverThread = useStore(
1717 useMemo(
apps/web/src/rpc/protocol.ts+4-4
......@@ -154,8 +154,8 @@ export function createWsRpcProtocolLayer(
154154 }),
155155 (protocol) => ({
156156 ...protocol,
157 run: (writeResponse) =>
158 protocol.run((response) => {
157 run: (clientId, writeResponse) =>
158 protocol.run(clientId, (response) => {
159159 if (response._tag === "Chunk" || response._tag === "Exit") {
160160 acknowledgeRpcRequest(response.requestId);
161161 } else if (response._tag === "ClientProtocolError" || response._tag === "Defect") {
......@@ -163,11 +163,11 @@ export function createWsRpcProtocolLayer(
163163 }
164164 return writeResponse(response);
165165 }),
166 send: (request, transferables) => {
166 send: (clientId, request, transferables) => {
167167 if (request._tag === "Request") {
168168 trackRpcRequestSent(request.id, request.tag);
169169 }
170 return protocol.send(request, transferables);
170 return protocol.send(clientId, request, transferables);
171171 },
172172 }),
173173 ),
apps/web/src/rpc/serverState.test.ts+7-7
......@@ -52,7 +52,7 @@ const defaultProviders: ReadonlyArray<ServerProvider> = [
5252];
5353
5454const baseEnvironment = {
55 environmentId: EnvironmentId.makeUnsafe("environment-local"),
55 environmentId: EnvironmentId.make("environment-local"),
5656 label: "Local environment",
5757 platform: {
5858 os: "darwin" as const,
......@@ -217,8 +217,8 @@ describe("serverState", () => {
217217 environment: baseEnvironment,
218218 cwd: "/tmp/workspace",
219219 projectName: "t3-code",
220 bootstrapProjectId: ProjectId.makeUnsafe("project-1"),
221 bootstrapThreadId: ThreadId.makeUnsafe("thread-1"),
220 bootstrapProjectId: ProjectId.make("project-1"),
221 bootstrapThreadId: ThreadId.make("thread-1"),
222222 },
223223 });
224224
......@@ -226,8 +226,8 @@ describe("serverState", () => {
226226 environment: baseEnvironment,
227227 cwd: "/tmp/workspace",
228228 projectName: "t3-code",
229 bootstrapProjectId: ProjectId.makeUnsafe("project-1"),
230 bootstrapThreadId: ThreadId.makeUnsafe("thread-1"),
229 bootstrapProjectId: ProjectId.make("project-1"),
230 bootstrapThreadId: ThreadId.make("thread-1"),
231231 });
232232
233233 const lateListener = vi.fn();
......@@ -236,8 +236,8 @@ describe("serverState", () => {
236236 environment: baseEnvironment,
237237 cwd: "/tmp/workspace",
238238 projectName: "t3-code",
239 bootstrapProjectId: ProjectId.makeUnsafe("project-1"),
240 bootstrapThreadId: ThreadId.makeUnsafe("thread-1"),
239 bootstrapProjectId: ProjectId.make("project-1"),
240 bootstrapThreadId: ThreadId.make("thread-1"),
241241 });
242242
243243 unsubscribeLate();
apps/web/src/session-logic.test.ts+43-43
......@@ -35,13 +35,13 @@ function makeActivity(overrides: {
3535}): OrchestrationThreadActivity {
3636 const payload = overrides.payload ?? {};
3737 return {
38 id: EventId.makeUnsafe(overrides.id ?? crypto.randomUUID()),
38 id: EventId.make(overrides.id ?? crypto.randomUUID()),
3939 createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z",
4040 kind: overrides.kind ?? "tool.started",
4141 summary: overrides.summary ?? "Tool call",
4242 tone: overrides.tone ?? "tool",
4343 payload,
44 turnId: overrides.turnId ? TurnId.makeUnsafe(overrides.turnId) : null,
44 turnId: overrides.turnId ? TurnId.make(overrides.turnId) : null,
4545 ...(overrides.sequence !== undefined ? { sequence: overrides.sequence } : {}),
4646 };
4747}
......@@ -336,7 +336,7 @@ describe("deriveActivePlanState", () => {
336336 }),
337337 ];
338338
339 expect(deriveActivePlanState(activities, TurnId.makeUnsafe("turn-1"))).toEqual({
339 expect(deriveActivePlanState(activities, TurnId.make("turn-1"))).toEqual({
340340 createdAt: "2026-02-23T00:00:02.000Z",
341341 turnId: "turn-1",
342342 explanation: "Refined plan",
......@@ -352,7 +352,7 @@ describe("findLatestProposedPlan", () => {
352352 [
353353 {
354354 id: "plan:thread-1:turn:turn-1",
355 turnId: TurnId.makeUnsafe("turn-1"),
355 turnId: TurnId.make("turn-1"),
356356 planMarkdown: "# Older",
357357 implementedAt: null,
358358 implementationThreadId: null,
......@@ -361,7 +361,7 @@ describe("findLatestProposedPlan", () => {
361361 },
362362 {
363363 id: "plan:thread-1:turn:turn-1",
364 turnId: TurnId.makeUnsafe("turn-1"),
364 turnId: TurnId.make("turn-1"),
365365 planMarkdown: "# Latest",
366366 implementedAt: null,
367367 implementationThreadId: null,
......@@ -370,7 +370,7 @@ describe("findLatestProposedPlan", () => {
370370 },
371371 {
372372 id: "plan:thread-1:turn:turn-2",
373 turnId: TurnId.makeUnsafe("turn-2"),
373 turnId: TurnId.make("turn-2"),
374374 planMarkdown: "# Different turn",
375375 implementedAt: null,
376376 implementationThreadId: null,
......@@ -378,7 +378,7 @@ describe("findLatestProposedPlan", () => {
378378 updatedAt: "2026-02-23T00:00:03.000Z",
379379 },
380380 ],
381 TurnId.makeUnsafe("turn-1"),
381 TurnId.make("turn-1"),
382382 ),
383383 ).toEqual({
384384 id: "plan:thread-1:turn:turn-1",
......@@ -396,7 +396,7 @@ describe("findLatestProposedPlan", () => {
396396 [
397397 {
398398 id: "plan:thread-1:turn:turn-1",
399 turnId: TurnId.makeUnsafe("turn-1"),
399 turnId: TurnId.make("turn-1"),
400400 planMarkdown: "# First",
401401 implementedAt: null,
402402 implementationThreadId: null,
......@@ -405,7 +405,7 @@ describe("findLatestProposedPlan", () => {
405405 },
406406 {
407407 id: "plan:thread-1:turn:turn-2",
408 turnId: TurnId.makeUnsafe("turn-2"),
408 turnId: TurnId.make("turn-2"),
409409 planMarkdown: "# Latest",
410410 implementedAt: null,
411411 implementationThreadId: null,
......@@ -425,7 +425,7 @@ describe("hasActionableProposedPlan", () => {
425425 expect(
426426 hasActionableProposedPlan({
427427 id: "plan-1",
428 turnId: TurnId.makeUnsafe("turn-1"),
428 turnId: TurnId.make("turn-1"),
429429 planMarkdown: "# Plan",
430430 implementedAt: null,
431431 implementationThreadId: null,
......@@ -439,10 +439,10 @@ describe("hasActionableProposedPlan", () => {
439439 expect(
440440 hasActionableProposedPlan({
441441 id: "plan-1",
442 turnId: TurnId.makeUnsafe("turn-1"),
442 turnId: TurnId.make("turn-1"),
443443 planMarkdown: "# Plan",
444444 implementedAt: "2026-02-23T00:00:02.000Z",
445 implementationThreadId: ThreadId.makeUnsafe("thread-implement"),
445 implementationThreadId: ThreadId.make("thread-implement"),
446446 createdAt: "2026-02-23T00:00:00.000Z",
447447 updatedAt: "2026-02-23T00:00:02.000Z",
448448 }),
......@@ -456,25 +456,25 @@ describe("findSidebarProposedPlan", () => {
456456 findSidebarProposedPlan({
457457 threads: [
458458 {
459 id: ThreadId.makeUnsafe("thread-1"),
459 id: ThreadId.make("thread-1"),
460460 proposedPlans: [
461461 {
462462 id: "plan-1",
463 turnId: TurnId.makeUnsafe("turn-plan"),
463 turnId: TurnId.make("turn-plan"),
464464 planMarkdown: "# Source plan",
465465 implementedAt: "2026-02-23T00:00:03.000Z",
466 implementationThreadId: ThreadId.makeUnsafe("thread-2"),
466 implementationThreadId: ThreadId.make("thread-2"),
467467 createdAt: "2026-02-23T00:00:01.000Z",
468468 updatedAt: "2026-02-23T00:00:02.000Z",
469469 },
470470 ],
471471 },
472472 {
473 id: ThreadId.makeUnsafe("thread-2"),
473 id: ThreadId.make("thread-2"),
474474 proposedPlans: [
475475 {
476476 id: "plan-2",
477 turnId: TurnId.makeUnsafe("turn-other"),
477 turnId: TurnId.make("turn-other"),
478478 planMarkdown: "# Latest elsewhere",
479479 implementedAt: null,
480480 implementationThreadId: null,
......@@ -485,14 +485,14 @@ describe("findSidebarProposedPlan", () => {
485485 },
486486 ],
487487 latestTurn: {
488 turnId: TurnId.makeUnsafe("turn-implementation"),
488 turnId: TurnId.make("turn-implementation"),
489489 sourceProposedPlan: {
490 threadId: ThreadId.makeUnsafe("thread-1"),
490 threadId: ThreadId.make("thread-1"),
491491 planId: "plan-1",
492492 },
493493 },
494494 latestTurnSettled: false,
495 threadId: ThreadId.makeUnsafe("thread-1"),
495 threadId: ThreadId.make("thread-1"),
496496 }),
497497 ).toEqual({
498498 id: "plan-1",
......@@ -510,11 +510,11 @@ describe("findSidebarProposedPlan", () => {
510510 findSidebarProposedPlan({
511511 threads: [
512512 {
513 id: ThreadId.makeUnsafe("thread-1"),
513 id: ThreadId.make("thread-1"),
514514 proposedPlans: [
515515 {
516516 id: "plan-1",
517 turnId: TurnId.makeUnsafe("turn-plan"),
517 turnId: TurnId.make("turn-plan"),
518518 planMarkdown: "# Older",
519519 implementedAt: null,
520520 implementationThreadId: null,
......@@ -523,7 +523,7 @@ describe("findSidebarProposedPlan", () => {
523523 },
524524 {
525525 id: "plan-2",
526 turnId: TurnId.makeUnsafe("turn-latest"),
526 turnId: TurnId.make("turn-latest"),
527527 planMarkdown: "# Latest",
528528 implementedAt: null,
529529 implementationThreadId: null,
......@@ -534,14 +534,14 @@ describe("findSidebarProposedPlan", () => {
534534 },
535535 ],
536536 latestTurn: {
537 turnId: TurnId.makeUnsafe("turn-implementation"),
537 turnId: TurnId.make("turn-implementation"),
538538 sourceProposedPlan: {
539 threadId: ThreadId.makeUnsafe("thread-1"),
539 threadId: ThreadId.make("thread-1"),
540540 planId: "plan-1",
541541 },
542542 },
543543 latestTurnSettled: true,
544 threadId: ThreadId.makeUnsafe("thread-1"),
544 threadId: ThreadId.make("thread-1"),
545545 })?.planMarkdown,
546546 ).toBe("# Latest");
547547 });
......@@ -609,7 +609,7 @@ describe("deriveWorkLogEntries", () => {
609609 makeActivity({ id: "no-turn", summary: "Checkpoint captured", tone: "info" }),
610610 ];
611611
612 const entries = deriveWorkLogEntries(activities, TurnId.makeUnsafe("turn-2"));
612 const entries = deriveWorkLogEntries(activities, TurnId.make("turn-2"));
613613 expect(entries.map((entry) => entry.id)).toEqual(["turn-2"]);
614614 });
615615
......@@ -1022,7 +1022,7 @@ describe("deriveTimelineEntries", () => {
10221022 const entries = deriveTimelineEntries(
10231023 [
10241024 {
1025 id: MessageId.makeUnsafe("message-1"),
1025 id: MessageId.make("message-1"),
10261026 role: "assistant",
10271027 text: "hello",
10281028 createdAt: "2026-02-23T00:00:01.000Z",
......@@ -1032,7 +1032,7 @@ describe("deriveTimelineEntries", () => {
10321032 [
10331033 {
10341034 id: "plan:thread-1:turn:turn-1",
1035 turnId: TurnId.makeUnsafe("turn-1"),
1035 turnId: TurnId.make("turn-1"),
10361036 planMarkdown: "# Ship it",
10371037 implementedAt: null,
10381038 implementationThreadId: null,
......@@ -1065,14 +1065,14 @@ describe("deriveTimelineEntries", () => {
10651065 const entries = deriveTimelineEntries(
10661066 [
10671067 {
1068 id: MessageId.makeUnsafe("assistant-earlier"),
1068 id: MessageId.make("assistant-earlier"),
10691069 role: "assistant",
10701070 text: "progress update",
10711071 createdAt: "2026-02-23T00:00:01.000Z",
10721072 streaming: false,
10731073 },
10741074 {
1075 id: MessageId.makeUnsafe("assistant-final"),
1075 id: MessageId.make("assistant-final"),
10761076 role: "assistant",
10771077 text: "final answer",
10781078 createdAt: "2026-02-23T00:00:01.000Z",
......@@ -1085,7 +1085,7 @@ describe("deriveTimelineEntries", () => {
10851085
10861086 expect(
10871087 deriveCompletionDividerBeforeEntryId(entries, {
1088 assistantMessageId: MessageId.makeUnsafe("assistant-final"),
1088 assistantMessageId: MessageId.make("assistant-final"),
10891089 startedAt: "2026-02-23T00:00:00.000Z",
10901090 completedAt: "2026-02-23T00:00:02.000Z",
10911091 }),
......@@ -1112,7 +1112,7 @@ describe("deriveWorkLogEntries context window handling", () => {
11121112 tone: "tool",
11131113 }),
11141114 ],
1115 TurnId.makeUnsafe("turn-1"),
1115 TurnId.make("turn-1"),
11161116 );
11171117
11181118 expect(entries).toHaveLength(1);
......@@ -1130,7 +1130,7 @@ describe("deriveWorkLogEntries context window handling", () => {
11301130 tone: "info",
11311131 }),
11321132 ],
1133 TurnId.makeUnsafe("turn-1"),
1133 TurnId.make("turn-1"),
11341134 );
11351135
11361136 expect(entries).toHaveLength(1);
......@@ -1154,14 +1154,14 @@ describe("hasToolActivityForTurn", () => {
11541154 makeActivity({ id: "info-1", turnId: "turn-2", kind: "turn.completed", tone: "info" }),
11551155 ];
11561156
1157 expect(hasToolActivityForTurn(activities, TurnId.makeUnsafe("turn-1"))).toBe(true);
1158 expect(hasToolActivityForTurn(activities, TurnId.makeUnsafe("turn-2"))).toBe(false);
1157 expect(hasToolActivityForTurn(activities, TurnId.make("turn-1"))).toBe(true);
1158 expect(hasToolActivityForTurn(activities, TurnId.make("turn-2"))).toBe(false);
11591159 });
11601160});
11611161
11621162describe("isLatestTurnSettled", () => {
11631163 const latestTurn = {
1164 turnId: TurnId.makeUnsafe("turn-1"),
1164 turnId: TurnId.make("turn-1"),
11651165 startedAt: "2026-02-27T21:10:00.000Z",
11661166 completedAt: "2026-02-27T21:10:06.000Z",
11671167 } as const;
......@@ -1170,7 +1170,7 @@ describe("isLatestTurnSettled", () => {
11701170 expect(
11711171 isLatestTurnSettled(latestTurn, {
11721172 orchestrationStatus: "running",
1173 activeTurnId: TurnId.makeUnsafe("turn-1"),
1173 activeTurnId: TurnId.make("turn-1"),
11741174 }),
11751175 ).toBe(false);
11761176 });
......@@ -1179,7 +1179,7 @@ describe("isLatestTurnSettled", () => {
11791179 expect(
11801180 isLatestTurnSettled(latestTurn, {
11811181 orchestrationStatus: "running",
1182 activeTurnId: TurnId.makeUnsafe("turn-2"),
1182 activeTurnId: TurnId.make("turn-2"),
11831183 }),
11841184 ).toBe(false);
11851185 });
......@@ -1197,7 +1197,7 @@ describe("isLatestTurnSettled", () => {
11971197 expect(
11981198 isLatestTurnSettled(
11991199 {
1200 turnId: TurnId.makeUnsafe("turn-1"),
1200 turnId: TurnId.make("turn-1"),
12011201 startedAt: null,
12021202 completedAt: "2026-02-27T21:10:06.000Z",
12031203 },
......@@ -1209,7 +1209,7 @@ describe("isLatestTurnSettled", () => {
12091209
12101210describe("deriveActiveWorkStartedAt", () => {
12111211 const latestTurn = {
1212 turnId: TurnId.makeUnsafe("turn-1"),
1212 turnId: TurnId.make("turn-1"),
12131213 startedAt: "2026-02-27T21:10:00.000Z",
12141214 completedAt: "2026-02-27T21:10:06.000Z",
12151215 } as const;
......@@ -1220,7 +1220,7 @@ describe("deriveActiveWorkStartedAt", () => {
12201220 latestTurn,
12211221 {
12221222 orchestrationStatus: "running",
1223 activeTurnId: TurnId.makeUnsafe("turn-1"),
1223 activeTurnId: TurnId.make("turn-1"),
12241224 },
12251225 "2026-02-27T21:11:00.000Z",
12261226 ),
......@@ -1244,7 +1244,7 @@ describe("deriveActiveWorkStartedAt", () => {
12441244 expect(
12451245 deriveActiveWorkStartedAt(
12461246 {
1247 turnId: TurnId.makeUnsafe("turn-1"),
1247 turnId: TurnId.make("turn-1"),
12481248 startedAt: "2026-02-27T21:10:00.000Z",
12491249 completedAt: "2026-02-27T21:10:06.000Z",
12501250 },
apps/web/src/session-logic.ts+2-2
......@@ -193,7 +193,7 @@ export function derivePendingApprovals(
193193 : null;
194194 const requestId =
195195 payload && typeof payload.requestId === "string"
196 ? ApprovalRequestId.makeUnsafe(payload.requestId)
196 ? ApprovalRequestId.make(payload.requestId)
197197 : null;
198198 const requestKind =
199199 payload &&
......@@ -299,7 +299,7 @@ export function derivePendingUserInputs(
299299 : null;
300300 const requestId =
301301 payload && typeof payload.requestId === "string"
302 ? ApprovalRequestId.makeUnsafe(payload.requestId)
302 ? ApprovalRequestId.make(payload.requestId)
303303 : null;
304304 const detail = payload && typeof payload.detail === "string" ? payload.detail : undefined;
305305
apps/web/src/store.test.ts+76-76
......@@ -26,8 +26,8 @@ import {
2626} from "./store";
2727import { DEFAULT_INTERACTION_MODE, DEFAULT_RUNTIME_MODE, type Thread } from "./types";
2828
29const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local");
30const remoteEnvironmentId = EnvironmentId.makeUnsafe("environment-remote");
29const localEnvironmentId = EnvironmentId.make("environment-local");
30const remoteEnvironmentId = EnvironmentId.make("environment-remote");
3131
3232function withActiveEnvironmentState(
3333 environmentState: EnvironmentState,
......@@ -59,10 +59,10 @@ function withActiveEnvironmentState(
5959
6060function makeThread(overrides: Partial<Thread> = {}): Thread {
6161 return {
62 id: ThreadId.makeUnsafe("thread-1"),
62 id: ThreadId.make("thread-1"),
6363 environmentId: localEnvironmentId,
6464 codexThreadId: null,
65 projectId: ProjectId.makeUnsafe("project-1"),
65 projectId: ProjectId.make("project-1"),
6666 title: "Thread",
6767 modelSelection: {
6868 provider: "codex",
......@@ -86,7 +86,7 @@ function makeThread(overrides: Partial<Thread> = {}): Thread {
8686}
8787
8888function makeState(thread: Thread): AppState {
89 const projectId = ProjectId.makeUnsafe("project-1");
89 const projectId = ProjectId.make("project-1");
9090 const project = {
9191 id: projectId,
9292 environmentId: thread.environmentId,
......@@ -226,14 +226,14 @@ function makeEvent<T extends OrchestrationEvent["type"]>(
226226 const sequence = overrides.sequence ?? 1;
227227 return {
228228 sequence,
229 eventId: EventId.makeUnsafe(`event-${sequence}`),
229 eventId: EventId.make(`event-${sequence}`),
230230 aggregateKind: "thread",
231231 aggregateId:
232232 "threadId" in payload
233233 ? payload.threadId
234234 : "projectId" in payload
235235 ? payload.projectId
236 : ProjectId.makeUnsafe("project-1"),
236 : ProjectId.make("project-1"),
237237 occurredAt: "2026-02-27T00:00:00.000Z",
238238 commandId: null,
239239 causationEventId: null,
......@@ -247,8 +247,8 @@ function makeEvent<T extends OrchestrationEvent["type"]>(
247247
248248function makeReadModelThread(overrides: Partial<OrchestrationReadModel["threads"][number]>) {
249249 return {
250 id: ThreadId.makeUnsafe("thread-1"),
251 projectId: ProjectId.makeUnsafe("project-1"),
250 id: ThreadId.make("thread-1"),
251 projectId: ProjectId.make("project-1"),
252252 title: "Thread",
253253 modelSelection: {
254254 provider: "codex",
......@@ -278,7 +278,7 @@ function makeReadModel(thread: OrchestrationReadModel["threads"][number]): Orche
278278 updatedAt: "2026-02-27T00:00:00.000Z",
279279 projects: [
280280 {
281 id: ProjectId.makeUnsafe("project-1"),
281 id: ProjectId.make("project-1"),
282282 title: "Project",
283283 workspaceRoot: "/tmp/project",
284284 defaultModelSelection: {
......@@ -299,7 +299,7 @@ function makeReadModelProject(
299299 overrides: Partial<OrchestrationReadModel["projects"][number]>,
300300): OrchestrationReadModel["projects"][number] {
301301 return {
302 id: ProjectId.makeUnsafe("project-1"),
302 id: ProjectId.make("project-1"),
303303 title: "Project",
304304 workspaceRoot: "/tmp/project",
305305 defaultModelSelection: {
......@@ -316,7 +316,7 @@ function makeReadModelProject(
316316
317317describe("setThreadBranch", () => {
318318 it("updates only the scoped thread environment", () => {
319 const sharedThreadId = ThreadId.makeUnsafe("thread-shared");
319 const sharedThreadId = ThreadId.make("thread-shared");
320320 const localThread = makeThread({
321321 id: sharedThreadId,
322322 environmentId: localEnvironmentId,
......@@ -397,7 +397,7 @@ describe("store read model sync", () => {
397397 model: "sonnet",
398398 },
399399 session: {
400 threadId: ThreadId.makeUnsafe("thread-1"),
400 threadId: ThreadId.make("thread-1"),
401401 status: "ready",
402402 providerName: "claudeAgent",
403403 runtimeMode: "approval-required",
......@@ -444,9 +444,9 @@ describe("store read model sync", () => {
444444 });
445445
446446 it("replaces projects using snapshot order during recovery", () => {
447 const project1 = ProjectId.makeUnsafe("project-1");
448 const project2 = ProjectId.makeUnsafe("project-2");
449 const project3 = ProjectId.makeUnsafe("project-3");
447 const project1 = ProjectId.make("project-1");
448 const project2 = ProjectId.make("project-2");
449 const project3 = ProjectId.make("project-3");
450450 const initialState: AppState = makeEmptyState({
451451 projectIds: [project2, project1],
452452 projectById: {
......@@ -516,7 +516,7 @@ describe("incremental orchestration updates", () => {
516516 const next = applyOrchestrationEvent(
517517 state,
518518 makeEvent("thread.meta-updated", {
519 threadId: ThreadId.makeUnsafe("thread-1"),
519 threadId: ThreadId.make("thread-1"),
520520 title: "Updated title",
521521 updatedAt: "2026-02-27T00:00:01.000Z",
522522 }),
......@@ -533,7 +533,7 @@ describe("incremental orchestration updates", () => {
533533 const nextAfterProjectDelete = applyOrchestrationEvent(
534534 state,
535535 makeEvent("project.deleted", {
536 projectId: ProjectId.makeUnsafe("project-missing"),
536 projectId: ProjectId.make("project-missing"),
537537 deletedAt: "2026-02-27T00:00:01.000Z",
538538 }),
539539 localEnvironmentId,
......@@ -541,7 +541,7 @@ describe("incremental orchestration updates", () => {
541541 const nextAfterThreadDelete = applyOrchestrationEvent(
542542 state,
543543 makeEvent("thread.deleted", {
544 threadId: ThreadId.makeUnsafe("thread-missing"),
544 threadId: ThreadId.make("thread-missing"),
545545 deletedAt: "2026-02-27T00:00:01.000Z",
546546 }),
547547 localEnvironmentId,
......@@ -552,8 +552,8 @@ describe("incremental orchestration updates", () => {
552552 });
553553
554554 it("reuses an existing project row when project.created arrives with a new id for the same cwd", () => {
555 const originalProjectId = ProjectId.makeUnsafe("project-1");
556 const recreatedProjectId = ProjectId.makeUnsafe("project-2");
555 const originalProjectId = ProjectId.make("project-1");
556 const recreatedProjectId = ProjectId.make("project-2");
557557 const state: AppState = makeEmptyState({
558558 projectIds: [originalProjectId],
559559 projectById: {
......@@ -602,9 +602,9 @@ describe("incremental orchestration updates", () => {
602602 });
603603
604604 it("removes stale project index entries when thread.created recreates a thread under a new project", () => {
605 const originalProjectId = ProjectId.makeUnsafe("project-1");
606 const recreatedProjectId = ProjectId.makeUnsafe("project-2");
607 const threadId = ThreadId.makeUnsafe("thread-1");
605 const originalProjectId = ProjectId.make("project-1");
606 const recreatedProjectId = ProjectId.make("project-2");
607 const threadId = ThreadId.make("thread-1");
608608 const thread = makeThread({
609609 id: threadId,
610610 projectId: originalProjectId,
......@@ -671,20 +671,20 @@ describe("incremental orchestration updates", () => {
671671
672672 it("updates only the affected thread for message events", () => {
673673 const thread1 = makeThread({
674 id: ThreadId.makeUnsafe("thread-1"),
674 id: ThreadId.make("thread-1"),
675675 messages: [
676676 {
677 id: MessageId.makeUnsafe("message-1"),
677 id: MessageId.make("message-1"),
678678 role: "assistant",
679679 text: "hello",
680 turnId: TurnId.makeUnsafe("turn-1"),
680 turnId: TurnId.make("turn-1"),
681681 createdAt: "2026-02-27T00:00:00.000Z",
682682 completedAt: "2026-02-27T00:00:00.000Z",
683683 streaming: false,
684684 },
685685 ],
686686 });
687 const thread2 = makeThread({ id: ThreadId.makeUnsafe("thread-2") });
687 const thread2 = makeThread({ id: ThreadId.make("thread-2") });
688688 const baseState = makeState(thread1);
689689 const baseEnvironmentState = localEnvironmentStateOf(baseState);
690690 const state = withActiveEnvironmentState(baseEnvironmentState, {
......@@ -762,10 +762,10 @@ describe("incremental orchestration updates", () => {
762762 state,
763763 makeEvent("thread.message-sent", {
764764 threadId: thread1.id,
765 messageId: MessageId.makeUnsafe("message-1"),
765 messageId: MessageId.make("message-1"),
766766 role: "assistant",
767767 text: " world",
768 turnId: TurnId.makeUnsafe("turn-1"),
768 turnId: TurnId.make("turn-1"),
769769 streaming: true,
770770 createdAt: "2026-02-27T00:00:01.000Z",
771771 updatedAt: "2026-02-27T00:00:01.000Z",
......@@ -794,7 +794,7 @@ describe("incremental orchestration updates", () => {
794794 it("applies replay batches in sequence and updates session state", () => {
795795 const thread = makeThread({
796796 latestTurn: {
797 turnId: TurnId.makeUnsafe("turn-1"),
797 turnId: TurnId.make("turn-1"),
798798 state: "running",
799799 requestedAt: "2026-02-27T00:00:00.000Z",
800800 startedAt: "2026-02-27T00:00:00.000Z",
......@@ -816,7 +816,7 @@ describe("incremental orchestration updates", () => {
816816 status: "running",
817817 providerName: "codex",
818818 runtimeMode: "full-access",
819 activeTurnId: TurnId.makeUnsafe("turn-1"),
819 activeTurnId: TurnId.make("turn-1"),
820820 lastError: null,
821821 updatedAt: "2026-02-27T00:00:02.000Z",
822822 },
......@@ -827,10 +827,10 @@ describe("incremental orchestration updates", () => {
827827 "thread.message-sent",
828828 {
829829 threadId: thread.id,
830 messageId: MessageId.makeUnsafe("assistant-1"),
830 messageId: MessageId.make("assistant-1"),
831831 role: "assistant",
832832 text: "done",
833 turnId: TurnId.makeUnsafe("turn-1"),
833 turnId: TurnId.make("turn-1"),
834834 streaming: false,
835835 createdAt: "2026-02-27T00:00:03.000Z",
836836 updatedAt: "2026-02-27T00:00:03.000Z",
......@@ -850,7 +850,7 @@ describe("incremental orchestration updates", () => {
850850 const state = makeState(
851851 makeThread({
852852 latestTurn: {
853 turnId: TurnId.makeUnsafe("turn-2"),
853 turnId: TurnId.make("turn-2"),
854854 state: "running",
855855 requestedAt: "2026-02-27T00:00:02.000Z",
856856 startedAt: "2026-02-27T00:00:03.000Z",
......@@ -863,13 +863,13 @@ describe("incremental orchestration updates", () => {
863863 const next = applyOrchestrationEvent(
864864 state,
865865 makeEvent("thread.turn-diff-completed", {
866 threadId: ThreadId.makeUnsafe("thread-1"),
867 turnId: TurnId.makeUnsafe("turn-1"),
866 threadId: ThreadId.make("thread-1"),
867 turnId: TurnId.make("turn-1"),
868868 checkpointTurnCount: 1,
869 checkpointRef: CheckpointRef.makeUnsafe("checkpoint-1"),
869 checkpointRef: CheckpointRef.make("checkpoint-1"),
870870 status: "ready",
871871 files: [],
872 assistantMessageId: MessageId.makeUnsafe("assistant-1"),
872 assistantMessageId: MessageId.make("assistant-1"),
873873 completedAt: "2026-02-27T00:00:04.000Z",
874874 }),
875875 localEnvironmentId,
......@@ -880,7 +880,7 @@ describe("incremental orchestration updates", () => {
880880 });
881881
882882 it("rebinds live turn diffs to the authoritative assistant message when it arrives later", () => {
883 const turnId = TurnId.makeUnsafe("turn-1");
883 const turnId = TurnId.make("turn-1");
884884 const state = makeState(
885885 makeThread({
886886 latestTurn: {
......@@ -889,7 +889,7 @@ describe("incremental orchestration updates", () => {
889889 requestedAt: "2026-02-27T00:00:00.000Z",
890890 startedAt: "2026-02-27T00:00:00.000Z",
891891 completedAt: "2026-02-27T00:00:02.000Z",
892 assistantMessageId: MessageId.makeUnsafe("assistant:turn-1"),
892 assistantMessageId: MessageId.make("assistant:turn-1"),
893893 },
894894 turnDiffSummaries: [
895895 {
......@@ -897,8 +897,8 @@ describe("incremental orchestration updates", () => {
897897 completedAt: "2026-02-27T00:00:02.000Z",
898898 status: "ready",
899899 checkpointTurnCount: 1,
900 checkpointRef: CheckpointRef.makeUnsafe("checkpoint-1"),
901 assistantMessageId: MessageId.makeUnsafe("assistant:turn-1"),
900 checkpointRef: CheckpointRef.make("checkpoint-1"),
901 assistantMessageId: MessageId.make("assistant:turn-1"),
902902 files: [{ path: "src/app.ts", additions: 1, deletions: 0 }],
903903 },
904904 ],
......@@ -908,8 +908,8 @@ describe("incremental orchestration updates", () => {
908908 const next = applyOrchestrationEvent(
909909 state,
910910 makeEvent("thread.message-sent", {
911 threadId: ThreadId.makeUnsafe("thread-1"),
912 messageId: MessageId.makeUnsafe("assistant-real"),
911 threadId: ThreadId.make("thread-1"),
912 messageId: MessageId.make("assistant-real"),
913913 role: "assistant",
914914 text: "final answer",
915915 turnId,
......@@ -921,10 +921,10 @@ describe("incremental orchestration updates", () => {
921921 );
922922
923923 expect(threadsOf(next)[0]?.turnDiffSummaries[0]?.assistantMessageId).toBe(
924 MessageId.makeUnsafe("assistant-real"),
924 MessageId.make("assistant-real"),
925925 );
926926 expect(threadsOf(next)[0]?.latestTurn?.assistantMessageId).toBe(
927 MessageId.makeUnsafe("assistant-real"),
927 MessageId.make("assistant-real"),
928928 );
929929 });
930930
......@@ -933,28 +933,28 @@ describe("incremental orchestration updates", () => {
933933 makeThread({
934934 messages: [
935935 {
936 id: MessageId.makeUnsafe("user-1"),
936 id: MessageId.make("user-1"),
937937 role: "user",
938938 text: "first",
939 turnId: TurnId.makeUnsafe("turn-1"),
939 turnId: TurnId.make("turn-1"),
940940 createdAt: "2026-02-27T00:00:00.000Z",
941941 completedAt: "2026-02-27T00:00:00.000Z",
942942 streaming: false,
943943 },
944944 {
945 id: MessageId.makeUnsafe("assistant-1"),
945 id: MessageId.make("assistant-1"),
946946 role: "assistant",
947947 text: "first reply",
948 turnId: TurnId.makeUnsafe("turn-1"),
948 turnId: TurnId.make("turn-1"),
949949 createdAt: "2026-02-27T00:00:01.000Z",
950950 completedAt: "2026-02-27T00:00:01.000Z",
951951 streaming: false,
952952 },
953953 {
954 id: MessageId.makeUnsafe("user-2"),
954 id: MessageId.make("user-2"),
955955 role: "user",
956956 text: "second",
957 turnId: TurnId.makeUnsafe("turn-2"),
957 turnId: TurnId.make("turn-2"),
958958 createdAt: "2026-02-27T00:00:02.000Z",
959959 completedAt: "2026-02-27T00:00:02.000Z",
960960 streaming: false,
......@@ -963,7 +963,7 @@ describe("incremental orchestration updates", () => {
963963 proposedPlans: [
964964 {
965965 id: "plan-1",
966 turnId: TurnId.makeUnsafe("turn-1"),
966 turnId: TurnId.make("turn-1"),
967967 planMarkdown: "plan 1",
968968 implementedAt: null,
969969 implementationThreadId: null,
......@@ -972,7 +972,7 @@ describe("incremental orchestration updates", () => {
972972 },
973973 {
974974 id: "plan-2",
975 turnId: TurnId.makeUnsafe("turn-2"),
975 turnId: TurnId.make("turn-2"),
976976 planMarkdown: "plan 2",
977977 implementedAt: null,
978978 implementationThreadId: null,
......@@ -982,39 +982,39 @@ describe("incremental orchestration updates", () => {
982982 ],
983983 activities: [
984984 {
985 id: EventId.makeUnsafe("activity-1"),
985 id: EventId.make("activity-1"),
986986 tone: "info",
987987 kind: "step",
988988 summary: "one",
989989 payload: {},
990 turnId: TurnId.makeUnsafe("turn-1"),
990 turnId: TurnId.make("turn-1"),
991991 createdAt: "2026-02-27T00:00:00.000Z",
992992 },
993993 {
994 id: EventId.makeUnsafe("activity-2"),
994 id: EventId.make("activity-2"),
995995 tone: "info",
996996 kind: "step",
997997 summary: "two",
998998 payload: {},
999 turnId: TurnId.makeUnsafe("turn-2"),
999 turnId: TurnId.make("turn-2"),
10001000 createdAt: "2026-02-27T00:00:02.000Z",
10011001 },
10021002 ],
10031003 turnDiffSummaries: [
10041004 {
1005 turnId: TurnId.makeUnsafe("turn-1"),
1005 turnId: TurnId.make("turn-1"),
10061006 completedAt: "2026-02-27T00:00:01.000Z",
10071007 status: "ready",
10081008 checkpointTurnCount: 1,
1009 checkpointRef: CheckpointRef.makeUnsafe("ref-1"),
1009 checkpointRef: CheckpointRef.make("ref-1"),
10101010 files: [],
10111011 },
10121012 {
1013 turnId: TurnId.makeUnsafe("turn-2"),
1013 turnId: TurnId.make("turn-2"),
10141014 completedAt: "2026-02-27T00:00:03.000Z",
10151015 status: "ready",
10161016 checkpointTurnCount: 2,
1017 checkpointRef: CheckpointRef.makeUnsafe("ref-2"),
1017 checkpointRef: CheckpointRef.make("ref-2"),
10181018 files: [],
10191019 },
10201020 ],
......@@ -1024,7 +1024,7 @@ describe("incremental orchestration updates", () => {
10241024 const next = applyOrchestrationEvent(
10251025 state,
10261026 makeEvent("thread.reverted", {
1027 threadId: ThreadId.makeUnsafe("thread-1"),
1027 threadId: ThreadId.make("thread-1"),
10281028 turnCount: 1,
10291029 }),
10301030 localEnvironmentId,
......@@ -1036,46 +1036,46 @@ describe("incremental orchestration updates", () => {
10361036 ]);
10371037 expect(threadsOf(next)[0]?.proposedPlans.map((plan) => plan.id)).toEqual(["plan-1"]);
10381038 expect(threadsOf(next)[0]?.activities.map((activity) => activity.id)).toEqual([
1039 EventId.makeUnsafe("activity-1"),
1039 EventId.make("activity-1"),
10401040 ]);
10411041 expect(threadsOf(next)[0]?.turnDiffSummaries.map((summary) => summary.turnId)).toEqual([
1042 TurnId.makeUnsafe("turn-1"),
1042 TurnId.make("turn-1"),
10431043 ]);
10441044 });
10451045
10461046 it("clears pending source proposed plans after revert before a new session-set event", () => {
10471047 const thread = makeThread({
10481048 latestTurn: {
1049 turnId: TurnId.makeUnsafe("turn-2"),
1049 turnId: TurnId.make("turn-2"),
10501050 state: "completed",
10511051 requestedAt: "2026-02-27T00:00:02.000Z",
10521052 startedAt: "2026-02-27T00:00:02.000Z",
10531053 completedAt: "2026-02-27T00:00:03.000Z",
1054 assistantMessageId: MessageId.makeUnsafe("assistant-2"),
1054 assistantMessageId: MessageId.make("assistant-2"),
10551055 sourceProposedPlan: {
1056 threadId: ThreadId.makeUnsafe("thread-source"),
1056 threadId: ThreadId.make("thread-source"),
10571057 planId: "plan-2" as never,
10581058 },
10591059 },
10601060 pendingSourceProposedPlan: {
1061 threadId: ThreadId.makeUnsafe("thread-source"),
1061 threadId: ThreadId.make("thread-source"),
10621062 planId: "plan-2" as never,
10631063 },
10641064 turnDiffSummaries: [
10651065 {
1066 turnId: TurnId.makeUnsafe("turn-1"),
1066 turnId: TurnId.make("turn-1"),
10671067 completedAt: "2026-02-27T00:00:01.000Z",
10681068 status: "ready",
10691069 checkpointTurnCount: 1,
1070 checkpointRef: CheckpointRef.makeUnsafe("ref-1"),
1070 checkpointRef: CheckpointRef.make("ref-1"),
10711071 files: [],
10721072 },
10731073 {
1074 turnId: TurnId.makeUnsafe("turn-2"),
1074 turnId: TurnId.make("turn-2"),
10751075 completedAt: "2026-02-27T00:00:03.000Z",
10761076 status: "ready",
10771077 checkpointTurnCount: 2,
1078 checkpointRef: CheckpointRef.makeUnsafe("ref-2"),
1078 checkpointRef: CheckpointRef.make("ref-2"),
10791079 files: [],
10801080 },
10811081 ],
......@@ -1100,7 +1100,7 @@ describe("incremental orchestration updates", () => {
11001100 status: "running",
11011101 providerName: "codex",
11021102 runtimeMode: "full-access",
1103 activeTurnId: TurnId.makeUnsafe("turn-3"),
1103 activeTurnId: TurnId.make("turn-3"),
11041104 lastError: null,
11051105 updatedAt: "2026-02-27T00:00:04.000Z",
11061106 },
......@@ -1109,7 +1109,7 @@ describe("incremental orchestration updates", () => {
11091109 );
11101110
11111111 expect(threadsOf(next)[0]?.latestTurn).toMatchObject({
1112 turnId: TurnId.makeUnsafe("turn-3"),
1112 turnId: TurnId.make("turn-3"),
11131113 state: "running",
11141114 });
11151115 expect(threadsOf(next)[0]?.latestTurn?.sourceProposedPlan).toBeUndefined();
apps/web/src/terminalStateStore.test.ts+1-1
......@@ -9,7 +9,7 @@ import {
99 useTerminalStateStore,
1010} from "./terminalStateStore";
1111
12const THREAD_ID = ThreadId.makeUnsafe("thread-1");
12const THREAD_ID = ThreadId.make("thread-1");
1313const THREAD_REF = scopeThreadRef("environment-a" as never, THREAD_ID);
1414const OTHER_THREAD_REF = scopeThreadRef("environment-b" as never, THREAD_ID);
1515
apps/web/src/threadRoutes.test.ts+2-2
......@@ -12,7 +12,7 @@ import {
1212
1313describe("threadRoutes", () => {
1414 it("builds canonical thread route params from a scoped ref", () => {
15 const ref = scopeThreadRef("env-1" as never, ThreadId.makeUnsafe("thread-1"));
15 const ref = scopeThreadRef("env-1" as never, ThreadId.make("thread-1"));
1616
1717 expect(buildThreadRouteParams(ref)).toEqual({
1818 environmentId: "env-1",
......@@ -36,7 +36,7 @@ describe("threadRoutes", () => {
3636 });
3737
3838 it("builds canonical draft route params from a draft id", () => {
39 expect(buildDraftThreadRouteParams(DraftId.makeUnsafe("draft-1"))).toEqual({
39 expect(buildDraftThreadRouteParams(DraftId.make("draft-1"))).toEqual({
4040 draftId: "draft-1",
4141 });
4242 });
apps/web/src/threadSelectionStore.test.ts+6-6
......@@ -3,11 +3,11 @@ import { beforeEach, describe, expect, it } from "vitest";
33
44import { useThreadSelectionStore } from "./threadSelectionStore";
55
6const THREAD_A = ThreadId.makeUnsafe("thread-a");
7const THREAD_B = ThreadId.makeUnsafe("thread-b");
8const THREAD_C = ThreadId.makeUnsafe("thread-c");
9const THREAD_D = ThreadId.makeUnsafe("thread-d");
10const THREAD_E = ThreadId.makeUnsafe("thread-e");
6const THREAD_A = ThreadId.make("thread-a");
7const THREAD_B = ThreadId.make("thread-b");
8const THREAD_C = ThreadId.make("thread-c");
9const THREAD_D = ThreadId.make("thread-d");
10const THREAD_E = ThreadId.make("thread-e");
1111
1212const ORDERED = [THREAD_A, THREAD_B, THREAD_C, THREAD_D, THREAD_E] as const;
1313
......@@ -173,7 +173,7 @@ describe("threadSelectionStore", () => {
173173 it("falls back to toggle when target is not in the ordered list", () => {
174174 const store = useThreadSelectionStore.getState();
175175 store.toggleThread(THREAD_B); // anchor = B
176 const unknownThread = ThreadId.makeUnsafe("thread-unknown");
176 const unknownThread = ThreadId.make("thread-unknown");
177177 store.rangeSelectTo(unknownThread, ORDERED);
178178
179179 const state = useThreadSelectionStore.getState();
apps/web/src/uiStateStore.test.ts+17-17
......@@ -22,7 +22,7 @@ function makeUiState(overrides: Partial<UiState> = {}): UiState {
2222
2323describe("uiStateStore pure functions", () => {
2424 it("markThreadUnread moves lastVisitedAt before completion for a completed thread", () => {
25 const threadId = ThreadId.makeUnsafe("thread-1");
25 const threadId = ThreadId.make("thread-1");
2626 const latestTurnCompletedAt = "2026-02-25T12:30:00.000Z";
2727 const initialState = makeUiState({
2828 threadLastVisitedAtById: {
......@@ -36,7 +36,7 @@ describe("uiStateStore pure functions", () => {
3636 });
3737
3838 it("markThreadUnread does not change a thread without a completed turn", () => {
39 const threadId = ThreadId.makeUnsafe("thread-1");
39 const threadId = ThreadId.make("thread-1");
4040 const initialState = makeUiState({
4141 threadLastVisitedAtById: {
4242 [threadId]: "2026-02-25T12:35:00.000Z",
......@@ -49,9 +49,9 @@ describe("uiStateStore pure functions", () => {
4949 });
5050
5151 it("reorderProjects moves a project to a target index", () => {
52 const project1 = ProjectId.makeUnsafe("project-1");
53 const project2 = ProjectId.makeUnsafe("project-2");
54 const project3 = ProjectId.makeUnsafe("project-3");
52 const project1 = ProjectId.make("project-1");
53 const project2 = ProjectId.make("project-2");
54 const project3 = ProjectId.make("project-3");
5555 const initialState = makeUiState({
5656 projectOrder: [project1, project2, project3],
5757 });
......@@ -62,9 +62,9 @@ describe("uiStateStore pure functions", () => {
6262 });
6363
6464 it("syncProjects preserves current project order during snapshot recovery", () => {
65 const project1 = ProjectId.makeUnsafe("project-1");
66 const project2 = ProjectId.makeUnsafe("project-2");
67 const project3 = ProjectId.makeUnsafe("project-3");
65 const project1 = ProjectId.make("project-1");
66 const project2 = ProjectId.make("project-2");
67 const project3 = ProjectId.make("project-3");
6868 const initialState = makeUiState({
6969 projectExpandedById: {
7070 [project1]: true,
......@@ -84,9 +84,9 @@ describe("uiStateStore pure functions", () => {
8484 });
8585
8686 it("syncProjects preserves manual order when a project is recreated with the same cwd", () => {
87 const oldProject1 = ProjectId.makeUnsafe("project-1");
88 const oldProject2 = ProjectId.makeUnsafe("project-2");
89 const recreatedProject2 = ProjectId.makeUnsafe("project-2b");
87 const oldProject1 = ProjectId.make("project-1");
88 const oldProject2 = ProjectId.make("project-2");
89 const recreatedProject2 = ProjectId.make("project-2b");
9090 const initialState = syncProjects(
9191 makeUiState({
9292 projectExpandedById: {
......@@ -111,7 +111,7 @@ describe("uiStateStore pure functions", () => {
111111 });
112112
113113 it("syncProjects returns a new state when only project cwd changes", () => {
114 const project1 = ProjectId.makeUnsafe("project-1");
114 const project1 = ProjectId.make("project-1");
115115 const initialState = syncProjects(
116116 makeUiState({
117117 projectExpandedById: {
......@@ -130,8 +130,8 @@ describe("uiStateStore pure functions", () => {
130130 });
131131
132132 it("syncThreads prunes missing thread UI state", () => {
133 const thread1 = ThreadId.makeUnsafe("thread-1");
134 const thread2 = ThreadId.makeUnsafe("thread-2");
133 const thread1 = ThreadId.make("thread-1");
134 const thread2 = ThreadId.make("thread-2");
135135 const initialState = makeUiState({
136136 threadLastVisitedAtById: {
137137 [thread1]: "2026-02-25T12:35:00.000Z",
......@@ -147,7 +147,7 @@ describe("uiStateStore pure functions", () => {
147147 });
148148
149149 it("syncThreads seeds visit state for unseen snapshot threads", () => {
150 const thread1 = ThreadId.makeUnsafe("thread-1");
150 const thread1 = ThreadId.make("thread-1");
151151 const initialState = makeUiState();
152152
153153 const next = syncThreads(initialState, [
......@@ -163,7 +163,7 @@ describe("uiStateStore pure functions", () => {
163163 });
164164
165165 it("setProjectExpanded updates expansion without touching order", () => {
166 const project1 = ProjectId.makeUnsafe("project-1");
166 const project1 = ProjectId.make("project-1");
167167 const initialState = makeUiState({
168168 projectExpandedById: {
169169 [project1]: true,
......@@ -178,7 +178,7 @@ describe("uiStateStore pure functions", () => {
178178 });
179179
180180 it("clearThreadUi removes visit state for deleted threads", () => {
181 const thread1 = ThreadId.makeUnsafe("thread-1");
181 const thread1 = ThreadId.make("thread-1");
182182 const initialState = makeUiState({
183183 threadLastVisitedAtById: {
184184 [thread1]: "2026-02-25T12:35:00.000Z",
apps/web/src/worktreeCleanup.test.ts+12-12
......@@ -4,14 +4,14 @@ import { describe, expect, it } from "vitest";
44import { DEFAULT_INTERACTION_MODE, DEFAULT_RUNTIME_MODE, type Thread } from "./types";
55import { formatWorktreePathForDisplay, getOrphanedWorktreePathForThread } from "./worktreeCleanup";
66
7const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local");
7const localEnvironmentId = EnvironmentId.make("environment-local");
88
99function makeThread(overrides: Partial<Thread> = {}): Thread {
1010 return {
11 id: ThreadId.makeUnsafe("thread-1"),
11 id: ThreadId.make("thread-1"),
1212 environmentId: localEnvironmentId,
1313 codexThreadId: null,
14 projectId: ProjectId.makeUnsafe("project-1"),
14 projectId: ProjectId.make("project-1"),
1515 title: "Thread",
1616 modelSelection: {
1717 provider: "codex",
......@@ -36,49 +36,49 @@ function makeThread(overrides: Partial<Thread> = {}): Thread {
3636
3737describe("getOrphanedWorktreePathForThread", () => {
3838 it("returns null when the target thread does not exist", () => {
39 const result = getOrphanedWorktreePathForThread([], ThreadId.makeUnsafe("missing-thread"));
39 const result = getOrphanedWorktreePathForThread([], ThreadId.make("missing-thread"));
4040 expect(result).toBeNull();
4141 });
4242
4343 it("returns null when the target thread has no worktree", () => {
4444 const threads = [makeThread()];
45 const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1"));
45 const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1"));
4646 expect(result).toBeNull();
4747 });
4848
4949 it("returns the path when no other thread links to that worktree", () => {
5050 const threads = [makeThread({ worktreePath: "/tmp/repo/worktrees/feature-a" })];
51 const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1"));
51 const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1"));
5252 expect(result).toBe("/tmp/repo/worktrees/feature-a");
5353 });
5454
5555 it("returns null when another thread links to the same worktree", () => {
5656 const threads = [
5757 makeThread({
58 id: ThreadId.makeUnsafe("thread-1"),
58 id: ThreadId.make("thread-1"),
5959 worktreePath: "/tmp/repo/worktrees/feature-a",
6060 }),
6161 makeThread({
62 id: ThreadId.makeUnsafe("thread-2"),
62 id: ThreadId.make("thread-2"),
6363 worktreePath: "/tmp/repo/worktrees/feature-a",
6464 }),
6565 ];
66 const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1"));
66 const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1"));
6767 expect(result).toBeNull();
6868 });
6969
7070 it("ignores threads linked to different worktrees", () => {
7171 const threads = [
7272 makeThread({
73 id: ThreadId.makeUnsafe("thread-1"),
73 id: ThreadId.make("thread-1"),
7474 worktreePath: "/tmp/repo/worktrees/feature-a",
7575 }),
7676 makeThread({
77 id: ThreadId.makeUnsafe("thread-2"),
77 id: ThreadId.make("thread-2"),
7878 worktreePath: "/tmp/repo/worktrees/feature-b",
7979 }),
8080 ];
81 const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1"));
81 const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1"));
8282 expect(result).toBe("/tmp/repo/worktrees/feature-a");
8383 });
8484});
apps/web/test/authHttpHandlers.ts+1-1
......@@ -7,7 +7,7 @@ import { HttpResponse, http } from "msw";
77
88const TEST_SESSION_EXPIRES_AT = "2026-05-01T12:00:00.000Z";
99const TEST_ENVIRONMENT_DESCRIPTOR: ExecutionEnvironmentDescriptor = {
10 environmentId: EnvironmentId.makeUnsafe("environment-local"),
10 environmentId: EnvironmentId.make("environment-local"),
1111 label: "Local environment",
1212 platform: {
1313 os: "darwin",
bun.lock+14-14
......@@ -189,16 +189,16 @@
189189 "vite": "^8.0.0",
190190 },
191191 "catalog": {
192 "@effect/atom-react": "4.0.0-beta.43",
192 "@effect/atom-react": "4.0.0-beta.45",
193193 "@effect/language-service": "0.84.2",
194 "@effect/platform-bun": "4.0.0-beta.43",
195 "@effect/platform-node": "4.0.0-beta.43",
196 "@effect/platform-node-shared": "4.0.0-beta.43",
197 "@effect/sql-sqlite-bun": "4.0.0-beta.43",
198 "@effect/vitest": "4.0.0-beta.43",
194 "@effect/platform-bun": "4.0.0-beta.45",
195 "@effect/platform-node": "4.0.0-beta.45",
196 "@effect/platform-node-shared": "4.0.0-beta.45",
197 "@effect/sql-sqlite-bun": "4.0.0-beta.45",
198 "@effect/vitest": "4.0.0-beta.45",
199199 "@types/bun": "^1.3.9",
200200 "@types/node": "^24.10.13",
201 "effect": "4.0.0-beta.43",
201 "effect": "4.0.0-beta.45",
202202 "tsdown": "^0.20.3",
203203 "typescript": "^5.7.3",
204204 "vitest": "^4.0.0",
......@@ -284,19 +284,19 @@
284284
285285 "@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="],
286286
287 "@effect/atom-react": ["@effect/atom-react@4.0.0-beta.43", "", { "peerDependencies": { "effect": "^4.0.0-beta.43", "react": "^19.2.4", "scheduler": "*" } }, "sha512-xSrRbGXuo4d0g4ph66TQST1GNSjtQZrZj8V7OiAQFuzMYcZ0kwRIPUUFwOBtbWHK43/zNENdNWOnlXh/iYM1dw=="],
287 "@effect/atom-react": ["@effect/atom-react@4.0.0-beta.45", "", { "peerDependencies": { "effect": "^4.0.0-beta.45", "react": "^19.2.4", "scheduler": "*" } }, "sha512-jCoiae9UNeis9Yoal1p5V/P4eJK9nX89wORom7X5LpR2Ok920SZJc8dIeYkRXRAp9BCYJ/yWcO8gGLf7do71vg=="],
288288
289289 "@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="],
290290
291 "@effect/platform-bun": ["@effect/platform-bun@4.0.0-beta.43", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.43" }, "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-nMZ9JsD6CzJNQ+5pDUFbPw7PSZdQdTQ092MbYrocVtvlf6qEFU/hji3ITvRIOX7eabyQ8AUyp55qFPQUeq+GIA=="],
291 "@effect/platform-bun": ["@effect/platform-bun@4.0.0-beta.45", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.45" }, "peerDependencies": { "effect": "^4.0.0-beta.45" } }, "sha512-dZsbkJ+o4JfKE1OIAlMq8YWhmEfXxtTYennYADK/M/XlOtkFLsc2jkZppDvMznVni6JpFxWc7wd5rUf8jBVP5g=="],
292292
293 "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.43", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.43", "mime": "^4.1.0", "undici": "^7.24.0" }, "peerDependencies": { "effect": "^4.0.0-beta.43", "ioredis": "^5.7.0" } }, "sha512-Uq6E1rjaIpjHauzjwoB2HzAg3battYt2Boy8XO50GoHiWCXKE6WapYZ0/AnaBx5v5qg2sOfqpuiLsUf9ZgxOkA=="],
293 "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.45", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.45", "mime": "^4.1.0", "undici": "^7.24.0" }, "peerDependencies": { "effect": "^4.0.0-beta.45", "ioredis": "^5.7.0" } }, "sha512-P07NMG4eoy62iLX9szak0hkr7hrwgq5+XMkm7URVug/3zqfZVxEG2kxn9JzVK1lF5WbaVrEKwjt3IkEJxzSPtg=="],
294294
295 "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.43", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-A9q0GEb61pYcQ06Dr6gXj1nKlDI3KHsar1sk3qb1ZY+kVSR64tBAylI8zGon23KY+NPtTUj/sEIToB7jc3Qt5w=="],
295 "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.45", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.45" } }, "sha512-0T4RG18o+aCVUSlmPxA7uAjHJkyE3MS/uRrR5kCNSZQNG3X71wdIbu82wE/MnV6+6YSSPDx/6TVdZWYkJF0JWw=="],
296296
297 "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.43", "", { "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-Ryb7x0rBjW5NHegbzvz9y2Yv4KpwZ1UiPk7/Rv+Mkux74Qkjdmotmrvy9P+M5A9TZyL2Av+GpaLTPJKsL0PG+Q=="],
297 "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.45", "", { "peerDependencies": { "effect": "^4.0.0-beta.45" } }, "sha512-sJBBztwI4YxjdjhdyjWelh3KKoZucmmZS2ONeNDIzYgqFlsrwEEUrhVkWf5ch9Io+kUUzeb6q7/SedFoLUWO7g=="],
298298
299 "@effect/vitest": ["@effect/vitest@4.0.0-beta.43", "", { "peerDependencies": { "effect": "^4.0.0-beta.43", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-XN2LAwiUWPqbV2jrsYYRjrVydQ8MIgwr83MVImtUaOQco4vk43+8OHlXQMRN/u2HnGK29KT+O2yTMMBdk2Q6Sw=="],
299 "@effect/vitest": ["@effect/vitest@4.0.0-beta.45", "", { "peerDependencies": { "effect": "^4.0.0-beta.45", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-38JA5Z6c2FoEhpVKbl7rjTrMU8Al5T30Kwtb6N3B9kOkyr2SsmvNsP9T65bh03IBh3ak9U//acrkmjS3hLQwKA=="],
300300
301301 "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="],
302302
......@@ -1018,7 +1018,7 @@
10181018
10191019 "dts-resolver": ["dts-resolver@2.1.3", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw=="],
10201020
1021 "effect": ["effect@4.0.0-beta.43", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ=="],
1021 "effect": ["effect@4.0.0-beta.45", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-vvNrUWqnzBIW1hRMa+zw0CLRW6HLgdu7hQ6K7PT/rS+UY/73Ma11O+Oi9oc9zwL8KcN37M47UDseAdlF0bGNWw=="],
10221022
10231023 "electron": ["electron@40.6.0", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-ett8W+yOFGDuM0vhJMamYSkrbV3LoaffzJd9GfjI96zRAxyrNqUSKqBpf/WGbQCweDxX2pkUCUfrv4wwKpsFZA=="],
10241024
package.json+7-7
......@@ -8,13 +8,13 @@
88 "scripts"
99 ],
1010 "catalog": {
11 "effect": "4.0.0-beta.43",
12 "@effect/atom-react": "4.0.0-beta.43",
13 "@effect/platform-bun": "4.0.0-beta.43",
14 "@effect/platform-node": "4.0.0-beta.43",
15 "@effect/platform-node-shared": "4.0.0-beta.43",
16 "@effect/sql-sqlite-bun": "4.0.0-beta.43",
17 "@effect/vitest": "4.0.0-beta.43",
11 "effect": "4.0.0-beta.45",
12 "@effect/atom-react": "4.0.0-beta.45",
13 "@effect/platform-bun": "4.0.0-beta.45",
14 "@effect/platform-node": "4.0.0-beta.45",
15 "@effect/platform-node-shared": "4.0.0-beta.45",
16 "@effect/sql-sqlite-bun": "4.0.0-beta.45",
17 "@effect/vitest": "4.0.0-beta.45",
1818 "@effect/language-service": "0.84.2",
1919 "@types/bun": "^1.3.9",
2020 "@types/node": "^24.10.13",
packages/client-runtime/src/knownEnvironment.test.ts+5-5
......@@ -61,9 +61,9 @@ describe("known environment bootstrap helpers", () => {
6161});
6262
6363describe("scoped refs", () => {
64 const environmentId = EnvironmentId.makeUnsafe("environment-test");
65 const projectRef = scopeProjectRef(environmentId, ProjectId.makeUnsafe("project-1"));
66 const threadRef = scopeThreadRef(environmentId, ThreadId.makeUnsafe("thread-1"));
64 const environmentId = EnvironmentId.make("environment-test");
65 const projectRef = scopeProjectRef(environmentId, ProjectId.make("project-1"));
66 const threadRef = scopeThreadRef(environmentId, ThreadId.make("thread-1"));
6767
6868 it("builds stable scoped project and thread keys", () => {
6969 expect(scopedRefKey(projectRef)).toBe("environment-test:project-1");
......@@ -75,11 +75,11 @@ describe("scoped refs", () => {
7575 it("returns typed scoped refs", () => {
7676 expect(projectRef).toEqual({
7777 environmentId,
78 projectId: ProjectId.makeUnsafe("project-1"),
78 projectId: ProjectId.make("project-1"),
7979 });
8080 expect(threadRef).toEqual({
8181 environmentId,
82 threadId: ThreadId.makeUnsafe("thread-1"),
82 threadId: ThreadId.make("thread-1"),
8383 });
8484 });
8585
packages/contracts/src/baseSchemas.ts+3-2
......@@ -12,8 +12,9 @@ export type IsoDateTime = typeof IsoDateTime.Type;
1212/**
1313 * Construct a branded identifier. Enforces non-empty trimmed strings
1414 */
15const makeEntityId = <Brand extends string>(brand: Brand) =>
16 TrimmedNonEmptyString.pipe(Schema.brand(brand));
15const makeEntityId = <Brand extends string>(brand: Brand) => {
16 return TrimmedNonEmptyString.pipe(Schema.brand(brand));
17};
1718
1819export const ThreadId = makeEntityId("ThreadId");
1920export type ThreadId = typeof ThreadId.Type;
packages/contracts/src/environment.ts+2-2
......@@ -1,4 +1,4 @@
1import { Schema } from "effect";
1import { Effect, Schema } from "effect";
22
33import { EnvironmentId, ProjectId, ThreadId, TrimmedNonEmptyString } from "./baseSchemas";
44
......@@ -20,7 +20,7 @@ export const ExecutionEnvironmentPlatform = Schema.Struct({
2020export type ExecutionEnvironmentPlatform = typeof ExecutionEnvironmentPlatform.Type;
2121
2222export const ExecutionEnvironmentCapabilities = Schema.Struct({
23 repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)),
23 repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
2424});
2525export type ExecutionEnvironmentCapabilities = typeof ExecutionEnvironmentCapabilities.Type;
2626
packages/contracts/src/orchestration.ts+19-15
......@@ -1,4 +1,4 @@
1import { Option, Schema, SchemaIssue, Struct } from "effect";
1import { Effect, Option, Schema, SchemaIssue, Struct } from "effect";
22import { ClaudeModelOptions, CodexModelOptions } from "./model";
33import { RepositoryIdentity } from "./environment";
44import {
......@@ -177,8 +177,10 @@ export const OrchestrationProposedPlan = Schema.Struct({
177177 id: OrchestrationProposedPlanId,
178178 turnId: Schema.NullOr(TurnId),
179179 planMarkdown: TrimmedNonEmptyString,
180 implementedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(() => null)),
181 implementationThreadId: Schema.NullOr(ThreadId).pipe(Schema.withDecodingDefault(() => null)),
180 implementedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))),
181 implementationThreadId: Schema.NullOr(ThreadId).pipe(
182 Schema.withDecodingDefault(Effect.succeed(null)),
183 ),
182184 createdAt: IsoDateTime,
183185 updatedAt: IsoDateTime,
184186});
......@@ -204,7 +206,7 @@ export const OrchestrationSession = Schema.Struct({
204206 threadId: ThreadId,
205207 status: OrchestrationSessionStatus,
206208 providerName: Schema.NullOr(TrimmedNonEmptyString),
207 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)),
209 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))),
208210 activeTurnId: Schema.NullOr(TurnId),
209211 lastError: Schema.NullOr(TrimmedNonEmptyString),
210212 updatedAt: IsoDateTime,
......@@ -279,17 +281,19 @@ export const OrchestrationThread = Schema.Struct({
279281 modelSelection: ModelSelection,
280282 runtimeMode: RuntimeMode,
281283 interactionMode: ProviderInteractionMode.pipe(
282 Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE),
284 Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),
283285 ),
284286 branch: Schema.NullOr(TrimmedNonEmptyString),
285287 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
286288 latestTurn: Schema.NullOr(OrchestrationLatestTurn),
287289 createdAt: IsoDateTime,
288290 updatedAt: IsoDateTime,
289 archivedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(() => null)),
291 archivedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))),
290292 deletedAt: Schema.NullOr(IsoDateTime),
291293 messages: Schema.Array(OrchestrationMessage),
292 proposedPlans: Schema.Array(OrchestrationProposedPlan).pipe(Schema.withDecodingDefault(() => [])),
294 proposedPlans: Schema.Array(OrchestrationProposedPlan).pipe(
295 Schema.withDecodingDefault(Effect.succeed([])),
296 ),
293297 activities: Schema.Array(OrchestrationThreadActivity),
294298 checkpoints: Schema.Array(OrchestrationCheckpointSummary),
295299 session: Schema.NullOr(OrchestrationSession),
......@@ -339,7 +343,7 @@ const ThreadCreateCommand = Schema.Struct({
339343 modelSelection: ModelSelection,
340344 runtimeMode: RuntimeMode,
341345 interactionMode: ProviderInteractionMode.pipe(
342 Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE),
346 Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),
343347 ),
344348 branch: Schema.NullOr(TrimmedNonEmptyString),
345349 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
......@@ -427,9 +431,9 @@ export const ThreadTurnStartCommand = Schema.Struct({
427431 }),
428432 modelSelection: Schema.optional(ModelSelection),
429433 titleSeed: Schema.optional(TrimmedNonEmptyString),
430 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)),
434 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))),
431435 interactionMode: ProviderInteractionMode.pipe(
432 Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE),
436 Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),
433437 ),
434438 bootstrap: Schema.optional(ThreadTurnStartBootstrap),
435439 sourceProposedPlan: Schema.optional(SourceProposedPlanReference),
......@@ -680,9 +684,9 @@ export const ThreadCreatedPayload = Schema.Struct({
680684 projectId: ProjectId,
681685 title: TrimmedNonEmptyString,
682686 modelSelection: ModelSelection,
683 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)),
687 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))),
684688 interactionMode: ProviderInteractionMode.pipe(
685 Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE),
689 Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),
686690 ),
687691 branch: Schema.NullOr(TrimmedNonEmptyString),
688692 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
......@@ -724,7 +728,7 @@ export const ThreadRuntimeModeSetPayload = Schema.Struct({
724728export const ThreadInteractionModeSetPayload = Schema.Struct({
725729 threadId: ThreadId,
726730 interactionMode: ProviderInteractionMode.pipe(
727 Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE),
731 Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),
728732 ),
729733 updatedAt: IsoDateTime,
730734});
......@@ -746,9 +750,9 @@ export const ThreadTurnStartRequestedPayload = Schema.Struct({
746750 messageId: MessageId,
747751 modelSelection: Schema.optional(ModelSelection),
748752 titleSeed: Schema.optional(TrimmedNonEmptyString),
749 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)),
753 runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))),
750754 interactionMode: ProviderInteractionMode.pipe(
751 Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE),
755 Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),
752756 ),
753757 sourceProposedPlan: Schema.optional(SourceProposedPlanReference),
754758 createdAt: IsoDateTime,
packages/contracts/src/providerRuntime.ts+2-2
......@@ -1,4 +1,4 @@
1import { Option, Schema } from "effect";
1import { Effect, Schema } from "effect";
22import {
33 EventId,
44 IsoDateTime,
......@@ -435,7 +435,7 @@ export const UserInputQuestion = Schema.Struct({
435435 question: TrimmedNonEmptyStringSchema,
436436 options: Schema.Array(UserInputQuestionOption),
437437 multiSelect: Schema.optional(Schema.Boolean).pipe(
438 Schema.withConstructorDefault(() => Option.some(false)),
438 Schema.withConstructorDefault(Effect.succeed(false)),
439439 ),
440440});
441441export type UserInputQuestion = typeof UserInputQuestion.Type;
packages/contracts/src/settings.ts+28-24
......@@ -24,16 +24,18 @@ export type SidebarThreadSortOrder = typeof SidebarThreadSortOrder.Type;
2424export const DEFAULT_SIDEBAR_THREAD_SORT_ORDER: SidebarThreadSortOrder = "updated_at";
2525
2626export const ClientSettingsSchema = Schema.Struct({
27 confirmThreadArchive: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)),
28 confirmThreadDelete: Schema.Boolean.pipe(Schema.withDecodingDefault(() => true)),
29 diffWordWrap: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)),
27 confirmThreadArchive: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
28 confirmThreadDelete: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),
29 diffWordWrap: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
3030 sidebarProjectSortOrder: SidebarProjectSortOrder.pipe(
31 Schema.withDecodingDefault(() => DEFAULT_SIDEBAR_PROJECT_SORT_ORDER),
31 Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_PROJECT_SORT_ORDER)),
3232 ),
3333 sidebarThreadSortOrder: SidebarThreadSortOrder.pipe(
34 Schema.withDecodingDefault(() => DEFAULT_SIDEBAR_THREAD_SORT_ORDER),
34 Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_THREAD_SORT_ORDER)),
35 ),
36 timestampFormat: TimestampFormat.pipe(
37 Schema.withDecodingDefault(Effect.succeed(DEFAULT_TIMESTAMP_FORMAT)),
3538 ),
36 timestampFormat: TimestampFormat.pipe(Schema.withDecodingDefault(() => DEFAULT_TIMESTAMP_FORMAT)),
3739});
3840export type ClientSettings = typeof ClientSettingsSchema.Type;
3941
......@@ -53,48 +55,50 @@ const makeBinaryPathSetting = (fallback: string) =>
5355 encode: (value) => Effect.succeed(value),
5456 }),
5557 ),
56 Schema.withDecodingDefault(() => fallback),
58 Schema.withDecodingDefault(Effect.succeed(fallback)),
5759 );
5860
5961export const CodexSettings = Schema.Struct({
60 enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(() => true)),
62 enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),
6163 binaryPath: makeBinaryPathSetting("codex"),
62 homePath: TrimmedString.pipe(Schema.withDecodingDefault(() => "")),
63 customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(() => [])),
64 homePath: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))),
65 customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
6466});
6567export type CodexSettings = typeof CodexSettings.Type;
6668
6769export const ClaudeSettings = Schema.Struct({
68 enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(() => true)),
70 enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),
6971 binaryPath: makeBinaryPathSetting("claude"),
70 customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(() => [])),
72 customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
7173});
7274export type ClaudeSettings = typeof ClaudeSettings.Type;
7375
7476export const ObservabilitySettings = Schema.Struct({
75 otlpTracesUrl: TrimmedString.pipe(Schema.withDecodingDefault(() => "")),
76 otlpMetricsUrl: TrimmedString.pipe(Schema.withDecodingDefault(() => "")),
77 otlpTracesUrl: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))),
78 otlpMetricsUrl: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))),
7779});
7880export type ObservabilitySettings = typeof ObservabilitySettings.Type;
7981
8082export const ServerSettings = Schema.Struct({
81 enableAssistantStreaming: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)),
83 enableAssistantStreaming: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
8284 defaultThreadEnvMode: ThreadEnvMode.pipe(
83 Schema.withDecodingDefault(() => "local" as const satisfies ThreadEnvMode),
85 Schema.withDecodingDefault(Effect.succeed("local" as const satisfies ThreadEnvMode)),
8486 ),
8587 textGenerationModelSelection: ModelSelection.pipe(
86 Schema.withDecodingDefault(() => ({
87 provider: "codex" as const,
88 model: DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER.codex,
89 })),
88 Schema.withDecodingDefault(
89 Effect.succeed({
90 provider: "codex" as const,
91 model: DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER.codex,
92 }),
93 ),
9094 ),
9195
9296 // Provider specific settings
9397 providers: Schema.Struct({
94 codex: CodexSettings.pipe(Schema.withDecodingDefault(() => ({}))),
95 claudeAgent: ClaudeSettings.pipe(Schema.withDecodingDefault(() => ({}))),
96 }).pipe(Schema.withDecodingDefault(() => ({}))),
97 observability: ObservabilitySettings.pipe(Schema.withDecodingDefault(() => ({}))),
98 codex: CodexSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))),
99 claudeAgent: ClaudeSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))),
100 }).pipe(Schema.withDecodingDefault(Effect.succeed({}))),
101 observability: ObservabilitySettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))),
98102});
99103export type ServerSettings = typeof ServerSettings.Type;
100104
packages/contracts/src/terminal.ts+2-2
......@@ -1,4 +1,4 @@
1import { Schema } from "effect";
1import { Effect, Schema } from "effect";
22import { TrimmedNonEmptyString } from "./baseSchemas";
33
44export const DEFAULT_TERMINAL_ID = "default";
......@@ -20,7 +20,7 @@ const TerminalEnvSchema = Schema.Record(TerminalEnvKeySchema, TerminalEnvValueSc
2020);
2121
2222const TerminalIdWithDefaultSchema = TerminalIdSchema.pipe(
23 Schema.withDecodingDefault(() => DEFAULT_TERMINAL_ID),
23 Schema.withDecodingDefault(Effect.succeed(DEFAULT_TERMINAL_ID)),
2424);
2525
2626export const TerminalThreadInput = Schema.Struct({
packages/shared/src/Net.ts+2-2
......@@ -1,6 +1,6 @@
11import * as Net from "node:net";
22
3import { Data, Effect, Layer, ServiceMap } from "effect";
3import { Data, Effect, Layer, Context } from "effect";
44
55export class NetError extends Data.TaggedError("NetError")<{
66 readonly message: string;
......@@ -85,7 +85,7 @@ export interface NetServiceShape {
8585/**
8686 * NetService - Service tag for startup networking helpers.
8787 */
88export class NetService extends ServiceMap.Service<NetService, NetServiceShape>()(
88export class NetService extends Context.Service<NetService, NetServiceShape>()(
8989 "@t3tools/shared/Net/NetService",
9090) {
9191 static readonly layer = Layer.sync(NetService, () => {
scripts/build-desktop-artifact.test.ts created+45
......@@ -0,0 +1,45 @@
1import * as NodeServices from "@effect/platform-node/NodeServices";
2import { assert, it } from "@effect/vitest";
3import { ConfigProvider, Effect, Option } from "effect";
4
5import { resolveBuildOptions } from "./build-desktop-artifact.ts";
6
7it.layer(NodeServices.layer)("build-desktop-artifact", (it) => {
8 it.effect("preserves explicit false boolean flags over true env defaults", () =>
9 Effect.gen(function* () {
10 const resolved = yield* resolveBuildOptions({
11 platform: Option.some("mac"),
12 target: Option.none(),
13 arch: Option.some("arm64"),
14 buildVersion: Option.none(),
15 outputDir: Option.some("release-test"),
16 skipBuild: Option.some(false),
17 keepStage: Option.some(false),
18 signed: Option.some(false),
19 verbose: Option.some(false),
20 mockUpdates: Option.some(false),
21 mockUpdateServerPort: Option.none(),
22 }).pipe(
23 Effect.provide(
24 ConfigProvider.layer(
25 ConfigProvider.fromEnv({
26 env: {
27 T3CODE_DESKTOP_SKIP_BUILD: "true",
28 T3CODE_DESKTOP_KEEP_STAGE: "true",
29 T3CODE_DESKTOP_SIGNED: "true",
30 T3CODE_DESKTOP_VERBOSE: "true",
31 T3CODE_DESKTOP_MOCK_UPDATES: "true",
32 },
33 }),
34 ),
35 ),
36 );
37
38 assert.equal(resolved.skipBuild, false);
39 assert.equal(resolved.keepStage, false);
40 assert.equal(resolved.signed, false);
41 assert.equal(resolved.verbose, false);
42 assert.equal(resolved.mockUpdates, false);
43 }),
44 );
45});
scripts/build-desktop-artifact.ts+11-7
......@@ -214,11 +214,13 @@ const BuildEnvConfig = Config.all({
214214});
215215
216216const resolveBooleanFlag = (flag: Option.Option<boolean>, envValue: boolean) =>
217 Option.getOrElse(Option.filter(flag, Boolean), () => envValue);
217 Option.getOrElse(flag, () => envValue);
218218const mergeOptions = <A>(a: Option.Option<A>, b: Option.Option<A>, defaultValue: A) =>
219219 Option.getOrElse(a, () => Option.getOrElse(b, () => defaultValue));
220220
221const resolveBuildOptions = Effect.fn("resolveBuildOptions")(function* (input: BuildCliInput) {
221export const resolveBuildOptions = Effect.fn("resolveBuildOptions")(function* (
222 input: BuildCliInput,
223) {
222224 const path = yield* Path.Path;
223225 const repoRoot = yield* RepoRoot;
224226 const env = yield* BuildEnvConfig.asEffect();
......@@ -838,8 +840,10 @@ const buildDesktopArtifactCli = Command.make("build-desktop-artifact", {
838840
839841const cliRuntimeLayer = Layer.mergeAll(Logger.layer([Logger.consolePretty()]), NodeServices.layer);
840842
841Command.run(buildDesktopArtifactCli, { version: "0.0.0" }).pipe(
842 Effect.scoped,
843 Effect.provide(cliRuntimeLayer),
844 NodeRuntime.runMain,
845);
843if (import.meta.main) {
844 Command.run(buildDesktopArtifactCli, { version: "0.0.0" }).pipe(
845 Effect.scoped,
846 Effect.provide(cliRuntimeLayer),
847 NodeRuntime.runMain,
848 );
849}
scripts/dev-runner.test.ts+3-1
......@@ -121,7 +121,9 @@ it.layer(NodeServices.layer)("dev-runner", (it) => {
121121 Effect.gen(function* () {
122122 const env = yield* createDevRunnerEnv({
123123 mode: "dev",
124 baseEnv: {},
124 baseEnv: {
125 T3CODE_LOG_WS_EVENTS: "1",
126 },
125127 serverOffset: 0,
126128 webOffset: 0,
127129 t3Home: undefined,
scripts/dev-runner.ts+3-44
......@@ -356,35 +356,6 @@ interface DevRunnerCliInput {
356356 readonly turboArgs: ReadonlyArray<string>;
357357}
358358
359const readOptionalBooleanEnv = (name: string): boolean | undefined => {
360 const value = process.env[name];
361 if (value === undefined) {
362 return undefined;
363 }
364 if (value === "1" || value.toLowerCase() === "true") {
365 return true;
366 }
367 if (value === "0" || value.toLowerCase() === "false") {
368 return false;
369 }
370 return undefined;
371};
372
373const resolveOptionalBooleanOverride = (
374 explicitValue: boolean | undefined,
375 envValue: boolean | undefined,
376): boolean | undefined => {
377 if (explicitValue === true) {
378 return true;
379 }
380
381 if (explicitValue === false) {
382 return envValue;
383 }
384
385 return envValue;
386};
387
388359export function runDevRunnerWithInput(input: DevRunnerCliInput) {
389360 return Effect.gen(function* () {
390361 const { portOffset, devInstance } = yield* OffsetConfig.asEffect().pipe(
......@@ -406,12 +377,6 @@ export function runDevRunnerWithInput(input: DevRunnerCliInput) {
406377 }),
407378 });
408379
409 const envOverrides = {
410 noBrowser: readOptionalBooleanEnv("T3CODE_NO_BROWSER"),
411 autoBootstrapProjectFromCwd: readOptionalBooleanEnv("T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD"),
412 logWebSocketEvents: readOptionalBooleanEnv("T3CODE_LOG_WS_EVENTS"),
413 };
414
415380 const { serverOffset, webOffset } = yield* resolveModePortOffsets({
416381 mode: input.mode,
417382 startOffset: offset,
......@@ -425,15 +390,9 @@ export function runDevRunnerWithInput(input: DevRunnerCliInput) {
425390 serverOffset,
426391 webOffset,
427392 t3Home: input.t3Home,
428 noBrowser: resolveOptionalBooleanOverride(input.noBrowser, envOverrides.noBrowser),
429 autoBootstrapProjectFromCwd: resolveOptionalBooleanOverride(
430 input.autoBootstrapProjectFromCwd,
431 envOverrides.autoBootstrapProjectFromCwd,
432 ),
433 logWebSocketEvents: resolveOptionalBooleanOverride(
434 input.logWebSocketEvents,
435 envOverrides.logWebSocketEvents,
436 ),
393 noBrowser: input.noBrowser,
394 autoBootstrapProjectFromCwd: input.autoBootstrapProjectFromCwd,
395 logWebSocketEvents: input.logWebSocketEvents,
437396 host: input.host,
438397 port: input.port,
439398 devUrl: input.devUrl,