| ... | ... | @@ -88,6 +88,13 @@ import * as Socket from "effect/unstable/socket/Socket"; |
| 88 | 88 | import { vi } from "vite-plus/test"; |
| 89 | 89 | |
| 90 | 90 | const TEST_EPOCH = DateTime.makeUnsafe("1970-01-01T00:00:00.000Z"); |
| 91 | const SUCCESSFUL_GIT_EXECUTION = { |
| 92 | exitCode: ChildProcessSpawner.ExitCode(0), |
| 93 | stdout: "", |
| 94 | stderr: "", |
| 95 | stdoutTruncated: false, |
| 96 | stderrTruncated: false, |
| 97 | }; |
| 91 | 98 | const decodeTransferThreadSnapshot = Schema.decodeUnknownEffect( |
| 92 | 99 | Schema.fromJsonString(OrchestrationThreadDetailSnapshot), |
| 93 | 100 | ); |
| ... | ... | @@ -10558,7 +10565,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 10558 | 10565 | |
| 10559 | 10566 | yield* buildAppUnderTest({ |
| 10560 | 10567 | layers: { |
| 10568 | vcsDriver: { |
| 10569 | isInsideWorkTree: () => Effect.succeed(true), |
| 10570 | }, |
| 10561 | 10571 | gitVcsDriver: { |
| 10572 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 10562 | 10573 | remoteExists, |
| 10563 | 10574 | fetchRemote, |
| 10564 | 10575 | remoteBranchExists, |
| ... | ... | @@ -10722,7 +10733,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 10722 | 10733 | |
| 10723 | 10734 | yield* buildAppUnderTest({ |
| 10724 | 10735 | layers: { |
| 10736 | vcsDriver: { |
| 10737 | isInsideWorkTree: () => Effect.succeed(true), |
| 10738 | }, |
| 10725 | 10739 | gitVcsDriver: { |
| 10740 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 10726 | 10741 | remoteExists, |
| 10727 | 10742 | fetchRemote, |
| 10728 | 10743 | remoteBranchExists, |
| ... | ... | @@ -10804,6 +10819,167 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 10804 | 10819 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), |
| 10805 | 10820 | ); |
| 10806 | 10821 | |
| 10822 | it.effect("falls back to the project checkout when worktree mode targets a non-repository", () => |
| 10823 | Effect.gen(function* () { |
| 10824 | const dispatchedCommands: Array<OrchestrationCommand> = []; |
| 10825 | const createWorktree = vi.fn( |
| 10826 | (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["createWorktree"]>[0]) => |
| 10827 | Effect.die(new Error("createWorktree must not run for a non-repository")), |
| 10828 | ); |
| 10829 | |
| 10830 | yield* buildAppUnderTest({ |
| 10831 | layers: { |
| 10832 | gitVcsDriver: { |
| 10833 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 10834 | createWorktree, |
| 10835 | }, |
| 10836 | orchestrationEngine: { |
| 10837 | dispatch: (command) => |
| 10838 | Effect.sync(() => { |
| 10839 | dispatchedCommands.push(command); |
| 10840 | return { sequence: dispatchedCommands.length }; |
| 10841 | }), |
| 10842 | readEvents: () => Stream.empty, |
| 10843 | }, |
| 10844 | }, |
| 10845 | }); |
| 10846 | |
| 10847 | const createdAt = "2026-01-01T00:00:00.000Z"; |
| 10848 | const wsUrl = yield* getWsServerUrl("/ws"); |
| 10849 | const response = yield* Effect.scoped( |
| 10850 | withWsRpcClient(wsUrl, (client) => |
| 10851 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 10852 | type: "thread.turn.start", |
| 10853 | commandId: CommandId.make("cmd-bootstrap-turn-start-non-repo"), |
| 10854 | threadId: ThreadId.make("thread-bootstrap-non-repo"), |
| 10855 | message: { |
| 10856 | messageId: MessageId.make("msg-bootstrap-non-repo"), |
| 10857 | role: "user", |
| 10858 | text: "hello", |
| 10859 | attachments: [], |
| 10860 | }, |
| 10861 | modelSelection: defaultModelSelection, |
| 10862 | runtimeMode: "full-access", |
| 10863 | interactionMode: "default", |
| 10864 | bootstrap: { |
| 10865 | createThread: { |
| 10866 | projectId: defaultProjectId, |
| 10867 | title: "Bootstrap Thread", |
| 10868 | modelSelection: defaultModelSelection, |
| 10869 | runtimeMode: "full-access", |
| 10870 | interactionMode: "default", |
| 10871 | branch: null, |
| 10872 | worktreePath: null, |
| 10873 | createdAt, |
| 10874 | }, |
| 10875 | prepareWorktree: { |
| 10876 | projectCwd: "/tmp/project", |
| 10877 | baseBranch: "main", |
| 10878 | branch: "t3code/bootstrap-refName", |
| 10879 | }, |
| 10880 | runSetupScript: true, |
| 10881 | }, |
| 10882 | createdAt, |
| 10883 | }), |
| 10884 | ), |
| 10885 | ); |
| 10886 | |
| 10887 | assert.equal(response.sequence, 2); |
| 10888 | assert.equal(createWorktree.mock.calls.length, 0); |
| 10889 | assert.deepEqual( |
| 10890 | dispatchedCommands.map((command) => command.type), |
| 10891 | ["thread.create", "thread.turn.start"], |
| 10892 | ); |
| 10893 | const finalCommand = dispatchedCommands[1]; |
| 10894 | assertTrue(finalCommand?.type === "thread.turn.start"); |
| 10895 | if (finalCommand?.type === "thread.turn.start") { |
| 10896 | assert.equal(finalCommand.bootstrap, undefined); |
| 10897 | } |
| 10898 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), |
| 10899 | ); |
| 10900 | |
| 10901 | it.effect("falls back to the project checkout when the worktree base has no commit", () => |
| 10902 | Effect.gen(function* () { |
| 10903 | const dispatchedCommands: Array<OrchestrationCommand> = []; |
| 10904 | const createWorktree = vi.fn( |
| 10905 | (_: Parameters<GitVcsDriver.GitVcsDriver["Service"]["createWorktree"]>[0]) => |
| 10906 | Effect.die(new Error("createWorktree must not run without a base commit")), |
| 10907 | ); |
| 10908 | |
| 10909 | yield* buildAppUnderTest({ |
| 10910 | layers: { |
| 10911 | vcsDriver: { |
| 10912 | isInsideWorkTree: () => Effect.succeed(true), |
| 10913 | }, |
| 10914 | gitVcsDriver: { |
| 10915 | execute: () => |
| 10916 | Effect.succeed({ |
| 10917 | ...SUCCESSFUL_GIT_EXECUTION, |
| 10918 | exitCode: ChildProcessSpawner.ExitCode(128), |
| 10919 | stderr: "fatal: Needed a single revision", |
| 10920 | }), |
| 10921 | createWorktree, |
| 10922 | }, |
| 10923 | orchestrationEngine: { |
| 10924 | dispatch: (command) => |
| 10925 | Effect.sync(() => { |
| 10926 | dispatchedCommands.push(command); |
| 10927 | return { sequence: dispatchedCommands.length }; |
| 10928 | }), |
| 10929 | readEvents: () => Stream.empty, |
| 10930 | }, |
| 10931 | }, |
| 10932 | }); |
| 10933 | |
| 10934 | const createdAt = "2026-01-01T00:00:00.000Z"; |
| 10935 | const wsUrl = yield* getWsServerUrl("/ws"); |
| 10936 | const response = yield* Effect.scoped( |
| 10937 | withWsRpcClient(wsUrl, (client) => |
| 10938 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 10939 | type: "thread.turn.start", |
| 10940 | commandId: CommandId.make("cmd-bootstrap-turn-start-unborn-head"), |
| 10941 | threadId: ThreadId.make("thread-bootstrap-unborn-head"), |
| 10942 | message: { |
| 10943 | messageId: MessageId.make("msg-bootstrap-unborn-head"), |
| 10944 | role: "user", |
| 10945 | text: "hello", |
| 10946 | attachments: [], |
| 10947 | }, |
| 10948 | modelSelection: defaultModelSelection, |
| 10949 | runtimeMode: "full-access", |
| 10950 | interactionMode: "default", |
| 10951 | bootstrap: { |
| 10952 | createThread: { |
| 10953 | projectId: defaultProjectId, |
| 10954 | title: "Bootstrap Thread", |
| 10955 | modelSelection: defaultModelSelection, |
| 10956 | runtimeMode: "full-access", |
| 10957 | interactionMode: "default", |
| 10958 | branch: "main", |
| 10959 | worktreePath: null, |
| 10960 | createdAt, |
| 10961 | }, |
| 10962 | prepareWorktree: { |
| 10963 | projectCwd: "/tmp/project", |
| 10964 | baseBranch: "main", |
| 10965 | branch: "t3code/bootstrap-refName", |
| 10966 | }, |
| 10967 | runSetupScript: true, |
| 10968 | }, |
| 10969 | createdAt, |
| 10970 | }), |
| 10971 | ), |
| 10972 | ); |
| 10973 | |
| 10974 | assert.equal(response.sequence, 2); |
| 10975 | assert.equal(createWorktree.mock.calls.length, 0); |
| 10976 | assert.deepEqual( |
| 10977 | dispatchedCommands.map((command) => command.type), |
| 10978 | ["thread.create", "thread.turn.start"], |
| 10979 | ); |
| 10980 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), |
| 10981 | ); |
| 10982 | |
| 10807 | 10983 | it.effect("records setup-script failures without aborting bootstrap turn start", () => |
| 10808 | 10984 | Effect.gen(function* () { |
| 10809 | 10985 | const dispatchedCommands: Array<OrchestrationCommand> = []; |
| ... | ... | @@ -10834,7 +11010,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 10834 | 11010 | |
| 10835 | 11011 | yield* buildAppUnderTest({ |
| 10836 | 11012 | layers: { |
| 11013 | vcsDriver: { |
| 11014 | isInsideWorkTree: () => Effect.succeed(true), |
| 11015 | }, |
| 10837 | 11016 | gitVcsDriver: { |
| 11017 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 10838 | 11018 | createWorktree, |
| 10839 | 11019 | }, |
| 10840 | 11020 | orchestrationEngine: { |
| ... | ... | @@ -10939,7 +11119,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 10939 | 11119 | |
| 10940 | 11120 | yield* buildAppUnderTest({ |
| 10941 | 11121 | layers: { |
| 11122 | vcsDriver: { |
| 11123 | isInsideWorkTree: () => Effect.succeed(true), |
| 11124 | }, |
| 10942 | 11125 | gitVcsDriver: { |
| 11126 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 10943 | 11127 | createWorktree, |
| 10944 | 11128 | }, |
| 10945 | 11129 | orchestrationEngine: { |
| ... | ... | @@ -11044,7 +11228,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 11044 | 11228 | |
| 11045 | 11229 | const config = yield* buildAppUnderTest({ |
| 11046 | 11230 | layers: { |
| 11231 | vcsDriver: { |
| 11232 | isInsideWorkTree: () => Effect.succeed(true), |
| 11233 | }, |
| 11047 | 11234 | gitVcsDriver: { |
| 11235 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 11048 | 11236 | createWorktree, |
| 11049 | 11237 | }, |
| 11050 | 11238 | orchestrationEngine: { |
| ... | ... | @@ -11253,7 +11441,11 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 11253 | 11441 | |
| 11254 | 11442 | yield* buildAppUnderTest({ |
| 11255 | 11443 | layers: { |
| 11444 | vcsDriver: { |
| 11445 | isInsideWorkTree: () => Effect.succeed(true), |
| 11446 | }, |
| 11256 | 11447 | gitVcsDriver: { |
| 11448 | execute: () => Effect.succeed(SUCCESSFUL_GIT_EXECUTION), |
| 11257 | 11449 | createWorktree, |
| 11258 | 11450 | }, |
| 11259 | 11451 | orchestrationEngine: { |