@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
@@ -3058,8 +3058,12 @@ function createStageControlRegistry() {
3058
3058
  }
3059
3059
  await disposeEntries(entries);
3060
3060
  },
3061
- async releaseIdle(runId) {
3062
- for (const [stageId, entry] of [..._byRun.get(runId) ?? []]) {
3061
+ async releaseIdle(runId, only) {
3062
+ const runMap = _byRun.get(runId);
3063
+ const entries = only === undefined ? [...runMap ?? []] : [[only, runMap?.get(only)]];
3064
+ for (const [stageId, entry] of entries) {
3065
+ if (entry === undefined)
3066
+ continue;
3063
3067
  try {
3064
3068
  await releaseIdleEntry(runId, stageId, entry);
3065
3069
  } catch (error) {
@@ -15573,9 +15577,104 @@ var init_workflow_artifacts = __esm(() => {
15573
15577
  pendingArtifactPrunes = new Map;
15574
15578
  });
15575
15579
 
15576
- // dist/builtin/workflows/src/runs/shared/worktree-generation.ts
15580
+ // dist/builtin/workflows/src/runs/shared/worktree-allocation.ts
15581
+ import { randomBytes } from "node:crypto";
15577
15582
  import * as fs from "node:fs";
15578
15583
  import * as path from "node:path";
15584
+ function nextBucketId() {
15585
+ return nextBucketIdOverride?.() ?? randomBytes(2).toString("hex");
15586
+ }
15587
+ function errorCode(error) {
15588
+ return error && typeof error === "object" && "code" in error ? String(error.code) : undefined;
15589
+ }
15590
+ function allocateWorktreeCheckoutPath(root, repositoryName) {
15591
+ for (let attempt = 0;attempt < MAX_BUCKET_ATTEMPTS; attempt++) {
15592
+ const bucket = path.join(root, nextBucketId());
15593
+ try {
15594
+ fs.mkdirSync(bucket);
15595
+ return path.join(bucket, repositoryName);
15596
+ } catch (error) {
15597
+ if (errorCode(error) === "EEXIST")
15598
+ continue;
15599
+ const message = error instanceof Error ? error.message : String(error);
15600
+ throw new Error(`Failed to create worktree bucket ${bucket} under gitWorktreeDir ${root}: ${message}`);
15601
+ }
15602
+ }
15603
+ throw new Error(`Every worktree bucket identifier under gitWorktreeDir ${root} is already in use.`);
15604
+ }
15605
+ function removeEmptyWorktreeBucket(checkout) {
15606
+ try {
15607
+ fs.rmdirSync(path.dirname(checkout));
15608
+ } catch {}
15609
+ }
15610
+ function linkedGitDirectory(checkout) {
15611
+ let pointer;
15612
+ try {
15613
+ if (!fs.lstatSync(path.join(checkout, ".git")).isFile())
15614
+ return;
15615
+ pointer = fs.readFileSync(path.join(checkout, ".git"), "utf8");
15616
+ } catch {
15617
+ return;
15618
+ }
15619
+ if (!pointer.startsWith("gitdir:"))
15620
+ return;
15621
+ const gitDir = pointer.slice("gitdir:".length).trim();
15622
+ return gitDir ? path.resolve(checkout, gitDir) : undefined;
15623
+ }
15624
+ function readWorktreeOwner(gitDir) {
15625
+ let contents;
15626
+ try {
15627
+ contents = fs.readFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), "utf8");
15628
+ } catch {
15629
+ return;
15630
+ }
15631
+ try {
15632
+ const record = JSON.parse(contents);
15633
+ return record.version === WORKTREE_OWNER_VERSION && typeof record.ownerRunId === "string" && record.ownerRunId ? record.ownerRunId : undefined;
15634
+ } catch {
15635
+ return;
15636
+ }
15637
+ }
15638
+ function findOwnedWorktreeCheckouts(root, repositoryName, ownerRunId) {
15639
+ let entries;
15640
+ try {
15641
+ entries = fs.readdirSync(root, { withFileTypes: true });
15642
+ } catch {
15643
+ return [];
15644
+ }
15645
+ const owned = [];
15646
+ for (const entry of entries) {
15647
+ if (!entry.isDirectory() || !BUCKET_PATTERN.test(entry.name))
15648
+ continue;
15649
+ const checkout = path.join(root, entry.name, repositoryName);
15650
+ try {
15651
+ if (!fs.lstatSync(checkout).isDirectory())
15652
+ continue;
15653
+ } catch {
15654
+ continue;
15655
+ }
15656
+ const gitDir = linkedGitDirectory(checkout);
15657
+ if (gitDir !== undefined && readWorktreeOwner(gitDir) === ownerRunId)
15658
+ owned.push(checkout);
15659
+ }
15660
+ return owned.sort();
15661
+ }
15662
+ function bindWorktreeOwner(gitDir, ownerRunId) {
15663
+ const record = { version: WORKTREE_OWNER_VERSION, ownerRunId };
15664
+ fs.writeFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), `${JSON.stringify(record)}
15665
+ `, {
15666
+ encoding: "utf8",
15667
+ flag: "wx"
15668
+ });
15669
+ }
15670
+ var WORKTREE_OWNER_FILENAME = "atomic-workflow-run.json", WORKTREE_OWNER_VERSION = 1, BUCKET_PATTERN, MAX_BUCKET_ATTEMPTS = 65536, nextBucketIdOverride;
15671
+ var init_worktree_allocation = __esm(() => {
15672
+ BUCKET_PATTERN = /^[0-9a-f]{4}$/;
15673
+ });
15674
+
15675
+ // dist/builtin/workflows/src/runs/shared/worktree-generation.ts
15676
+ import * as fs2 from "node:fs";
15677
+ import * as path2 from "node:path";
15579
15678
  function sameFileIdentity(left, right) {
15580
15679
  return left.dev === right.dev && left.ino === right.ino;
15581
15680
  }
@@ -15585,7 +15684,7 @@ function openMainCheckoutAnchor(gitDir) {
15585
15684
  assertCurrent() {
15586
15685
  if (disposed)
15587
15686
  throw new Error(`cached .git identity anchor is already disposed: ${gitDir}`);
15588
- if (!fs.lstatSync(gitDir).isDirectory()) {
15687
+ if (!fs2.lstatSync(gitDir).isDirectory()) {
15589
15688
  throw new Error(`cached main-checkout .git directory is no longer current: ${gitDir}`);
15590
15689
  }
15591
15690
  },
@@ -15595,17 +15694,17 @@ function openMainCheckoutAnchor(gitDir) {
15595
15694
  };
15596
15695
  }
15597
15696
  function openGitWorktreeGenerationAnchor(worktreeRoot) {
15598
- const gitFile = path.join(worktreeRoot, ".git");
15599
- if (fs.lstatSync(gitFile).isDirectory())
15697
+ const gitFile = path2.join(worktreeRoot, ".git");
15698
+ if (fs2.lstatSync(gitFile).isDirectory())
15600
15699
  return openMainCheckoutAnchor(gitFile);
15601
- const descriptor = fs.openSync(gitFile, "r");
15700
+ const descriptor = fs2.openSync(gitFile, "r");
15602
15701
  let disposed = false;
15603
15702
  const anchor = {
15604
15703
  assertCurrent() {
15605
15704
  if (disposed)
15606
15705
  throw new Error(`cached .git identity anchor is already disposed: ${gitFile}`);
15607
- const held = fs.fstatSync(descriptor, { bigint: true });
15608
- const current = fs.lstatSync(gitFile, { bigint: true });
15706
+ const held = fs2.fstatSync(descriptor, { bigint: true });
15707
+ const current = fs2.lstatSync(gitFile, { bigint: true });
15609
15708
  if (!current.isFile() || !sameFileIdentity(held, current)) {
15610
15709
  throw new Error(`cached .git identity anchor no longer matches the selected checkout: ${gitFile}`);
15611
15710
  }
@@ -15614,7 +15713,7 @@ function openGitWorktreeGenerationAnchor(worktreeRoot) {
15614
15713
  if (disposed)
15615
15714
  return;
15616
15715
  disposed = true;
15617
- fs.closeSync(descriptor);
15716
+ fs2.closeSync(descriptor);
15618
15717
  }
15619
15718
  };
15620
15719
  try {
@@ -15728,84 +15827,84 @@ var init_worktree_git_runner = __esm(() => {
15728
15827
  });
15729
15828
 
15730
15829
  // dist/builtin/workflows/src/runs/shared/worktree-root.ts
15731
- import * as fs2 from "node:fs";
15732
- import * as path2 from "node:path";
15830
+ import * as fs3 from "node:fs";
15831
+ import * as path3 from "node:path";
15733
15832
  function pathFromPointer(contents, prefix, base) {
15734
15833
  if (!contents.startsWith(prefix))
15735
15834
  return;
15736
15835
  const value2 = contents.slice(prefix.length).trim();
15737
15836
  if (!value2)
15738
15837
  return;
15739
- return path2.resolve(base, value2);
15838
+ return path3.resolve(base, value2);
15740
15839
  }
15741
15840
  function readText(file) {
15742
15841
  try {
15743
- return fs2.readFileSync(file, "utf8");
15842
+ return fs3.readFileSync(file, "utf8");
15744
15843
  } catch {
15745
15844
  return;
15746
15845
  }
15747
15846
  }
15748
15847
  function samePath(left, right) {
15749
15848
  try {
15750
- const a = fs2.realpathSync.native(left);
15751
- const b = fs2.realpathSync.native(right);
15849
+ const a = fs3.realpathSync.native(left);
15850
+ const b = fs3.realpathSync.native(right);
15752
15851
  return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
15753
15852
  } catch {
15754
15853
  return false;
15755
15854
  }
15756
15855
  }
15757
15856
  function findGitRoot(cwd) {
15758
- let current = path2.resolve(cwd);
15857
+ let current = path3.resolve(cwd);
15759
15858
  try {
15760
- if (!fs2.statSync(current).isDirectory())
15761
- current = path2.dirname(current);
15859
+ if (!fs3.statSync(current).isDirectory())
15860
+ current = path3.dirname(current);
15762
15861
  } catch {
15763
15862
  return;
15764
15863
  }
15765
15864
  while (true) {
15766
15865
  try {
15767
- const entry = fs2.statSync(path2.join(current, ".git"));
15866
+ const entry = fs3.statSync(path3.join(current, ".git"));
15768
15867
  if (entry.isDirectory() || entry.isFile())
15769
15868
  return current;
15770
15869
  } catch {}
15771
- const parent = path2.dirname(current);
15870
+ const parent = path3.dirname(current);
15772
15871
  if (parent === current)
15773
15872
  return;
15774
15873
  current = parent;
15775
15874
  }
15776
15875
  }
15777
15876
  function resolveMainRepoRoot(repoRoot) {
15778
- const gitEntry = path2.join(repoRoot, ".git");
15877
+ const gitEntry = path3.join(repoRoot, ".git");
15779
15878
  let stats;
15780
15879
  try {
15781
- stats = fs2.statSync(gitEntry);
15880
+ stats = fs3.statSync(gitEntry);
15782
15881
  } catch {
15783
15882
  return;
15784
15883
  }
15785
15884
  if (stats.isDirectory())
15786
- return path2.resolve(repoRoot);
15885
+ return path3.resolve(repoRoot);
15787
15886
  if (!stats.isFile())
15788
15887
  return;
15789
15888
  const pointer = readText(gitEntry);
15790
15889
  if (pointer === undefined)
15791
15890
  return;
15792
15891
  const gitDir = pathFromPointer(pointer, "gitdir:", repoRoot);
15793
- if (gitDir === undefined || path2.basename(path2.dirname(gitDir)) !== "worktrees")
15892
+ if (gitDir === undefined || path3.basename(path3.dirname(gitDir)) !== "worktrees")
15794
15893
  return;
15795
- const commonGitDir = path2.dirname(path2.dirname(gitDir));
15796
- if (path2.basename(commonGitDir) !== ".git")
15894
+ const commonGitDir = path3.dirname(path3.dirname(gitDir));
15895
+ if (path3.basename(commonGitDir) !== ".git")
15797
15896
  return;
15798
- const backPointer = readText(path2.join(gitDir, "gitdir"));
15799
- const commonPointer = readText(path2.join(gitDir, "commondir"));
15897
+ const backPointer = readText(path3.join(gitDir, "gitdir"));
15898
+ const commonPointer = readText(path3.join(gitDir, "commondir"));
15800
15899
  if (backPointer === undefined || commonPointer === undefined)
15801
15900
  return;
15802
- const linkedGitEntry = path2.resolve(gitDir, backPointer.trim());
15803
- const declaredCommonDir = path2.resolve(gitDir, commonPointer.trim());
15901
+ const linkedGitEntry = path3.resolve(gitDir, backPointer.trim());
15902
+ const declaredCommonDir = path3.resolve(gitDir, commonPointer.trim());
15804
15903
  if (!backPointer.trim() || !commonPointer.trim())
15805
15904
  return;
15806
15905
  if (!samePath(linkedGitEntry, gitEntry) || !samePath(declaredCommonDir, commonGitDir))
15807
15906
  return;
15808
- return path2.dirname(commonGitDir);
15907
+ return path3.dirname(commonGitDir);
15809
15908
  }
15810
15909
  function findCanonicalGitRoot(cwd) {
15811
15910
  const repoRoot = findGitRoot(cwd);
@@ -15814,33 +15913,31 @@ function findCanonicalGitRoot(cwd) {
15814
15913
  var init_worktree_root = () => {};
15815
15914
 
15816
15915
  // dist/builtin/workflows/src/runs/shared/worktree-git.ts
15817
- import * as fs3 from "node:fs";
15818
- import * as path3 from "node:path";
15819
- function gitWorktreeSetupCacheKey(options) {
15820
- const repoRoot = repositoryRootForGitWorktree(options.cwd);
15821
- const { logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
15822
- const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
15916
+ import * as fs4 from "node:fs";
15917
+ import * as path4 from "node:path";
15918
+ function gitWorktreeSetupCacheKey(request) {
15823
15919
  return JSON.stringify([
15824
- comparableRealPath(gitCommonDirForWorktree(repoRoot)),
15825
- comparablePathThroughExistingAncestor(worktreeRoot)
15920
+ comparablePathThroughExistingAncestor(request.options.cwd),
15921
+ comparablePathThroughExistingAncestor(request.target)
15826
15922
  ]);
15827
15923
  }
15828
- function createGitWorktreeSetupCache() {
15924
+ function createGitWorktreeSetupCache(ownerRunId) {
15829
15925
  const results = new Map;
15830
15926
  let disposed = false;
15831
15927
  return {
15832
15928
  get(options) {
15833
15929
  if (disposed)
15834
15930
  throw new Error("Git worktree setup cache is already disposed");
15835
- const key = gitWorktreeSetupCacheKey(options);
15931
+ const request = resolveGitWorktreeSetupRequest(options);
15932
+ const key = gitWorktreeSetupCacheKey(request);
15836
15933
  const cached = results.get(key);
15837
15934
  if (cached !== undefined) {
15838
15935
  assertCachedGitWorktreeIdentity(cached, options);
15839
15936
  return cached.result;
15840
15937
  }
15841
- const result = setupGitWorktree(options);
15842
- results.set(key, { result, identity: captureGitWorktreeIdentity(result) });
15843
- return result;
15938
+ const setup = setupGitWorktreeFromRequest(request, ownerRunId);
15939
+ results.set(key, { ...setup, identity: captureGitWorktreeIdentity(setup) });
15940
+ return setup.result;
15844
15941
  },
15845
15942
  dispose() {
15846
15943
  if (disposed)
@@ -15872,10 +15969,10 @@ function worktreeRecoveryCommand(repositoryRoot, worktreeDir) {
15872
15969
  return `git -C ${quoteShellArg(repositoryRoot)} worktree remove --force ${quoteShellArg(worktreeDir)}`;
15873
15970
  }
15874
15971
  function hasGrandparent(value2) {
15875
- const parent = path3.dirname(value2);
15972
+ const parent = path4.dirname(value2);
15876
15973
  if (parent === value2)
15877
15974
  return false;
15878
- const grandparent = path3.dirname(parent);
15975
+ const grandparent = path4.dirname(parent);
15879
15976
  return grandparent !== parent;
15880
15977
  }
15881
15978
  function pathAncestors(value2) {
@@ -15883,7 +15980,7 @@ function pathAncestors(value2) {
15883
15980
  let current = value2;
15884
15981
  while (true) {
15885
15982
  ancestors.push(current);
15886
- const parent = path3.dirname(current);
15983
+ const parent = path4.dirname(current);
15887
15984
  if (parent === current)
15888
15985
  return ancestors;
15889
15986
  current = parent;
@@ -15892,89 +15989,167 @@ function pathAncestors(value2) {
15892
15989
  function shouldPreserveLogicalPath(logicalPath) {
15893
15990
  return pathAncestors(logicalPath).some((ancestor) => {
15894
15991
  try {
15895
- return fs3.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
15992
+ return fs4.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
15896
15993
  } catch {
15897
15994
  return false;
15898
15995
  }
15899
15996
  });
15900
15997
  }
15901
15998
  function canonicalizePreservingSymlinks(value2) {
15902
- const logicalPath = path3.resolve(value2);
15999
+ const logicalPath = path4.resolve(value2);
15903
16000
  const preserveLogicalPath = shouldPreserveLogicalPath(logicalPath);
15904
16001
  try {
15905
- const canonical = fs3.realpathSync.native(logicalPath);
16002
+ const canonical = fs4.realpathSync.native(logicalPath);
15906
16003
  return preserveLogicalPath && canonical !== logicalPath ? logicalPath : canonical;
15907
16004
  } catch {
15908
16005
  return logicalPath;
15909
16006
  }
15910
16007
  }
15911
- function resolveGitWorktreePath(value2, repoRoot) {
16008
+ function resolveGitWorktreePath(value2, baseDir) {
15912
16009
  const trimmed = value2.trim();
15913
16010
  if (!trimmed)
15914
16011
  throw new Error("gitWorktreeDir cannot be empty");
15915
16012
  if (trimmed.includes("\x00")) {
15916
16013
  throw new Error("gitWorktreeDir contains an unusable null byte; provide a valid path or omit gitWorktreeDir.");
15917
16014
  }
15918
- return canonicalizePreservingSymlinks(path3.isAbsolute(trimmed) ? trimmed : path3.resolve(repoRoot, trimmed));
16015
+ return canonicalizePreservingSymlinks(path4.isAbsolute(trimmed) ? trimmed : path4.resolve(baseDir, trimmed));
15919
16016
  }
15920
16017
  function comparableRealPath(value2) {
15921
- const realpath = fs3.realpathSync.native(value2).replace(/\\/g, "/");
16018
+ const realpath = fs4.realpathSync.native(value2).replace(/\\/g, "/");
15922
16019
  return process.platform === "win32" ? realpath.toLowerCase() : realpath;
15923
16020
  }
15924
- function comparablePathThroughExistingAncestor(value2) {
15925
- let existing = path3.resolve(value2);
16021
+ function nearestExistingAncestor(value2) {
16022
+ let existing = path4.resolve(value2);
15926
16023
  const missing = [];
15927
16024
  while (!pathExistsSync(existing)) {
15928
- const parent = path3.dirname(existing);
16025
+ const parent = path4.dirname(existing);
15929
16026
  if (parent === existing)
15930
16027
  break;
15931
- missing.unshift(path3.basename(existing));
16028
+ missing.unshift(path4.basename(existing));
15932
16029
  existing = parent;
15933
16030
  }
15934
- const resolved = path3.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
16031
+ return { existing, missing };
16032
+ }
16033
+ function comparablePathThroughExistingAncestor(value2) {
16034
+ const { existing, missing } = nearestExistingAncestor(value2);
16035
+ const resolved = path4.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
15935
16036
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
15936
16037
  }
16038
+ function isFileOrLink(value2) {
16039
+ try {
16040
+ const entry = fs4.lstatSync(value2);
16041
+ return entry.isFile() || entry.isSymbolicLink();
16042
+ } catch {
16043
+ return false;
16044
+ }
16045
+ }
16046
+ function isDirectory(value2) {
16047
+ try {
16048
+ return fs4.statSync(value2).isDirectory();
16049
+ } catch {
16050
+ return false;
16051
+ }
16052
+ }
16053
+ function looksLikeGitDirectory(directory) {
16054
+ if (!isDirectory(directory))
16055
+ return false;
16056
+ if (path4.basename(directory) === ".git")
16057
+ return true;
16058
+ if (!isFileOrLink(path4.join(directory, "HEAD")))
16059
+ return false;
16060
+ if (isFileOrLink(path4.join(directory, "commondir")))
16061
+ return true;
16062
+ return isDirectory(path4.join(directory, "objects")) && isDirectory(path4.join(directory, "refs"));
16063
+ }
16064
+ function enclosingGitMetadataDirectory(target) {
16065
+ const { existing } = nearestExistingAncestor(target);
16066
+ let realExisting = existing;
16067
+ try {
16068
+ realExisting = fs4.realpathSync.native(existing);
16069
+ } catch {}
16070
+ for (const candidate of new Set([...pathAncestors(existing), ...pathAncestors(realExisting)])) {
16071
+ if (looksLikeGitDirectory(candidate))
16072
+ return candidate;
16073
+ }
16074
+ const insideGitDir = runGitReadOnlyProbe(existing, ["rev-parse", "--is-inside-git-dir"]);
16075
+ if (insideGitDir.status !== 0 && isGitTimeoutResult(insideGitDir)) {
16076
+ throw new Error(`Timed out while validating gitWorktreeDir ${target}. Git reported: ${gitFailureMessage(insideGitDir)}`);
16077
+ }
16078
+ return insideGitDir.status === 0 && insideGitDir.stdout.trim() === "true" ? existing : undefined;
16079
+ }
16080
+ function assertSafeGitWorktreeTarget(target, invokingRoot) {
16081
+ const gitDirectory = enclosingGitMetadataDirectory(target);
16082
+ if (gitDirectory !== undefined) {
16083
+ 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.`);
16084
+ }
16085
+ if (invokingRoot !== undefined)
16086
+ validateWorktreeOutsideInvokingCheckout(target, invokingRoot);
16087
+ const { existing, missing } = nearestExistingAncestor(target);
16088
+ const workingTree = gitTopLevel(existing);
16089
+ if (workingTree === undefined)
16090
+ return;
16091
+ if (missing.length === 0 && comparableRealPath(target) === comparableRealPath(workingTree))
16092
+ return;
16093
+ 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.`);
16094
+ }
15937
16095
  function validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot) {
15938
16096
  const repository = comparableRealPath(repoRoot);
15939
16097
  const candidate = comparablePathThroughExistingAncestor(worktreeRoot);
15940
- const relativePath = path3.relative(repository, candidate);
16098
+ const relativePath = path4.relative(repository, candidate);
15941
16099
  if (relativePath === "") {
15942
- throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate same-repository worktree path.");
16100
+ throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate worktree path outside it.");
15943
16101
  }
15944
- if (!relativePath.startsWith(`..${path3.sep}`) && relativePath !== ".." && !path3.isAbsolute(relativePath)) {
15945
- throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate same-repository worktree path.");
16102
+ if (!relativePath.startsWith(`..${path4.sep}`) && relativePath !== ".." && !path4.isAbsolute(relativePath)) {
16103
+ throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate worktree path outside it.");
15946
16104
  }
15947
16105
  }
15948
16106
  function gitPathFromOutput(value2, cwd) {
15949
16107
  const trimmed = value2.trim();
15950
16108
  if (!trimmed)
15951
16109
  return;
15952
- return path3.isAbsolute(trimmed) ? path3.resolve(trimmed) : path3.resolve(cwd, trimmed);
16110
+ return path4.isAbsolute(trimmed) ? path4.resolve(trimmed) : path4.resolve(cwd, trimmed);
15953
16111
  }
15954
16112
  function pathExistsSync(value2) {
16113
+ return pathStatSync(value2) !== undefined;
16114
+ }
16115
+ function pathStatSync(value2) {
15955
16116
  try {
15956
- fs3.statSync(value2);
15957
- return true;
16117
+ return fs4.statSync(value2);
15958
16118
  } catch (error) {
15959
16119
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
15960
16120
  if (code === "ENOENT" || code === "ENOTDIR")
15961
- return false;
16121
+ return;
15962
16122
  throw error;
15963
16123
  }
15964
16124
  }
15965
- function repositoryRootForGitWorktree(cwd) {
16125
+ function probeInvokingRepository(cwd) {
15966
16126
  const result = runGitReadOnlyProbe(cwd, ["rev-parse", "--show-toplevel"]);
15967
16127
  if (result.status !== 0) {
15968
16128
  if (isGitTimeoutResult(result)) {
15969
16129
  throw new Error(`Timed out while checking the Git repository for gitWorktreeDir from ${cwd}. Git reported: ${gitFailureMessage(result)}`);
15970
16130
  }
15971
- 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)}`);
16131
+ return { failure: gitFailureMessage(result) };
15972
16132
  }
15973
- const normalized = gitPathFromOutput(result.stdout, cwd);
15974
- if (normalized === undefined) {
16133
+ const root = gitPathFromOutput(result.stdout, cwd);
16134
+ if (root === undefined) {
15975
16135
  throw new Error(`gitWorktreeDir could not resolve the repository top level from ${cwd}: git returned an empty path.`);
15976
16136
  }
15977
- return normalized;
16137
+ return { repository: { root, ...cwdWithinGitRepository(cwd, root) } };
16138
+ }
16139
+ function resolveGitWorktreeSetupRequest(options) {
16140
+ const probe = probeInvokingRepository(options.cwd);
16141
+ if ("repository" in probe) {
16142
+ return {
16143
+ options,
16144
+ repository: probe.repository,
16145
+ target: resolveGitWorktreePath(options.gitWorktreeDir, probe.repository.logicalRoot)
16146
+ };
16147
+ }
16148
+ return {
16149
+ options,
16150
+ repositoryProbeFailure: probe.failure,
16151
+ target: resolveGitWorktreePath(options.gitWorktreeDir, canonicalizePreservingSymlinks(options.cwd))
16152
+ };
15978
16153
  }
15979
16154
  function gitTopLevelFromResult(result, cwd, description) {
15980
16155
  if (result.status !== 0) {
@@ -16010,25 +16185,25 @@ function dirnameForEachRelativeComponent(base, relativePath) {
16010
16185
  continue;
16011
16186
  if (component === "..")
16012
16187
  return;
16013
- current = path3.dirname(current);
16188
+ current = path4.dirname(current);
16014
16189
  }
16015
16190
  return current;
16016
16191
  }
16017
16192
  function cwdWithinGitRepository(cwd, repoRoot) {
16018
- const sourceCwd = fs3.realpathSync.native(cwd);
16019
- const sourceRepoRoot = fs3.realpathSync.native(repoRoot);
16020
- const relativeCwd = path3.relative(sourceRepoRoot, sourceCwd);
16021
- const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path3.isAbsolute(relativeCwd) ? "" : relativeCwd;
16193
+ const sourceCwd = fs4.realpathSync.native(cwd);
16194
+ const sourceRepoRoot = fs4.realpathSync.native(repoRoot);
16195
+ const relativeCwd = path4.relative(sourceRepoRoot, sourceCwd);
16196
+ const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path4.isAbsolute(relativeCwd) ? "" : relativeCwd;
16022
16197
  const logicalCwd = canonicalizePreservingSymlinks(cwd);
16023
16198
  return {
16024
16199
  relativeCwd: safeRelativeCwd,
16025
- logicalRepoRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
16200
+ logicalRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
16026
16201
  };
16027
16202
  }
16028
16203
  function workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd) {
16029
- return relativeCwd === "" ? worktreeRoot : path3.join(worktreeRoot, relativeCwd);
16204
+ return relativeCwd === "" ? worktreeRoot : path4.join(worktreeRoot, relativeCwd);
16030
16205
  }
16031
- function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
16206
+ function validateGitWorktreeRoot(worktreeRoot) {
16032
16207
  const topLevel = gitTopLevel(worktreeRoot);
16033
16208
  if (topLevel === undefined) {
16034
16209
  throw new Error(`gitWorktreeDir already exists but is not a Git worktree: ${worktreeRoot}`);
@@ -16036,8 +16211,18 @@ function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
16036
16211
  if (comparableRealPath(worktreeRoot) !== comparableRealPath(topLevel)) {
16037
16212
  throw new Error(`gitWorktreeDir already exists but is not a Git worktree root: ${worktreeRoot}. Git top-level checkout is ${topLevel}`);
16038
16213
  }
16039
- if (comparableRealPath(gitCommonDirForWorktree(repoRoot)) !== comparableRealPath(gitCommonDirForWorktree(topLevel))) {
16040
- throw new Error(`gitWorktreeDir already exists but does not belong to the invoking Git repository: ${worktreeRoot}`);
16214
+ return gitCommonDirForWorktree(topLevel);
16215
+ }
16216
+ function existingGitWorktreeCommonDir(directory) {
16217
+ return gitTopLevel(directory) === undefined ? undefined : validateGitWorktreeRoot(directory);
16218
+ }
16219
+ function sameGitCommonDir(left, right) {
16220
+ return comparableRealPath(left) === comparableRealPath(right);
16221
+ }
16222
+ function validateCreatedGitWorktree(worktreeRoot, repository) {
16223
+ assertSafeGitWorktreeTarget(worktreeRoot, repository.root);
16224
+ if (!sameGitCommonDir(validateGitWorktreeRoot(worktreeRoot), gitCommonDirForWorktree(repository.root))) {
16225
+ throw new Error(`gitWorktreeDir does not belong to the invoking Git repository: ${worktreeRoot}`);
16041
16226
  }
16042
16227
  }
16043
16228
  function gitDirectoryForWorktree(cwd) {
@@ -16051,26 +16236,27 @@ function gitDirectoryForWorktree(cwd) {
16051
16236
  return gitDir;
16052
16237
  }
16053
16238
  function captureGitWorktreeIdentitySnapshot(setup) {
16054
- validateWorktreeOutsideInvokingCheckout(setup.worktreeRoot, setup.repositoryRoot);
16055
- validateExistingGitWorktreeRoot(setup.worktreeRoot, setup.repositoryRoot);
16056
- const stats = fs3.statSync(setup.worktreeRoot);
16239
+ const { worktreeRoot, repositoryRoot } = setup.result;
16240
+ assertSafeGitWorktreeTarget(worktreeRoot, setup.invokingRoot);
16241
+ const commonDir = validateGitWorktreeRoot(worktreeRoot);
16242
+ const stats = fs4.statSync(worktreeRoot);
16057
16243
  return {
16058
- worktreeRealPath: comparableRealPath(setup.worktreeRoot),
16059
- repositoryRealPath: comparableRealPath(setup.repositoryRoot),
16060
- gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(setup.worktreeRoot)),
16061
- commonDirRealPath: comparableRealPath(gitCommonDirForWorktree(setup.worktreeRoot)),
16244
+ worktreeRealPath: comparableRealPath(worktreeRoot),
16245
+ repositoryRealPath: comparableRealPath(repositoryRoot),
16246
+ gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(worktreeRoot)),
16247
+ commonDirRealPath: comparableRealPath(commonDir),
16062
16248
  device: stats.dev,
16063
16249
  inode: stats.ino
16064
16250
  };
16065
16251
  }
16066
16252
  function captureGitWorktreeIdentity(setup) {
16067
16253
  const snapshot = captureGitWorktreeIdentitySnapshot(setup);
16068
- return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.worktreeRoot) };
16254
+ return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.result.worktreeRoot) };
16069
16255
  }
16070
16256
  function assertCachedGitWorktreeIdentity(cached, options) {
16071
16257
  let current;
16072
16258
  try {
16073
- current = captureGitWorktreeIdentitySnapshot(cached.result);
16259
+ current = captureGitWorktreeIdentitySnapshot(cached);
16074
16260
  cached.identity.generation.assertCurrent();
16075
16261
  } catch (error) {
16076
16262
  const message = error instanceof Error ? error.message : String(error);
@@ -16078,34 +16264,58 @@ function assertCachedGitWorktreeIdentity(cached, options) {
16078
16264
  }
16079
16265
  const expected = cached.identity;
16080
16266
  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) {
16081
- throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended same-repository worktree.`);
16082
- }
16267
+ throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended worktree.`);
16268
+ }
16269
+ }
16270
+ function requireInvokingRepository(request, action) {
16271
+ if (request.repository !== undefined)
16272
+ return request.repository;
16273
+ throw new Error([
16274
+ `gitWorktreeDir requires the workflow to be invoked from inside a Git repository to ${action}.`,
16275
+ "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.",
16276
+ `Git reported: ${request.repositoryProbeFailure ?? "no repository"}`
16277
+ ].join(" "));
16278
+ }
16279
+ function setupGitWorktreeFromRequest(request, ownerRunId) {
16280
+ const { repository, target } = request;
16281
+ assertSafeGitWorktreeTarget(target, repository?.root);
16282
+ const entry = pathStatSync(target);
16283
+ if (entry === undefined)
16284
+ return createGitWorktreeAtPath(request, false);
16285
+ if (!entry.isDirectory())
16286
+ throw new Error(`gitWorktreeDir already exists but is not a directory: ${target}`);
16287
+ if (fs4.readdirSync(target).length === 0)
16288
+ return createGitWorktreeAtPath(request, true);
16289
+ const commonDir = existingGitWorktreeCommonDir(target);
16290
+ if (commonDir === undefined)
16291
+ return allocateGitWorktree(request, ownerRunId);
16292
+ const sameRepository = repository !== undefined && sameGitCommonDir(commonDir, gitCommonDirForWorktree(repository.root));
16293
+ return {
16294
+ result: {
16295
+ worktreeRoot: target,
16296
+ cwd: sameRepository ? workspaceCwdForGitWorktreeRoot(target, repository.relativeCwd) : target,
16297
+ repositoryRoot: sameRepository ? repository.root : target,
16298
+ created: false
16299
+ },
16300
+ ...repository !== undefined ? { invokingRoot: repository.root } : {}
16301
+ };
16083
16302
  }
16084
- function setupGitWorktree(options) {
16085
- const repoRoot = repositoryRootForGitWorktree(options.cwd);
16086
- const mainRoot = findCanonicalGitRoot(repoRoot);
16303
+ function createGitWorktreeAtPath(request, existingEmptyDirectory) {
16304
+ const { target: worktreeRoot } = request;
16305
+ const repository = requireInvokingRepository(request, `create a new worktree at ${worktreeRoot}`);
16306
+ const mainRoot = findCanonicalGitRoot(repository.root);
16087
16307
  if (mainRoot === undefined) {
16088
- throw new Error(`Unable to resolve the canonical main Git repository root from ${repoRoot}.`);
16089
- }
16090
- const { relativeCwd, logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
16091
- const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
16092
- validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot);
16093
- if (pathExistsSync(worktreeRoot)) {
16094
- validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
16095
- return {
16096
- worktreeRoot,
16097
- cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
16098
- repositoryRoot: repoRoot,
16099
- created: false
16100
- };
16308
+ throw new Error(`Unable to resolve the canonical main Git repository root from ${repository.root}.`);
16101
16309
  }
16102
- try {
16103
- fs3.mkdirSync(path3.dirname(worktreeRoot), { recursive: true });
16104
- } catch (error) {
16105
- const message = error instanceof Error ? error.message : String(error);
16106
- throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
16310
+ if (!existingEmptyDirectory) {
16311
+ try {
16312
+ fs4.mkdirSync(path4.dirname(worktreeRoot), { recursive: true });
16313
+ } catch (error) {
16314
+ const message = error instanceof Error ? error.message : String(error);
16315
+ throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
16316
+ }
16107
16317
  }
16108
- const baseRef = options.baseBranch?.trim() || "HEAD";
16318
+ const baseRef = request.options.baseBranch?.trim() || "HEAD";
16109
16319
  const result = runGit(mainRoot, ["worktree", "add", "--detach", worktreeRoot, baseRef]);
16110
16320
  if (result.status !== 0) {
16111
16321
  throw new Error([
@@ -16115,30 +16325,127 @@ function setupGitWorktree(options) {
16115
16325
  `));
16116
16326
  }
16117
16327
  try {
16118
- validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot);
16119
- validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
16328
+ validateCreatedGitWorktree(worktreeRoot, repository);
16120
16329
  } catch (error) {
16121
16330
  runGit(mainRoot, ["worktree", "remove", "--force", worktreeRoot]);
16122
16331
  const message = error instanceof Error ? error.message : String(error);
16123
16332
  throw new Error(`Created gitWorktreeDir failed post-creation validation: ${message}`);
16124
16333
  }
16125
16334
  return {
16126
- worktreeRoot,
16127
- cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
16128
- repositoryRoot: repoRoot,
16129
- created: true
16335
+ result: {
16336
+ worktreeRoot,
16337
+ cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, repository.relativeCwd),
16338
+ repositoryRoot: repository.root,
16339
+ created: true
16340
+ },
16341
+ invokingRoot: repository.root
16342
+ };
16343
+ }
16344
+ function containedWorktreeCwd(checkout, relativeCwd) {
16345
+ const cwd = workspaceCwdForGitWorktreeRoot(checkout, relativeCwd);
16346
+ let resolved;
16347
+ try {
16348
+ resolved = fs4.realpathSync.native(cwd);
16349
+ } catch {
16350
+ resolved = "";
16351
+ }
16352
+ const relative2 = resolved === "" ? undefined : path4.relative(fs4.realpathSync.native(checkout), resolved);
16353
+ if (relative2 === undefined || relative2 === ".." || relative2.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative2) || !fs4.statSync(resolved).isDirectory()) {
16354
+ throw new Error(`The selected base does not contain a working directory ${relativeCwd || "."} inside the worktree ${checkout}.`);
16355
+ }
16356
+ return cwd;
16357
+ }
16358
+ function allocatedGitWorktreeSetup(checkout, repository, created) {
16359
+ return {
16360
+ result: {
16361
+ worktreeRoot: checkout,
16362
+ cwd: containedWorktreeCwd(checkout, repository.relativeCwd),
16363
+ repositoryRoot: repository.root,
16364
+ created
16365
+ },
16366
+ invokingRoot: repository.root
16130
16367
  };
16131
16368
  }
16369
+ function validateOwnedGitWorktree(checkout, repository) {
16370
+ validateCreatedGitWorktree(checkout, repository);
16371
+ const gitDir = gitDirectoryForWorktree(checkout);
16372
+ if (sameGitCommonDir(gitDir, gitCommonDirForWorktree(checkout))) {
16373
+ throw new Error(`${checkout} is not a linked worktree`);
16374
+ }
16375
+ const backlink = fs4.readFileSync(path4.join(gitDir, "gitdir"), "utf8").trim();
16376
+ if (!backlink || comparableRealPath(path4.resolve(gitDir, backlink)) !== comparableRealPath(path4.join(checkout, ".git"))) {
16377
+ throw new Error(`the Git directory of ${checkout} belongs to another checkout`);
16378
+ }
16379
+ }
16380
+ function findOwnedGitWorktree(root, repository, ownerRunId) {
16381
+ const [checkout] = findOwnedWorktreeCheckouts(root, path4.basename(repository.root), ownerRunId);
16382
+ if (checkout === undefined)
16383
+ return;
16384
+ try {
16385
+ validateOwnedGitWorktree(checkout, repository);
16386
+ return allocatedGitWorktreeSetup(checkout, repository, false);
16387
+ } catch (error) {
16388
+ const message = error instanceof Error ? error.message : String(error);
16389
+ throw new Error(`The worktree this workflow run allocated under gitWorktreeDir ${root} can no longer be reused: ${checkout}. ${message}`);
16390
+ }
16391
+ }
16392
+ function allocateGitWorktree(request, ownerRunId) {
16393
+ const { target: root } = request;
16394
+ const repository = requireInvokingRepository(request, `create a new worktree under ${root}`);
16395
+ if (ownerRunId !== undefined) {
16396
+ const owned = findOwnedGitWorktree(root, repository, ownerRunId);
16397
+ if (owned !== undefined)
16398
+ return owned;
16399
+ }
16400
+ const baseRef = request.options.baseBranch?.trim() || "HEAD";
16401
+ const revision = runGit(repository.root, ["rev-parse", "--verify", "--end-of-options", `${baseRef}^{commit}`]);
16402
+ const commit = revision.status === 0 ? revision.stdout.trim() : "";
16403
+ if (commit === "") {
16404
+ throw new Error(`Failed to resolve ${baseRef} to a commit for gitWorktreeDir ${root}. Git reported: ${gitFailureMessage(revision)}`);
16405
+ }
16406
+ const checkout = allocateWorktreeCheckoutPath(root, path4.basename(repository.root));
16407
+ const add = runGit(repository.root, ["worktree", "add", "--detach", "--no-checkout", checkout, commit]);
16408
+ if (add.status !== 0) {
16409
+ removeEmptyWorktreeBucket(checkout);
16410
+ throw new Error(`Failed to create git worktree at ${checkout} under gitWorktreeDir ${root} from ${baseRef}. Git reported: ${gitFailureMessage(add)}`);
16411
+ }
16412
+ try {
16413
+ const gitDir = gitDirectoryForWorktree(checkout);
16414
+ runGitOrThrow(checkout, ["config", "--file", path4.join(gitDir, "config.worktree"), "core.worktree", checkout]);
16415
+ runGitOrThrow(checkout, ["--work-tree=.", "reset", "--hard", "--no-recurse-submodules", commit]);
16416
+ validateCreatedGitWorktree(checkout, repository);
16417
+ const setup = allocatedGitWorktreeSetup(checkout, repository, true);
16418
+ if (ownerRunId !== undefined)
16419
+ bindWorktreeOwner(gitDir, ownerRunId);
16420
+ return setup;
16421
+ } catch (error) {
16422
+ const message = error instanceof Error ? error.message : String(error);
16423
+ const removal = runGit(repository.root, ["worktree", "remove", "--force", checkout]);
16424
+ removeEmptyWorktreeBucket(checkout);
16425
+ const rollback = removal.status === 0 ? "" : ` Rolling back the incomplete worktree also failed; remove it with: ${worktreeRecoveryCommand(repository.root, checkout)}`;
16426
+ throw new Error(`Failed to set up git worktree at ${checkout} under gitWorktreeDir ${root}: ${message}${rollback}`);
16427
+ }
16428
+ }
16429
+ function runGitOrThrow(cwd, args) {
16430
+ const result = runGit(cwd, args);
16431
+ if (result.status !== 0)
16432
+ throw new Error(gitFailureMessage(result));
16433
+ }
16434
+ function setupGitWorktree(options) {
16435
+ return setupGitWorktreeFromRequest(resolveGitWorktreeSetupRequest(options)).result;
16436
+ }
16132
16437
  var init_worktree_git = __esm(() => {
16438
+ init_worktree_allocation();
16133
16439
  init_worktree_generation();
16134
16440
  init_worktree_git_runner();
16135
16441
  init_worktree_root();
16442
+ init_worktree_allocation();
16136
16443
  init_worktree_git_runner();
16137
16444
  });
16138
16445
 
16139
16446
  // dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts
16140
- function createGitWorktreeSetupCacheOwner(suppliedCache) {
16141
- const cache = suppliedCache ?? createGitWorktreeSetupCache();
16447
+ function createGitWorktreeSetupCacheOwner(suppliedCache, ownerRunId) {
16448
+ const cache = suppliedCache ?? createGitWorktreeSetupCache(ownerRunId);
16142
16449
  const ownsCache = suppliedCache === undefined;
16143
16450
  let released = false;
16144
16451
  return {
@@ -16159,20 +16466,20 @@ var init_worktree_cache_lifecycle = __esm(() => {
16159
16466
  });
16160
16467
 
16161
16468
  // dist/builtin/workflows/src/runs/shared/worktree-diff.ts
16162
- import * as fs4 from "node:fs";
16163
- import * as path4 from "node:path";
16469
+ import * as fs5 from "node:fs";
16470
+ import * as path5 from "node:path";
16164
16471
  function safePatchAgentName(agent) {
16165
16472
  return agent.replace(/[^\w.-]/g, "_");
16166
16473
  }
16167
16474
  function removeSyntheticPath(worktree, syntheticPath) {
16168
- const resolved = path4.resolve(worktree.path, syntheticPath);
16169
- const relative = path4.relative(worktree.path, resolved);
16170
- if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative)) {
16475
+ const resolved = path5.resolve(worktree.path, syntheticPath);
16476
+ const relative = path5.relative(worktree.path, resolved);
16477
+ if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path5.sep}`) || path5.isAbsolute(relative)) {
16171
16478
  return;
16172
16479
  }
16173
16480
  let stat;
16174
16481
  try {
16175
- stat = fs4.lstatSync(resolved);
16482
+ stat = fs5.lstatSync(resolved);
16176
16483
  } catch (error) {
16177
16484
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
16178
16485
  if (code === "ENOENT")
@@ -16180,14 +16487,14 @@ function removeSyntheticPath(worktree, syntheticPath) {
16180
16487
  throw error;
16181
16488
  }
16182
16489
  if (stat.isSymbolicLink()) {
16183
- fs4.unlinkSync(resolved);
16490
+ fs5.unlinkSync(resolved);
16184
16491
  return;
16185
16492
  }
16186
16493
  if (stat.isDirectory()) {
16187
- fs4.rmSync(resolved, { recursive: true, force: true });
16494
+ fs5.rmSync(resolved, { recursive: true, force: true });
16188
16495
  return;
16189
16496
  }
16190
- fs4.rmSync(resolved, { force: true });
16497
+ fs5.rmSync(resolved, { force: true });
16191
16498
  }
16192
16499
  function removeSyntheticPathsBeforeDiff(worktree) {
16193
16500
  if (worktree.syntheticPaths.length === 0)
@@ -16236,7 +16543,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
16236
16543
  const diffStat = runGitChecked(worktree.path, ["diff", "--cached", "--stat", setup.baseCommit]).trim();
16237
16544
  const patch = runGitChecked(worktree.path, ["diff", "--cached", setup.baseCommit]);
16238
16545
  const numstat = runGitChecked(worktree.path, ["diff", "--cached", "--numstat", setup.baseCommit]);
16239
- fs4.writeFileSync(patchPath, patch, "utf-8");
16546
+ fs5.writeFileSync(patchPath, patch, "utf-8");
16240
16547
  if (!patch.trim()) {
16241
16548
  return emptyDiff(worktree.index, agent, worktree.branch, patchPath);
16242
16549
  }
@@ -16254,7 +16561,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
16254
16561
  }
16255
16562
  function writeEmptyPatch(patchPath) {
16256
16563
  try {
16257
- fs4.writeFileSync(patchPath, "", "utf-8");
16564
+ fs5.writeFileSync(patchPath, "", "utf-8");
16258
16565
  } catch {}
16259
16566
  }
16260
16567
  function hasWorktreeChanges(diff) {
@@ -16262,7 +16569,7 @@ function hasWorktreeChanges(diff) {
16262
16569
  }
16263
16570
  function diffWorktrees(setup, agents, diffsDir) {
16264
16571
  try {
16265
- fs4.mkdirSync(diffsDir, { recursive: true });
16572
+ fs5.mkdirSync(diffsDir, { recursive: true });
16266
16573
  } catch {
16267
16574
  return [];
16268
16575
  }
@@ -16270,7 +16577,7 @@ function diffWorktrees(setup, agents, diffsDir) {
16270
16577
  for (let index = 0;index < setup.worktrees.length; index++) {
16271
16578
  const worktree = setup.worktrees[index];
16272
16579
  const agent = agents[index] ?? `task-${index + 1}`;
16273
- const patchPath = path4.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
16580
+ const patchPath = path5.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
16274
16581
  try {
16275
16582
  diffs.push(captureWorktreeDiff(setup, worktree, agent, patchPath));
16276
16583
  } catch {
@@ -16292,7 +16599,7 @@ function formatWorktreeDiffSummary(diffs) {
16292
16599
  }
16293
16600
  lines.push("");
16294
16601
  }
16295
- const patchesDir = path4.dirname(changed[0].patchPath);
16602
+ const patchesDir = path5.dirname(changed[0].patchPath);
16296
16603
  lines.push(`Full patches: ${patchesDir}`);
16297
16604
  return lines.join(`
16298
16605
  `).trimEnd();
@@ -16302,8 +16609,8 @@ var init_worktree_diff = __esm(() => {
16302
16609
  });
16303
16610
 
16304
16611
  // dist/builtin/workflows/src/runs/shared/worktree-post-create.ts
16305
- import * as fs5 from "node:fs";
16306
- import * as path5 from "node:path";
16612
+ import * as fs6 from "node:fs";
16613
+ import * as path6 from "node:path";
16307
16614
  function tracked(repo, relativePath) {
16308
16615
  const result = runGit(repo, ["ls-files", "--error-unmatch", "--", relativePath]);
16309
16616
  return result.status === 0;
@@ -16323,12 +16630,12 @@ function hasTrackedPathComponent(repo, relativePath) {
16323
16630
  return false;
16324
16631
  }
16325
16632
  function copyUntrackedFile(mainRoot, worktreeRoot, relativePath) {
16326
- const source = path5.join(mainRoot, relativePath);
16327
- const destination = path5.join(worktreeRoot, relativePath);
16328
- if (!fs5.existsSync(source) || fs5.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
16633
+ const source = path6.join(mainRoot, relativePath);
16634
+ const destination = path6.join(worktreeRoot, relativePath);
16635
+ if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
16329
16636
  return false;
16330
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
16331
- fs5.copyFileSync(source, destination);
16637
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
16638
+ fs6.copyFileSync(source, destination);
16332
16639
  return true;
16333
16640
  }
16334
16641
  function propagateLocalSettings(mainRoot, worktreeRoot) {
@@ -16341,14 +16648,14 @@ function propagateLocalSettings(mainRoot, worktreeRoot) {
16341
16648
  return copied;
16342
16649
  }
16343
16650
  function populatedHooksDirectory(mainRoot) {
16344
- const husky = path5.join(mainRoot, ".husky");
16651
+ const husky = path6.join(mainRoot, ".husky");
16345
16652
  try {
16346
- if (fs5.statSync(husky).isDirectory())
16653
+ if (fs6.statSync(husky).isDirectory())
16347
16654
  return husky;
16348
16655
  } catch {}
16349
- const hooks = path5.join(mainRoot, ".git", "hooks");
16656
+ const hooks = path6.join(mainRoot, ".git", "hooks");
16350
16657
  try {
16351
- const populated = fs5.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
16658
+ const populated = fs6.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
16352
16659
  return populated ? hooks : undefined;
16353
16660
  } catch {
16354
16661
  return;
@@ -16359,7 +16666,7 @@ function configureSharedHooksPath(mainRoot) {
16359
16666
  if (desired === undefined)
16360
16667
  return;
16361
16668
  const current = runGitPlain(mainRoot, ["config", "--get", "core.hooksPath"]);
16362
- if (current.status === 0 && path5.resolve(mainRoot, current.stdout.trim()) === desired)
16669
+ if (current.status === 0 && path6.resolve(mainRoot, current.stdout.trim()) === desired)
16363
16670
  return;
16364
16671
  const configured = runGitPlain(mainRoot, ["config", "core.hooksPath", desired]);
16365
16672
  if (configured.status !== 0) {
@@ -16368,10 +16675,10 @@ function configureSharedHooksPath(mainRoot) {
16368
16675
  }
16369
16676
  function normalizeSymlinkDirectory(value2) {
16370
16677
  const trimmed = value2.trim();
16371
- if (!trimmed || path5.isAbsolute(trimmed))
16678
+ if (!trimmed || path6.isAbsolute(trimmed))
16372
16679
  return;
16373
- const normalized = path5.normalize(trimmed);
16374
- if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path5.sep}`))
16680
+ const normalized = path6.normalize(trimmed);
16681
+ if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path6.sep}`))
16375
16682
  return;
16376
16683
  return normalized;
16377
16684
  }
@@ -16381,20 +16688,20 @@ function symlinkConfiguredDirectories(mainRoot, worktreeRoot, directories) {
16381
16688
  const relativePath = normalizeSymlinkDirectory(rawDirectory);
16382
16689
  if (relativePath === undefined || synthetic.includes(relativePath))
16383
16690
  continue;
16384
- const source = path5.join(mainRoot, relativePath);
16385
- const destination = path5.join(worktreeRoot, relativePath);
16386
- if (!fs5.existsSync(source) || fs5.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
16691
+ const source = path6.join(mainRoot, relativePath);
16692
+ const destination = path6.join(worktreeRoot, relativePath);
16693
+ if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
16387
16694
  continue;
16388
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
16695
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
16389
16696
  try {
16390
- fs5.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
16697
+ fs6.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
16391
16698
  synthetic.push(relativePath);
16392
16699
  } catch {}
16393
16700
  }
16394
16701
  return synthetic;
16395
16702
  }
16396
16703
  function copyWorktreeIncludes(mainRoot, worktreeRoot) {
16397
- if (!fs5.existsSync(path5.join(mainRoot, ".worktreeinclude")))
16704
+ if (!fs6.existsSync(path6.join(mainRoot, ".worktreeinclude")))
16398
16705
  return;
16399
16706
  const ignored = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-standard"]);
16400
16707
  const included = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-from=.worktreeinclude"]);
@@ -16404,13 +16711,13 @@ function copyWorktreeIncludes(mainRoot, worktreeRoot) {
16404
16711
  for (const relativePath of included.stdout.split(/\r?\n/).filter(Boolean)) {
16405
16712
  if (!ignoredPaths.has(relativePath) || hasTrackedPathComponent(worktreeRoot, relativePath))
16406
16713
  continue;
16407
- const source = path5.join(mainRoot, relativePath);
16408
- const destination = path5.join(worktreeRoot, relativePath);
16714
+ const source = path6.join(mainRoot, relativePath);
16715
+ const destination = path6.join(worktreeRoot, relativePath);
16409
16716
  try {
16410
- if (!fs5.statSync(source).isFile() || fs5.existsSync(destination))
16717
+ if (!fs6.statSync(source).isFile() || fs6.existsSync(destination))
16411
16718
  continue;
16412
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
16413
- fs5.copyFileSync(source, destination);
16719
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
16720
+ fs6.copyFileSync(source, destination);
16414
16721
  } catch {}
16415
16722
  }
16416
16723
  }
@@ -16427,9 +16734,9 @@ var init_worktree_post_create = __esm(() => {
16427
16734
 
16428
16735
  // dist/builtin/workflows/src/runs/shared/worktree-setup.ts
16429
16736
  import { spawnSync as spawnSync2 } from "node:child_process";
16430
- import * as fs6 from "node:fs";
16737
+ import * as fs7 from "node:fs";
16431
16738
  import * as os from "node:os";
16432
- import * as path6 from "node:path";
16739
+ import * as path7 from "node:path";
16433
16740
  import { createChildProcessEnvironment as createChildProcessEnvironment2 } from "@bastani/atomic";
16434
16741
  function originDefaultBranch(mainRoot) {
16435
16742
  const symbolic = runGit(mainRoot, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]);
@@ -16449,7 +16756,7 @@ function originDefaultBranch(mainRoot) {
16449
16756
  }
16450
16757
  function resolveRepoState(cwd, explicitBaseBranch) {
16451
16758
  const cwdRelative = resolveRepoCwdRelative(cwd);
16452
- const toplevel = path6.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
16759
+ const toplevel = path7.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
16453
16760
  const mainRoot = findCanonicalGitRoot(toplevel);
16454
16761
  if (mainRoot === undefined)
16455
16762
  throw new Error(`unable to resolve canonical main Git repository root from ${toplevel}`);
@@ -16462,9 +16769,9 @@ function resolveRepoState(cwd, explicitBaseBranch) {
16462
16769
  return { toplevel, mainRoot, cwdRelative, baseCommit, baseRef };
16463
16770
  }
16464
16771
  function normalizeComparableCwd(cwd) {
16465
- const resolved = path6.resolve(cwd);
16772
+ const resolved = path7.resolve(cwd);
16466
16773
  try {
16467
- return fs6.realpathSync(resolved);
16774
+ return fs7.realpathSync(resolved);
16468
16775
  } catch {
16469
16776
  return resolved;
16470
16777
  }
@@ -16475,7 +16782,7 @@ function findWorktreeTaskCwdConflict(tasks, sharedCwd) {
16475
16782
  const task = tasks[index];
16476
16783
  if (!task.cwd)
16477
16784
  continue;
16478
- const taskCwd = path6.isAbsolute(task.cwd) ? task.cwd : path6.resolve(sharedCwd, task.cwd);
16785
+ const taskCwd = path7.isAbsolute(task.cwd) ? task.cwd : path7.resolve(sharedCwd, task.cwd);
16479
16786
  if (normalizeComparableCwd(taskCwd) === normalizedSharedCwd)
16480
16787
  continue;
16481
16788
  return { index, agent: task.agent, cwd: task.cwd };
@@ -16492,12 +16799,12 @@ function buildWorktreeBranch(runId, index) {
16492
16799
  return `worktree-${flattenedWorktreeName(runId, index)}`;
16493
16800
  }
16494
16801
  function buildWorktreePath(mainRoot, runId, index) {
16495
- return path6.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
16802
+ return path7.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
16496
16803
  }
16497
16804
  function ensureWorktreeIgnore(mainRoot) {
16498
- const worktreesRoot = path6.join(mainRoot, ".atomic", "worktrees");
16499
- fs6.mkdirSync(worktreesRoot, { recursive: true });
16500
- fs6.writeFileSync(path6.join(worktreesRoot, ".gitignore"), `*
16805
+ const worktreesRoot = path7.join(mainRoot, ".atomic", "worktrees");
16806
+ fs7.mkdirSync(worktreesRoot, { recursive: true });
16807
+ fs7.writeFileSync(path7.join(worktreesRoot, ".gitignore"), `*
16501
16808
  `, "utf8");
16502
16809
  }
16503
16810
  function resolveRepoCwdRelative(cwd) {
@@ -16506,7 +16813,7 @@ function resolveRepoCwdRelative(cwd) {
16506
16813
  throw new Error("worktree isolation requires a git repository");
16507
16814
  }
16508
16815
  const rawPrefix = runGitChecked(cwd, ["rev-parse", "--show-prefix"]).trim();
16509
- const normalizedPrefix = rawPrefix ? path6.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
16816
+ const normalizedPrefix = rawPrefix ? path7.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
16510
16817
  return normalizedPrefix === "." ? "" : normalizedPrefix;
16511
16818
  }
16512
16819
  function parseHookTimeout(timeoutMs) {
@@ -16524,19 +16831,19 @@ function resolveWorktreeSetupHook(repoRoot, config) {
16524
16831
  if (!hookPath) {
16525
16832
  throw new Error("worktree setup hook path cannot be empty");
16526
16833
  }
16527
- const expandedHookPath = hookPath.startsWith("~/") ? path6.join(os.homedir(), hookPath.slice(2)) : hookPath;
16834
+ const expandedHookPath = hookPath.startsWith("~/") ? path7.join(os.homedir(), hookPath.slice(2)) : hookPath;
16528
16835
  let resolvedPath;
16529
- if (path6.isAbsolute(expandedHookPath)) {
16836
+ if (path7.isAbsolute(expandedHookPath)) {
16530
16837
  resolvedPath = expandedHookPath;
16531
16838
  } else if (expandedHookPath.includes("/") || expandedHookPath.includes("\\")) {
16532
- resolvedPath = path6.resolve(repoRoot, expandedHookPath);
16839
+ resolvedPath = path7.resolve(repoRoot, expandedHookPath);
16533
16840
  } else {
16534
16841
  throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
16535
16842
  }
16536
- if (!fs6.existsSync(resolvedPath)) {
16843
+ if (!fs7.existsSync(resolvedPath)) {
16537
16844
  throw new Error(`worktree setup hook not found: ${resolvedPath}`);
16538
16845
  }
16539
- if (fs6.statSync(resolvedPath).isDirectory()) {
16846
+ if (fs7.statSync(resolvedPath).isDirectory()) {
16540
16847
  throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
16541
16848
  }
16542
16849
  return {
@@ -16548,17 +16855,17 @@ function normalizeSyntheticPath(worktreePath, rawPath) {
16548
16855
  const trimmed = rawPath.trim();
16549
16856
  if (!trimmed)
16550
16857
  throw new Error("synthetic path cannot be empty");
16551
- if (path6.isAbsolute(trimmed))
16858
+ if (path7.isAbsolute(trimmed))
16552
16859
  throw new Error(`synthetic path must be relative: ${rawPath}`);
16553
- const resolved = path6.resolve(worktreePath, trimmed);
16554
- const relative = path6.relative(worktreePath, resolved);
16860
+ const resolved = path7.resolve(worktreePath, trimmed);
16861
+ const relative = path7.relative(worktreePath, resolved);
16555
16862
  if (!relative || relative === ".") {
16556
16863
  throw new Error(`synthetic path cannot target the worktree root: ${rawPath}`);
16557
16864
  }
16558
- if (relative === ".." || relative.startsWith(`..${path6.sep}`) || path6.isAbsolute(relative)) {
16865
+ if (relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative)) {
16559
16866
  throw new Error(`synthetic path escapes the worktree root: ${rawPath}`);
16560
16867
  }
16561
- return path6.normalize(relative);
16868
+ return path7.normalize(relative);
16562
16869
  }
16563
16870
  function hasTrackedEntries(worktreePath, relativePath) {
16564
16871
  const result = runGit(worktreePath, ["ls-files", "--", relativePath]);
@@ -16630,16 +16937,16 @@ function waitForGitLockRelease() {
16630
16937
  }
16631
16938
  function unlinkWorktreeLinks(worktreePath, relativePaths) {
16632
16939
  for (const relativePath of new Set(relativePaths)) {
16633
- const target = path6.resolve(worktreePath, relativePath);
16634
- const relative = path6.relative(worktreePath, target);
16635
- if (!relative || relative === ".." || relative.startsWith(`..${path6.sep}`) || path6.isAbsolute(relative))
16940
+ const target = path7.resolve(worktreePath, relativePath);
16941
+ const relative = path7.relative(worktreePath, target);
16942
+ if (!relative || relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative))
16636
16943
  continue;
16637
16944
  let current = worktreePath;
16638
- for (const component of relative.split(path6.sep)) {
16639
- current = path6.join(current, component);
16945
+ for (const component of relative.split(path7.sep)) {
16946
+ current = path7.join(current, component);
16640
16947
  let stat;
16641
16948
  try {
16642
- stat = fs6.lstatSync(current);
16949
+ stat = fs7.lstatSync(current);
16643
16950
  } catch (error) {
16644
16951
  const code = error.code;
16645
16952
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -16649,7 +16956,7 @@ function unlinkWorktreeLinks(worktreePath, relativePaths) {
16649
16956
  if (!stat.isSymbolicLink())
16650
16957
  continue;
16651
16958
  if (current === target)
16652
- fs6.unlinkSync(current);
16959
+ fs7.unlinkSync(current);
16653
16960
  break;
16654
16961
  }
16655
16962
  }
@@ -16677,7 +16984,7 @@ function createSingleWorktree(mainRoot, cwdRelative, runId, index, baseRef, base
16677
16984
  cleanupSingleWorktree(mainRoot, { path: worktreePath, branch }, []);
16678
16985
  throw new Error(message);
16679
16986
  }
16680
- const agentCwd = cwdRelative ? path6.join(worktreePath, cwdRelative) : worktreePath;
16987
+ const agentCwd = cwdRelative ? path7.join(worktreePath, cwdRelative) : worktreePath;
16681
16988
  const syntheticPaths = [];
16682
16989
  try {
16683
16990
  syntheticPaths.push(...performPostCreationSetup(mainRoot, worktreePath, symlinkDirectories));
@@ -16746,8 +17053,8 @@ var init_worktree = __esm(() => {
16746
17053
  });
16747
17054
 
16748
17055
  // dist/builtin/workflows/src/runs/shared/worktree-cwd.ts
16749
- import { lstatSync as lstatSync5, realpathSync as realpathSync4 } from "node:fs";
16750
- import { dirname as dirname9, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve7, sep as sep5 } from "node:path";
17056
+ import { lstatSync as lstatSync6, realpathSync as realpathSync4 } from "node:fs";
17057
+ import { dirname as dirname10, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve8, sep as sep5 } from "node:path";
16751
17058
  function relativePathWithin(root, candidate) {
16752
17059
  const path = relative4(root, candidate);
16753
17060
  return path === ".." || path.startsWith(`..${sep5}`) || isAbsolute6(path) ? undefined : path;
@@ -16766,14 +17073,14 @@ function resolveWorktreeStageCwd(cwd, setup) {
16766
17073
  if (cwd === undefined || cwd.length === 0)
16767
17074
  return;
16768
17075
  const absoluteInput = isAbsolute6(cwd);
16769
- const candidate = absoluteInput ? cwd : resolve7(setup.cwd, cwd);
17076
+ const candidate = absoluteInput ? cwd : resolve8(setup.cwd, cwd);
16770
17077
  if (!absoluteInput && relativePathWithin(setup.worktreeRoot, candidate) === undefined) {
16771
17078
  throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a cwd inside the worktree.`);
16772
17079
  }
16773
17080
  const candidateRealPath = existingRealPath(candidate, "cwd");
16774
17081
  const worktreeRelative = relativePathWithin(worktreeRoot, candidateRealPath);
16775
17082
  if (worktreeRelative !== undefined)
16776
- return resolve7(setup.worktreeRoot, worktreeRelative);
17083
+ return resolve8(setup.worktreeRoot, worktreeRelative);
16777
17084
  if (!isAbsolute6(cwd)) {
16778
17085
  throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a path that remains inside the selected worktree.`);
16779
17086
  }
@@ -16782,9 +17089,9 @@ function resolveWorktreeStageCwd(cwd, setup) {
16782
17089
  }
16783
17090
  const repositoryRelative = absoluteInput ? relativePathWithin(repositoryRoot, candidateRealPath) : undefined;
16784
17091
  if (repositoryRelative === undefined) {
16785
- 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.`);
17092
+ 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.`);
16786
17093
  }
16787
- const mappedCwd = resolve7(setup.worktreeRoot, repositoryRelative);
17094
+ const mappedCwd = resolve8(setup.worktreeRoot, repositoryRelative);
16788
17095
  const mappedRealPath = existingRealPath(mappedCwd, "remapped worktree cwd");
16789
17096
  if (relativePathWithin(worktreeRoot, mappedRealPath) === undefined) {
16790
17097
  throw new Error(`atomic-workflows: cwd ${cwd} remaps through a path that resolves outside gitWorktreeDir ${setup.worktreeRoot}; remove the escaping symlink or omit cwd.`);
@@ -16795,7 +17102,7 @@ var init_worktree_cwd = () => {};
16795
17102
 
16796
17103
  // dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts
16797
17104
  import { existsSync as existsSync4 } from "node:fs";
16798
- import { isAbsolute as isAbsolute7, resolve as resolve8 } from "node:path";
17105
+ import { isAbsolute as isAbsolute7, resolve as resolve9 } from "node:path";
16799
17106
  function normalizeTaskContexts(previous) {
16800
17107
  if (previous === undefined)
16801
17108
  return [];
@@ -16848,7 +17155,7 @@ function taskPrevious(options) {
16848
17155
  function resolveWorkflowPath(filePath, baseDir) {
16849
17156
  if (isAbsolute7(filePath))
16850
17157
  return filePath;
16851
- return resolve8(baseDir ?? process.cwd(), filePath);
17158
+ return resolve9(baseDir ?? process.cwd(), filePath);
16852
17159
  }
16853
17160
  function taskBaseDir(options) {
16854
17161
  if (typeof options.chainDir === "string" && options.chainDir.trim().length > 0) {
@@ -17003,7 +17310,7 @@ function taskWithSharedDefaults(taskOptions, options) {
17003
17310
  var init_executor_task_prompts = () => {};
17004
17311
 
17005
17312
  // dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts
17006
- import { isAbsolute as isAbsolute8, join as join11, resolve as resolve9 } from "node:path";
17313
+ import { isAbsolute as isAbsolute8, join as join12, resolve as resolve10 } from "node:path";
17007
17314
  import { CONFIG_DIR_NAME } from "@bastani/atomic";
17008
17315
  function positiveConcurrency(value2) {
17009
17316
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 < 1)
@@ -17156,10 +17463,10 @@ function workflowInvocationMetadata(inputDefaults, workflowInvocationCwd, cache,
17156
17463
  function resolvedTaskCwd(cwd, workflowInvocationCwd) {
17157
17464
  if (cwd === undefined)
17158
17465
  return;
17159
- return isAbsolute8(cwd) ? cwd : resolve9(workflowInvocationCwd, cwd);
17466
+ return isAbsolute8(cwd) ? cwd : resolve10(workflowInvocationCwd, cwd);
17160
17467
  }
17161
17468
  function taskWorktreeOutputsRoot(runId) {
17162
- return join11(workflowArtifactRunPath(runId), "task-outputs");
17469
+ return join12(workflowArtifactRunPath(runId), "task-outputs");
17163
17470
  }
17164
17471
  function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCwd = process.cwd(), symlinkDirectories) {
17165
17472
  if (options.worktree !== true && !tasks.some((task) => task.worktree === true)) {
@@ -17169,7 +17476,7 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
17169
17476
  throw new Error("atomic-workflows: worktree and gitWorktreeDir are mutually exclusive; use gitWorktreeDir for a reusable worktree or worktree:true for temporary isolated worktrees.");
17170
17477
  }
17171
17478
  const explicitCwd = tasks.find((task) => typeof task.cwd === "string")?.cwd;
17172
- const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve9(workflowInvocationCwd, explicitCwd);
17479
+ const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve10(workflowInvocationCwd, explicitCwd);
17173
17480
  const conflict = findWorktreeTaskCwdConflict(tasks.map((task) => ({ agent: task.name, cwd: resolvedTaskCwd(task.cwd, workflowInvocationCwd) })), sharedCwd);
17174
17481
  if (conflict !== undefined)
17175
17482
  throw new Error(formatWorktreeTaskCwdConflict(conflict, sharedCwd));
@@ -17184,9 +17491,9 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
17184
17491
  tasks: tasks.map((task, index) => ({ ...task, cwd: setup.worktrees[index].agentCwd })),
17185
17492
  setup,
17186
17493
  agents,
17187
- diffsDir: join11(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
17494
+ diffsDir: join12(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
17188
17495
  outputIsolations: tasks.map((_, index) => ({
17189
- baseDir: join11(trustedRoot, runId, scope, String(index)),
17496
+ baseDir: join12(trustedRoot, runId, scope, String(index)),
17190
17497
  trustedRoot
17191
17498
  }))
17192
17499
  };
@@ -18628,13 +18935,13 @@ function raceAbort2(operation, signal) {
18628
18935
  }
18629
18936
 
18630
18937
  // dist/builtin/workflows/src/shared/possible-stages.ts
18631
- import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
18632
- import { dirname as dirname10, join as join12, resolve as resolve10 } from "node:path";
18938
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
18939
+ import { dirname as dirname11, join as join13, resolve as resolve11 } from "node:path";
18633
18940
  import { fileURLToPath as fileURLToPath3 } from "node:url";
18634
18941
  function scanPossibleStagesFromSource(entrySourcePath, options = {}) {
18635
18942
  const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
18636
18943
  const scanner = new PossibleStagesScanner(maxDepth);
18637
- scanner.scanSubtree(resolve10(entrySourcePath), "", 0, [resolve10(entrySourcePath)]);
18944
+ scanner.scanSubtree(resolve11(entrySourcePath), "", 0, [resolve11(entrySourcePath)]);
18638
18945
  return {
18639
18946
  hasTrackedNodes: scanner.hasTrackedNodes,
18640
18947
  stages: [...scanner.stages].sort(),
@@ -18645,7 +18952,7 @@ function resolveBuiltinDefinitionSource(name) {
18645
18952
  const builtinDir = fileURLToPath3(new URL("../../builtin/", import.meta.url));
18646
18953
  for (const stem of [name, kebabCase(name)]) {
18647
18954
  for (const extension of [".ts", ".js"]) {
18648
- const candidate = join12(builtinDir, `${stem}${extension}`);
18955
+ const candidate = join13(builtinDir, `${stem}${extension}`);
18649
18956
  if (isFileSync(candidate))
18650
18957
  return candidate;
18651
18958
  }
@@ -18884,7 +19191,7 @@ function templateToPattern(raw) {
18884
19191
  function buildFileUnit(path, warnings) {
18885
19192
  let source;
18886
19193
  try {
18887
- source = readFileSync2(path, "utf-8");
19194
+ source = readFileSync4(path, "utf-8");
18888
19195
  } catch (error) {
18889
19196
  warnings.push(`possible-stages: failed to read ${path}: ${errorMessage2(error)}`);
18890
19197
  return;
@@ -20088,16 +20395,16 @@ function resolveRelativeSpecifier(specifier, importingFile) {
20088
20395
  return;
20089
20396
  const candidates = [];
20090
20397
  if (specifier.endsWith(".js")) {
20091
- candidates.push(join12(dirname10(importingFile), `${specifier.slice(0, -3)}.ts`));
20398
+ candidates.push(join13(dirname11(importingFile), `${specifier.slice(0, -3)}.ts`));
20092
20399
  }
20093
- candidates.push(join12(dirname10(importingFile), specifier), join12(dirname10(importingFile), `${specifier}.ts`), join12(dirname10(importingFile), `${specifier}.js`), join12(dirname10(importingFile), specifier, "index.ts"), join12(dirname10(importingFile), specifier, "index.js"));
20400
+ candidates.push(join13(dirname11(importingFile), specifier), join13(dirname11(importingFile), `${specifier}.ts`), join13(dirname11(importingFile), `${specifier}.js`), join13(dirname11(importingFile), specifier, "index.ts"), join13(dirname11(importingFile), specifier, "index.js"));
20094
20401
  return candidates.find((candidate) => isFileSync(candidate));
20095
20402
  }
20096
20403
  function isFileSync(path) {
20097
20404
  if (!existsSync5(path))
20098
20405
  return false;
20099
20406
  try {
20100
- readFileSync2(path, { flag: "r" });
20407
+ readFileSync4(path, { flag: "r" });
20101
20408
  return true;
20102
20409
  } catch {
20103
20410
  return false;
@@ -20125,7 +20432,7 @@ var init_possible_stages = __esm(() => {
20125
20432
 
20126
20433
  // dist/builtin/workflows/src/workers/admission-host.ts
20127
20434
  import { execFile, execFileSync } from "node:child_process";
20128
- import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
20435
+ import { readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
20129
20436
  import { readFile } from "node:fs/promises";
20130
20437
  import { hostname } from "node:os";
20131
20438
  function admissionBootIdentity() {
@@ -20156,7 +20463,7 @@ function workerProcessExited(pid, final = false) {
20156
20463
  return true;
20157
20464
  if (process.platform === "linux") {
20158
20465
  try {
20159
- const stat = readFileSync3(`/proc/${pid}/stat`, "utf8");
20466
+ const stat = readFileSync5(`/proc/${pid}/stat`, "utf8");
20160
20467
  return stat.slice(stat.lastIndexOf(")") + 2).startsWith("Z");
20161
20468
  } catch {
20162
20469
  return admissionProcessStopped(pid);
@@ -20176,7 +20483,7 @@ function scanProcessGroup(group) {
20176
20483
  let complete = true;
20177
20484
  let entries;
20178
20485
  try {
20179
- entries = readdirSync2("/proc");
20486
+ entries = readdirSync4("/proc");
20180
20487
  } catch {
20181
20488
  return { members, complete: false };
20182
20489
  }
@@ -20185,7 +20492,7 @@ function scanProcessGroup(group) {
20185
20492
  continue;
20186
20493
  let stat;
20187
20494
  try {
20188
- stat = readFileSync3(`/proc/${entry}/stat`, "utf8");
20495
+ stat = readFileSync5(`/proc/${entry}/stat`, "utf8");
20189
20496
  } catch {
20190
20497
  complete = false;
20191
20498
  continue;
@@ -56924,10 +57231,10 @@ var init_verification_prompts = __esm(() => {
56924
57231
  // dist/builtin/workflows/builtin/pattern-artifact-root.ts
56925
57232
  import { randomUUID as randomUUID9 } from "node:crypto";
56926
57233
  import { mkdir as mkdir2 } from "node:fs/promises";
56927
- import { join as join13 } from "node:path";
57234
+ import { join as join14 } from "node:path";
56928
57235
  async function stableArtifactRoot(ctx, workflowName) {
56929
57236
  const cwd = ctx.cwd ?? process.cwd();
56930
- const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join13(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
57237
+ const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join14(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
56931
57238
  await mkdir2(artifactDir, { recursive: true });
56932
57239
  return artifactDir;
56933
57240
  }
@@ -56967,7 +57274,7 @@ function fold_usage(results) {
56967
57274
 
56968
57275
  // dist/builtin/workflows/builtin/adversarial-verification-runner.ts
56969
57276
  import { readFile as readFile2, writeFile } from "node:fs/promises";
56970
- import { join as join14 } from "node:path";
57277
+ import { join as join15 } from "node:path";
56971
57278
  import { Type as Type4 } from "typebox";
56972
57279
  function isRecord3(value2) {
56973
57280
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -57062,8 +57369,8 @@ async function writeInvalid(path, stage) {
57062
57369
  }
57063
57370
  async function runAdversarialVerification(ctx) {
57064
57371
  const root = await stableArtifactRoot(ctx, "adversarial-verification");
57065
- const criteriaPath = join14(root, "criteria.md");
57066
- const candidatePath = join14(root, "candidate.md");
57372
+ const criteriaPath = join15(root, "criteria.md");
57373
+ const candidatePath = join15(root, "candidate.md");
57067
57374
  const resolvedCriteria = resolveCriteria(ctx.inputs.criteria);
57068
57375
  await writeFile(criteriaPath, renderCriteriaMarkdown(resolvedCriteria));
57069
57376
  await ctx.task("worker", { prompt: renderWorkerPrompt(ctx.inputs.task), context: "fresh", output: candidatePath, outputMode: "file-only" });
@@ -57095,7 +57402,7 @@ async function runAdversarialVerification(ctx) {
57095
57402
  criterion,
57096
57403
  verifierIndex: index + 1,
57097
57404
  name,
57098
- artifactPath: join14(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
57405
+ artifactPath: join15(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
57099
57406
  });
57100
57407
  }
57101
57408
  }
@@ -57148,8 +57455,8 @@ async function runAdversarialVerification(ctx) {
57148
57455
  const decision = decide_verification(roundResult, { acceptMean, quorumFraction: QUORUM_FRACTION });
57149
57456
  finalDecision = decision;
57150
57457
  finalMean = meanScore(scoreReports);
57151
- scoreTablePath = join14(root, `verification-summary-${round}.json`);
57152
- reviewReportPath = join14(root, `review-${round}.json`);
57458
+ scoreTablePath = join15(root, `verification-summary-${round}.json`);
57459
+ reviewReportPath = join15(root, `review-${round}.json`);
57153
57460
  const summary = {
57154
57461
  scores: scoreReports,
57155
57462
  mean: finalMean,
@@ -57330,7 +57637,7 @@ var GROUNDED_REPORTING2 = "Before reporting progress, audit each claim against a
57330
57637
 
57331
57638
  // dist/builtin/workflows/builtin/classify-and-act-runner.ts
57332
57639
  import { writeFile as writeFile2 } from "node:fs/promises";
57333
- import { join as join15 } from "node:path";
57640
+ import { join as join16 } from "node:path";
57334
57641
  import { Type as Type6 } from "typebox";
57335
57642
  function safeName(value2) {
57336
57643
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -57370,7 +57677,7 @@ async function runClassifyAndAct(ctx) {
57370
57677
  const needsFallback = exactCategory === undefined || confidence < ctx.inputs.confidence_threshold;
57371
57678
  const fallback = needsFallback ? await resolveFallbackCategory(ctx, exactCategory) : undefined;
57372
57679
  const category = fallback?.category ?? exactCategory;
57373
- const classificationPath = join15(artifactDir, "classification.json");
57680
+ const classificationPath = join16(artifactDir, "classification.json");
57374
57681
  await writeFile2(classificationPath, JSON.stringify({
57375
57682
  proposed_category: proposedCategory,
57376
57683
  selected_category: category,
@@ -57380,7 +57687,7 @@ async function runClassifyAndAct(ctx) {
57380
57687
  fallback_used: needsFallback,
57381
57688
  fallback_mode: fallback?.fallbackMode ?? "none"
57382
57689
  }, null, 2));
57383
- const actionPath = join15(artifactDir, `action-${safeName(category)}.md`);
57690
+ const actionPath = join16(artifactDir, `action-${safeName(category)}.md`);
57384
57691
  const action = await ctx.task(`action-${safeName(category)}`, {
57385
57692
  tools: actionTools(category),
57386
57693
  prompt: actionPrompt({ prompt: ctx.inputs.prompt, category, classificationPath }),
@@ -57520,7 +57827,7 @@ var GROUNDED_REPORTING3 = "Before reporting progress, audit each claim against a
57520
57827
 
57521
57828
  // dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts
57522
57829
  import { writeFile as writeFile3 } from "node:fs/promises";
57523
- import { join as join16 } from "node:path";
57830
+ import { join as join17 } from "node:path";
57524
57831
  import { Type as Type8 } from "typebox";
57525
57832
  function safeName2(value2, index) {
57526
57833
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -57551,9 +57858,9 @@ async function runFanOutAndSynthesize(ctx) {
57551
57858
  context: "fresh"
57552
57859
  });
57553
57860
  const partitions = parsedPartitions(plan.structured, ctx.inputs.max_branches, ctx.inputs.prompt);
57554
- const partitionPath = join16(artifactDir, "partition-plan.json");
57861
+ const partitionPath = join17(artifactDir, "partition-plan.json");
57555
57862
  await writeFile3(partitionPath, JSON.stringify({ task: ctx.inputs.prompt, partitions }, null, 2));
57556
- const branchPaths = partitions.map((partition, index) => join16(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
57863
+ const branchPaths = partitions.map((partition, index) => join17(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
57557
57864
  const steps = partitions.map((partition, index) => ({
57558
57865
  name: `branch-${safeName2(partition.label, index)}`,
57559
57866
  prompt: branchPrompt({ prompt: ctx.inputs.prompt, ...partition }),
@@ -57563,13 +57870,13 @@ async function runFanOutAndSynthesize(ctx) {
57563
57870
  outputMode: "file-only"
57564
57871
  }));
57565
57872
  await ctx.parallel(steps, { concurrency: Math.min(ctx.inputs.max_concurrency, partitions.length), failFast: false });
57566
- const manifestPath = join16(artifactDir, "manifest.json");
57873
+ const manifestPath = join17(artifactDir, "manifest.json");
57567
57874
  await writeFile3(manifestPath, JSON.stringify({
57568
57875
  task: ctx.inputs.prompt,
57569
57876
  partition_plan: partitionPath,
57570
57877
  branches: partitions.map((partition, index) => ({ ...partition, artifact_path: branchPaths[index] }))
57571
57878
  }, null, 2));
57572
- const synthesisPath = join16(artifactDir, "synthesis.md");
57879
+ const synthesisPath = join17(artifactDir, "synthesis.md");
57573
57880
  const synthesis = await ctx.task("synthesize", {
57574
57881
  prompt: synthesisPrompt(ctx.inputs.prompt, manifestPath),
57575
57882
  context: "fresh",
@@ -57734,7 +58041,7 @@ var init_generate_and_filter_prompts = __esm(() => {
57734
58041
 
57735
58042
  // dist/builtin/workflows/builtin/generate-and-filter-runner.ts
57736
58043
  import { readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
57737
- import { join as join17 } from "node:path";
58044
+ import { join as join18 } from "node:path";
57738
58045
  import { Type as Type10 } from "typebox";
57739
58046
  function isRecord4(value2) {
57740
58047
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -57753,7 +58060,7 @@ function judgeDecision(value2) {
57753
58060
  }
57754
58061
  async function runGenerateAndFilter(ctx) {
57755
58062
  const root = await stableArtifactRoot(ctx, "generate-and-filter");
57756
- const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join17(root, `candidate-${index + 1}.md`));
58063
+ const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join18(root, `candidate-${index + 1}.md`));
57757
58064
  const shortlistLimit = Math.min(ctx.inputs.shortlist_size, ctx.inputs.num_candidates);
57758
58065
  await ctx.parallel(candidatePaths.map((path, index) => ({
57759
58066
  name: `generate-${index + 1}`,
@@ -57762,9 +58069,9 @@ async function runGenerateAndFilter(ctx) {
57762
58069
  output: path,
57763
58070
  outputMode: "file-only"
57764
58071
  })), { concurrency: ctx.inputs.max_concurrency, failFast: false });
57765
- const manifestPath = join17(root, "manifest.json");
58072
+ const manifestPath = join18(root, "manifest.json");
57766
58073
  await writeFile4(manifestPath, JSON.stringify({ task: ctx.inputs.prompt, candidate_artifact_paths: candidatePaths }, null, 2));
57767
- const filterPath = join17(root, "filter.json");
58074
+ const filterPath = join18(root, "filter.json");
57768
58075
  const filtered = await ctx.task("dedupe-and-filter", {
57769
58076
  prompt: renderFilterPrompt(ctx.inputs.prompt, candidatePaths, shortlistLimit),
57770
58077
  context: "fresh",
@@ -57781,7 +58088,7 @@ async function runGenerateAndFilter(ctx) {
57781
58088
  let judgePath = null;
57782
58089
  let decisionPath = filterPath;
57783
58090
  if (ctx.inputs.use_judge) {
57784
- judgePath = join17(root, "judge.json");
58091
+ judgePath = join18(root, "judge.json");
57785
58092
  const judgeCandidates = await Promise.all(shortlist.map(async (path) => ({ path, body: await readFile3(path, "utf8") })));
57786
58093
  const judgePrompt = renderJudgePrompt(ctx.inputs.prompt, filterPath, shortlistLimit, judgeCandidates);
57787
58094
  const judged = await ctx.task("judge", {
@@ -57797,7 +58104,7 @@ async function runGenerateAndFilter(ctx) {
57797
58104
  shortlist = judgedShortlist.length > 0 ? judgedShortlist : shortlist;
57798
58105
  decisionPath = judgePath;
57799
58106
  }
57800
- const finalPath = join17(root, "shortlist.md");
58107
+ const finalPath = join18(root, "shortlist.md");
57801
58108
  const finalShortlist = await ctx.task("final-shortlist", {
57802
58109
  prompt: renderFinalShortlistPrompt(ctx.inputs.prompt, decisionPath),
57803
58110
  context: "fresh",
@@ -58326,7 +58633,7 @@ var init_review_convergence = __esm(() => {
58326
58633
 
58327
58634
  // dist/builtin/workflows/builtin/goal-artifacts.ts
58328
58635
  import { writeFile as writeFile5 } from "node:fs/promises";
58329
- import { join as join18 } from "node:path";
58636
+ import { join as join19 } from "node:path";
58330
58637
  function artifactSafeName(value2) {
58331
58638
  const safe = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
58332
58639
  return safe.length > 0 ? safe : "artifact";
@@ -58337,7 +58644,7 @@ function withoutTurn(value2) {
58337
58644
  return copy;
58338
58645
  }
58339
58646
  async function writeReviewArtifact(artifactDir, reviewer, decision, rawText, convergenceDecision) {
58340
- const artifactPath = join18(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
58647
+ const artifactPath = join19(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
58341
58648
  await writeFile5(artifactPath, `${JSON.stringify({ reviewer, decision, convergence_decision: convergenceDecision, raw_text: rawText }, null, 2)}
58342
58649
  `, { encoding: "utf8" });
58343
58650
  return artifactPath;
@@ -58346,7 +58653,7 @@ async function writeReviewRoundArtifact(artifactDir, reviews, consolidatedFindin
58346
58653
  reviewer: review.reviewer,
58347
58654
  findings: review.findings
58348
58655
  }))), reverification = []) {
58349
- const artifactPath = join18(artifactDir, "review-round-latest.json");
58656
+ const artifactPath = join19(artifactDir, "review-round-latest.json");
58350
58657
  const visibleReviews = reviews.map(withoutTurn);
58351
58658
  await writeFile5(artifactPath, `${JSON.stringify({ reviews: visibleReviews, consolidated_findings: consolidatedFindings, reverification }, null, 2)}
58352
58659
  `, { encoding: "utf8" });
@@ -58576,7 +58883,7 @@ var init_goal_review = __esm(() => {
58576
58883
  // dist/builtin/workflows/builtin/goal-ledger.ts
58577
58884
  import { randomUUID as randomUUID10 } from "node:crypto";
58578
58885
  import { readFile as readFile4, rename, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
58579
- import { dirname as dirname11, join as join19 } from "node:path";
58886
+ import { dirname as dirname12, join as join20 } from "node:path";
58580
58887
  import { isDeepStrictEqual } from "node:util";
58581
58888
  function withoutTurn2(value2) {
58582
58889
  const copy = { ...value2 };
@@ -58601,7 +58908,7 @@ function modelVisibleLedger(ledger) {
58601
58908
  };
58602
58909
  }
58603
58910
  function goalLedgerStatePath(ledgerPath) {
58604
- return join19(dirname11(ledgerPath), LEDGER_STATE_FILENAME);
58911
+ return join20(dirname12(ledgerPath), LEDGER_STATE_FILENAME);
58605
58912
  }
58606
58913
  function appendLifecycleEvent(ledger, event, summary, turn = ledger.turns) {
58607
58914
  ledger.lifecycle.push({
@@ -58677,7 +58984,7 @@ function recoverLegacyExecutionInterruption(ledger) {
58677
58984
  return true;
58678
58985
  }
58679
58986
  async function createGoalLedger(objective, acceptanceCriteria, artifactDir) {
58680
- const ledgerPath = join19(artifactDir, LEDGER_FILENAME);
58987
+ const ledgerPath = join20(artifactDir, LEDGER_FILENAME);
58681
58988
  const existing = await readExistingGoalLedger(ledgerPath);
58682
58989
  if (existing !== undefined) {
58683
58990
  if (recoverLegacyExecutionInterruption(existing))
@@ -59184,7 +59491,7 @@ var init_goal_orchestrator_prompts = __esm(() => {
59184
59491
  });
59185
59492
 
59186
59493
  // dist/builtin/workflows/builtin/goal-runner.ts
59187
- import { join as join20 } from "node:path";
59494
+ import { join as join21 } from "node:path";
59188
59495
  function positiveInteger(value2, fallback) {
59189
59496
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 <= 0) {
59190
59497
  return fallback;
@@ -59235,7 +59542,7 @@ async function runGoalWorkflow(ctx, options) {
59235
59542
  appendLifecycleEvent(ledger, "work_turn_started", "Orchestrator started.", turn);
59236
59543
  await writeGoalLedger(ledgerPath, ledger);
59237
59544
  }
59238
- const orchestratorReceiptPath = join20(artifactDir, "orchestrator-receipt.md");
59545
+ const orchestratorReceiptPath = join21(artifactDir, "orchestrator-receipt.md");
59239
59546
  const orchestratorForkOptions = forkContinuationOptions(previousOrchestratorSessionId);
59240
59547
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? renderGoalOrchestratorPrompt({
59241
59548
  ledger,
@@ -59306,7 +59613,7 @@ async function runGoalWorkflow(ctx, options) {
59306
59613
  const reviewerName = result.name ?? result.stageName;
59307
59614
  const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
59308
59615
  const parsed = reviewerContractError === undefined ? parsedReviewDecisionFromResult(result, reviewerName) : { decision: reviewerErrorDecision(reviewerContractError.message), parsed: false, diagnostics: [reviewerContractError.message] };
59309
- const reviewArtifactPath = join20(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
59616
+ const reviewArtifactPath = join21(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
59310
59617
  const record = reviewDecisionToRecord({
59311
59618
  turn,
59312
59619
  reviewer: normalizedReviewerName,
@@ -59509,7 +59816,7 @@ var init_goal = __esm(() => {
59509
59816
  }),
59510
59817
  git_worktree_dir: Type15.String({
59511
59818
  default: "",
59512
- 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."
59819
+ 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."
59513
59820
  }),
59514
59821
  create_pr: Type15.Boolean({
59515
59822
  default: false,
@@ -59627,7 +59934,7 @@ var GROUNDED_REPORTING5 = "Before reporting progress, audit each claim against a
59627
59934
 
59628
59935
  // dist/builtin/workflows/builtin/loop-until-done-runner.ts
59629
59936
  import { mkdir as mkdir3, writeFile as writeFile7 } from "node:fs/promises";
59630
- import { join as join21 } from "node:path";
59937
+ import { join as join22 } from "node:path";
59631
59938
  import { Type as Type16 } from "typebox";
59632
59939
  function progressCurve(entries) {
59633
59940
  return entries.flatMap((entry) => entry.progress === undefined ? [] : [entry.progress.score]);
@@ -59710,18 +60017,18 @@ async function writeLedger(path, task, maxIterations, status, entries) {
59710
60017
  }
59711
60018
  async function runLoopUntilDone(ctx) {
59712
60019
  const artifactDir = await stableArtifactRoot(ctx, "loop-until-done");
59713
- const iterationsDir = join21(artifactDir, "iterations");
59714
- const evaluationsDir = join21(artifactDir, "evaluations");
60020
+ const iterationsDir = join22(artifactDir, "iterations");
60021
+ const evaluationsDir = join22(artifactDir, "evaluations");
59715
60022
  await mkdir3(iterationsDir, { recursive: true });
59716
60023
  await mkdir3(evaluationsDir, { recursive: true });
59717
- const ledgerPath = join21(artifactDir, "progress-ledger.json");
60024
+ const ledgerPath = join22(artifactDir, "progress-ledger.json");
59718
60025
  const entries = [];
59719
60026
  const iterationArtifactPaths = [];
59720
60027
  const evaluationArtifactPaths = [];
59721
60028
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, "active", entries);
59722
60029
  for (let iteration = 1;iteration <= ctx.inputs.max_iterations; iteration += 1) {
59723
- const iterationPath = join21(iterationsDir, `iteration-${iteration}.md`);
59724
- const evaluationPath = join21(evaluationsDir, `evaluation-${iteration}.json`);
60030
+ const iterationPath = join22(iterationsDir, `iteration-${iteration}.md`);
60031
+ const evaluationPath = join22(evaluationsDir, `evaluation-${iteration}.json`);
59725
60032
  iterationArtifactPaths.push(iterationPath);
59726
60033
  evaluationArtifactPaths.push(evaluationPath);
59727
60034
  await ctx.task(`iteration-${iteration}`, {
@@ -59770,7 +60077,7 @@ async function runLoopUntilDone(ctx) {
59770
60077
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, decision.done ? "complete" : "active", entries);
59771
60078
  if (decision.done) {
59772
60079
  const report = progressReport(entries);
59773
- const resultPath = join21(artifactDir, "result.md");
60080
+ const resultPath = join22(artifactDir, "result.md");
59774
60081
  const final = await ctx.task("completion-summary", {
59775
60082
  prompt: renderCompletionPrompt({ task: ctx.inputs.prompt, ledgerPath, iterationPath }),
59776
60083
  context: "fresh",
@@ -59887,9 +60194,9 @@ var init_loop_until_done = __esm(() => {
59887
60194
 
59888
60195
  // dist/builtin/workflows/builtin/open-claude-design-utils.ts
59889
60196
  import { spawnSync as spawnSync3 } from "node:child_process";
59890
- import { mkdirSync as mkdirSync5 } from "node:fs";
60197
+ import { mkdirSync as mkdirSync6 } from "node:fs";
59891
60198
  import { tmpdir, userInfo } from "node:os";
59892
- import { join as join22 } from "node:path";
60199
+ import { join as join23 } from "node:path";
59893
60200
  import { Type as Type18 } from "typebox";
59894
60201
  import { createChildProcessEnvironment as createChildProcessEnvironment3 } from "@bastani/atomic";
59895
60202
  function taggedPrompt3(sections) {
@@ -59932,32 +60239,32 @@ function tmpArtifactBase() {
59932
60239
  try {
59933
60240
  user = userInfo().username.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
59934
60241
  } catch {}
59935
- return join22(tmpdir(), `open-claude-design-${user}`);
60242
+ return join23(tmpdir(), `open-claude-design-${user}`);
59936
60243
  }
59937
60244
  function prepareArtifactDir(cwd = process.cwd()) {
59938
60245
  const runId = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
59939
60246
  const tmpCandidates = [
59940
- join22(tmpArtifactBase(), runId),
59941
- join22(tmpdir(), "open-claude-design", runId)
60247
+ join23(tmpArtifactBase(), runId),
60248
+ join23(tmpdir(), "open-claude-design", runId)
59942
60249
  ];
59943
- const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join22(cwd, "specs", "design", runId), ...tmpCandidates];
60250
+ const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join23(cwd, "specs", "design", runId), ...tmpCandidates];
59944
60251
  for (const candidate of candidates) {
59945
60252
  try {
59946
- mkdirSync5(candidate, { recursive: true });
60253
+ mkdirSync6(candidate, { recursive: true });
59947
60254
  return {
59948
60255
  runId,
59949
60256
  artifactDir: candidate,
59950
- previewPath: join22(candidate, "preview.html"),
59951
- specPath: join22(candidate, "spec.html")
60257
+ previewPath: join23(candidate, "preview.html"),
60258
+ specPath: join23(candidate, "spec.html")
59952
60259
  };
59953
60260
  } catch {}
59954
60261
  }
59955
- const fallback = join22(tmpArtifactBase(), runId);
60262
+ const fallback = join23(tmpArtifactBase(), runId);
59956
60263
  return {
59957
60264
  runId,
59958
60265
  artifactDir: fallback,
59959
- previewPath: join22(fallback, "preview.html"),
59960
- specPath: join22(fallback, "spec.html")
60266
+ previewPath: join23(fallback, "preview.html"),
60267
+ specPath: join23(fallback, "spec.html")
59961
60268
  };
59962
60269
  }
59963
60270
  function ensureAgentBrowser() {
@@ -60291,8 +60598,8 @@ var init_open_claude_design_live_protocol = __esm(() => {
60291
60598
  });
60292
60599
 
60293
60600
  // dist/builtin/workflows/builtin/open-claude-design-setup.ts
60294
- import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync3 } from "node:fs";
60295
- import { join as join23 } from "node:path";
60601
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "node:fs";
60602
+ import { join as join24 } from "node:path";
60296
60603
  function renderDiscoveryContext(discovery) {
60297
60604
  return [
60298
60605
  `Confirmed design brief: ${discovery.brief}`,
@@ -60357,10 +60664,10 @@ async function runDiscoveryAndInit(args) {
60357
60664
  };
60358
60665
  }
60359
60666
  function designContextPath(artifactDir) {
60360
- return join23(artifactDir, DESIGN_CONTEXT_FILENAME);
60667
+ return join24(artifactDir, DESIGN_CONTEXT_FILENAME);
60361
60668
  }
60362
60669
  function referencesBriefPath(artifactDir) {
60363
- return join23(artifactDir, REFERENCES_BRIEF_FILENAME);
60670
+ return join24(artifactDir, REFERENCES_BRIEF_FILENAME);
60364
60671
  }
60365
60672
  function buildReferenceDiscoveryPrompt(args) {
60366
60673
  const siteList = REFERENCE_DESIGN_SITES.map((site, index) => `${index + 1}. ${site.name} — ${site.url}`).join(`
@@ -60386,8 +60693,8 @@ function buildReferenceDiscoveryPrompt(args) {
60386
60693
  [
60387
60694
  "Use the agent-browser skill to open each gallery; if `agent-browser` reports a missing browser executable, follow the bootstrap rules and retry once.",
60388
60695
  "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.",
60389
- `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\`.`,
60390
- `Also run \`agent-browser screenshot ${join23(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
60696
+ `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\`.`,
60697
+ `Also run \`agent-browser screenshot ${join24(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
60391
60698
  "Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
60392
60699
  "Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
60393
60700
  "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.",
@@ -60412,8 +60719,8 @@ function buildReferenceDiscoveryPrompt(args) {
60412
60719
  }
60413
60720
  function writeRequiredContextArtifact(artifactDir, filePath, content, label) {
60414
60721
  try {
60415
- mkdirSync6(artifactDir, { recursive: true });
60416
- writeFileSync3(filePath, `${content}
60722
+ mkdirSync7(artifactDir, { recursive: true });
60723
+ writeFileSync4(filePath, `${content}
60417
60724
  `);
60418
60725
  } catch (error) {
60419
60726
  const detail = error instanceof Error ? error.message : String(error);
@@ -60964,7 +61271,7 @@ var init_ralph_review_gate = __esm(() => {
60964
61271
 
60965
61272
  // dist/builtin/workflows/builtin/ralph-core.ts
60966
61273
  import { mkdir as mkdir4, writeFile as writeFile8 } from "node:fs/promises";
60967
- import { dirname as dirname12, join as join24 } from "node:path";
61274
+ import { dirname as dirname13, join as join25 } from "node:path";
60968
61275
  import { Type as Type20 } from "typebox";
60969
61276
  function taggedPrompt4(sections) {
60970
61277
  return sections.map(([tag, content]) => {
@@ -61004,11 +61311,11 @@ function slugifyResearchTopic(prompt) {
61004
61311
  }
61005
61312
  function defaultResearchPath(prompt, now = new Date) {
61006
61313
  const date = now.toISOString().slice(0, 10);
61007
- return join24(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
61314
+ return join25(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
61008
61315
  }
61009
61316
  async function createImplementationNotesFile(prompt, runId) {
61010
61317
  const notesDir = await createWorkflowArtifactDirectory(runId);
61011
- const notesPath = join24(notesDir, IMPLEMENTATION_NOTES_FILENAME);
61318
+ const notesPath = join25(notesDir, IMPLEMENTATION_NOTES_FILENAME);
61012
61319
  const initialNotes = [
61013
61320
  "# Implementation Notes",
61014
61321
  "",
@@ -61029,7 +61336,7 @@ async function createImplementationNotesFile(prompt, runId) {
61029
61336
  }
61030
61337
  async function createQaEvidenceVideoPath(runId) {
61031
61338
  const qaDir = await createWorkflowArtifactDirectory(runId);
61032
- return join24(qaDir, QA_E2E_VIDEO_FILENAME);
61339
+ return join25(qaDir, QA_E2E_VIDEO_FILENAME);
61033
61340
  }
61034
61341
  function renderQaE2eVideoGuidance(qaVideoPath) {
61035
61342
  return [
@@ -61095,7 +61402,7 @@ function artifactSafeName2(value2) {
61095
61402
  return safe.length > 0 ? safe : "artifact";
61096
61403
  }
61097
61404
  async function writeJsonArtifact(path, content) {
61098
- await mkdir4(dirname12(path), { recursive: true });
61405
+ await mkdir4(dirname13(path), { recursive: true });
61099
61406
  await writeFile8(path, `${JSON.stringify(content, null, 2)}
61100
61407
  `, {
61101
61408
  encoding: "utf8"
@@ -61433,7 +61740,7 @@ var init_ralph_models = __esm(() => {
61433
61740
 
61434
61741
  // dist/builtin/workflows/builtin/ralph-runner.ts
61435
61742
  import { existsSync as existsSync6 } from "node:fs";
61436
- import { join as join25, resolve as resolve11 } from "node:path";
61743
+ import { join as join26, resolve as resolve12 } from "node:path";
61437
61744
  async function runRalphWorkflow(ctx, options) {
61438
61745
  const { prompt, acceptanceCriteria, maxLoops, comparisonBaseBranch, workflowStartCwd, createPr, runId } = options;
61439
61746
  let latestReviewReportPath;
@@ -61445,7 +61752,7 @@ async function runRalphWorkflow(ctx, options) {
61445
61752
  let finalPrReport;
61446
61753
  const workflowCwdContext = workflowCwdContextSection(workflowStartCwd);
61447
61754
  const workflowPrompt = prompt;
61448
- const workflowResearchPath = resolve11(workflowStartCwd, defaultResearchPath(workflowPrompt));
61755
+ const workflowResearchPath = resolve12(workflowStartCwd, defaultResearchPath(workflowPrompt));
61449
61756
  const implementationNotesPath = await createImplementationNotesFile(workflowPrompt, runId);
61450
61757
  const qaVideoPath = await createQaEvidenceVideoPath(runId);
61451
61758
  const artifactDir = await createWorkflowArtifactDirectory(runId);
@@ -61494,7 +61801,7 @@ async function runRalphWorkflow(ctx, options) {
61494
61801
  const researchPath = workflowResearchPath;
61495
61802
  finalResearchPath = researchPath;
61496
61803
  finalPlanPath = researchPath;
61497
- const orchestratorReportPath = join25(artifactDir, "orchestrator-report.md");
61804
+ const orchestratorReportPath = join26(artifactDir, "orchestrator-report.md");
61498
61805
  const orchestratorForkOptions = forkContinuationOptions3(previousOrchestratorSessionId);
61499
61806
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? taggedPrompt4([
61500
61807
  ["acceptance_criteria", keepContext(acceptanceCriteria)],
@@ -61630,7 +61937,7 @@ Read it before implementation or delegation because it is the primary current im
61630
61937
  diagnostics: parsed.diagnostics,
61631
61938
  allowFinalActionRemaining: createPr
61632
61939
  });
61633
- const artifactPath = join25(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
61940
+ const artifactPath = join26(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
61634
61941
  await writeJsonArtifact(artifactPath, {
61635
61942
  reviewer,
61636
61943
  decision: parsed.decision,
@@ -61686,7 +61993,7 @@ Read it before implementation or delegation because it is the primary current im
61686
61993
  usage: fold_usage([orchestrator, ...reviews, ...reverifyResults])
61687
61994
  }));
61688
61995
  }
61689
- latestReviewReportPath = await writeJsonArtifact(join25(artifactDir, "review-round-latest.json"), {
61996
+ latestReviewReportPath = await writeJsonArtifact(join26(artifactDir, "review-round-latest.json"), {
61690
61997
  convergence_decision: roundConvergenceDecision,
61691
61998
  convergence: convergenceEntries,
61692
61999
  consolidated_findings: reverified.batch,
@@ -61835,7 +62142,7 @@ var init_ralph = __esm(() => {
61835
62142
  }),
61836
62143
  git_worktree_dir: Type21.String({
61837
62144
  default: "",
61838
- 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."
62145
+ 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."
61839
62146
  }),
61840
62147
  create_pr: Type21.Boolean({
61841
62148
  default: false,
@@ -62055,7 +62362,7 @@ var init_tournament_prompts = __esm(() => {
62055
62362
 
62056
62363
  // dist/builtin/workflows/builtin/tournament-runner.ts
62057
62364
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile9 } from "node:fs/promises";
62058
- import { join as join26, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve12 } from "node:path";
62365
+ import { join as join27, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve13 } from "node:path";
62059
62366
  import { Type as Type22 } from "typebox";
62060
62367
  function serializableObject3(value2) {
62061
62368
  if (value2 === null || Array.isArray(value2) || typeof value2 !== "object")
@@ -62092,8 +62399,8 @@ function criterionSlug(id) {
62092
62399
  }
62093
62400
  function judgeArtifactPath(judgesDir, job, criterionIndex) {
62094
62401
  const filename = `judge-${job.a}-${job.b}-c${criterionIndex}-${criterionSlug(job.criterionId)}-r${job.rep}.json`;
62095
- const root = resolve12(judgesDir);
62096
- const path = resolve12(judgesDir, filename);
62402
+ const root = resolve13(judgesDir);
62403
+ const path = resolve13(judgesDir, filename);
62097
62404
  const fromRoot = relative5(root, path);
62098
62405
  if (fromRoot.startsWith("..") || isAbsolute9(fromRoot)) {
62099
62406
  throw new Error(`tournament: judge artifact escaped its directory: ${path}`);
@@ -62144,16 +62451,16 @@ function combineUsage(totals) {
62144
62451
  }
62145
62452
  async function runTournament(ctx) {
62146
62453
  const artifactDir = await stableArtifactRoot(ctx, "tournament");
62147
- const attemptsDir = join26(artifactDir, "attempts");
62454
+ const attemptsDir = join27(artifactDir, "attempts");
62148
62455
  const numAttempts = ctx.inputs.num_attempts ?? 4;
62149
62456
  const maxConcurrency = ctx.inputs.max_concurrency ?? 4;
62150
62457
  const nEvaluations = ctx.inputs.n_evaluations ?? 2;
62151
62458
  const pivotCount = ctx.inputs.pivots ?? 1;
62152
62459
  const seed = ctx.inputs.seed ?? 0;
62153
- const judgesDir = join26(artifactDir, "judges");
62460
+ const judgesDir = join27(artifactDir, "judges");
62154
62461
  await mkdir5(attemptsDir, { recursive: true });
62155
62462
  await mkdir5(judgesDir, { recursive: true });
62156
- const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join26(attemptsDir, `attempt-${index + 1}.md`));
62463
+ const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join27(attemptsDir, `attempt-${index + 1}.md`));
62157
62464
  const models = ctx.inputs.models;
62158
62465
  const attemptResults = await ctx.parallel(attemptArtifactPaths.map((path, index) => ({
62159
62466
  name: `attempt-${index + 1}`,
@@ -62318,7 +62625,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
62318
62625
  const outputRanking = ranking.map(({ label, meanPreference }) => ({ label, meanPreference }));
62319
62626
  const budgetPivots = Math.min(pivotCount, entrants.length);
62320
62627
  const comparisonBudget = (entrants.length + budgetPivots * (entrants.length - budgetPivots) + budgetPivots * (budgetPivots - 1) / 2) * criteria.length * nEvaluations;
62321
- const comparisonPath = join26(artifactDir, "comparisons.json");
62628
+ const comparisonPath = join27(artifactDir, "comparisons.json");
62322
62629
  const assignment = modelAssignment(entrants, models);
62323
62630
  const phaseUsage = {
62324
62631
  attempts: fold_usage(attemptResults),
@@ -62354,7 +62661,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
62354
62661
  await writeLedger(fold_usage([]));
62355
62662
  const winner = ranking[0];
62356
62663
  const winnerEntrant = entrants[winner.index];
62357
- const resultPath = join26(artifactDir, "winner.md");
62664
+ const resultPath = join27(artifactDir, "winner.md");
62358
62665
  const reducer = await ctx.task("comparisons-reducer", {
62359
62666
  prompt: renderComparisonsReducerPrompt({
62360
62667
  task: ctx.inputs.prompt,
@@ -63301,7 +63608,7 @@ class SqlPoolQueue {
63301
63608
  throw new Error("Stale pool coordinator authority", { cause: error });
63302
63609
  throw error;
63303
63610
  });
63304
- const row = await this.current(tx, lease, token);
63611
+ const row = await this.current(tx, lease, token, true);
63305
63612
  if (row.epoch !== lease.epoch)
63306
63613
  throw new Error(STALE_WORK_LEASE);
63307
63614
  assertSession();
@@ -65313,7 +65620,7 @@ function isBrokerStatusReport(value2) {
65313
65620
 
65314
65621
  // dist/builtin/intercom/broker/paths.ts
65315
65622
  import { homedir as homedir2 } from "os";
65316
- import { join as join27 } from "path";
65623
+ import { join as join28 } from "path";
65317
65624
  function getHomeDir() {
65318
65625
  if (process.platform === "win32") {
65319
65626
  if (process.env.USERPROFILE)
@@ -65330,7 +65637,7 @@ function expandTildePath(path) {
65330
65637
  if (path === "~")
65331
65638
  return getHomeDir();
65332
65639
  if (path.startsWith("~/") || process.platform === "win32" && path.startsWith("~\\")) {
65333
- return join27(getHomeDir(), path.slice(2));
65640
+ return join28(getHomeDir(), path.slice(2));
65334
65641
  }
65335
65642
  return path;
65336
65643
  }
@@ -65341,31 +65648,31 @@ function getAgentDir5() {
65341
65648
  const piAgentDir = process.env.PI_CODING_AGENT_DIR;
65342
65649
  if (piAgentDir)
65343
65650
  return expandTildePath(piAgentDir);
65344
- return join27(getHomeDir(), ".atomic", "agent");
65651
+ return join28(getHomeDir(), ".atomic", "agent");
65345
65652
  }
65346
65653
  function sanitizePipeSegment(value2) {
65347
65654
  return value2.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "default";
65348
65655
  }
65349
65656
  function getIntercomDirPath(agentDir = getAgentDir5()) {
65350
- return join27(agentDir, "intercom");
65657
+ return join28(agentDir, "intercom");
65351
65658
  }
65352
65659
  function getBrokerPidPath(agentDir = getAgentDir5()) {
65353
- return join27(getIntercomDirPath(agentDir), "broker.pid");
65660
+ return join28(getIntercomDirPath(agentDir), "broker.pid");
65354
65661
  }
65355
65662
  function getBrokerSpawnLockPath(agentDir = getAgentDir5()) {
65356
- return join27(getIntercomDirPath(agentDir), "broker.spawn.lock");
65663
+ return join28(getIntercomDirPath(agentDir), "broker.spawn.lock");
65357
65664
  }
65358
65665
  function getBrokerLogPath(agentDir = getAgentDir5()) {
65359
- return join27(getIntercomDirPath(agentDir), "broker.log");
65666
+ return join28(getIntercomDirPath(agentDir), "broker.log");
65360
65667
  }
65361
65668
  function getBrokerStartAnnouncementPath(agentDir = getAgentDir5()) {
65362
- return join27(getIntercomDirPath(agentDir), "broker.starting");
65669
+ return join28(getIntercomDirPath(agentDir), "broker.starting");
65363
65670
  }
65364
65671
  function getBrokerSocketPath(platform = process.platform, agentDir = getAgentDir5()) {
65365
65672
  if (platform === "win32") {
65366
65673
  return `\\\\.\\pipe\\pi-intercom-${sanitizePipeSegment(agentDir)}`;
65367
65674
  }
65368
- return join27(getIntercomDirPath(agentDir), "broker.sock");
65675
+ return join28(getIntercomDirPath(agentDir), "broker.sock");
65369
65676
  }
65370
65677
  var BROKER_STORAGE_ENV = "ATOMIC_STORAGE";
65371
65678
  var init_paths = () => {};
@@ -67049,11 +67356,11 @@ var init_client = __esm(() => {
67049
67356
  var BROKER_READY_TIMEOUT_MS = 30000, MIN_BROKER_STARTUP_TIMEOUT_MS = 1000;
67050
67357
 
67051
67358
  // dist/builtin/intercom/broker/start-announcement.ts
67052
- import { readFileSync as readFileSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
67359
+ import { readFileSync as readFileSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
67053
67360
  function readBrokerStartAnnouncement(announcement) {
67054
67361
  let text;
67055
67362
  try {
67056
- text = readFileSync4(announcement.path, "utf-8");
67363
+ text = readFileSync6(announcement.path, "utf-8");
67057
67364
  } catch {
67058
67365
  return;
67059
67366
  }
@@ -67072,26 +67379,26 @@ var init_start_announcement = () => {};
67072
67379
  // dist/builtin/intercom/broker/spawn.ts
67073
67380
  import { spawn } from "child_process";
67074
67381
  import { randomUUID as randomUUID15 } from "crypto";
67075
- import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync7, mkdirSync as mkdirSync7, openSync as openSync3, readFileSync as readFileSync5, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "fs";
67076
- import { join as join28, dirname as dirname13 } from "path";
67382
+ import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync7, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync7, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
67383
+ import { join as join29, dirname as dirname14 } from "path";
67077
67384
  import { fileURLToPath as fileURLToPath5 } from "url";
67078
67385
  import { createRequire as createRequire3 } from "module";
67079
67386
  import { createChildProcessEnvironment as createChildProcessEnvironment4, isBunBinary, processSharedStorageSelection } from "@bastani/atomic";
67080
67387
  function isIntercomPackageRoot(dir) {
67081
- return existsSync7(join28(dir, "package.json")) && existsSync7(join28(dir, "broker"));
67388
+ return existsSync7(join29(dir, "package.json")) && existsSync7(join29(dir, "broker"));
67082
67389
  }
67083
67390
  function resolveIntercomPackageRoot(moduleHref) {
67084
- const here = dirname13(fileURLToPath5(moduleHref));
67391
+ const here = dirname14(fileURLToPath5(moduleHref));
67085
67392
  if (isIntercomPackageRoot(here))
67086
67393
  return here;
67087
- return join28(here, "..");
67394
+ return join29(here, "..");
67088
67395
  }
67089
67396
  function resolveBrokerEntrypoint(packageRoot) {
67090
- const bundled = join28(packageRoot, "broker", "broker.bundle.mjs");
67091
- return existsSync7(bundled) ? bundled : join28(packageRoot, "broker", "broker.ts");
67397
+ const bundled = join29(packageRoot, "broker", "broker.bundle.mjs");
67398
+ return existsSync7(bundled) ? bundled : join29(packageRoot, "broker", "broker.ts");
67092
67399
  }
67093
67400
  function ensurePrivateDirectory(path) {
67094
- mkdirSync7(path, { recursive: true, mode: 448 });
67401
+ mkdirSync8(path, { recursive: true, mode: 448 });
67095
67402
  if (process.platform !== "win32")
67096
67403
  chmodSync(path, 448);
67097
67404
  }
@@ -67104,14 +67411,14 @@ function getCurrentBrokerRuntime() {
67104
67411
  return isBunBinary ? "bun-binary" : "bun-source";
67105
67412
  }
67106
67413
  function requireFromExtensionDir(extensionDir) {
67107
- return createRequire3(join28(extensionDir, "package.json"));
67414
+ return createRequire3(join29(extensionDir, "package.json"));
67108
67415
  }
67109
67416
  function getJitiCliPath(extensionDir = EXTENSION_DIR) {
67110
67417
  try {
67111
67418
  const jitiPackage = requireFromExtensionDir(extensionDir).resolve("jiti/package.json");
67112
- return join28(dirname13(jitiPackage), "lib", "jiti-cli.mjs");
67419
+ return join29(dirname14(jitiPackage), "lib", "jiti-cli.mjs");
67113
67420
  } catch {
67114
- return join28(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
67421
+ return join29(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
67115
67422
  }
67116
67423
  }
67117
67424
  function getDefaultBrokerRunnerPath(extensionDir) {
@@ -67133,7 +67440,7 @@ function quoteWindowsArg(value2) {
67133
67440
  return `"${value2.replace(/"/g, '""')}"`;
67134
67441
  }
67135
67442
  function getWindowsHiddenLauncherPath(intercomDir = INTERCOM_DIR) {
67136
- return join28(intercomDir, "broker-launch.vbs");
67443
+ return join29(intercomDir, "broker-launch.vbs");
67137
67444
  }
67138
67445
  function usesDefaultBrokerCommand(brokerCommand, brokerArgs) {
67139
67446
  return brokerCommand === "npx" && brokerArgs.length === 2 && brokerArgs[0] === "--no-install" && brokerArgs[1] === "tsx";
@@ -67160,8 +67467,8 @@ function getWindowsHiddenLauncherScript(commandLine) {
67160
67467
  `);
67161
67468
  }
67162
67469
  function writeWindowsHiddenLauncher(commandLine, launcherPath = getWindowsHiddenLauncherPath()) {
67163
- ensurePrivateDirectory(dirname13(launcherPath));
67164
- writeFileSync5(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
67470
+ ensurePrivateDirectory(dirname14(launcherPath));
67471
+ writeFileSync6(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
67165
67472
  return launcherPath;
67166
67473
  }
67167
67474
  function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath, runtime = getCurrentBrokerRuntime(), logPath = BROKER_LOG) {
@@ -67204,14 +67511,14 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore",
67204
67511
  };
67205
67512
  }
67206
67513
  function resetBrokerLog(logPath = BROKER_LOG) {
67207
- ensurePrivateDirectory(dirname13(logPath));
67514
+ ensurePrivateDirectory(dirname14(logPath));
67208
67515
  try {
67209
67516
  const previous = readBrokerLogTail(logPath);
67210
67517
  closeSync3(openSync3(logPath, "w"));
67211
67518
  if (previous.length > 0) {
67212
67519
  try {
67213
67520
  const previousPath = `${logPath}.previous`;
67214
- writeFileSync5(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
67521
+ writeFileSync6(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
67215
67522
  if (process.platform !== "win32")
67216
67523
  chmodSync(previousPath, 384);
67217
67524
  } catch {}
@@ -67355,7 +67662,7 @@ async function isBrokerRunning() {
67355
67662
  if (!existsSync7(BROKER_PID))
67356
67663
  return false;
67357
67664
  try {
67358
- const pid = parseInt(readFileSync5(BROKER_PID, "utf-8").trim(), 10);
67665
+ const pid = parseInt(readFileSync7(BROKER_PID, "utf-8").trim(), 10);
67359
67666
  if (!Number.isFinite(pid))
67360
67667
  return false;
67361
67668
  process.kill(pid, 0);
@@ -67380,7 +67687,7 @@ function handSpawnLockToBroker(pid, owner) {
67380
67687
  }
67381
67688
  function ownsSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
67382
67689
  try {
67383
- return readFileSync5(lockPath, "utf-8").startsWith(owner);
67690
+ return readFileSync7(lockPath, "utf-8").startsWith(owner);
67384
67691
  } catch {
67385
67692
  return false;
67386
67693
  }
@@ -67392,7 +67699,7 @@ function acquireSpawnLock() {
67392
67699
  ${Date.now()}
67393
67700
  `;
67394
67701
  try {
67395
- writeFileSync5(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
67702
+ writeFileSync6(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
67396
67703
  return owner;
67397
67704
  } catch (error) {
67398
67705
  if (!(error instanceof Error) || error.code !== "EEXIST") {
@@ -67422,7 +67729,7 @@ function isSpawnLockStale(lockPath = BROKER_SPAWN_LOCK, nowMs = Date.now()) {
67422
67729
  return false;
67423
67730
  }
67424
67731
  try {
67425
- const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync5(lockPath, "utf-8").trim().split(`
67732
+ const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync7(lockPath, "utf-8").trim().split(`
67426
67733
  `);
67427
67734
  const spawnerPid = Number.parseInt(spawnerLine, 10);
67428
67735
  const createdAt = Number.parseInt(createdAtLine, 10);
@@ -67500,14 +67807,14 @@ var init_reply_waiter = __esm(() => {
67500
67807
  });
67501
67808
 
67502
67809
  // dist/builtin/intercom/config.ts
67503
- import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
67810
+ import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
67504
67811
  import { getAgentConfigPaths } from "@bastani/atomic";
67505
67812
  function loadConfig() {
67506
67813
  if (!existsSync8(CONFIG_PATH)) {
67507
67814
  return { ...defaults };
67508
67815
  }
67509
67816
  try {
67510
- const raw = readFileSync6(CONFIG_PATH, "utf-8");
67817
+ const raw = readFileSync8(CONFIG_PATH, "utf-8");
67511
67818
  const parsed = JSON.parse(raw);
67512
67819
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
67513
67820
  throw new Error("Config must be a JSON object");
@@ -68090,12 +68397,12 @@ var init_sql_pool_usage = __esm(() => {
68090
68397
 
68091
68398
  // dist/builtin/workflows/src/workers/pooled-watch-trace.ts
68092
68399
  import { appendFileSync as appendFileSync2 } from "node:fs";
68093
- import { dirname as dirname14, join as join29, resolve as resolve13 } from "node:path";
68400
+ import { dirname as dirname15, join as join30, resolve as resolve14 } from "node:path";
68094
68401
  function configurePooledWatchTrace(journalPath, processRole) {
68095
68402
  if (setting === undefined || setting === "" || setting === "0")
68096
68403
  return;
68097
68404
  role = processRole;
68098
- file = setting === "1" ? join29(dirname14(resolve13(journalPath)), "pooled-watch-trace.jsonl") : resolve13(setting);
68405
+ file = setting === "1" ? join30(dirname15(resolve14(journalPath)), "pooled-watch-trace.jsonl") : resolve14(setting);
68099
68406
  }
68100
68407
  function tracePooledWatch(step, detail) {
68101
68408
  if (file === undefined)
@@ -68289,7 +68596,7 @@ import { fork } from "node:child_process";
68289
68596
  import { randomUUID as randomUUID17 } from "node:crypto";
68290
68597
  import { createWriteStream } from "node:fs";
68291
68598
  import { appendFile, mkdir as mkdir6, rm as rm3, rmdir } from "node:fs/promises";
68292
- import { dirname as dirname15, join as join30, resolve as resolve14 } from "node:path";
68599
+ import { dirname as dirname16, join as join31, resolve as resolve15 } from "node:path";
68293
68600
  import { setTimeout as delay2 } from "node:timers/promises";
68294
68601
  function isRootLeaseLost(error) {
68295
68602
  return error instanceof StaleLeaseError || error.message.startsWith("Stale lease for run ");
@@ -68298,7 +68605,7 @@ function unconfirmedCleanup(groups) {
68298
68605
  return new Error(`Local worker process cleanup unconfirmed; ${groups.length > 0 ? `process groups ${groups.join(", ")} still running after SIGKILL; ` : ""}permits quarantined`);
68299
68606
  }
68300
68607
  function workerLogDirectory(journalPath, root) {
68301
- return join30(dirname15(resolve14(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
68608
+ return join31(dirname16(resolve15(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
68302
68609
  }
68303
68610
  function token(work) {
68304
68611
  return {
@@ -68486,6 +68793,7 @@ class PoolCoordinator {
68486
68793
  cleanups = new Set;
68487
68794
  controlAcks = new Map;
68488
68795
  lastHeard = new Map;
68796
+ awaiting = new Map;
68489
68797
  pendingActivity = new Map;
68490
68798
  batches = new Map;
68491
68799
  publicationFailures = new Map;
@@ -69229,7 +69537,7 @@ class PoolCoordinator {
69229
69537
  this.slots.add(slot);
69230
69538
  let ready = false;
69231
69539
  let serial = Promise.resolve();
69232
- const logPath = join30(this.logDirectory, `${worker}.log`);
69540
+ const logPath = join31(this.logDirectory, `${worker}.log`);
69233
69541
  this.logs.set(child, logPath);
69234
69542
  let logFailure;
69235
69543
  const log = createWriteStream(logPath, { flags: "a" });
@@ -69285,6 +69593,7 @@ class PoolCoordinator {
69285
69593
  this.readyWorkers.delete(worker);
69286
69594
  this.controlAcks.delete(worker);
69287
69595
  this.lastHeard.delete(worker);
69596
+ this.awaiting.delete(worker);
69288
69597
  this.slots.delete(slot);
69289
69598
  this.endStageWatches((watch) => watch.slot === slot, "worker_exited");
69290
69599
  for (const settle of slot.stageCommands.values())
@@ -69542,8 +69851,19 @@ class PoolCoordinator {
69542
69851
  await this.sendResult(work.id);
69543
69852
  });
69544
69853
  const response = handled.then((value2) => routeReady ?? value2);
69545
- if (message.kind !== "delivery" && message.kind !== "delivery-ready")
69546
- serial = handled.then(() => {}, () => {});
69854
+ if (message.kind !== "delivery" && message.kind !== "delivery-ready") {
69855
+ this.awaiting.set(worker, (this.awaiting.get(worker) ?? 0) + 1);
69856
+ const answered = () => {
69857
+ const left = (this.awaiting.get(worker) ?? 1) - 1;
69858
+ if (left > 0)
69859
+ this.awaiting.set(worker, left);
69860
+ else
69861
+ this.awaiting.delete(worker);
69862
+ if (this.incarnations.get(worker) === child)
69863
+ this.lastHeard.set(worker, { at: performance.now(), stalled: this.stalledMs });
69864
+ };
69865
+ serial = handled.then(answered, answered);
69866
+ }
69547
69867
  response.then((value2) => child.send({ id: message.id, value: value2 }, replied), (error) => {
69548
69868
  const rootLeaseLost = isRootLeaseLost(error);
69549
69869
  if (rootLeaseLost)
@@ -69613,7 +69933,10 @@ class PoolCoordinator {
69613
69933
  if (work.epoch < lease.epoch)
69614
69934
  await this.releaseRetained(work);
69615
69935
  else
69616
- await queue.expire(lease, work);
69936
+ await queue.expire(lease, work).catch((error) => {
69937
+ if (error.message !== STALE_WORK_LEASE)
69938
+ throw error;
69939
+ });
69617
69940
  }
69618
69941
  })().finally(() => {
69619
69942
  this.recovering = undefined;
@@ -69631,7 +69954,7 @@ class PoolCoordinator {
69631
69954
  isLive(worker, child) {
69632
69955
  this.observeResponsiveness();
69633
69956
  const heard = this.lastHeard.get(worker);
69634
- return child.exitCode === null && child.signalCode === null && child.connected && heard !== undefined && performance.now() - heard.at - (this.stalledMs - heard.stalled) < this.options.leaseMs;
69957
+ 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);
69635
69958
  }
69636
69959
  async stop(child) {
69637
69960
  const pid = child.pid;
@@ -69966,7 +70289,7 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
69966
70289
  };
69967
70290
  }
69968
70291
  async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient) {
69969
- const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient);
70292
+ const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, recipient?.receivedMessageIds);
69970
70293
  const candidateIds = new Set([
69971
70294
  ...activeStore.pendingStageMessagesFor(runId, stageId),
69972
70295
  ...activeStore.pendingStageMessagesFor(runId, stageName),
@@ -70022,7 +70345,7 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
70022
70345
  }
70023
70346
  }
70024
70347
  }
70025
- function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient) {
70348
+ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, receivedByEndedStage = []) {
70026
70349
  const runs = activeStore.runs();
70027
70350
  const rootRunId = durableRootRunIdForRun(runs, runId);
70028
70351
  if (rootRunId === undefined)
@@ -70031,22 +70354,28 @@ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageNam
70031
70354
  if (rootRun === undefined)
70032
70355
  return [];
70033
70356
  const stage = runs.find((run) => run.id === runId)?.stages.find((candidate) => candidate.id === stageId);
70034
- if (stage?.status === "completed" || stage?.status === "skipped")
70357
+ const ended = stage?.status === "completed" || stage?.status === "skipped";
70358
+ if (ended && receivedByEndedStage.length === 0)
70035
70359
  return [];
70036
70360
  const hops = workflowBoundaryHops(runs, runId);
70037
70361
  if (hops === undefined)
70038
70362
  return [];
70039
70363
  return (rootRun.pendingStageMessages ?? []).filter((entry) => {
70040
- if (entry.sticky !== true || entry.status !== "queued")
70041
- return false;
70042
- const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
70043
- if (parsed === undefined || parsed.rootRunId !== rootRunId)
70044
- return false;
70045
70364
  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)))))
70046
70365
  return false;
70047
- return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
70366
+ if (ended && !receivedByEndedStage.includes(entry.message.id))
70367
+ return false;
70368
+ return stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName);
70048
70369
  });
70049
70370
  }
70371
+ function stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName) {
70372
+ if (entry.sticky !== true || entry.status !== "queued")
70373
+ return false;
70374
+ const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
70375
+ if (parsed === undefined || parsed.rootRunId !== rootRunId)
70376
+ return false;
70377
+ return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
70378
+ }
70050
70379
  function claimPendingDelivery(store, runId, stageKey, messageId) {
70051
70380
  let claims = pendingDeliveryClaims.get(store);
70052
70381
  if (claims === undefined) {
@@ -70110,6 +70439,7 @@ class PoolStageHandoff {
70110
70439
  owners = new Map;
70111
70440
  publications = new Map;
70112
70441
  drains = new Map;
70442
+ deliveryIssues = 0;
70113
70443
  constructor(backend, store, queue, lease, claimRun) {
70114
70444
  this.backend = backend;
70115
70445
  this.store = store;
@@ -70190,11 +70520,23 @@ class PoolStageHandoff {
70190
70520
  this.drains.set(stage, drain);
70191
70521
  try {
70192
70522
  await drain;
70523
+ } catch (error) {
70524
+ const current = this.attempts.get(work.id) === attempt && !attempt.fenced;
70525
+ if (current && attempt.sessions.get(stage) === recipient.sessionId && error.message !== STALE)
70526
+ this.recordDeliveryIssue(error);
70527
+ throw error;
70193
70528
  } finally {
70194
70529
  if (this.drains.get(stage) === drain)
70195
70530
  this.drains.delete(stage);
70196
70531
  }
70197
70532
  }
70533
+ recordDeliveryIssue(error) {
70534
+ this.deliveryIssues++;
70535
+ const drains = this.deliveryIssues === 1 ? "1 stage drain" : `${this.deliveryIssues} stage drains`;
70536
+ this.store.recordRunExecutionState(this.lease.runId, {
70537
+ intercomDeliveryIssue: `${drains} on local workers failed; undelivered messages stay queued and arrive live or on the stage's next drain (last: ${error.message})`
70538
+ });
70539
+ }
70198
70540
  async complete(work) {
70199
70541
  const root = this.lease.runId;
70200
70542
  const result = await this.queue.result(root, work.id);
@@ -71502,7 +71844,7 @@ var init_pooled_stage_registry = __esm(() => {
71502
71844
  // dist/builtin/workflows/src/workers/local-pool.ts
71503
71845
  import { fork as fork2 } from "node:child_process";
71504
71846
  import { randomUUID as randomUUID19 } from "node:crypto";
71505
- import { resolve as resolve15 } from "node:path";
71847
+ import { resolve as resolve16 } from "node:path";
71506
71848
  import { setTimeout as delay3 } from "node:timers/promises";
71507
71849
  import { fileURLToPath as fileURLToPath6 } from "node:url";
71508
71850
  import {
@@ -71736,7 +72078,7 @@ class LocalWorkerPool {
71736
72078
  async poolJournal() {
71737
72079
  const journal = this.backend.journal;
71738
72080
  if (this.options.durable === undefined) {
71739
- if (!(journal instanceof SqlRunJournal) || resolve15(this.options.journalPath) !== resolve15(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
72081
+ if (!(journal instanceof SqlRunJournal) || resolve16(this.options.journalPath) !== resolve16(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
71740
72082
  throw new Error("Local workers require the same default-prefix SQLite journal");
71741
72083
  return journal;
71742
72084
  }
@@ -72763,7 +73105,7 @@ var init_local_pool = __esm(() => {
72763
73105
  var DEFAULT_POOLED_STAGE_START_MAX_LOAD_PER_CPU = 3;
72764
73106
 
72765
73107
  // dist/builtin/workflows/src/workers/public-pool.ts
72766
- import { resolve as resolve16 } from "node:path";
73108
+ import { resolve as resolve17 } from "node:path";
72767
73109
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
72768
73110
  function withWorkerSettings(options, settings) {
72769
73111
  const configured = settings?.workflows;
@@ -72823,16 +73165,16 @@ async function activatePublicPool(backend, options) {
72823
73165
  startupTimeoutMs: undefined,
72824
73166
  leaseMs: undefined,
72825
73167
  maxLoadPerCpu: undefined,
72826
- definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve16(cwd, source.path) }))
73168
+ definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve17(cwd, source.path) }))
72827
73169
  };
72828
73170
  const admission = options.admission && {
72829
73171
  ...options.admission,
72830
- ...options.admission.userDatabase ? { userDatabase: resolve16(cwd, options.admission.userDatabase) } : {}
73172
+ ...options.admission.userDatabase ? { userDatabase: resolve17(cwd, options.admission.userDatabase) } : {}
72831
73173
  };
72832
73174
  if (durable !== undefined && admission?.userLimits) {
72833
- if (admission.userDatabase !== undefined && admission.userDatabase !== resolve16(poolPath))
72834
- throw new Error(`admission.userDatabase must be omitted, or ${resolve16(poolPath)}, for a journal that is not a local SQLite file`);
72835
- admission.userDatabase = resolve16(poolPath);
73175
+ if (admission.userDatabase !== undefined && admission.userDatabase !== resolve17(poolPath))
73176
+ throw new Error(`admission.userDatabase must be omitted, or ${resolve17(poolPath)}, for a journal that is not a local SQLite file`);
73177
+ admission.userDatabase = resolve17(poolPath);
72836
73178
  }
72837
73179
  const sources = localWorkers && await Promise.all(localWorkers.definitions.map(async (source) => ({ ...source, digest: await definitionDigest(source.path) })));
72838
73180
  const resources = JSON.parse(JSON.stringify({
@@ -73438,6 +73780,7 @@ function createTaskPrimitive(runtime) {
73438
73780
  }
73439
73781
  })();
73440
73782
  const stageMeta = stage.__modelFallbackMeta();
73783
+ stage.__releaseIfIdle?.();
73441
73784
  return {
73442
73785
  name,
73443
73786
  stageName: name,
@@ -75908,6 +76251,8 @@ function createTrackedStageCaller(input) {
75908
76251
  await runtime.releaseLiveHandle().catch(() => {});
75909
76252
  }
75910
76253
  runtime.state.sessionCheckpointed = finalizationError === undefined;
76254
+ if (runtime.state.contextUnreachable)
76255
+ runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId);
75911
76256
  input.limiter.release();
75912
76257
  if (finalizationError !== undefined)
75913
76258
  throwFinalizationError(finalizationError.error);
@@ -76071,7 +76416,8 @@ function createStageContext(input) {
76071
76416
  recordStageNotice({ kind: "abort", to: "interrupted" });
76072
76417
  await innerCtx.abort();
76073
76418
  },
76074
- __modelFallbackMeta: () => innerCtx.__modelFallbackMeta()
76419
+ __modelFallbackMeta: () => innerCtx.__modelFallbackMeta(),
76420
+ __releaseIfIdle: () => runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId)
76075
76421
  };
76076
76422
  }
76077
76423
 
@@ -77760,10 +78106,10 @@ function isRetryableSameCandidateFailure(error) {
77760
78106
  return isTransientExtensionStartupFailure(error);
77761
78107
  return isRetryableSameModelFailure(error);
77762
78108
  }
77763
- function mayAdvanceToNextCandidate(error) {
78109
+ function mayAdvanceToNextCandidate(error, options) {
77764
78110
  if (isExtensionStartupFailure(error))
77765
78111
  return isTransientExtensionStartupFailure(error);
77766
- return isRetryableModelFailure(error);
78112
+ return isRetryableModelFailure(error, options);
77767
78113
  }
77768
78114
  function hasMeaningfulUsage(usage) {
77769
78115
  if (usage === undefined)
@@ -77855,6 +78201,7 @@ class StageSessionController {
77855
78201
  structuredOutputExecutionFailureValue;
77856
78202
  structuredOutputCycleAttemptMark;
77857
78203
  unsubscribeTerminateWatcher;
78204
+ unbindAbortSignal;
77858
78205
  sessionInternalRetries = 0;
77859
78206
  unresolvedContextOverflowMessage;
77860
78207
  generationSealed = false;
@@ -78344,6 +78691,8 @@ class StageSessionController {
78344
78691
  this.pendingListeners.clear();
78345
78692
  this.unsubscribeTerminateWatcher?.();
78346
78693
  this.unsubscribeTerminateWatcher = undefined;
78694
+ this.unbindAbortSignal?.();
78695
+ this.unbindAbortSignal = undefined;
78347
78696
  this.terminatingToolCallIds.clear();
78348
78697
  this.messageAdmission.dispose();
78349
78698
  this.deliveryActivity.dispose();
@@ -78438,8 +78787,10 @@ class StageSessionController {
78438
78787
  };
78439
78788
  if (signal.aborted)
78440
78789
  onAbort();
78441
- else
78790
+ else {
78442
78791
  signal.addEventListener("abort", onAbort, { once: true });
78792
+ this.unbindAbortSignal = () => signal.removeEventListener("abort", onAbort);
78793
+ }
78443
78794
  }
78444
78795
  markAbort(reason) {
78445
78796
  this.abortGeneration += 1;
@@ -78466,6 +78817,9 @@ class StageSessionController {
78466
78817
  state.controller.abort(reason);
78467
78818
  this.thrownErrorRetryStates.clear();
78468
78819
  }
78820
+ fallbackFailureOptions() {
78821
+ return { fallbackOnContentFilter: this.retrySettings()?.fallbackOnContentFilter !== false };
78822
+ }
78469
78823
  retrySettings() {
78470
78824
  const managers = [
78471
78825
  this.sessionSettingsManager,
@@ -78740,7 +79094,7 @@ class StageSessionController {
78740
79094
  const errorSettingsManager = retrySettingsManagerFromError(error);
78741
79095
  if (errorSettingsManager !== undefined)
78742
79096
  this.sessionSettingsManager = errorSettingsManager;
78743
- const retryableFailure = isRetryableModelFailure(error);
79097
+ const retryableFailure = isRetryableModelFailure(error, this.fallbackFailureOptions());
78744
79098
  const sameCandidateRetryable = isRetryableSameModelFailure(error) && !isUnresolvedContextOverflowFailure(error);
78745
79099
  recordProviderRateLimit(this.currentProvider(), error, modelIdForModel(this.currentModelValue()));
78746
79100
  if (this.hasExplicitModelFallbackConfig && isProviderRateLimit(error)) {
@@ -79365,7 +79719,7 @@ class StageSessionController {
79365
79719
  }
79366
79720
  throw new WorkflowPromptModelFailure(terminalFailure);
79367
79721
  } catch (err) {
79368
- if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
79722
+ if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
79369
79723
  this.artifactCapture.settleAttempt(true);
79370
79724
  const usage = this.takeAttemptUsage(resumedSession);
79371
79725
  this.modelAttempts.push({
@@ -79387,7 +79741,7 @@ class StageSessionController {
79387
79741
  ...usage === undefined ? {} : { usage },
79388
79742
  error: message
79389
79743
  });
79390
- if (this.opts.signal?.aborted || !isRetryableModelFailure(err)) {
79744
+ if (this.opts.signal?.aborted || !isRetryableModelFailure(err, this.fallbackFailureOptions())) {
79391
79745
  this.modelWarnings.push(...this.pendingFallbackWarnings);
79392
79746
  this.pendingFallbackWarnings.length = 0;
79393
79747
  this.notifyModelFallbackMetaChange();
@@ -79436,7 +79790,7 @@ class StageSessionController {
79436
79790
  throw err;
79437
79791
  const message = errorMessage4(err);
79438
79792
  const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
79439
- if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
79793
+ if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
79440
79794
  this.recordSuccessfulAttempt(candidate);
79441
79795
  return "handled";
79442
79796
  }
@@ -79453,7 +79807,7 @@ class StageSessionController {
79453
79807
  if (walk !== undefined) {
79454
79808
  this.recordCandidateFailure(walk, index, err, candidates);
79455
79809
  nextIndex = undefined;
79456
- if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err)) {
79810
+ if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err, this.fallbackFailureOptions())) {
79457
79811
  try {
79458
79812
  nextIndex = await this.selectReadyCandidate(candidates, walk, index + 1);
79459
79813
  } catch (error) {
@@ -79466,7 +79820,7 @@ class StageSessionController {
79466
79820
  }
79467
79821
  }
79468
79822
  }
79469
- if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err) || nextIndex === undefined) {
79823
+ if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err, this.fallbackFailureOptions()) || nextIndex === undefined) {
79470
79824
  await this.settleFailedCandidate();
79471
79825
  return "throw";
79472
79826
  }
@@ -79561,7 +79915,7 @@ var init_stage_runner_controller = __esm(() => {
79561
79915
  // dist/builtin/workflows/src/runs/foreground/stage-runner-output.ts
79562
79916
  import { createHash as createHash5 } from "node:crypto";
79563
79917
  import { mkdir as mkdir7, writeFile as writeFile10 } from "node:fs/promises";
79564
- import { basename as basename5, dirname as dirname16, isAbsolute as isAbsolute11, join as join31, resolve as resolve17 } from "node:path";
79918
+ import { basename as basename5, dirname as dirname17, isAbsolute as isAbsolute11, join as join32, resolve as resolve18 } from "node:path";
79565
79919
  function normalizeMaxOutput2(maxOutput) {
79566
79920
  return {
79567
79921
  bytes: maxOutput?.bytes ?? DEFAULT_MAX_OUTPUT_BYTES,
@@ -79624,7 +79978,7 @@ function formatByteSize(bytes) {
79624
79978
  }
79625
79979
  function transcriptPath(runId, outputPath) {
79626
79980
  const digest = createHash5("sha256").update(outputPath).digest("hex").slice(0, 16);
79627
- return join31(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename5(outputPath)}.transcript.md`);
79981
+ return join32(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename5(outputPath)}.transcript.md`);
79628
79982
  }
79629
79983
  function appendContent(lines, content) {
79630
79984
  if (typeof content === "string") {
@@ -79669,7 +80023,7 @@ function renderTranscript(messages, fallbackOutput) {
79669
80023
  `);
79670
80024
  }
79671
80025
  function savedOutputReference(outputPath, fullOutput, transcriptPathValue, transcriptText, transcriptAvailable, warning) {
79672
- const absolutePath = resolve17(outputPath);
80026
+ const absolutePath = resolve18(outputPath);
79673
80027
  const bytes = Buffer.byteLength(fullOutput, "utf8");
79674
80028
  const lines = countLines(fullOutput);
79675
80029
  const transcriptBytes = Buffer.byteLength(transcriptText, "utf8");
@@ -79684,8 +80038,8 @@ function resolveOutputPath(output, runtimeCwd, requestedCwd) {
79684
80038
  return;
79685
80039
  if (isAbsolute11(output))
79686
80040
  return output;
79687
- const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve17(runtimeCwd, requestedCwd);
79688
- return resolve17(baseCwd, output);
80041
+ const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve18(runtimeCwd, requestedCwd);
80042
+ return resolve18(baseCwd, output);
79689
80043
  }
79690
80044
  function degenerateWarning(fullOutput) {
79691
80045
  return fullOutput.trim().length === 0 ? "WARNING: the stage artifact is empty; search the companion transcript for this stage's work." : undefined;
@@ -79744,7 +80098,7 @@ async function finalizePromptOutput(fullOutput, outputOptions, runtimeCwd, runId
79744
80098
  const transcriptFile = transcriptPath(runId, outputPath);
79745
80099
  const transcript = renderTranscript(messages, fullOutput);
79746
80100
  try {
79747
- await mkdir7(dirname16(outputPath), { recursive: true });
80101
+ await mkdir7(dirname17(outputPath), { recursive: true });
79748
80102
  await writeFile10(outputPath, fullOutput, "utf8");
79749
80103
  } catch (err) {
79750
80104
  return `${displayOutput}
@@ -79756,7 +80110,7 @@ ${err instanceof Error ? err.message : String(err)}`;
79756
80110
  let transcriptError;
79757
80111
  try {
79758
80112
  await ensureWorkflowArtifactRunDirectory(runId);
79759
- await mkdir7(dirname16(transcriptFile), { recursive: true });
80113
+ await mkdir7(dirname17(transcriptFile), { recursive: true });
79760
80114
  await writeFile10(transcriptFile, transcript, "utf8");
79761
80115
  transcriptAvailable = true;
79762
80116
  } catch (err) {
@@ -80267,7 +80621,8 @@ function createWorkflowStageFactory(input) {
80267
80621
  stageFinalized: false,
80268
80622
  sessionCheckpointed: false,
80269
80623
  skippedForParallelFailFast: false,
80270
- stageControlDropped: false
80624
+ stageControlDropped: false,
80625
+ contextUnreachable: false
80271
80626
  };
80272
80627
  const activeAskUserQuestionCalls = new Set;
80273
80628
  const hasActiveAskUserQuestion = () => activeAskUserQuestionCalls.size > 0 || state.activeAskUserQuestionAnonymousCalls > 0;
@@ -80513,9 +80868,18 @@ function createWorkflowStageFactory(input) {
80513
80868
  hasContinuation: input.opts.continuation !== undefined,
80514
80869
  hasScopedParents: stageFailFastScope?.parentIds !== undefined
80515
80870
  });
80516
- return createStageContext({ runtime, runTrackedStageCall });
80871
+ const context = createStageContext({ runtime, runTrackedStageCall });
80872
+ unreachableStageContexts.register(context, releaseWhenUnreachable(state, input.stageRegistry, input.runId, stageId));
80873
+ return context;
80874
+ };
80875
+ }
80876
+ function releaseWhenUnreachable(state, registry, runId, stageId) {
80877
+ return () => {
80878
+ state.contextUnreachable = true;
80879
+ registry.releaseIdle(runId, stageId);
80517
80880
  };
80518
80881
  }
80882
+ var unreachableStageContexts;
80519
80883
  var init_executor_stage_factory = __esm(() => {
80520
80884
  init_intercom_group();
80521
80885
  init_pending_stage_route_readiness();
@@ -80530,6 +80894,7 @@ var init_executor_stage_factory = __esm(() => {
80530
80894
  init_pending_stage_delivery2();
80531
80895
  init_stage_runner();
80532
80896
  init_stage_runner_session();
80897
+ unreachableStageContexts = new FinalizationRegistry((release) => release());
80533
80898
  });
80534
80899
 
80535
80900
  // dist/builtin/workflows/src/engine/runtime.ts
@@ -80871,7 +81236,7 @@ async function executeRun(def, resolvedInputs, opts) {
80871
81236
  const ownsCancellationRegistration = opts.signal === undefined && opts.cancellation !== undefined;
80872
81237
  const tracker = new GraphFrontierTracker;
80873
81238
  const inputConcurrency = resolveInputConcurrency(def.inputs, resolvedInputs);
80874
- const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache);
81239
+ const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache, runId);
80875
81240
  const gitWorktreeSetupCache = gitWorktreeSetupCacheOwner.cache;
80876
81241
  const workflowInvocationCwd = opts.cwd ?? process.cwd();
80877
81242
  let workflowCwd;
@@ -81970,8 +82335,8 @@ var init_workflows_host_module = __esm(() => {
81970
82335
 
81971
82336
  // dist/builtin/workflows/src/workers/pool-journal.ts
81972
82337
  import { createHash as createHash6, randomUUID as randomUUID22 } from "node:crypto";
81973
- import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
81974
- import { basename as basename6, dirname as dirname17, join as join32, resolve as resolve18 } from "node:path";
82338
+ import { existsSync as existsSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
82339
+ import { basename as basename6, dirname as dirname18, join as join33, resolve as resolve19 } from "node:path";
81975
82340
  import { storageSelectionKey as storageSelectionKey2 } from "@bastani/atomic/storage";
81976
82341
  function encodeOption(value2) {
81977
82342
  if (typeof value2 === "bigint")
@@ -81993,7 +82358,7 @@ function isReopenableSelection(selection) {
81993
82358
  }
81994
82359
  function encodeSelection(selection) {
81995
82360
  if (selection.kind === "sqlite")
81996
- return JSON.stringify({ ...selection, path: resolve18(selection.path) });
82361
+ return JSON.stringify({ ...selection, path: resolve19(selection.path) });
81997
82362
  return JSON.stringify({
81998
82363
  ...selection,
81999
82364
  ...selection.options === undefined ? {} : {
@@ -82025,7 +82390,7 @@ function openDurableJournal(durable) {
82025
82390
  return openSelectedRunJournal(decodeSelection(durable.selection), durable.agentDir);
82026
82391
  }
82027
82392
  function poolStateDirectory(agentDir) {
82028
- return join32(dirname17(agentDir), "workflows", "pool");
82393
+ return join33(dirname18(agentDir), "workflows", "pool");
82029
82394
  }
82030
82395
  function databaseIdentity(selection, agentDir) {
82031
82396
  return storageSelectionKey2(selection.kind === "adapter" ? { ...selection, secrets: undefined } : selection, agentDir);
@@ -82033,16 +82398,16 @@ function databaseIdentity(selection, agentDir) {
82033
82398
  function coordinationPath(durable) {
82034
82399
  const selection = decodeSelection(durable.selection);
82035
82400
  const identity = createHash6("sha256").update(databaseIdentity(selection, durable.agentDir)).digest("hex");
82036
- return join32(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
82401
+ return join33(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
82037
82402
  }
82038
82403
  function coordinationDatabase(durable) {
82039
82404
  return basename6(coordinationPath(durable), ".sqlite");
82040
82405
  }
82041
82406
  function openCoordinationJournal(path) {
82042
- const file = resolve18(path);
82407
+ const file = resolve19(path);
82043
82408
  let opened = coordinationJournals.get(file);
82044
82409
  if (opened === undefined) {
82045
- mkdirSync8(dirname17(file), { recursive: true });
82410
+ mkdirSync9(dirname18(file), { recursive: true });
82046
82411
  opened = resolveRunJournal({ journal: { path: file } });
82047
82412
  coordinationJournals.set(file, opened);
82048
82413
  opened.catch(() => {
@@ -82059,20 +82424,20 @@ function poolJournalFor(journal) {
82059
82424
  return coordinations.get(journal) ?? journal;
82060
82425
  }
82061
82426
  function poolHostId(agentDir) {
82062
- const file = join32(poolStateDirectory(agentDir), "host-id");
82427
+ const file = join33(poolStateDirectory(agentDir), "host-id");
82063
82428
  try {
82064
- const existing = readFileSync7(file, "utf8").trim();
82429
+ const existing = readFileSync9(file, "utf8").trim();
82065
82430
  if (existing !== "")
82066
82431
  return existing;
82067
82432
  } catch {}
82068
- mkdirSync8(dirname17(file), { recursive: true });
82433
+ mkdirSync9(dirname18(file), { recursive: true });
82069
82434
  const id = randomUUID22();
82070
82435
  try {
82071
- writeFileSync6(file, `${id}
82436
+ writeFileSync7(file, `${id}
82072
82437
  `, { flag: "wx" });
82073
82438
  return id;
82074
82439
  } catch {
82075
- return readFileSync7(file, "utf8").trim();
82440
+ return readFileSync9(file, "utf8").trim();
82076
82441
  }
82077
82442
  }
82078
82443
  async function poolJournalOf(journal) {
@@ -82873,9 +83238,9 @@ var init_sdk_owner_release = __esm(() => {
82873
83238
 
82874
83239
  // dist/builtin/workflows/src/durable/sdk-recovery-scope.ts
82875
83240
  import { realpathSync as realpathSync5 } from "node:fs";
82876
- import { resolve as resolve19 } from "node:path";
83241
+ import { resolve as resolve20 } from "node:path";
82877
83242
  function canonicalDirectory(path) {
82878
- const absolute = resolve19(path);
83243
+ const absolute = resolve20(path);
82879
83244
  try {
82880
83245
  const canonical = realpathSync5.native(absolute);
82881
83246
  return process.platform === "win32" ? canonical.toLowerCase() : canonical;
@@ -84821,6 +85186,8 @@ function summaryRows(detail, now) {
84821
85186
  rows.push(["last progress", formatTime(detail.lastProgressAt)]);
84822
85187
  if (detail.dependencyError !== undefined)
84823
85188
  rows.push(["dependency", detail.dependencyError]);
85189
+ if (detail.intercomDeliveryIssue !== undefined)
85190
+ rows.push(["intercom", detail.intercomDeliveryIssue]);
84824
85191
  if (detail.controlPersistence !== undefined) {
84825
85192
  rows.push(["control", `${detail.controlRequestedStatus} (${detail.controlPersistence})`]);
84826
85193
  }
@@ -96559,7 +96926,8 @@ function observeRunExecution(run, now = Date.now()) {
96559
96926
  dependencyError: run.dependencyError,
96560
96927
  lastProgressAt,
96561
96928
  controlPersistence: run.controlPersistence,
96562
- controlRequestedStatus: run.controlRequestedStatus
96929
+ controlRequestedStatus: run.controlRequestedStatus,
96930
+ ...run.intercomDeliveryIssue === undefined ? {} : { intercomDeliveryIssue: run.intercomDeliveryIssue }
96563
96931
  };
96564
96932
  }
96565
96933
 
@@ -97143,7 +97511,7 @@ function installCompactionHook(api, store) {
97143
97511
  });
97144
97512
  }
97145
97513
  // dist/builtin/workflows/src/extension/config-loader.ts
97146
- import { isAbsolute as isAbsolute12, join as join33 } from "node:path";
97514
+ import { isAbsolute as isAbsolute12, join as join34 } from "node:path";
97147
97515
  import { CONFIG_DIR_NAME as CONFIG_DIR_NAME2, getAgentDir as getAgentDir6 } from "@bastani/atomic";
97148
97516
  // dist/builtin/workflows/src/extension/lifecycle-notifications.ts
97149
97517
  init_returned_run_status();
@@ -98060,7 +98428,7 @@ function resolveWorkflowPaths(workflows, baseDir) {
98060
98428
  }
98061
98429
  return Object.fromEntries(Object.entries(workflows).map(([name, entry]) => [
98062
98430
  name,
98063
- isAbsolute12(entry.path) ? entry.path : join33(baseDir, entry.path)
98431
+ isAbsolute12(entry.path) ? entry.path : join34(baseDir, entry.path)
98064
98432
  ]));
98065
98433
  }
98066
98434
  function workflowAgentDirs(opts) {
@@ -98068,12 +98436,12 @@ function workflowAgentDirs(opts) {
98068
98436
  return opts.agentDirs;
98069
98437
  if (opts.homeDir !== undefined) {
98070
98438
  const homeDir = opts.homeDir;
98071
- return [join33(homeDir, CONFIG_DIR_NAME2, "agent")];
98439
+ return [join34(homeDir, CONFIG_DIR_NAME2, "agent")];
98072
98440
  }
98073
98441
  return [getAgentDir6()];
98074
98442
  }
98075
98443
  function toScopedDiscoveryConfig(globalConfig, projectConfig, opts) {
98076
- const globalBase = opts.agentDir ?? (opts.homeDir === undefined ? getAgentDir6() : join33(opts.homeDir, CONFIG_DIR_NAME2, "agent"));
98444
+ const globalBase = opts.agentDir ?? (opts.homeDir === undefined ? getAgentDir6() : join34(opts.homeDir, CONFIG_DIR_NAME2, "agent"));
98077
98445
  const projectBase = opts.projectRoot;
98078
98446
  const result = {};
98079
98447
  const projectWorkflows = resolveWorkflowPaths(projectConfig?.workflows, projectBase);
@@ -98083,7 +98451,7 @@ function toScopedDiscoveryConfig(globalConfig, projectConfig, opts) {
98083
98451
  if (hasWorkflows(globalConfig)) {
98084
98452
  const projectKeys = new Set(Object.keys(projectWorkflows ?? {}));
98085
98453
  const globalEntries = Object.entries(globalConfig.workflows).filter(([name]) => !projectKeys.has(name)).map(([name, entry]) => {
98086
- return [name, isAbsolute12(entry.path) ? entry.path : join33(globalBase, entry.path)];
98454
+ return [name, isAbsolute12(entry.path) ? entry.path : join34(globalBase, entry.path)];
98087
98455
  });
98088
98456
  if (globalEntries.length > 0) {
98089
98457
  result.globalWorkflows = Object.fromEntries(globalEntries);
@@ -98094,8 +98462,8 @@ function toScopedDiscoveryConfig(globalConfig, projectConfig, opts) {
98094
98462
  async function loadWorkflowConfig(opts = {}) {
98095
98463
  const projectRoot = opts.projectRoot ?? process.cwd();
98096
98464
  const diagnostics = [];
98097
- const globalCandidates = workflowAgentDirs(opts).map((agentDir) => join33(agentDir, "extensions", "workflow", "config.json"));
98098
- const projectCandidates = [join33(projectRoot, CONFIG_DIR_NAME2, "extensions", "workflow", "config.json")];
98465
+ const globalCandidates = workflowAgentDirs(opts).map((agentDir) => join34(agentDir, "extensions", "workflow", "config.json"));
98466
+ const projectCandidates = [join34(projectRoot, CONFIG_DIR_NAME2, "extensions", "workflow", "config.json")];
98099
98467
  let globalConfig = null;
98100
98468
  for (let i = globalCandidates.length - 1;i >= 0; i--) {
98101
98469
  const globalPath = globalCandidates[i];
@@ -99787,7 +100155,7 @@ init_possible_stages();
99787
100155
  import { registerExtensionContextRetirementEffect as registerExtensionContextRetirementEffect2 } from "@bastani/atomic";
99788
100156
 
99789
100157
  // dist/builtin/workflows/src/extension/discovery.ts
99790
- import { join as join35 } from "node:path";
100158
+ import { join as join36 } from "node:path";
99791
100159
  import { CONFIG_DIR_NAME as CONFIG_DIR_NAME3, getAgentDir as getAgentDir7 } from "@bastani/atomic";
99792
100160
 
99793
100161
  // dist/builtin/workflows/builtin/index.ts
@@ -99808,12 +100176,12 @@ init_registry();
99808
100176
  // dist/builtin/workflows/src/extension/discovery-loaders.ts
99809
100177
  init_workflow_module_loader();
99810
100178
  import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
99811
- import { extname, isAbsolute as isAbsolute13, join as join34, resolve as resolve20 } from "node:path";
100179
+ import { extname, isAbsolute as isAbsolute13, join as join35, resolve as resolve21 } from "node:path";
99812
100180
  async function scanWorkflowDir(dir) {
99813
100181
  try {
99814
100182
  const entries = await readdir2(dir, { withFileTypes: true });
99815
100183
  const WORKFLOW_EXTS = new Set([".ts", ".js", ".mjs", ".cjs"]);
99816
- return entries.filter((e) => e.isFile() && WORKFLOW_EXTS.has(extname(e.name))).map((e) => join34(dir, e.name)).sort();
100184
+ return entries.filter((e) => e.isFile() && WORKFLOW_EXTS.has(extname(e.name))).map((e) => join35(dir, e.name)).sort();
99817
100185
  } catch {
99818
100186
  return null;
99819
100187
  }
@@ -99852,7 +100220,7 @@ async function loadFromPaths(pathsOrMap, kind, baseCwd, diagnostics, getWorkflow
99852
100220
  const all = [];
99853
100221
  const entries = Array.isArray(pathsOrMap) ? pathsOrMap.map((p) => ({ rawPath: p })) : Object.entries(pathsOrMap).map(([name, p]) => ({ rawPath: p, configuredName: name }));
99854
100222
  for (const { rawPath, configuredName } of entries) {
99855
- const absPath = isAbsolute13(rawPath) ? rawPath : resolve20(baseCwd, rawPath);
100223
+ const absPath = isAbsolute13(rawPath) ? rawPath : resolve21(baseCwd, rawPath);
99856
100224
  let pathStats;
99857
100225
  try {
99858
100226
  pathStats = await stat2(absPath);
@@ -99883,7 +100251,7 @@ function workflowAgentDirs2(options) {
99883
100251
  return options.agentDirs;
99884
100252
  if (options?.homeDir !== undefined) {
99885
100253
  const homeDir = options.homeDir;
99886
- return [join35(homeDir, CONFIG_DIR_NAME3, "agent")];
100254
+ return [join36(homeDir, CONFIG_DIR_NAME3, "agent")];
99887
100255
  }
99888
100256
  return [getAgentDir7()];
99889
100257
  }
@@ -100039,7 +100407,7 @@ async function discoverWorkflows(options) {
100039
100407
  registry = await applyBatch(candidates, registry, sources, diagnostics);
100040
100408
  }
100041
100409
  }
100042
- for (const dir of [join35(cwd, CONFIG_DIR_NAME3, "workflows")]) {
100410
+ for (const dir of [join36(cwd, CONFIG_DIR_NAME3, "workflows")]) {
100043
100411
  const candidates = await loadFromDir(dir, "project-local", diagnostics, getWorkflowHostModules);
100044
100412
  registry = await applyBatch(candidates, registry, sources, diagnostics);
100045
100413
  }
@@ -100051,7 +100419,7 @@ async function discoverWorkflows(options) {
100051
100419
  registry = await applyBatch(candidates, registry, sources, diagnostics);
100052
100420
  }
100053
100421
  }
100054
- for (const dir of agentDirs.map((agentDir) => join35(agentDir, "workflows")).reverse()) {
100422
+ for (const dir of agentDirs.map((agentDir) => join36(agentDir, "workflows")).reverse()) {
100055
100423
  const candidates = await loadFromDir(dir, "user-global", diagnostics, getWorkflowHostModules);
100056
100424
  registry = await applyBatch(candidates, registry, sources, diagnostics);
100057
100425
  }
@@ -100926,17 +101294,17 @@ function createExtensionRuntime(opts = {}) {
100926
101294
 
100927
101295
  // dist/builtin/workflows/src/extension/status-writer.ts
100928
101296
  import { mkdir as mkdir8, rename as rename2, writeFile as writeFile11 } from "node:fs/promises";
100929
- import { dirname as dirname18, join as join36 } from "node:path";
101297
+ import { dirname as dirname19, join as join37 } from "node:path";
100930
101298
  import { CONFIG_DIR_NAME as CONFIG_DIR_NAME4 } from "@bastani/atomic";
100931
- var DEFAULT_STATUS_SUBPATH = join36(CONFIG_DIR_NAME4, "workflows", "status.json");
101299
+ var DEFAULT_STATUS_SUBPATH = join37(CONFIG_DIR_NAME4, "workflows", "status.json");
100932
101300
  function resolveStatusFilePath(config, opts = {}) {
100933
101301
  if (config.statusFilePath)
100934
101302
  return config.statusFilePath;
100935
101303
  const root = opts.projectRoot ?? process.cwd();
100936
- return join36(root, DEFAULT_STATUS_SUBPATH);
101304
+ return join37(root, DEFAULT_STATUS_SUBPATH);
100937
101305
  }
100938
101306
  async function atomicWriteJson(path, content) {
100939
- const dir = dirname18(path);
101307
+ const dir = dirname19(path);
100940
101308
  await mkdir8(dir, { recursive: true });
100941
101309
  const tmpPath = `${path}.tmp`;
100942
101310
  await writeFile11(tmpPath, content, "utf8");
@@ -105078,6 +105446,8 @@ function renderStatusToolContent(result) {
105078
105446
  }
105079
105447
  if (run.dependencyError !== undefined)
105080
105448
  lines.push(` dependency: ${run.dependencyError}`);
105449
+ if (run.intercomDeliveryIssue !== undefined)
105450
+ lines.push(` Intercom delivery: ${run.intercomDeliveryIssue}`);
105081
105451
  if (run.controlPersistence !== undefined) {
105082
105452
  lines.push(` control: ${run.controlRequestedStatus} (${run.controlPersistence})`);
105083
105453
  }