@bastani/atomic 0.9.61-alpha.1 → 0.9.61-alpha.2

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 (61) hide show
  1. package/CHANGELOG.md +54 -4
  2. package/dist/builtin/intercom/index.bundle.mjs +3 -3
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  6. package/dist/builtin/subagents/package.json +1 -1
  7. package/dist/builtin/web-access/package.json +1 -1
  8. package/dist/builtin/workflows/CHANGELOG.md +14 -0
  9. package/dist/builtin/workflows/README.md +9 -7
  10. package/dist/builtin/workflows/builtin/{chunk-h6bt0r0g.js → chunk-a2j0x1a6.js} +1 -1
  11. package/dist/builtin/workflows/builtin/{chunk-g3b2zf8r.js → chunk-vzbec50q.js} +1 -1
  12. package/dist/builtin/workflows/builtin/goal.js +1 -1
  13. package/dist/builtin/workflows/builtin/index.js +2 -2
  14. package/dist/builtin/workflows/builtin/ralph.js +1 -1
  15. package/dist/builtin/workflows/package.json +1 -1
  16. package/dist/builtin/workflows/src/extension/index.bundle.mjs +779 -409
  17. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +844 -419
  18. package/dist/builtin/workflows/src/index.js +749 -384
  19. package/dist/builtin/workflows/src/local-worker-entry.mjs +844 -419
  20. package/dist/core/agent-session-retry.d.ts.map +1 -1
  21. package/dist/core/agent-session-retry.js +12 -3
  22. package/dist/core/agent-session-retry.js.map +1 -1
  23. package/dist/core/model-fallback-failures.d.ts +14 -4
  24. package/dist/core/model-fallback-failures.d.ts.map +1 -1
  25. package/dist/core/model-fallback-failures.js +43 -15
  26. package/dist/core/model-fallback-failures.js.map +1 -1
  27. package/dist/core/settings-defaults.d.ts +1 -0
  28. package/dist/core/settings-defaults.d.ts.map +1 -1
  29. package/dist/core/settings-defaults.js +1 -0
  30. package/dist/core/settings-defaults.js.map +1 -1
  31. package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
  32. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  33. package/dist/core/settings-manager-basic-accessors.js +2 -0
  34. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  35. package/dist/core/settings-schema.d.ts +2 -0
  36. package/dist/core/settings-schema.d.ts.map +1 -1
  37. package/dist/core/settings-schema.js +4 -0
  38. package/dist/core/settings-schema.js.map +1 -1
  39. package/dist/core/slash-commands.js +2 -2
  40. package/dist/core/slash-commands.js.map +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/modes/interactive/interactive-startup-chat-container.d.ts +2 -0
  45. package/dist/modes/interactive/interactive-startup-chat-container.d.ts.map +1 -1
  46. package/dist/modes/interactive/interactive-startup-chat-container.js +6 -0
  47. package/dist/modes/interactive/interactive-startup-chat-container.js.map +1 -1
  48. package/dist/modes/interactive-engine/remote-renderer.d.ts +27 -5
  49. package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -1
  50. package/dist/modes/interactive-engine/remote-renderer.js +76 -16
  51. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
  52. package/docs/intercom/reference.md +1 -1
  53. package/docs/models/evals.md +30 -2
  54. package/docs/settings.md +3 -0
  55. package/docs/subagents/reference.md +3 -1
  56. package/docs/workflows/api-reference.md +9 -6
  57. package/docs/workflows/builtins.md +1 -1
  58. package/docs/workflows/operations.md +3 -3
  59. package/npm-shrinkwrap.json +32 -32
  60. package/package.json +3 -3
  61. package/schemas/settings.schema.json +5 -0
@@ -13456,9 +13456,104 @@ var init_workflow_artifacts = __esm(() => {
13456
13456
  pendingArtifactPrunes = new Map;
13457
13457
  });
13458
13458
 
13459
- // dist/builtin/workflows/src/runs/shared/worktree-generation.ts
13459
+ // dist/builtin/workflows/src/runs/shared/worktree-allocation.ts
13460
+ import { randomBytes } from "node:crypto";
13460
13461
  import * as fs from "node:fs";
13461
13462
  import * as path from "node:path";
13463
+ function nextBucketId() {
13464
+ return nextBucketIdOverride?.() ?? randomBytes(2).toString("hex");
13465
+ }
13466
+ function errorCode(error) {
13467
+ return error && typeof error === "object" && "code" in error ? String(error.code) : undefined;
13468
+ }
13469
+ function allocateWorktreeCheckoutPath(root, repositoryName) {
13470
+ for (let attempt = 0;attempt < MAX_BUCKET_ATTEMPTS; attempt++) {
13471
+ const bucket = path.join(root, nextBucketId());
13472
+ try {
13473
+ fs.mkdirSync(bucket);
13474
+ return path.join(bucket, repositoryName);
13475
+ } catch (error) {
13476
+ if (errorCode(error) === "EEXIST")
13477
+ continue;
13478
+ const message = error instanceof Error ? error.message : String(error);
13479
+ throw new Error(`Failed to create worktree bucket ${bucket} under gitWorktreeDir ${root}: ${message}`);
13480
+ }
13481
+ }
13482
+ throw new Error(`Every worktree bucket identifier under gitWorktreeDir ${root} is already in use.`);
13483
+ }
13484
+ function removeEmptyWorktreeBucket(checkout) {
13485
+ try {
13486
+ fs.rmdirSync(path.dirname(checkout));
13487
+ } catch {}
13488
+ }
13489
+ function linkedGitDirectory(checkout) {
13490
+ let pointer;
13491
+ try {
13492
+ if (!fs.lstatSync(path.join(checkout, ".git")).isFile())
13493
+ return;
13494
+ pointer = fs.readFileSync(path.join(checkout, ".git"), "utf8");
13495
+ } catch {
13496
+ return;
13497
+ }
13498
+ if (!pointer.startsWith("gitdir:"))
13499
+ return;
13500
+ const gitDir = pointer.slice("gitdir:".length).trim();
13501
+ return gitDir ? path.resolve(checkout, gitDir) : undefined;
13502
+ }
13503
+ function readWorktreeOwner(gitDir) {
13504
+ let contents;
13505
+ try {
13506
+ contents = fs.readFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), "utf8");
13507
+ } catch {
13508
+ return;
13509
+ }
13510
+ try {
13511
+ const record = JSON.parse(contents);
13512
+ return record.version === WORKTREE_OWNER_VERSION && typeof record.ownerRunId === "string" && record.ownerRunId ? record.ownerRunId : undefined;
13513
+ } catch {
13514
+ return;
13515
+ }
13516
+ }
13517
+ function findOwnedWorktreeCheckouts(root, repositoryName, ownerRunId) {
13518
+ let entries;
13519
+ try {
13520
+ entries = fs.readdirSync(root, { withFileTypes: true });
13521
+ } catch {
13522
+ return [];
13523
+ }
13524
+ const owned = [];
13525
+ for (const entry of entries) {
13526
+ if (!entry.isDirectory() || !BUCKET_PATTERN.test(entry.name))
13527
+ continue;
13528
+ const checkout = path.join(root, entry.name, repositoryName);
13529
+ try {
13530
+ if (!fs.lstatSync(checkout).isDirectory())
13531
+ continue;
13532
+ } catch {
13533
+ continue;
13534
+ }
13535
+ const gitDir = linkedGitDirectory(checkout);
13536
+ if (gitDir !== undefined && readWorktreeOwner(gitDir) === ownerRunId)
13537
+ owned.push(checkout);
13538
+ }
13539
+ return owned.sort();
13540
+ }
13541
+ function bindWorktreeOwner(gitDir, ownerRunId) {
13542
+ const record = { version: WORKTREE_OWNER_VERSION, ownerRunId };
13543
+ fs.writeFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), `${JSON.stringify(record)}
13544
+ `, {
13545
+ encoding: "utf8",
13546
+ flag: "wx"
13547
+ });
13548
+ }
13549
+ var WORKTREE_OWNER_FILENAME = "atomic-workflow-run.json", WORKTREE_OWNER_VERSION = 1, BUCKET_PATTERN, MAX_BUCKET_ATTEMPTS = 65536, nextBucketIdOverride;
13550
+ var init_worktree_allocation = __esm(() => {
13551
+ BUCKET_PATTERN = /^[0-9a-f]{4}$/;
13552
+ });
13553
+
13554
+ // dist/builtin/workflows/src/runs/shared/worktree-generation.ts
13555
+ import * as fs2 from "node:fs";
13556
+ import * as path2 from "node:path";
13462
13557
  function sameFileIdentity(left, right) {
13463
13558
  return left.dev === right.dev && left.ino === right.ino;
13464
13559
  }
