| ... | @@ -302,6 +302,7 @@ describe("CheckpointReactor", () => { | ... | @@ -302,6 +302,7 @@ describe("CheckpointReactor", () => { |
| 302 | readonly providerName?: ProviderDriverKind; | 302 | readonly providerName?: ProviderDriverKind; |
| 303 | readonly gitStatusRefreshCalls?: Array<string>; | 303 | readonly gitStatusRefreshCalls?: Array<string>; |
| 304 | readonly pullRequestRefreshCalls?: Array<string>; | 304 | readonly pullRequestRefreshCalls?: Array<string>; |
| | 305 | readonly pullRequestRefresh?: Effect.Effect<void>; |
| 305 | }) { | 306 | }) { |
| 306 | const cwd = createGitRepository(); | 307 | const cwd = createGitRepository(); |
| 307 | if (options?.initializeGit === false) { | 308 | if (options?.initializeGit === false) { |
| ... | @@ -357,7 +358,7 @@ describe("CheckpointReactor", () => { | ... | @@ -357,7 +358,7 @@ describe("CheckpointReactor", () => { |
| 357 | refreshPullRequestStatus: (cwd: string) => | 358 | refreshPullRequestStatus: (cwd: string) => |
| 358 | Effect.sync(() => { | 359 | Effect.sync(() => { |
| 359 | options?.pullRequestRefreshCalls?.push(cwd); | 360 | options?.pullRequestRefreshCalls?.push(cwd); |
| 360 | }).pipe(Effect.as(null)), | 361 | }).pipe(Effect.andThen(options?.pullRequestRefresh ?? Effect.void), Effect.as(null)), |
| 361 | streamStatus: () => Stream.empty, | 362 | streamStatus: () => Stream.empty, |
| 362 | }); | 363 | }); |
| 363 | | 364 | |
| ... | @@ -879,6 +880,49 @@ describe("CheckpointReactor", () => { | ... | @@ -879,6 +880,49 @@ describe("CheckpointReactor", () => { |
| 879 | expect(pullRequestRefreshCalls).toEqual([harness.cwd]); | 880 | expect(pullRequestRefreshCalls).toEqual([harness.cwd]); |
| 880 | }); | 881 | }); |
| 881 | | 882 | |
| | 883 | effectIt.effect("captures files while the pull request lookup is still pending", () => |
| | 884 | Effect.gen(function* () { |
| | 885 | const lookupStarted = yield* Deferred.make<void>(); |
| | 886 | const finishLookup = yield* Deferred.make<void>(); |
| | 887 | const harness = yield* Effect.promise(() => |
| | 888 | createHarness({ |
| | 889 | seedFilesystemCheckpoints: false, |
| | 890 | threadBranch: "t3code/feature", |
| | 891 | localStatusRefName: "t3code/feature", |
| | 892 | pullRequestRefresh: Deferred.succeed(lookupStarted, undefined).pipe( |
| | 893 | Effect.andThen(Deferred.await(finishLookup)), |
| | 894 | ), |
| | 895 | }), |
| | 896 | ); |
| | 897 | NodeFS.writeFileSync(NodePath.join(harness.cwd, "README.md"), "completed turn\n"); |
| | 898 | harness.provider.emit({ |
| | 899 | type: "turn.completed", |
| | 900 | eventId: EventId.make("evt-turn-completed-slow-pr"), |
| | 901 | provider: ProviderDriverKind.make("codex"), |
| | 902 | createdAt: "2026-01-01T00:00:00.000Z", |
| | 903 | threadId: ThreadId.make("thread-1"), |
| | 904 | turnId: asTurnId("turn-slow-pr"), |
| | 905 | payload: { state: "completed" }, |
| | 906 | }); |
| | 907 | |
| | 908 | yield* Deferred.await(lookupStarted); |
| | 909 | yield* Effect.gen(function* () { |
| | 910 | expect(yield* harness.nextReceipt).toMatchObject({ |
| | 911 | type: "checkpoint.diff.finalized", |
| | 912 | turnId: "turn-slow-pr", |
| | 913 | }); |
| | 914 | expect( |
| | 915 | gitShowFileAtRef( |
| | 916 | harness.cwd, |
| | 917 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), |
| | 918 | "README.md", |
| | 919 | ), |
| | 920 | ).toBe("completed turn\n"); |
| | 921 | }).pipe(Effect.ensuring(Deferred.succeed(finishLookup, undefined))); |
| | 922 | yield* Effect.promise(harness.drain); |
| | 923 | }), |
| | 924 | ); |
| | 925 | |
| 882 | it("re-asks for the pull request after adopting a drifted checkout", async () => { | 926 | it("re-asks for the pull request after adopting a drifted checkout", async () => { |
| 883 | const pullRequestRefreshCalls: string[] = []; | 927 | const pullRequestRefreshCalls: string[] = []; |
| 884 | const harness = await createHarness({ | 928 | const harness = await createHarness({ |