@snappedly-tools/shipyard 0.5.0-staging.36072068333 → 0.6.0
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.
- package/README.md +165 -64
- package/dist/MountConfig-bZoCs4Dd.d.ts +26 -0
- package/dist/SandboxProvider-XJQqEdSf.d.ts +261 -0
- package/dist/{chunk-JI3HDDMS.js → chunk-56TDSWFU.js} +3 -3
- package/dist/{chunk-JI3HDDMS.js.map → chunk-56TDSWFU.js.map} +1 -1
- package/dist/chunk-ACD46ZM4.js +136 -0
- package/dist/chunk-ACD46ZM4.js.map +1 -0
- package/dist/{chunk-L6PX5QTU.js → chunk-FDYOTN55.js} +887 -262
- package/dist/chunk-FDYOTN55.js.map +1 -0
- package/dist/chunk-KMGNFXKN.js +38 -0
- package/dist/chunk-KMGNFXKN.js.map +1 -0
- package/dist/chunk-SOJTAJTF.js +78 -0
- package/dist/chunk-SOJTAJTF.js.map +1 -0
- package/dist/{chunk-44I2BL6E.js → chunk-WAXEMZUV.js} +33 -225
- package/dist/chunk-WAXEMZUV.js.map +1 -0
- package/dist/index.d.ts +97 -117
- package/dist/index.js +344 -322
- package/dist/index.js.map +1 -1
- package/dist/main.js +139 -235
- package/dist/main.js.map +1 -1
- package/dist/sandboxes/docker.d.ts +3 -1
- package/dist/sandboxes/docker.js +4 -2
- package/dist/sandboxes/no-sandbox.d.ts +37 -0
- package/dist/sandboxes/no-sandbox.js +4 -0
- package/dist/sandboxes/no-sandbox.js.map +1 -0
- package/dist/sandboxes/vercel.d.ts +104 -0
- package/dist/sandboxes/vercel.js +166 -0
- package/dist/sandboxes/vercel.js.map +1 -0
- package/dist/templates/blank/main.mts +13 -0
- package/dist/templates/blank/prompt.md +12 -0
- package/dist/templates/blank/template.json +4 -0
- package/dist/templates/parallel-planner/main.mts +9 -67
- package/dist/templates/parallel-planner-with-review/main.mts +12 -70
- package/dist/templates/sequential-reviewer/main.mts +3 -52
- package/dist/templates/simple-loop/main.mts +2 -51
- package/package.json +17 -1
- package/dist/MountConfig-BHnKnA4h.d.ts +0 -145
- package/dist/chunk-44I2BL6E.js.map +0 -1
- package/dist/chunk-L6PX5QTU.js.map +0 -1
- package/dist/templates/parallel-planner/planner-branch.mts +0 -151
- package/dist/templates/parallel-planner-with-review/planner-branch.mts +0 -151
package/dist/index.js
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
|
-
import { CODEX_MODELS, resolveEnv, formatErrorMessage, buildLogDirectoryName } from './chunk-
|
|
2
|
-
export { CODEX_MODELS, CODEX_REASONING_EFFORTS } from './chunk-
|
|
3
|
-
import { CwdError, resolveCwd, getCurrentBranch, generateTempBranchName, assertNoSymlinkComponents, FileDisplay, ClackDisplay, WorktreeDockerSandboxFactory, SandboxConfig, Display, CLI_NAME, PRODUCT_NAME, pruneStale, create, runHostHooks, startSandbox, remove, makeSandboxFromHandle, withSandboxLifecycle, hasUncommittedChanges,
|
|
4
|
-
|
|
1
|
+
import { CODEX_MODELS, resolveEnv, formatErrorMessage, buildLogDirectoryName } from './chunk-56TDSWFU.js';
|
|
2
|
+
export { CODEX_MODELS, CODEX_REASONING_EFFORTS } from './chunk-56TDSWFU.js';
|
|
3
|
+
import { CwdError, resolveCwd, getCurrentBranch, generateTempBranchName, assertNoSymlinkComponents, FileDisplay, ClackDisplay, WorktreeDockerSandboxFactory, SandboxConfig, Display, CLI_NAME, PRODUCT_NAME, pruneStale, create, copyToWorktree, runHostHooks, startSandbox, resolveGitMounts, patchGitMountsForWindows, SANDBOX_REPO_DIR, remove, makeSandboxFromHandle, syncOut, withSandboxLifecycle, hasUncommittedChanges, registerShutdown, SandboxFactory, PromptError, CONFIG_DIR, LOGS_DIR, AgentError, SessionCaptureError, PromptExpansionTimeoutError, SilentDisplay, AgentIdleTimeoutError } from './chunk-FDYOTN55.js';
|
|
4
|
+
import { shellQuote, toSessionTransferHandle } from './chunk-KMGNFXKN.js';
|
|
5
|
+
export { createBindMountSandboxProvider, createIsolatedSandboxProvider } from './chunk-KMGNFXKN.js';
|
|
6
|
+
import { noSandbox } from './chunk-SOJTAJTF.js';
|
|
7
|
+
import './chunk-ACD46ZM4.js';
|
|
5
8
|
import { NodeContext, NodeFileSystem } from '@effect/platform-node';
|
|
6
|
-
import {
|
|
9
|
+
import { mkdirSync, chmodSync, appendFileSync, constants } from 'fs';
|
|
7
10
|
import path, { join, posix, dirname, relative } from 'path';
|
|
8
11
|
import { styleText } from 'util';
|
|
9
12
|
import { Context, Effect, Layer, Clock, Duration, Option, Deferred, Ref, Fiber } from 'effect';
|
|
10
13
|
import { FileSystem } from '@effect/platform';
|
|
11
14
|
import * as clack from '@clack/prompts';
|
|
12
|
-
import { execFile } from 'child_process';
|
|
13
15
|
import { readdir, access, readFile, mkdir, mkdtemp, writeFile, rm, lstat, open, chmod } from 'fs/promises';
|
|
14
16
|
import { homedir, tmpdir } from 'os';
|
|
15
17
|
import { createHmac, timingSafeEqual, createHash, randomUUID } from 'crypto';
|
|
16
18
|
|
|
17
19
|
// src/resumePrecheck.ts
|
|
18
20
|
var assertResumeSessionExists = async (params) => {
|
|
19
|
-
const { provider, hostRepoDir, resumeSession } = params;
|
|
21
|
+
const { provider, sandboxTag, hostRepoDir, resumeSession } = params;
|
|
20
22
|
if (!provider.sessionStorage) {
|
|
21
23
|
throw new Error(`${provider.name} does not support resumeSession`);
|
|
22
24
|
}
|
|
25
|
+
if (sandboxTag === "none") {
|
|
26
|
+
const found = await provider.sessionStorage.findByIdOnHost(resumeSession);
|
|
27
|
+
if (!found.path) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`resumeSession "${resumeSession}" not found under ${found.searchedRoot}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
23
34
|
const exists = await provider.sessionStorage.existsOnHost(
|
|
24
35
|
hostRepoDir,
|
|
25
36
|
resumeSession
|
|
@@ -413,12 +424,7 @@ var orchestrate = (options) => {
|
|
|
413
424
|
yield* checkAbort();
|
|
414
425
|
yield* display.status(label(`Iteration ${i}/${iterations}`), "info");
|
|
415
426
|
const sandboxResult = yield* factory.withSandbox(
|
|
416
|
-
({
|
|
417
|
-
hostWorktreePath,
|
|
418
|
-
sandboxRepoPath,
|
|
419
|
-
applyToHost,
|
|
420
|
-
sessionTransferHandle
|
|
421
|
-
}, sandbox) => withSandboxLifecycle(
|
|
427
|
+
({ hostWorktreePath, sandboxRepoPath, applyToHost, bindMountHandle }, sandbox) => withSandboxLifecycle(
|
|
422
428
|
{
|
|
423
429
|
hostRepoDir,
|
|
424
430
|
sandboxRepoDir: sandboxRepoPath,
|
|
@@ -434,14 +440,14 @@ var orchestrate = (options) => {
|
|
|
434
440
|
(ctx) => Effect.gen(function* () {
|
|
435
441
|
const iterationResumeSession = i === 1 ? options.resumeSession : void 0;
|
|
436
442
|
const iterationForkSession = i === 1 ? options.forkSession : void 0;
|
|
437
|
-
if (iterationResumeSession &&
|
|
443
|
+
if (iterationResumeSession && bindMountHandle && provider.sessionStorage) {
|
|
438
444
|
yield* display.status(label("Resuming session"), "info");
|
|
439
445
|
yield* Effect.tryPromise({
|
|
440
446
|
try: () => provider.sessionStorage.resumeIntoSandbox({
|
|
441
447
|
hostCwd: hostRepoDir,
|
|
442
448
|
sandboxCwd: ctx.sandboxRepoDir,
|
|
443
449
|
sessionId: iterationResumeSession,
|
|
444
|
-
handle:
|
|
450
|
+
handle: bindMountHandle
|
|
445
451
|
}),
|
|
446
452
|
catch: (e) => new SessionCaptureError({
|
|
447
453
|
message: `Session resume failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
@@ -533,14 +539,14 @@ var orchestrate = (options) => {
|
|
|
533
539
|
yield* display.status(label("Agent stopped"), "info");
|
|
534
540
|
let sessionFilePath;
|
|
535
541
|
let usage = streamUsage;
|
|
536
|
-
if (provider.captureSessions && provider.sessionStorage && sessionId &&
|
|
542
|
+
if (provider.captureSessions && provider.sessionStorage && sessionId && bindMountHandle) {
|
|
537
543
|
yield* display.status(label("Capturing session"), "info");
|
|
538
544
|
yield* Effect.tryPromise({
|
|
539
545
|
try: () => provider.sessionStorage.captureToHost({
|
|
540
546
|
hostCwd: hostRepoDir,
|
|
541
547
|
sandboxCwd: ctx.sandboxRepoDir,
|
|
542
548
|
sessionId,
|
|
543
|
-
handle:
|
|
549
|
+
handle: bindMountHandle
|
|
544
550
|
}),
|
|
545
551
|
catch: (e) => new SessionCaptureError({
|
|
546
552
|
message: `Session capture failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
@@ -1013,9 +1019,18 @@ async function run(options) {
|
|
|
1013
1019
|
agent: provider
|
|
1014
1020
|
} = options;
|
|
1015
1021
|
validateMaxIterations(maxIterations);
|
|
1016
|
-
const branchStrategy = options.branchStrategy ?? {
|
|
1017
|
-
|
|
1018
|
-
|
|
1022
|
+
const branchStrategy = options.branchStrategy ?? (options.sandbox.tag === "isolated" ? { type: "merge-to-head" } : { type: "head" });
|
|
1023
|
+
const effectiveBranchType = branchStrategy.type;
|
|
1024
|
+
if (effectiveBranchType === "head" && options.sandbox.tag === "isolated") {
|
|
1025
|
+
throw new Error(
|
|
1026
|
+
"head branch strategy is not supported with isolated providers"
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
if (effectiveBranchType === "head" && options.copyToWorktree && options.copyToWorktree.length > 0) {
|
|
1030
|
+
throw new Error(
|
|
1031
|
+
"copyToWorktree is not supported with head branch strategy. In head mode the host working directory is bind-mounted directly."
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1019
1034
|
if (options.resumeSession && maxIterations > 1) {
|
|
1020
1035
|
throw new Error(
|
|
1021
1036
|
"resumeSession cannot be combined with maxIterations > 1. Resume applies to iteration 1 only; multi-iteration resume semantics are not supported."
|
|
@@ -1049,6 +1064,7 @@ async function run(options) {
|
|
|
1049
1064
|
if (options.resumeSession) {
|
|
1050
1065
|
await assertResumeSessionExists({
|
|
1051
1066
|
provider,
|
|
1067
|
+
sandboxTag: options.sandbox.tag,
|
|
1052
1068
|
hostRepoDir,
|
|
1053
1069
|
resumeSession: options.resumeSession
|
|
1054
1070
|
});
|
|
@@ -1080,8 +1096,8 @@ async function run(options) {
|
|
|
1080
1096
|
const currentHostBranch = await Effect.runPromise(
|
|
1081
1097
|
getCurrentBranch(hostRepoDir)
|
|
1082
1098
|
);
|
|
1083
|
-
const resolvedBranch = branch ?? generateTempBranchName(options.name);
|
|
1084
|
-
const targetBranch =
|
|
1099
|
+
const resolvedBranch = effectiveBranchType === "head" ? currentHostBranch : branch ?? generateTempBranchName(options.name);
|
|
1100
|
+
const targetBranch = effectiveBranchType === "merge-to-head" ? currentHostBranch : void 0;
|
|
1085
1101
|
const resolvedLogging = options.logging ?? {
|
|
1086
1102
|
type: "file",
|
|
1087
1103
|
path: buildDefaultLogPath(
|
|
@@ -1166,7 +1182,7 @@ async function run(options) {
|
|
|
1166
1182
|
builtInArgKeysSet
|
|
1167
1183
|
);
|
|
1168
1184
|
}
|
|
1169
|
-
const orchestrateBranch = branch;
|
|
1185
|
+
const orchestrateBranch = effectiveBranchType === "head" ? currentHostBranch : branch;
|
|
1170
1186
|
const orchestrateResult = yield* orchestrate({
|
|
1171
1187
|
hostRepoDir,
|
|
1172
1188
|
iterations: maxIterations,
|
|
@@ -1317,16 +1333,25 @@ var raceAbortSignal = (effect, signal) => {
|
|
|
1317
1333
|
var interactive = async (options) => {
|
|
1318
1334
|
options.signal?.throwIfAborted();
|
|
1319
1335
|
const { prompt, promptFile, hooks, agent: provider } = options;
|
|
1320
|
-
const resolvedSandbox = options.sandbox;
|
|
1321
|
-
const branchStrategy = options.branchStrategy ?? {
|
|
1322
|
-
|
|
1323
|
-
|
|
1336
|
+
const resolvedSandbox = options.sandbox ?? noSandbox();
|
|
1337
|
+
const branchStrategy = options.branchStrategy ?? (resolvedSandbox.tag === "isolated" ? { type: "merge-to-head" } : { type: "head" });
|
|
1338
|
+
if (branchStrategy.type === "head" && resolvedSandbox.tag === "isolated") {
|
|
1339
|
+
throw new Error(
|
|
1340
|
+
"head branch strategy is not supported with isolated providers"
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
if (branchStrategy.type === "head" && options.copyToWorktree && options.copyToWorktree.length > 0) {
|
|
1344
|
+
throw new Error(
|
|
1345
|
+
"copyToWorktree is not supported with head branch strategy. In head mode the host working directory is bind-mounted directly."
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1324
1348
|
if (!provider.buildInteractiveArgs) {
|
|
1325
1349
|
throw new Error(
|
|
1326
1350
|
`Agent provider "${provider.name}" does not support buildInteractiveArgs, required for interactive sessions.`
|
|
1327
1351
|
);
|
|
1328
1352
|
}
|
|
1329
1353
|
const branch = branchStrategy.type === "branch" ? branchStrategy.branch : void 0;
|
|
1354
|
+
const isHeadMode = branchStrategy.type === "head";
|
|
1330
1355
|
const sandboxProvider = resolvedSandbox;
|
|
1331
1356
|
const inner = Effect.gen(function* () {
|
|
1332
1357
|
const hostRepoDir = yield* resolveCwd(options.cwd);
|
|
@@ -1343,7 +1368,7 @@ var interactive = async (options) => {
|
|
|
1343
1368
|
});
|
|
1344
1369
|
const effectiveEnv = { ...env, ...options.env ?? {} };
|
|
1345
1370
|
const currentHostBranch = yield* getCurrentBranch(hostRepoDir);
|
|
1346
|
-
const resolvedBranch = branch ?? generateTempBranchName(options.name);
|
|
1371
|
+
const resolvedBranch = branchStrategy.type === "head" ? currentHostBranch : branch ?? generateTempBranchName(options.name);
|
|
1347
1372
|
let substitutedPrompt = rawPrompt;
|
|
1348
1373
|
if (hasPromptSource && !isInlinePrompt) {
|
|
1349
1374
|
const userArgs = options.promptArgs ?? {};
|
|
@@ -1383,38 +1408,86 @@ var interactive = async (options) => {
|
|
|
1383
1408
|
const userArgs = options.promptArgs ?? {};
|
|
1384
1409
|
yield* validateNoArgsWithInlinePrompt(userArgs);
|
|
1385
1410
|
}
|
|
1386
|
-
const lifecycleBranch = branch;
|
|
1411
|
+
const lifecycleBranch = isHeadMode ? currentHostBranch : branch;
|
|
1387
1412
|
yield* d.intro(options.name ?? `${CLI_NAME} interactive`);
|
|
1388
1413
|
yield* d.summary("Interactive Session", {
|
|
1389
1414
|
Agent: options.name ?? provider.name,
|
|
1390
1415
|
Sandbox: sandboxProvider.name,
|
|
1391
1416
|
Branch: resolvedBranch
|
|
1392
1417
|
});
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1418
|
+
let worktreeInfo;
|
|
1419
|
+
if (!isHeadMode) {
|
|
1420
|
+
worktreeInfo = yield* d.taskLog(
|
|
1421
|
+
"Creating worktree",
|
|
1422
|
+
() => pruneStale(hostRepoDir).pipe(
|
|
1423
|
+
Effect.catchAll(() => Effect.void),
|
|
1424
|
+
Effect.andThen(
|
|
1425
|
+
branch ? create(hostRepoDir, { branch }) : create(hostRepoDir, { name: options.name })
|
|
1426
|
+
)
|
|
1399
1427
|
)
|
|
1400
|
-
)
|
|
1401
|
-
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1402
1430
|
const handle = yield* Effect.gen(function* () {
|
|
1403
|
-
if (
|
|
1404
|
-
|
|
1431
|
+
if (!isHeadMode) {
|
|
1432
|
+
if ((sandboxProvider.tag === "bind-mount" || sandboxProvider.tag === "none") && options.copyToWorktree && options.copyToWorktree.length > 0) {
|
|
1433
|
+
yield* d.taskLog(
|
|
1434
|
+
"Copying files to worktree",
|
|
1435
|
+
() => copyToWorktree(
|
|
1436
|
+
options.copyToWorktree,
|
|
1437
|
+
hostRepoDir,
|
|
1438
|
+
worktreeInfo.path,
|
|
1439
|
+
options.timeouts?.copyToWorktreeMs
|
|
1440
|
+
)
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
if (hooks?.host?.onWorktreeReady?.length) {
|
|
1444
|
+
yield* runHostHooks(hooks.host.onWorktreeReady, worktreeInfo.path);
|
|
1445
|
+
}
|
|
1446
|
+
} else if (hooks?.host?.onWorktreeReady?.length) {
|
|
1447
|
+
yield* runHostHooks(hooks.host.onWorktreeReady, hostRepoDir);
|
|
1448
|
+
}
|
|
1449
|
+
if (sandboxProvider.tag === "none") {
|
|
1450
|
+
const worktreePath = isHeadMode ? hostRepoDir : worktreeInfo.path;
|
|
1451
|
+
return yield* Effect.promise(
|
|
1452
|
+
() => sandboxProvider.create({
|
|
1453
|
+
worktreePath,
|
|
1454
|
+
env: effectiveEnv
|
|
1455
|
+
})
|
|
1456
|
+
);
|
|
1457
|
+
} else if (sandboxProvider.tag === "isolated") {
|
|
1458
|
+
const startResult = yield* d.taskLog(
|
|
1459
|
+
"Starting sandbox",
|
|
1460
|
+
() => startSandbox({
|
|
1461
|
+
provider: sandboxProvider,
|
|
1462
|
+
hostRepoDir: worktreeInfo.path,
|
|
1463
|
+
sourceRepoDir: hostRepoDir,
|
|
1464
|
+
env: effectiveEnv,
|
|
1465
|
+
copyPaths: options.copyToWorktree
|
|
1466
|
+
})
|
|
1467
|
+
);
|
|
1468
|
+
return startResult.handle;
|
|
1469
|
+
} else {
|
|
1470
|
+
const gitPath = join(hostRepoDir, ".git");
|
|
1471
|
+
const rawGitMounts = yield* resolveGitMounts(gitPath);
|
|
1472
|
+
const worktreeOrRepoPath = isHeadMode ? hostRepoDir : worktreeInfo.path;
|
|
1473
|
+
const gitMounts = yield* patchGitMountsForWindows(
|
|
1474
|
+
rawGitMounts,
|
|
1475
|
+
worktreeOrRepoPath,
|
|
1476
|
+
SANDBOX_REPO_DIR
|
|
1477
|
+
);
|
|
1478
|
+
const startResult = yield* d.taskLog(
|
|
1479
|
+
"Starting sandbox",
|
|
1480
|
+
() => startSandbox({
|
|
1481
|
+
provider: sandboxProvider,
|
|
1482
|
+
hostRepoDir,
|
|
1483
|
+
env: effectiveEnv,
|
|
1484
|
+
worktreeOrRepoPath,
|
|
1485
|
+
gitMounts,
|
|
1486
|
+
repoDir: SANDBOX_REPO_DIR
|
|
1487
|
+
})
|
|
1488
|
+
);
|
|
1489
|
+
return startResult.handle;
|
|
1405
1490
|
}
|
|
1406
|
-
const startResult = yield* d.taskLog(
|
|
1407
|
-
"Starting sandbox",
|
|
1408
|
-
() => startSandbox({
|
|
1409
|
-
provider: sandboxProvider,
|
|
1410
|
-
hostRepoDir: worktreeInfo.path,
|
|
1411
|
-
sourceRepoDir: hostRepoDir,
|
|
1412
|
-
env: effectiveEnv,
|
|
1413
|
-
copyPaths: options.copyToWorktree,
|
|
1414
|
-
copyTimeoutMs: options.timeouts?.copyToWorktreeMs
|
|
1415
|
-
})
|
|
1416
|
-
);
|
|
1417
|
-
return startResult.handle;
|
|
1418
1491
|
}).pipe(
|
|
1419
1492
|
Effect.tapError(
|
|
1420
1493
|
() => worktreeInfo ? remove(worktreeInfo.path).pipe(
|
|
@@ -1431,14 +1504,14 @@ var interactive = async (options) => {
|
|
|
1431
1504
|
const interactiveExecFn = handle.interactiveExec.bind(handle);
|
|
1432
1505
|
const sandbox = makeSandboxFromHandle(handle);
|
|
1433
1506
|
const worktreePath = handle.worktreePath;
|
|
1434
|
-
const applyToHost = () => syncOut(worktreeInfo.path, handle);
|
|
1507
|
+
const applyToHost = sandboxProvider.tag === "isolated" && worktreeInfo ? () => syncOut(worktreeInfo.path, handle) : () => Effect.void;
|
|
1435
1508
|
const lifecycleEffect = withSandboxLifecycle(
|
|
1436
1509
|
{
|
|
1437
1510
|
hostRepoDir,
|
|
1438
1511
|
sandboxRepoDir: worktreePath,
|
|
1439
1512
|
hooks,
|
|
1440
1513
|
branch: lifecycleBranch,
|
|
1441
|
-
hostWorktreePath: worktreeInfo
|
|
1514
|
+
hostWorktreePath: isHeadMode ? hostRepoDir : worktreeInfo?.path,
|
|
1442
1515
|
applyToHost,
|
|
1443
1516
|
timeouts: options.timeouts
|
|
1444
1517
|
},
|
|
@@ -1451,7 +1524,7 @@ var interactive = async (options) => {
|
|
|
1451
1524
|
);
|
|
1452
1525
|
const interactiveArgs = provider.buildInteractiveArgs({
|
|
1453
1526
|
prompt: fullPrompt,
|
|
1454
|
-
dangerouslySkipPermissions:
|
|
1527
|
+
dangerouslySkipPermissions: sandboxProvider.tag !== "none"
|
|
1455
1528
|
});
|
|
1456
1529
|
const result4 = yield* raceAbortSignal(
|
|
1457
1530
|
Effect.promise(
|
|
@@ -1540,7 +1613,7 @@ var buildSandboxHandle = (ctx, close) => {
|
|
|
1540
1613
|
sandboxRepoDir,
|
|
1541
1614
|
sandbox,
|
|
1542
1615
|
providerHandle,
|
|
1543
|
-
|
|
1616
|
+
bindMountHandle,
|
|
1544
1617
|
applyToHost,
|
|
1545
1618
|
timeouts,
|
|
1546
1619
|
branchStrategy
|
|
@@ -1571,6 +1644,7 @@ var buildSandboxHandle = (ctx, close) => {
|
|
|
1571
1644
|
if (runOptions.resumeSession) {
|
|
1572
1645
|
await assertResumeSessionExists({
|
|
1573
1646
|
provider,
|
|
1647
|
+
sandboxTag: ctx.providerTag,
|
|
1574
1648
|
hostRepoDir,
|
|
1575
1649
|
resumeSession: runOptions.resumeSession
|
|
1576
1650
|
});
|
|
@@ -1641,7 +1715,7 @@ var buildSandboxHandle = (ctx, close) => {
|
|
|
1641
1715
|
hostWorktreePath: worktreePath,
|
|
1642
1716
|
sandboxRepoPath: sandboxRepoDir,
|
|
1643
1717
|
applyToHost,
|
|
1644
|
-
|
|
1718
|
+
bindMountHandle
|
|
1645
1719
|
},
|
|
1646
1720
|
sandbox
|
|
1647
1721
|
).pipe(
|
|
@@ -1861,13 +1935,24 @@ var buildSandboxHandle = (ctx, close) => {
|
|
|
1861
1935
|
var createSandboxFromWorktree = async (options) => {
|
|
1862
1936
|
const { branch, worktreePath, hostRepoDir } = options;
|
|
1863
1937
|
const isTestMode = !!options._test?.buildSandbox;
|
|
1938
|
+
if (options.copyToWorktree && options.copyToWorktree.length > 0 && options.sandbox.tag !== "isolated") {
|
|
1939
|
+
await Effect.runPromise(
|
|
1940
|
+
copyToWorktree(
|
|
1941
|
+
options.copyToWorktree,
|
|
1942
|
+
hostRepoDir,
|
|
1943
|
+
worktreePath,
|
|
1944
|
+
options.timeouts?.copyToWorktreeMs
|
|
1945
|
+
)
|
|
1946
|
+
);
|
|
1947
|
+
}
|
|
1864
1948
|
let providerHandle;
|
|
1865
1949
|
let sandbox;
|
|
1866
1950
|
let sandboxRepoDir;
|
|
1951
|
+
const isIsolated = options.sandbox.tag === "isolated";
|
|
1867
1952
|
if (isTestMode) {
|
|
1868
1953
|
sandbox = options._test.buildSandbox(worktreePath);
|
|
1869
1954
|
sandboxRepoDir = worktreePath;
|
|
1870
|
-
providerHandle = options._test.
|
|
1955
|
+
providerHandle = options._test.bindMountHandle;
|
|
1871
1956
|
} else {
|
|
1872
1957
|
const resolvedEnv = await Effect.runPromise(
|
|
1873
1958
|
resolveEnv(hostRepoDir).pipe(Effect.provide(NodeContext.layer))
|
|
@@ -1878,15 +1963,42 @@ var createSandboxFromWorktree = async (options) => {
|
|
|
1878
1963
|
sandboxProviderEnv: options.sandbox.env
|
|
1879
1964
|
});
|
|
1880
1965
|
const provider = options.sandbox;
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1966
|
+
let startEffect;
|
|
1967
|
+
if (provider.tag === "isolated") {
|
|
1968
|
+
startEffect = startSandbox({
|
|
1969
|
+
provider,
|
|
1970
|
+
hostRepoDir: worktreePath,
|
|
1971
|
+
sourceRepoDir: hostRepoDir,
|
|
1972
|
+
env,
|
|
1973
|
+
copyPaths: options.copyToWorktree
|
|
1974
|
+
});
|
|
1975
|
+
} else if (provider.tag === "none") {
|
|
1976
|
+
startEffect = startSandbox({
|
|
1977
|
+
provider,
|
|
1978
|
+
hostRepoDir,
|
|
1979
|
+
env,
|
|
1980
|
+
worktreeOrRepoPath: worktreePath
|
|
1981
|
+
});
|
|
1982
|
+
} else {
|
|
1983
|
+
startEffect = resolveGitMounts(join(hostRepoDir, ".git")).pipe(
|
|
1984
|
+
Effect.provide(NodeFileSystem.layer),
|
|
1985
|
+
Effect.catchAll(() => Effect.succeed([])),
|
|
1986
|
+
// Patch git mounts for Windows worktree compatibility (ADR-0006)
|
|
1987
|
+
Effect.flatMap(
|
|
1988
|
+
(gitMounts) => patchGitMountsForWindows(gitMounts, worktreePath, SANDBOX_REPO_DIR)
|
|
1989
|
+
),
|
|
1990
|
+
Effect.flatMap(
|
|
1991
|
+
(gitMounts) => startSandbox({
|
|
1992
|
+
provider,
|
|
1993
|
+
hostRepoDir,
|
|
1994
|
+
env,
|
|
1995
|
+
worktreeOrRepoPath: worktreePath,
|
|
1996
|
+
gitMounts,
|
|
1997
|
+
repoDir: SANDBOX_REPO_DIR
|
|
1998
|
+
})
|
|
1999
|
+
)
|
|
2000
|
+
);
|
|
2001
|
+
}
|
|
1890
2002
|
const startResult = await Effect.runPromise(startEffect);
|
|
1891
2003
|
providerHandle = startResult.handle;
|
|
1892
2004
|
sandbox = startResult.sandbox;
|
|
@@ -1923,9 +2035,9 @@ var createSandboxFromWorktree = async (options) => {
|
|
|
1923
2035
|
)
|
|
1924
2036
|
);
|
|
1925
2037
|
}
|
|
1926
|
-
const applyToHost = providerHandle ? () => syncOut(worktreePath, providerHandle) : () => Effect.void;
|
|
2038
|
+
const applyToHost = isIsolated && providerHandle ? () => syncOut(worktreePath, providerHandle) : () => Effect.void;
|
|
1927
2039
|
let closed = false;
|
|
1928
|
-
const
|
|
2040
|
+
const bindMountHandle = toSessionTransferHandle(providerHandle);
|
|
1929
2041
|
return buildSandboxHandle(
|
|
1930
2042
|
{
|
|
1931
2043
|
branch,
|
|
@@ -1934,7 +2046,8 @@ var createSandboxFromWorktree = async (options) => {
|
|
|
1934
2046
|
sandboxRepoDir,
|
|
1935
2047
|
sandbox,
|
|
1936
2048
|
providerHandle,
|
|
1937
|
-
|
|
2049
|
+
bindMountHandle,
|
|
2050
|
+
providerTag: options.sandbox.tag,
|
|
1938
2051
|
applyToHost,
|
|
1939
2052
|
timeouts: options.timeouts,
|
|
1940
2053
|
branchStrategy: options.branchStrategy
|
|
@@ -1950,6 +2063,7 @@ var createSandboxFromWorktree = async (options) => {
|
|
|
1950
2063
|
var createSandbox = async (options) => {
|
|
1951
2064
|
const { branch } = options;
|
|
1952
2065
|
const isTestMode = !!options._test?.buildSandbox;
|
|
2066
|
+
const isIsolated = options.sandbox.tag === "isolated";
|
|
1953
2067
|
const { hostRepoDir, worktreePath, providerHandle, sandbox, sandboxRepoDir } = await Effect.runPromise(
|
|
1954
2068
|
Effect.gen(function* () {
|
|
1955
2069
|
const hostRepoDir2 = yield* resolveCwd(options.cwd);
|
|
@@ -1961,6 +2075,14 @@ var createSandbox = async (options) => {
|
|
|
1961
2075
|
{ branch, baseBranch: options.baseBranch }
|
|
1962
2076
|
);
|
|
1963
2077
|
const prepared = yield* Effect.gen(function* () {
|
|
2078
|
+
if (options.copyToWorktree && options.copyToWorktree.length > 0 && options.sandbox.tag !== "isolated") {
|
|
2079
|
+
yield* copyToWorktree(
|
|
2080
|
+
options.copyToWorktree,
|
|
2081
|
+
hostRepoDir2,
|
|
2082
|
+
worktreePath2,
|
|
2083
|
+
options.timeouts?.copyToWorktreeMs
|
|
2084
|
+
);
|
|
2085
|
+
}
|
|
1964
2086
|
if (options.hooks?.host?.onWorktreeReady?.length) {
|
|
1965
2087
|
yield* runHostHooks(
|
|
1966
2088
|
options.hooks.host.onWorktreeReady,
|
|
@@ -1973,7 +2095,7 @@ var createSandbox = async (options) => {
|
|
|
1973
2095
|
if (isTestMode) {
|
|
1974
2096
|
sandbox2 = options._test.buildSandbox(worktreePath2);
|
|
1975
2097
|
sandboxRepoDir2 = worktreePath2;
|
|
1976
|
-
providerHandle2 = options._test.
|
|
2098
|
+
providerHandle2 = options._test.bindMountHandle;
|
|
1977
2099
|
} else {
|
|
1978
2100
|
const resolvedEnv = yield* resolveEnv(hostRepoDir2);
|
|
1979
2101
|
const env = mergeProviderEnv({
|
|
@@ -1982,14 +2104,39 @@ var createSandbox = async (options) => {
|
|
|
1982
2104
|
sandboxProviderEnv: options.sandbox.env
|
|
1983
2105
|
});
|
|
1984
2106
|
const provider = options.sandbox;
|
|
1985
|
-
const startResult = yield* startSandbox({
|
|
2107
|
+
const startResult = yield* provider.tag === "isolated" ? startSandbox({
|
|
1986
2108
|
provider,
|
|
1987
2109
|
hostRepoDir: worktreePath2,
|
|
1988
2110
|
sourceRepoDir: hostRepoDir2,
|
|
1989
2111
|
env,
|
|
1990
|
-
copyPaths: options.copyToWorktree
|
|
1991
|
-
|
|
1992
|
-
|
|
2112
|
+
copyPaths: options.copyToWorktree
|
|
2113
|
+
}) : provider.tag === "none" ? startSandbox({
|
|
2114
|
+
provider,
|
|
2115
|
+
hostRepoDir: hostRepoDir2,
|
|
2116
|
+
env,
|
|
2117
|
+
worktreeOrRepoPath: worktreePath2
|
|
2118
|
+
}) : resolveGitMounts(join(hostRepoDir2, ".git")).pipe(
|
|
2119
|
+
Effect.provide(NodeFileSystem.layer),
|
|
2120
|
+
Effect.catchAll(() => Effect.succeed([])),
|
|
2121
|
+
// Patch git mounts for Windows worktree compatibility (ADR-0006)
|
|
2122
|
+
Effect.flatMap(
|
|
2123
|
+
(gitMounts) => patchGitMountsForWindows(
|
|
2124
|
+
gitMounts,
|
|
2125
|
+
worktreePath2,
|
|
2126
|
+
SANDBOX_REPO_DIR
|
|
2127
|
+
)
|
|
2128
|
+
),
|
|
2129
|
+
Effect.flatMap(
|
|
2130
|
+
(gitMounts) => startSandbox({
|
|
2131
|
+
provider,
|
|
2132
|
+
hostRepoDir: hostRepoDir2,
|
|
2133
|
+
env,
|
|
2134
|
+
worktreeOrRepoPath: worktreePath2,
|
|
2135
|
+
gitMounts,
|
|
2136
|
+
repoDir: SANDBOX_REPO_DIR
|
|
2137
|
+
})
|
|
2138
|
+
)
|
|
2139
|
+
);
|
|
1993
2140
|
providerHandle2 = startResult.handle;
|
|
1994
2141
|
sandbox2 = startResult.sandbox;
|
|
1995
2142
|
sandboxRepoDir2 = startResult.worktreePath;
|
|
@@ -2034,7 +2181,7 @@ var createSandbox = async (options) => {
|
|
|
2034
2181
|
return { hostRepoDir: hostRepoDir2, worktreePath: worktreePath2, ...prepared };
|
|
2035
2182
|
}).pipe(Effect.provide(NodeContext.layer))
|
|
2036
2183
|
);
|
|
2037
|
-
const applyToHost = providerHandle ? () => syncOut(worktreePath, providerHandle) : () => Effect.void;
|
|
2184
|
+
const applyToHost = isIsolated && providerHandle ? () => syncOut(worktreePath, providerHandle) : () => Effect.void;
|
|
2038
2185
|
let closed = false;
|
|
2039
2186
|
const forceCleanup = () => {
|
|
2040
2187
|
console.error(`
|
|
@@ -2064,7 +2211,7 @@ Worktree preserved at ${worktreePath}`);
|
|
|
2064
2211
|
})
|
|
2065
2212
|
);
|
|
2066
2213
|
};
|
|
2067
|
-
const
|
|
2214
|
+
const bindMountHandle = toSessionTransferHandle(providerHandle);
|
|
2068
2215
|
return buildSandboxHandle(
|
|
2069
2216
|
{
|
|
2070
2217
|
branch,
|
|
@@ -2073,7 +2220,8 @@ Worktree preserved at ${worktreePath}`);
|
|
|
2073
2220
|
sandboxRepoDir,
|
|
2074
2221
|
sandbox,
|
|
2075
2222
|
providerHandle,
|
|
2076
|
-
|
|
2223
|
+
bindMountHandle,
|
|
2224
|
+
providerTag: options.sandbox.tag,
|
|
2077
2225
|
applyToHost,
|
|
2078
2226
|
timeouts: options.timeouts
|
|
2079
2227
|
},
|
|
@@ -2083,82 +2231,6 @@ Worktree preserved at ${worktreePath}`);
|
|
|
2083
2231
|
}
|
|
2084
2232
|
);
|
|
2085
2233
|
};
|
|
2086
|
-
var COPY_TO_WORKTREE_TIMEOUT_MS = 6e4;
|
|
2087
|
-
var getCopyOnWriteFlags = (platform) => platform === "darwin" ? ["-cR"] : ["-R", "--reflink=auto"];
|
|
2088
|
-
var copyToWorktree = (paths, hostRepoDir, worktreePath, timeoutMs) => {
|
|
2089
|
-
const effectiveTimeout = timeoutMs ?? COPY_TO_WORKTREE_TIMEOUT_MS;
|
|
2090
|
-
return Effect.gen(function* () {
|
|
2091
|
-
const cowFlags = getCopyOnWriteFlags(process.platform);
|
|
2092
|
-
for (const relativePath of paths) {
|
|
2093
|
-
let src;
|
|
2094
|
-
let dest;
|
|
2095
|
-
try {
|
|
2096
|
-
assertExcludesRepositoryRunner(relativePath);
|
|
2097
|
-
src = resolveSafeRelativePath(hostRepoDir, relativePath, "copy path");
|
|
2098
|
-
dest = resolveSafeRelativePath(worktreePath, relativePath, "copy path");
|
|
2099
|
-
} catch (error) {
|
|
2100
|
-
return yield* Effect.fail(
|
|
2101
|
-
new CopyToWorktreeError({
|
|
2102
|
-
message: `Refusing unsafe copy path ${relativePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
2103
|
-
path: relativePath,
|
|
2104
|
-
stderr: error instanceof Error ? error.message : String(error),
|
|
2105
|
-
exitCode: null
|
|
2106
|
-
})
|
|
2107
|
-
);
|
|
2108
|
-
}
|
|
2109
|
-
if (!existsSync(src)) {
|
|
2110
|
-
continue;
|
|
2111
|
-
}
|
|
2112
|
-
yield* Effect.tryPromise({
|
|
2113
|
-
try: async () => {
|
|
2114
|
-
await assertNoSymlinkComponents(hostRepoDir, src, "copy source");
|
|
2115
|
-
await assertNoSymlinkComponents(worktreePath, dest, "copy target");
|
|
2116
|
-
},
|
|
2117
|
-
catch: (error) => new CopyToWorktreeError({
|
|
2118
|
-
message: `Refusing symlinked copy path ${relativePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
2119
|
-
path: relativePath,
|
|
2120
|
-
stderr: error instanceof Error ? error.message : String(error),
|
|
2121
|
-
exitCode: null
|
|
2122
|
-
})
|
|
2123
|
-
});
|
|
2124
|
-
yield* Effect.async((resume) => {
|
|
2125
|
-
execFile("cp", [...cowFlags, src, dest], (error) => {
|
|
2126
|
-
if (error) {
|
|
2127
|
-
execFile("cp", ["-R", src, dest], (fallbackError, _, stderr) => {
|
|
2128
|
-
if (fallbackError) {
|
|
2129
|
-
resume(
|
|
2130
|
-
Effect.fail(
|
|
2131
|
-
new CopyToWorktreeError({
|
|
2132
|
-
message: `Failed to copy ${relativePath} to worktree: ${stderr || fallbackError.message}`,
|
|
2133
|
-
path: relativePath,
|
|
2134
|
-
stderr: stderr || fallbackError.message,
|
|
2135
|
-
exitCode: typeof fallbackError.code === "number" ? fallbackError.code : null
|
|
2136
|
-
})
|
|
2137
|
-
)
|
|
2138
|
-
);
|
|
2139
|
-
} else {
|
|
2140
|
-
resume(Effect.succeed(void 0));
|
|
2141
|
-
}
|
|
2142
|
-
});
|
|
2143
|
-
} else {
|
|
2144
|
-
resume(Effect.succeed(void 0));
|
|
2145
|
-
}
|
|
2146
|
-
});
|
|
2147
|
-
});
|
|
2148
|
-
}
|
|
2149
|
-
}).pipe(
|
|
2150
|
-
withTimeout(
|
|
2151
|
-
effectiveTimeout,
|
|
2152
|
-
() => new CopyToWorktreeTimeoutError({
|
|
2153
|
-
message: `Copying files to worktree timed out after ${effectiveTimeout}ms`,
|
|
2154
|
-
timeoutMs: effectiveTimeout,
|
|
2155
|
-
paths
|
|
2156
|
-
})
|
|
2157
|
-
)
|
|
2158
|
-
);
|
|
2159
|
-
};
|
|
2160
|
-
|
|
2161
|
-
// src/createWorktree.ts
|
|
2162
2234
|
var createWorktree = async (options) => {
|
|
2163
2235
|
const branch = options.branchStrategy.type === "branch" ? options.branchStrategy.branch : void 0;
|
|
2164
2236
|
const baseBranch = options.branchStrategy.type === "branch" ? options.branchStrategy.baseBranch : void 0;
|
|
@@ -2205,7 +2277,7 @@ var createWorktree = async (options) => {
|
|
|
2205
2277
|
const worktreeInteractive = async (opts) => {
|
|
2206
2278
|
opts.signal?.throwIfAborted();
|
|
2207
2279
|
const { prompt, promptFile, hooks, agent: provider } = opts;
|
|
2208
|
-
const resolvedSandbox = opts.sandbox;
|
|
2280
|
+
const resolvedSandbox = opts.sandbox ?? noSandbox();
|
|
2209
2281
|
if (!provider.buildInteractiveArgs) {
|
|
2210
2282
|
throw new Error(
|
|
2211
2283
|
`Agent provider "${provider.name}" does not support buildInteractiveArgs, required for interactive sessions.`
|
|
@@ -2248,19 +2320,46 @@ var createWorktree = async (options) => {
|
|
|
2248
2320
|
Sandbox: resolvedSandbox.name,
|
|
2249
2321
|
Branch: worktreeInfo.branch
|
|
2250
2322
|
});
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2323
|
+
let handle;
|
|
2324
|
+
if (resolvedSandbox.tag === "none") {
|
|
2325
|
+
handle = yield* Effect.promise(
|
|
2326
|
+
() => resolvedSandbox.create({
|
|
2327
|
+
worktreePath: worktreeInfo.path,
|
|
2328
|
+
env: effectiveEnv
|
|
2329
|
+
})
|
|
2330
|
+
);
|
|
2331
|
+
} else if (resolvedSandbox.tag === "isolated") {
|
|
2332
|
+
const startResult = yield* d.taskLog(
|
|
2333
|
+
"Starting sandbox",
|
|
2334
|
+
() => startSandbox({
|
|
2335
|
+
provider: resolvedSandbox,
|
|
2336
|
+
hostRepoDir: worktreeInfo.path,
|
|
2337
|
+
sourceRepoDir: hostRepoDir,
|
|
2338
|
+
env: effectiveEnv
|
|
2339
|
+
})
|
|
2340
|
+
);
|
|
2341
|
+
handle = startResult.handle;
|
|
2342
|
+
} else {
|
|
2343
|
+
const gitPath = join(hostRepoDir, ".git");
|
|
2344
|
+
const rawGitMounts = yield* resolveGitMounts(gitPath);
|
|
2345
|
+
const gitMounts = yield* patchGitMountsForWindows(
|
|
2346
|
+
rawGitMounts,
|
|
2347
|
+
worktreeInfo.path,
|
|
2348
|
+
SANDBOX_REPO_DIR
|
|
2349
|
+
);
|
|
2350
|
+
const startResult = yield* d.taskLog(
|
|
2351
|
+
"Starting sandbox",
|
|
2352
|
+
() => startSandbox({
|
|
2353
|
+
provider: resolvedSandbox,
|
|
2354
|
+
hostRepoDir,
|
|
2355
|
+
env: effectiveEnv,
|
|
2356
|
+
worktreeOrRepoPath: worktreeInfo.path,
|
|
2357
|
+
gitMounts,
|
|
2358
|
+
repoDir: SANDBOX_REPO_DIR
|
|
2359
|
+
})
|
|
2360
|
+
);
|
|
2361
|
+
handle = startResult.handle;
|
|
2362
|
+
}
|
|
2264
2363
|
return yield* Effect.gen(function* () {
|
|
2265
2364
|
if (!handle.interactiveExec) {
|
|
2266
2365
|
throw new Error(
|
|
@@ -2270,7 +2369,7 @@ var createWorktree = async (options) => {
|
|
|
2270
2369
|
const interactiveExecFn = handle.interactiveExec.bind(handle);
|
|
2271
2370
|
const sandbox = makeSandboxFromHandle(handle);
|
|
2272
2371
|
const worktreePath = handle.worktreePath;
|
|
2273
|
-
const applyToHost = () => syncOut(worktreeInfo.path, handle);
|
|
2372
|
+
const applyToHost = resolvedSandbox.tag === "isolated" ? () => syncOut(worktreeInfo.path, handle) : () => Effect.void;
|
|
2274
2373
|
const lifecycleEffect = withSandboxLifecycle(
|
|
2275
2374
|
{
|
|
2276
2375
|
hostRepoDir,
|
|
@@ -2294,7 +2393,7 @@ var createWorktree = async (options) => {
|
|
|
2294
2393
|
);
|
|
2295
2394
|
const interactiveArgs = provider.buildInteractiveArgs({
|
|
2296
2395
|
prompt: fullPrompt,
|
|
2297
|
-
dangerouslySkipPermissions:
|
|
2396
|
+
dangerouslySkipPermissions: resolvedSandbox.tag !== "none"
|
|
2298
2397
|
});
|
|
2299
2398
|
const result3 = yield* raceAbortSignal(
|
|
2300
2399
|
Effect.promise(
|
|
@@ -2357,6 +2456,7 @@ var createWorktree = async (options) => {
|
|
|
2357
2456
|
if (opts.resumeSession) {
|
|
2358
2457
|
await assertResumeSessionExists({
|
|
2359
2458
|
provider,
|
|
2459
|
+
sandboxTag: sandboxProvider.tag,
|
|
2360
2460
|
hostRepoDir,
|
|
2361
2461
|
resumeSession: opts.resumeSession
|
|
2362
2462
|
});
|
|
@@ -2391,19 +2491,47 @@ var createWorktree = async (options) => {
|
|
|
2391
2491
|
builtInArgKeysSet
|
|
2392
2492
|
);
|
|
2393
2493
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2494
|
+
let handle;
|
|
2495
|
+
let sandboxRepoDir;
|
|
2496
|
+
if (sandboxProvider.tag === "isolated") {
|
|
2497
|
+
const startResult = yield* startSandbox({
|
|
2498
|
+
provider: sandboxProvider,
|
|
2499
|
+
hostRepoDir: worktreeInfo.path,
|
|
2500
|
+
sourceRepoDir: hostRepoDir,
|
|
2501
|
+
env: effectiveEnv
|
|
2502
|
+
});
|
|
2503
|
+
handle = startResult.handle;
|
|
2504
|
+
sandboxRepoDir = startResult.worktreePath;
|
|
2505
|
+
} else if (sandboxProvider.tag === "none") {
|
|
2506
|
+
const startResult = yield* startSandbox({
|
|
2507
|
+
provider: sandboxProvider,
|
|
2508
|
+
hostRepoDir,
|
|
2509
|
+
env: effectiveEnv,
|
|
2510
|
+
worktreeOrRepoPath: worktreeInfo.path
|
|
2511
|
+
});
|
|
2512
|
+
handle = startResult.handle;
|
|
2513
|
+
sandboxRepoDir = startResult.worktreePath;
|
|
2514
|
+
} else {
|
|
2515
|
+
const gitPath = join(hostRepoDir, ".git");
|
|
2516
|
+
const rawGitMounts = yield* resolveGitMounts(gitPath);
|
|
2517
|
+
const gitMounts = yield* patchGitMountsForWindows(
|
|
2518
|
+
rawGitMounts,
|
|
2519
|
+
worktreeInfo.path,
|
|
2520
|
+
SANDBOX_REPO_DIR
|
|
2521
|
+
);
|
|
2522
|
+
const startResult = yield* startSandbox({
|
|
2523
|
+
provider: sandboxProvider,
|
|
2524
|
+
hostRepoDir,
|
|
2525
|
+
env: effectiveEnv,
|
|
2526
|
+
worktreeOrRepoPath: worktreeInfo.path,
|
|
2527
|
+
gitMounts,
|
|
2528
|
+
repoDir: SANDBOX_REPO_DIR
|
|
2529
|
+
});
|
|
2530
|
+
handle = startResult.handle;
|
|
2531
|
+
sandboxRepoDir = startResult.worktreePath;
|
|
2532
|
+
}
|
|
2405
2533
|
const sandbox = makeSandboxFromHandle(handle);
|
|
2406
|
-
const applyToHost = () => syncOut(worktreeInfo.path, handle);
|
|
2534
|
+
const applyToHost = sandboxProvider.tag === "isolated" ? () => syncOut(worktreeInfo.path, handle) : () => Effect.void;
|
|
2407
2535
|
const resolvedLogging = opts.logging ?? {
|
|
2408
2536
|
type: "file",
|
|
2409
2537
|
path: buildDefaultLogPath(
|
|
@@ -2436,14 +2564,14 @@ var createWorktree = async (options) => {
|
|
|
2436
2564
|
NodeFileSystem.layer
|
|
2437
2565
|
);
|
|
2438
2566
|
})() : ClackDisplay.layer;
|
|
2439
|
-
const
|
|
2567
|
+
const bindMountHandle = toSessionTransferHandle(handle);
|
|
2440
2568
|
const reuseFactoryLayer = Layer.succeed(SandboxFactory, {
|
|
2441
2569
|
withSandbox: (makeEffect) => makeEffect(
|
|
2442
2570
|
{
|
|
2443
2571
|
hostWorktreePath: worktreeInfo.path,
|
|
2444
2572
|
sandboxRepoPath: sandboxRepoDir,
|
|
2445
2573
|
applyToHost,
|
|
2446
|
-
|
|
2574
|
+
bindMountHandle
|
|
2447
2575
|
},
|
|
2448
2576
|
sandbox
|
|
2449
2577
|
).pipe(
|
|
@@ -2524,28 +2652,13 @@ var createWorktree = async (options) => {
|
|
|
2524
2652
|
}
|
|
2525
2653
|
};
|
|
2526
2654
|
const worktreeCreateSandbox = async (opts) => {
|
|
2527
|
-
if (opts.copyToWorktree?.length) {
|
|
2528
|
-
await Effect.runPromise(
|
|
2529
|
-
copyToWorktree(
|
|
2530
|
-
opts.copyToWorktree,
|
|
2531
|
-
hostRepoDir,
|
|
2532
|
-
worktreeInfo.path,
|
|
2533
|
-
opts.timeouts?.copyToWorktreeMs ?? options.timeouts?.copyToWorktreeMs
|
|
2534
|
-
)
|
|
2535
|
-
);
|
|
2536
|
-
}
|
|
2537
2655
|
return createSandboxFromWorktree({
|
|
2538
2656
|
branch: worktreeInfo.branch,
|
|
2539
2657
|
worktreePath: worktreeInfo.path,
|
|
2540
2658
|
hostRepoDir,
|
|
2541
2659
|
sandbox: opts.sandbox,
|
|
2542
2660
|
hooks: opts.hooks,
|
|
2543
|
-
copyToWorktree:
|
|
2544
|
-
.../* @__PURE__ */ new Set([
|
|
2545
|
-
...options.copyToWorktree ?? [],
|
|
2546
|
-
...opts.copyToWorktree ?? []
|
|
2547
|
-
])
|
|
2548
|
-
],
|
|
2661
|
+
copyToWorktree: opts.copyToWorktree,
|
|
2549
2662
|
timeouts: opts.timeouts,
|
|
2550
2663
|
branchStrategy: options.branchStrategy,
|
|
2551
2664
|
_test: opts._test
|
|
@@ -2914,7 +3027,8 @@ var makeClaudeSessionStorage = (options) => {
|
|
|
2914
3027
|
sandboxProjectsDir
|
|
2915
3028
|
);
|
|
2916
3029
|
await writeSandboxFile(handle, sandboxPath, rewritten, "claude-res");
|
|
2917
|
-
}
|
|
3030
|
+
},
|
|
3031
|
+
findByIdOnHost: (id) => findClaudeSessionOnHost(id, hostProjectsDir)
|
|
2918
3032
|
};
|
|
2919
3033
|
};
|
|
2920
3034
|
var makeCodexSessionStorage = (options) => {
|
|
@@ -2952,7 +3066,8 @@ var makeCodexSessionStorage = (options) => {
|
|
|
2952
3066
|
const rewritten = transferCodexSession(jsonl, hostCwd, sandboxCwd);
|
|
2953
3067
|
const target = posix.join(sandboxSessionsDir, located.relativePath);
|
|
2954
3068
|
await writeSandboxFile(handle, target, rewritten, "codex-res");
|
|
2955
|
-
}
|
|
3069
|
+
},
|
|
3070
|
+
findByIdOnHost: (id) => findCodexSessionOnHost(id, hostSessionsDir)
|
|
2956
3071
|
};
|
|
2957
3072
|
};
|
|
2958
3073
|
var parseCodexUsage = (usage) => {
|
|
@@ -2999,7 +3114,7 @@ var parseCodexStreamLine = (line) => {
|
|
|
2999
3114
|
};
|
|
3000
3115
|
var codex = (model, options) => {
|
|
3001
3116
|
const modelId = typeof model === "string" ? model : model.model;
|
|
3002
|
-
const effort = options?.effort
|
|
3117
|
+
const effort = options?.effort ?? (typeof model === "string" ? CONFIGURED_CODEX_MODEL_EFFORTS.get(modelId) : model.effort);
|
|
3003
3118
|
return {
|
|
3004
3119
|
name: "codex",
|
|
3005
3120
|
env: options?.env ?? {},
|
|
@@ -3260,18 +3375,7 @@ var createWorkBrief = (input) => {
|
|
|
3260
3375
|
"acceptanceCriteria"
|
|
3261
3376
|
),
|
|
3262
3377
|
exclusions: stringArray(input.exclusions, "exclusions"),
|
|
3263
|
-
risk: enumValue(
|
|
3264
|
-
input.risk,
|
|
3265
|
-
["low", "medium", "high", "critical", "unknown"],
|
|
3266
|
-
"risk"
|
|
3267
|
-
),
|
|
3268
|
-
...input.scope === void 0 ? {} : {
|
|
3269
|
-
scope: enumValue(
|
|
3270
|
-
input.scope,
|
|
3271
|
-
["small", "substantial", "unknown"],
|
|
3272
|
-
"scope"
|
|
3273
|
-
)
|
|
3274
|
-
},
|
|
3378
|
+
risk: enumValue(input.risk, ["low", "medium", "high", "critical"], "risk"),
|
|
3275
3379
|
verification: parseVerification(input.verification),
|
|
3276
3380
|
unresolvedQuestions: stringArray(
|
|
3277
3381
|
input.unresolvedQuestions,
|
|
@@ -3311,18 +3415,7 @@ var parseWorkBrief = (value) => {
|
|
|
3311
3415
|
"acceptanceCriteria"
|
|
3312
3416
|
),
|
|
3313
3417
|
exclusions: stringArray(value.exclusions, "exclusions"),
|
|
3314
|
-
risk: enumValue(
|
|
3315
|
-
value.risk,
|
|
3316
|
-
["low", "medium", "high", "critical", "unknown"],
|
|
3317
|
-
"risk"
|
|
3318
|
-
),
|
|
3319
|
-
...value.scope === void 0 ? {} : {
|
|
3320
|
-
scope: enumValue(
|
|
3321
|
-
value.scope,
|
|
3322
|
-
["small", "substantial", "unknown"],
|
|
3323
|
-
"scope"
|
|
3324
|
-
)
|
|
3325
|
-
},
|
|
3418
|
+
risk: enumValue(value.risk, ["low", "medium", "high", "critical"], "risk"),
|
|
3326
3419
|
verification: parseVerification(value.verification),
|
|
3327
3420
|
unresolvedQuestions: stringArray(
|
|
3328
3421
|
value.unresolvedQuestions,
|
|
@@ -3378,28 +3471,6 @@ var parseRepositoryPolicy = (value) => {
|
|
|
3378
3471
|
if (!isRecord(value.worker)) {
|
|
3379
3472
|
throw new ContractValidationError("policy.worker must be an object");
|
|
3380
3473
|
}
|
|
3381
|
-
const workerModels = value.worker.models === void 0 ? void 0 : (() => {
|
|
3382
|
-
if (value.worker.model !== void 0) {
|
|
3383
|
-
throw new ContractValidationError(
|
|
3384
|
-
"policy.worker.model cannot be combined with policy.worker.models"
|
|
3385
|
-
);
|
|
3386
|
-
}
|
|
3387
|
-
if (!isRecord(value.worker.models)) {
|
|
3388
|
-
throw new ContractValidationError(
|
|
3389
|
-
"policy.worker.models must be an object"
|
|
3390
|
-
);
|
|
3391
|
-
}
|
|
3392
|
-
return {
|
|
3393
|
-
routine: nonEmptyString(
|
|
3394
|
-
value.worker.models.routine,
|
|
3395
|
-
"policy.worker.models.routine"
|
|
3396
|
-
),
|
|
3397
|
-
strong: nonEmptyString(
|
|
3398
|
-
value.worker.models.strong,
|
|
3399
|
-
"policy.worker.models.strong"
|
|
3400
|
-
)
|
|
3401
|
-
};
|
|
3402
|
-
})();
|
|
3403
3474
|
if (!Array.isArray(value.checks)) {
|
|
3404
3475
|
throw new ContractValidationError("policy.checks must be an array");
|
|
3405
3476
|
}
|
|
@@ -3493,7 +3564,7 @@ var parseRepositoryPolicy = (value) => {
|
|
|
3493
3564
|
authorization: { required, allowedActors, autoStartRisk },
|
|
3494
3565
|
worker: {
|
|
3495
3566
|
provider: nonEmptyString(value.worker.provider, "policy.worker.provider"),
|
|
3496
|
-
|
|
3567
|
+
model: nonEmptyString(value.worker.model, "policy.worker.model"),
|
|
3497
3568
|
sandbox: nonEmptyString(value.worker.sandbox, "policy.worker.sandbox"),
|
|
3498
3569
|
skillRevision: nonEmptyString(
|
|
3499
3570
|
value.worker.skillRevision,
|
|
@@ -3509,16 +3580,6 @@ var createRepositoryPolicy = (input) => parseRepositoryPolicy({
|
|
|
3509
3580
|
contractVersion: WORKFLOW_CONTRACT_VERSION,
|
|
3510
3581
|
...input
|
|
3511
3582
|
});
|
|
3512
|
-
var resolveAgentSelection = (policy, phase2, risk, scope) => {
|
|
3513
|
-
const role = phase2 === "review" && !(risk === "low" && scope === "small") ? "strong" : "routine";
|
|
3514
|
-
const worker = policy.worker;
|
|
3515
|
-
const modelPath = worker.models ? `policy.worker.models.${role}` : "policy.worker.model";
|
|
3516
|
-
return Object.freeze({
|
|
3517
|
-
provider: nonEmptyString(worker.provider, "policy.worker.provider"),
|
|
3518
|
-
model: nonEmptyString(worker.models?.[role] ?? worker.model, modelPath),
|
|
3519
|
-
role
|
|
3520
|
-
});
|
|
3521
|
-
};
|
|
3522
3583
|
var parseCheckEvidence = (value) => {
|
|
3523
3584
|
if (!isRecord(value)) {
|
|
3524
3585
|
throw new ContractValidationError("check evidence must be an object");
|
|
@@ -3657,12 +3718,6 @@ var createAssignment = (input) => {
|
|
|
3657
3718
|
briefHash: brief.hash,
|
|
3658
3719
|
policyRevision: input.policy.revision,
|
|
3659
3720
|
skillRevision: brief.skillRevision,
|
|
3660
|
-
agentSelection: resolveAgentSelection(
|
|
3661
|
-
input.policy,
|
|
3662
|
-
input.phase,
|
|
3663
|
-
brief.risk,
|
|
3664
|
-
brief.scope
|
|
3665
|
-
),
|
|
3666
3721
|
base: brief.base,
|
|
3667
3722
|
head: input.head,
|
|
3668
3723
|
createdAt: nonEmptyString(input.createdAt, "assignment.createdAt")
|
|
@@ -4032,25 +4087,6 @@ var parseAssignment = (value) => {
|
|
|
4032
4087
|
throw new Error("Stored assignment base must be an object");
|
|
4033
4088
|
}
|
|
4034
4089
|
const head = candidate.head;
|
|
4035
|
-
const agentSelection = candidate.agentSelection;
|
|
4036
|
-
let parsedAgentSelection;
|
|
4037
|
-
if (agentSelection !== void 0) {
|
|
4038
|
-
if (typeof agentSelection !== "object" || agentSelection === null || Array.isArray(agentSelection)) {
|
|
4039
|
-
throw new Error("Stored assignment agent selection must be an object");
|
|
4040
|
-
}
|
|
4041
|
-
const selection = agentSelection;
|
|
4042
|
-
if (selection.role !== "routine" && selection.role !== "strong") {
|
|
4043
|
-
throw new Error("Stored assignment agent selection role is invalid");
|
|
4044
|
-
}
|
|
4045
|
-
parsedAgentSelection = {
|
|
4046
|
-
provider: requiredString(
|
|
4047
|
-
selection.provider,
|
|
4048
|
-
"assignment.agentSelection.provider"
|
|
4049
|
-
),
|
|
4050
|
-
model: requiredString(selection.model, "assignment.agentSelection.model"),
|
|
4051
|
-
role: selection.role
|
|
4052
|
-
};
|
|
4053
|
-
}
|
|
4054
4090
|
const revision = (value2, path2) => {
|
|
4055
4091
|
if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) {
|
|
4056
4092
|
throw new Error(`${path2} must be an object`);
|
|
@@ -4094,7 +4130,6 @@ var parseAssignment = (value) => {
|
|
|
4094
4130
|
candidate.skillRevision,
|
|
4095
4131
|
"assignment.skillRevision"
|
|
4096
4132
|
),
|
|
4097
|
-
...parsedAgentSelection === void 0 ? {} : { agentSelection: parsedAgentSelection },
|
|
4098
4133
|
base: revision(base, "assignment.base"),
|
|
4099
4134
|
head: head === void 0 ? void 0 : revision(head, "assignment.head"),
|
|
4100
4135
|
createdAt: requiredString(candidate.createdAt, "assignment.createdAt")
|
|
@@ -4284,6 +4319,9 @@ var PostgresTransaction = class {
|
|
|
4284
4319
|
async one(text2, values, path2) {
|
|
4285
4320
|
return row(await this.client.query(text2, values), path2);
|
|
4286
4321
|
}
|
|
4322
|
+
async optional(text2, values) {
|
|
4323
|
+
return optionalRow(await this.client.query(text2, values));
|
|
4324
|
+
}
|
|
4287
4325
|
async insertEventIfAbsent(event) {
|
|
4288
4326
|
const inserted = await this.client.query(
|
|
4289
4327
|
`INSERT INTO shipyard_events (
|
|
@@ -6011,23 +6049,11 @@ var cancelledResult = (assignment, response, artifacts, message, kind) => ({
|
|
|
6011
6049
|
evidence: response.report.evidence
|
|
6012
6050
|
})
|
|
6013
6051
|
});
|
|
6014
|
-
var sameAgentSelection = (left, right) => left.provider === right.provider && left.model === right.model && left.role === right.role;
|
|
6015
6052
|
var executePhase = async (options) => {
|
|
6016
6053
|
const assignment = deepFreeze(structuredClone(options.assignment));
|
|
6017
6054
|
const trusted = deepFreeze(structuredClone(options.trusted));
|
|
6018
6055
|
const untrusted = deepFreeze(structuredClone(options.untrusted));
|
|
6019
6056
|
const controls = deepFreeze(structuredClone(options.controls));
|
|
6020
|
-
const resolvedSelection = resolveAgentSelection(
|
|
6021
|
-
trusted.policy,
|
|
6022
|
-
assignment.phase,
|
|
6023
|
-
trusted.brief.risk,
|
|
6024
|
-
trusted.brief.scope
|
|
6025
|
-
);
|
|
6026
|
-
const persistedSelection = assignment.agentSelection;
|
|
6027
|
-
if (persistedSelection !== void 0 && !sameAgentSelection(persistedSelection, resolvedSelection)) {
|
|
6028
|
-
throw new Error("Assignment agent selection does not match trusted policy");
|
|
6029
|
-
}
|
|
6030
|
-
const agentSelection = persistedSelection ?? resolvedSelection;
|
|
6031
6057
|
const secretValues = /* @__PURE__ */ new Set();
|
|
6032
6058
|
const controller = new AbortController();
|
|
6033
6059
|
let timedOut = false;
|
|
@@ -6041,7 +6067,6 @@ var executePhase = async (options) => {
|
|
|
6041
6067
|
}, options.controls.timeoutSeconds * 1e3);
|
|
6042
6068
|
const request = {
|
|
6043
6069
|
assignment,
|
|
6044
|
-
agentSelection,
|
|
6045
6070
|
trusted,
|
|
6046
6071
|
untrusted,
|
|
6047
6072
|
controls,
|
|
@@ -6286,23 +6311,6 @@ var executePhase = async (options) => {
|
|
|
6286
6311
|
})
|
|
6287
6312
|
};
|
|
6288
6313
|
};
|
|
6289
|
-
var resolvePhaseAgent = (options, request) => {
|
|
6290
|
-
if (options.resolveAgent === void 0 && request.trusted.policy.worker.models !== void 0) {
|
|
6291
|
-
throw new Error(
|
|
6292
|
-
"An agent resolver is required when repository policy defines worker models"
|
|
6293
|
-
);
|
|
6294
|
-
}
|
|
6295
|
-
const agent = options.resolveAgent === void 0 ? options.agent : options.resolveAgent(request.agentSelection);
|
|
6296
|
-
if (agent === void 0) {
|
|
6297
|
-
throw new Error("The phase engine has no agent for the selected model");
|
|
6298
|
-
}
|
|
6299
|
-
if (agent.name !== request.agentSelection.provider) {
|
|
6300
|
-
throw new Error(
|
|
6301
|
-
`Resolved agent provider "${agent.name}" does not match repository policy provider "${request.agentSelection.provider}"`
|
|
6302
|
-
);
|
|
6303
|
-
}
|
|
6304
|
-
return agent;
|
|
6305
|
-
};
|
|
6306
6314
|
var runResultToResponse = (result3, branch) => {
|
|
6307
6315
|
const commits = result3.commits.map((commit) => commit.sha);
|
|
6308
6316
|
const headSha = commits.at(-1) ?? "";
|
|
@@ -6327,12 +6335,11 @@ var runResultToResponse = (result3, branch) => {
|
|
|
6327
6335
|
};
|
|
6328
6336
|
var createRunPhaseEngineAdapter = (options) => ({
|
|
6329
6337
|
execute: async (request) => {
|
|
6330
|
-
|
|
6331
|
-
assertToolAllowlistSupport(agent);
|
|
6338
|
+
assertToolAllowlistSupport(options.agent);
|
|
6332
6339
|
const branch = request.checkout.branch;
|
|
6333
6340
|
const baseBranch = request.checkout.immutable ? request.checkout.candidate?.sha ?? request.assignment.base.sha : request.assignment.base.sha;
|
|
6334
6341
|
const result3 = await options.run({
|
|
6335
|
-
agent,
|
|
6342
|
+
agent: options.agent,
|
|
6336
6343
|
sandbox: options.sandbox,
|
|
6337
6344
|
cwd: options.cwd,
|
|
6338
6345
|
prompt: buildPrompt(request),
|
|
@@ -6370,8 +6377,7 @@ var sandboxResultToResponse = (result3, branch) => {
|
|
|
6370
6377
|
};
|
|
6371
6378
|
var createCreateSandboxPhaseEngineAdapter = (options) => ({
|
|
6372
6379
|
execute: async (request) => {
|
|
6373
|
-
|
|
6374
|
-
assertToolAllowlistSupport(agent);
|
|
6380
|
+
assertToolAllowlistSupport(options.agent);
|
|
6375
6381
|
const branch = request.checkout.branch;
|
|
6376
6382
|
const baseBranch = request.checkout.immutable ? request.checkout.candidate?.sha ?? request.assignment.base.sha : request.assignment.base.sha;
|
|
6377
6383
|
const sandbox = await options.createSandbox({
|
|
@@ -6382,7 +6388,7 @@ var createCreateSandboxPhaseEngineAdapter = (options) => ({
|
|
|
6382
6388
|
});
|
|
6383
6389
|
try {
|
|
6384
6390
|
const result3 = await sandbox.run({
|
|
6385
|
-
agent,
|
|
6391
|
+
agent: options.agent,
|
|
6386
6392
|
prompt: buildPrompt(request),
|
|
6387
6393
|
toolAllowlist: request.controls.toolAllowlist,
|
|
6388
6394
|
maxIterations: request.controls.maxIterations,
|
|
@@ -9024,6 +9030,22 @@ var GitHubIntegration = class {
|
|
|
9024
9030
|
reason: ingest.reason
|
|
9025
9031
|
};
|
|
9026
9032
|
}
|
|
9033
|
+
async recordRejected(input) {
|
|
9034
|
+
const payloadRecord = record(input.payload);
|
|
9035
|
+
const delivery = {
|
|
9036
|
+
deliveryId: input.deliveryId,
|
|
9037
|
+
eventName: input.eventName,
|
|
9038
|
+
repository: payloadRecord ? repositoryName(payloadRecord) ?? "unknown" : "unknown",
|
|
9039
|
+
senderLogin: payloadRecord ? sender(payloadRecord).login : "unknown",
|
|
9040
|
+
receivedAt: this.now(),
|
|
9041
|
+
payloadHash: payloadHash(input.body),
|
|
9042
|
+
payload: input.payload,
|
|
9043
|
+
status: "rejected",
|
|
9044
|
+
reason: input.reason
|
|
9045
|
+
};
|
|
9046
|
+
const stored = await this.options.deliveryStore.recordDeliveryIfAbsent(delivery);
|
|
9047
|
+
if (!stored.inserted) return;
|
|
9048
|
+
}
|
|
9027
9049
|
async rejectStored(delivery, reason) {
|
|
9028
9050
|
await this.options.deliveryStore.updateDelivery({
|
|
9029
9051
|
...delivery,
|
|
@@ -9948,6 +9970,6 @@ var ReleaseIntegration = class {
|
|
|
9948
9970
|
};
|
|
9949
9971
|
var candidateMatchesApproval = (candidate, approval) => sameCandidate(candidate, approval.candidate);
|
|
9950
9972
|
|
|
9951
|
-
export { ContractValidationError, CredentialNotAllowedError, CredentialUnavailableError, CwdError2 as CwdError, GitHubIntegration, GitHubPublication, InMemoryCoordinatorStorage, InMemoryGitHubStore, InMemoryReleaseStore, InMemoryRepairBatchStore, InMemoryTriageStore, LeaseBusyError, LeaseLostError, Output, PostgresCoordinatorStorage, ReleaseIntegration, StructuredOutputError, WORKFLOW_CONTRACT_VERSION, WorkflowCoordinator, WorkflowOperator, candidateMatchesApproval, claudeCode, claudeHostSessionPath, claudeSandboxSessionPath, closeSourceIssue, codex, completeSourceIssue, createAssignment, createCreateSandboxPhaseEngineAdapter, createFakePhaseEngineAdapter, createGitHubIssueBrief, createInMemoryArtifactStore, createRepositoryPolicy, createRunPhaseEngineAdapter, createSandbox, createWorkBrief, createWorktree, defaultInvestigator as defaultTriageInvestigator, encodeProjectPath, evaluateHandoffReadiness, executePhase, findClaudeSessionOnHost, findCodexSessionOnHost, interactive, isAuthorizationAllowed, mergeProtectedCandidate, parseCheckEvidence, parsePhaseResult, parseRepositoryPolicy, parseWorkBrief, prepareHumanHandoff, prepareIndependentReview, processHumanReviewDecision, redact2 as redactOperatorText, releaseCandidateKey, requireTransition,
|
|
9973
|
+
export { ContractValidationError, CredentialNotAllowedError, CredentialUnavailableError, CwdError2 as CwdError, GitHubIntegration, GitHubPublication, InMemoryCoordinatorStorage, InMemoryGitHubStore, InMemoryReleaseStore, InMemoryRepairBatchStore, InMemoryTriageStore, LeaseBusyError, LeaseLostError, Output, PostgresCoordinatorStorage, ReleaseIntegration, StructuredOutputError, WORKFLOW_CONTRACT_VERSION, WorkflowCoordinator, WorkflowOperator, candidateMatchesApproval, claudeCode, claudeHostSessionPath, claudeSandboxSessionPath, closeSourceIssue, codex, completeSourceIssue, createAssignment, createCreateSandboxPhaseEngineAdapter, createFakePhaseEngineAdapter, createGitHubIssueBrief, createInMemoryArtifactStore, createRepositoryPolicy, createRunPhaseEngineAdapter, createSandbox, createWorkBrief, createWorktree, defaultInvestigator as defaultTriageInvestigator, encodeProjectPath, evaluateHandoffReadiness, executePhase, findClaudeSessionOnHost, findCodexSessionOnHost, interactive, isAuthorizationAllowed, mergeProtectedCandidate, parseCheckEvidence, parsePhaseResult, parseRepositoryPolicy, parseWorkBrief, prepareHumanHandoff, prepareIndependentReview, processHumanReviewDecision, redact2 as redactOperatorText, releaseCandidateKey, requireTransition, resolveHumanReviewDecision, reviewDecisionFor, run, runAuthorizedImplementation, runBoundedRepair, runIndependentReview, runTriage, scheduleBoundedRepair, transferClaudeSession, transferCodexSession, verifyGitHubWebhookSignature };
|
|
9952
9974
|
//# sourceMappingURL=index.js.map
|
|
9953
9975
|
//# sourceMappingURL=index.js.map
|