import { assert, it } from "@effect/vitest";import { ContextTransferId, MessageId, type ModelSelection, type OrchestrationV2AppThread, type OrchestrationV2Run, type OrchestrationV2ThreadProjection, ProjectId, ProviderInstanceId, ProviderThreadId, RunId, ThreadId,} from "@t3tools/contracts";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect"; import { layer, ThreadForkServiceV2 } from "./ThreadForkService.ts"; const sourceThreadId = ThreadId.make("thread:fork-snoozed-source");const targetThreadId = ThreadId.make("thread:fork-awake-target");const sourceRunId = RunId.make("run:fork-snoozed-source");const providerInstanceId = ProviderInstanceId.make("codex");const modelSelection = { instanceId: providerInstanceId, model: "gpt-5.4",} satisfies ModelSelection;const sourceCreatedAt = DateTime.makeUnsafe("2026-07-24T09:00:00.000Z");const snoozedAt = DateTime.makeUnsafe("2026-07-24T09:05:00.000Z");const snoozedUntil = DateTime.makeUnsafe("2026-07-25T09:00:00.000Z");const forkCreatedAt = DateTime.makeUnsafe("2026-07-24T09:10:00.000Z"); function makeSourceThread(): OrchestrationV2AppThread { return { createdBy: "user", creationSource: "web", id: sourceThreadId, projectId: ProjectId.make("project:fork-snooze"), title: "Snoozed source", providerInstanceId, modelSelection, runtimeMode: "full-access", interactionMode: "plan", branch: "feature/source", worktreePath: "/tmp/source-worktree", activeProviderThreadId: ProviderThreadId.make("provider-thread:fork-snoozed-source"), lineage: { parentThreadId: null, relationshipToParent: null, rootThreadId: sourceThreadId, }, forkedFrom: null, createdAt: sourceCreatedAt, updatedAt: snoozedAt, archivedAt: null, settledOverride: null, settledAt: null, lastVisitedAt: null, snoozedUntil, snoozedAt, deletedAt: null, };} function makeCompletedSourceRun(): OrchestrationV2Run { return { id: sourceRunId, threadId: sourceThreadId, ordinal: 1, providerInstanceId, modelSelection, providerThreadId: ProviderThreadId.make("provider-thread:fork-snoozed-source"), userMessageId: MessageId.make("message:fork-snoozed-source"), rootNodeId: null, activeAttemptId: null, status: "completed", queuePosition: null, requestedAt: sourceCreatedAt, startedAt: sourceCreatedAt, completedAt: snoozedAt, checkpointId: null, contextHandoffId: null, };} it.effect("keeps a fork awake when its source thread is snoozed", () => Effect.gen(function* () { const sourceThread = makeSourceThread(); const sourceRun = makeCompletedSourceRun(); const sourceProjection: OrchestrationV2ThreadProjection = { thread: sourceThread, runs: [sourceRun], attempts: [], nodes: [], subagents: [], providerSessions: [], providerThreads: [], providerTurns: [], runtimeRequests: [], messages: [], plans: [], turnItems: [], checkpointScopes: [], checkpoints: [], contextHandoffs: [], contextTransfers: [], visibleTurnItems: [], updatedAt: snoozedAt, }; const service = yield* ThreadForkServiceV2; const result = yield* service.plan({ sourceProjection, sourceRun, sourceProviderThread: undefined, canonicalSourcePoint: { threadId: sourceThreadId, runId: sourceRunId, }, transferId: ContextTransferId.make("context-transfer:fork-snoozed-source"), targetThreadId, title: "Awake fork", createdBy: "user", creationSource: "mobile", createdAt: forkCreatedAt, }); assert.isNull(result.targetThread.snoozedUntil); assert.isNull(result.targetThread.snoozedAt); assert.equal(result.targetThread.projectId, sourceThread.projectId); assert.equal(result.targetThread.providerInstanceId, sourceThread.providerInstanceId); assert.deepEqual(result.targetThread.modelSelection, sourceThread.modelSelection); assert.equal(result.targetThread.runtimeMode, sourceThread.runtimeMode); assert.equal(result.targetThread.interactionMode, sourceThread.interactionMode); assert.equal(result.targetThread.branch, sourceThread.branch); assert.equal(result.targetThread.worktreePath, sourceThread.worktreePath); assert.isNull(result.targetThread.activeProviderThreadId); assert.deepEqual(result.targetThread.lineage, { parentThreadId: sourceThreadId, relationshipToParent: "fork", rootThreadId: sourceThreadId, }); assert.deepEqual(result.targetThread.forkedFrom, { type: "run", threadId: sourceThreadId, runId: sourceRunId, }); }).pipe(Effect.provide(layer)),);
import { assert, it } from "@effect/vitest";
import {
ContextTransferId,
MessageId,
type ModelSelection,
type OrchestrationV2AppThread,
type OrchestrationV2Run,
type OrchestrationV2ThreadProjection,
ProjectId,
ProviderInstanceId,
ProviderThreadId,
RunId,
ThreadId,
} from "@t3tools/contracts";
import * as DateTime from "effect/DateTime";
import * as Effect from "effect/Effect";
import { layer, ThreadForkServiceV2 } from "./ThreadForkService.ts";
const sourceThreadId = ThreadId.make("thread:fork-snoozed-source");
const targetThreadId = ThreadId.make("thread:fork-awake-target");
const sourceRunId = RunId.make("run:fork-snoozed-source");
const providerInstanceId = ProviderInstanceId.make("codex");
const modelSelection = {
instanceId: providerInstanceId,
model: "gpt-5.4",
} satisfies ModelSelection;
const sourceCreatedAt = DateTime.makeUnsafe("2026-07-24T09:00:00.000Z");
const snoozedAt = DateTime.makeUnsafe("2026-07-24T09:05:00.000Z");
const snoozedUntil = DateTime.makeUnsafe("2026-07-25T09:00:00.000Z");
const forkCreatedAt = DateTime.makeUnsafe("2026-07-24T09:10:00.000Z");
function makeSourceThread(): OrchestrationV2AppThread {
return {
createdBy: "user",
creationSource: "web",
id: sourceThreadId,
projectId: ProjectId.make("project:fork-snooze"),
title: "Snoozed source",
providerInstanceId,
modelSelection,
runtimeMode: "full-access",
interactionMode: "plan",
branch: "feature/source",
worktreePath: "/tmp/source-worktree",
activeProviderThreadId: ProviderThreadId.make("provider-thread:fork-snoozed-source"),
lineage: {
parentThreadId: null,
relationshipToParent: null,
rootThreadId: sourceThreadId,
},
forkedFrom: null,
createdAt: sourceCreatedAt,
updatedAt: snoozedAt,
archivedAt: null,
settledOverride: null,
settledAt: null,
lastVisitedAt: null,
snoozedUntil,
snoozedAt,
deletedAt: null,
};
}
function makeCompletedSourceRun(): OrchestrationV2Run {
return {
id: sourceRunId,
threadId: sourceThreadId,
ordinal: 1,
providerInstanceId,
modelSelection,
providerThreadId: ProviderThreadId.make("provider-thread:fork-snoozed-source"),
userMessageId: MessageId.make("message:fork-snoozed-source"),
rootNodeId: null,
activeAttemptId: null,
status: "completed",
queuePosition: null,
requestedAt: sourceCreatedAt,
startedAt: sourceCreatedAt,
completedAt: snoozedAt,
checkpointId: null,
contextHandoffId: null,
};
}
it.effect("keeps a fork awake when its source thread is snoozed", () =>
Effect.gen(function* () {
const sourceThread = makeSourceThread();
const sourceRun = makeCompletedSourceRun();
const sourceProjection: OrchestrationV2ThreadProjection = {
thread: sourceThread,
runs: [sourceRun],
attempts: [],
nodes: [],
subagents: [],
providerSessions: [],
providerThreads: [],
providerTurns: [],
runtimeRequests: [],
messages: [],
plans: [],
turnItems: [],
checkpointScopes: [],
checkpoints: [],
contextHandoffs: [],
contextTransfers: [],
visibleTurnItems: [],
updatedAt: snoozedAt,
};
const service = yield* ThreadForkServiceV2;
const result = yield* service.plan({
sourceProjection,
sourceRun,
sourceProviderThread: undefined,
canonicalSourcePoint: {
threadId: sourceThreadId,
runId: sourceRunId,
},
transferId: ContextTransferId.make("context-transfer:fork-snoozed-source"),
targetThreadId,
title: "Awake fork",
createdBy: "user",
creationSource: "mobile",
createdAt: forkCreatedAt,
});
assert.isNull(result.targetThread.snoozedUntil);
assert.isNull(result.targetThread.snoozedAt);
assert.equal(result.targetThread.projectId, sourceThread.projectId);
assert.equal(result.targetThread.providerInstanceId, sourceThread.providerInstanceId);
assert.deepEqual(result.targetThread.modelSelection, sourceThread.modelSelection);
assert.equal(result.targetThread.runtimeMode, sourceThread.runtimeMode);
assert.equal(result.targetThread.interactionMode, sourceThread.interactionMode);
assert.equal(result.targetThread.branch, sourceThread.branch);
assert.equal(result.targetThread.worktreePath, sourceThread.worktreePath);
assert.isNull(result.targetThread.activeProviderThreadId);
assert.deepEqual(result.targetThread.lineage, {
parentThreadId: sourceThreadId,
relationshipToParent: "fork",
rootThreadId: sourceThreadId,
});
assert.deepEqual(result.targetThread.forkedFrom, {
type: "run",
threadId: sourceThreadId,
runId: sourceRunId,
});
}).pipe(Effect.provide(layer)),
);