import { assert, it, vi } from "@effect/vitest";import { CheckpointRef, CheckpointScopeId, RunId, ThreadId } from "@t3tools/contracts";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer"; import { checkpointRefForScopeOrdinal } from "../orchestration-v2/CheckpointService.ts";import { OrchestratorProjectionError } from "../orchestration-v2/Orchestrator.ts";import type { ProjectionCheckpointContext } from "../orchestration-v2/ProjectionStore.ts";import * as ThreadManagement from "../orchestration-v2/ThreadManagementService.ts";import * as CheckpointDiffQuery from "./CheckpointDiffQuery.ts";import * as CheckpointStore from "./CheckpointStore.ts";import { CheckpointRefUnavailableError, CheckpointThreadNotFoundError, CheckpointTurnRangeUnavailableError,} from "./Errors.ts"; const threadId = ThreadId.make("thread:checkpoint-diff-v2");const firstRunId = RunId.make("run:checkpoint-diff-v2:1");const secondRunId = RunId.make("run:checkpoint-diff-v2:2");const firstScopeId = CheckpointScopeId.make("scope:checkpoint-diff-v2:1");const secondScopeId = CheckpointScopeId.make("scope:checkpoint-diff-v2:2");const secondRef = CheckpointRef.make("refs/t3/test/second"); function makeProjection(): ProjectionCheckpointContext { return { runs: [ { id: firstRunId, ordinal: 1, status: "completed" }, { id: secondRunId, ordinal: 2, status: "completed" }, ], checkpointScopes: [ { id: firstScopeId, runId: firstRunId, kind: "root_run", cwd: "/repo" }, { id: secondScopeId, runId: secondRunId, kind: "root_run", cwd: "/repo" }, ], checkpoints: [ { scopeId: secondScopeId, runId: secondRunId, appRunOrdinal: 2, status: "ready", ref: secondRef, }, ], };} function makeLayer(input: { readonly projection: Effect.Effect<ProjectionCheckpointContext, OrchestratorProjectionError>; readonly diffCheckpoints?: CheckpointStore.CheckpointStore["Service"]["diffCheckpoints"];}) { return CheckpointDiffQuery.layer.pipe( Layer.provide( Layer.mergeAll( Layer.mock(ThreadManagement.ThreadManagementService)({ getCheckpointContext: () => input.projection, }), Layer.mock(CheckpointStore.CheckpointStore)({ diffCheckpoints: input.diffCheckpoints ?? (() => Effect.succeed("diff")), }), ), ), );} it.effect("computes V2 run diffs from projected checkpoint scopes", () => { const diffCheckpoints = vi.fn((_input: CheckpointStore.DiffCheckpointsInput) => Effect.succeed("diff --git a/file b/file"), ); const layer = makeLayer({ projection: Effect.succeed(makeProjection()), diffCheckpoints }); return Effect.gen(function* () { const query = yield* CheckpointDiffQuery.CheckpointDiffQuery; const result = yield* query.getFullThreadDiff({ threadId, toTurnCount: 2 }); assert.deepEqual(result, { threadId, fromTurnCount: 0, toTurnCount: 2, diff: "diff --git a/file b/file", }); assert.deepEqual(diffCheckpoints.mock.calls[0]?.[0], { cwd: "/repo", fromCheckpointRef: checkpointRefForScopeOrdinal({ scopeId: firstScopeId, ordinalWithinScope: 0, }), toCheckpointRef: secondRef, fallbackFromToHead: false, ignoreWhitespace: true, }); }).pipe(Effect.provide(layer));}); it.effect("preserves the typed missing-thread error contract", () => { const layer = makeLayer({ projection: Effect.fail(new OrchestratorProjectionError({ threadId })), }); return Effect.gen(function* () { const query = yield* CheckpointDiffQuery.CheckpointDiffQuery; const error = yield* query .getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 1 }) .pipe(Effect.flip); assert.instanceOf(error, CheckpointThreadNotFoundError); assert.deepEqual( { operation: error.operation, threadId: error.threadId }, { operation: "CheckpointDiffQuery.getTurnDiff", threadId }, ); }).pipe(Effect.provide(layer));}); it.effect("preserves the typed unavailable-range error contract", () => { const layer = makeLayer({ projection: Effect.succeed(makeProjection()) }); return Effect.gen(function* () { const query = yield* CheckpointDiffQuery.CheckpointDiffQuery; const error = yield* query .getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 3 }) .pipe(Effect.flip); assert.instanceOf(error, CheckpointTurnRangeUnavailableError); assert.deepEqual( { requestedTurnCount: error.requestedTurnCount, availableTurnCount: error.availableTurnCount, }, { requestedTurnCount: 3, availableTurnCount: 2 }, ); }).pipe(Effect.provide(layer));}); it.effect("excludes ready checkpoints from rolled-back runs", () => { const projection = makeProjection(); const layer = makeLayer({ projection: Effect.succeed({ ...projection, runs: projection.runs.map((run) => run.id === secondRunId ? { ...run, status: "rolled_back" as const } : run, ), checkpoints: [ { ...projection.checkpoints[0]!, scopeId: firstScopeId, runId: firstRunId, appRunOrdinal: 1, ref: CheckpointRef.make("refs/t3/test/first"), }, ...projection.checkpoints, ], }), }); return Effect.gen(function* () { const query = yield* CheckpointDiffQuery.CheckpointDiffQuery; const error = yield* query .getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 2 }) .pipe(Effect.flip); assert.instanceOf(error, CheckpointTurnRangeUnavailableError); assert.deepEqual( { requestedTurnCount: error.requestedTurnCount, availableTurnCount: error.availableTurnCount, }, { requestedTurnCount: 2, availableTurnCount: 1 }, ); }).pipe(Effect.provide(layer));}); it.effect("preserves the typed missing-baseline-ref error contract", () => { const projection = makeProjection(); const layer = makeLayer({ projection: Effect.succeed({ ...projection, checkpointScopes: projection.checkpointScopes.filter((scope) => scope.id !== firstScopeId), }), }); return Effect.gen(function* () { const query = yield* CheckpointDiffQuery.CheckpointDiffQuery; const error = yield* query .getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 2 }) .pipe(Effect.flip); assert.instanceOf(error, CheckpointRefUnavailableError); assert.deepEqual( { checkpoint: error.checkpoint, turnCount: error.turnCount }, { checkpoint: "from", turnCount: 0 }, ); }).pipe(Effect.provide(layer));});
import { assert, it, vi } from "@effect/vitest";
import { CheckpointRef, CheckpointScopeId, RunId, ThreadId } from "@t3tools/contracts";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import { checkpointRefForScopeOrdinal } from "../orchestration-v2/CheckpointService.ts";
import { OrchestratorProjectionError } from "../orchestration-v2/Orchestrator.ts";
import type { ProjectionCheckpointContext } from "../orchestration-v2/ProjectionStore.ts";
import * as ThreadManagement from "../orchestration-v2/ThreadManagementService.ts";
import * as CheckpointDiffQuery from "./CheckpointDiffQuery.ts";
import * as CheckpointStore from "./CheckpointStore.ts";
import {
CheckpointRefUnavailableError,
CheckpointThreadNotFoundError,
CheckpointTurnRangeUnavailableError,
} from "./Errors.ts";
const threadId = ThreadId.make("thread:checkpoint-diff-v2");
const firstRunId = RunId.make("run:checkpoint-diff-v2:1");
const secondRunId = RunId.make("run:checkpoint-diff-v2:2");
const firstScopeId = CheckpointScopeId.make("scope:checkpoint-diff-v2:1");
const secondScopeId = CheckpointScopeId.make("scope:checkpoint-diff-v2:2");
const secondRef = CheckpointRef.make("refs/t3/test/second");
function makeProjection(): ProjectionCheckpointContext {
return {
runs: [
{ id: firstRunId, ordinal: 1, status: "completed" },
{ id: secondRunId, ordinal: 2, status: "completed" },
],
checkpointScopes: [
{ id: firstScopeId, runId: firstRunId, kind: "root_run", cwd: "/repo" },
{ id: secondScopeId, runId: secondRunId, kind: "root_run", cwd: "/repo" },
],
checkpoints: [
{
scopeId: secondScopeId,
runId: secondRunId,
appRunOrdinal: 2,
status: "ready",
ref: secondRef,
},
],
};
}
function makeLayer(input: {
readonly projection: Effect.Effect<ProjectionCheckpointContext, OrchestratorProjectionError>;
readonly diffCheckpoints?: CheckpointStore.CheckpointStore["Service"]["diffCheckpoints"];
}) {
return CheckpointDiffQuery.layer.pipe(
Layer.provide(
Layer.mergeAll(
Layer.mock(ThreadManagement.ThreadManagementService)({
getCheckpointContext: () => input.projection,
}),
Layer.mock(CheckpointStore.CheckpointStore)({
diffCheckpoints: input.diffCheckpoints ?? (() => Effect.succeed("diff")),
}),
),
),
);
}
it.effect("computes V2 run diffs from projected checkpoint scopes", () => {
const diffCheckpoints = vi.fn((_input: CheckpointStore.DiffCheckpointsInput) =>
Effect.succeed("diff --git a/file b/file"),
);
const layer = makeLayer({ projection: Effect.succeed(makeProjection()), diffCheckpoints });
return Effect.gen(function* () {
const query = yield* CheckpointDiffQuery.CheckpointDiffQuery;
const result = yield* query.getFullThreadDiff({ threadId, toTurnCount: 2 });
assert.deepEqual(result, {
threadId,
fromTurnCount: 0,
toTurnCount: 2,
diff: "diff --git a/file b/file",
});
assert.deepEqual(diffCheckpoints.mock.calls[0]?.[0], {
cwd: "/repo",
fromCheckpointRef: checkpointRefForScopeOrdinal({
scopeId: firstScopeId,
ordinalWithinScope: 0,
}),
toCheckpointRef: secondRef,
fallbackFromToHead: false,
ignoreWhitespace: true,
});
}).pipe(Effect.provide(layer));
});
it.effect("preserves the typed missing-thread error contract", () => {
const layer = makeLayer({
projection: Effect.fail(new OrchestratorProjectionError({ threadId })),
});
return Effect.gen(function* () {
const query = yield* CheckpointDiffQuery.CheckpointDiffQuery;
const error = yield* query
.getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 1 })
.pipe(Effect.flip);
assert.instanceOf(error, CheckpointThreadNotFoundError);
assert.deepEqual(
{ operation: error.operation, threadId: error.threadId },
{ operation: "CheckpointDiffQuery.getTurnDiff", threadId },
);
}).pipe(Effect.provide(layer));
});
it.effect("preserves the typed unavailable-range error contract", () => {
const layer = makeLayer({ projection: Effect.succeed(makeProjection()) });
return Effect.gen(function* () {
const query = yield* CheckpointDiffQuery.CheckpointDiffQuery;
const error = yield* query
.getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 3 })
.pipe(Effect.flip);
assert.instanceOf(error, CheckpointTurnRangeUnavailableError);
assert.deepEqual(
{
requestedTurnCount: error.requestedTurnCount,
availableTurnCount: error.availableTurnCount,
},
{ requestedTurnCount: 3, availableTurnCount: 2 },
);
}).pipe(Effect.provide(layer));
});
it.effect("excludes ready checkpoints from rolled-back runs", () => {
const projection = makeProjection();
const layer = makeLayer({
projection: Effect.succeed({
...projection,
runs: projection.runs.map((run) =>
run.id === secondRunId ? { ...run, status: "rolled_back" as const } : run,
),
checkpoints: [
{
...projection.checkpoints[0]!,
scopeId: firstScopeId,
runId: firstRunId,
appRunOrdinal: 1,
ref: CheckpointRef.make("refs/t3/test/first"),
},
...projection.checkpoints,
],
}),
});
return Effect.gen(function* () {
const query = yield* CheckpointDiffQuery.CheckpointDiffQuery;
const error = yield* query
.getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 2 })
.pipe(Effect.flip);
assert.instanceOf(error, CheckpointTurnRangeUnavailableError);
assert.deepEqual(
{
requestedTurnCount: error.requestedTurnCount,
availableTurnCount: error.availableTurnCount,
},
{ requestedTurnCount: 2, availableTurnCount: 1 },
);
}).pipe(Effect.provide(layer));
});
it.effect("preserves the typed missing-baseline-ref error contract", () => {
const projection = makeProjection();
const layer = makeLayer({
projection: Effect.succeed({
...projection,
checkpointScopes: projection.checkpointScopes.filter((scope) => scope.id !== firstScopeId),
}),
});
return Effect.gen(function* () {
const query = yield* CheckpointDiffQuery.CheckpointDiffQuery;
const error = yield* query
.getTurnDiff({ threadId, fromTurnCount: 0, toTurnCount: 2 })
.pipe(Effect.flip);
assert.instanceOf(error, CheckpointRefUnavailableError);
assert.deepEqual(
{ checkpoint: error.checkpoint, turnCount: error.turnCount },
{ checkpoint: "from", turnCount: 0 },
);
}).pipe(Effect.provide(layer));
});