Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ describe("CheckpointDiffQueryLive", () => {
Effect.die("CheckpointDiffQuery should not request the full orchestration snapshot"),
getShellSnapshot: () =>
Effect.die("CheckpointDiffQuery should not request the orchestration shell snapshot"),
getArchivedShellSnapshot: () =>
Effect.die("CheckpointDiffQuery should not request archived shell snapshots"),
getSnapshotSequence: () => Effect.succeed({ snapshotSequence: 0 }),
getCounts: () => Effect.succeed({ projectCount: 0, threadCount: 0 }),
getActiveProjectByWorkspaceRoot: () => Effect.succeed(Option.none()),
Expand Down Expand Up @@ -172,6 +174,8 @@ describe("CheckpointDiffQueryLive", () => {
Effect.die("CheckpointDiffQuery should not request the full orchestration snapshot"),
getShellSnapshot: () =>
Effect.die("CheckpointDiffQuery should not request the orchestration shell snapshot"),
getArchivedShellSnapshot: () =>
Effect.die("CheckpointDiffQuery should not request archived shell snapshots"),
getSnapshotSequence: () => Effect.succeed({ snapshotSequence: 0 }),
getCounts: () => Effect.succeed({ projectCount: 0, threadCount: 0 }),
getActiveProjectByWorkspaceRoot: () => Effect.succeed(Option.none()),
Expand Down Expand Up @@ -220,6 +224,8 @@ describe("CheckpointDiffQueryLive", () => {
Effect.die("CheckpointDiffQuery should not request the full orchestration snapshot"),
getShellSnapshot: () =>
Effect.die("CheckpointDiffQuery should not request the orchestration shell snapshot"),
getArchivedShellSnapshot: () =>
Effect.die("CheckpointDiffQuery should not request archived shell snapshots"),
getSnapshotSequence: () => Effect.succeed({ snapshotSequence: 0 }),
getCounts: () => Effect.succeed({ projectCount: 0, threadCount: 0 }),
getActiveProjectByWorkspaceRoot: () => Effect.succeed(Option.none()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
TurnId,
type OrchestrationEvent,
ProviderInstanceId,
type OrchestrationReadModel,
} from "@t3tools/contracts";
import { Effect, Layer, ManagedRuntime, Metric, Option, Queue, Stream } from "effect";
import { describe, expect, it } from "vitest";
Expand Down Expand Up @@ -178,6 +177,13 @@ describe("OrchestrationEngine", () => {
threads: [],
updatedAt: projectionSnapshot.updatedAt,
}),
getArchivedShellSnapshot: () =>
Effect.succeed({
snapshotSequence: projectionSnapshot.snapshotSequence,
projects: [],
threads: [],
updatedAt: projectionSnapshot.updatedAt,
}),
getSnapshotSequence: () =>
Effect.succeed({ snapshotSequence: projectionSnapshot.snapshotSequence }),
getCounts: () => Effect.succeed({ projectCount: 1, threadCount: 1 }),
Expand Down
120 changes: 120 additions & 0 deletions apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,126 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => {
}),
);

it.effect("keeps archived threads out of the main shell snapshot", () =>
Effect.gen(function* () {
const snapshotQuery = yield* ProjectionSnapshotQuery;
const sql = yield* SqlClient.SqlClient;

yield* sql`DELETE FROM projection_projects`;
yield* sql`DELETE FROM projection_threads`;
yield* sql`DELETE FROM projection_state`;

yield* sql`
INSERT INTO projection_projects (
project_id,
title,
workspace_root,
default_model_selection_json,
scripts_json,
created_at,
updated_at,
deleted_at
)
VALUES (
'project-archive-test',
'Archive Test',
'/tmp/archive-test',
'{"provider":"codex","model":"gpt-5-codex"}',
'[]',
'2026-04-06T00:00:00.000Z',
'2026-04-06T00:00:01.000Z',
NULL
)
`;

yield* sql`
INSERT INTO projection_threads (
thread_id,
project_id,
title,
model_selection_json,
runtime_mode,
interaction_mode,
branch,
worktree_path,
latest_turn_id,
latest_user_message_at,
pending_approval_count,
pending_user_input_count,
has_actionable_proposed_plan,
created_at,
updated_at,
archived_at,
deleted_at
)
VALUES
(
'thread-active',
'project-archive-test',
'Active Thread',
'{"provider":"codex","model":"gpt-5-codex"}',
'full-access',
'default',
NULL,
NULL,
NULL,
NULL,
0,
0,
0,
'2026-04-06T00:00:02.000Z',
'2026-04-06T00:00:03.000Z',
NULL,
NULL
),
(
'thread-archived',
'project-archive-test',
'Archived Thread',
'{"provider":"codex","model":"gpt-5-codex"}',
'full-access',
'default',
NULL,
NULL,
NULL,
NULL,
0,
0,
0,
'2026-04-06T00:00:04.000Z',
'2026-04-06T00:00:05.000Z',
'2026-04-06T00:00:06.000Z',
NULL
)
`;

yield* sql`
INSERT INTO projection_state (projector, last_applied_sequence, updated_at)
VALUES
(${ORCHESTRATION_PROJECTOR_NAMES.projects}, 4, '2026-04-06T00:00:07.000Z'),
(${ORCHESTRATION_PROJECTOR_NAMES.threads}, 4, '2026-04-06T00:00:07.000Z'),
(${ORCHESTRATION_PROJECTOR_NAMES.threadMessages}, 4, '2026-04-06T00:00:07.000Z'),
(${ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans}, 4, '2026-04-06T00:00:07.000Z'),
(${ORCHESTRATION_PROJECTOR_NAMES.threadActivities}, 4, '2026-04-06T00:00:07.000Z'),
(${ORCHESTRATION_PROJECTOR_NAMES.threadSessions}, 4, '2026-04-06T00:00:07.000Z'),
(${ORCHESTRATION_PROJECTOR_NAMES.checkpoints}, 4, '2026-04-06T00:00:07.000Z')
`;

const shellSnapshot = yield* snapshotQuery.getShellSnapshot();
assert.deepEqual(
shellSnapshot.threads.map((thread) => thread.id),
[ThreadId.make("thread-active")],
);

const archivedShellSnapshot = yield* snapshotQuery.getArchivedShellSnapshot();
assert.deepEqual(
archivedShellSnapshot.threads.map((thread) => thread.id),
[ThreadId.make("thread-archived")],
);
assert.equal(archivedShellSnapshot.threads[0]?.archivedAt, "2026-04-06T00:00:06.000Z");
}),
);

it.effect(
"reads targeted project, thread, and count queries without hydrating the full snapshot",
() =>
Expand Down
Loading
Loading