@ai-hero/sandcastle 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +284 -0
  2. package/dist/AgentProvider.d.ts +8 -0
  3. package/dist/AgentProvider.d.ts.map +1 -0
  4. package/dist/AgentProvider.js +60 -0
  5. package/dist/AgentProvider.js.map +1 -0
  6. package/dist/Config.d.ts +35 -0
  7. package/dist/Config.d.ts.map +1 -0
  8. package/dist/Config.js +56 -0
  9. package/dist/Config.js.map +1 -0
  10. package/dist/CopyToSandbox.d.ts +8 -0
  11. package/dist/CopyToSandbox.d.ts.map +1 -0
  12. package/dist/CopyToSandbox.js +32 -0
  13. package/dist/CopyToSandbox.js.map +1 -0
  14. package/dist/Display.d.ts +52 -0
  15. package/dist/Display.d.ts.map +1 -0
  16. package/dist/Display.js +132 -0
  17. package/dist/Display.js.map +1 -0
  18. package/dist/DockerLifecycle.d.ts +37 -0
  19. package/dist/DockerLifecycle.d.ts.map +1 -0
  20. package/dist/DockerLifecycle.js +109 -0
  21. package/dist/DockerLifecycle.js.map +1 -0
  22. package/dist/DockerSandbox.d.ts +6 -0
  23. package/dist/DockerSandbox.d.ts.map +1 -0
  24. package/dist/DockerSandbox.js +122 -0
  25. package/dist/DockerSandbox.js.map +1 -0
  26. package/dist/EnvResolver.d.ts +11 -0
  27. package/dist/EnvResolver.d.ts.map +1 -0
  28. package/dist/EnvResolver.js +43 -0
  29. package/dist/EnvResolver.js.map +1 -0
  30. package/dist/ErrorHandler.d.ts +15 -0
  31. package/dist/ErrorHandler.d.ts.map +1 -0
  32. package/dist/ErrorHandler.js +58 -0
  33. package/dist/ErrorHandler.js.map +1 -0
  34. package/dist/FilesystemSandbox.d.ts +6 -0
  35. package/dist/FilesystemSandbox.d.ts.map +1 -0
  36. package/dist/FilesystemSandbox.js +83 -0
  37. package/dist/FilesystemSandbox.js.map +1 -0
  38. package/dist/InitService.d.ts +11 -0
  39. package/dist/InitService.d.ts.map +1 -0
  40. package/dist/InitService.js +111 -0
  41. package/dist/InitService.js.map +1 -0
  42. package/dist/Orchestrator.d.ts +49 -0
  43. package/dist/Orchestrator.d.ts.map +1 -0
  44. package/dist/Orchestrator.js +155 -0
  45. package/dist/Orchestrator.js.map +1 -0
  46. package/dist/PromptArgumentSubstitution.d.ts +6 -0
  47. package/dist/PromptArgumentSubstitution.d.ts.map +1 -0
  48. package/dist/PromptArgumentSubstitution.js +33 -0
  49. package/dist/PromptArgumentSubstitution.js.map +1 -0
  50. package/dist/PromptPreprocessor.d.ts +7 -0
  51. package/dist/PromptPreprocessor.d.ts.map +1 -0
  52. package/dist/PromptPreprocessor.js +34 -0
  53. package/dist/PromptPreprocessor.js.map +1 -0
  54. package/dist/PromptResolver.d.ts +9 -0
  55. package/dist/PromptResolver.d.ts.map +1 -0
  56. package/dist/PromptResolver.js +26 -0
  57. package/dist/PromptResolver.js.map +1 -0
  58. package/dist/RecoveryMessage.d.ts +15 -0
  59. package/dist/RecoveryMessage.d.ts.map +1 -0
  60. package/dist/RecoveryMessage.js +81 -0
  61. package/dist/RecoveryMessage.js.map +1 -0
  62. package/dist/Sandbox.d.ts +23 -0
  63. package/dist/Sandbox.d.ts.map +1 -0
  64. package/dist/Sandbox.js +5 -0
  65. package/dist/Sandbox.js.map +1 -0
  66. package/dist/SandboxFactory.d.ts +56 -0
  67. package/dist/SandboxFactory.d.ts.map +1 -0
  68. package/dist/SandboxFactory.js +219 -0
  69. package/dist/SandboxFactory.js.map +1 -0
  70. package/dist/SandboxLifecycle.d.ts +32 -0
  71. package/dist/SandboxLifecycle.d.ts.map +1 -0
  72. package/dist/SandboxLifecycle.js +152 -0
  73. package/dist/SandboxLifecycle.js.map +1 -0
  74. package/dist/SyncService.d.ts +20 -0
  75. package/dist/SyncService.d.ts.map +1 -0
  76. package/dist/SyncService.js +504 -0
  77. package/dist/SyncService.js.map +1 -0
  78. package/dist/TokenResolver.d.ts +6 -0
  79. package/dist/TokenResolver.d.ts.map +1 -0
  80. package/dist/TokenResolver.js +43 -0
  81. package/dist/TokenResolver.js.map +1 -0
  82. package/dist/WorktreeManager.d.ts +42 -0
  83. package/dist/WorktreeManager.d.ts.map +1 -0
  84. package/dist/WorktreeManager.js +170 -0
  85. package/dist/WorktreeManager.js.map +1 -0
  86. package/dist/cli.d.ts +22 -0
  87. package/dist/cli.d.ts.map +1 -0
  88. package/dist/cli.js +217 -0
  89. package/dist/cli.js.map +1 -0
  90. package/dist/errors.d.ts +95 -0
  91. package/dist/errors.d.ts.map +1 -0
  92. package/dist/errors.js +35 -0
  93. package/dist/errors.js.map +1 -0
  94. package/dist/index.d.ts +4 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +2 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/main.d.ts +3 -0
  99. package/dist/main.d.ts.map +1 -0
  100. package/dist/main.js +16 -0
  101. package/dist/main.js.map +1 -0
  102. package/dist/run.d.ts +91 -0
  103. package/dist/run.d.ts.map +1 -0
  104. package/dist/run.js +155 -0
  105. package/dist/run.js.map +1 -0
  106. package/dist/templates/blank/main.ts +9 -0
  107. package/dist/templates/blank/prompt.md +12 -0
  108. package/dist/templates/blank/template.json +4 -0
  109. package/dist/templates/parallel-planner/implement-prompt.md +62 -0
  110. package/dist/templates/parallel-planner/main.ts +200 -0
  111. package/dist/templates/parallel-planner/merge-prompt.md +22 -0
  112. package/dist/templates/parallel-planner/plan-prompt.md +33 -0
  113. package/dist/templates/parallel-planner/template.json +4 -0
  114. package/dist/templates/sequential-reviewer/implement-prompt.md +62 -0
  115. package/dist/templates/sequential-reviewer/main.ts +102 -0
  116. package/dist/templates/sequential-reviewer/review-prompt.md +43 -0
  117. package/dist/templates/sequential-reviewer/template.json +4 -0
  118. package/dist/templates/simple-loop/main.ts +37 -0
  119. package/dist/templates/simple-loop/prompt.md +51 -0
  120. package/dist/templates/simple-loop/template.json +4 -0
  121. package/dist/templates.d.ts +2 -0
  122. package/dist/templates.d.ts.map +1 -0
  123. package/dist/templates.js +26 -0
  124. package/dist/templates.js.map +1 -0
  125. package/dist/terminalCleanup.d.ts +30 -0
  126. package/dist/terminalCleanup.d.ts.map +1 -0
  127. package/dist/terminalCleanup.js +37 -0
  128. package/dist/terminalCleanup.js.map +1 -0
  129. package/dist/testSandbox.d.ts +8 -0
  130. package/dist/testSandbox.d.ts.map +1 -0
  131. package/dist/testSandbox.js +101 -0
  132. package/dist/testSandbox.js.map +1 -0
  133. package/package.json +62 -0