@@ -13468,7 +13563,7 @@ function openMainCheckoutAnchor(gitDir) {
13468
13563
  assertCurrent() {
13469
13564
  if (disposed)
13470
13565
  throw new Error(`cached .git identity anchor is already disposed: ${gitDir}`);
13471
- if (!fs.lstatSync(gitDir).isDirectory()) {
13566
+ if (!fs2.lstatSync(gitDir).isDirectory()) {
13472
13567
  throw new Error(`cached main-checkout .git directory is no longer current: ${gitDir}`);
13473
13568
  }
13474
13569
  },
@@ -13478,17 +13573,17 @@ function openMainCheckoutAnchor(gitDir) {
13478
13573
  };
13479
13574
  }
13480
13575
  function openGitWorktreeGenerationAnchor(worktreeRoot) {
13481
- const gitFile = path.join(worktreeRoot, ".git");
13482
- if (fs.lstatSync(gitFile).isDirectory())
13576
+ const gitFile = path2.join(worktreeRoot, ".git");
13577
+ if (fs2.lstatSync(gitFile).isDirectory())
13483
13578
  return openMainCheckoutAnchor(gitFile);
13484
- const descriptor = fs.openSync(gitFile, "r");
13579
+ const descriptor = fs2.openSync(gitFile, "r");
13485
13580
  let disposed = false;
13486
13581
  const anchor = {
13487
13582
  assertCurrent() {
13488
13583
  if (disposed)
13489
13584
  throw new Error(`cached .git identity anchor is already disposed: ${gitFile}`);
13490
- const held = fs.fstatSync(descriptor, { bigint: true });
13491
- const current = fs.lstatSync(gitFile, { bigint: true });
13585
+ const held = fs2.fstatSync(descriptor, { bigint: true });
13586
+ const current = fs2.lstatSync(gitFile, { bigint: true });
13492
13587
  if (!current.isFile() || !sameFileIdentity(held, current)) {
13493
13588
  throw new Error(`cached .git identity anchor no longer matches the selected checkout: ${gitFile}`);
13494
13589
  }
@@ -13497,7 +13592,7 @@ function openGitWorktreeGenerationAnchor(worktreeRoot) {
13497
13592
  if (disposed)
13498
13593
  return;
13499
13594
  disposed = true;
13500
- fs.closeSync(descriptor);
13595
+ fs2.closeSync(descriptor);
13501
13596
  }
13502
13597
  };
13503
13598
  try {
@@ -13611,84 +13706,84 @@ var init_worktree_git_runner = __esm(() => {
13611
13706
  });
13612
13707
 
13613
13708
  // dist/builtin/workflows/src/runs/shared/worktree-root.ts
13614
- import * as fs2 from "node:fs";
13615
- import * as path2 from "node:path";
13709
+ import * as fs3 from "node:fs";
13710
+ import * as path3 from "node:path";
13616
13711
  function pathFromPointer(contents, prefix, base) {
13617
13712
  if (!contents.startsWith(prefix))
13618
13713
  return;
13619
13714
  const value2 = contents.slice(prefix.length).trim();
13620
13715
  if (!value2)
13621
13716
  return;
13622
- return path2.resolve(base, value2);
13717
+ return path3.resolve(base, value2);
13623
13718
  }
13624
13719
  function readText(file) {
13625
13720
  try {
13626
- return fs2.readFileSync(file, "utf8");
13721
+ return fs3.readFileSync(file, "utf8");
13627
13722
  } catch {
13628
13723
  return;
13629
13724
  }
13630
13725
  }
13631
13726
  function samePath(left, right) {
13632
13727
  try {
13633
- const a = fs2.realpathSync.native(left);
13634
- const b = fs2.realpathSync.native(right);
13728
+ const a = fs3.realpathSync.native(left);
13729
+ const b = fs3.realpathSync.native(right);
13635
13730
  return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
13636
13731
  } catch {
13637
13732
  return false;
13638
13733
  }
13639
13734
  }
13640
13735
  function findGitRoot(cwd) {
13641
- let current = path2.resolve(cwd);
13736
+ let current = path3.resolve(cwd);
13642
13737
  try {
13643
- if (!fs2.statSync(current).isDirectory())
13644
- current = path2.dirname(current);
13738
+ if (!fs3.statSync(current).isDirectory())
13739
+ current = path3.dirname(current);
13645
13740
  } catch {
13646
13741
  return;
13647
13742
  }
13648
13743
  while (true) {
13649
13744
  try {
13650
- const entry = fs2.statSync(path2.join(current, ".git"));
13745
+ const entry = fs3.statSync(path3.join(current, ".git"));
13651
13746
  if (entry.isDirectory() || entry.isFile())
13652
13747
  return current;
13653
13748
  } catch {}
13654
- const parent = path2.dirname(current);
13749
+ const parent = path3.dirname(current);
13655
13750
  if (parent === current)
13656
13751
  return;
13657
13752
  current = parent;
13658
13753
  }
13659
13754
  }
13660
13755
  function resolveMainRepoRoot(repoRoot) {
13661
- const gitEntry = path2.join(repoRoot, ".git");
13756
+ const gitEntry = path3.join(repoRoot, ".git");
13662
13757
  let stats;
13663
13758
  try {
13664
- stats = fs2.statSync(gitEntry);
13759
+ stats = fs3.statSync(gitEntry);
13665
13760
  } catch {
13666
13761
  return;
13667
13762
  }
13668
13763
  if (stats.isDirectory())
13669
- return path2.resolve(repoRoot);
13764
+ return path3.resolve(repoRoot);
13670
13765
  if (!stats.isFile())
13671
13766
  return;
13672
13767
  const pointer = readText(gitEntry);
13673
13768
  if (pointer === undefined)
13674
13769
  return;
13675
13770
  const gitDir = pathFromPointer(pointer, "gitdir:", repoRoot);
13676
- if (gitDir === undefined || path2.basename(path2.dirname(gitDir)) !== "worktrees")
13771
+ if (gitDir === undefined || path3.basename(path3.dirname(gitDir)) !== "worktrees")
13677
13772
  return;
13678
- const commonGitDir = path2.dirname(path2.dirname(gitDir));
13679
- if (path2.basename(commonGitDir) !== ".git")
13773
+ const commonGitDir = path3.dirname(path3.dirname(gitDir));
13774
+ if (path3.basename(commonGitDir) !== ".git")
13680
13775
  return;
13681
- const backPointer = readText(path2.join(gitDir, "gitdir"));
13682
- const commonPointer = readText(path2.join(gitDir, "commondir"));
13776
+ const backPointer = readText(path3.join(gitDir, "gitdir"));
13777
+ const commonPointer = readText(path3.join(gitDir, "commondir"));
13683
13778
  if (backPointer === undefined || commonPointer === undefined)
13684
13779
  return;
13685
- const linkedGitEntry = path2.resolve(gitDir, backPointer.trim());
13686
- const declaredCommonDir = path2.resolve(gitDir, commonPointer.trim());
13780
+ const linkedGitEntry = path3.resolve(gitDir, backPointer.trim());
13781
+ const declaredCommonDir = path3.resolve(gitDir, commonPointer.trim());
13687
13782
  if (!backPointer.trim() || !commonPointer.trim())
13688
13783
  return;
13689
13784
  if (!samePath(linkedGitEntry, gitEntry) || !samePath(declaredCommonDir, commonGitDir))
13690
13785
  return;
13691
- return path2.dirname(commonGitDir);
13786
+ return path3.dirname(commonGitDir);
13692
13787
  }
13693
13788
  function findCanonicalGitRoot(cwd) {
13694
13789
  const repoRoot = findGitRoot(cwd);
@@ -13697,33 +13792,31 @@ function findCanonicalGitRoot(cwd) {
13697
13792
  var init_worktree_root = () => {};
13698
13793
 
13699
13794
  // dist/builtin/workflows/src/runs/shared/worktree-git.ts
13700
- import * as fs3 from "node:fs";
13701
- import * as path3 from "node:path";
13702
- function gitWorktreeSetupCacheKey(options) {
13703
- const repoRoot = repositoryRootForGitWorktree(options.cwd);
13704
- const { logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
13705
- const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
13795
+ import * as fs4 from "node:fs";
13796
+ import * as path4 from "node:path";
13797
+ function gitWorktreeSetupCacheKey(request) {
13706
13798
  return JSON.stringify([
13707
- comparableRealPath(gitCommonDirForWorktree(repoRoot)),
13708
- comparablePathThroughExistingAncestor(worktreeRoot)
13799
+ comparablePathThroughExistingAncestor(request.options.cwd),
13800
+ comparablePathThroughExistingAncestor(request.target)
13709
13801
  ]);
13710
13802
  }
13711
- function createGitWorktreeSetupCache() {
13803
+ function createGitWorktreeSetupCache(ownerRunId) {
13712
13804
  const results = new Map;
13713
13805
  let disposed = false;
13714
13806
  return {
13715
13807
  get(options) {
13716
13808
  if (disposed)
13717
13809
  throw new Error("Git worktree setup cache is already disposed");
13718
- const key = gitWorktreeSetupCacheKey(options);
13810
+ const request = resolveGitWorktreeSetupRequest(options);
13811
+ const key = gitWorktreeSetupCacheKey(request);
13719
13812
  const cached = results.get(key);
13720
13813
  if (cached !== undefined) {
13721
13814
  assertCachedGitWorktreeIdentity(cached, options);
13722
13815
  return cached.result;
13723
13816
  }
13724
- const result = setupGitWorktree(options);
13725
- results.set(key, { result, identity: captureGitWorktreeIdentity(result) });
13726
- return result;
13817
+ const setup = setupGitWorktreeFromRequest(request, ownerRunId);
13818
+ results.set(key, { ...setup, identity: captureGitWorktreeIdentity(setup) });
13819
+ return setup.result;
13727
13820
  },
13728
13821
  dispose() {
13729
13822
  if (disposed)
@@ -13755,10 +13848,10 @@ function worktreeRecoveryCommand(repositoryRoot, worktreeDir) {
13755
13848
  return `git -C ${quoteShellArg(repositoryRoot)} worktree remove --force ${quoteShellArg(worktreeDir)}`;
13756
13849
  }
13757
13850
  function hasGrandparent(value2) {
13758
- const parent = path3.dirname(value2);
13851
+ const parent = path4.dirname(value2);
13759
13852
  if (parent === value2)
13760
13853
  return false;
13761
- const grandparent = path3.dirname(parent);
13854
+ const grandparent = path4.dirname(parent);
13762
13855
  return grandparent !== parent;
13763
13856
  }
13764
13857
  function pathAncestors(value2) {
@@ -13766,7 +13859,7 @@ function pathAncestors(value2) {
13766
13859
  let current = value2;
13767
13860
  while (true) {
13768
13861
  ancestors.push(current);
13769
- const parent = path3.dirname(current);
13862
+ const parent = path4.dirname(current);
13770
13863
  if (parent === current)
13771
13864
  return ancestors;
13772
13865
  current = parent;
@@ -13775,89 +13868,167 @@ function pathAncestors(value2) {
13775
13868
  function shouldPreserveLogicalPath(logicalPath) {
13776
13869
  return pathAncestors(logicalPath).some((ancestor) => {
13777
13870
  try {
13778
- return fs3.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
13871
+ return fs4.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
13779
13872
  } catch {
13780
13873
  return false;
13781
13874
  }
13782
13875
  });
13783
13876
  }
13784
13877
  function canonicalizePreservingSymlinks(value2) {
13785
- const logicalPath = path3.resolve(value2);
13878
+ const logicalPath = path4.resolve(value2);
13786
13879
  const preserveLogicalPath = shouldPreserveLogicalPath(logicalPath);
13787
13880
  try {
13788
- const canonical = fs3.realpathSync.native(logicalPath);
13881
+ const canonical = fs4.realpathSync.native(logicalPath);
13789
13882
  return preserveLogicalPath && canonical !== logicalPath ? logicalPath : canonical;
13790
13883
  } catch {
13791
13884
  return logicalPath;
13792
13885
  }
13793
13886
  }
13794
- function resolveGitWorktreePath(value2, repoRoot) {
13887
+ function resolveGitWorktreePath(value2, baseDir) {
13795
13888
  const trimmed = value2.trim();
13796
13889
  if (!trimmed)
13797
13890
  throw new Error("gitWorktreeDir cannot be empty");
13798
13891
  if (trimmed.includes("\x00")) {
13799
13892
  throw new Error("gitWorktreeDir contains an unusable null byte; provide a valid path or omit gitWorktreeDir.");
13800
13893
  }
13801
- return canonicalizePreservingSymlinks(path3.isAbsolute(trimmed) ? trimmed : path3.resolve(repoRoot, trimmed));
13894
+ return canonicalizePreservingSymlinks(path4.isAbsolute(trimmed) ? trimmed : path4.resolve(baseDir, trimmed));
13802
13895
  }
13803
13896
  function comparableRealPath(value2) {
13804
- const realpath = fs3.realpathSync.native(value2).replace(/\\/g, "/");
13897
+ const realpath = fs4.realpathSync.native(value2).replace(/\\/g, "/");
13805
13898
  return process.platform === "win32" ? realpath.toLowerCase() : realpath;
13806
13899
  }
13807
- function comparablePathThroughExistingAncestor(value2) {
13808
- let existing = path3.resolve(value2);
13900
+ function nearestExistingAncestor(value2) {
13901
+ let existing = path4.resolve(value2);
13809
13902
  const missing = [];
13810
13903
  while (!pathExistsSync(existing)) {
13811
- const parent = path3.dirname(existing);
13904
+ const parent = path4.dirname(existing);
13812
13905
  if (parent === existing)
13813
13906
  break;
13814
- missing.unshift(path3.basename(existing));
13907
+ missing.unshift(path4.basename(existing));
13815
13908
  existing = parent;
13816
13909
  }
13817
- const resolved = path3.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
13910
+ return { existing, missing };
13911
+ }
13912
+ function comparablePathThroughExistingAncestor(value2) {
13913
+ const { existing, missing } = nearestExistingAncestor(value2);
13914
+ const resolved = path4.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
13818
13915
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
13819
13916
  }
13917
+ function isFileOrLink(value2) {
13918
+ try {
13919
+ const entry = fs4.lstatSync(value2);
13920
+ return entry.isFile() || entry.isSymbolicLink();
13921
+ } catch {
13922
+ return false;
13923
+ }
13924
+ }
13925
+ function isDirectory(value2) {
13926
+ try {
13927
+ return fs4.statSync(value2).isDirectory();
13928
+ } catch {
13929
+ return false;
13930
+ }
13931
+ }
13932
+ function looksLikeGitDirectory(directory) {
13933
+ if (!isDirectory(directory))
13934
+ return false;
13935
+ if (path4.basename(directory) === ".git")
13936
+ return true;
13937
+ if (!isFileOrLink(path4.join(directory, "HEAD")))
13938
+ return false;
13939
+ if (isFileOrLink(path4.join(directory, "commondir")))
13940
+ return true;
13941
+ return isDirectory(path4.join(directory, "objects")) && isDirectory(path4.join(directory, "refs"));
13942
+ }
13943
+ function enclosingGitMetadataDirectory(target) {
13944
+ const { existing } = nearestExistingAncestor(target);
13945
+ let realExisting = existing;
13946
+ try {
13947
+ realExisting = fs4.realpathSync.native(existing);
13948
+ } catch {}
13949
+ for (const candidate of new Set([...pathAncestors(existing), ...pathAncestors(realExisting)])) {
13950
+ if (looksLikeGitDirectory(candidate))
13951
+ return candidate;
13952
+ }
13953
+ const insideGitDir = runGitReadOnlyProbe(existing, ["rev-parse", "--is-inside-git-dir"]);
13954
+ if (insideGitDir.status !== 0 && isGitTimeoutResult(insideGitDir)) {
13955
+ throw new Error(`Timed out while validating gitWorktreeDir ${target}. Git reported: ${gitFailureMessage(insideGitDir)}`);
13956
+ }
13957
+ return insideGitDir.status === 0 && insideGitDir.stdout.trim() === "true" ? existing : undefined;
13958
+ }
13959
+ function assertSafeGitWorktreeTarget(target, invokingRoot) {
13960
+ const gitDirectory = enclosingGitMetadataDirectory(target);
13961
+ if (gitDirectory !== undefined) {
13962
+ throw new Error(`gitWorktreeDir must not be inside Git metadata: ${target} is inside the Git directory ${gitDirectory}. Choose a worktree root or a plain directory outside Git metadata.`);
13963
+ }
13964
+ if (invokingRoot !== undefined)
13965
+ validateWorktreeOutsideInvokingCheckout(target, invokingRoot);
13966
+ const { existing, missing } = nearestExistingAncestor(target);
13967
+ const workingTree = gitTopLevel(existing);
13968
+ if (workingTree === undefined)
13969
+ return;
13970
+ if (missing.length === 0 && comparableRealPath(target) === comparableRealPath(workingTree))
13971
+ return;
13972
+ throw new Error(`gitWorktreeDir must not be inside another Git working tree: ${target} is inside ${workingTree}. Pass that checkout's root to reuse it, or a path outside every Git checkout.`);
13973
+ }
13820
13974
  function validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot) {
13821
13975
  const repository = comparableRealPath(repoRoot);
13822
13976
  const candidate = comparablePathThroughExistingAncestor(worktreeRoot);
13823
- const relativePath = path3.relative(repository, candidate);
13977
+ const relativePath = path4.relative(repository, candidate);
13824
13978
  if (relativePath === "") {
13825
- throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate same-repository worktree path.");
13979
+ throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate worktree path outside it.");
13826
13980
  }
13827
- if (!relativePath.startsWith(`..${path3.sep}`) && relativePath !== ".." && !path3.isAbsolute(relativePath)) {
13828
- throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate same-repository worktree path.");
13981
+ if (!relativePath.startsWith(`..${path4.sep}`) && relativePath !== ".." && !path4.isAbsolute(relativePath)) {
13982
+ throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate worktree path outside it.");
13829
13983
  }
13830
13984
  }
13831
13985
  function gitPathFromOutput(value2, cwd) {
13832
13986
  const trimmed = value2.trim();
13833
13987
  if (!trimmed)
13834
13988
  return;
13835
- return path3.isAbsolute(trimmed) ? path3.resolve(trimmed) : path3.resolve(cwd, trimmed);
13989
+ return path4.isAbsolute(trimmed) ? path4.resolve(trimmed) : path4.resolve(cwd, trimmed);
13836
13990
  }
13837
13991
  function pathExistsSync(value2) {
13992
+ return pathStatSync(value2) !== undefined;
13993
+ }
13994
+ function pathStatSync(value2) {
13838
13995
  try {
13839
- fs3.statSync(value2);
13840
- return true;
13996
+ return fs4.statSync(value2);
13841
13997
  } catch (error) {
13842
13998
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
13843
13999
  if (code === "ENOENT" || code === "ENOTDIR")
13844
- return false;
14000
+ return;
13845
14001
  throw error;
13846
14002
  }
13847
14003
  }
13848
- function repositoryRootForGitWorktree(cwd) {
14004
+ function probeInvokingRepository(cwd) {
13849
14005
  const result = runGitReadOnlyProbe(cwd, ["rev-parse", "--show-toplevel"]);
13850
14006
  if (result.status !== 0) {
13851
14007
  if (isGitTimeoutResult(result)) {
13852
14008
  throw new Error(`Timed out while checking the Git repository for gitWorktreeDir from ${cwd}. Git reported: ${gitFailureMessage(result)}`);
13853
14009
  }
13854
- throw new Error(`gitWorktreeDir requires the workflow to be invoked from inside a Git repository. Start from a Git checkout or omit gitWorktreeDir. Git reported: ${gitFailureMessage(result)}`);
14010
+ return { failure: gitFailureMessage(result) };
13855
14011
  }
13856
- const normalized = gitPathFromOutput(result.stdout, cwd);
13857
- if (normalized === undefined) {
14012
+ const root = gitPathFromOutput(result.stdout, cwd);
14013
+ if (root === undefined) {
13858
14014
  throw new Error(`gitWorktreeDir could not resolve the repository top level from ${cwd}: git returned an empty path.`);
13859
14015
  }
13860
- return normalized;
14016
+ return { repository: { root, ...cwdWithinGitRepository(cwd, root) } };
14017
+ }
14018
+ function resolveGitWorktreeSetupRequest(options) {
14019
+ const probe = probeInvokingRepository(options.cwd);
14020
+ if ("repository" in probe) {
14021
+ return {
14022
+ options,
14023
+ repository: probe.repository,
14024
+ target: resolveGitWorktreePath(options.gitWorktreeDir, probe.repository.logicalRoot)
14025
+ };
14026
+ }
14027
+ return {
14028
+ options,
14029
+ repositoryProbeFailure: probe.failure,
14030
+ target: resolveGitWorktreePath(options.gitWorktreeDir, canonicalizePreservingSymlinks(options.cwd))
14031
+ };
13861
14032
  }
13862
14033
  function gitTopLevelFromResult(result, cwd, description) {
13863
14034
  if (result.status !== 0) {
@@ -13893,25 +14064,25 @@ function dirnameForEachRelativeComponent(base, relativePath) {
13893
14064
  continue;
13894
14065
  if (component === "..")
13895
14066
  return;
13896
- current = path3.dirname(current);
14067
+ current = path4.dirname(current);
13897
14068
  }
13898
14069
  return current;
13899
14070
  }
13900
14071
  function cwdWithinGitRepository(cwd, repoRoot) {
13901
- const sourceCwd = fs3.realpathSync.native(cwd);
13902
- const sourceRepoRoot = fs3.realpathSync.native(repoRoot);
13903
- const relativeCwd = path3.relative(sourceRepoRoot, sourceCwd);
13904
- const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path3.isAbsolute(relativeCwd) ? "" : relativeCwd;
14072
+ const sourceCwd = fs4.realpathSync.native(cwd);
14073
+ const sourceRepoRoot = fs4.realpathSync.native(repoRoot);
14074
+ const relativeCwd = path4.relative(sourceRepoRoot, sourceCwd);
14075
+ const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path4.isAbsolute(relativeCwd) ? "" : relativeCwd;
13905
14076
  const logicalCwd = canonicalizePreservingSymlinks(cwd);
13906
14077
  return {
13907
14078
  relativeCwd: safeRelativeCwd,
13908
- logicalRepoRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
14079
+ logicalRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
13909
14080
  };
13910
14081
  }
13911
14082
  function workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd) {
13912
- return relativeCwd === "" ? worktreeRoot : path3.join(worktreeRoot, relativeCwd);
14083
+ return relativeCwd === "" ? worktreeRoot : path4.join(worktreeRoot, relativeCwd);
13913
14084
  }
13914
- function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
14085
+ function validateGitWorktreeRoot(worktreeRoot) {
13915
14086
  const topLevel = gitTopLevel(worktreeRoot);
13916
14087
  if (topLevel === undefined) {
13917
14088
  throw new Error(`gitWorktreeDir already exists but is not a Git worktree: ${worktreeRoot}`);
@@ -13919,8 +14090,18 @@ function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
13919
14090
  if (comparableRealPath(worktreeRoot) !== comparableRealPath(topLevel)) {
13920
14091
  throw new Error(`gitWorktreeDir already exists but is not a Git worktree root: ${worktreeRoot}. Git top-level checkout is ${topLevel}`);
13921
14092
  }
13922
- if (comparableRealPath(gitCommonDirForWorktree(repoRoot)) !== comparableRealPath(gitCommonDirForWorktree(topLevel))) {
13923
- throw new Error(`gitWorktreeDir already exists but does not belong to the invoking Git repository: ${worktreeRoot}`);
14093
+ return gitCommonDirForWorktree(topLevel);
14094
+ }
14095
+ function existingGitWorktreeCommonDir(directory) {
14096
+ return gitTopLevel(directory) === undefined ? undefined : validateGitWorktreeRoot(directory);
14097
+ }
14098
+ function sameGitCommonDir(left, right) {
14099
+ return comparableRealPath(left) === comparableRealPath(right);
14100
+ }
14101
+ function validateCreatedGitWorktree(worktreeRoot, repository) {
14102
+ assertSafeGitWorktreeTarget(worktreeRoot, repository.root);
14103
+ if (!sameGitCommonDir(validateGitWorktreeRoot(worktreeRoot), gitCommonDirForWorktree(repository.root))) {
14104
+ throw new Error(`gitWorktreeDir does not belong to the invoking Git repository: ${worktreeRoot}`);
13924
14105
  }
13925
14106
  }
13926
14107
  function gitDirectoryForWorktree(cwd) {
@@ -13934,26 +14115,27 @@ function gitDirectoryForWorktree(cwd) {
13934
14115
  return gitDir;
13935
14116
  }
13936
14117
  function captureGitWorktreeIdentitySnapshot(setup) {
13937
- validateWorktreeOutsideInvokingCheckout(setup.worktreeRoot, setup.repositoryRoot);
13938
- validateExistingGitWorktreeRoot(setup.worktreeRoot, setup.repositoryRoot);
13939
- const stats = fs3.statSync(setup.worktreeRoot);
14118
+ const { worktreeRoot, repositoryRoot } = setup.result;
14119
+ assertSafeGitWorktreeTarget(worktreeRoot, setup.invokingRoot);
14120
+ const commonDir = validateGitWorktreeRoot(worktreeRoot);
14121
+ const stats = fs4.statSync(worktreeRoot);
13940
14122
  return {
13941
- worktreeRealPath: comparableRealPath(setup.worktreeRoot),
13942
- repositoryRealPath: comparableRealPath(setup.repositoryRoot),
13943
- gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(setup.worktreeRoot)),
13944
- commonDirRealPath: comparableRealPath(gitCommonDirForWorktree(setup.worktreeRoot)),
14123
+ worktreeRealPath: comparableRealPath(worktreeRoot),
14124
+ repositoryRealPath: comparableRealPath(repositoryRoot),
14125
+ gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(worktreeRoot)),
14126
+ commonDirRealPath: comparableRealPath(commonDir),
13945
14127
  device: stats.dev,
13946
14128
  inode: stats.ino
13947
14129
  };
13948
14130
  }
13949
14131
  function captureGitWorktreeIdentity(setup) {
13950
14132
  const snapshot = captureGitWorktreeIdentitySnapshot(setup);
13951
- return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.worktreeRoot) };
14133
+ return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.result.worktreeRoot) };
13952
14134
  }
13953
14135
  function assertCachedGitWorktreeIdentity(cached, options) {
13954
14136
  let current;
13955
14137
  try {
13956
- current = captureGitWorktreeIdentitySnapshot(cached.result);
14138
+ current = captureGitWorktreeIdentitySnapshot(cached);
13957
14139
  cached.identity.generation.assertCurrent();
13958
14140
  } catch (error) {
13959
14141
  const message = error instanceof Error ? error.message : String(error);
@@ -13961,34 +14143,58 @@ function assertCachedGitWorktreeIdentity(cached, options) {
13961
14143
  }
13962
14144
  const expected = cached.identity;
13963
14145
  if (current.worktreeRealPath !== expected.worktreeRealPath || current.repositoryRealPath !== expected.repositoryRealPath || current.gitDirRealPath !== expected.gitDirRealPath || current.commonDirRealPath !== expected.commonDirRealPath || current.device !== expected.device || current.inode !== expected.inode) {
13964
- throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended same-repository worktree.`);
13965
- }
14146
+ throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended worktree.`);
14147
+ }
14148
+ }
14149
+ function requireInvokingRepository(request, action) {
14150
+ if (request.repository !== undefined)
14151
+ return request.repository;
14152
+ throw new Error([
14153
+ `gitWorktreeDir requires the workflow to be invoked from inside a Git repository to ${action}.`,
14154
+ "Start the workflow from a checkout of the repository the new worktree should come from, or set gitWorktreeDir to the root of an existing Git worktree to reuse it from any directory.",
14155
+ `Git reported: ${request.repositoryProbeFailure ?? "no repository"}`
14156
+ ].join(" "));
14157
+ }
14158
+ function setupGitWorktreeFromRequest(request, ownerRunId) {
14159
+ const { repository, target } = request;
14160
+ assertSafeGitWorktreeTarget(target, repository?.root);
14161
+ const entry = pathStatSync(target);
14162
+ if (entry === undefined)
14163
+ return createGitWorktreeAtPath(request, false);
14164
+ if (!entry.isDirectory())
14165
+ throw new Error(`gitWorktreeDir already exists but is not a directory: ${target}`);
14166
+ if (fs4.readdirSync(target).length === 0)
14167
+ return createGitWorktreeAtPath(request, true);
14168
+ const commonDir = existingGitWorktreeCommonDir(target);
14169
+ if (commonDir === undefined)
14170
+ return allocateGitWorktree(request, ownerRunId);
14171
+ const sameRepository = repository !== undefined && sameGitCommonDir(commonDir, gitCommonDirForWorktree(repository.root));
14172
+ return {
14173
+ result: {
14174
+ worktreeRoot: target,
14175
+ cwd: sameRepository ? workspaceCwdForGitWorktreeRoot(target, repository.relativeCwd) : target,
14176
+ repositoryRoot: sameRepository ? repository.root : target,
14177
+ created: false
14178
+ },
14179
+ ...repository !== undefined ? { invokingRoot: repository.root } : {}
14180
+ };
13966
14181
  }
13967
- function setupGitWorktree(options) {
13968
- const repoRoot = repositoryRootForGitWorktree(options.cwd);
13969
- const mainRoot = findCanonicalGitRoot(repoRoot);
14182
+ function createGitWorktreeAtPath(request, existingEmptyDirectory) {
14183
+ const { target: worktreeRoot } = request;
14184
+ const repository = requireInvokingRepository(request, `create a new worktree at ${worktreeRoot}`);
14185
+ const mainRoot = findCanonicalGitRoot(repository.root);
13970
14186
  if (mainRoot === undefined) {
13971
- throw new Error(`Unable to resolve the canonical main Git repository root from ${repoRoot}.`);
13972
- }
13973
- const { relativeCwd, logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
13974
- const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
13975
- validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot);
13976
- if (pathExistsSync(worktreeRoot)) {
13977
- validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
13978
- return {
13979
- worktreeRoot,
13980
- cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
13981
- repositoryRoot: repoRoot,
13982
- created: false
13983
- };
14187
+ throw new Error(`Unable to resolve the canonical main Git repository root from ${repository.root}.`);
13984
14188
  }
13985
- try {
13986
- fs3.mkdirSync(path3.dirname(worktreeRoot), { recursive: true });
13987
- } catch (error) {
13988
- const message = error instanceof Error ? error.message : String(error);
13989
- throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
14189
+ if (!existingEmptyDirectory) {
14190
+ try {
14191
+ fs4.mkdirSync(path4.dirname(worktreeRoot), { recursive: true });
14192
+ } catch (error) {
14193
+ const message = error instanceof Error ? error.message : String(error);
14194
+ throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
14195
+ }
13990
14196
  }
13991
- const baseRef = options.baseBranch?.trim() || "HEAD";
14197
+ const baseRef = request.options.baseBranch?.trim() || "HEAD";
13992
14198
  const result = runGit(mainRoot, ["worktree", "add", "--detach", worktreeRoot, baseRef]);
13993
14199
  if (result.status !== 0) {
13994
14200
  throw new Error([
@@ -13998,30 +14204,127 @@ function setupGitWorktree(options) {
13998
14204
  `));
13999
14205
  }
14000
14206
  try {
14001
- validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot);
14002
- validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
14207
+ validateCreatedGitWorktree(worktreeRoot, repository);
14003
14208
  } catch (error) {
14004
14209
  runGit(mainRoot, ["worktree", "remove", "--force", worktreeRoot]);
14005
14210
  const message = error instanceof Error ? error.message : String(error);
14006
14211
  throw new Error(`Created gitWorktreeDir failed post-creation validation: ${message}`);
14007
14212
  }
14008
14213
  return {
14009
- worktreeRoot,
14010
- cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
14011
- repositoryRoot: repoRoot,
14012
- created: true
14214
+ result: {
14215
+ worktreeRoot,
14216
+ cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, repository.relativeCwd),
14217
+ repositoryRoot: repository.root,
14218
+ created: true
14219
+ },
14220
+ invokingRoot: repository.root
14221
+ };
14222
+ }
14223
+ function containedWorktreeCwd(checkout, relativeCwd) {
14224
+ const cwd = workspaceCwdForGitWorktreeRoot(checkout, relativeCwd);
14225
+ let resolved;
14226
+ try {
14227
+ resolved = fs4.realpathSync.native(cwd);
14228
+ } catch {
14229
+ resolved = "";
14230
+ }
14231
+ const relative2 = resolved === "" ? undefined : path4.relative(fs4.realpathSync.native(checkout), resolved);
14232
+ if (relative2 === undefined || relative2 === ".." || relative2.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative2) || !fs4.statSync(resolved).isDirectory()) {
14233
+ throw new Error(`The selected base does not contain a working directory ${relativeCwd || "."} inside the worktree ${checkout}.`);
14234
+ }
14235
+ return cwd;
14236
+ }
14237
+ function allocatedGitWorktreeSetup(checkout, repository, created) {
14238
+ return {
14239
+ result: {
14240
+ worktreeRoot: checkout,
14241
+ cwd: containedWorktreeCwd(checkout, repository.relativeCwd),
14242
+ repositoryRoot: repository.root,
14243
+ created
14244
+ },
14245
+ invokingRoot: repository.root
14013
14246
  };
14014
14247
  }
14248
+ function validateOwnedGitWorktree(checkout, repository) {
14249
+ validateCreatedGitWorktree(checkout, repository);
14250
+ const gitDir = gitDirectoryForWorktree(checkout);
14251
+ if (sameGitCommonDir(gitDir, gitCommonDirForWorktree(checkout))) {
14252
+ throw new Error(`${checkout} is not a linked worktree`);
14253
+ }
14254
+ const backlink = fs4.readFileSync(path4.join(gitDir, "gitdir"), "utf8").trim();
14255
+ if (!backlink || comparableRealPath(path4.resolve(gitDir, backlink)) !== comparableRealPath(path4.join(checkout, ".git"))) {
14256
+ throw new Error(`the Git directory of ${checkout} belongs to another checkout`);
14257
+ }
14258
+ }
14259
+ function findOwnedGitWorktree(root, repository, ownerRunId) {
14260
+ const [checkout] = findOwnedWorktreeCheckouts(root, path4.basename(repository.root), ownerRunId);
14261
+ if (checkout === undefined)
14262
+ return;
14263
+ try {
14264
+ validateOwnedGitWorktree(checkout, repository);
14265
+ return allocatedGitWorktreeSetup(checkout, repository, false);
14266
+ } catch (error) {
14267
+ const message = error instanceof Error ? error.message : String(error);
14268
+ throw new Error(`The worktree this workflow run allocated under gitWorktreeDir ${root} can no longer be reused: ${checkout}. ${message}`);
14269
+ }
14270
+ }
14271
+ function allocateGitWorktree(request, ownerRunId) {
14272
+ const { target: root } = request;
14273
+ const repository = requireInvokingRepository(request, `create a new worktree under ${root}`);
14274
+ if (ownerRunId !== undefined) {
14275
+ const owned = findOwnedGitWorktree(root, repository, ownerRunId);
14276
+ if (owned !== undefined)
14277
+ return owned;
14278
+ }
14279
+ const baseRef = request.options.baseBranch?.trim() || "HEAD";
14280
+ const revision = runGit(repository.root, ["rev-parse", "--verify", "--end-of-options", `${baseRef}^{commit}`]);
14281
+ const commit = revision.status === 0 ? revision.stdout.trim() : "";
14282
+ if (commit === "") {
14283
+ throw new Error(`Failed to resolve ${baseRef} to a commit for gitWorktreeDir ${root}. Git reported: ${gitFailureMessage(revision)}`);
14284
+ }
14285
+ const checkout = allocateWorktreeCheckoutPath(root, path4.basename(repository.root));
14286
+ const add = runGit(repository.root, ["worktree", "add", "--detach", "--no-checkout", checkout, commit]);
14287
+ if (add.status !== 0) {
14288
+ removeEmptyWorktreeBucket(checkout);
14289
+ throw new Error(`Failed to create git worktree at ${checkout} under gitWorktreeDir ${root} from ${baseRef}. Git reported: ${gitFailureMessage(add)}`);
14290
+ }
14291
+ try {
14292
+ const gitDir = gitDirectoryForWorktree(checkout);
14293
+ runGitOrThrow(checkout, ["config", "--file", path4.join(gitDir, "config.worktree"), "core.worktree", checkout]);
14294
+ runGitOrThrow(checkout, ["--work-tree=.", "reset", "--hard", "--no-recurse-submodules", commit]);
14295
+ validateCreatedGitWorktree(checkout, repository);
14296
+ const setup = allocatedGitWorktreeSetup(checkout, repository, true);
14297
+ if (ownerRunId !== undefined)
14298
+ bindWorktreeOwner(gitDir, ownerRunId);
14299
+ return setup;
14300
+ } catch (error) {
14301
+ const message = error instanceof Error ? error.message : String(error);
14302
+ const removal = runGit(repository.root, ["worktree", "remove", "--force", checkout]);
14303
+ removeEmptyWorktreeBucket(checkout);
14304
+ const rollback = removal.status === 0 ? "" : ` Rolling back the incomplete worktree also failed; remove it with: ${worktreeRecoveryCommand(repository.root, checkout)}`;
14305
+ throw new Error(`Failed to set up git worktree at ${checkout} under gitWorktreeDir ${root}: ${message}${rollback}`);
14306
+ }
14307
+ }
14308
+ function runGitOrThrow(cwd, args) {
14309
+ const result = runGit(cwd, args);
14310
+ if (result.status !== 0)
14311
+ throw new Error(gitFailureMessage(result));
14312
+ }
14313
+ function setupGitWorktree(options) {
14314
+ return setupGitWorktreeFromRequest(resolveGitWorktreeSetupRequest(options)).result;
14315
+ }
14015
14316
  var init_worktree_git = __esm(() => {
14317
+ init_worktree_allocation();
14016
14318
  init_worktree_generation();
14017
14319
  init_worktree_git_runner();
14018
14320
  init_worktree_root();
14321
+ init_worktree_allocation();
14019
14322
  init_worktree_git_runner();
14020
14323
  });
14021
14324
 
14022
14325
  // dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts
14023
- function createGitWorktreeSetupCacheOwner(suppliedCache) {
14024
- const cache = suppliedCache ?? createGitWorktreeSetupCache();
14326
+ function createGitWorktreeSetupCacheOwner(suppliedCache, ownerRunId) {
14327
+ const cache = suppliedCache ?? createGitWorktreeSetupCache(ownerRunId);
14025
14328
  const ownsCache = suppliedCache === undefined;
14026
14329
  let released = false;
14027
14330
  return {
@@ -14042,20 +14345,20 @@ var init_worktree_cache_lifecycle = __esm(() => {
14042
14345
  });
14043
14346
 
14044
14347
  // dist/builtin/workflows/src/runs/shared/worktree-diff.ts
14045
- import * as fs4 from "node:fs";
14046
- import * as path4 from "node:path";
14348
+ import * as fs5 from "node:fs";
14349
+ import * as path5 from "node:path";
14047
14350
  function safePatchAgentName(agent) {
14048
14351
  return agent.replace(/[^\w.-]/g, "_");
14049
14352
  }
14050
14353
  function removeSyntheticPath(worktree, syntheticPath) {
14051
- const resolved = path4.resolve(worktree.path, syntheticPath);
14052
- const relative = path4.relative(worktree.path, resolved);
14053
- if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative)) {
14354
+ const resolved = path5.resolve(worktree.path, syntheticPath);
14355
+ const relative = path5.relative(worktree.path, resolved);
14356
+ if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path5.sep}`) || path5.isAbsolute(relative)) {
14054
14357
  return;
14055
14358
  }
14056
14359
  let stat;
14057
14360
  try {
14058
- stat = fs4.lstatSync(resolved);
14361
+ stat = fs5.lstatSync(resolved);
14059
14362
  } catch (error) {
14060
14363
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
14061
14364
  if (code === "ENOENT")
@@ -14063,14 +14366,14 @@ function removeSyntheticPath(worktree, syntheticPath) {
14063
14366
  throw error;
14064
14367
  }
14065
14368
  if (stat.isSymbolicLink()) {
14066
- fs4.unlinkSync(resolved);
14369
+ fs5.unlinkSync(resolved);
14067
14370
  return;
14068
14371
  }
14069
14372
  if (stat.isDirectory()) {
14070
- fs4.rmSync(resolved, { recursive: true, force: true });
14373
+ fs5.rmSync(resolved, { recursive: true, force: true });
14071
14374
  return;
14072
14375
  }
14073
- fs4.rmSync(resolved, { force: true });
14376
+ fs5.rmSync(resolved, { force: true });
14074
14377
  }
14075
14378
  function removeSyntheticPathsBeforeDiff(worktree) {
14076
14379
  if (worktree.syntheticPaths.length === 0)
@@ -14119,7 +14422,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
14119
14422
  const diffStat = runGitChecked(worktree.path, ["diff", "--cached", "--stat", setup.baseCommit]).trim();
14120
14423
  const patch = runGitChecked(worktree.path, ["diff", "--cached", setup.baseCommit]);
14121
14424
  const numstat = runGitChecked(worktree.path, ["diff", "--cached", "--numstat", setup.baseCommit]);
14122
- fs4.writeFileSync(patchPath, patch, "utf-8");
14425
+ fs5.writeFileSync(patchPath, patch, "utf-8");
14123
14426
  if (!patch.trim()) {
14124
14427
  return emptyDiff(worktree.index, agent, worktree.branch, patchPath);
14125
14428
  }
@@ -14137,7 +14440,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
14137
14440
  }
14138
14441
  function writeEmptyPatch(patchPath) {
14139
14442
  try {
14140
- fs4.writeFileSync(patchPath, "", "utf-8");
14443
+ fs5.writeFileSync(patchPath, "", "utf-8");
14141
14444
  } catch {}
14142
14445
  }
14143
14446
  function hasWorktreeChanges(diff) {
@@ -14145,7 +14448,7 @@ function hasWorktreeChanges(diff) {
14145
14448
  }
14146
14449
  function diffWorktrees(setup, agents, diffsDir) {
14147
14450
  try {
14148
- fs4.mkdirSync(diffsDir, { recursive: true });
14451
+ fs5.mkdirSync(diffsDir, { recursive: true });
14149
14452
  } catch {
14150
14453
  return [];
14151
14454
  }
@@ -14153,7 +14456,7 @@ function diffWorktrees(setup, agents, diffsDir) {
14153
14456
  for (let index = 0;index < setup.worktrees.length; index++) {
14154
14457
  const worktree = setup.worktrees[index];
14155
14458
  const agent = agents[index] ?? `task-${index + 1}`;
14156
- const patchPath = path4.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
14459
+ const patchPath = path5.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
14157
14460
  try {
14158
14461
  diffs.push(captureWorktreeDiff(setup, worktree, agent, patchPath));
14159
14462
  } catch {
@@ -14175,7 +14478,7 @@ function formatWorktreeDiffSummary(diffs) {
14175
14478
  }
14176
14479
  lines.push("");
14177
14480
  }
14178
- const patchesDir = path4.dirname(changed[0].patchPath);
14481
+ const patchesDir = path5.dirname(changed[0].patchPath);
14179
14482
  lines.push(`Full patches: ${patchesDir}`);
14180
14483
  return lines.join(`
14181
14484
  `).trimEnd();
@@ -14185,8 +14488,8 @@ var init_worktree_diff = __esm(() => {
14185
14488
  });
14186
14489
 
14187
14490
  // dist/builtin/workflows/src/runs/shared/worktree-post-create.ts
14188
- import * as fs5 from "node:fs";
14189
- import * as path5 from "node:path";
14491
+ import * as fs6 from "node:fs";
14492
+ import * as path6 from "node:path";
14190
14493
  function tracked(repo, relativePath) {
14191
14494
  const result = runGit(repo, ["ls-files", "--error-unmatch", "--", relativePath]);
14192
14495
  return result.status === 0;
@@ -14206,12 +14509,12 @@ function hasTrackedPathComponent(repo, relativePath) {
14206
14509
  return false;
14207
14510
  }
14208
14511
  function copyUntrackedFile(mainRoot, worktreeRoot, relativePath) {
14209
- const source = path5.join(mainRoot, relativePath);
14210
- const destination = path5.join(worktreeRoot, relativePath);
14211
- if (!fs5.existsSync(source) || fs5.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14512
+ const source = path6.join(mainRoot, relativePath);
14513
+ const destination = path6.join(worktreeRoot, relativePath);
14514
+ if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14212
14515
  return false;
14213
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
14214
- fs5.copyFileSync(source, destination);
14516
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
14517
+ fs6.copyFileSync(source, destination);
14215
14518
  return true;
14216
14519
  }
14217
14520
  function propagateLocalSettings(mainRoot, worktreeRoot) {
@@ -14224,14 +14527,14 @@ function propagateLocalSettings(mainRoot, worktreeRoot) {
14224
14527
  return copied;
14225
14528
  }
14226
14529
  function populatedHooksDirectory(mainRoot) {
14227
- const husky = path5.join(mainRoot, ".husky");
14530
+ const husky = path6.join(mainRoot, ".husky");
14228
14531
  try {
14229
- if (fs5.statSync(husky).isDirectory())
14532
+ if (fs6.statSync(husky).isDirectory())
14230
14533
  return husky;
14231
14534
  } catch {}
14232
- const hooks = path5.join(mainRoot, ".git", "hooks");
14535
+ const hooks = path6.join(mainRoot, ".git", "hooks");
14233
14536
  try {
14234
- const populated = fs5.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
14537
+ const populated = fs6.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
14235
14538
  return populated ? hooks : undefined;
14236
14539
  } catch {
14237
14540
  return;
@@ -14242,7 +14545,7 @@ function configureSharedHooksPath(mainRoot) {
14242
14545
  if (desired === undefined)
14243
14546
  return;
14244
14547
  const current = runGitPlain(mainRoot, ["config", "--get", "core.hooksPath"]);
14245
- if (current.status === 0 && path5.resolve(mainRoot, current.stdout.trim()) === desired)
14548
+ if (current.status === 0 && path6.resolve(mainRoot, current.stdout.trim()) === desired)
14246
14549
  return;
14247
14550
  const configured = runGitPlain(mainRoot, ["config", "core.hooksPath", desired]);
14248
14551
  if (configured.status !== 0) {
@@ -14251,10 +14554,10 @@ function configureSharedHooksPath(mainRoot) {
14251
14554
  }
14252
14555
  function normalizeSymlinkDirectory(value2) {
14253
14556
  const trimmed = value2.trim();
14254
- if (!trimmed || path5.isAbsolute(trimmed))
14557
+ if (!trimmed || path6.isAbsolute(trimmed))
14255
14558
  return;
14256
- const normalized = path5.normalize(trimmed);
14257
- if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path5.sep}`))
14559
+ const normalized = path6.normalize(trimmed);
14560
+ if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path6.sep}`))
14258
14561
  return;
14259
14562
  return normalized;
14260
14563
  }
@@ -14264,20 +14567,20 @@ function symlinkConfiguredDirectories(mainRoot, worktreeRoot, directories) {
14264
14567
  const relativePath = normalizeSymlinkDirectory(rawDirectory);
14265
14568
  if (relativePath === undefined || synthetic.includes(relativePath))
14266
14569
  continue;
14267
- const source = path5.join(mainRoot, relativePath);
14268
- const destination = path5.join(worktreeRoot, relativePath);
14269
- if (!fs5.existsSync(source) || fs5.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14570
+ const source = path6.join(mainRoot, relativePath);
14571
+ const destination = path6.join(worktreeRoot, relativePath);
14572
+ if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14270
14573
  continue;
14271
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
14574
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
14272
14575
  try {
14273
- fs5.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
14576
+ fs6.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
14274
14577
  synthetic.push(relativePath);
14275
14578
  } catch {}
14276
14579
  }
14277
14580
  return synthetic;
14278
14581
  }
14279
14582
  function copyWorktreeIncludes(mainRoot, worktreeRoot) {
14280
- if (!fs5.existsSync(path5.join(mainRoot, ".worktreeinclude")))
14583
+ if (!fs6.existsSync(path6.join(mainRoot, ".worktreeinclude")))
14281
14584
  return;
14282
14585
  const ignored = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-standard"]);
14283
14586
  const included = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-from=.worktreeinclude"]);
@@ -14287,13 +14590,13 @@ function copyWorktreeIncludes(mainRoot, worktreeRoot) {
14287
14590
  for (const relativePath of included.stdout.split(/\r?\n/).filter(Boolean)) {
14288
14591
  if (!ignoredPaths.has(relativePath) || hasTrackedPathComponent(worktreeRoot, relativePath))
14289
14592
  continue;
14290
- const source = path5.join(mainRoot, relativePath);
14291
- const destination = path5.join(worktreeRoot, relativePath);
14593
+ const source = path6.join(mainRoot, relativePath);
14594
+ const destination = path6.join(worktreeRoot, relativePath);
14292
14595
  try {
14293
- if (!fs5.statSync(source).isFile() || fs5.existsSync(destination))
14596
+ if (!fs6.statSync(source).isFile() || fs6.existsSync(destination))
14294
14597
  continue;
14295
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
14296
- fs5.copyFileSync(source, destination);
14598
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
14599
+ fs6.copyFileSync(source, destination);
14297
14600
  } catch {}
14298
14601
  }
14299
14602
  }
@@ -14310,9 +14613,9 @@ var init_worktree_post_create = __esm(() => {
14310
14613
 
14311
14614
  // dist/builtin/workflows/src/runs/shared/worktree-setup.ts
14312
14615
  import { spawnSync as spawnSync2 } from "node:child_process";
14313
- import * as fs6 from "node:fs";
14616
+ import * as fs7 from "node:fs";
14314
14617
  import * as os from "node:os";
14315
- import * as path6 from "node:path";
14618
+ import * as path7 from "node:path";
14316
14619
  import { createChildProcessEnvironment as createChildProcessEnvironment2 } from "@bastani/atomic";
14317
14620
  function originDefaultBranch(mainRoot) {
14318
14621
  const symbolic = runGit(mainRoot, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]);
@@ -14332,7 +14635,7 @@ function originDefaultBranch(mainRoot) {
14332
14635
  }
14333
14636
  function resolveRepoState(cwd, explicitBaseBranch) {
14334
14637
  const cwdRelative = resolveRepoCwdRelative(cwd);
14335
- const toplevel = path6.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
14638
+ const toplevel = path7.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
14336
14639
  const mainRoot = findCanonicalGitRoot(toplevel);
14337
14640
  if (mainRoot === undefined)
14338
14641
  throw new Error(`unable to resolve canonical main Git repository root from ${toplevel}`);
@@ -14345,9 +14648,9 @@ function resolveRepoState(cwd, explicitBaseBranch) {
14345
14648
  return { toplevel, mainRoot, cwdRelative, baseCommit, baseRef };
14346
14649
  }
14347
14650
  function normalizeComparableCwd(cwd) {
14348
- const resolved = path6.resolve(cwd);
14651
+ const resolved = path7.resolve(cwd);
14349
14652
  try {
14350
- return fs6.realpathSync(resolved);
14653
+ return fs7.realpathSync(resolved);
14351
14654
  } catch {
14352
14655
  return resolved;
14353
14656
  }
@@ -14358,7 +14661,7 @@ function findWorktreeTaskCwdConflict(tasks, sharedCwd) {
14358
14661
  const task = tasks[index];
14359
14662
  if (!task.cwd)
14360
14663
  continue;
14361
- const taskCwd = path6.isAbsolute(task.cwd) ? task.cwd : path6.resolve(sharedCwd, task.cwd);
14664
+ const taskCwd = path7.isAbsolute(task.cwd) ? task.cwd : path7.resolve(sharedCwd, task.cwd);
14362
14665
  if (normalizeComparableCwd(taskCwd) === normalizedSharedCwd)
14363
14666
  continue;
14364
14667
  return { index, agent: task.agent, cwd: task.cwd };
@@ -14375,12 +14678,12 @@ function buildWorktreeBranch(runId, index) {
14375
14678
  return `worktree-${flattenedWorktreeName(runId, index)}`;
14376
14679
  }
14377
14680
  function buildWorktreePath(mainRoot, runId, index) {
14378
- return path6.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
14681
+ return path7.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
14379
14682
  }
14380
14683
  function ensureWorktreeIgnore(mainRoot) {
14381
- const worktreesRoot = path6.join(mainRoot, ".atomic", "worktrees");
14382
- fs6.mkdirSync(worktreesRoot, { recursive: true });
14383
- fs6.writeFileSync(path6.join(worktreesRoot, ".gitignore"), `*
14684
+ const worktreesRoot = path7.join(mainRoot, ".atomic", "worktrees");
14685
+ fs7.mkdirSync(worktreesRoot, { recursive: true });
14686
+ fs7.writeFileSync(path7.join(worktreesRoot, ".gitignore"), `*
14384
14687
  `, "utf8");
14385
14688
  }
14386
14689
  function resolveRepoCwdRelative(cwd) {
@@ -14389,7 +14692,7 @@ function resolveRepoCwdRelative(cwd) {
14389
14692
  throw new Error("worktree isolation requires a git repository");
14390
14693
  }
14391
14694
  const rawPrefix = runGitChecked(cwd, ["rev-parse", "--show-prefix"]).trim();
14392
- const normalizedPrefix = rawPrefix ? path6.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
14695
+ const normalizedPrefix = rawPrefix ? path7.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
14393
14696
  return normalizedPrefix === "." ? "" : normalizedPrefix;
14394
14697
  }
14395
14698
  function parseHookTimeout(timeoutMs) {
@@ -14407,19 +14710,19 @@ function resolveWorktreeSetupHook(repoRoot, config) {
14407
14710
  if (!hookPath) {
14408
14711
  throw new Error("worktree setup hook path cannot be empty");
14409
14712
  }
14410
- const expandedHookPath = hookPath.startsWith("~/") ? path6.join(os.homedir(), hookPath.slice(2)) : hookPath;
14713
+ const expandedHookPath = hookPath.startsWith("~/") ? path7.join(os.homedir(), hookPath.slice(2)) : hookPath;
14411
14714
  let resolvedPath;
14412
- if (path6.isAbsolute(expandedHookPath)) {
14715
+ if (path7.isAbsolute(expandedHookPath)) {
14413
14716
  resolvedPath = expandedHookPath;
14414
14717
  } else if (expandedHookPath.includes("/") || expandedHookPath.includes("\\")) {
14415
- resolvedPath = path6.resolve(repoRoot, expandedHookPath);
14718
+ resolvedPath = path7.resolve(repoRoot, expandedHookPath);
14416
14719
  } else {
14417
14720
  throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
14418
14721
  }
14419
- if (!fs6.existsSync(resolvedPath)) {
14722
+ if (!fs7.existsSync(resolvedPath)) {
14420
14723
  throw new Error(`worktree setup hook not found: ${resolvedPath}`);
14421
14724
  }
14422
- if (fs6.statSync(resolvedPath).isDirectory()) {
14725
+ if (fs7.statSync(resolvedPath).isDirectory()) {
14423
14726
  throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
14424
14727
  }
14425
14728
  return {
@@ -14431,17 +14734,17 @@ function normalizeSyntheticPath(worktreePath, rawPath) {
14431
14734
  const trimmed = rawPath.trim();
14432
14735
  if (!trimmed)
14433
14736
  throw new Error("synthetic path cannot be empty");
14434
- if (path6.isAbsolute(trimmed))
14737
+ if (path7.isAbsolute(trimmed))
14435
14738
  throw new Error(`synthetic path must be relative: ${rawPath}`);
14436
- const resolved = path6.resolve(worktreePath, trimmed);
14437
- const relative = path6.relative(worktreePath, resolved);
14739
+ const resolved = path7.resolve(worktreePath, trimmed);
14740
+ const relative = path7.relative(worktreePath, resolved);
14438
14741
  if (!relative || relative === ".") {
14439
14742
  throw new Error(`synthetic path cannot target the worktree root: ${rawPath}`);
14440
14743
  }
14441
- if (relative === ".." || relative.startsWith(`..${path6.sep}`) || path6.isAbsolute(relative)) {
14744
+ if (relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative)) {
14442
14745
  throw new Error(`synthetic path escapes the worktree root: ${rawPath}`);
14443
14746
  }
14444
- return path6.normalize(relative);
14747
+ return path7.normalize(relative);
14445
14748
  }
14446
14749
  function hasTrackedEntries(worktreePath, relativePath) {
14447
14750
  const result = runGit(worktreePath, ["ls-files", "--", relativePath]);
@@ -14513,16 +14816,16 @@ function waitForGitLockRelease() {
14513
14816
  }
14514
14817
  function unlinkWorktreeLinks(worktreePath, relativePaths) {
14515
14818
  for (const relativePath of new Set(relativePaths)) {
14516
- const target = path6.resolve(worktreePath, relativePath);
14517
- const relative = path6.relative(worktreePath, target);
14518
- if (!relative || relative === ".." || relative.startsWith(`..${path6.sep}`) || path6.isAbsolute(relative))
14819
+ const target = path7.resolve(worktreePath, relativePath);
14820
+ const relative = path7.relative(worktreePath, target);
14821
+ if (!relative || relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative))
14519
14822
  continue;
14520
14823
  let current = worktreePath;
14521
- for (const component of relative.split(path6.sep)) {
14522
- current = path6.join(current, component);
14824
+ for (const component of relative.split(path7.sep)) {
14825
+ current = path7.join(current, component);
14523
14826
  let stat;
14524
14827
  try {
14525
- stat = fs6.lstatSync(current);
14828
+ stat = fs7.lstatSync(current);
14526
14829
  } catch (error) {
14527
14830
  const code = error.code;
14528
14831
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -14532,7 +14835,7 @@ function unlinkWorktreeLinks(worktreePath, relativePaths) {
14532
14835
  if (!stat.isSymbolicLink())
14533
14836
  continue;
14534
14837
  if (current === target)
14535
- fs6.unlinkSync(current);
14838
+ fs7.unlinkSync(current);
14536
14839
  break;
14537
14840
  }
14538
14841
  }
@@ -14560,7 +14863,7 @@ function createSingleWorktree(mainRoot, cwdRelative, runId, index, baseRef, base
14560
14863
  cleanupSingleWorktree(mainRoot, { path: worktreePath, branch }, []);
14561
14864
  throw new Error(message);
14562
14865
  }
14563
- const agentCwd = cwdRelative ? path6.join(worktreePath, cwdRelative) : worktreePath;
14866
+ const agentCwd = cwdRelative ? path7.join(worktreePath, cwdRelative) : worktreePath;
14564
14867
  const syntheticPaths = [];
14565
14868
  try {
14566
14869
  syntheticPaths.push(...performPostCreationSetup(mainRoot, worktreePath, symlinkDirectories));
@@ -14629,8 +14932,8 @@ var init_worktree = __esm(() => {
14629
14932
  });
14630
14933
 
14631
14934
  // dist/builtin/workflows/src/runs/shared/worktree-cwd.ts
14632
- import { lstatSync as lstatSync5, realpathSync as realpathSync4 } from "node:fs";
14633
- import { dirname as dirname8, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve6, sep as sep5 } from "node:path";
14935
+ import { lstatSync as lstatSync6, realpathSync as realpathSync4 } from "node:fs";
14936
+ import { dirname as dirname9, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve7, sep as sep5 } from "node:path";
14634
14937
  function relativePathWithin(root, candidate) {
14635
14938
  const path = relative4(root, candidate);
14636
14939
  return path === ".." || path.startsWith(`..${sep5}`) || isAbsolute6(path) ? undefined : path;
@@ -14649,14 +14952,14 @@ function resolveWorktreeStageCwd(cwd, setup) {
14649
14952
  if (cwd === undefined || cwd.length === 0)
14650
14953
  return;
14651
14954
  const absoluteInput = isAbsolute6(cwd);
14652
- const candidate = absoluteInput ? cwd : resolve6(setup.cwd, cwd);
14955
+ const candidate = absoluteInput ? cwd : resolve7(setup.cwd, cwd);
14653
14956
  if (!absoluteInput && relativePathWithin(setup.worktreeRoot, candidate) === undefined) {
14654
14957
  throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a cwd inside the worktree.`);
14655
14958
  }
14656
14959
  const candidateRealPath = existingRealPath(candidate, "cwd");
14657
14960
  const worktreeRelative = relativePathWithin(worktreeRoot, candidateRealPath);
14658
14961
  if (worktreeRelative !== undefined)
14659
- return resolve6(setup.worktreeRoot, worktreeRelative);
14962
+ return resolve7(setup.worktreeRoot, worktreeRelative);
14660
14963
  if (!isAbsolute6(cwd)) {
14661
14964
  throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a path that remains inside the selected worktree.`);
14662
14965
  }
@@ -14665,9 +14968,9 @@ function resolveWorktreeStageCwd(cwd, setup) {
14665
14968
  }
14666
14969
  const repositoryRelative = absoluteInput ? relativePathWithin(repositoryRoot, candidateRealPath) : undefined;
14667
14970
  if (repositoryRelative === undefined) {
14668
- throw new Error(`atomic-workflows: cwd ${cwd} is outside gitWorktreeDir ${setup.worktreeRoot}; use a cwd inside the invoking repository so Atomic can remap it, or omit cwd.`);
14971
+ throw new Error(repositoryRoot === worktreeRoot ? `atomic-workflows: cwd ${cwd} is outside gitWorktreeDir ${setup.worktreeRoot}, which belongs to a different repository than the invoking cwd; choose a cwd inside the worktree, or omit cwd.` : `atomic-workflows: cwd ${cwd} is outside gitWorktreeDir ${setup.worktreeRoot}; use a cwd inside the invoking repository so Atomic can remap it, or omit cwd.`);
14669
14972
  }
14670
- const mappedCwd = resolve6(setup.worktreeRoot, repositoryRelative);
14973
+ const mappedCwd = resolve7(setup.worktreeRoot, repositoryRelative);
14671
14974
  const mappedRealPath = existingRealPath(mappedCwd, "remapped worktree cwd");
14672
14975
  if (relativePathWithin(worktreeRoot, mappedRealPath) === undefined) {
14673
14976
  throw new Error(`atomic-workflows: cwd ${cwd} remaps through a path that resolves outside gitWorktreeDir ${setup.worktreeRoot}; remove the escaping symlink or omit cwd.`);
@@ -14678,7 +14981,7 @@ var init_worktree_cwd = () => {};
14678
14981
 
14679
14982
  // dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts
14680
14983
  import { existsSync as existsSync3 } from "node:fs";
14681
- import { isAbsolute as isAbsolute7, resolve as resolve7 } from "node:path";
14984
+ import { isAbsolute as isAbsolute7, resolve as resolve8 } from "node:path";
14682
14985
  function normalizeTaskContexts(previous) {
14683
14986
  if (previous === undefined)
14684
14987
  return [];
@@ -14731,7 +15034,7 @@ function taskPrevious(options) {
14731
15034
  function resolveWorkflowPath(filePath, baseDir) {
14732
15035
  if (isAbsolute7(filePath))
14733
15036
  return filePath;
14734
- return resolve7(baseDir ?? process.cwd(), filePath);
15037
+ return resolve8(baseDir ?? process.cwd(), filePath);
14735
15038
  }
14736
15039
  function taskBaseDir(options) {
14737
15040
  if (typeof options.chainDir === "string" && options.chainDir.trim().length > 0) {
@@ -14886,7 +15189,7 @@ function taskWithSharedDefaults(taskOptions, options) {
14886
15189
  var init_executor_task_prompts = () => {};
14887
15190
 
14888
15191
  // dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts
14889
- import { isAbsolute as isAbsolute8, join as join11, resolve as resolve8 } from "node:path";
15192
+ import { isAbsolute as isAbsolute8, join as join12, resolve as resolve9 } from "node:path";
14890
15193
  import { CONFIG_DIR_NAME } from "@bastani/atomic";
14891
15194
  function positiveConcurrency(value2) {
14892
15195
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 < 1)
@@ -15039,10 +15342,10 @@ function workflowInvocationMetadata(inputDefaults, workflowInvocationCwd, cache,
15039
15342
  function resolvedTaskCwd(cwd, workflowInvocationCwd) {
15040
15343
  if (cwd === undefined)
15041
15344
  return;
15042
- return isAbsolute8(cwd) ? cwd : resolve8(workflowInvocationCwd, cwd);
15345
+ return isAbsolute8(cwd) ? cwd : resolve9(workflowInvocationCwd, cwd);
15043
15346
  }
15044
15347
  function taskWorktreeOutputsRoot(runId) {
15045
- return join11(workflowArtifactRunPath(runId), "task-outputs");
15348
+ return join12(workflowArtifactRunPath(runId), "task-outputs");
15046
15349
  }
15047
15350
  function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCwd = process.cwd(), symlinkDirectories) {
15048
15351
  if (options.worktree !== true && !tasks.some((task) => task.worktree === true)) {
@@ -15052,7 +15355,7 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
15052
15355
  throw new Error("atomic-workflows: worktree and gitWorktreeDir are mutually exclusive; use gitWorktreeDir for a reusable worktree or worktree:true for temporary isolated worktrees.");
15053
15356
  }
15054
15357
  const explicitCwd = tasks.find((task) => typeof task.cwd === "string")?.cwd;
15055
- const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve8(workflowInvocationCwd, explicitCwd);
15358
+ const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve9(workflowInvocationCwd, explicitCwd);
15056
15359
  const conflict = findWorktreeTaskCwdConflict(tasks.map((task) => ({ agent: task.name, cwd: resolvedTaskCwd(task.cwd, workflowInvocationCwd) })), sharedCwd);
15057
15360
  if (conflict !== undefined)
15058
15361
  throw new Error(formatWorktreeTaskCwdConflict(conflict, sharedCwd));
@@ -15067,9 +15370,9 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
15067
15370
  tasks: tasks.map((task, index) => ({ ...task, cwd: setup.worktrees[index].agentCwd })),
15068
15371
  setup,
15069
15372
  agents,
15070
- diffsDir: join11(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
15373
+ diffsDir: join12(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
15071
15374
  outputIsolations: tasks.map((_, index) => ({
15072
- baseDir: join11(trustedRoot, runId, scope, String(index)),
15375
+ baseDir: join12(trustedRoot, runId, scope, String(index)),
15073
15376
  trustedRoot
15074
15377
  }))
15075
15378
  };
@@ -16796,8 +17099,12 @@ function createStageControlRegistry() {
16796
17099
  }
16797
17100
  await disposeEntries(entries);
16798
17101
  },
16799
- async releaseIdle(runId) {
16800
- for (const [stageId, entry] of [..._byRun.get(runId) ?? []]) {
17102
+ async releaseIdle(runId, only) {
17103
+ const runMap = _byRun.get(runId);
17104
+ const entries = only === undefined ? [...runMap ?? []] : [[only, runMap?.get(only)]];
17105
+ for (const [stageId, entry] of entries) {
17106
+ if (entry === undefined)
17107
+ continue;
16801
17108
  try {
16802
17109
  await releaseIdleEntry(runId, stageId, entry);
16803
17110
  } catch (error) {
@@ -16858,8 +17165,8 @@ var init_possible_stages = __esm(() => {
16858
17165
 
16859
17166
  // dist/builtin/workflows/src/workers/pool-journal.ts
16860
17167
  import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
16861
- import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
16862
- import { basename as basename5, dirname as dirname9, join as join12, resolve as resolve9 } from "node:path";
17168
+ import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
17169
+ import { basename as basename5, dirname as dirname10, join as join13, resolve as resolve10 } from "node:path";
16863
17170
  import { storageSelectionKey as storageSelectionKey2 } from "@bastani/atomic/storage";
16864
17171
  function encodeOption(value2) {
16865
17172
  if (typeof value2 === "bigint")
@@ -16881,7 +17188,7 @@ function isReopenableSelection(selection) {
16881
17188
  }
16882
17189
  function encodeSelection(selection) {
16883
17190
  if (selection.kind === "sqlite")
16884
- return JSON.stringify({ ...selection, path: resolve9(selection.path) });
17191
+ return JSON.stringify({ ...selection, path: resolve10(selection.path) });
16885
17192
  return JSON.stringify({
16886
17193
  ...selection,
16887
17194
  ...selection.options === undefined ? {} : {
@@ -16913,7 +17220,7 @@ function openDurableJournal(durable) {
16913
17220
  return openSelectedRunJournal(decodeSelection(durable.selection), durable.agentDir);
16914
17221
  }
16915
17222
  function poolStateDirectory(agentDir) {
16916
- return join12(dirname9(agentDir), "workflows", "pool");
17223
+ return join13(dirname10(agentDir), "workflows", "pool");
16917
17224
  }
16918
17225
  function databaseIdentity(selection, agentDir) {
16919
17226
  return storageSelectionKey2(selection.kind === "adapter" ? { ...selection, secrets: undefined } : selection, agentDir);
@@ -16921,16 +17228,16 @@ function databaseIdentity(selection, agentDir) {
16921
17228
  function coordinationPath(durable) {
16922
17229
  const selection = decodeSelection(durable.selection);
16923
17230
  const identity = createHash3("sha256").update(databaseIdentity(selection, durable.agentDir)).digest("hex");
16924
- return join12(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
17231
+ return join13(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
16925
17232
  }
16926
17233
  function coordinationDatabase(durable) {
16927
17234
  return basename5(coordinationPath(durable), ".sqlite");
16928
17235
  }
16929
17236
  function openCoordinationJournal(path) {
16930
- const file = resolve9(path);
17237
+ const file = resolve10(path);
16931
17238
  let opened = coordinationJournals.get(file);
16932
17239
  if (opened === undefined) {
16933
- mkdirSync5(dirname9(file), { recursive: true });
17240
+ mkdirSync6(dirname10(file), { recursive: true });
16934
17241
  opened = resolveRunJournal({ journal: { path: file } });
16935
17242
  coordinationJournals.set(file, opened);
16936
17243
  opened.catch(() => {
@@ -16947,20 +17254,20 @@ function poolJournalFor(journal) {
16947
17254
  return coordinations.get(journal) ?? journal;
16948
17255
  }
16949
17256
  function poolHostId(agentDir) {
16950
- const file = join12(poolStateDirectory(agentDir), "host-id");
17257
+ const file = join13(poolStateDirectory(agentDir), "host-id");
16951
17258
  try {
16952
- const existing = readFileSync2(file, "utf8").trim();
17259
+ const existing = readFileSync4(file, "utf8").trim();
16953
17260
  if (existing !== "")
16954
17261
  return existing;
16955
17262
  } catch {}
16956
- mkdirSync5(dirname9(file), { recursive: true });
17263
+ mkdirSync6(dirname10(file), { recursive: true });
16957
17264
  const id = randomUUID6();
16958
17265
  try {
16959
- writeFileSync3(file, `${id}
17266
+ writeFileSync4(file, `${id}
16960
17267
  `, { flag: "wx" });
16961
17268
  return id;
16962
17269
  } catch {
16963
- return readFileSync2(file, "utf8").trim();
17270
+ return readFileSync4(file, "utf8").trim();
16964
17271
  }
16965
17272
  }
16966
17273
  var POOL_DURABLE_JOURNAL_ENV = "ATOMIC_POOL_DURABLE_JOURNAL", coordinationJournals, coordinations;
@@ -16975,7 +17282,7 @@ var init_pool_journal = __esm(() => {
16975
17282
 
16976
17283
  // dist/builtin/workflows/src/workers/admission-host.ts
16977
17284
  import { execFile, execFileSync } from "node:child_process";
16978
- import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
17285
+ import { readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
16979
17286
  import { readFile } from "node:fs/promises";
16980
17287
  import { hostname } from "node:os";
16981
17288
  function admissionBootIdentity() {
@@ -17006,7 +17313,7 @@ function workerProcessExited(pid, final = false) {
17006
17313
  return true;
17007
17314
  if (process.platform === "linux") {
17008
17315
  try {
17009
- const stat = readFileSync3(`/proc/${pid}/stat`, "utf8");
17316
+ const stat = readFileSync5(`/proc/${pid}/stat`, "utf8");
17010
17317
  return stat.slice(stat.lastIndexOf(")") + 2).startsWith("Z");
17011
17318
  } catch {
17012
17319
  return admissionProcessStopped(pid);
@@ -17026,7 +17333,7 @@ function scanProcessGroup(group) {
17026
17333
  let complete = true;
17027
17334
  let entries;
17028
17335
  try {
17029
- entries = readdirSync2("/proc");
17336
+ entries = readdirSync4("/proc");
17030
17337
  } catch {
17031
17338
  return { members, complete: false };
17032
17339
  }
@@ -17035,7 +17342,7 @@ function scanProcessGroup(group) {
17035
17342
  continue;
17036
17343
  let stat;
17037
17344
  try {
17038
- stat = readFileSync3(`/proc/${entry}/stat`, "utf8");
17345
+ stat = readFileSync5(`/proc/${entry}/stat`, "utf8");
17039
17346
  } catch {
17040
17347
  complete = false;
17041
17348
  continue;
@@ -53774,10 +54081,10 @@ var init_verification_prompts = __esm(() => {
53774
54081
  // dist/builtin/workflows/builtin/pattern-artifact-root.ts
53775
54082
  import { randomUUID as randomUUID9 } from "node:crypto";
53776
54083
  import { mkdir as mkdir2 } from "node:fs/promises";
53777
- import { join as join13 } from "node:path";
54084
+ import { join as join14 } from "node:path";
53778
54085
  async function stableArtifactRoot(ctx, workflowName) {
53779
54086
  const cwd = ctx.cwd ?? process.cwd();
53780
- const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join13(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
54087
+ const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join14(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
53781
54088
  await mkdir2(artifactDir, { recursive: true });
53782
54089
  return artifactDir;
53783
54090
  }
@@ -53817,7 +54124,7 @@ function fold_usage(results) {
53817
54124
 
53818
54125
  // dist/builtin/workflows/builtin/adversarial-verification-runner.ts
53819
54126
  import { readFile as readFile2, writeFile } from "node:fs/promises";
53820
- import { join as join14 } from "node:path";
54127
+ import { join as join15 } from "node:path";
53821
54128
  import { Type as Type4 } from "typebox";
53822
54129
  function isRecord3(value2) {
53823
54130
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -53912,8 +54219,8 @@ async function writeInvalid(path, stage) {
53912
54219
  }
53913
54220
  async function runAdversarialVerification(ctx) {
53914
54221
  const root = await stableArtifactRoot(ctx, "adversarial-verification");
53915
- const criteriaPath = join14(root, "criteria.md");
53916
- const candidatePath = join14(root, "candidate.md");
54222
+ const criteriaPath = join15(root, "criteria.md");
54223
+ const candidatePath = join15(root, "candidate.md");
53917
54224
  const resolvedCriteria = resolveCriteria(ctx.inputs.criteria);
53918
54225
  await writeFile(criteriaPath, renderCriteriaMarkdown(resolvedCriteria));
53919
54226
  await ctx.task("worker", { prompt: renderWorkerPrompt(ctx.inputs.task), context: "fresh", output: candidatePath, outputMode: "file-only" });
@@ -53945,7 +54252,7 @@ async function runAdversarialVerification(ctx) {
53945
54252
  criterion,
53946
54253
  verifierIndex: index + 1,
53947
54254
  name,
53948
- artifactPath: join14(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
54255
+ artifactPath: join15(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
53949
54256
  });
53950
54257
  }
53951
54258
  }
@@ -53998,8 +54305,8 @@ async function runAdversarialVerification(ctx) {
53998
54305
  const decision = decide_verification(roundResult, { acceptMean, quorumFraction: QUORUM_FRACTION });
53999
54306
  finalDecision = decision;
54000
54307
  finalMean = meanScore(scoreReports);
54001
- scoreTablePath = join14(root, `verification-summary-${round}.json`);
54002
- reviewReportPath = join14(root, `review-${round}.json`);
54308
+ scoreTablePath = join15(root, `verification-summary-${round}.json`);
54309
+ reviewReportPath = join15(root, `review-${round}.json`);
54003
54310
  const summary = {
54004
54311
  scores: scoreReports,
54005
54312
  mean: finalMean,
@@ -54180,7 +54487,7 @@ var GROUNDED_REPORTING2 = "Before reporting progress, audit each claim against a
54180
54487
 
54181
54488
  // dist/builtin/workflows/builtin/classify-and-act-runner.ts
54182
54489
  import { writeFile as writeFile2 } from "node:fs/promises";
54183
- import { join as join15 } from "node:path";
54490
+ import { join as join16 } from "node:path";
54184
54491
  import { Type as Type6 } from "typebox";
54185
54492
  function safeName(value2) {
54186
54493
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -54220,7 +54527,7 @@ async function runClassifyAndAct(ctx) {
54220
54527
  const needsFallback = exactCategory === undefined || confidence < ctx.inputs.confidence_threshold;
54221
54528
  const fallback = needsFallback ? await resolveFallbackCategory(ctx, exactCategory) : undefined;
54222
54529
  const category = fallback?.category ?? exactCategory;
54223
- const classificationPath = join15(artifactDir, "classification.json");
54530
+ const classificationPath = join16(artifactDir, "classification.json");
54224
54531
  await writeFile2(classificationPath, JSON.stringify({
54225
54532
  proposed_category: proposedCategory,
54226
54533
  selected_category: category,
@@ -54230,7 +54537,7 @@ async function runClassifyAndAct(ctx) {
54230
54537
  fallback_used: needsFallback,
54231
54538
  fallback_mode: fallback?.fallbackMode ?? "none"
54232
54539
  }, null, 2));
54233
- const actionPath = join15(artifactDir, `action-${safeName(category)}.md`);
54540
+ const actionPath = join16(artifactDir, `action-${safeName(category)}.md`);
54234
54541
  const action = await ctx.task(`action-${safeName(category)}`, {
54235
54542
  tools: actionTools(category),
54236
54543
  prompt: actionPrompt({ prompt: ctx.inputs.prompt, category, classificationPath }),
@@ -54370,7 +54677,7 @@ var GROUNDED_REPORTING3 = "Before reporting progress, audit each claim against a
54370
54677
 
54371
54678
  // dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts
54372
54679
  import { writeFile as writeFile3 } from "node:fs/promises";
54373
- import { join as join16 } from "node:path";
54680
+ import { join as join17 } from "node:path";
54374
54681
  import { Type as Type8 } from "typebox";
54375
54682
  function safeName2(value2, index) {
54376
54683
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -54401,9 +54708,9 @@ async function runFanOutAndSynthesize(ctx) {
54401
54708
  context: "fresh"
54402
54709
  });
54403
54710
  const partitions = parsedPartitions(plan.structured, ctx.inputs.max_branches, ctx.inputs.prompt);
54404
- const partitionPath = join16(artifactDir, "partition-plan.json");
54711
+ const partitionPath = join17(artifactDir, "partition-plan.json");
54405
54712
  await writeFile3(partitionPath, JSON.stringify({ task: ctx.inputs.prompt, partitions }, null, 2));
54406
- const branchPaths = partitions.map((partition, index) => join16(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
54713
+ const branchPaths = partitions.map((partition, index) => join17(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
54407
54714
  const steps = partitions.map((partition, index) => ({
54408
54715
  name: `branch-${safeName2(partition.label, index)}`,
54409
54716
  prompt: branchPrompt({ prompt: ctx.inputs.prompt, ...partition }),
@@ -54413,13 +54720,13 @@ async function runFanOutAndSynthesize(ctx) {
54413
54720
  outputMode: "file-only"
54414
54721
  }));
54415
54722
  await ctx.parallel(steps, { concurrency: Math.min(ctx.inputs.max_concurrency, partitions.length), failFast: false });
54416
- const manifestPath = join16(artifactDir, "manifest.json");
54723
+ const manifestPath = join17(artifactDir, "manifest.json");
54417
54724
  await writeFile3(manifestPath, JSON.stringify({
54418
54725
  task: ctx.inputs.prompt,
54419
54726
  partition_plan: partitionPath,
54420
54727
  branches: partitions.map((partition, index) => ({ ...partition, artifact_path: branchPaths[index] }))
54421
54728
  }, null, 2));
54422
- const synthesisPath = join16(artifactDir, "synthesis.md");
54729
+ const synthesisPath = join17(artifactDir, "synthesis.md");
54423
54730
  const synthesis = await ctx.task("synthesize", {
54424
54731
  prompt: synthesisPrompt(ctx.inputs.prompt, manifestPath),
54425
54732
  context: "fresh",
@@ -54584,7 +54891,7 @@ var init_generate_and_filter_prompts = __esm(() => {
54584
54891
 
54585
54892
  // dist/builtin/workflows/builtin/generate-and-filter-runner.ts
54586
54893
  import { readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
54587
- import { join as join17 } from "node:path";
54894
+ import { join as join18 } from "node:path";
54588
54895
  import { Type as Type10 } from "typebox";
54589
54896
  function isRecord4(value2) {
54590
54897
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -54603,7 +54910,7 @@ function judgeDecision(value2) {
54603
54910
  }
54604
54911
  async function runGenerateAndFilter(ctx) {
54605
54912
  const root = await stableArtifactRoot(ctx, "generate-and-filter");
54606
- const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join17(root, `candidate-${index + 1}.md`));
54913
+ const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join18(root, `candidate-${index + 1}.md`));
54607
54914
  const shortlistLimit = Math.min(ctx.inputs.shortlist_size, ctx.inputs.num_candidates);
54608
54915
  await ctx.parallel(candidatePaths.map((path, index) => ({
54609
54916
  name: `generate-${index + 1}`,
@@ -54612,9 +54919,9 @@ async function runGenerateAndFilter(ctx) {
54612
54919
  output: path,
54613
54920
  outputMode: "file-only"
54614
54921
  })), { concurrency: ctx.inputs.max_concurrency, failFast: false });
54615
- const manifestPath = join17(root, "manifest.json");
54922
+ const manifestPath = join18(root, "manifest.json");
54616
54923
  await writeFile4(manifestPath, JSON.stringify({ task: ctx.inputs.prompt, candidate_artifact_paths: candidatePaths }, null, 2));
54617
- const filterPath = join17(root, "filter.json");
54924
+ const filterPath = join18(root, "filter.json");
54618
54925
  const filtered = await ctx.task("dedupe-and-filter", {
54619
54926
  prompt: renderFilterPrompt(ctx.inputs.prompt, candidatePaths, shortlistLimit),
54620
54927
  context: "fresh",
@@ -54631,7 +54938,7 @@ async function runGenerateAndFilter(ctx) {
54631
54938
  let judgePath = null;
54632
54939
  let decisionPath = filterPath;
54633
54940
  if (ctx.inputs.use_judge) {
54634
- judgePath = join17(root, "judge.json");
54941
+ judgePath = join18(root, "judge.json");
54635
54942
  const judgeCandidates = await Promise.all(shortlist.map(async (path) => ({ path, body: await readFile3(path, "utf8") })));
54636
54943
  const judgePrompt = renderJudgePrompt(ctx.inputs.prompt, filterPath, shortlistLimit, judgeCandidates);
54637
54944
  const judged = await ctx.task("judge", {
@@ -54647,7 +54954,7 @@ async function runGenerateAndFilter(ctx) {
54647
54954
  shortlist = judgedShortlist.length > 0 ? judgedShortlist : shortlist;
54648
54955
  decisionPath = judgePath;
54649
54956
  }
54650
- const finalPath = join17(root, "shortlist.md");
54957
+ const finalPath = join18(root, "shortlist.md");
54651
54958
  const finalShortlist = await ctx.task("final-shortlist", {
54652
54959
  prompt: renderFinalShortlistPrompt(ctx.inputs.prompt, decisionPath),
54653
54960
  context: "fresh",
@@ -55176,7 +55483,7 @@ var init_review_convergence = __esm(() => {
55176
55483
 
55177
55484
  // dist/builtin/workflows/builtin/goal-artifacts.ts
55178
55485
  import { writeFile as writeFile5 } from "node:fs/promises";
55179
- import { join as join18 } from "node:path";
55486
+ import { join as join19 } from "node:path";
55180
55487
  function artifactSafeName(value2) {
55181
55488
  const safe = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
55182
55489
  return safe.length > 0 ? safe : "artifact";
@@ -55187,7 +55494,7 @@ function withoutTurn(value2) {
55187
55494
  return copy;
55188
55495
  }
55189
55496
  async function writeReviewArtifact(artifactDir, reviewer, decision, rawText, convergenceDecision) {
55190
- const artifactPath = join18(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
55497
+ const artifactPath = join19(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
55191
55498
  await writeFile5(artifactPath, `${JSON.stringify({ reviewer, decision, convergence_decision: convergenceDecision, raw_text: rawText }, null, 2)}
55192
55499
  `, { encoding: "utf8" });
55193
55500
  return artifactPath;
@@ -55196,7 +55503,7 @@ async function writeReviewRoundArtifact(artifactDir, reviews, consolidatedFindin
55196
55503
  reviewer: review.reviewer,
55197
55504
  findings: review.findings
55198
55505
  }))), reverification = []) {
55199
- const artifactPath = join18(artifactDir, "review-round-latest.json");
55506
+ const artifactPath = join19(artifactDir, "review-round-latest.json");
55200
55507
  const visibleReviews = reviews.map(withoutTurn);
55201
55508
  await writeFile5(artifactPath, `${JSON.stringify({ reviews: visibleReviews, consolidated_findings: consolidatedFindings, reverification }, null, 2)}
55202
55509
  `, { encoding: "utf8" });
@@ -55426,7 +55733,7 @@ var init_goal_review = __esm(() => {
55426
55733
  // dist/builtin/workflows/builtin/goal-ledger.ts
55427
55734
  import { randomUUID as randomUUID10 } from "node:crypto";
55428
55735
  import { readFile as readFile4, rename, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
55429
- import { dirname as dirname10, join as join19 } from "node:path";
55736
+ import { dirname as dirname11, join as join20 } from "node:path";
55430
55737
  import { isDeepStrictEqual } from "node:util";
55431
55738
  function withoutTurn2(value2) {
55432
55739
  const copy = { ...value2 };
@@ -55451,7 +55758,7 @@ function modelVisibleLedger(ledger) {
55451
55758
  };
55452
55759
  }
55453
55760
  function goalLedgerStatePath(ledgerPath) {
55454
- return join19(dirname10(ledgerPath), LEDGER_STATE_FILENAME);
55761
+ return join20(dirname11(ledgerPath), LEDGER_STATE_FILENAME);
55455
55762
  }
55456
55763
  function appendLifecycleEvent(ledger, event, summary, turn = ledger.turns) {
55457
55764
  ledger.lifecycle.push({
@@ -55527,7 +55834,7 @@ function recoverLegacyExecutionInterruption(ledger) {
55527
55834
  return true;
55528
55835
  }
55529
55836
  async function createGoalLedger(objective, acceptanceCriteria, artifactDir) {
55530
- const ledgerPath = join19(artifactDir, LEDGER_FILENAME);
55837
+ const ledgerPath = join20(artifactDir, LEDGER_FILENAME);
55531
55838
  const existing = await readExistingGoalLedger(ledgerPath);
55532
55839
  if (existing !== undefined) {
55533
55840
  if (recoverLegacyExecutionInterruption(existing))
@@ -56034,7 +56341,7 @@ var init_goal_orchestrator_prompts = __esm(() => {
56034
56341
  });
56035
56342
 
56036
56343
  // dist/builtin/workflows/builtin/goal-runner.ts
56037
- import { join as join20 } from "node:path";
56344
+ import { join as join21 } from "node:path";
56038
56345
  function positiveInteger(value2, fallback) {
56039
56346
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 <= 0) {
56040
56347
  return fallback;
@@ -56085,7 +56392,7 @@ async function runGoalWorkflow(ctx, options) {
56085
56392
  appendLifecycleEvent(ledger, "work_turn_started", "Orchestrator started.", turn);
56086
56393
  await writeGoalLedger(ledgerPath, ledger);
56087
56394
  }
56088
- const orchestratorReceiptPath = join20(artifactDir, "orchestrator-receipt.md");
56395
+ const orchestratorReceiptPath = join21(artifactDir, "orchestrator-receipt.md");
56089
56396
  const orchestratorForkOptions = forkContinuationOptions(previousOrchestratorSessionId);
56090
56397
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? renderGoalOrchestratorPrompt({
56091
56398
  ledger,
@@ -56156,7 +56463,7 @@ async function runGoalWorkflow(ctx, options) {
56156
56463
  const reviewerName = result.name ?? result.stageName;
56157
56464
  const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
56158
56465
  const parsed = reviewerContractError === undefined ? parsedReviewDecisionFromResult(result, reviewerName) : { decision: reviewerErrorDecision(reviewerContractError.message), parsed: false, diagnostics: [reviewerContractError.message] };
56159
- const reviewArtifactPath = join20(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
56466
+ const reviewArtifactPath = join21(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
56160
56467
  const record = reviewDecisionToRecord({
56161
56468
  turn,
56162
56469
  reviewer: normalizedReviewerName,
@@ -56359,7 +56666,7 @@ var init_goal = __esm(() => {
56359
56666
  }),
56360
56667
  git_worktree_dir: Type15.String({
56361
56668
  default: "",
56362
- description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Must start inside a Git repo; absolute paths are used as-is, relative paths resolve from the repo root, existing Git worktrees from the invoking repository are reused/shared as-is, and missing paths are created from base_branch."
56669
+ description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Absolute paths are used as-is; relative paths resolve from the invoking repo root (or the invoking cwd outside a Git repo). An existing Git worktree root of any repository is reused as-is, even from another repository or a non-Git cwd. Creating a worktree requires starting inside the source Git repo: a missing path or an empty directory becomes a new worktree from base_branch, and a non-empty non-Git directory is treated as a worktree root that gets this run's own <dir>/<4-hex>/<repo-name> checkout, reused on resume."
56363
56670
  }),
56364
56671
  create_pr: Type15.Boolean({
56365
56672
  default: false,
@@ -56477,7 +56784,7 @@ var GROUNDED_REPORTING5 = "Before reporting progress, audit each claim against a
56477
56784
 
56478
56785
  // dist/builtin/workflows/builtin/loop-until-done-runner.ts
56479
56786
  import { mkdir as mkdir3, writeFile as writeFile7 } from "node:fs/promises";
56480
- import { join as join21 } from "node:path";
56787
+ import { join as join22 } from "node:path";
56481
56788
  import { Type as Type16 } from "typebox";
56482
56789
  function progressCurve(entries) {
56483
56790
  return entries.flatMap((entry) => entry.progress === undefined ? [] : [entry.progress.score]);
@@ -56560,18 +56867,18 @@ async function writeLedger(path, task, maxIterations, status, entries) {
56560
56867
  }
56561
56868
  async function runLoopUntilDone(ctx) {
56562
56869
  const artifactDir = await stableArtifactRoot(ctx, "loop-until-done");
56563
- const iterationsDir = join21(artifactDir, "iterations");
56564
- const evaluationsDir = join21(artifactDir, "evaluations");
56870
+ const iterationsDir = join22(artifactDir, "iterations");
56871
+ const evaluationsDir = join22(artifactDir, "evaluations");
56565
56872
  await mkdir3(iterationsDir, { recursive: true });
56566
56873
  await mkdir3(evaluationsDir, { recursive: true });
56567
- const ledgerPath = join21(artifactDir, "progress-ledger.json");
56874
+ const ledgerPath = join22(artifactDir, "progress-ledger.json");
56568
56875
  const entries = [];
56569
56876
  const iterationArtifactPaths = [];
56570
56877
  const evaluationArtifactPaths = [];
56571
56878
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, "active", entries);
56572
56879
  for (let iteration = 1;iteration <= ctx.inputs.max_iterations; iteration += 1) {
56573
- const iterationPath = join21(iterationsDir, `iteration-${iteration}.md`);
56574
- const evaluationPath = join21(evaluationsDir, `evaluation-${iteration}.json`);
56880
+ const iterationPath = join22(iterationsDir, `iteration-${iteration}.md`);
56881
+ const evaluationPath = join22(evaluationsDir, `evaluation-${iteration}.json`);
56575
56882
  iterationArtifactPaths.push(iterationPath);
56576
56883
  evaluationArtifactPaths.push(evaluationPath);
56577
56884
  await ctx.task(`iteration-${iteration}`, {
@@ -56620,7 +56927,7 @@ async function runLoopUntilDone(ctx) {
56620
56927
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, decision.done ? "complete" : "active", entries);
56621
56928
  if (decision.done) {
56622
56929
  const report = progressReport(entries);
56623
- const resultPath = join21(artifactDir, "result.md");
56930
+ const resultPath = join22(artifactDir, "result.md");
56624
56931
  const final = await ctx.task("completion-summary", {
56625
56932
  prompt: renderCompletionPrompt({ task: ctx.inputs.prompt, ledgerPath, iterationPath }),
56626
56933
  context: "fresh",
@@ -56737,9 +57044,9 @@ var init_loop_until_done = __esm(() => {
56737
57044
 
56738
57045
  // dist/builtin/workflows/builtin/open-claude-design-utils.ts
56739
57046
  import { spawnSync as spawnSync3 } from "node:child_process";
56740
- import { mkdirSync as mkdirSync6 } from "node:fs";
57047
+ import { mkdirSync as mkdirSync7 } from "node:fs";
56741
57048
  import { tmpdir, userInfo } from "node:os";
56742
- import { join as join22 } from "node:path";
57049
+ import { join as join23 } from "node:path";
56743
57050
  import { Type as Type18 } from "typebox";
56744
57051
  import { createChildProcessEnvironment as createChildProcessEnvironment3 } from "@bastani/atomic";
56745
57052
  function taggedPrompt3(sections) {
@@ -56782,32 +57089,32 @@ function tmpArtifactBase() {
56782
57089
  try {
56783
57090
  user = userInfo().username.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
56784
57091
  } catch {}
56785
- return join22(tmpdir(), `open-claude-design-${user}`);
57092
+ return join23(tmpdir(), `open-claude-design-${user}`);
56786
57093
  }
56787
57094
  function prepareArtifactDir(cwd = process.cwd()) {
56788
57095
  const runId = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
56789
57096
  const tmpCandidates = [
56790
- join22(tmpArtifactBase(), runId),
56791
- join22(tmpdir(), "open-claude-design", runId)
57097
+ join23(tmpArtifactBase(), runId),
57098
+ join23(tmpdir(), "open-claude-design", runId)
56792
57099
  ];
56793
- const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join22(cwd, "specs", "design", runId), ...tmpCandidates];
57100
+ const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join23(cwd, "specs", "design", runId), ...tmpCandidates];
56794
57101
  for (const candidate of candidates) {
56795
57102
  try {
56796
- mkdirSync6(candidate, { recursive: true });
57103
+ mkdirSync7(candidate, { recursive: true });
56797
57104
  return {
56798
57105
  runId,
56799
57106
  artifactDir: candidate,
56800
- previewPath: join22(candidate, "preview.html"),
56801
- specPath: join22(candidate, "spec.html")
57107
+ previewPath: join23(candidate, "preview.html"),
57108
+ specPath: join23(candidate, "spec.html")
56802
57109
  };
56803
57110
  } catch {}
56804
57111
  }
56805
- const fallback = join22(tmpArtifactBase(), runId);
57112
+ const fallback = join23(tmpArtifactBase(), runId);
56806
57113
  return {
56807
57114
  runId,
56808
57115
  artifactDir: fallback,
56809
- previewPath: join22(fallback, "preview.html"),
56810
- specPath: join22(fallback, "spec.html")
57116
+ previewPath: join23(fallback, "preview.html"),
57117
+ specPath: join23(fallback, "spec.html")
56811
57118
  };
56812
57119
  }
56813
57120
  function ensureAgentBrowser() {
@@ -57141,8 +57448,8 @@ var init_open_claude_design_live_protocol = __esm(() => {
57141
57448
  });
57142
57449
 
57143
57450
  // dist/builtin/workflows/builtin/open-claude-design-setup.ts
57144
- import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "node:fs";
57145
- import { join as join23 } from "node:path";
57451
+ import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync5 } from "node:fs";
57452
+ import { join as join24 } from "node:path";
57146
57453
  function renderDiscoveryContext(discovery) {
57147
57454
  return [
57148
57455
  `Confirmed design brief: ${discovery.brief}`,
@@ -57207,10 +57514,10 @@ async function runDiscoveryAndInit(args) {
57207
57514
  };
57208
57515
  }
57209
57516
  function designContextPath(artifactDir) {
57210
- return join23(artifactDir, DESIGN_CONTEXT_FILENAME);
57517
+ return join24(artifactDir, DESIGN_CONTEXT_FILENAME);
57211
57518
  }
57212
57519
  function referencesBriefPath(artifactDir) {
57213
- return join23(artifactDir, REFERENCES_BRIEF_FILENAME);
57520
+ return join24(artifactDir, REFERENCES_BRIEF_FILENAME);
57214
57521
  }
57215
57522
  function buildReferenceDiscoveryPrompt(args) {
57216
57523
  const siteList = REFERENCE_DESIGN_SITES.map((site, index) => `${index + 1}. ${site.name} — ${site.url}`).join(`
@@ -57236,8 +57543,8 @@ function buildReferenceDiscoveryPrompt(args) {
57236
57543
  [
57237
57544
  "Use the agent-browser skill to open each gallery; if `agent-browser` reports a missing browser executable, follow the bootstrap rules and retry once.",
57238
57545
  "From each gallery, choose 1-3 fitting designs and CLICK INTO each actual live or project-detail page; do not capture only the grid or thumbnail.",
57239
- `Capture motion across the entire page: start \`agent-browser record start ${join23(args.artifactDir, "ref-<site>-<n>.webm")}\`, scroll smoothly in small increments with waits (using repeated \`agent-browser scroll down 600\` or \`agent-browser mouse wheel 600\`) so animations fire and lazy content loads, then run \`agent-browser record stop\`.`,
57240
- `Also run \`agent-browser screenshot ${join23(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
57546
+ `Capture motion across the entire page: start \`agent-browser record start ${join24(args.artifactDir, "ref-<site>-<n>.webm")}\`, scroll smoothly in small increments with waits (using repeated \`agent-browser scroll down 600\` or \`agent-browser mouse wheel 600\`) so animations fire and lazy content loads, then run \`agent-browser record stop\`.`,
57547
+ `Also run \`agent-browser screenshot ${join24(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
57241
57548
  "Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
57242
57549
  "Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
57243
57550
  "Use ask_user_question to ask which reference direction they prefer, offering 2-4 strongest options plus `None of these fit`. If none fit, ask them to provide a reference image, screenshot, URL, or local file path and record the answer.",
@@ -57262,8 +57569,8 @@ function buildReferenceDiscoveryPrompt(args) {
57262
57569
  }
57263
57570
  function writeRequiredContextArtifact(artifactDir, filePath, content, label) {
57264
57571
  try {
57265
- mkdirSync7(artifactDir, { recursive: true });
57266
- writeFileSync4(filePath, `${content}
57572
+ mkdirSync8(artifactDir, { recursive: true });
57573
+ writeFileSync5(filePath, `${content}
57267
57574
  `);
57268
57575
  } catch (error) {
57269
57576
  const detail = error instanceof Error ? error.message : String(error);
@@ -57814,7 +58121,7 @@ var init_ralph_review_gate = __esm(() => {
57814
58121
 
57815
58122
  // dist/builtin/workflows/builtin/ralph-core.ts
57816
58123
  import { mkdir as mkdir4, writeFile as writeFile8 } from "node:fs/promises";
57817
- import { dirname as dirname11, join as join24 } from "node:path";
58124
+ import { dirname as dirname12, join as join25 } from "node:path";
57818
58125
  import { Type as Type20 } from "typebox";
57819
58126
  function taggedPrompt4(sections) {
57820
58127
  return sections.map(([tag, content]) => {
@@ -57854,11 +58161,11 @@ function slugifyResearchTopic(prompt) {
57854
58161
  }
57855
58162
  function defaultResearchPath(prompt, now = new Date) {
57856
58163
  const date = now.toISOString().slice(0, 10);
57857
- return join24(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
58164
+ return join25(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
57858
58165
  }
57859
58166
  async function createImplementationNotesFile(prompt, runId) {
57860
58167
  const notesDir = await createWorkflowArtifactDirectory(runId);
57861
- const notesPath = join24(notesDir, IMPLEMENTATION_NOTES_FILENAME);
58168
+ const notesPath = join25(notesDir, IMPLEMENTATION_NOTES_FILENAME);
57862
58169
  const initialNotes = [
57863
58170
  "# Implementation Notes",
57864
58171
  "",
@@ -57879,7 +58186,7 @@ async function createImplementationNotesFile(prompt, runId) {
57879
58186
  }
57880
58187
  async function createQaEvidenceVideoPath(runId) {
57881
58188
  const qaDir = await createWorkflowArtifactDirectory(runId);
57882
- return join24(qaDir, QA_E2E_VIDEO_FILENAME);
58189
+ return join25(qaDir, QA_E2E_VIDEO_FILENAME);
57883
58190
  }
57884
58191
  function renderQaE2eVideoGuidance(qaVideoPath) {
57885
58192
  return [
@@ -57945,7 +58252,7 @@ function artifactSafeName2(value2) {
57945
58252
  return safe.length > 0 ? safe : "artifact";
57946
58253
  }
57947
58254
  async function writeJsonArtifact(path, content) {
57948
- await mkdir4(dirname11(path), { recursive: true });
58255
+ await mkdir4(dirname12(path), { recursive: true });
57949
58256
  await writeFile8(path, `${JSON.stringify(content, null, 2)}
57950
58257
  `, {
57951
58258
  encoding: "utf8"
@@ -58283,7 +58590,7 @@ var init_ralph_models = __esm(() => {
58283
58590
 
58284
58591
  // dist/builtin/workflows/builtin/ralph-runner.ts
58285
58592
  import { existsSync as existsSync5 } from "node:fs";
58286
- import { join as join25, resolve as resolve10 } from "node:path";
58593
+ import { join as join26, resolve as resolve11 } from "node:path";
58287
58594
  async function runRalphWorkflow(ctx, options) {
58288
58595
  const { prompt, acceptanceCriteria, maxLoops, comparisonBaseBranch, workflowStartCwd, createPr, runId } = options;
58289
58596
  let latestReviewReportPath;
@@ -58295,7 +58602,7 @@ async function runRalphWorkflow(ctx, options) {
58295
58602
  let finalPrReport;
58296
58603
  const workflowCwdContext = workflowCwdContextSection(workflowStartCwd);
58297
58604
  const workflowPrompt = prompt;
58298
- const workflowResearchPath = resolve10(workflowStartCwd, defaultResearchPath(workflowPrompt));
58605
+ const workflowResearchPath = resolve11(workflowStartCwd, defaultResearchPath(workflowPrompt));
58299
58606
  const implementationNotesPath = await createImplementationNotesFile(workflowPrompt, runId);
58300
58607
  const qaVideoPath = await createQaEvidenceVideoPath(runId);
58301
58608
  const artifactDir = await createWorkflowArtifactDirectory(runId);
@@ -58344,7 +58651,7 @@ async function runRalphWorkflow(ctx, options) {
58344
58651
  const researchPath = workflowResearchPath;
58345
58652
  finalResearchPath = researchPath;
58346
58653
  finalPlanPath = researchPath;
58347
- const orchestratorReportPath = join25(artifactDir, "orchestrator-report.md");
58654
+ const orchestratorReportPath = join26(artifactDir, "orchestrator-report.md");
58348
58655
  const orchestratorForkOptions = forkContinuationOptions3(previousOrchestratorSessionId);
58349
58656
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? taggedPrompt4([
58350
58657
  ["acceptance_criteria", keepContext(acceptanceCriteria)],
@@ -58480,7 +58787,7 @@ Read it before implementation or delegation because it is the primary current im
58480
58787
  diagnostics: parsed.diagnostics,
58481
58788
  allowFinalActionRemaining: createPr
58482
58789
  });
58483
- const artifactPath = join25(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
58790
+ const artifactPath = join26(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
58484
58791
  await writeJsonArtifact(artifactPath, {
58485
58792
  reviewer,
58486
58793
  decision: parsed.decision,
@@ -58536,7 +58843,7 @@ Read it before implementation or delegation because it is the primary current im
58536
58843
  usage: fold_usage([orchestrator, ...reviews, ...reverifyResults])
58537
58844
  }));
58538
58845
  }
58539
- latestReviewReportPath = await writeJsonArtifact(join25(artifactDir, "review-round-latest.json"), {
58846
+ latestReviewReportPath = await writeJsonArtifact(join26(artifactDir, "review-round-latest.json"), {
58540
58847
  convergence_decision: roundConvergenceDecision,
58541
58848
  convergence: convergenceEntries,
58542
58849
  consolidated_findings: reverified.batch,
@@ -58685,7 +58992,7 @@ var init_ralph = __esm(() => {
58685
58992
  }),
58686
58993
  git_worktree_dir: Type21.String({
58687
58994
  default: "",
58688
- description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Must start inside a Git repo; absolute paths are used as-is, relative paths resolve from the repo root, existing Git worktrees from the invoking repository are reused/shared as-is, and missing paths are created from base_branch."
58995
+ description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Absolute paths are used as-is; relative paths resolve from the invoking repo root (or the invoking cwd outside a Git repo). An existing Git worktree root of any repository is reused as-is, even from another repository or a non-Git cwd. Creating a worktree requires starting inside the source Git repo: a missing path or an empty directory becomes a new worktree from base_branch, and a non-empty non-Git directory is treated as a worktree root that gets this run's own <dir>/<4-hex>/<repo-name> checkout, reused on resume."
58689
58996
  }),
58690
58997
  create_pr: Type21.Boolean({
58691
58998
  default: false,
@@ -58905,7 +59212,7 @@ var init_tournament_prompts = __esm(() => {
58905
59212
 
58906
59213
  // dist/builtin/workflows/builtin/tournament-runner.ts
58907
59214
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile9 } from "node:fs/promises";
58908
- import { join as join26, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve11 } from "node:path";
59215
+ import { join as join27, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve12 } from "node:path";
58909
59216
  import { Type as Type22 } from "typebox";
58910
59217
  function serializableObject2(value2) {
58911
59218
  if (value2 === null || Array.isArray(value2) || typeof value2 !== "object")
@@ -58942,8 +59249,8 @@ function criterionSlug(id) {
58942
59249
  }
58943
59250
  function judgeArtifactPath(judgesDir, job, criterionIndex) {
58944
59251
  const filename = `judge-${job.a}-${job.b}-c${criterionIndex}-${criterionSlug(job.criterionId)}-r${job.rep}.json`;
58945
- const root = resolve11(judgesDir);
58946
- const path = resolve11(judgesDir, filename);
59252
+ const root = resolve12(judgesDir);
59253
+ const path = resolve12(judgesDir, filename);
58947
59254
  const fromRoot = relative5(root, path);
58948
59255
  if (fromRoot.startsWith("..") || isAbsolute9(fromRoot)) {
58949
59256
  throw new Error(`tournament: judge artifact escaped its directory: ${path}`);
@@ -58994,16 +59301,16 @@ function combineUsage(totals) {
58994
59301
  }
58995
59302
  async function runTournament(ctx) {
58996
59303
  const artifactDir = await stableArtifactRoot(ctx, "tournament");
58997
- const attemptsDir = join26(artifactDir, "attempts");
59304
+ const attemptsDir = join27(artifactDir, "attempts");
58998
59305
  const numAttempts = ctx.inputs.num_attempts ?? 4;
58999
59306
  const maxConcurrency = ctx.inputs.max_concurrency ?? 4;
59000
59307
  const nEvaluations = ctx.inputs.n_evaluations ?? 2;
59001
59308
  const pivotCount = ctx.inputs.pivots ?? 1;
59002
59309
  const seed = ctx.inputs.seed ?? 0;
59003
- const judgesDir = join26(artifactDir, "judges");
59310
+ const judgesDir = join27(artifactDir, "judges");
59004
59311
  await mkdir5(attemptsDir, { recursive: true });
59005
59312
  await mkdir5(judgesDir, { recursive: true });
59006
- const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join26(attemptsDir, `attempt-${index + 1}.md`));
59313
+ const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join27(attemptsDir, `attempt-${index + 1}.md`));
59007
59314
  const models = ctx.inputs.models;
59008
59315
  const attemptResults = await ctx.parallel(attemptArtifactPaths.map((path, index) => ({
59009
59316
  name: `attempt-${index + 1}`,
@@ -59168,7 +59475,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
59168
59475
  const outputRanking = ranking.map(({ label, meanPreference }) => ({ label, meanPreference }));
59169
59476
  const budgetPivots = Math.min(pivotCount, entrants.length);
59170
59477
  const comparisonBudget = (entrants.length + budgetPivots * (entrants.length - budgetPivots) + budgetPivots * (budgetPivots - 1) / 2) * criteria.length * nEvaluations;
59171
- const comparisonPath = join26(artifactDir, "comparisons.json");
59478
+ const comparisonPath = join27(artifactDir, "comparisons.json");
59172
59479
  const assignment = modelAssignment(entrants, models);
59173
59480
  const phaseUsage = {
59174
59481
  attempts: fold_usage(attemptResults),
@@ -59204,7 +59511,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
59204
59511
  await writeLedger(fold_usage([]));
59205
59512
  const winner = ranking[0];
59206
59513
  const winnerEntrant = entrants[winner.index];
59207
- const resultPath = join26(artifactDir, "winner.md");
59514
+ const resultPath = join27(artifactDir, "winner.md");
59208
59515
  const reducer = await ctx.task("comparisons-reducer", {
59209
59516
  prompt: renderComparisonsReducerPrompt({
59210
59517
  task: ctx.inputs.prompt,
@@ -60110,7 +60417,7 @@ class SqlPoolQueue {
60110
60417
  throw new Error("Stale pool coordinator authority", { cause: error });
60111
60418
  throw error;
60112
60419
  });
60113
- const row = await this.current(tx, lease, token);
60420
+ const row = await this.current(tx, lease, token, true);
60114
60421
  if (row.epoch !== lease.epoch)
60115
60422
  throw new Error(STALE_WORK_LEASE);
60116
60423
  assertSession();
@@ -62344,7 +62651,7 @@ function isBrokerStatusReport(value2) {
62344
62651
 
62345
62652
  // dist/builtin/intercom/broker/paths.ts
62346
62653
  import { homedir as homedir2 } from "os";
62347
- import { join as join27 } from "path";
62654
+ import { join as join28 } from "path";
62348
62655
  function getHomeDir() {
62349
62656
  if (process.platform === "win32") {
62350
62657
  if (process.env.USERPROFILE)
@@ -62361,7 +62668,7 @@ function expandTildePath(path) {
62361
62668
  if (path === "~")
62362
62669
  return getHomeDir();
62363
62670
  if (path.startsWith("~/") || process.platform === "win32" && path.startsWith("~\\")) {
62364
- return join27(getHomeDir(), path.slice(2));
62671
+ return join28(getHomeDir(), path.slice(2));
62365
62672
  }
62366
62673
  return path;
62367
62674
  }
@@ -62372,31 +62679,31 @@ function getAgentDir5() {
62372
62679
  const piAgentDir = process.env.PI_CODING_AGENT_DIR;
62373
62680
  if (piAgentDir)
62374
62681
  return expandTildePath(piAgentDir);
62375
- return join27(getHomeDir(), ".atomic", "agent");
62682
+ return join28(getHomeDir(), ".atomic", "agent");
62376
62683
  }
62377
62684
  function sanitizePipeSegment(value2) {
62378
62685
  return value2.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "default";
62379
62686
  }
62380
62687
  function getIntercomDirPath(agentDir = getAgentDir5()) {
62381
- return join27(agentDir, "intercom");
62688
+ return join28(agentDir, "intercom");
62382
62689
  }
62383
62690
  function getBrokerPidPath(agentDir = getAgentDir5()) {
62384
- return join27(getIntercomDirPath(agentDir), "broker.pid");
62691
+ return join28(getIntercomDirPath(agentDir), "broker.pid");
62385
62692
  }
62386
62693
  function getBrokerSpawnLockPath(agentDir = getAgentDir5()) {
62387
- return join27(getIntercomDirPath(agentDir), "broker.spawn.lock");
62694
+ return join28(getIntercomDirPath(agentDir), "broker.spawn.lock");
62388
62695
  }
62389
62696
  function getBrokerLogPath(agentDir = getAgentDir5()) {
62390
- return join27(getIntercomDirPath(agentDir), "broker.log");
62697
+ return join28(getIntercomDirPath(agentDir), "broker.log");
62391
62698
  }
62392
62699
  function getBrokerStartAnnouncementPath(agentDir = getAgentDir5()) {
62393
- return join27(getIntercomDirPath(agentDir), "broker.starting");
62700
+ return join28(getIntercomDirPath(agentDir), "broker.starting");
62394
62701
  }
62395
62702
  function getBrokerSocketPath(platform = process.platform, agentDir = getAgentDir5()) {
62396
62703
  if (platform === "win32") {
62397
62704
  return `\\\\.\\pipe\\pi-intercom-${sanitizePipeSegment(agentDir)}`;
62398
62705
  }
62399
- return join27(getIntercomDirPath(agentDir), "broker.sock");
62706
+ return join28(getIntercomDirPath(agentDir), "broker.sock");
62400
62707
  }
62401
62708
  var BROKER_STORAGE_ENV = "ATOMIC_STORAGE";
62402
62709
  var init_paths = () => {};
@@ -64080,11 +64387,11 @@ var init_client = __esm(() => {
64080
64387
  var BROKER_READY_TIMEOUT_MS = 30000, MIN_BROKER_STARTUP_TIMEOUT_MS = 1000;
64081
64388
 
64082
64389
  // dist/builtin/intercom/broker/start-announcement.ts
64083
- import { readFileSync as readFileSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
64390
+ import { readFileSync as readFileSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
64084
64391
  function readBrokerStartAnnouncement(announcement) {
64085
64392
  let text;
64086
64393
  try {
64087
- text = readFileSync4(announcement.path, "utf-8");
64394
+ text = readFileSync6(announcement.path, "utf-8");
64088
64395
  } catch {
64089
64396
  return;
64090
64397
  }
@@ -64103,26 +64410,26 @@ var init_start_announcement = () => {};
64103
64410
  // dist/builtin/intercom/broker/spawn.ts
64104
64411
  import { spawn } from "child_process";
64105
64412
  import { randomUUID as randomUUID15 } from "crypto";
64106
- import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync5, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
64107
- import { join as join28, dirname as dirname12 } from "path";
64413
+ import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync7, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
64414
+ import { join as join29, dirname as dirname13 } from "path";
64108
64415
  import { fileURLToPath as fileURLToPath4 } from "url";
64109
64416
  import { createRequire as createRequire3 } from "module";
64110
64417
  import { createChildProcessEnvironment as createChildProcessEnvironment4, isBunBinary, processSharedStorageSelection } from "@bastani/atomic";
64111
64418
  function isIntercomPackageRoot(dir) {
64112
- return existsSync6(join28(dir, "package.json")) && existsSync6(join28(dir, "broker"));
64419
+ return existsSync6(join29(dir, "package.json")) && existsSync6(join29(dir, "broker"));
64113
64420
  }
64114
64421
  function resolveIntercomPackageRoot(moduleHref) {
64115
- const here = dirname12(fileURLToPath4(moduleHref));
64422
+ const here = dirname13(fileURLToPath4(moduleHref));
64116
64423
  if (isIntercomPackageRoot(here))
64117
64424
  return here;
64118
- return join28(here, "..");
64425
+ return join29(here, "..");
64119
64426
  }
64120
64427
  function resolveBrokerEntrypoint(packageRoot) {
64121
- const bundled = join28(packageRoot, "broker", "broker.bundle.mjs");
64122
- return existsSync6(bundled) ? bundled : join28(packageRoot, "broker", "broker.ts");
64428
+ const bundled = join29(packageRoot, "broker", "broker.bundle.mjs");
64429
+ return existsSync6(bundled) ? bundled : join29(packageRoot, "broker", "broker.ts");
64123
64430
  }
64124
64431
  function ensurePrivateDirectory(path) {
64125
- mkdirSync8(path, { recursive: true, mode: 448 });
64432
+ mkdirSync9(path, { recursive: true, mode: 448 });
64126
64433
  if (process.platform !== "win32")
64127
64434
  chmodSync(path, 448);
64128
64435
  }
@@ -64135,14 +64442,14 @@ function getCurrentBrokerRuntime() {
64135
64442
  return isBunBinary ? "bun-binary" : "bun-source";
64136
64443
  }
64137
64444
  function requireFromExtensionDir(extensionDir) {
64138
- return createRequire3(join28(extensionDir, "package.json"));
64445
+ return createRequire3(join29(extensionDir, "package.json"));
64139
64446
  }
64140
64447
  function getJitiCliPath(extensionDir = EXTENSION_DIR) {
64141
64448
  try {
64142
64449
  const jitiPackage = requireFromExtensionDir(extensionDir).resolve("jiti/package.json");
64143
- return join28(dirname12(jitiPackage), "lib", "jiti-cli.mjs");
64450
+ return join29(dirname13(jitiPackage), "lib", "jiti-cli.mjs");
64144
64451
  } catch {
64145
- return join28(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
64452
+ return join29(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
64146
64453
  }
64147
64454
  }
64148
64455
  function getDefaultBrokerRunnerPath(extensionDir) {
@@ -64164,7 +64471,7 @@ function quoteWindowsArg(value2) {
64164
64471
  return `"${value2.replace(/"/g, '""')}"`;
64165
64472
  }
64166
64473
  function getWindowsHiddenLauncherPath(intercomDir = INTERCOM_DIR) {
64167
- return join28(intercomDir, "broker-launch.vbs");
64474
+ return join29(intercomDir, "broker-launch.vbs");
64168
64475
  }
64169
64476
  function usesDefaultBrokerCommand(brokerCommand, brokerArgs) {
64170
64477
  return brokerCommand === "npx" && brokerArgs.length === 2 && brokerArgs[0] === "--no-install" && brokerArgs[1] === "tsx";
@@ -64191,8 +64498,8 @@ function getWindowsHiddenLauncherScript(commandLine) {
64191
64498
  `);
64192
64499
  }
64193
64500
  function writeWindowsHiddenLauncher(commandLine, launcherPath = getWindowsHiddenLauncherPath()) {
64194
- ensurePrivateDirectory(dirname12(launcherPath));
64195
- writeFileSync6(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
64501
+ ensurePrivateDirectory(dirname13(launcherPath));
64502
+ writeFileSync7(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
64196
64503
  return launcherPath;
64197
64504
  }
64198
64505
  function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath, runtime = getCurrentBrokerRuntime(), logPath = BROKER_LOG) {
@@ -64235,14 +64542,14 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore",
64235
64542
  };
64236
64543
  }
64237
64544
  function resetBrokerLog(logPath = BROKER_LOG) {
64238
- ensurePrivateDirectory(dirname12(logPath));
64545
+ ensurePrivateDirectory(dirname13(logPath));
64239
64546
  try {
64240
64547
  const previous = readBrokerLogTail(logPath);
64241
64548
  closeSync3(openSync3(logPath, "w"));
64242
64549
  if (previous.length > 0) {
64243
64550
  try {
64244
64551
  const previousPath = `${logPath}.previous`;
64245
- writeFileSync6(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
64552
+ writeFileSync7(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
64246
64553
  if (process.platform !== "win32")
64247
64554
  chmodSync(previousPath, 384);
64248
64555
  } catch {}
@@ -64386,7 +64693,7 @@ async function isBrokerRunning() {
64386
64693
  if (!existsSync6(BROKER_PID))
64387
64694
  return false;
64388
64695
  try {
64389
- const pid = parseInt(readFileSync5(BROKER_PID, "utf-8").trim(), 10);
64696
+ const pid = parseInt(readFileSync7(BROKER_PID, "utf-8").trim(), 10);
64390
64697
  if (!Number.isFinite(pid))
64391
64698
  return false;
64392
64699
  process.kill(pid, 0);
@@ -64411,7 +64718,7 @@ function handSpawnLockToBroker(pid, owner) {
64411
64718
  }
64412
64719
  function ownsSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
64413
64720
  try {
64414
- return readFileSync5(lockPath, "utf-8").startsWith(owner);
64721
+ return readFileSync7(lockPath, "utf-8").startsWith(owner);
64415
64722
  } catch {
64416
64723
  return false;
64417
64724
  }
@@ -64423,7 +64730,7 @@ function acquireSpawnLock() {
64423
64730
  ${Date.now()}
64424
64731
  `;
64425
64732
  try {
64426
- writeFileSync6(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
64733
+ writeFileSync7(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
64427
64734
  return owner;
64428
64735
  } catch (error) {
64429
64736
  if (!(error instanceof Error) || error.code !== "EEXIST") {
@@ -64453,7 +64760,7 @@ function isSpawnLockStale(lockPath = BROKER_SPAWN_LOCK, nowMs = Date.now()) {
64453
64760
  return false;
64454
64761
  }
64455
64762
  try {
64456
- const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync5(lockPath, "utf-8").trim().split(`
64763
+ const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync7(lockPath, "utf-8").trim().split(`
64457
64764
  `);
64458
64765
  const spawnerPid = Number.parseInt(spawnerLine, 10);
64459
64766
  const createdAt = Number.parseInt(createdAtLine, 10);
@@ -64531,14 +64838,14 @@ var init_reply_waiter = __esm(() => {
64531
64838
  });
64532
64839
 
64533
64840
  // dist/builtin/intercom/config.ts
64534
- import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
64841
+ import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
64535
64842
  import { getAgentConfigPaths } from "@bastani/atomic";
64536
64843
  function loadConfig() {
64537
64844
  if (!existsSync7(CONFIG_PATH)) {
64538
64845
  return { ...defaults };
64539
64846
  }
64540
64847
  try {
64541
- const raw = readFileSync6(CONFIG_PATH, "utf-8");
64848
+ const raw = readFileSync8(CONFIG_PATH, "utf-8");
64542
64849
  const parsed = JSON.parse(raw);
64543
64850
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
64544
64851
  throw new Error("Config must be a JSON object");
@@ -65121,12 +65428,12 @@ var init_sql_pool_usage = __esm(() => {
65121
65428
 
65122
65429
  // dist/builtin/workflows/src/workers/pooled-watch-trace.ts
65123
65430
  import { appendFileSync as appendFileSync2 } from "node:fs";
65124
- import { dirname as dirname13, join as join29, resolve as resolve12 } from "node:path";
65431
+ import { dirname as dirname14, join as join30, resolve as resolve13 } from "node:path";
65125
65432
  function configurePooledWatchTrace(journalPath, processRole) {
65126
65433
  if (setting === undefined || setting === "" || setting === "0")
65127
65434
  return;
65128
65435
  role = processRole;
65129
- file = setting === "1" ? join29(dirname13(resolve12(journalPath)), "pooled-watch-trace.jsonl") : resolve12(setting);
65436
+ file = setting === "1" ? join30(dirname14(resolve13(journalPath)), "pooled-watch-trace.jsonl") : resolve13(setting);
65130
65437
  }
65131
65438
  function tracePooledWatch(step, detail) {
65132
65439
  if (file === undefined)
@@ -65320,7 +65627,7 @@ import { fork } from "node:child_process";
65320
65627
  import { randomUUID as randomUUID17 } from "node:crypto";
65321
65628
  import { createWriteStream } from "node:fs";
65322
65629
  import { appendFile, mkdir as mkdir6, rm as rm3, rmdir } from "node:fs/promises";
65323
- import { dirname as dirname14, join as join30, resolve as resolve13 } from "node:path";
65630
+ import { dirname as dirname15, join as join31, resolve as resolve14 } from "node:path";
65324
65631
  import { setTimeout as delay2 } from "node:timers/promises";
65325
65632
  function isRootLeaseLost(error) {
65326
65633
  return error instanceof StaleLeaseError || error.message.startsWith("Stale lease for run ");
@@ -65329,7 +65636,7 @@ function unconfirmedCleanup(groups) {
65329
65636
  return new Error(`Local worker process cleanup unconfirmed; ${groups.length > 0 ? `process groups ${groups.join(", ")} still running after SIGKILL; ` : ""}permits quarantined`);
65330
65637
  }
65331
65638
  function workerLogDirectory(journalPath, root) {
65332
- return join30(dirname14(resolve13(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
65639
+ return join31(dirname15(resolve14(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
65333
65640
  }
65334
65641
  function token(work) {
65335
65642
  return {
@@ -65517,6 +65824,7 @@ class PoolCoordinator {
65517
65824
  cleanups = new Set;
65518
65825
  controlAcks = new Map;
65519
65826
  lastHeard = new Map;
65827
+ awaiting = new Map;
65520
65828
  pendingActivity = new Map;
65521
65829
  batches = new Map;
65522
65830
  publicationFailures = new Map;
@@ -66260,7 +66568,7 @@ class PoolCoordinator {
66260
66568
  this.slots.add(slot);
66261
66569
  let ready = false;
66262
66570
  let serial = Promise.resolve();
66263
- const logPath = join30(this.logDirectory, `${worker}.log`);
66571
+ const logPath = join31(this.logDirectory, `${worker}.log`);
66264
66572
  this.logs.set(child, logPath);
66265
66573
  let logFailure;
66266
66574
  const log = createWriteStream(logPath, { flags: "a" });
@@ -66316,6 +66624,7 @@ class PoolCoordinator {
66316
66624
  this.readyWorkers.delete(worker);
66317
66625
  this.controlAcks.delete(worker);
66318
66626
  this.lastHeard.delete(worker);
66627
+ this.awaiting.delete(worker);
66319
66628
  this.slots.delete(slot);
66320
66629
  this.endStageWatches((watch) => watch.slot === slot, "worker_exited");
66321
66630
  for (const settle of slot.stageCommands.values())
@@ -66573,8 +66882,19 @@ class PoolCoordinator {
66573
66882
  await this.sendResult(work.id);
66574
66883
  });
66575
66884
  const response = handled.then((value2) => routeReady ?? value2);
66576
- if (message.kind !== "delivery" && message.kind !== "delivery-ready")
66577
- serial = handled.then(() => {}, () => {});
66885
+ if (message.kind !== "delivery" && message.kind !== "delivery-ready") {
66886
+ this.awaiting.set(worker, (this.awaiting.get(worker) ?? 0) + 1);
66887
+ const answered = () => {
66888
+ const left = (this.awaiting.get(worker) ?? 1) - 1;
66889
+ if (left > 0)
66890
+ this.awaiting.set(worker, left);
66891
+ else
66892
+ this.awaiting.delete(worker);
66893
+ if (this.incarnations.get(worker) === child)
66894
+ this.lastHeard.set(worker, { at: performance.now(), stalled: this.stalledMs });
66895
+ };
66896
+ serial = handled.then(answered, answered);
66897
+ }
66578
66898
  response.then((value2) => child.send({ id: message.id, value: value2 }, replied), (error) => {
66579
66899
  const rootLeaseLost = isRootLeaseLost(error);
66580
66900
  if (rootLeaseLost)
@@ -66644,7 +66964,10 @@ class PoolCoordinator {
66644
66964
  if (work.epoch < lease.epoch)
66645
66965
  await this.releaseRetained(work);
66646
66966
  else
66647
- await queue.expire(lease, work);
66967
+ await queue.expire(lease, work).catch((error) => {
66968
+ if (error.message !== STALE_WORK_LEASE)
66969
+ throw error;
66970
+ });
66648
66971
  }
66649
66972
  })().finally(() => {
66650
66973
  this.recovering = undefined;
@@ -66662,7 +66985,7 @@ class PoolCoordinator {
66662
66985
  isLive(worker, child) {
66663
66986
  this.observeResponsiveness();
66664
66987
  const heard = this.lastHeard.get(worker);
66665
- return child.exitCode === null && child.signalCode === null && child.connected && heard !== undefined && performance.now() - heard.at - (this.stalledMs - heard.stalled) < this.options.leaseMs;
66988
+ return child.exitCode === null && child.signalCode === null && child.connected && heard !== undefined && ((this.awaiting.get(worker) ?? 0) > 0 || performance.now() - heard.at - (this.stalledMs - heard.stalled) < this.options.leaseMs);
66666
66989
  }
66667
66990
  async stop(child) {
66668
66991
  const pid = child.pid;
@@ -67014,7 +67337,7 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
67014
67337
  };
67015
67338
  }
67016
67339
  async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient) {
67017
- const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient);
67340
+ const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, recipient?.receivedMessageIds);
67018
67341
  const candidateIds = new Set([
67019
67342
  ...activeStore.pendingStageMessagesFor(runId, stageId),
67020
67343
  ...activeStore.pendingStageMessagesFor(runId, stageName),
@@ -67070,7 +67393,7 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
67070
67393
  }
67071
67394
  }
67072
67395
  }
67073
- function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient) {
67396
+ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, receivedByEndedStage = []) {
67074
67397
  const runs = activeStore.runs();
67075
67398
  const rootRunId = durableRootRunIdForRun(runs, runId);
67076
67399
  if (rootRunId === undefined)
@@ -67079,22 +67402,28 @@ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageNam
67079
67402
  if (rootRun === undefined)
67080
67403
  return [];
67081
67404
  const stage = runs.find((run) => run.id === runId)?.stages.find((candidate) => candidate.id === stageId);
67082
- if (stage?.status === "completed" || stage?.status === "skipped")
67405
+ const ended = stage?.status === "completed" || stage?.status === "skipped";
67406
+ if (ended && receivedByEndedStage.length === 0)
67083
67407
  return [];
67084
67408
  const hops = workflowBoundaryHops(runs, runId);
67085
67409
  if (hops === undefined)
67086
67410
  return [];
67087
67411
  return (rootRun.pendingStageMessages ?? []).filter((entry) => {
67088
- if (entry.sticky !== true || entry.status !== "queued")
67089
- return false;
67090
- const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
67091
- if (parsed === undefined || parsed.rootRunId !== rootRunId)
67092
- return false;
67093
67412
  if ((entry.deliveries ?? []).some((delivery) => delivery.runId === runId && delivery.stageId === stageId && (recipient === undefined || delivery.admission === "context" && delivery.sessionId === recipient.sessionId && (recipient.receivedMessageIds === undefined || recipient.receivedMessageIds.includes(entry.message.id)))))
67094
67413
  return false;
67095
- return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
67414
+ if (ended && !receivedByEndedStage.includes(entry.message.id))
67415
+ return false;
67416
+ return stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName);
67096
67417
  });
67097
67418
  }
67419
+ function stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName) {
67420
+ if (entry.sticky !== true || entry.status !== "queued")
67421
+ return false;
67422
+ const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
67423
+ if (parsed === undefined || parsed.rootRunId !== rootRunId)
67424
+ return false;
67425
+ return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
67426
+ }
67098
67427
  function claimPendingDelivery(store, runId, stageKey, messageId) {
67099
67428
  let claims = pendingDeliveryClaims.get(store);
67100
67429
  if (claims === undefined) {
@@ -67158,6 +67487,7 @@ class PoolStageHandoff {
67158
67487
  owners = new Map;
67159
67488
  publications = new Map;
67160
67489
  drains = new Map;
67490
+ deliveryIssues = 0;
67161
67491
  constructor(backend, store, queue, lease, claimRun) {
67162
67492
  this.backend = backend;
67163
67493
  this.store = store;
@@ -67238,11 +67568,23 @@ class PoolStageHandoff {
67238
67568
  this.drains.set(stage, drain);
67239
67569
  try {
67240
67570
  await drain;
67571
+ } catch (error) {
67572
+ const current = this.attempts.get(work.id) === attempt && !attempt.fenced;
67573
+ if (current && attempt.sessions.get(stage) === recipient.sessionId && error.message !== STALE)
67574
+ this.recordDeliveryIssue(error);
67575
+ throw error;
67241
67576
  } finally {
67242
67577
  if (this.drains.get(stage) === drain)
67243
67578
  this.drains.delete(stage);
67244
67579
  }
67245
67580
  }
67581
+ recordDeliveryIssue(error) {
67582
+ this.deliveryIssues++;
67583
+ const drains = this.deliveryIssues === 1 ? "1 stage drain" : `${this.deliveryIssues} stage drains`;
67584
+ this.store.recordRunExecutionState(this.lease.runId, {
67585
+ intercomDeliveryIssue: `${drains} on local workers failed; undelivered messages stay queued and arrive live or on the stage's next drain (last: ${error.message})`
67586
+ });
67587
+ }
67246
67588
  async complete(work) {
67247
67589
  const root = this.lease.runId;
67248
67590
  const result = await this.queue.result(root, work.id);
@@ -68598,7 +68940,7 @@ var init_pooled_stage_registry = __esm(() => {
68598
68940
  // dist/builtin/workflows/src/workers/local-pool.ts
68599
68941
  import { fork as fork2 } from "node:child_process";
68600
68942
  import { randomUUID as randomUUID19 } from "node:crypto";
68601
- import { resolve as resolve14 } from "node:path";
68943
+ import { resolve as resolve15 } from "node:path";
68602
68944
  import { setTimeout as delay3 } from "node:timers/promises";
68603
68945
  import { fileURLToPath as fileURLToPath5 } from "node:url";
68604
68946
  import {
@@ -68832,7 +69174,7 @@ class LocalWorkerPool {
68832
69174
  async poolJournal() {
68833
69175
  const journal = this.backend.journal;
68834
69176
  if (this.options.durable === undefined) {
68835
- if (!(journal instanceof SqlRunJournal) || resolve14(this.options.journalPath) !== resolve14(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
69177
+ if (!(journal instanceof SqlRunJournal) || resolve15(this.options.journalPath) !== resolve15(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
68836
69178
  throw new Error("Local workers require the same default-prefix SQLite journal");
68837
69179
  return journal;
68838
69180
  }
@@ -69859,7 +70201,7 @@ var init_local_pool = __esm(() => {
69859
70201
  var DEFAULT_POOLED_STAGE_START_MAX_LOAD_PER_CPU = 3;
69860
70202
 
69861
70203
  // dist/builtin/workflows/src/workers/public-pool.ts
69862
- import { resolve as resolve15 } from "node:path";
70204
+ import { resolve as resolve16 } from "node:path";
69863
70205
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
69864
70206
  async function restoreWorkerOptions(backend, options) {
69865
70207
  const source = options.continuation?.source.id ?? options.runId;
@@ -69909,16 +70251,16 @@ async function activatePublicPool(backend, options) {
69909
70251
  startupTimeoutMs: undefined,
69910
70252
  leaseMs: undefined,
69911
70253
  maxLoadPerCpu: undefined,
69912
- definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve15(cwd, source.path) }))
70254
+ definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve16(cwd, source.path) }))
69913
70255
  };
69914
70256
  const admission = options.admission && {
69915
70257
  ...options.admission,
69916
- ...options.admission.userDatabase ? { userDatabase: resolve15(cwd, options.admission.userDatabase) } : {}
70258
+ ...options.admission.userDatabase ? { userDatabase: resolve16(cwd, options.admission.userDatabase) } : {}
69917
70259
  };
69918
70260
  if (durable !== undefined && admission?.userLimits) {
69919
- if (admission.userDatabase !== undefined && admission.userDatabase !== resolve15(poolPath))
69920
- throw new Error(`admission.userDatabase must be omitted, or ${resolve15(poolPath)}, for a journal that is not a local SQLite file`);
69921
- admission.userDatabase = resolve15(poolPath);
70261
+ if (admission.userDatabase !== undefined && admission.userDatabase !== resolve16(poolPath))
70262
+ throw new Error(`admission.userDatabase must be omitted, or ${resolve16(poolPath)}, for a journal that is not a local SQLite file`);
70263
+ admission.userDatabase = resolve16(poolPath);
69922
70264
  }
69923
70265
  const sources = localWorkers && await Promise.all(localWorkers.definitions.map(async (source) => ({ ...source, digest: await definitionDigest(source.path) })));
69924
70266
  const resources = JSON.parse(JSON.stringify({
@@ -70524,6 +70866,7 @@ function createTaskPrimitive(runtime) {
70524
70866
  }
70525
70867
  })();
70526
70868
  const stageMeta = stage.__modelFallbackMeta();
70869
+ stage.__releaseIfIdle?.();
70527
70870
  return {
70528
70871
  name,
70529
70872
  stageName: name,
@@ -71322,7 +71665,7 @@ function hasUsableContentBlock(block) {
71322
71665
 
71323
71666
  // dist/builtin/workflows/src/shared/stage-session-store.ts
71324
71667
  import { randomUUID as randomUUID21 } from "node:crypto";
71325
- import { dirname as dirname15, resolve as resolve16 } from "node:path";
71668
+ import { dirname as dirname16, resolve as resolve17 } from "node:path";
71326
71669
  import {
71327
71670
  JsonlSessionStore,
71328
71671
  resolveSessionStore,
@@ -71358,11 +71701,11 @@ async function forkStageSession(store, sessionId, cwd, options, destination = st
71358
71701
  async function migrateLegacyStageSession(store, sessionId, sessionFile) {
71359
71702
  if (sessionFile === undefined || await store.readHeader(sessionId) !== undefined)
71360
71703
  return;
71361
- const location = resolve16(sessionFile);
71362
- const legacy = await JsonlSessionStore.open(dirname15(location), { exactDirectory: true, scanExisting: false });
71704
+ const location = resolve17(sessionFile);
71705
+ const legacy = await JsonlSessionStore.open(dirname16(location), { exactDirectory: true, scanExisting: false });
71363
71706
  try {
71364
71707
  for await (const file of legacy.scanFiles()) {
71365
- if (resolve16(file.location) !== location || file.header.id !== sessionId)
71708
+ if (resolve17(file.location) !== location || file.header.id !== sessionId)
71366
71709
  continue;
71367
71710
  const snapshot = await file.read();
71368
71711
  if (await store.readHeader(sessionId) === undefined)
@@ -74188,6 +74531,8 @@ function createTrackedStageCaller(input) {
74188
74531
  await runtime.releaseLiveHandle().catch(() => {});
74189
74532
  }
74190
74533
  runtime.state.sessionCheckpointed = finalizationError === undefined;
74534
+ if (runtime.state.contextUnreachable)
74535
+ runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId);
74191
74536
  input.limiter.release();
74192
74537
  if (finalizationError !== undefined)
74193
74538
  throwFinalizationError(finalizationError.error);
@@ -74351,7 +74696,8 @@ function createStageContext(input) {
74351
74696
  recordStageNotice({ kind: "abort", to: "interrupted" });
74352
74697
  await innerCtx.abort();
74353
74698
  },
74354
- __modelFallbackMeta: () => innerCtx.__modelFallbackMeta()
74699
+ __modelFallbackMeta: () => innerCtx.__modelFallbackMeta(),
74700
+ __releaseIfIdle: () => runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId)
74355
74701
  };
74356
74702
  }
74357
74703
 
@@ -76040,10 +76386,10 @@ function isRetryableSameCandidateFailure(error) {
76040
76386
  return isTransientExtensionStartupFailure(error);
76041
76387
  return isRetryableSameModelFailure(error);
76042
76388
  }
76043
- function mayAdvanceToNextCandidate(error) {
76389
+ function mayAdvanceToNextCandidate(error, options) {
76044
76390
  if (isExtensionStartupFailure(error))
76045
76391
  return isTransientExtensionStartupFailure(error);
76046
- return isRetryableModelFailure(error);
76392
+ return isRetryableModelFailure(error, options);
76047
76393
  }
76048
76394
  function hasMeaningfulUsage(usage) {
76049
76395
  if (usage === undefined)
@@ -76135,6 +76481,7 @@ class StageSessionController {
76135
76481
  structuredOutputExecutionFailureValue;
76136
76482
  structuredOutputCycleAttemptMark;
76137
76483
  unsubscribeTerminateWatcher;
76484
+ unbindAbortSignal;
76138
76485
  sessionInternalRetries = 0;
76139
76486
  unresolvedContextOverflowMessage;
76140
76487
  generationSealed = false;
@@ -76624,6 +76971,8 @@ class StageSessionController {
76624
76971
  this.pendingListeners.clear();
76625
76972
  this.unsubscribeTerminateWatcher?.();
76626
76973
  this.unsubscribeTerminateWatcher = undefined;
76974
+ this.unbindAbortSignal?.();
76975
+ this.unbindAbortSignal = undefined;
76627
76976
  this.terminatingToolCallIds.clear();
76628
76977
  this.messageAdmission.dispose();
76629
76978
  this.deliveryActivity.dispose();
@@ -76718,8 +77067,10 @@ class StageSessionController {
76718
77067
  };
76719
77068
  if (signal.aborted)
76720
77069
  onAbort();
76721
- else
77070
+ else {
76722
77071
  signal.addEventListener("abort", onAbort, { once: true });
77072
+ this.unbindAbortSignal = () => signal.removeEventListener("abort", onAbort);
77073
+ }
76723
77074
  }
76724
77075
  markAbort(reason) {
76725
77076
  this.abortGeneration += 1;
@@ -76746,6 +77097,9 @@ class StageSessionController {
76746
77097
  state.controller.abort(reason);
76747
77098
  this.thrownErrorRetryStates.clear();
76748
77099
  }
77100
+ fallbackFailureOptions() {
77101
+ return { fallbackOnContentFilter: this.retrySettings()?.fallbackOnContentFilter !== false };
77102
+ }
76749
77103
  retrySettings() {
76750
77104
  const managers = [
76751
77105
  this.sessionSettingsManager,
@@ -77020,7 +77374,7 @@ class StageSessionController {
77020
77374
  const errorSettingsManager = retrySettingsManagerFromError(error);
77021
77375
  if (errorSettingsManager !== undefined)
77022
77376
  this.sessionSettingsManager = errorSettingsManager;
77023
- const retryableFailure = isRetryableModelFailure(error);
77377
+ const retryableFailure = isRetryableModelFailure(error, this.fallbackFailureOptions());
77024
77378
  const sameCandidateRetryable = isRetryableSameModelFailure(error) && !isUnresolvedContextOverflowFailure(error);
77025
77379
  recordProviderRateLimit(this.currentProvider(), error, modelIdForModel(this.currentModelValue()));
77026
77380
  if (this.hasExplicitModelFallbackConfig && isProviderRateLimit(error)) {
@@ -77645,7 +77999,7 @@ class StageSessionController {
77645
77999
  }
77646
78000
  throw new WorkflowPromptModelFailure(terminalFailure);
77647
78001
  } catch (err) {
77648
- if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
78002
+ if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
77649
78003
  this.artifactCapture.settleAttempt(true);
77650
78004
  const usage = this.takeAttemptUsage(resumedSession);
77651
78005
  this.modelAttempts.push({
@@ -77667,7 +78021,7 @@ class StageSessionController {
77667
78021
  ...usage === undefined ? {} : { usage },
77668
78022
  error: message
77669
78023
  });
77670
- if (this.opts.signal?.aborted || !isRetryableModelFailure(err)) {
78024
+ if (this.opts.signal?.aborted || !isRetryableModelFailure(err, this.fallbackFailureOptions())) {
77671
78025
  this.modelWarnings.push(...this.pendingFallbackWarnings);
77672
78026
  this.pendingFallbackWarnings.length = 0;
77673
78027
  this.notifyModelFallbackMetaChange();
@@ -77716,7 +78070,7 @@ class StageSessionController {
77716
78070
  throw err;
77717
78071
  const message = errorMessage3(err);
77718
78072
  const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
77719
- if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
78073
+ if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
77720
78074
  this.recordSuccessfulAttempt(candidate);
77721
78075
  return "handled";
77722
78076
  }
@@ -77733,7 +78087,7 @@ class StageSessionController {
77733
78087
  if (walk !== undefined) {
77734
78088
  this.recordCandidateFailure(walk, index, err, candidates);
77735
78089
  nextIndex = undefined;
77736
- if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err)) {
78090
+ if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err, this.fallbackFailureOptions())) {
77737
78091
  try {
77738
78092
  nextIndex = await this.selectReadyCandidate(candidates, walk, index + 1);
77739
78093
  } catch (error) {
@@ -77746,7 +78100,7 @@ class StageSessionController {
77746
78100
  }
77747
78101
  }
77748
78102
  }
77749
- if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err) || nextIndex === undefined) {
78103
+ if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err, this.fallbackFailureOptions()) || nextIndex === undefined) {
77750
78104
  await this.settleFailedCandidate();
77751
78105
  return "throw";
77752
78106
  }
@@ -77841,7 +78195,7 @@ var init_stage_runner_controller = __esm(() => {
77841
78195
  // dist/builtin/workflows/src/runs/foreground/stage-runner-output.ts
77842
78196
  import { createHash as createHash6 } from "node:crypto";
77843
78197
  import { mkdir as mkdir7, writeFile as writeFile10 } from "node:fs/promises";
77844
- import { basename as basename6, dirname as dirname16, isAbsolute as isAbsolute11, join as join31, resolve as resolve17 } from "node:path";
78198
+ import { basename as basename6, dirname as dirname17, isAbsolute as isAbsolute11, join as join32, resolve as resolve18 } from "node:path";
77845
78199
  function normalizeMaxOutput2(maxOutput) {
77846
78200
  return {
77847
78201
  bytes: maxOutput?.bytes ?? DEFAULT_MAX_OUTPUT_BYTES,
@@ -77904,7 +78258,7 @@ function formatByteSize(bytes) {
77904
78258
  }
77905
78259
  function transcriptPath(runId, outputPath) {
77906
78260
  const digest = createHash6("sha256").update(outputPath).digest("hex").slice(0, 16);
77907
- return join31(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename6(outputPath)}.transcript.md`);
78261
+ return join32(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename6(outputPath)}.transcript.md`);
77908
78262
  }
77909
78263
  function appendContent(lines, content) {
77910
78264
  if (typeof content === "string") {
@@ -77949,7 +78303,7 @@ function renderTranscript(messages, fallbackOutput) {
77949
78303
  `);
77950
78304
  }
77951
78305
  function savedOutputReference(outputPath, fullOutput, transcriptPathValue, transcriptText, transcriptAvailable, warning) {
77952
- const absolutePath = resolve17(outputPath);
78306
+ const absolutePath = resolve18(outputPath);
77953
78307
  const bytes = Buffer.byteLength(fullOutput, "utf8");
77954
78308
  const lines = countLines(fullOutput);
77955
78309
  const transcriptBytes = Buffer.byteLength(transcriptText, "utf8");
@@ -77964,8 +78318,8 @@ function resolveOutputPath(output, runtimeCwd, requestedCwd) {
77964
78318
  return;
77965
78319
  if (isAbsolute11(output))
77966
78320
  return output;
77967
- const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve17(runtimeCwd, requestedCwd);
77968
- return resolve17(baseCwd, output);
78321
+ const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve18(runtimeCwd, requestedCwd);
78322
+ return resolve18(baseCwd, output);
77969
78323
  }
77970
78324
  function degenerateWarning(fullOutput) {
77971
78325
  return fullOutput.trim().length === 0 ? "WARNING: the stage artifact is empty; search the companion transcript for this stage's work." : undefined;
@@ -78024,7 +78378,7 @@ async function finalizePromptOutput(fullOutput, outputOptions, runtimeCwd, runId
78024
78378
  const transcriptFile = transcriptPath(runId, outputPath);
78025
78379
  const transcript = renderTranscript(messages, fullOutput);
78026
78380
  try {
78027
- await mkdir7(dirname16(outputPath), { recursive: true });
78381
+ await mkdir7(dirname17(outputPath), { recursive: true });
78028
78382
  await writeFile10(outputPath, fullOutput, "utf8");
78029
78383
  } catch (err) {
78030
78384
  return `${displayOutput}
@@ -78036,7 +78390,7 @@ ${err instanceof Error ? err.message : String(err)}`;
78036
78390
  let transcriptError;
78037
78391
  try {
78038
78392
  await ensureWorkflowArtifactRunDirectory(runId);
78039
- await mkdir7(dirname16(transcriptFile), { recursive: true });
78393
+ await mkdir7(dirname17(transcriptFile), { recursive: true });
78040
78394
  await writeFile10(transcriptFile, transcript, "utf8");
78041
78395
  transcriptAvailable = true;
78042
78396
  } catch (err) {
@@ -78547,7 +78901,8 @@ function createWorkflowStageFactory(input) {
78547
78901
  stageFinalized: false,
78548
78902
  sessionCheckpointed: false,
78549
78903
  skippedForParallelFailFast: false,
78550
- stageControlDropped: false
78904
+ stageControlDropped: false,
78905
+ contextUnreachable: false
78551
78906
  };
78552
78907
  const activeAskUserQuestionCalls = new Set;
78553
78908
  const hasActiveAskUserQuestion = () => activeAskUserQuestionCalls.size > 0 || state.activeAskUserQuestionAnonymousCalls > 0;
@@ -78793,9 +79148,18 @@ function createWorkflowStageFactory(input) {
78793
79148
  hasContinuation: input.opts.continuation !== undefined,
78794
79149
  hasScopedParents: stageFailFastScope?.parentIds !== undefined
78795
79150
  });
78796
- return createStageContext({ runtime, runTrackedStageCall });
79151
+ const context = createStageContext({ runtime, runTrackedStageCall });
79152
+ unreachableStageContexts.register(context, releaseWhenUnreachable(state, input.stageRegistry, input.runId, stageId));
79153
+ return context;
79154
+ };
79155
+ }
79156
+ function releaseWhenUnreachable(state, registry, runId, stageId) {
79157
+ return () => {
79158
+ state.contextUnreachable = true;
79159
+ registry.releaseIdle(runId, stageId);
78797
79160
  };
78798
79161
  }
79162
+ var unreachableStageContexts;
78799
79163
  var init_executor_stage_factory = __esm(() => {
78800
79164
  init_intercom_group();
78801
79165
  init_pending_stage_route_readiness();
@@ -78810,6 +79174,7 @@ var init_executor_stage_factory = __esm(() => {
78810
79174
  init_pending_stage_delivery2();
78811
79175
  init_stage_runner();
78812
79176
  init_stage_runner_session();
79177
+ unreachableStageContexts = new FinalizationRegistry((release) => release());
78813
79178
  });
78814
79179
 
78815
79180
  // dist/builtin/workflows/src/engine/runtime.ts
@@ -79151,7 +79516,7 @@ async function executeRun(def, resolvedInputs, opts) {
79151
79516
  const ownsCancellationRegistration = opts.signal === undefined && opts.cancellation !== undefined;
79152
79517
  const tracker = new GraphFrontierTracker;
79153
79518
  const inputConcurrency = resolveInputConcurrency(def.inputs, resolvedInputs);
79154
- const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache);
79519
+ const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache, runId);
79155
79520
  const gitWorktreeSetupCache = gitWorktreeSetupCacheOwner.cache;
79156
79521
  const workflowInvocationCwd = opts.cwd ?? process.cwd();
79157
79522
  let workflowCwd;