Skip to content

Commit 9dcea68

Browse files
Refresh git status after branch rename and worktree setup (#2005)
1 parent 5f7ec73 commit 9dcea68

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import {
2727
type ProviderServiceShape,
2828
} from "../../provider/Services/ProviderService.ts";
2929
import { GitCore, type GitCoreShape } from "../../git/Services/GitCore.ts";
30+
import {
31+
GitStatusBroadcaster,
32+
type GitStatusBroadcasterShape,
33+
} from "../../git/Services/GitStatusBroadcaster.ts";
3034
import { TextGeneration, type TextGenerationShape } from "../../git/Services/TextGeneration.ts";
3135
import { RepositoryIdentityResolverLive } from "../../project/Layers/RepositoryIdentityResolver.ts";
3236
import { OrchestrationEngineLive } from "./OrchestrationEngine.ts";
@@ -177,6 +181,24 @@ describe("ProviderCommandReactor", () => {
177181
: "renamed-branch",
178182
}),
179183
);
184+
const refreshStatus = vi.fn((_: string) =>
185+
Effect.succeed({
186+
isRepo: true,
187+
hasOriginRemote: true,
188+
isDefaultBranch: false,
189+
branch: "renamed-branch",
190+
hasWorkingTreeChanges: false,
191+
workingTree: {
192+
files: [],
193+
insertions: 0,
194+
deletions: 0,
195+
},
196+
hasUpstream: true,
197+
aheadCount: 0,
198+
behindCount: 0,
199+
pr: null,
200+
}),
201+
);
180202
const generateBranchName = vi.fn<TextGenerationShape["generateBranchName"]>((_) =>
181203
Effect.fail(
182204
new TextGenerationError({
@@ -225,6 +247,15 @@ describe("ProviderCommandReactor", () => {
225247
Layer.provideMerge(orchestrationLayer),
226248
Layer.provideMerge(Layer.succeed(ProviderService, service)),
227249
Layer.provideMerge(Layer.succeed(GitCore, { renameBranch } as unknown as GitCoreShape)),
250+
Layer.provideMerge(
251+
Layer.succeed(GitStatusBroadcaster, {
252+
getStatus: () => Effect.die("getStatus should not be called in this test"),
253+
refreshLocalStatus: () =>
254+
Effect.die("refreshLocalStatus should not be called in this test"),
255+
refreshStatus,
256+
streamStatus: () => Stream.die("streamStatus should not be called in this test"),
257+
} satisfies GitStatusBroadcasterShape),
258+
),
228259
Layer.provideMerge(
229260
Layer.mock(TextGeneration, {
230261
generateBranchName,
@@ -279,6 +310,7 @@ describe("ProviderCommandReactor", () => {
279310
respondToUserInput,
280311
stopSession,
281312
renameBranch,
313+
refreshStatus,
282314
generateBranchName,
283315
generateThreadTitle,
284316
stateDir,
@@ -513,9 +545,11 @@ describe("ProviderCommandReactor", () => {
513545
);
514546

515547
await waitFor(() => harness.generateBranchName.mock.calls.length === 1);
548+
await waitFor(() => harness.refreshStatus.mock.calls.length === 1);
516549
expect(harness.generateBranchName.mock.calls[0]?.[0]).toMatchObject({
517550
message: "Add a safer reconnect backoff.",
518551
});
552+
expect(harness.refreshStatus.mock.calls[0]?.[0]).toBe("/tmp/provider-project-worktree");
519553
});
520554

521555
it("forwards codex model options through session start and turn send", async () => {

apps/server/src/orchestration/Layers/ProviderCommandReactor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker";
1717

1818
import { resolveThreadWorkspaceCwd } from "../../checkpointing/Utils.ts";
1919
import { GitCore } from "../../git/Services/GitCore.ts";
20+
import { GitStatusBroadcaster } from "../../git/Services/GitStatusBroadcaster.ts";
2021
import { increment, orchestrationEventsProcessedTotal } from "../../observability/Metrics.ts";
2122
import { ProviderAdapterRequestError, ProviderServiceError } from "../../provider/Errors.ts";
2223
import { TextGeneration } from "../../git/Services/TextGeneration.ts";
@@ -145,6 +146,7 @@ const make = Effect.gen(function* () {
145146
const orchestrationEngine = yield* OrchestrationEngineService;
146147
const providerService = yield* ProviderService;
147148
const git = yield* GitCore;
149+
const gitStatusBroadcaster = yield* GitStatusBroadcaster;
148150
const textGeneration = yield* TextGeneration;
149151
const serverSettingsService = yield* ServerSettingsService;
150152
const handledTurnStartKeys = yield* Cache.make<string, true>({
@@ -447,6 +449,7 @@ const make = Effect.gen(function* () {
447449
branch: renamed.branch,
448450
worktreePath: cwd,
449451
});
452+
yield* gitStatusBroadcaster.refreshStatus(cwd).pipe(Effect.ignoreCause({ log: true }));
450453
}).pipe(
451454
Effect.catchCause((cause) =>
452455
Effect.logWarning("provider command reactor failed to generate or rename worktree branch", {

apps/server/src/server.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ import {
5858
import { GitCore, type GitCoreShape } from "./git/Services/GitCore.ts";
5959
import { GitManager, type GitManagerShape } from "./git/Services/GitManager.ts";
6060
import { GitStatusBroadcasterLive } from "./git/Layers/GitStatusBroadcaster.ts";
61+
import {
62+
GitStatusBroadcaster,
63+
type GitStatusBroadcasterShape,
64+
} from "./git/Services/GitStatusBroadcaster.ts";
6165
import { Keybindings, type KeybindingsShape } from "./keybindings.ts";
6266
import { Open, type OpenShape } from "./open.ts";
6367
import {
@@ -293,6 +297,7 @@ const buildAppUnderTest = (options?: {
293297
open?: Partial<OpenShape>;
294298
gitCore?: Partial<GitCoreShape>;
295299
gitManager?: Partial<GitManagerShape>;
300+
gitStatusBroadcaster?: Partial<GitStatusBroadcasterShape>;
296301
projectSetupScriptRunner?: Partial<ProjectSetupScriptRunnerShape>;
297302
terminalManager?: Partial<TerminalManagerShape>;
298303
orchestrationEngine?: Partial<OrchestrationEngineShape>;
@@ -341,7 +346,11 @@ const buildAppUnderTest = (options?: {
341346
const gitManagerLayer = Layer.mock(GitManager)({
342347
...options?.layers?.gitManager,
343348
});
344-
const gitStatusBroadcasterLayer = GitStatusBroadcasterLive.pipe(Layer.provide(gitManagerLayer));
349+
const gitStatusBroadcasterLayer = options?.layers?.gitStatusBroadcaster
350+
? Layer.mock(GitStatusBroadcaster)({
351+
...options.layers.gitStatusBroadcaster,
352+
})
353+
: GitStatusBroadcasterLive.pipe(Layer.provide(gitManagerLayer));
345354

346355
const servedRoutesLayer = HttpRouter.serve(makeRoutesLayer, {
347356
disableListenLog: true,
@@ -2913,6 +2922,24 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
29132922
() =>
29142923
Effect.gen(function* () {
29152924
const dispatchedCommands: Array<OrchestrationCommand> = [];
2925+
const refreshStatus = vi.fn((_: string) =>
2926+
Effect.succeed({
2927+
isRepo: true,
2928+
hasOriginRemote: true,
2929+
isDefaultBranch: false,
2930+
branch: "t3code/bootstrap-branch",
2931+
hasWorkingTreeChanges: false,
2932+
workingTree: {
2933+
files: [],
2934+
insertions: 0,
2935+
deletions: 0,
2936+
},
2937+
hasUpstream: true,
2938+
aheadCount: 0,
2939+
behindCount: 0,
2940+
pr: null,
2941+
}),
2942+
);
29162943
const createWorktree = vi.fn((_: Parameters<GitCoreShape["createWorktree"]>[0]) =>
29172944
Effect.succeed({
29182945
worktree: {
@@ -2937,6 +2964,9 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
29372964
gitCore: {
29382965
createWorktree,
29392966
},
2967+
gitStatusBroadcaster: {
2968+
refreshStatus,
2969+
},
29402970
orchestrationEngine: {
29412971
dispatch: (command) =>
29422972
Effect.sync(() => {
@@ -3014,6 +3044,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
30143044
projectCwd: "/tmp/project",
30153045
worktreePath: "/tmp/bootstrap-worktree",
30163046
});
3047+
assert.deepEqual(refreshStatus.mock.calls[0]?.[0], "/tmp/bootstrap-worktree");
30173048

30183049
const setupActivities = dispatchedCommands.filter(
30193050
(command): command is Extract<OrchestrationCommand, { type: "thread.activity.append" }> =>

apps/server/src/ws.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
464464
branch: worktree.worktree.branch,
465465
worktreePath: targetWorktreePath,
466466
});
467+
yield* refreshGitStatus(targetWorktreePath);
467468
}
468469

469470
yield* runSetupProgram();

0 commit comments

Comments
 (0)