@@ -0,0 +1,20 @@
1
+ import { Effect } from "effect";
2
+ import { ExecError } from "./errors.js";
3
+ import { type ExecResult, Sandbox, type SandboxError, type SandboxService } from "./Sandbox.js";
4
+ export declare const execOk: (sandbox: SandboxService, command: string, options?: {
5
+ cwd?: string | undefined;
6
+ } | undefined) => Effect.Effect<ExecResult, ExecError, never>;
7
+ export declare const runHooks: (hooks: readonly {
8
+ readonly command: string;
9
+ }[] | undefined, options?: {
10
+ cwd?: string | undefined;
11
+ } | undefined) => Effect.Effect<void, ExecError, Sandbox>;
12
+ export declare const syncIn: (hostRepoDir: string, sandboxRepoDir: string, options?: {
13
+ branch?: string | undefined;
14
+ } | undefined) => Effect.Effect<{
15
+ branch: string;
16
+ }, SandboxError, Sandbox>;
17
+ export declare const syncOut: (hostRepoDir: string, sandboxRepoDir: string, baseHead: string, options?: {
18
+ branch?: string | undefined;
19
+ } | undefined) => Effect.Effect<void, SandboxError, Sandbox>;
20
+ //# sourceMappingURL=SyncService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncService.d.ts","sourceRoot":"","sources":["../src/SyncService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAehC,OAAO,EAAE,SAAS,EAA4B,MAAM,aAAa,CAAC;AAClE,OAAO,EACL,KAAK,UAAU,EACf,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AA4BtB,eAAO,MAAM,MAAM;;6DAchB,CAAC;AAEJ,eAAO,MAAM,QAAQ;;;;yDAUjB,CAAC;AAEL,eAAO,MAAM,MAAM;;;;yBA0Kf,CAAC;AAEL,eAAO,MAAM,OAAO;;4DA2BhB,CAAC"}
@@ -0,0 +1,504 @@
1
+ import { Effect } from "effect";
2
+ import { execFile } from "node:child_process";
3
+ import { copyFile, mkdir, mkdtemp, readdir, readFile, rm, stat, } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join, relative } from "node:path";
6
+ import { buildRecoveryMessage } from "./RecoveryMessage.js";
7
+ import { ExecError, ExecHostError, SyncError } from "./errors.js";
8
+ import { Sandbox, } from "./Sandbox.js";
9
+ const execHost = (command, cwd) => Effect.async((resume) => {
10
+ execFile("sh", ["-c", command], { cwd, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
11
+ if (error) {
12
+ resume(Effect.fail(new ExecHostError({
13
+ command,
14
+ message: `${command}: ${stderr?.toString() || error.message}`,
15
+ })));
16
+ }
17
+ else {
18
+ resume(Effect.succeed(stdout.toString()));
19
+ }
20
+ });
21
+ });
22
+ export const execOk = (sandbox, command, options) => Effect.flatMap(sandbox.exec(command, options), (result) => result.exitCode !== 0
23
+ ? Effect.fail(new ExecError({
24
+ command,
25
+ message: `Command failed (exit ${result.exitCode}): ${command}\n${result.stderr}`,
26
+ }))
27
+ : Effect.succeed(result));
28
+ export const runHooks = (hooks, options) => Effect.gen(function* () {
29
+ if (!hooks || hooks.length === 0)
30
+ return;
31
+ const sandbox = yield* Sandbox;
32
+ for (const hook of hooks) {
33
+ yield* execOk(sandbox, hook.command, options);
34
+ }
35
+ });
36
+ export const syncIn = (hostRepoDir, sandboxRepoDir, options) => Effect.gen(function* () {
37
+ const sandbox = yield* Sandbox;
38
+ // Get current branch from host
39
+ const hostBranch = (yield* execHost("git rev-parse --abbrev-ref HEAD", hostRepoDir)).trim();
40
+ // The branch to check out in the sandbox
41
+ const branch = options?.branch ?? hostBranch;
42
+ // Create git bundle on host
43
+ const bundleDir = yield* Effect.promise(() => mkdtemp(join(tmpdir(), "sandcastle-bundle-")));
44
+ const bundleHostPath = join(bundleDir, "repo.bundle");
45
+ yield* execHost(`git bundle create "${bundleHostPath}" --all`, hostRepoDir);
46
+ // Detect if --branch target exists on the host
47
+ const branchExistsOnHost = branch !== hostBranch
48
+ ? yield* Effect.map(Effect.either(execHost(`git rev-parse --verify "refs/heads/${branch}"`, hostRepoDir)), (either) => either._tag === "Right")
49
+ : true; // hostBranch always exists
50
+ // Create temp dir in sandbox for the bundle
51
+ const sandboxTmpDir = (yield* execOk(sandbox, "mktemp -d -t sandcastle-XXXXXX")).stdout.trim();
52
+ const bundleSandboxPath = `${sandboxTmpDir}/repo.bundle`;
53
+ // Copy bundle into sandbox
54
+ yield* sandbox.copyIn(bundleHostPath, bundleSandboxPath);
55
+ // Check if sandbox repo already initialized
56
+ const gitCheck = yield* sandbox.exec(`test -d "${sandboxRepoDir}/.git" && echo yes || echo no`);
57
+ const repoExists = gitCheck.stdout.trim() === "yes";
58
+ // Determine the ref to fetch and sync to
59
+ const fetchRef = branchExistsOnHost ? branch : hostBranch;
60
+ const isNewBranch = !branchExistsOnHost;
61
+ if (repoExists) {
62
+ // Fetch bundle into temp ref, reset to match host
63
+ yield* execOk(sandbox, `git fetch "${bundleSandboxPath}" "${fetchRef}:refs/sandcastle/sync" --force`, { cwd: sandboxRepoDir });
64
+ if (isNewBranch) {
65
+ // Create new branch from host HEAD
66
+ yield* execOk(sandbox, `git checkout -B "${branch}" refs/sandcastle/sync`, { cwd: sandboxRepoDir });
67
+ }
68
+ else {
69
+ yield* execOk(sandbox, `git checkout -B "${branch}" refs/sandcastle/sync`, { cwd: sandboxRepoDir });
70
+ yield* execOk(sandbox, "git reset --hard refs/sandcastle/sync", {
71
+ cwd: sandboxRepoDir,
72
+ });
73
+ }
74
+ yield* execOk(sandbox, "git clean -fdx -e node_modules", {
75
+ cwd: sandboxRepoDir,
76
+ });
77
+ }
78
+ else {
79
+ // Clone from bundle
80
+ yield* execOk(sandbox, `git clone "${bundleSandboxPath}" "${sandboxRepoDir}"`);
81
+ if (branchExistsOnHost) {
82
+ yield* execOk(sandbox, `git checkout "${branch}"`, {
83
+ cwd: sandboxRepoDir,
84
+ });
85
+ }
86
+ else {
87
+ yield* execOk(sandbox, `git checkout "${hostBranch}"`, {
88
+ cwd: sandboxRepoDir,
89
+ });
90
+ // Create new branch from host HEAD
91
+ yield* execOk(sandbox, `git checkout -b "${branch}"`, {
92
+ cwd: sandboxRepoDir,
93
+ });
94
+ }
95
+ }
96
+ // Configure remotes from host
97
+ const hostRemotes = (yield* execHost("git remote -v", hostRepoDir)).trim();
98
+ if (hostRemotes.length > 0) {
99
+ // Parse unique remote names and their fetch URLs
100
+ const remotes = new Map();
101
+ for (const line of hostRemotes.split("\n")) {
102
+ const match = line.match(/^(\S+)\t(\S+)\s+\(fetch\)$/);
103
+ if (match) {
104
+ remotes.set(match[1], match[2]);
105
+ }
106
+ }
107
+ // Get existing sandbox remotes
108
+ const sandboxRemotes = (yield* execOk(sandbox, "git remote", {
109
+ cwd: sandboxRepoDir,
110
+ })).stdout
111
+ .trim()
112
+ .split("\n")
113
+ .filter((r) => r.length > 0);
114
+ for (const [name, url] of remotes) {
115
+ if (sandboxRemotes.includes(name)) {
116
+ yield* execOk(sandbox, `git remote set-url "${name}" "${url}"`, {
117
+ cwd: sandboxRepoDir,
118
+ });
119
+ }
120
+ else {
121
+ yield* execOk(sandbox, `git remote add "${name}" "${url}"`, {
122
+ cwd: sandboxRepoDir,
123
+ });
124
+ }
125
+ }
126
+ // Remove sandbox remotes that don't exist on host
127
+ for (const name of sandboxRemotes) {
128
+ if (!remotes.has(name)) {
129
+ yield* execOk(sandbox, `git remote remove "${name}"`, {
130
+ cwd: sandboxRepoDir,
131
+ });
132
+ }
133
+ }
134
+ }
135
+ // Clean up temp files
136
+ yield* sandbox.exec(`rm -rf "${sandboxTmpDir}"`);
137
+ yield* Effect.promise(() => rm(bundleDir, { recursive: true }));
138
+ // Verify sync succeeded — compare against the ref we synced to
139
+ const expectedHead = (yield* execHost(`git rev-parse "refs/heads/${fetchRef}"`, hostRepoDir)).trim();
140
+ const sandboxHead = (yield* execOk(sandbox, "git rev-parse HEAD", {
141
+ cwd: sandboxRepoDir,
142
+ })).stdout.trim();
143
+ if (expectedHead !== sandboxHead) {
144
+ yield* Effect.fail(new SyncError({
145
+ message: `HEAD mismatch after sync: host=${expectedHead} sandbox=${sandboxHead}`,
146
+ }));
147
+ }
148
+ return { branch };
149
+ });
150
+ export const syncOut = (hostRepoDir, sandboxRepoDir, baseHead, options) => Effect.gen(function* () {
151
+ const sandbox = yield* Sandbox;
152
+ // Determine if we need worktree-based sync
153
+ const targetBranch = options?.branch;
154
+ const hostBranch = targetBranch
155
+ ? (yield* execHost("git rev-parse --abbrev-ref HEAD", hostRepoDir)).trim()
156
+ : undefined;
157
+ const useWorktree = targetBranch != null && targetBranch !== hostBranch;
158
+ if (useWorktree) {
159
+ yield* syncOutViaWorktree(sandbox, hostRepoDir, sandboxRepoDir, baseHead, targetBranch);
160
+ }
161
+ else {
162
+ yield* syncOutDirect(sandbox, hostRepoDir, sandboxRepoDir, baseHead);
163
+ }
164
+ });
165
+ /** Format a timestamp as YYYYMMDD-HHMMSS */
166
+ const formatTimestamp = (date) => {
167
+ const pad = (n) => String(n).padStart(2, "0");
168
+ return (`${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-` +
169
+ `${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`);
170
+ };
171
+ /** Create a unique timestamped directory under .sandcastle/patches/ */
172
+ const createPatchDir = async (hostRepoDir) => {
173
+ const base = formatTimestamp(new Date());
174
+ const patchesDir = join(hostRepoDir, ".sandcastle", "patches");
175
+ await mkdir(patchesDir, { recursive: true });
176
+ // Ensure uniqueness by appending a counter if the dir already exists
177
+ let dir = join(patchesDir, base);
178
+ let counter = 0;
179
+ while (true) {
180
+ try {
181
+ await mkdir(dir);
182
+ return dir;
183
+ }
184
+ catch (e) {
185
+ if (e.code === "EEXIST") {
186
+ counter++;
187
+ dir = join(patchesDir, `${base}-${counter}`);
188
+ }
189
+ else {
190
+ throw e;
191
+ }
192
+ }
193
+ }
194
+ };
195
+ /** Eagerly save all patch artifacts to .sandcastle/patches/<timestamp>/ */
196
+ const saveArtifacts = (sandbox, hostRepoDir, sandboxRepoDir, baseHead) => Effect.gen(function* () {
197
+ const patchDir = yield* Effect.promise(() => createPatchDir(hostRepoDir));
198
+ let hasCommits = false;
199
+ let hasDiff = false;
200
+ let hasUntracked = false;
201
+ // --- 1. Save committed patches ---
202
+ const sandboxHead = (yield* execOk(sandbox, "git rev-parse HEAD", {
203
+ cwd: sandboxRepoDir,
204
+ })).stdout.trim();
205
+ if (sandboxHead !== baseHead) {
206
+ const countResult = yield* execOk(sandbox, `git rev-list "${baseHead}..HEAD" --count`, { cwd: sandboxRepoDir });
207
+ const commitCount = parseInt(countResult.stdout.trim(), 10);
208
+ if (commitCount > 0) {
209
+ hasCommits = true;
210
+ const hostPatchDir = yield* generateAndCopyPatches(sandbox, sandboxRepoDir, baseHead);
211
+ // Move patch files into the persistent directory
212
+ const patchFiles = (yield* Effect.promise(() => readdir(hostPatchDir))).filter((f) => f.endsWith(".patch"));
213
+ for (const file of patchFiles) {
214
+ yield* Effect.promise(() => copyFile(join(hostPatchDir, file), join(patchDir, file)));
215
+ }
216
+ yield* Effect.promise(() => rm(hostPatchDir, { recursive: true }));
217
+ }
218
+ }
219
+ // --- 2. Save uncommitted diff ---
220
+ const diffCheck = yield* sandbox.exec("git diff HEAD --quiet", {
221
+ cwd: sandboxRepoDir,
222
+ });
223
+ if (diffCheck.exitCode !== 0) {
224
+ hasDiff = true;
225
+ const sandboxDiffDir = (yield* execOk(sandbox, "mktemp -d -t sandcastle-diff-XXXXXX")).stdout.trim();
226
+ const sandboxDiffFile = `${sandboxDiffDir}/changes.patch`;
227
+ yield* execOk(sandbox, `git diff HEAD > "${sandboxDiffFile}"`, {
228
+ cwd: sandboxRepoDir,
229
+ });
230
+ yield* sandbox.copyOut(sandboxDiffFile, join(patchDir, "changes.patch"));
231
+ yield* sandbox.exec(`rm -rf "${sandboxDiffDir}"`);
232
+ }
233
+ // --- 3. Save untracked files ---
234
+ const untrackedResult = yield* sandbox.exec("git ls-files --others --exclude-standard", { cwd: sandboxRepoDir });
235
+ if (untrackedResult.exitCode === 0 &&
236
+ untrackedResult.stdout.trim().length > 0) {
237
+ const untrackedFiles = untrackedResult.stdout
238
+ .trim()
239
+ .split("\n")
240
+ .filter((f) => f.length > 0);
241
+ if (untrackedFiles.length > 0) {
242
+ hasUntracked = true;
243
+ const untrackedDir = join(patchDir, "untracked");
244
+ yield* Effect.promise(() => mkdir(untrackedDir, { recursive: true }));
245
+ for (const file of untrackedFiles) {
246
+ const destPath = join(untrackedDir, file);
247
+ const destDir = join(untrackedDir, file.split("/").slice(0, -1).join("/"));
248
+ if (destDir !== untrackedDir) {
249
+ yield* Effect.promise(() => mkdir(destDir, { recursive: true }));
250
+ }
251
+ yield* sandbox.copyOut(`${sandboxRepoDir}/${file}`, destPath);
252
+ }
253
+ }
254
+ }
255
+ return { patchDir, hasCommits, hasDiff, hasUntracked };
256
+ });
257
+ /** Apply patches directly to the host's current branch (existing behavior) */
258
+ const syncOutDirect = (sandbox, hostRepoDir, sandboxRepoDir, baseHead) => Effect.gen(function* () {
259
+ const sandboxHead = (yield* execOk(sandbox, "git rev-parse HEAD", {
260
+ cwd: sandboxRepoDir,
261
+ })).stdout.trim();
262
+ // Check if there's anything to do
263
+ const diffCheck = yield* sandbox.exec("git diff HEAD --quiet", {
264
+ cwd: sandboxRepoDir,
265
+ });
266
+ const untrackedResult = yield* sandbox.exec("git ls-files --others --exclude-standard", { cwd: sandboxRepoDir });
267
+ const hasAnyChanges = sandboxHead !== baseHead ||
268
+ diffCheck.exitCode !== 0 ||
269
+ (untrackedResult.exitCode === 0 &&
270
+ untrackedResult.stdout.trim().length > 0);
271
+ if (!hasAnyChanges)
272
+ return;
273
+ // Phase 1: Eagerly save all artifacts
274
+ const { patchDir, hasCommits, hasDiff, hasUntracked } = yield* saveArtifacts(sandbox, hostRepoDir, sandboxRepoDir, baseHead);
275
+ // Phase 2: Apply from the saved directory, tracking which step we're on
276
+ let currentStep;
277
+ const applyEffect = Effect.gen(function* () {
278
+ // Apply committed patches
279
+ if (hasCommits) {
280
+ currentStep = "commits";
281
+ const patchFiles = (yield* Effect.promise(() => readdir(patchDir)))
282
+ .filter((f) => f.endsWith(".patch") && f !== "changes.patch")
283
+ .sort();
284
+ // Skip empty patches (e.g. from merge commits — git format-patch
285
+ // produces 0-byte files or header-only patches with no diff)
286
+ const nonEmptyPatchFiles = [];
287
+ for (const file of patchFiles) {
288
+ const filePath = join(patchDir, file);
289
+ const { size } = yield* Effect.promise(() => stat(filePath));
290
+ if (size === 0)
291
+ continue;
292
+ const content = yield* Effect.promise(() => readFile(filePath, "utf-8"));
293
+ if (!content.includes("diff "))
294
+ continue;
295
+ nonEmptyPatchFiles.push(file);
296
+ }
297
+ // Abort any leftover git am session
298
+ yield* Effect.ignore(execHost("git am --abort", hostRepoDir));
299
+ for (const file of nonEmptyPatchFiles) {
300
+ yield* execHost(`git am --3way "${join(patchDir, file)}"`, hostRepoDir);
301
+ }
302
+ }
303
+ // Apply uncommitted diff
304
+ if (hasDiff) {
305
+ currentStep = "diff";
306
+ yield* execHost(`git apply "${join(patchDir, "changes.patch")}"`, hostRepoDir);
307
+ }
308
+ // Copy untracked files
309
+ if (hasUntracked) {
310
+ currentStep = "untracked";
311
+ const untrackedDir = join(patchDir, "untracked");
312
+ const files = yield* Effect.promise(() => readdir(untrackedDir));
313
+ for (const file of files) {
314
+ const src = join(untrackedDir, file);
315
+ const dest = join(hostRepoDir, file);
316
+ yield* Effect.promise(() => copyFile(src, dest));
317
+ }
318
+ }
319
+ });
320
+ // On success, clean up the patch directory. On failure, generate recovery message.
321
+ yield* Effect.matchEffect(applyEffect, {
322
+ onSuccess: () => Effect.promise(() => rm(patchDir, { recursive: true, force: true })),
323
+ onFailure: (error) => {
324
+ const relativePatchDir = relative(hostRepoDir, patchDir);
325
+ const recovery = currentStep
326
+ ? buildRecoveryMessage({
327
+ patchDir: relativePatchDir,
328
+ failedStep: currentStep,
329
+ hasCommits,
330
+ hasDiff,
331
+ hasUntracked,
332
+ })
333
+ : "";
334
+ const errorMsg = error.message + (recovery ? `\n\n${recovery}` : "");
335
+ return Effect.fail(new SyncError({ message: errorMsg }));
336
+ },
337
+ });
338
+ });
339
+ /** Create a WIP commit in the sandbox for any uncommitted/untracked changes */
340
+ const createWipCommit = (sandbox, sandboxRepoDir) => Effect.gen(function* () {
341
+ // Check for uncommitted changes (staged + unstaged)
342
+ const diffCheck = yield* sandbox.exec("git diff HEAD --quiet", {
343
+ cwd: sandboxRepoDir,
344
+ });
345
+ const stagedCheck = yield* sandbox.exec("git diff --cached --quiet", {
346
+ cwd: sandboxRepoDir,
347
+ });
348
+ // Check for untracked files
349
+ const untrackedResult = yield* sandbox.exec("git ls-files --others --exclude-standard", { cwd: sandboxRepoDir });
350
+ const untrackedFiles = untrackedResult.exitCode === 0 && untrackedResult.stdout.trim().length > 0
351
+ ? untrackedResult.stdout
352
+ .trim()
353
+ .split("\n")
354
+ .filter((f) => f.length > 0)
355
+ : [];
356
+ const hasUncommitted = diffCheck.exitCode !== 0 ||
357
+ stagedCheck.exitCode !== 0 ||
358
+ untrackedFiles.length > 0;
359
+ if (!hasUncommitted)
360
+ return false;
361
+ // Stage everything
362
+ yield* execOk(sandbox, "git add -A", { cwd: sandboxRepoDir });
363
+ // Build a detailed WIP commit message listing affected files
364
+ const statusResult = yield* execOk(sandbox, "git diff --cached --name-status", {
365
+ cwd: sandboxRepoDir,
366
+ });
367
+ const fileList = statusResult.stdout.trim();
368
+ const message = [
369
+ "WIP: uncommitted sandbox changes",
370
+ "",
371
+ "These are uncommitted changes from a sandcastle sandbox run.",
372
+ "They were auto-committed to preserve work that would otherwise be lost.",
373
+ "",
374
+ "Affected files:",
375
+ ...fileList
376
+ .split("\n")
377
+ .filter((l) => l.length > 0)
378
+ .map((l) => ` ${l}`),
379
+ ].join("\n");
380
+ yield* execOk(sandbox, `git commit -m ${JSON.stringify(message)}`, {
381
+ cwd: sandboxRepoDir,
382
+ });
383
+ return true;
384
+ });
385
+ /** Apply committed patches to a target branch via a temporary git worktree */
386
+ const syncOutViaWorktree = (sandbox, hostRepoDir, sandboxRepoDir, baseHead, targetBranch) => Effect.gen(function* () {
387
+ // Create WIP commit for any uncommitted/untracked changes
388
+ yield* createWipCommit(sandbox, sandboxRepoDir);
389
+ // Check if there are new commits to apply (including WIP)
390
+ const sandboxHead = (yield* execOk(sandbox, "git rev-parse HEAD", {
391
+ cwd: sandboxRepoDir,
392
+ })).stdout.trim();
393
+ if (sandboxHead === baseHead) {
394
+ // No commits and no uncommitted changes — nothing to do
395
+ return;
396
+ }
397
+ const countResult = yield* execOk(sandbox, `git rev-list "${baseHead}..HEAD" --count`, { cwd: sandboxRepoDir });
398
+ const commitCount = parseInt(countResult.stdout.trim(), 10);
399
+ if (commitCount === 0)
400
+ return;
401
+ // Phase 1: Eagerly save patches to persistent timestamped directory
402
+ const patchDir = yield* Effect.promise(() => createPatchDir(hostRepoDir));
403
+ const hostPatchDir = yield* generateAndCopyPatches(sandbox, sandboxRepoDir, baseHead);
404
+ // Move patch files into the persistent directory
405
+ const patchFiles = (yield* Effect.promise(() => readdir(hostPatchDir))).filter((f) => f.endsWith(".patch"));
406
+ for (const file of patchFiles) {
407
+ yield* Effect.promise(() => copyFile(join(hostPatchDir, file), join(patchDir, file)));
408
+ }
409
+ yield* Effect.promise(() => rm(hostPatchDir, { recursive: true }));
410
+ // Phase 2: Create worktree, apply patches
411
+ const worktreeDir = yield* Effect.promise(() => mkdtemp(join(tmpdir(), "sandcastle-worktree-")));
412
+ // Check if target branch already exists on host and record its tip
413
+ const branchExistsResult = yield* Effect.either(execHost(`git rev-parse --verify "refs/heads/${targetBranch}"`, hostRepoDir));
414
+ const branchExists = branchExistsResult._tag === "Right";
415
+ const originalBranchTip = branchExists
416
+ ? branchExistsResult.right.trim()
417
+ : undefined;
418
+ const applyEffect = Effect.ensuring(
419
+ // Try: create worktree and apply patches
420
+ Effect.gen(function* () {
421
+ if (branchExists) {
422
+ yield* execHost(`git worktree add "${worktreeDir}/wt" "${targetBranch}"`, hostRepoDir);
423
+ }
424
+ else {
425
+ yield* execHost(`git worktree add "${worktreeDir}/wt" -b "${targetBranch}" HEAD`, hostRepoDir);
426
+ }
427
+ // Abort any leftover git am session
428
+ yield* Effect.ignore(execHost("git am --abort", `${worktreeDir}/wt`));
429
+ // Apply patches in the worktree
430
+ const sortedFiles = (yield* Effect.promise(() => readdir(patchDir)))
431
+ .filter((f) => f.endsWith(".patch"))
432
+ .sort();
433
+ for (const file of sortedFiles) {
434
+ yield* execHost(`git am --3way "${join(patchDir, file)}"`, `${worktreeDir}/wt`);
435
+ }
436
+ }),
437
+ // Finally: always clean up worktree (but not patches)
438
+ Effect.gen(function* () {
439
+ yield* Effect.ignore(execHost(`git worktree remove "${worktreeDir}/wt" --force`, hostRepoDir));
440
+ yield* Effect.promise(() => rm(worktreeDir, { recursive: true, force: true }));
441
+ }));
442
+ // On success, clean up patch dir. On failure, generate recovery message.
443
+ yield* Effect.matchEffect(applyEffect, {
444
+ onSuccess: () => Effect.promise(() => rm(patchDir, { recursive: true, force: true })),
445
+ onFailure: (error) => Effect.gen(function* () {
446
+ // Roll back the branch to its original state (all-or-nothing)
447
+ if (originalBranchTip) {
448
+ yield* Effect.ignore(execHost(`git update-ref "refs/heads/${targetBranch}" "${originalBranchTip}"`, hostRepoDir));
449
+ }
450
+ else {
451
+ // Branch was newly created — delete it
452
+ yield* Effect.ignore(execHost(`git branch -D "${targetBranch}"`, hostRepoDir));
453
+ }
454
+ const relativePatchDir = relative(hostRepoDir, patchDir);
455
+ const recovery = buildRecoveryMessage({
456
+ patchDir: relativePatchDir,
457
+ failedStep: "commits",
458
+ hasCommits: true,
459
+ hasDiff: false,
460
+ hasUntracked: false,
461
+ branch: targetBranch,
462
+ });
463
+ const errorMsg = error.message + `\n\n${recovery}`;
464
+ yield* Effect.fail(new SyncError({ message: errorMsg }));
465
+ }),
466
+ });
467
+ });
468
+ /** Generate format-patch files in sandbox and copy them to host temp dir */
469
+ const generateAndCopyPatches = (sandbox, sandboxRepoDir, baseHead) => Effect.gen(function* () {
470
+ const sandboxPatchDir = (yield* execOk(sandbox, "mktemp -d -t sandcastle-patches-XXXXXX")).stdout.trim();
471
+ yield* execOk(sandbox, `git format-patch "${baseHead}..HEAD" -o "${sandboxPatchDir}"`, { cwd: sandboxRepoDir });
472
+ const hostPatchDir = yield* Effect.promise(() => mkdtemp(join(tmpdir(), "sandcastle-patches-")));
473
+ const patchListResult = yield* execOk(sandbox, `ls "${sandboxPatchDir}"/*.patch`);
474
+ const patchFiles = patchListResult.stdout
475
+ .trim()
476
+ .split("\n")
477
+ .filter((f) => f.length > 0);
478
+ for (const sandboxPatchPath of patchFiles) {
479
+ const filename = sandboxPatchPath.split("/").pop();
480
+ const hostPatchPath = join(hostPatchDir, filename);
481
+ yield* sandbox.copyOut(sandboxPatchPath, hostPatchPath);
482
+ }
483
+ yield* sandbox.exec(`rm -rf "${sandboxPatchDir}"`);
484
+ return hostPatchDir;
485
+ });
486
+ /** Apply patches directly to a host repo dir */
487
+ const applyPatches = (sandbox, hostRepoDir, sandboxRepoDir, baseHead) => Effect.gen(function* () {
488
+ const countResult = yield* execOk(sandbox, `git rev-list "${baseHead}..HEAD" --count`, { cwd: sandboxRepoDir });
489
+ const commitCount = parseInt(countResult.stdout.trim(), 10);
490
+ if (commitCount > 0) {
491
+ const hostPatchDir = yield* generateAndCopyPatches(sandbox, sandboxRepoDir, baseHead);
492
+ // Abort any leftover git am session
493
+ yield* Effect.ignore(execHost("git am --abort", hostRepoDir));
494
+ // Apply patches in order
495
+ const sortedFiles = (yield* Effect.promise(() => readdir(hostPatchDir)))
496
+ .filter((f) => f.endsWith(".patch"))
497
+ .sort();
498
+ for (const file of sortedFiles) {
499
+ yield* execHost(`git am --3way "${join(hostPatchDir, file)}"`, hostRepoDir);
500
+ }
501
+ yield* Effect.promise(() => rm(hostPatchDir, { recursive: true }));
502
+ }
503
+ });
504
+ //# sourceMappingURL=SyncService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncService.js","sourceRoot":"","sources":["../src/SyncService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface ResolvedTokens {
2
+ readonly oauthToken: string;
3
+ readonly ghToken: string;
4
+ }
5
+ export declare const resolveTokens: (repoDir: string) => Promise<ResolvedTokens>;
6
+ //# sourceMappingURL=TokenResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenResolver.d.ts","sourceRoot":"","sources":["../src/TokenResolver.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAuBD,eAAO,MAAM,aAAa,8CAgCzB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ const parseEnvFile = async (filePath) => {
4
+ try {
5
+ const content = await readFile(filePath, "utf-8");
6
+ const vars = {};
7
+ for (const line of content.split("\n")) {
8
+ const trimmed = line.trim();
9
+ if (!trimmed || trimmed.startsWith("#"))
10
+ continue;
11
+ const eqIndex = trimmed.indexOf("=");
12
+ if (eqIndex === -1)
13
+ continue;
14
+ const key = trimmed.slice(0, eqIndex).trim();
15
+ const value = trimmed.slice(eqIndex + 1).trim();
16
+ if (value)
17
+ vars[key] = value;
18
+ }
19
+ return vars;
20
+ }
21
+ catch {
22
+ return {};
23
+ }
24
+ };
25
+ export const resolveTokens = async (repoDir) => {
26
+ // Precedence: repo root .env > .sandcastle/.env > process env
27
+ const rootEnv = await parseEnvFile(join(repoDir, ".env"));
28
+ const sandcastleEnv = await parseEnvFile(join(repoDir, ".sandcastle", ".env"));
29
+ const oauthToken = rootEnv["CLAUDE_CODE_OAUTH_TOKEN"] ??
30
+ sandcastleEnv["CLAUDE_CODE_OAUTH_TOKEN"] ??
31
+ process.env["CLAUDE_CODE_OAUTH_TOKEN"];
32
+ const ghToken = rootEnv["GH_TOKEN"] ??
33
+ sandcastleEnv["GH_TOKEN"] ??
34
+ process.env["GH_TOKEN"];
35
+ if (!oauthToken) {
36
+ throw new Error("CLAUDE_CODE_OAUTH_TOKEN not found. Set it in .env, .sandcastle/.env, or as an environment variable.");
37
+ }
38
+ if (!ghToken) {
39
+ throw new Error("GH_TOKEN not found. Set it in .env, .sandcastle/.env, or as an environment variable.");
40
+ }
41
+ return { oauthToken, ghToken };
42
+ };
43
+ //# sourceMappingURL=TokenResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenResolver.js","sourceRoot":"","sources":["../src/TokenResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOjC,MAAM,YAAY,GAAG,KAAK,EACxB,QAAgB,EACiB,EAAE;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,GAA2B,EAAE,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAClD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,OAAO,KAAK,CAAC,CAAC;gBAAE,SAAS;YAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAChD,IAAI,KAAK;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,OAAe,EACU,EAAE;IAC3B,8DAA8D;IAC9D,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,MAAM,YAAY,CACtC,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,CACrC,CAAC;IAEF,MAAM,UAAU,GACd,OAAO,CAAC,yBAAyB,CAAC;QAClC,aAAa,CAAC,yBAAyB,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAEzC,MAAM,OAAO,GACX,OAAO,CAAC,UAAU,CAAC;QACnB,aAAa,CAAC,UAAU,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAE1B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,qGAAqG,CACtG,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC,CAAC"}