@@ -41,6 +41,7 @@ import {
4141 type OrchestrationEngineShape ,
4242} from "../Services/OrchestrationEngine.ts" ;
4343import { CheckpointReactor } from "../Services/CheckpointReactor.ts" ;
44+ import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts" ;
4445import {
4546 ProviderService ,
4647 type ProviderServiceShape ,
@@ -132,7 +133,14 @@ function createProviderServiceHarness(
132133}
133134
134135async function waitForThread (
135- engine : OrchestrationEngineShape ,
136+ readModel : ( ) => Promise < {
137+ readonly threads : ReadonlyArray < {
138+ readonly id : ThreadId ;
139+ readonly latestTurn : { readonly turnId : string } | null ;
140+ readonly checkpoints : ReadonlyArray < { readonly checkpointTurnCount : number } > ;
141+ readonly activities : ReadonlyArray < { readonly kind : string } > ;
142+ } > ;
143+ } > ,
136144 predicate : ( thread : {
137145 latestTurn : { turnId : string } | null ;
138146 checkpoints : ReadonlyArray < { checkpointTurnCount : number } > ;
@@ -146,8 +154,8 @@ async function waitForThread(
146154 checkpoints : ReadonlyArray < { checkpointTurnCount : number } > ;
147155 activities : ReadonlyArray < { kind : string } > ;
148156 } > => {
149- const readModel = await Effect . runPromise ( engine . getReadModel ( ) ) ;
150- const thread = readModel . threads . find ( ( entry ) => entry . id === ThreadId . make ( "thread-1" ) ) ;
157+ const snapshot = await readModel ( ) ;
158+ const thread = snapshot . threads . find ( ( entry ) => entry . id === ThreadId . make ( "thread-1" ) ) ;
151159 if ( thread && predicate ( thread ) ) {
152160 return thread ;
153161 }
@@ -231,7 +239,7 @@ async function waitForGitRefExists(cwd: string, ref: string, timeoutMs = 15_000)
231239
232240describe ( "CheckpointReactor" , ( ) => {
233241 let runtime : ManagedRuntime . ManagedRuntime <
234- OrchestrationEngineService | CheckpointReactor | CheckpointStore ,
242+ OrchestrationEngineService | CheckpointReactor | CheckpointStore | ProjectionSnapshotQuery ,
235243 unknown
236244 > | null = null ;
237245 let scope : Scope . Closeable | null = null ;
@@ -279,6 +287,10 @@ describe("CheckpointReactor", () => {
279287 Layer . provide ( RepositoryIdentityResolverLive ) ,
280288 Layer . provide ( SqlitePersistenceMemory ) ,
281289 ) ;
290+ const projectionSnapshotLayer = OrchestrationProjectionSnapshotQueryLive . pipe (
291+ Layer . provide ( RepositoryIdentityResolverLive ) ,
292+ Layer . provide ( SqlitePersistenceMemory ) ,
293+ ) ;
282294
283295 const ServerConfigLayer = ServerConfig . layerTest ( process . cwd ( ) , {
284296 prefix : "t3-checkpoint-reactor-test-" ,
@@ -304,6 +316,7 @@ describe("CheckpointReactor", () => {
304316
305317 const layer = CheckpointReactorLive . pipe (
306318 Layer . provideMerge ( orchestrationLayer ) ,
319+ Layer . provideMerge ( projectionSnapshotLayer ) ,
307320 Layer . provideMerge ( RuntimeReceiptBusLive ) ,
308321 Layer . provideMerge ( Layer . succeed ( ProviderService , provider . service ) ) ,
309322 Layer . provideMerge ( vcsStatusBroadcasterLayer ) ,
@@ -322,6 +335,7 @@ describe("CheckpointReactor", () => {
322335
323336 runtime = ManagedRuntime . make ( layer ) ;
324337 const engine = await runtime . runPromise ( Effect . service ( OrchestrationEngineService ) ) ;
338+ const snapshotQuery = await runtime . runPromise ( Effect . service ( ProjectionSnapshotQuery ) ) ;
325339 const reactor = await runtime . runPromise ( Effect . service ( CheckpointReactor ) ) ;
326340 const checkpointStore = await runtime . runPromise ( Effect . service ( CheckpointStore ) ) ;
327341 scope = await Effect . runPromise ( Scope . make ( "sequential" ) ) ;
@@ -387,6 +401,7 @@ describe("CheckpointReactor", () => {
387401
388402 return {
389403 engine,
404+ readModel : ( ) => Effect . runPromise ( snapshotQuery . getSnapshot ( ) ) ,
390405 provider,
391406 cwd,
392407 drain,
@@ -443,7 +458,7 @@ describe("CheckpointReactor", () => {
443458
444459 await waitForEvent ( harness . engine , ( event ) => event . type === "thread.turn-diff-completed" ) ;
445460 const thread = await waitForThread (
446- harness . engine ,
461+ harness . readModel ,
447462 ( entry ) => entry . latestTurn ?. turnId === "turn-1" && entry . checkpoints . length === 1 ,
448463 ) ;
449464 expect ( thread . checkpoints [ 0 ] ?. checkpointTurnCount ) . toBe ( 1 ) ;
@@ -541,7 +556,7 @@ describe("CheckpointReactor", () => {
541556 } ) ;
542557
543558 await harness . drain ( ) ;
544- const midReadModel = await Effect . runPromise ( harness . engine . getReadModel ( ) ) ;
559+ const midReadModel = await harness . readModel ( ) ;
545560 const midThread = midReadModel . threads . find ( ( entry ) => entry . id === ThreadId . make ( "thread-1" ) ) ;
546561 expect ( midThread ?. checkpoints ) . toHaveLength ( 0 ) ;
547562
@@ -557,7 +572,7 @@ describe("CheckpointReactor", () => {
557572 } ) ;
558573
559574 const thread = await waitForThread (
560- harness . engine ,
575+ harness . readModel ,
561576 ( entry ) => entry . latestTurn ?. turnId === "turn-main" && entry . checkpoints . length === 1 ,
562577 ) ;
563578 expect ( thread . checkpoints [ 0 ] ?. checkpointTurnCount ) . toBe ( 1 ) ;
@@ -614,7 +629,7 @@ describe("CheckpointReactor", () => {
614629
615630 await waitForEvent ( harness . engine , ( event ) => event . type === "thread.turn-diff-completed" ) ;
616631 const thread = await waitForThread (
617- harness . engine ,
632+ harness . readModel ,
618633 ( entry ) => entry . latestTurn ?. turnId === "turn-claude-1" && entry . checkpoints . length === 1 ,
619634 ) ;
620635
@@ -659,7 +674,7 @@ describe("CheckpointReactor", () => {
659674
660675 await waitForEvent ( harness . engine , ( event ) => event . type === "thread.turn-diff-completed" ) ;
661676 const thread = await waitForThread (
662- harness . engine ,
677+ harness . readModel ,
663678 ( entry ) =>
664679 entry . checkpoints . length === 1 &&
665680 entry . activities . some ( ( activity ) => activity . kind === "checkpoint.capture.failed" ) ,
@@ -794,7 +809,7 @@ describe("CheckpointReactor", () => {
794809 } ) ;
795810
796811 await harness . drain ( ) ;
797- const readModel = await Effect . runPromise ( harness . engine . getReadModel ( ) ) ;
812+ const readModel = await harness . readModel ( ) ;
798813 const thread = readModel . threads . find ( ( entry ) => entry . id === ThreadId . make ( "thread-1" ) ) ;
799814 expect ( thread ?. checkpoints . some ( ( checkpoint ) => checkpoint . checkpointTurnCount === 3 ) ) . toBe (
800815 false ,
@@ -923,7 +938,10 @@ describe("CheckpointReactor", () => {
923938 ) ;
924939
925940 await waitForEvent ( harness . engine , ( event ) => event . type === "thread.reverted" ) ;
926- const thread = await waitForThread ( harness . engine , ( entry ) => entry . checkpoints . length === 1 ) ;
941+ const thread = await waitForThread (
942+ harness . readModel ,
943+ ( entry ) => entry . checkpoints . length === 1 ,
944+ ) ;
927945
928946 expect ( thread . latestTurn ?. turnId ) . toBe ( "turn-1" ) ;
929947 expect ( thread . checkpoints ) . toHaveLength ( 1 ) ;
@@ -1105,7 +1123,7 @@ describe("CheckpointReactor", () => {
11051123 } ) ,
11061124 ) ;
11071125
1108- const thread = await waitForThread ( harness . engine , ( entry ) =>
1126+ const thread = await waitForThread ( harness . readModel , ( entry ) =>
11091127 entry . activities . some ( ( activity ) => activity . kind === "checkpoint.revert.failed" ) ,
11101128 ) ;
11111129
0 commit comments