| ... | ... | @@ -108,27 +108,11 @@ describe("ProviderCommandReactor", () => { |
| 108 | 108 | const interruptTurn = vi.fn((_: unknown) => Effect.void); |
| 109 | 109 | const respondToRequest = vi.fn((_: unknown) => Effect.void); |
| 110 | 110 | const stopSession = vi.fn((_: unknown) => Effect.void); |
| 111 | | const statusBranchByCwd = new Map<string, string | null>(); |
| 112 | 111 | const renameBranch = vi.fn((_: unknown) => |
| 113 | 112 | Effect.succeed({ |
| 114 | 113 | branch: "t3code/generated-name", |
| 115 | 114 | }), |
| 116 | 115 | ); |
| 117 | | const statusDetails = vi.fn((cwd: string) => |
| 118 | | Effect.succeed({ |
| 119 | | branch: statusBranchByCwd.get(cwd) ?? null, |
| 120 | | upstreamRef: null, |
| 121 | | hasWorkingTreeChanges: false, |
| 122 | | workingTree: { |
| 123 | | files: [], |
| 124 | | insertions: 0, |
| 125 | | deletions: 0, |
| 126 | | }, |
| 127 | | hasUpstream: false, |
| 128 | | aheadCount: 0, |
| 129 | | behindCount: 0, |
| 130 | | }), |
| 131 | | ); |
| 132 | 116 | const generateBranchName = vi.fn<TextGenerationShape["generateBranchName"]>(() => |
| 133 | 117 | Effect.succeed({ |
| 134 | 118 | branch: "generated-name", |
| ... | ... | @@ -157,12 +141,7 @@ describe("ProviderCommandReactor", () => { |
| 157 | 141 | const layer = ProviderCommandReactorLive.pipe( |
| 158 | 142 | Layer.provideMerge(orchestrationLayer), |
| 159 | 143 | Layer.provideMerge(Layer.succeed(ProviderService, service)), |
| 160 | | Layer.provideMerge( |
| 161 | | Layer.succeed( |
| 162 | | GitCore, |
| 163 | | { renameBranch, statusDetails } as unknown as GitCoreShape, |
| 164 | | ), |
| 165 | | ), |
| 144 | Layer.provideMerge(Layer.succeed(GitCore, { renameBranch } as unknown as GitCoreShape)), |
| 166 | 145 | Layer.provideMerge( |
| 167 | 146 | Layer.succeed(TextGeneration, { generateBranchName } as unknown as TextGenerationShape), |
| 168 | 147 | ), |
| ... | ... | @@ -210,11 +189,7 @@ describe("ProviderCommandReactor", () => { |
| 210 | 189 | respondToRequest, |
| 211 | 190 | stopSession, |
| 212 | 191 | renameBranch, |
| 213 | | statusDetails, |
| 214 | 192 | generateBranchName, |
| 215 | | setStatusBranch: (cwd: string, branch: string | null) => { |
| 216 | | statusBranchByCwd.set(cwd, branch); |
| 217 | | }, |
| 218 | 193 | stateDir, |
| 219 | 194 | }; |
| 220 | 195 | } |
| ... | ... | @@ -260,7 +235,6 @@ describe("ProviderCommandReactor", () => { |
| 260 | 235 | it("generates and renames temporary worktree branch on first turn", async () => { |
| 261 | 236 | const harness = await createHarness(); |
| 262 | 237 | const now = new Date().toISOString(); |
| 263 | | const worktreeCwd = "/tmp/provider-project/.t3/worktrees/t3code-89abc123"; |
| 264 | 238 | |
| 265 | 239 | await Effect.runPromise( |
| 266 | 240 | harness.engine.dispatch({ |
| ... | ... | @@ -268,10 +242,9 @@ describe("ProviderCommandReactor", () => { |
| 268 | 242 | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch"), |
| 269 | 243 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 270 | 244 | branch: "t3code/89abc123", |
| 271 | | worktreePath: worktreeCwd, |
| 245 | worktreePath: "/tmp/provider-project/.t3/worktrees/t3code-89abc123", |
| 272 | 246 | }), |
| 273 | 247 | ); |
| 274 | | harness.setStatusBranch(worktreeCwd, "t3code/89abc123"); |
| 275 | 248 | |
| 276 | 249 | await Effect.runPromise( |
| 277 | 250 | harness.engine.dispatch({ |
| ... | ... | @@ -302,7 +275,7 @@ describe("ProviderCommandReactor", () => { |
| 302 | 275 | await waitFor(() => harness.renameBranch.mock.calls.length === 1); |
| 303 | 276 | |
| 304 | 277 | expect(harness.generateBranchName.mock.calls[0]?.[0]).toEqual({ |
| 305 | | cwd: worktreeCwd, |
| 278 | cwd: "/tmp/provider-project/.t3/worktrees/t3code-89abc123", |
| 306 | 279 | message: "Fix visual bug from screenshot", |
| 307 | 280 | attachments: [ |
| 308 | 281 | { |
| ... | ... | @@ -315,14 +288,18 @@ describe("ProviderCommandReactor", () => { |
| 315 | 288 | ], |
| 316 | 289 | }); |
| 317 | 290 | expect(harness.renameBranch.mock.calls[0]?.[0]).toEqual({ |
| 318 | | cwd: worktreeCwd, |
| 291 | cwd: "/tmp/provider-project/.t3/worktrees/t3code-89abc123", |
| 319 | 292 | oldBranch: "t3code/89abc123", |
| 320 | 293 | newBranch: "t3code/generated-name", |
| 321 | 294 | }); |
| 322 | 295 | |
| 323 | | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 324 | | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); |
| 325 | | expect(thread?.branch).toBe("t3code/89abc123"); |
| 296 | await waitFor(() => { |
| 297 | const readModel = Effect.runSync(harness.engine.getReadModel()); |
| 298 | const thread = readModel.threads.find( |
| 299 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), |
| 300 | ); |
| 301 | return thread?.branch === "t3code/generated-name"; |
| 302 | }); |
| 326 | 303 | }); |
| 327 | 304 | |
| 328 | 305 | it("passes persisted attachment references to branch generation and turn start", async () => { |
| ... | ... | @@ -396,7 +373,6 @@ describe("ProviderCommandReactor", () => { |
| 396 | 373 | it("skips worktree branch generation after the first user turn", async () => { |
| 397 | 374 | const harness = await createHarness(); |
| 398 | 375 | const now = new Date().toISOString(); |
| 399 | | const worktreeCwd = "/tmp/provider-project/.t3/worktrees/t3code-1234abcd"; |
| 400 | 376 | |
| 401 | 377 | await Effect.runPromise( |
| 402 | 378 | harness.engine.dispatch({ |
| ... | ... | @@ -404,10 +380,9 @@ describe("ProviderCommandReactor", () => { |
| 404 | 380 | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch-2"), |
| 405 | 381 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 406 | 382 | branch: "t3code/1234abcd", |
| 407 | | worktreePath: worktreeCwd, |
| 383 | worktreePath: "/tmp/provider-project/.t3/worktrees/t3code-1234abcd", |
| 408 | 384 | }), |
| 409 | 385 | ); |
| 410 | | harness.setStatusBranch(worktreeCwd, "t3code/1234abcd"); |
| 411 | 386 | |
| 412 | 387 | await Effect.runPromise( |
| 413 | 388 | harness.engine.dispatch({ |
| ... | ... | @@ -450,44 +425,6 @@ describe("ProviderCommandReactor", () => { |
| 450 | 425 | expect(harness.renameBranch.mock.calls.length).toBe(1); |
| 451 | 426 | }); |
| 452 | 427 | |
| 453 | | it("skips worktree rename when active branch already changed", async () => { |
| 454 | | const harness = await createHarness(); |
| 455 | | const now = new Date().toISOString(); |
| 456 | | const worktreeCwd = "/tmp/provider-project/.t3/worktrees/t3code-badf00d0"; |
| 457 | | |
| 458 | | await Effect.runPromise( |
| 459 | | harness.engine.dispatch({ |
| 460 | | type: "thread.meta.update", |
| 461 | | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch-switched"), |
| 462 | | threadId: ThreadId.makeUnsafe("thread-1"), |
| 463 | | branch: "t3code/badf00d0", |
| 464 | | worktreePath: worktreeCwd, |
| 465 | | }), |
| 466 | | ); |
| 467 | | harness.setStatusBranch(worktreeCwd, "feature/add-vscode-open-in-support"); |
| 468 | | |
| 469 | | await Effect.runPromise( |
| 470 | | harness.engine.dispatch({ |
| 471 | | type: "thread.turn.start", |
| 472 | | commandId: CommandId.makeUnsafe("cmd-turn-start-worktree-switched"), |
| 473 | | threadId: ThreadId.makeUnsafe("thread-1"), |
| 474 | | message: { |
| 475 | | messageId: asMessageId("user-message-worktree-switched"), |
| 476 | | role: "user", |
| 477 | | text: "Fix visual bug from screenshot", |
| 478 | | attachments: [], |
| 479 | | }, |
| 480 | | approvalPolicy: "on-request", |
| 481 | | sandboxMode: "workspace-write", |
| 482 | | createdAt: now, |
| 483 | | }), |
| 484 | | ); |
| 485 | | |
| 486 | | await waitFor(() => harness.generateBranchName.mock.calls.length === 1); |
| 487 | | await Effect.runPromise(Effect.sleep("20 millis")); |
| 488 | | expect(harness.renameBranch.mock.calls.length).toBe(0); |
| 489 | | }); |
| 490 | | |
| 491 | 428 | it("skips worktree rename when branch-name generation fails", async () => { |
| 492 | 429 | const harness = await createHarness(); |
| 493 | 430 | const now = new Date().toISOString(); |