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

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 (72) hide show
  1. package/CHANGELOG.md +68 -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 +828 -418
  17. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +905 -429
  18. package/dist/builtin/workflows/src/index.js +798 -393
  19. package/dist/builtin/workflows/src/local-worker-entry.mjs +905 -429
  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/engine-render-service.d.ts +8 -0
  49. package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
  50. package/dist/modes/interactive-engine/engine-render-service.js +28 -6
  51. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
  52. package/dist/modes/interactive-engine/remote-renderer.d.ts +33 -5
  53. package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -1
  54. package/dist/modes/interactive-engine/remote-renderer.js +91 -17
  55. package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
  56. package/dist/modes/rpc/queued-writer.d.ts +2 -0
  57. package/dist/modes/rpc/queued-writer.d.ts.map +1 -1
  58. package/dist/modes/rpc/queued-writer.js +8 -0
  59. package/dist/modes/rpc/queued-writer.js.map +1 -1
  60. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  61. package/dist/modes/rpc/rpc-client.js +4 -0
  62. package/dist/modes/rpc/rpc-client.js.map +1 -1
  63. package/docs/intercom/reference.md +1 -1
  64. package/docs/models/evals.md +30 -2
  65. package/docs/settings.md +3 -0
  66. package/docs/subagents/reference.md +3 -1
  67. package/docs/workflows/api-reference.md +9 -6
  68. package/docs/workflows/builtins.md +1 -1
  69. package/docs/workflows/operations.md +4 -4
  70. package/npm-shrinkwrap.json +32 -32
  71. package/package.json +3 -3
  72. package/schemas/settings.schema.json +5 -0
@@ -13462,9 +13462,104 @@ var init_workflow_artifacts = __esm(() => {
13462
13462
  pendingArtifactPrunes = new Map;
13463
13463
  });
13464
13464
 
13465
- // dist/builtin/workflows/src/runs/shared/worktree-generation.ts
13465
+ // dist/builtin/workflows/src/runs/shared/worktree-allocation.ts
13466
+ import { randomBytes } from "node:crypto";
13466
13467
  import * as fs from "node:fs";
13467
13468
  import * as path from "node:path";
13469
+ function nextBucketId() {
13470
+ return nextBucketIdOverride?.() ?? randomBytes(2).toString("hex");
13471
+ }
13472
+ function errorCode(error) {
13473
+ return error && typeof error === "object" && "code" in error ? String(error.code) : undefined;
13474
+ }
13475
+ function allocateWorktreeCheckoutPath(root, repositoryName) {
13476
+ for (let attempt = 0;attempt < MAX_BUCKET_ATTEMPTS; attempt++) {
13477
+ const bucket = path.join(root, nextBucketId());
13478
+ try {
13479
+ fs.mkdirSync(bucket);
13480
+ return path.join(bucket, repositoryName);
13481
+ } catch (error) {
13482
+ if (errorCode(error) === "EEXIST")
13483
+ continue;
13484
+ const message = error instanceof Error ? error.message : String(error);
13485
+ throw new Error(`Failed to create worktree bucket ${bucket} under gitWorktreeDir ${root}: ${message}`);
13486
+ }
13487
+ }
13488
+ throw new Error(`Every worktree bucket identifier under gitWorktreeDir ${root} is already in use.`);
13489
+ }
13490
+ function removeEmptyWorktreeBucket(checkout) {
13491
+ try {
13492
+ fs.rmdirSync(path.dirname(checkout));
13493
+ } catch {}
13494
+ }
13495
+ function linkedGitDirectory(checkout) {
13496
+ let pointer;
13497
+ try {
13498
+ if (!fs.lstatSync(path.join(checkout, ".git")).isFile())
13499
+ return;
13500
+ pointer = fs.readFileSync(path.join(checkout, ".git"), "utf8");
13501
+ } catch {
13502
+ return;
13503
+ }
13504
+ if (!pointer.startsWith("gitdir:"))
13505
+ return;
13506
+ const gitDir = pointer.slice("gitdir:".length).trim();
13507
+ return gitDir ? path.resolve(checkout, gitDir) : undefined;
13508
+ }
13509
+ function readWorktreeOwner(gitDir) {
13510
+ let contents;
13511
+ try {
13512
+ contents = fs.readFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), "utf8");
13513
+ } catch {
13514
+ return;
13515
+ }
13516
+ try {
13517
+ const record = JSON.parse(contents);
13518
+ return record.version === WORKTREE_OWNER_VERSION && typeof record.ownerRunId === "string" && record.ownerRunId ? record.ownerRunId : undefined;
13519
+ } catch {
13520
+ return;
13521
+ }
13522
+ }
13523
+ function findOwnedWorktreeCheckouts(root, repositoryName, ownerRunId) {
13524
+ let entries;
13525
+ try {
13526
+ entries = fs.readdirSync(root, { withFileTypes: true });
13527
+ } catch {
13528
+ return [];
13529
+ }
13530
+ const owned = [];
13531
+ for (const entry of entries) {
13532
+ if (!entry.isDirectory() || !BUCKET_PATTERN.test(entry.name))
13533
+ continue;
13534
+ const checkout = path.join(root, entry.name, repositoryName);
13535
+ try {
13536
+ if (!fs.lstatSync(checkout).isDirectory())
13537
+ continue;
13538
+ } catch {
13539
+ continue;
13540
+ }
13541
+ const gitDir = linkedGitDirectory(checkout);
13542
+ if (gitDir !== undefined && readWorktreeOwner(gitDir) === ownerRunId)
13543
+ owned.push(checkout);
13544
+ }
13545
+ return owned.sort();
13546
+ }
13547
+ function bindWorktreeOwner(gitDir, ownerRunId) {
13548
+ const record = { version: WORKTREE_OWNER_VERSION, ownerRunId };
13549
+ fs.writeFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), `${JSON.stringify(record)}
13550
+ `, {
13551
+ encoding: "utf8",
13552
+ flag: "wx"
13553
+ });
13554
+ }
13555
+ var WORKTREE_OWNER_FILENAME = "atomic-workflow-run.json", WORKTREE_OWNER_VERSION = 1, BUCKET_PATTERN, MAX_BUCKET_ATTEMPTS = 65536, nextBucketIdOverride;
13556
+ var init_worktree_allocation = __esm(() => {
13557
+ BUCKET_PATTERN = /^[0-9a-f]{4}$/;
13558
+ });
13559
+
13560
+ // dist/builtin/workflows/src/runs/shared/worktree-generation.ts
13561
+ import * as fs2 from "node:fs";
13562
+ import * as path2 from "node:path";
13468
13563
  function sameFileIdentity(left, right) {
13469
13564
  return left.dev === right.dev && left.ino === right.ino;
13470
13565
  }
@@ -13474,7 +13569,7 @@ function openMainCheckoutAnchor(gitDir) {
13474
13569
  assertCurrent() {
13475
13570
  if (disposed)
13476
13571
  throw new Error(`cached .git identity anchor is already disposed: ${gitDir}`);
13477
- if (!fs.lstatSync(gitDir).isDirectory()) {
13572
+ if (!fs2.lstatSync(gitDir).isDirectory()) {
13478
13573
  throw new Error(`cached main-checkout .git directory is no longer current: ${gitDir}`);
13479
13574
  }
13480
13575
  },
@@ -13484,17 +13579,17 @@ function openMainCheckoutAnchor(gitDir) {
13484
13579
  };
13485
13580
  }
13486
13581
  function openGitWorktreeGenerationAnchor(worktreeRoot) {
13487
- const gitFile = path.join(worktreeRoot, ".git");
13488
- if (fs.lstatSync(gitFile).isDirectory())
13582
+ const gitFile = path2.join(worktreeRoot, ".git");
13583
+ if (fs2.lstatSync(gitFile).isDirectory())
13489
13584
  return openMainCheckoutAnchor(gitFile);
13490
- const descriptor = fs.openSync(gitFile, "r");
13585
+ const descriptor = fs2.openSync(gitFile, "r");
13491
13586
  let disposed = false;
13492
13587
  const anchor = {
13493
13588
  assertCurrent() {
13494
13589
  if (disposed)
13495
13590
  throw new Error(`cached .git identity anchor is already disposed: ${gitFile}`);
13496
- const held = fs.fstatSync(descriptor, { bigint: true });
13497
- const current = fs.lstatSync(gitFile, { bigint: true });
13591
+ const held = fs2.fstatSync(descriptor, { bigint: true });
13592
+ const current = fs2.lstatSync(gitFile, { bigint: true });
13498
13593
  if (!current.isFile() || !sameFileIdentity(held, current)) {
13499
13594
  throw new Error(`cached .git identity anchor no longer matches the selected checkout: ${gitFile}`);
13500
13595
  }
@@ -13503,7 +13598,7 @@ function openGitWorktreeGenerationAnchor(worktreeRoot) {
13503
13598
  if (disposed)
13504
13599
  return;
13505
13600
  disposed = true;
13506
- fs.closeSync(descriptor);
13601
+ fs2.closeSync(descriptor);
13507
13602
  }
13508
13603
  };
13509
13604
  try {
@@ -13617,84 +13712,84 @@ var init_worktree_git_runner = __esm(() => {
13617
13712
  });
13618
13713
 
13619
13714
  // dist/builtin/workflows/src/runs/shared/worktree-root.ts
13620
- import * as fs2 from "node:fs";
13621
- import * as path2 from "node:path";
13715
+ import * as fs3 from "node:fs";
13716
+ import * as path3 from "node:path";
13622
13717
  function pathFromPointer(contents, prefix, base) {
13623
13718
  if (!contents.startsWith(prefix))
13624
13719
  return;
13625
13720
  const value2 = contents.slice(prefix.length).trim();
13626
13721
  if (!value2)
13627
13722
  return;
13628
- return path2.resolve(base, value2);
13723
+ return path3.resolve(base, value2);
13629
13724
  }
13630
13725
  function readText(file) {
13631
13726
  try {
13632
- return fs2.readFileSync(file, "utf8");
13727
+ return fs3.readFileSync(file, "utf8");
13633
13728
  } catch {
13634
13729
  return;
13635
13730
  }
13636
13731
  }
13637
13732
  function samePath(left, right) {
13638
13733
  try {
13639
- const a = fs2.realpathSync.native(left);
13640
- const b = fs2.realpathSync.native(right);
13734
+ const a = fs3.realpathSync.native(left);
13735
+ const b = fs3.realpathSync.native(right);
13641
13736
  return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
13642
13737
  } catch {
13643
13738
  return false;
13644
13739
  }
13645
13740
  }
13646
13741
  function findGitRoot(cwd) {
13647
- let current = path2.resolve(cwd);
13742
+ let current = path3.resolve(cwd);
13648
13743
  try {
13649
- if (!fs2.statSync(current).isDirectory())
13650
- current = path2.dirname(current);
13744
+ if (!fs3.statSync(current).isDirectory())
13745
+ current = path3.dirname(current);
13651
13746
  } catch {
13652
13747
  return;
13653
13748
  }
13654
13749
  while (true) {
13655
13750
  try {
13656
- const entry = fs2.statSync(path2.join(current, ".git"));
13751
+ const entry = fs3.statSync(path3.join(current, ".git"));
13657
13752
  if (entry.isDirectory() || entry.isFile())
13658
13753
  return current;
13659
13754
  } catch {}
13660
- const parent = path2.dirname(current);
13755
+ const parent = path3.dirname(current);
13661
13756
  if (parent === current)
13662
13757
  return;
13663
13758
  current = parent;
13664
13759
  }
13665
13760
  }
13666
13761
  function resolveMainRepoRoot(repoRoot) {
13667
- const gitEntry = path2.join(repoRoot, ".git");
13762
+ const gitEntry = path3.join(repoRoot, ".git");
13668
13763
  let stats;
13669
13764
  try {
13670
- stats = fs2.statSync(gitEntry);
13765
+ stats = fs3.statSync(gitEntry);
13671
13766
  } catch {
13672
13767
  return;
13673
13768
  }
13674
13769
  if (stats.isDirectory())
13675
- return path2.resolve(repoRoot);
13770
+ return path3.resolve(repoRoot);
13676
13771
  if (!stats.isFile())
13677
13772
  return;
13678
13773
  const pointer = readText(gitEntry);
13679
13774
  if (pointer === undefined)
13680
13775
  return;
13681
13776
  const gitDir = pathFromPointer(pointer, "gitdir:", repoRoot);
13682
- if (gitDir === undefined || path2.basename(path2.dirname(gitDir)) !== "worktrees")
13777
+ if (gitDir === undefined || path3.basename(path3.dirname(gitDir)) !== "worktrees")
13683
13778
  return;
13684
- const commonGitDir = path2.dirname(path2.dirname(gitDir));
13685
- if (path2.basename(commonGitDir) !== ".git")
13779
+ const commonGitDir = path3.dirname(path3.dirname(gitDir));
13780
+ if (path3.basename(commonGitDir) !== ".git")
13686
13781
  return;
13687
- const backPointer = readText(path2.join(gitDir, "gitdir"));
13688
- const commonPointer = readText(path2.join(gitDir, "commondir"));
13782
+ const backPointer = readText(path3.join(gitDir, "gitdir"));
13783
+ const commonPointer = readText(path3.join(gitDir, "commondir"));
13689
13784
  if (backPointer === undefined || commonPointer === undefined)
13690
13785
  return;
13691
- const linkedGitEntry = path2.resolve(gitDir, backPointer.trim());
13692
- const declaredCommonDir = path2.resolve(gitDir, commonPointer.trim());
13786
+ const linkedGitEntry = path3.resolve(gitDir, backPointer.trim());
13787
+ const declaredCommonDir = path3.resolve(gitDir, commonPointer.trim());
13693
13788
  if (!backPointer.trim() || !commonPointer.trim())
13694
13789
  return;
13695
13790
  if (!samePath(linkedGitEntry, gitEntry) || !samePath(declaredCommonDir, commonGitDir))
13696
13791
  return;
13697
- return path2.dirname(commonGitDir);
13792
+ return path3.dirname(commonGitDir);
13698
13793
  }
13699
13794
  function findCanonicalGitRoot(cwd) {
13700
13795
  const repoRoot = findGitRoot(cwd);
@@ -13703,33 +13798,31 @@ function findCanonicalGitRoot(cwd) {
13703
13798
  var init_worktree_root = () => {};
13704
13799
 
13705
13800
  // dist/builtin/workflows/src/runs/shared/worktree-git.ts
13706
- import * as fs3 from "node:fs";
13707
- import * as path3 from "node:path";
13708
- function gitWorktreeSetupCacheKey(options) {
13709
- const repoRoot = repositoryRootForGitWorktree(options.cwd);
13710
- const { logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
13711
- const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
13801
+ import * as fs4 from "node:fs";
13802
+ import * as path4 from "node:path";
13803
+ function gitWorktreeSetupCacheKey(request) {
13712
13804
  return JSON.stringify([
13713
- comparableRealPath(gitCommonDirForWorktree(repoRoot)),
13714
- comparablePathThroughExistingAncestor(worktreeRoot)
13805
+ comparablePathThroughExistingAncestor(request.options.cwd),
13806
+ comparablePathThroughExistingAncestor(request.target)
13715
13807
  ]);
13716
13808
  }
13717
- function createGitWorktreeSetupCache() {
13809
+ function createGitWorktreeSetupCache(ownerRunId) {
13718
13810
  const results = new Map;
13719
13811
  let disposed = false;
13720
13812
  return {
13721
13813
  get(options) {
13722
13814
  if (disposed)
13723
13815
  throw new Error("Git worktree setup cache is already disposed");
13724
- const key = gitWorktreeSetupCacheKey(options);
13816
+ const request = resolveGitWorktreeSetupRequest(options);
13817
+ const key = gitWorktreeSetupCacheKey(request);
13725
13818
  const cached = results.get(key);
13726
13819
  if (cached !== undefined) {
13727
13820
  assertCachedGitWorktreeIdentity(cached, options);
13728
13821
  return cached.result;
13729
13822
  }
13730
- const result = setupGitWorktree(options);
13731
- results.set(key, { result, identity: captureGitWorktreeIdentity(result) });
13732
- return result;
13823
+ const setup = setupGitWorktreeFromRequest(request, ownerRunId);
13824
+ results.set(key, { ...setup, identity: captureGitWorktreeIdentity(setup) });
13825
+ return setup.result;
13733
13826
  },
13734
13827
  dispose() {
13735
13828
  if (disposed)
@@ -13761,10 +13854,10 @@ function worktreeRecoveryCommand(repositoryRoot, worktreeDir) {
13761
13854
  return `git -C ${quoteShellArg(repositoryRoot)} worktree remove --force ${quoteShellArg(worktreeDir)}`;
13762
13855
  }
13763
13856
  function hasGrandparent(value2) {
13764
- const parent = path3.dirname(value2);
13857
+ const parent = path4.dirname(value2);
13765
13858
  if (parent === value2)
13766
13859
  return false;
13767
- const grandparent = path3.dirname(parent);
13860
+ const grandparent = path4.dirname(parent);
13768
13861
  return grandparent !== parent;
13769
13862
  }
13770
13863
  function pathAncestors(value2) {
@@ -13772,7 +13865,7 @@ function pathAncestors(value2) {
13772
13865
  let current = value2;
13773
13866
  while (true) {
13774
13867
  ancestors.push(current);
13775
- const parent = path3.dirname(current);
13868
+ const parent = path4.dirname(current);
13776
13869
  if (parent === current)
13777
13870
  return ancestors;
13778
13871
  current = parent;
@@ -13781,89 +13874,167 @@ function pathAncestors(value2) {
13781
13874
  function shouldPreserveLogicalPath(logicalPath) {
13782
13875
  return pathAncestors(logicalPath).some((ancestor) => {
13783
13876
  try {
13784
- return fs3.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
13877
+ return fs4.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
13785
13878
  } catch {
13786
13879
  return false;
13787
13880
  }
13788
13881
  });
13789
13882
  }
13790
13883
  function canonicalizePreservingSymlinks(value2) {
13791
- const logicalPath = path3.resolve(value2);
13884
+ const logicalPath = path4.resolve(value2);
13792
13885
  const preserveLogicalPath = shouldPreserveLogicalPath(logicalPath);
13793
13886
  try {
13794
- const canonical = fs3.realpathSync.native(logicalPath);
13887
+ const canonical = fs4.realpathSync.native(logicalPath);
13795
13888
  return preserveLogicalPath && canonical !== logicalPath ? logicalPath : canonical;
13796
13889
  } catch {
13797
13890
  return logicalPath;
13798
13891
  }
13799
13892
  }
13800
- function resolveGitWorktreePath(value2, repoRoot) {
13893
+ function resolveGitWorktreePath(value2, baseDir) {
13801
13894
  const trimmed = value2.trim();
13802
13895
  if (!trimmed)
13803
13896
  throw new Error("gitWorktreeDir cannot be empty");
13804
13897
  if (trimmed.includes("\x00")) {
13805
13898
  throw new Error("gitWorktreeDir contains an unusable null byte; provide a valid path or omit gitWorktreeDir.");
13806
13899
  }
13807
- return canonicalizePreservingSymlinks(path3.isAbsolute(trimmed) ? trimmed : path3.resolve(repoRoot, trimmed));
13900
+ return canonicalizePreservingSymlinks(path4.isAbsolute(trimmed) ? trimmed : path4.resolve(baseDir, trimmed));
13808
13901
  }
13809
13902
  function comparableRealPath(value2) {
13810
- const realpath = fs3.realpathSync.native(value2).replace(/\\/g, "/");
13903
+ const realpath = fs4.realpathSync.native(value2).replace(/\\/g, "/");
13811
13904
  return process.platform === "win32" ? realpath.toLowerCase() : realpath;
13812
13905
  }
13813
- function comparablePathThroughExistingAncestor(value2) {
13814
- let existing = path3.resolve(value2);
13906
+ function nearestExistingAncestor(value2) {
13907
+ let existing = path4.resolve(value2);
13815
13908
  const missing = [];
13816
13909
  while (!pathExistsSync(existing)) {
13817
- const parent = path3.dirname(existing);
13910
+ const parent = path4.dirname(existing);
13818
13911
  if (parent === existing)
13819
13912
  break;
13820
- missing.unshift(path3.basename(existing));
13913
+ missing.unshift(path4.basename(existing));
13821
13914
  existing = parent;
13822
13915
  }
13823
- const resolved = path3.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
13916
+ return { existing, missing };
13917
+ }
13918
+ function comparablePathThroughExistingAncestor(value2) {
13919
+ const { existing, missing } = nearestExistingAncestor(value2);
13920
+ const resolved = path4.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
13824
13921
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
13825
13922
  }
13923
+ function isFileOrLink(value2) {
13924
+ try {
13925
+ const entry = fs4.lstatSync(value2);
13926
+ return entry.isFile() || entry.isSymbolicLink();
13927
+ } catch {
13928
+ return false;
13929
+ }
13930
+ }
13931
+ function isDirectory(value2) {
13932
+ try {
13933
+ return fs4.statSync(value2).isDirectory();
13934
+ } catch {
13935
+ return false;
13936
+ }
13937
+ }
13938
+ function looksLikeGitDirectory(directory) {
13939
+ if (!isDirectory(directory))
13940
+ return false;
13941
+ if (path4.basename(directory) === ".git")
13942
+ return true;
13943
+ if (!isFileOrLink(path4.join(directory, "HEAD")))
13944
+ return false;
13945
+ if (isFileOrLink(path4.join(directory, "commondir")))
13946
+ return true;
13947
+ return isDirectory(path4.join(directory, "objects")) && isDirectory(path4.join(directory, "refs"));
13948
+ }
13949
+ function enclosingGitMetadataDirectory(target) {
13950
+ const { existing } = nearestExistingAncestor(target);
13951
+ let realExisting = existing;
13952
+ try {
13953
+ realExisting = fs4.realpathSync.native(existing);
13954
+ } catch {}
13955
+ for (const candidate of new Set([...pathAncestors(existing), ...pathAncestors(realExisting)])) {
13956
+ if (looksLikeGitDirectory(candidate))
13957
+ return candidate;
13958
+ }
13959
+ const insideGitDir = runGitReadOnlyProbe(existing, ["rev-parse", "--is-inside-git-dir"]);
13960
+ if (insideGitDir.status !== 0 && isGitTimeoutResult(insideGitDir)) {
13961
+ throw new Error(`Timed out while validating gitWorktreeDir ${target}. Git reported: ${gitFailureMessage(insideGitDir)}`);
13962
+ }
13963
+ return insideGitDir.status === 0 && insideGitDir.stdout.trim() === "true" ? existing : undefined;
13964
+ }
13965
+ function assertSafeGitWorktreeTarget(target, invokingRoot) {
13966
+ const gitDirectory = enclosingGitMetadataDirectory(target);
13967
+ if (gitDirectory !== undefined) {
13968
+ 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.`);
13969
+ }
13970
+ if (invokingRoot !== undefined)
13971
+ validateWorktreeOutsideInvokingCheckout(target, invokingRoot);
13972
+ const { existing, missing } = nearestExistingAncestor(target);
13973
+ const workingTree = gitTopLevel(existing);
13974
+ if (workingTree === undefined)
13975
+ return;
13976
+ if (missing.length === 0 && comparableRealPath(target) === comparableRealPath(workingTree))
13977
+ return;
13978
+ 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.`);
13979
+ }
13826
13980
  function validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot) {
13827
13981
  const repository = comparableRealPath(repoRoot);
13828
13982
  const candidate = comparablePathThroughExistingAncestor(worktreeRoot);
13829
- const relativePath = path3.relative(repository, candidate);
13983
+ const relativePath = path4.relative(repository, candidate);
13830
13984
  if (relativePath === "") {
13831
- throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate same-repository worktree path.");
13985
+ throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate worktree path outside it.");
13832
13986
  }
13833
- if (!relativePath.startsWith(`..${path3.sep}`) && relativePath !== ".." && !path3.isAbsolute(relativePath)) {
13834
- throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate same-repository worktree path.");
13987
+ if (!relativePath.startsWith(`..${path4.sep}`) && relativePath !== ".." && !path4.isAbsolute(relativePath)) {
13988
+ throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate worktree path outside it.");
13835
13989
  }
13836
13990
  }
13837
13991
  function gitPathFromOutput(value2, cwd) {
13838
13992
  const trimmed = value2.trim();
13839
13993
  if (!trimmed)
13840
13994
  return;
13841
- return path3.isAbsolute(trimmed) ? path3.resolve(trimmed) : path3.resolve(cwd, trimmed);
13995
+ return path4.isAbsolute(trimmed) ? path4.resolve(trimmed) : path4.resolve(cwd, trimmed);
13842
13996
  }
13843
13997
  function pathExistsSync(value2) {
13998
+ return pathStatSync(value2) !== undefined;
13999
+ }
14000
+ function pathStatSync(value2) {
13844
14001
  try {
13845
- fs3.statSync(value2);
13846
- return true;
14002
+ return fs4.statSync(value2);
13847
14003
  } catch (error) {
13848
14004
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
13849
14005
  if (code === "ENOENT" || code === "ENOTDIR")
13850
- return false;
14006
+ return;
13851
14007
  throw error;
13852
14008
  }
13853
14009
  }
13854
- function repositoryRootForGitWorktree(cwd) {
14010
+ function probeInvokingRepository(cwd) {
13855
14011
  const result = runGitReadOnlyProbe(cwd, ["rev-parse", "--show-toplevel"]);
13856
14012
  if (result.status !== 0) {
13857
14013
  if (isGitTimeoutResult(result)) {
13858
14014
  throw new Error(`Timed out while checking the Git repository for gitWorktreeDir from ${cwd}. Git reported: ${gitFailureMessage(result)}`);
13859
14015
  }
13860
- 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)}`);
14016
+ return { failure: gitFailureMessage(result) };
13861
14017
  }
13862
- const normalized = gitPathFromOutput(result.stdout, cwd);
13863
- if (normalized === undefined) {
14018
+ const root = gitPathFromOutput(result.stdout, cwd);
14019
+ if (root === undefined) {
13864
14020
  throw new Error(`gitWorktreeDir could not resolve the repository top level from ${cwd}: git returned an empty path.`);
13865
14021
  }
13866
- return normalized;
14022
+ return { repository: { root, ...cwdWithinGitRepository(cwd, root) } };
14023
+ }
14024
+ function resolveGitWorktreeSetupRequest(options) {
14025
+ const probe = probeInvokingRepository(options.cwd);
14026
+ if ("repository" in probe) {
14027
+ return {
14028
+ options,
14029
+ repository: probe.repository,
14030
+ target: resolveGitWorktreePath(options.gitWorktreeDir, probe.repository.logicalRoot)
14031
+ };
14032
+ }
14033
+ return {
14034
+ options,
14035
+ repositoryProbeFailure: probe.failure,
14036
+ target: resolveGitWorktreePath(options.gitWorktreeDir, canonicalizePreservingSymlinks(options.cwd))
14037
+ };
13867
14038
  }
13868
14039
  function gitTopLevelFromResult(result, cwd, description) {
13869
14040
  if (result.status !== 0) {
@@ -13899,25 +14070,25 @@ function dirnameForEachRelativeComponent(base, relativePath) {
13899
14070
  continue;
13900
14071
  if (component === "..")
13901
14072
  return;
13902
- current = path3.dirname(current);
14073
+ current = path4.dirname(current);
13903
14074
  }
13904
14075
  return current;
13905
14076
  }
13906
14077
  function cwdWithinGitRepository(cwd, repoRoot) {
13907
- const sourceCwd = fs3.realpathSync.native(cwd);
13908
- const sourceRepoRoot = fs3.realpathSync.native(repoRoot);
13909
- const relativeCwd = path3.relative(sourceRepoRoot, sourceCwd);
13910
- const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path3.isAbsolute(relativeCwd) ? "" : relativeCwd;
14078
+ const sourceCwd = fs4.realpathSync.native(cwd);
14079
+ const sourceRepoRoot = fs4.realpathSync.native(repoRoot);
14080
+ const relativeCwd = path4.relative(sourceRepoRoot, sourceCwd);
14081
+ const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path4.isAbsolute(relativeCwd) ? "" : relativeCwd;
13911
14082
  const logicalCwd = canonicalizePreservingSymlinks(cwd);
13912
14083
  return {
13913
14084
  relativeCwd: safeRelativeCwd,
13914
- logicalRepoRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
14085
+ logicalRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
13915
14086
  };
13916
14087
  }
13917
14088
  function workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd) {
13918
- return relativeCwd === "" ? worktreeRoot : path3.join(worktreeRoot, relativeCwd);
14089
+ return relativeCwd === "" ? worktreeRoot : path4.join(worktreeRoot, relativeCwd);
13919
14090
  }
13920
- function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
14091
+ function validateGitWorktreeRoot(worktreeRoot) {
13921
14092
  const topLevel = gitTopLevel(worktreeRoot);
13922
14093
  if (topLevel === undefined) {
13923
14094
  throw new Error(`gitWorktreeDir already exists but is not a Git worktree: ${worktreeRoot}`);
@@ -13925,8 +14096,18 @@ function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
13925
14096
  if (comparableRealPath(worktreeRoot) !== comparableRealPath(topLevel)) {
13926
14097
  throw new Error(`gitWorktreeDir already exists but is not a Git worktree root: ${worktreeRoot}. Git top-level checkout is ${topLevel}`);
13927
14098
  }
13928
- if (comparableRealPath(gitCommonDirForWorktree(repoRoot)) !== comparableRealPath(gitCommonDirForWorktree(topLevel))) {
13929
- throw new Error(`gitWorktreeDir already exists but does not belong to the invoking Git repository: ${worktreeRoot}`);
14099
+ return gitCommonDirForWorktree(topLevel);
14100
+ }
14101
+ function existingGitWorktreeCommonDir(directory) {
14102
+ return gitTopLevel(directory) === undefined ? undefined : validateGitWorktreeRoot(directory);
14103
+ }
14104
+ function sameGitCommonDir(left, right) {
14105
+ return comparableRealPath(left) === comparableRealPath(right);
14106
+ }
14107
+ function validateCreatedGitWorktree(worktreeRoot, repository) {
14108
+ assertSafeGitWorktreeTarget(worktreeRoot, repository.root);
14109
+ if (!sameGitCommonDir(validateGitWorktreeRoot(worktreeRoot), gitCommonDirForWorktree(repository.root))) {
14110
+ throw new Error(`gitWorktreeDir does not belong to the invoking Git repository: ${worktreeRoot}`);
13930
14111
  }
13931
14112
  }
13932
14113
  function gitDirectoryForWorktree(cwd) {
@@ -13940,26 +14121,27 @@ function gitDirectoryForWorktree(cwd) {
13940
14121
  return gitDir;
13941
14122
  }
13942
14123
  function captureGitWorktreeIdentitySnapshot(setup) {
13943
- validateWorktreeOutsideInvokingCheckout(setup.worktreeRoot, setup.repositoryRoot);
13944
- validateExistingGitWorktreeRoot(setup.worktreeRoot, setup.repositoryRoot);
13945
- const stats = fs3.statSync(setup.worktreeRoot);
14124
+ const { worktreeRoot, repositoryRoot } = setup.result;
14125
+ assertSafeGitWorktreeTarget(worktreeRoot, setup.invokingRoot);
14126
+ const commonDir = validateGitWorktreeRoot(worktreeRoot);
14127
+ const stats = fs4.statSync(worktreeRoot);
13946
14128
  return {
13947
- worktreeRealPath: comparableRealPath(setup.worktreeRoot),
13948
- repositoryRealPath: comparableRealPath(setup.repositoryRoot),
13949
- gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(setup.worktreeRoot)),
13950
- commonDirRealPath: comparableRealPath(gitCommonDirForWorktree(setup.worktreeRoot)),
14129
+ worktreeRealPath: comparableRealPath(worktreeRoot),
14130
+ repositoryRealPath: comparableRealPath(repositoryRoot),
14131
+ gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(worktreeRoot)),
14132
+ commonDirRealPath: comparableRealPath(commonDir),
13951
14133
  device: stats.dev,
13952
14134
  inode: stats.ino
13953
14135
  };
13954
14136
  }
13955
14137
  function captureGitWorktreeIdentity(setup) {
13956
14138
  const snapshot = captureGitWorktreeIdentitySnapshot(setup);
13957
- return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.worktreeRoot) };
14139
+ return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.result.worktreeRoot) };
13958
14140
  }
13959
14141
  function assertCachedGitWorktreeIdentity(cached, options) {
13960
14142
  let current;
13961
14143
  try {
13962
- current = captureGitWorktreeIdentitySnapshot(cached.result);
14144
+ current = captureGitWorktreeIdentitySnapshot(cached);
13963
14145
  cached.identity.generation.assertCurrent();
13964
14146
  } catch (error) {
13965
14147
  const message = error instanceof Error ? error.message : String(error);
@@ -13967,34 +14149,58 @@ function assertCachedGitWorktreeIdentity(cached, options) {
13967
14149
  }
13968
14150
  const expected = cached.identity;
13969
14151
  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) {
13970
- throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended same-repository worktree.`);
13971
- }
14152
+ throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended worktree.`);
14153
+ }
14154
+ }
14155
+ function requireInvokingRepository(request, action) {
14156
+ if (request.repository !== undefined)
14157
+ return request.repository;
14158
+ throw new Error([
14159
+ `gitWorktreeDir requires the workflow to be invoked from inside a Git repository to ${action}.`,
14160
+ "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.",
14161
+ `Git reported: ${request.repositoryProbeFailure ?? "no repository"}`
14162
+ ].join(" "));
14163
+ }
14164
+ function setupGitWorktreeFromRequest(request, ownerRunId) {
14165
+ const { repository, target } = request;
14166
+ assertSafeGitWorktreeTarget(target, repository?.root);
14167
+ const entry = pathStatSync(target);
14168
+ if (entry === undefined)
14169
+ return createGitWorktreeAtPath(request, false);
14170
+ if (!entry.isDirectory())
14171
+ throw new Error(`gitWorktreeDir already exists but is not a directory: ${target}`);
14172
+ if (fs4.readdirSync(target).length === 0)
14173
+ return createGitWorktreeAtPath(request, true);
14174
+ const commonDir = existingGitWorktreeCommonDir(target);
14175
+ if (commonDir === undefined)
14176
+ return allocateGitWorktree(request, ownerRunId);
14177
+ const sameRepository = repository !== undefined && sameGitCommonDir(commonDir, gitCommonDirForWorktree(repository.root));
14178
+ return {
14179
+ result: {
14180
+ worktreeRoot: target,
14181
+ cwd: sameRepository ? workspaceCwdForGitWorktreeRoot(target, repository.relativeCwd) : target,
14182
+ repositoryRoot: sameRepository ? repository.root : target,
14183
+ created: false
14184
+ },
14185
+ ...repository !== undefined ? { invokingRoot: repository.root } : {}
14186
+ };
13972
14187
  }
13973
- function setupGitWorktree(options) {
13974
- const repoRoot = repositoryRootForGitWorktree(options.cwd);
13975
- const mainRoot = findCanonicalGitRoot(repoRoot);
14188
+ function createGitWorktreeAtPath(request, existingEmptyDirectory) {
14189
+ const { target: worktreeRoot } = request;
14190
+ const repository = requireInvokingRepository(request, `create a new worktree at ${worktreeRoot}`);
14191
+ const mainRoot = findCanonicalGitRoot(repository.root);
13976
14192
  if (mainRoot === undefined) {
13977
- throw new Error(`Unable to resolve the canonical main Git repository root from ${repoRoot}.`);
13978
- }
13979
- const { relativeCwd, logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
13980
- const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
13981
- validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot);
13982
- if (pathExistsSync(worktreeRoot)) {
13983
- validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
13984
- return {
13985
- worktreeRoot,
13986
- cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
13987
- repositoryRoot: repoRoot,
13988
- created: false
13989
- };
14193
+ throw new Error(`Unable to resolve the canonical main Git repository root from ${repository.root}.`);
13990
14194
  }
13991
- try {
13992
- fs3.mkdirSync(path3.dirname(worktreeRoot), { recursive: true });
13993
- } catch (error) {
13994
- const message = error instanceof Error ? error.message : String(error);
13995
- throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
14195
+ if (!existingEmptyDirectory) {
14196
+ try {
14197
+ fs4.mkdirSync(path4.dirname(worktreeRoot), { recursive: true });
14198
+ } catch (error) {
14199
+ const message = error instanceof Error ? error.message : String(error);
14200
+ throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
14201
+ }
13996
14202
  }
13997
- const baseRef = options.baseBranch?.trim() || "HEAD";
14203
+ const baseRef = request.options.baseBranch?.trim() || "HEAD";
13998
14204
  const result = runGit(mainRoot, ["worktree", "add", "--detach", worktreeRoot, baseRef]);
13999
14205
  if (result.status !== 0) {
14000
14206
  throw new Error([
@@ -14004,30 +14210,127 @@ function setupGitWorktree(options) {
14004
14210
  `));
14005
14211
  }
14006
14212
  try {
14007
- validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot);
14008
- validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
14213
+ validateCreatedGitWorktree(worktreeRoot, repository);
14009
14214
  } catch (error) {
14010
14215
  runGit(mainRoot, ["worktree", "remove", "--force", worktreeRoot]);
14011
14216
  const message = error instanceof Error ? error.message : String(error);
14012
14217
  throw new Error(`Created gitWorktreeDir failed post-creation validation: ${message}`);
14013
14218
  }
14014
14219
  return {
14015
- worktreeRoot,
14016
- cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
14017
- repositoryRoot: repoRoot,
14018
- created: true
14220
+ result: {
14221
+ worktreeRoot,
14222
+ cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, repository.relativeCwd),
14223
+ repositoryRoot: repository.root,
14224
+ created: true
14225
+ },
14226
+ invokingRoot: repository.root
14019
14227
  };
14020
14228
  }
14229
+ function containedWorktreeCwd(checkout, relativeCwd) {
14230
+ const cwd = workspaceCwdForGitWorktreeRoot(checkout, relativeCwd);
14231
+ let resolved;
14232
+ try {
14233
+ resolved = fs4.realpathSync.native(cwd);
14234
+ } catch {
14235
+ resolved = "";
14236
+ }
14237
+ const relative2 = resolved === "" ? undefined : path4.relative(fs4.realpathSync.native(checkout), resolved);
14238
+ if (relative2 === undefined || relative2 === ".." || relative2.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative2) || !fs4.statSync(resolved).isDirectory()) {
14239
+ throw new Error(`The selected base does not contain a working directory ${relativeCwd || "."} inside the worktree ${checkout}.`);
14240
+ }
14241
+ return cwd;
14242
+ }
14243
+ function allocatedGitWorktreeSetup(checkout, repository, created) {
14244
+ return {
14245
+ result: {
14246
+ worktreeRoot: checkout,
14247
+ cwd: containedWorktreeCwd(checkout, repository.relativeCwd),
14248
+ repositoryRoot: repository.root,
14249
+ created
14250
+ },
14251
+ invokingRoot: repository.root
14252
+ };
14253
+ }
14254
+ function validateOwnedGitWorktree(checkout, repository) {
14255
+ validateCreatedGitWorktree(checkout, repository);
14256
+ const gitDir = gitDirectoryForWorktree(checkout);
14257
+ if (sameGitCommonDir(gitDir, gitCommonDirForWorktree(checkout))) {
14258
+ throw new Error(`${checkout} is not a linked worktree`);
14259
+ }
14260
+ const backlink = fs4.readFileSync(path4.join(gitDir, "gitdir"), "utf8").trim();
14261
+ if (!backlink || comparableRealPath(path4.resolve(gitDir, backlink)) !== comparableRealPath(path4.join(checkout, ".git"))) {
14262
+ throw new Error(`the Git directory of ${checkout} belongs to another checkout`);
14263
+ }
14264
+ }
14265
+ function findOwnedGitWorktree(root, repository, ownerRunId) {
14266
+ const [checkout] = findOwnedWorktreeCheckouts(root, path4.basename(repository.root), ownerRunId);
14267
+ if (checkout === undefined)
14268
+ return;
14269
+ try {
14270
+ validateOwnedGitWorktree(checkout, repository);
14271
+ return allocatedGitWorktreeSetup(checkout, repository, false);
14272
+ } catch (error) {
14273
+ const message = error instanceof Error ? error.message : String(error);
14274
+ throw new Error(`The worktree this workflow run allocated under gitWorktreeDir ${root} can no longer be reused: ${checkout}. ${message}`);
14275
+ }
14276
+ }
14277
+ function allocateGitWorktree(request, ownerRunId) {
14278
+ const { target: root } = request;
14279
+ const repository = requireInvokingRepository(request, `create a new worktree under ${root}`);
14280
+ if (ownerRunId !== undefined) {
14281
+ const owned = findOwnedGitWorktree(root, repository, ownerRunId);
14282
+ if (owned !== undefined)
14283
+ return owned;
14284
+ }
14285
+ const baseRef = request.options.baseBranch?.trim() || "HEAD";
14286
+ const revision = runGit(repository.root, ["rev-parse", "--verify", "--end-of-options", `${baseRef}^{commit}`]);
14287
+ const commit = revision.status === 0 ? revision.stdout.trim() : "";
14288
+ if (commit === "") {
14289
+ throw new Error(`Failed to resolve ${baseRef} to a commit for gitWorktreeDir ${root}. Git reported: ${gitFailureMessage(revision)}`);
14290
+ }
14291
+ const checkout = allocateWorktreeCheckoutPath(root, path4.basename(repository.root));
14292
+ const add = runGit(repository.root, ["worktree", "add", "--detach", "--no-checkout", checkout, commit]);
14293
+ if (add.status !== 0) {
14294
+ removeEmptyWorktreeBucket(checkout);
14295
+ throw new Error(`Failed to create git worktree at ${checkout} under gitWorktreeDir ${root} from ${baseRef}. Git reported: ${gitFailureMessage(add)}`);
14296
+ }
14297
+ try {
14298
+ const gitDir = gitDirectoryForWorktree(checkout);
14299
+ runGitOrThrow(checkout, ["config", "--file", path4.join(gitDir, "config.worktree"), "core.worktree", checkout]);
14300
+ runGitOrThrow(checkout, ["--work-tree=.", "reset", "--hard", "--no-recurse-submodules", commit]);
14301
+ validateCreatedGitWorktree(checkout, repository);
14302
+ const setup = allocatedGitWorktreeSetup(checkout, repository, true);
14303
+ if (ownerRunId !== undefined)
14304
+ bindWorktreeOwner(gitDir, ownerRunId);
14305
+ return setup;
14306
+ } catch (error) {
14307
+ const message = error instanceof Error ? error.message : String(error);
14308
+ const removal = runGit(repository.root, ["worktree", "remove", "--force", checkout]);
14309
+ removeEmptyWorktreeBucket(checkout);
14310
+ const rollback = removal.status === 0 ? "" : ` Rolling back the incomplete worktree also failed; remove it with: ${worktreeRecoveryCommand(repository.root, checkout)}`;
14311
+ throw new Error(`Failed to set up git worktree at ${checkout} under gitWorktreeDir ${root}: ${message}${rollback}`);
14312
+ }
14313
+ }
14314
+ function runGitOrThrow(cwd, args) {
14315
+ const result = runGit(cwd, args);
14316
+ if (result.status !== 0)
14317
+ throw new Error(gitFailureMessage(result));
14318
+ }
14319
+ function setupGitWorktree(options) {
14320
+ return setupGitWorktreeFromRequest(resolveGitWorktreeSetupRequest(options)).result;
14321
+ }
14021
14322
  var init_worktree_git = __esm(() => {
14323
+ init_worktree_allocation();
14022
14324
  init_worktree_generation();
14023
14325
  init_worktree_git_runner();
14024
14326
  init_worktree_root();
14327
+ init_worktree_allocation();
14025
14328
  init_worktree_git_runner();
14026
14329
  });
14027
14330
 
14028
14331
  // dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts
14029
- function createGitWorktreeSetupCacheOwner(suppliedCache) {
14030
- const cache = suppliedCache ?? createGitWorktreeSetupCache();
14332
+ function createGitWorktreeSetupCacheOwner(suppliedCache, ownerRunId) {
14333
+ const cache = suppliedCache ?? createGitWorktreeSetupCache(ownerRunId);
14031
14334
  const ownsCache = suppliedCache === undefined;
14032
14335
  let released = false;
14033
14336
  return {
@@ -14048,20 +14351,20 @@ var init_worktree_cache_lifecycle = __esm(() => {
14048
14351
  });
14049
14352
 
14050
14353
  // dist/builtin/workflows/src/runs/shared/worktree-diff.ts
14051
- import * as fs4 from "node:fs";
14052
- import * as path4 from "node:path";
14354
+ import * as fs5 from "node:fs";
14355
+ import * as path5 from "node:path";
14053
14356
  function safePatchAgentName(agent) {
14054
14357
  return agent.replace(/[^\w.-]/g, "_");
14055
14358
  }
14056
14359
  function removeSyntheticPath(worktree, syntheticPath) {
14057
- const resolved = path4.resolve(worktree.path, syntheticPath);
14058
- const relative = path4.relative(worktree.path, resolved);
14059
- if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative)) {
14360
+ const resolved = path5.resolve(worktree.path, syntheticPath);
14361
+ const relative = path5.relative(worktree.path, resolved);
14362
+ if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path5.sep}`) || path5.isAbsolute(relative)) {
14060
14363
  return;
14061
14364
  }
14062
14365
  let stat;
14063
14366
  try {
14064
- stat = fs4.lstatSync(resolved);
14367
+ stat = fs5.lstatSync(resolved);
14065
14368
  } catch (error) {
14066
14369
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
14067
14370
  if (code === "ENOENT")
@@ -14069,14 +14372,14 @@ function removeSyntheticPath(worktree, syntheticPath) {
14069
14372
  throw error;
14070
14373
  }
14071
14374
  if (stat.isSymbolicLink()) {
14072
- fs4.unlinkSync(resolved);
14375
+ fs5.unlinkSync(resolved);
14073
14376
  return;
14074
14377
  }
14075
14378
  if (stat.isDirectory()) {
14076
- fs4.rmSync(resolved, { recursive: true, force: true });
14379
+ fs5.rmSync(resolved, { recursive: true, force: true });
14077
14380
  return;
14078
14381
  }
14079
- fs4.rmSync(resolved, { force: true });
14382
+ fs5.rmSync(resolved, { force: true });
14080
14383
  }
14081
14384
  function removeSyntheticPathsBeforeDiff(worktree) {
14082
14385
  if (worktree.syntheticPaths.length === 0)
@@ -14125,7 +14428,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
14125
14428
  const diffStat = runGitChecked(worktree.path, ["diff", "--cached", "--stat", setup.baseCommit]).trim();
14126
14429
  const patch = runGitChecked(worktree.path, ["diff", "--cached", setup.baseCommit]);
14127
14430
  const numstat = runGitChecked(worktree.path, ["diff", "--cached", "--numstat", setup.baseCommit]);
14128
- fs4.writeFileSync(patchPath, patch, "utf-8");
14431
+ fs5.writeFileSync(patchPath, patch, "utf-8");
14129
14432
  if (!patch.trim()) {
14130
14433
  return emptyDiff(worktree.index, agent, worktree.branch, patchPath);
14131
14434
  }
@@ -14143,7 +14446,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
14143
14446
  }
14144
14447
  function writeEmptyPatch(patchPath) {
14145
14448
  try {
14146
- fs4.writeFileSync(patchPath, "", "utf-8");
14449
+ fs5.writeFileSync(patchPath, "", "utf-8");
14147
14450
  } catch {}
14148
14451
  }
14149
14452
  function hasWorktreeChanges(diff) {
@@ -14151,7 +14454,7 @@ function hasWorktreeChanges(diff) {
14151
14454
  }
14152
14455
  function diffWorktrees(setup, agents, diffsDir) {
14153
14456
  try {
14154
- fs4.mkdirSync(diffsDir, { recursive: true });
14457
+ fs5.mkdirSync(diffsDir, { recursive: true });
14155
14458
  } catch {
14156
14459
  return [];
14157
14460
  }
@@ -14159,7 +14462,7 @@ function diffWorktrees(setup, agents, diffsDir) {
14159
14462
  for (let index = 0;index < setup.worktrees.length; index++) {
14160
14463
  const worktree = setup.worktrees[index];
14161
14464
  const agent = agents[index] ?? `task-${index + 1}`;
14162
- const patchPath = path4.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
14465
+ const patchPath = path5.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
14163
14466
  try {
14164
14467
  diffs.push(captureWorktreeDiff(setup, worktree, agent, patchPath));
14165
14468
  } catch {
@@ -14181,7 +14484,7 @@ function formatWorktreeDiffSummary(diffs) {
14181
14484
  }
14182
14485
  lines.push("");
14183
14486
  }
14184
- const patchesDir = path4.dirname(changed[0].patchPath);
14487
+ const patchesDir = path5.dirname(changed[0].patchPath);
14185
14488
  lines.push(`Full patches: ${patchesDir}`);
14186
14489
  return lines.join(`
14187
14490
  `).trimEnd();
@@ -14191,8 +14494,8 @@ var init_worktree_diff = __esm(() => {
14191
14494
  });
14192
14495
 
14193
14496
  // dist/builtin/workflows/src/runs/shared/worktree-post-create.ts
14194
- import * as fs5 from "node:fs";
14195
- import * as path5 from "node:path";
14497
+ import * as fs6 from "node:fs";
14498
+ import * as path6 from "node:path";
14196
14499
  function tracked(repo, relativePath) {
14197
14500
  const result = runGit(repo, ["ls-files", "--error-unmatch", "--", relativePath]);
14198
14501
  return result.status === 0;
@@ -14212,12 +14515,12 @@ function hasTrackedPathComponent(repo, relativePath) {
14212
14515
  return false;
14213
14516
  }
14214
14517
  function copyUntrackedFile(mainRoot, worktreeRoot, relativePath) {
14215
- const source = path5.join(mainRoot, relativePath);
14216
- const destination = path5.join(worktreeRoot, relativePath);
14217
- if (!fs5.existsSync(source) || fs5.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14518
+ const source = path6.join(mainRoot, relativePath);
14519
+ const destination = path6.join(worktreeRoot, relativePath);
14520
+ if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14218
14521
  return false;
14219
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
14220
- fs5.copyFileSync(source, destination);
14522
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
14523
+ fs6.copyFileSync(source, destination);
14221
14524
  return true;
14222
14525
  }
14223
14526
  function propagateLocalSettings(mainRoot, worktreeRoot) {
@@ -14230,14 +14533,14 @@ function propagateLocalSettings(mainRoot, worktreeRoot) {
14230
14533
  return copied;
14231
14534
  }
14232
14535
  function populatedHooksDirectory(mainRoot) {
14233
- const husky = path5.join(mainRoot, ".husky");
14536
+ const husky = path6.join(mainRoot, ".husky");
14234
14537
  try {
14235
- if (fs5.statSync(husky).isDirectory())
14538
+ if (fs6.statSync(husky).isDirectory())
14236
14539
  return husky;
14237
14540
  } catch {}
14238
- const hooks = path5.join(mainRoot, ".git", "hooks");
14541
+ const hooks = path6.join(mainRoot, ".git", "hooks");
14239
14542
  try {
14240
- const populated = fs5.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
14543
+ const populated = fs6.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
14241
14544
  return populated ? hooks : undefined;
14242
14545
  } catch {
14243
14546
  return;
@@ -14248,7 +14551,7 @@ function configureSharedHooksPath(mainRoot) {
14248
14551
  if (desired === undefined)
14249
14552
  return;
14250
14553
  const current = runGitPlain(mainRoot, ["config", "--get", "core.hooksPath"]);
14251
- if (current.status === 0 && path5.resolve(mainRoot, current.stdout.trim()) === desired)
14554
+ if (current.status === 0 && path6.resolve(mainRoot, current.stdout.trim()) === desired)
14252
14555
  return;
14253
14556
  const configured = runGitPlain(mainRoot, ["config", "core.hooksPath", desired]);
14254
14557
  if (configured.status !== 0) {
@@ -14257,10 +14560,10 @@ function configureSharedHooksPath(mainRoot) {
14257
14560
  }
14258
14561
  function normalizeSymlinkDirectory(value2) {
14259
14562
  const trimmed = value2.trim();
14260
- if (!trimmed || path5.isAbsolute(trimmed))
14563
+ if (!trimmed || path6.isAbsolute(trimmed))
14261
14564
  return;
14262
- const normalized = path5.normalize(trimmed);
14263
- if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path5.sep}`))
14565
+ const normalized = path6.normalize(trimmed);
14566
+ if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path6.sep}`))
14264
14567
  return;
14265
14568
  return normalized;
14266
14569
  }
@@ -14270,20 +14573,20 @@ function symlinkConfiguredDirectories(mainRoot, worktreeRoot, directories) {
14270
14573
  const relativePath = normalizeSymlinkDirectory(rawDirectory);
14271
14574
  if (relativePath === undefined || synthetic.includes(relativePath))
14272
14575
  continue;
14273
- const source = path5.join(mainRoot, relativePath);
14274
- const destination = path5.join(worktreeRoot, relativePath);
14275
- if (!fs5.existsSync(source) || fs5.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14576
+ const source = path6.join(mainRoot, relativePath);
14577
+ const destination = path6.join(worktreeRoot, relativePath);
14578
+ if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
14276
14579
  continue;
14277
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
14580
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
14278
14581
  try {
14279
- fs5.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
14582
+ fs6.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
14280
14583
  synthetic.push(relativePath);
14281
14584
  } catch {}
14282
14585
  }
14283
14586
  return synthetic;
14284
14587
  }
14285
14588
  function copyWorktreeIncludes(mainRoot, worktreeRoot) {
14286
- if (!fs5.existsSync(path5.join(mainRoot, ".worktreeinclude")))
14589
+ if (!fs6.existsSync(path6.join(mainRoot, ".worktreeinclude")))
14287
14590
  return;
14288
14591
  const ignored = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-standard"]);
14289
14592
  const included = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-from=.worktreeinclude"]);
@@ -14293,13 +14596,13 @@ function copyWorktreeIncludes(mainRoot, worktreeRoot) {
14293
14596
  for (const relativePath of included.stdout.split(/\r?\n/).filter(Boolean)) {
14294
14597
  if (!ignoredPaths.has(relativePath) || hasTrackedPathComponent(worktreeRoot, relativePath))
14295
14598
  continue;
14296
- const source = path5.join(mainRoot, relativePath);
14297
- const destination = path5.join(worktreeRoot, relativePath);
14599
+ const source = path6.join(mainRoot, relativePath);
14600
+ const destination = path6.join(worktreeRoot, relativePath);
14298
14601
  try {
14299
- if (!fs5.statSync(source).isFile() || fs5.existsSync(destination))
14602
+ if (!fs6.statSync(source).isFile() || fs6.existsSync(destination))
14300
14603
  continue;
14301
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
14302
- fs5.copyFileSync(source, destination);
14604
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
14605
+ fs6.copyFileSync(source, destination);
14303
14606
  } catch {}
14304
14607
  }
14305
14608
  }
@@ -14316,9 +14619,9 @@ var init_worktree_post_create = __esm(() => {
14316
14619
 
14317
14620
  // dist/builtin/workflows/src/runs/shared/worktree-setup.ts
14318
14621
  import { spawnSync as spawnSync2 } from "node:child_process";
14319
- import * as fs6 from "node:fs";
14622
+ import * as fs7 from "node:fs";
14320
14623
  import * as os from "node:os";
14321
- import * as path6 from "node:path";
14624
+ import * as path7 from "node:path";
14322
14625
  import { createChildProcessEnvironment as createChildProcessEnvironment2 } from "@bastani/atomic";
14323
14626
  function originDefaultBranch(mainRoot) {
14324
14627
  const symbolic = runGit(mainRoot, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]);
@@ -14338,7 +14641,7 @@ function originDefaultBranch(mainRoot) {
14338
14641
  }
14339
14642
  function resolveRepoState(cwd, explicitBaseBranch) {
14340
14643
  const cwdRelative = resolveRepoCwdRelative(cwd);
14341
- const toplevel = path6.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
14644
+ const toplevel = path7.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
14342
14645
  const mainRoot = findCanonicalGitRoot(toplevel);
14343
14646
  if (mainRoot === undefined)
14344
14647
  throw new Error(`unable to resolve canonical main Git repository root from ${toplevel}`);
@@ -14351,9 +14654,9 @@ function resolveRepoState(cwd, explicitBaseBranch) {
14351
14654
  return { toplevel, mainRoot, cwdRelative, baseCommit, baseRef };
14352
14655
  }
14353
14656
  function normalizeComparableCwd(cwd) {
14354
- const resolved = path6.resolve(cwd);
14657
+ const resolved = path7.resolve(cwd);
14355
14658
  try {
14356
- return fs6.realpathSync(resolved);
14659
+ return fs7.realpathSync(resolved);
14357
14660
  } catch {
14358
14661
  return resolved;
14359
14662
  }
@@ -14364,7 +14667,7 @@ function findWorktreeTaskCwdConflict(tasks, sharedCwd) {
14364
14667
  const task = tasks[index];
14365
14668
  if (!task.cwd)
14366
14669
  continue;
14367
- const taskCwd = path6.isAbsolute(task.cwd) ? task.cwd : path6.resolve(sharedCwd, task.cwd);
14670
+ const taskCwd = path7.isAbsolute(task.cwd) ? task.cwd : path7.resolve(sharedCwd, task.cwd);
14368
14671
  if (normalizeComparableCwd(taskCwd) === normalizedSharedCwd)
14369
14672
  continue;
14370
14673
  return { index, agent: task.agent, cwd: task.cwd };
@@ -14381,12 +14684,12 @@ function buildWorktreeBranch(runId, index) {
14381
14684
  return `worktree-${flattenedWorktreeName(runId, index)}`;
14382
14685
  }
14383
14686
  function buildWorktreePath(mainRoot, runId, index) {
14384
- return path6.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
14687
+ return path7.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
14385
14688
  }
14386
14689
  function ensureWorktreeIgnore(mainRoot) {
14387
- const worktreesRoot = path6.join(mainRoot, ".atomic", "worktrees");
14388
- fs6.mkdirSync(worktreesRoot, { recursive: true });
14389
- fs6.writeFileSync(path6.join(worktreesRoot, ".gitignore"), `*
14690
+ const worktreesRoot = path7.join(mainRoot, ".atomic", "worktrees");
14691
+ fs7.mkdirSync(worktreesRoot, { recursive: true });
14692
+ fs7.writeFileSync(path7.join(worktreesRoot, ".gitignore"), `*
14390
14693
  `, "utf8");
14391
14694
  }
14392
14695
  function resolveRepoCwdRelative(cwd) {
@@ -14395,7 +14698,7 @@ function resolveRepoCwdRelative(cwd) {
14395
14698
  throw new Error("worktree isolation requires a git repository");
14396
14699
  }
14397
14700
  const rawPrefix = runGitChecked(cwd, ["rev-parse", "--show-prefix"]).trim();
14398
- const normalizedPrefix = rawPrefix ? path6.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
14701
+ const normalizedPrefix = rawPrefix ? path7.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
14399
14702
  return normalizedPrefix === "." ? "" : normalizedPrefix;
14400
14703
  }
14401
14704
  function parseHookTimeout(timeoutMs) {
@@ -14413,19 +14716,19 @@ function resolveWorktreeSetupHook(repoRoot, config) {
14413
14716
  if (!hookPath) {
14414
14717
  throw new Error("worktree setup hook path cannot be empty");
14415
14718
  }
14416
- const expandedHookPath = hookPath.startsWith("~/") ? path6.join(os.homedir(), hookPath.slice(2)) : hookPath;
14719
+ const expandedHookPath = hookPath.startsWith("~/") ? path7.join(os.homedir(), hookPath.slice(2)) : hookPath;
14417
14720
  let resolvedPath;
14418
- if (path6.isAbsolute(expandedHookPath)) {
14721
+ if (path7.isAbsolute(expandedHookPath)) {
14419
14722
  resolvedPath = expandedHookPath;
14420
14723
  } else if (expandedHookPath.includes("/") || expandedHookPath.includes("\\")) {
14421
- resolvedPath = path6.resolve(repoRoot, expandedHookPath);
14724
+ resolvedPath = path7.resolve(repoRoot, expandedHookPath);
14422
14725
  } else {
14423
14726
  throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
14424
14727
  }
14425
- if (!fs6.existsSync(resolvedPath)) {
14728
+ if (!fs7.existsSync(resolvedPath)) {
14426
14729
  throw new Error(`worktree setup hook not found: ${resolvedPath}`);
14427
14730
  }
14428
- if (fs6.statSync(resolvedPath).isDirectory()) {
14731
+ if (fs7.statSync(resolvedPath).isDirectory()) {
14429
14732
  throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
14430
14733
  }
14431
14734
  return {
@@ -14437,17 +14740,17 @@ function normalizeSyntheticPath(worktreePath, rawPath) {
14437
14740
  const trimmed = rawPath.trim();
14438
14741
  if (!trimmed)
14439
14742
  throw new Error("synthetic path cannot be empty");
14440
- if (path6.isAbsolute(trimmed))
14743
+ if (path7.isAbsolute(trimmed))
14441
14744
  throw new Error(`synthetic path must be relative: ${rawPath}`);
14442
- const resolved = path6.resolve(worktreePath, trimmed);
14443
- const relative = path6.relative(worktreePath, resolved);
14745
+ const resolved = path7.resolve(worktreePath, trimmed);
14746
+ const relative = path7.relative(worktreePath, resolved);
14444
14747
  if (!relative || relative === ".") {
14445
14748
  throw new Error(`synthetic path cannot target the worktree root: ${rawPath}`);
14446
14749
  }
14447
- if (relative === ".." || relative.startsWith(`..${path6.sep}`) || path6.isAbsolute(relative)) {
14750
+ if (relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative)) {
14448
14751
  throw new Error(`synthetic path escapes the worktree root: ${rawPath}`);
14449
14752
  }
14450
- return path6.normalize(relative);
14753
+ return path7.normalize(relative);
14451
14754
  }
14452
14755
  function hasTrackedEntries(worktreePath, relativePath) {
14453
14756
  const result = runGit(worktreePath, ["ls-files", "--", relativePath]);
@@ -14519,16 +14822,16 @@ function waitForGitLockRelease() {
14519
14822
  }
14520
14823
  function unlinkWorktreeLinks(worktreePath, relativePaths) {
14521
14824
  for (const relativePath of new Set(relativePaths)) {
14522
- const target = path6.resolve(worktreePath, relativePath);
14523
- const relative = path6.relative(worktreePath, target);
14524
- if (!relative || relative === ".." || relative.startsWith(`..${path6.sep}`) || path6.isAbsolute(relative))
14825
+ const target = path7.resolve(worktreePath, relativePath);
14826
+ const relative = path7.relative(worktreePath, target);
14827
+ if (!relative || relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative))
14525
14828
  continue;
14526
14829
  let current = worktreePath;
14527
- for (const component of relative.split(path6.sep)) {
14528
- current = path6.join(current, component);
14830
+ for (const component of relative.split(path7.sep)) {
14831
+ current = path7.join(current, component);
14529
14832
  let stat;
14530
14833
  try {
14531
- stat = fs6.lstatSync(current);
14834
+ stat = fs7.lstatSync(current);
14532
14835
  } catch (error) {
14533
14836
  const code = error.code;
14534
14837
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -14538,7 +14841,7 @@ function unlinkWorktreeLinks(worktreePath, relativePaths) {
14538
14841
  if (!stat.isSymbolicLink())
14539
14842
  continue;
14540
14843
  if (current === target)
14541
- fs6.unlinkSync(current);
14844
+ fs7.unlinkSync(current);
14542
14845
  break;
14543
14846
  }
14544
14847
  }
@@ -14566,7 +14869,7 @@ function createSingleWorktree(mainRoot, cwdRelative, runId, index, baseRef, base
14566
14869
  cleanupSingleWorktree(mainRoot, { path: worktreePath, branch }, []);
14567
14870
  throw new Error(message);
14568
14871
  }
14569
- const agentCwd = cwdRelative ? path6.join(worktreePath, cwdRelative) : worktreePath;
14872
+ const agentCwd = cwdRelative ? path7.join(worktreePath, cwdRelative) : worktreePath;
14570
14873
  const syntheticPaths = [];
14571
14874
  try {
14572
14875
  syntheticPaths.push(...performPostCreationSetup(mainRoot, worktreePath, symlinkDirectories));
@@ -14635,8 +14938,8 @@ var init_worktree = __esm(() => {
14635
14938
  });
14636
14939
 
14637
14940
  // dist/builtin/workflows/src/runs/shared/worktree-cwd.ts
14638
- import { lstatSync as lstatSync5, realpathSync as realpathSync4 } from "node:fs";
14639
- import { dirname as dirname8, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve6, sep as sep5 } from "node:path";
14941
+ import { lstatSync as lstatSync6, realpathSync as realpathSync4 } from "node:fs";
14942
+ import { dirname as dirname9, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve7, sep as sep5 } from "node:path";
14640
14943
  function relativePathWithin(root, candidate) {
14641
14944
  const path = relative4(root, candidate);
14642
14945
  return path === ".." || path.startsWith(`..${sep5}`) || isAbsolute6(path) ? undefined : path;
@@ -14655,14 +14958,14 @@ function resolveWorktreeStageCwd(cwd, setup) {
14655
14958
  if (cwd === undefined || cwd.length === 0)
14656
14959
  return;
14657
14960
  const absoluteInput = isAbsolute6(cwd);
14658
- const candidate = absoluteInput ? cwd : resolve6(setup.cwd, cwd);
14961
+ const candidate = absoluteInput ? cwd : resolve7(setup.cwd, cwd);
14659
14962
  if (!absoluteInput && relativePathWithin(setup.worktreeRoot, candidate) === undefined) {
14660
14963
  throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a cwd inside the worktree.`);
14661
14964
  }
14662
14965
  const candidateRealPath = existingRealPath(candidate, "cwd");
14663
14966
  const worktreeRelative = relativePathWithin(worktreeRoot, candidateRealPath);
14664
14967
  if (worktreeRelative !== undefined)
14665
- return resolve6(setup.worktreeRoot, worktreeRelative);
14968
+ return resolve7(setup.worktreeRoot, worktreeRelative);
14666
14969
  if (!isAbsolute6(cwd)) {
14667
14970
  throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a path that remains inside the selected worktree.`);
14668
14971
  }
@@ -14671,9 +14974,9 @@ function resolveWorktreeStageCwd(cwd, setup) {
14671
14974
  }
14672
14975
  const repositoryRelative = absoluteInput ? relativePathWithin(repositoryRoot, candidateRealPath) : undefined;
14673
14976
  if (repositoryRelative === undefined) {
14674
- 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.`);
14977
+ 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.`);
14675
14978
  }
14676
- const mappedCwd = resolve6(setup.worktreeRoot, repositoryRelative);
14979
+ const mappedCwd = resolve7(setup.worktreeRoot, repositoryRelative);
14677
14980
  const mappedRealPath = existingRealPath(mappedCwd, "remapped worktree cwd");
14678
14981
  if (relativePathWithin(worktreeRoot, mappedRealPath) === undefined) {
14679
14982
  throw new Error(`atomic-workflows: cwd ${cwd} remaps through a path that resolves outside gitWorktreeDir ${setup.worktreeRoot}; remove the escaping symlink or omit cwd.`);
@@ -14684,7 +14987,7 @@ var init_worktree_cwd = () => {};
14684
14987
 
14685
14988
  // dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts
14686
14989
  import { existsSync as existsSync3 } from "node:fs";
14687
- import { isAbsolute as isAbsolute7, resolve as resolve7 } from "node:path";
14990
+ import { isAbsolute as isAbsolute7, resolve as resolve8 } from "node:path";
14688
14991
  function normalizeTaskContexts(previous) {
14689
14992
  if (previous === undefined)
14690
14993
  return [];
@@ -14737,7 +15040,7 @@ function taskPrevious(options) {
14737
15040
  function resolveWorkflowPath(filePath, baseDir) {
14738
15041
  if (isAbsolute7(filePath))
14739
15042
  return filePath;
14740
- return resolve7(baseDir ?? process.cwd(), filePath);
15043
+ return resolve8(baseDir ?? process.cwd(), filePath);
14741
15044
  }
14742
15045
  function taskBaseDir(options) {
14743
15046
  if (typeof options.chainDir === "string" && options.chainDir.trim().length > 0) {
@@ -14892,7 +15195,7 @@ function taskWithSharedDefaults(taskOptions, options) {
14892
15195
  var init_executor_task_prompts = () => {};
14893
15196
 
14894
15197
  // dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts
14895
- import { isAbsolute as isAbsolute8, join as join11, resolve as resolve8 } from "node:path";
15198
+ import { isAbsolute as isAbsolute8, join as join12, resolve as resolve9 } from "node:path";
14896
15199
  import { CONFIG_DIR_NAME } from "@bastani/atomic";
14897
15200
  function positiveConcurrency(value2) {
14898
15201
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 < 1)
@@ -15045,10 +15348,10 @@ function workflowInvocationMetadata(inputDefaults, workflowInvocationCwd, cache,
15045
15348
  function resolvedTaskCwd(cwd, workflowInvocationCwd) {
15046
15349
  if (cwd === undefined)
15047
15350
  return;
15048
- return isAbsolute8(cwd) ? cwd : resolve8(workflowInvocationCwd, cwd);
15351
+ return isAbsolute8(cwd) ? cwd : resolve9(workflowInvocationCwd, cwd);
15049
15352
  }
15050
15353
  function taskWorktreeOutputsRoot(runId) {
15051
- return join11(workflowArtifactRunPath(runId), "task-outputs");
15354
+ return join12(workflowArtifactRunPath(runId), "task-outputs");
15052
15355
  }
15053
15356
  function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCwd = process.cwd(), symlinkDirectories) {
15054
15357
  if (options.worktree !== true && !tasks.some((task) => task.worktree === true)) {
@@ -15058,7 +15361,7 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
15058
15361
  throw new Error("atomic-workflows: worktree and gitWorktreeDir are mutually exclusive; use gitWorktreeDir for a reusable worktree or worktree:true for temporary isolated worktrees.");
15059
15362
  }
15060
15363
  const explicitCwd = tasks.find((task) => typeof task.cwd === "string")?.cwd;
15061
- const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve8(workflowInvocationCwd, explicitCwd);
15364
+ const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve9(workflowInvocationCwd, explicitCwd);
15062
15365
  const conflict = findWorktreeTaskCwdConflict(tasks.map((task) => ({ agent: task.name, cwd: resolvedTaskCwd(task.cwd, workflowInvocationCwd) })), sharedCwd);
15063
15366
  if (conflict !== undefined)
15064
15367
  throw new Error(formatWorktreeTaskCwdConflict(conflict, sharedCwd));
@@ -15073,9 +15376,9 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
15073
15376
  tasks: tasks.map((task, index) => ({ ...task, cwd: setup.worktrees[index].agentCwd })),
15074
15377
  setup,
15075
15378
  agents,
15076
- diffsDir: join11(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
15379
+ diffsDir: join12(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
15077
15380
  outputIsolations: tasks.map((_, index) => ({
15078
- baseDir: join11(trustedRoot, runId, scope, String(index)),
15381
+ baseDir: join12(trustedRoot, runId, scope, String(index)),
15079
15382
  trustedRoot
15080
15383
  }))
15081
15384
  };
@@ -16802,8 +17105,12 @@ function createStageControlRegistry() {
16802
17105
  }
16803
17106
  await disposeEntries(entries);
16804
17107
  },
16805
- async releaseIdle(runId) {
16806
- for (const [stageId, entry] of [..._byRun.get(runId) ?? []]) {
17108
+ async releaseIdle(runId, only) {
17109
+ const runMap = _byRun.get(runId);
17110
+ const entries = only === undefined ? [...runMap ?? []] : [[only, runMap?.get(only)]];
17111
+ for (const [stageId, entry] of entries) {
17112
+ if (entry === undefined)
17113
+ continue;
16807
17114
  try {
16808
17115
  await releaseIdleEntry(runId, stageId, entry);
16809
17116
  } catch (error) {
@@ -16864,7 +17171,7 @@ var init_possible_stages = __esm(() => {
16864
17171
 
16865
17172
  // dist/builtin/workflows/src/workers/admission-host.ts
16866
17173
  import { execFile, execFileSync } from "node:child_process";
16867
- import { readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
17174
+ import { readdirSync as readdirSync4, readFileSync as readFileSync4 } from "node:fs";
16868
17175
  import { readFile } from "node:fs/promises";
16869
17176
  import { hostname } from "node:os";
16870
17177
  function admissionBootIdentity() {
@@ -16895,7 +17202,7 @@ function workerProcessExited(pid, final = false) {
16895
17202
  return true;
16896
17203
  if (process.platform === "linux") {
16897
17204
  try {
16898
- const stat = readFileSync2(`/proc/${pid}/stat`, "utf8");
17205
+ const stat = readFileSync4(`/proc/${pid}/stat`, "utf8");
16899
17206
  return stat.slice(stat.lastIndexOf(")") + 2).startsWith("Z");
16900
17207
  } catch {
16901
17208
  return admissionProcessStopped(pid);
@@ -16915,7 +17222,7 @@ function scanProcessGroup(group) {
16915
17222
  let complete = true;
16916
17223
  let entries;
16917
17224
  try {
16918
- entries = readdirSync2("/proc");
17225
+ entries = readdirSync4("/proc");
16919
17226
  } catch {
16920
17227
  return { members, complete: false };
16921
17228
  }
@@ -16924,7 +17231,7 @@ function scanProcessGroup(group) {
16924
17231
  continue;
16925
17232
  let stat;
16926
17233
  try {
16927
- stat = readFileSync2(`/proc/${entry}/stat`, "utf8");
17234
+ stat = readFileSync4(`/proc/${entry}/stat`, "utf8");
16928
17235
  } catch {
16929
17236
  complete = false;
16930
17237
  continue;
@@ -17155,6 +17462,7 @@ class SqlResourceAdmission {
17155
17462
  epoch: this.options.attempt.epoch
17156
17463
  }) : null);
17157
17464
  });
17465
+ let quarantinedSince;
17158
17466
  try {
17159
17467
  for (;; ) {
17160
17468
  signal?.throwIfAborted();
@@ -17164,7 +17472,9 @@ class SqlResourceAdmission {
17164
17472
  }
17165
17473
  const hostReason = this.hostReason();
17166
17474
  const pressure = this.stageStartPressure(kind, request?.delegated);
17475
+ let quarantined = undefined;
17167
17476
  const granted = await this.storage.transaction(async (tx) => {
17477
+ quarantined = undefined;
17168
17478
  await tx.run(`UPDATE ${this.owners} SET expires_at = CAST(unixepoch('subsec') * 1000 AS INTEGER) + ? WHERE id = ?`, OWNER_LEASE_MS, this.owner);
17169
17479
  const { root } = this.options;
17170
17480
  if (!await this.assertCurrentAttempt(tx)) {
@@ -17182,6 +17492,8 @@ class SqlResourceAdmission {
17182
17492
  if (control && control.state !== "running")
17183
17493
  reason ??= `root ${control.state}`;
17184
17494
  }
17495
+ const held = [];
17496
+ let blockedOtherwise = reason !== undefined;
17185
17497
  for (const scope of [`root:${root}`, "user"]) {
17186
17498
  const row = await tx.get(`SELECT config FROM ${this.configuration} WHERE scope = ?`, scope);
17187
17499
  const limit = row ? JSON.parse(String(row.config))[kind] : undefined;
@@ -17191,9 +17503,21 @@ class SqlResourceAdmission {
17191
17503
  const args = scope === "user" ? [kind] : [kind, root];
17192
17504
  const count = await tx.get(`SELECT COUNT(*) AS count FROM ${this.permits} WHERE kind = ? ${rootClause} AND state = 'granted'`, ...args);
17193
17505
  const older = await tx.get(`SELECT 1 AS waiting FROM ${this.permits} WHERE kind = ? ${rootClause} AND state = 'waiting' AND reason IS NOT ? AND ticket < (SELECT ticket FROM ${this.permits} WHERE operation = ?) LIMIT 1`, ...args, STAGE_START_PRESSURE_REASON, operation);
17194
- if (Number(count?.count) >= limit || older)
17195
- reason ??= `${scope} ${kind}`;
17506
+ const used = Number(count?.count);
17507
+ if (used < limit && !older)
17508
+ continue;
17509
+ reason ??= `${scope} ${kind}`;
17510
+ const quarantinedPermits = kind === "process" && used >= limit ? await tx.all(`SELECT process_identity FROM ${this.permits} WHERE kind = ? ${rootClause} AND state = 'granted' AND reason = ?`, ...args, QUARANTINED_REASON) : [];
17511
+ if (quarantinedPermits.length > 0 && used - quarantinedPermits.length < limit)
17512
+ held.push({
17513
+ limit: `${scope === "user" ? "admission.userLimits" : "admission.limits"}.${kind} (${limit})`,
17514
+ groups: quarantinedPermits.flatMap(({ process_identity }) => process_identity === null ? [] : [JSON.parse(process_identity).id])
17515
+ });
17516
+ else
17517
+ blockedOtherwise = true;
17196
17518
  }
17519
+ if (!blockedOtherwise && held.length > 0)
17520
+ quarantined = held;
17197
17521
  if (reason && request?.delegated)
17198
17522
  throw new Error(`Delegated session cannot be admitted without capacity headroom: ${reason}`);
17199
17523
  const stageStart = kind === "session" && request?.delegated !== true;
@@ -17206,6 +17530,14 @@ class SqlResourceAdmission {
17206
17530
  signal?.throwIfAborted();
17207
17531
  return release;
17208
17532
  }
17533
+ if (quarantined === undefined)
17534
+ quarantinedSince = undefined;
17535
+ else {
17536
+ const now = performance.now();
17537
+ quarantinedSince ??= now;
17538
+ if (now - quarantinedSince >= QUARANTINED_CAPACITY_WAIT_MS)
17539
+ throw new QuarantinedCapacityError(quarantined, now - quarantinedSince);
17540
+ }
17209
17541
  await delay(50 + Math.floor(Math.random() * 25), undefined, { signal });
17210
17542
  }
17211
17543
  } catch (error) {
@@ -17247,9 +17579,9 @@ class SqlResourceAdmission {
17247
17579
  await tx.run(`UPDATE ${this.permits} SET state = 'released', reason = 'host reboot confirmed' WHERE owner = ? AND state = 'granted'`, owner.id);
17248
17580
  } else if (stopped) {
17249
17581
  await tx.run(`UPDATE ${this.permits} SET state = 'released', reason = 'owner death confirmed' WHERE owner = ? AND kind = 'session' AND state = 'granted'`, owner.id);
17250
- await tx.run(`UPDATE ${this.permits} SET reason = ? WHERE owner = ? AND kind = 'process' AND state = 'granted' AND reason IS NOT ?`, UNCONFIRMED_REASON, owner.id, UNCONFIRMED_REASON);
17582
+ await tx.run(`UPDATE ${this.permits} SET reason = ? WHERE owner = ? AND kind = 'process' AND state = 'granted' AND reason IS NOT ? AND reason IS NOT ?`, UNCONFIRMED_REASON, owner.id, UNCONFIRMED_REASON, QUARANTINED_REASON);
17251
17583
  } else {
17252
- await tx.run(`UPDATE ${this.permits} SET reason = ? WHERE owner = ? AND state = 'granted' AND reason IS NOT ? AND EXISTS (SELECT 1 FROM ${this.owners} WHERE id = ? AND expires_at < ${NOW_MS})`, EXPIRED_REASON, owner.id, EXPIRED_REASON, owner.id);
17584
+ await tx.run(`UPDATE ${this.permits} SET reason = ? WHERE owner = ? AND state = 'granted' AND reason IS NOT ? AND reason IS NOT ? AND EXISTS (SELECT 1 FROM ${this.owners} WHERE id = ? AND expires_at < ${NOW_MS})`, EXPIRED_REASON, owner.id, EXPIRED_REASON, QUARANTINED_REASON, owner.id);
17253
17585
  }
17254
17586
  if (owner.host === admissionHost && process.platform !== "win32") {
17255
17587
  const processes = await tx.all(`SELECT * FROM ${this.permits} WHERE owner = ? AND state = 'granted' AND kind = 'process' AND process_identity IS NOT NULL`, owner.id);
@@ -17277,9 +17609,10 @@ class SqlResourceAdmission {
17277
17609
  return true;
17278
17610
  if (permit.state === "waiting")
17279
17611
  return stopped || !!permit.expired;
17280
- if (stopped && (permit.kind === "session" || permit.reason !== UNCONFIRMED_REASON))
17612
+ const quarantined = permit.reason === QUARANTINED_REASON;
17613
+ if (stopped && (permit.kind === "session" || permit.reason !== UNCONFIRMED_REASON && !quarantined))
17281
17614
  return true;
17282
- if (!stopped && permit.expired && permit.reason !== EXPIRED_REASON)
17615
+ if (!stopped && permit.expired && permit.reason !== EXPIRED_REASON && !quarantined)
17283
17616
  return true;
17284
17617
  return permit.kind === "process" && permit.host === admissionHost && process.platform !== "win32" && permit.process_identity !== null && processGroupStopped(permit.process_identity);
17285
17618
  }
@@ -17290,7 +17623,9 @@ class SqlResourceAdmission {
17290
17623
  await this.reconcile();
17291
17624
  return this.storage.transaction(async (tx) => {
17292
17625
  await tx.run(`UPDATE ${this.permits} SET state = 'released', reason = 'worker exit confirmed' WHERE root = ? AND holder = ? AND state IN ('waiting', 'granted') AND (kind = 'session' OR state = 'waiting')`, this.options.root, holder);
17293
- return (await tx.run(`UPDATE ${this.permits} SET reason = 'cleanup unconfirmed' WHERE root = ? AND holder = ? AND kind = 'process' AND state = 'granted'`, this.options.root, holder)).changes;
17626
+ await tx.run(`UPDATE ${this.permits} SET reason = ? WHERE root = ? AND holder = ? AND kind = 'process' AND state = 'granted' AND reason IS NOT ?`, UNCONFIRMED_REASON, this.options.root, holder, QUARANTINED_REASON);
17627
+ const held = await tx.get(`SELECT COUNT(*) AS count FROM ${this.permits} WHERE root = ? AND holder = ? AND kind = 'process' AND state = 'granted'`, this.options.root, holder);
17628
+ return Number(held?.count);
17294
17629
  });
17295
17630
  }
17296
17631
  async reapStoppedProcesses(holder) {
@@ -17337,10 +17672,13 @@ async function settleProcessGroups(storage, root, scope, reap) {
17337
17672
  survivors = await settle(REAP_KILL_GRACE_MS);
17338
17673
  }
17339
17674
  const confirmed = [...groups].flatMap(([group, operations]) => survivors.includes(group) ? [] : operations);
17340
- if (confirmed.length > 0)
17675
+ const quarantined = reap ? survivors.flatMap((group) => groups.get(group) ?? []) : [];
17676
+ if (confirmed.length > 0 || quarantined.length > 0)
17341
17677
  await storage.transaction(async (tx) => {
17342
17678
  for (const operation of confirmed)
17343
17679
  await tx.run(`UPDATE ${permits} SET state = 'released', reason = 'process group cleanup confirmed' WHERE operation = ? AND state = 'granted'`, operation);
17680
+ for (const operation of quarantined)
17681
+ await tx.run(`UPDATE ${permits} SET reason = ? WHERE operation = ? AND state = 'granted'`, QUARANTINED_REASON, operation);
17344
17682
  });
17345
17683
  return { survivors, unprobeable };
17346
17684
  }
@@ -17357,11 +17695,20 @@ async function reapProcessGroups(journal, root, scope) {
17357
17695
  return { survivors: [], unprobeable: [] };
17358
17696
  return settleProcessGroups(storage, root, scope, true);
17359
17697
  }
17360
- var OWNER_LEASE_MS = 30000, REAP_TERM_GRACE_MS = 5000, REAP_KILL_GRACE_MS = 1e4, REAP_POLL_MS = 50, RELEASED_PERMIT_RETENTION = 256, RELEASED_PERMIT_PRUNE_BATCH = 1000, EXPIRED_REASON = "owner expired; cleanup unconfirmed", UNCONFIRMED_REASON = "cleanup unconfirmed", ANONYMOUS_REASON = "owner identity unavailable; cleanup unconfirmed", NOW_MS = "CAST(unixepoch('subsec') * 1000 AS INTEGER)", LATE_ATTEMPT_POLL_MS = 100, LATE_ATTEMPT_REASON = "waiting for its attempt lease", STAGE_START_SPACING_MS = 5000, STAGE_START_PRESSURE_REASON = "paced for host load";
17698
+ var OWNER_LEASE_MS = 30000, REAP_TERM_GRACE_MS = 5000, REAP_KILL_GRACE_MS = 1e4, REAP_POLL_MS = 50, RELEASED_PERMIT_RETENTION = 256, RELEASED_PERMIT_PRUNE_BATCH = 1000, EXPIRED_REASON = "owner expired; cleanup unconfirmed", UNCONFIRMED_REASON = "cleanup unconfirmed", QUARANTINED_REASON = "cleanup unconfirmed; permit quarantined", ANONYMOUS_REASON = "owner identity unavailable; cleanup unconfirmed", QUARANTINED_CAPACITY_WAIT_MS, QuarantinedCapacityError, NOW_MS = "CAST(unixepoch('subsec') * 1000 AS INTEGER)", LATE_ATTEMPT_POLL_MS = 100, LATE_ATTEMPT_REASON = "waiting for its attempt lease", STAGE_START_SPACING_MS = 5000, STAGE_START_PRESSURE_REASON = "paced for host load";
17361
17699
  var init_resource_admission = __esm(() => {
17362
17700
  init_internal();
17363
17701
  init_sql_run_journal();
17702
+ init_workflow_infrastructure_error();
17364
17703
  init_admission_host();
17704
+ QUARANTINED_CAPACITY_WAIT_MS = REAP_TERM_GRACE_MS + REAP_KILL_GRACE_MS;
17705
+ QuarantinedCapacityError = class QuarantinedCapacityError extends WorkflowInfrastructureError {
17706
+ constructor(capacity, waitedMs) {
17707
+ const limits = capacity.map(({ limit }) => limit).join(" and ");
17708
+ const groups = [...new Set(capacity.flatMap(({ groups }) => groups))].join(", ");
17709
+ super("worker_cleanup_unconfirmed", `Local worker process cleanup unconfirmed; process permit refused after ${Math.round(waitedMs)} ms: ${limits} ${capacity.length === 1 ? "is" : "are"} held by quarantined permits of process groups ${groups} that survived SIGKILL`);
17710
+ }
17711
+ };
17365
17712
  });
17366
17713
 
17367
17714
  // dist/builtin/workflows/src/workers/admission-binding.ts
@@ -53663,10 +54010,10 @@ var init_verification_prompts = __esm(() => {
53663
54010
  // dist/builtin/workflows/builtin/pattern-artifact-root.ts
53664
54011
  import { randomUUID as randomUUID8 } from "node:crypto";
53665
54012
  import { mkdir as mkdir2 } from "node:fs/promises";
53666
- import { join as join12 } from "node:path";
54013
+ import { join as join13 } from "node:path";
53667
54014
  async function stableArtifactRoot(ctx, workflowName) {
53668
54015
  const cwd = ctx.cwd ?? process.cwd();
53669
- const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join12(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID8()}`));
54016
+ const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join13(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID8()}`));
53670
54017
  await mkdir2(artifactDir, { recursive: true });
53671
54018
  return artifactDir;
53672
54019
  }
@@ -53706,7 +54053,7 @@ function fold_usage(results) {
53706
54053
 
53707
54054
  // dist/builtin/workflows/builtin/adversarial-verification-runner.ts
53708
54055
  import { readFile as readFile2, writeFile } from "node:fs/promises";
53709
- import { join as join13 } from "node:path";
54056
+ import { join as join14 } from "node:path";
53710
54057
  import { Type as Type4 } from "typebox";
53711
54058
  function isRecord3(value2) {
53712
54059
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -53801,8 +54148,8 @@ async function writeInvalid(path, stage) {
53801
54148
  }
53802
54149
  async function runAdversarialVerification(ctx) {
53803
54150
  const root = await stableArtifactRoot(ctx, "adversarial-verification");
53804
- const criteriaPath = join13(root, "criteria.md");
53805
- const candidatePath = join13(root, "candidate.md");
54151
+ const criteriaPath = join14(root, "criteria.md");
54152
+ const candidatePath = join14(root, "candidate.md");
53806
54153
  const resolvedCriteria = resolveCriteria(ctx.inputs.criteria);
53807
54154
  await writeFile(criteriaPath, renderCriteriaMarkdown(resolvedCriteria));
53808
54155
  await ctx.task("worker", { prompt: renderWorkerPrompt(ctx.inputs.task), context: "fresh", output: candidatePath, outputMode: "file-only" });
@@ -53834,7 +54181,7 @@ async function runAdversarialVerification(ctx) {
53834
54181
  criterion,
53835
54182
  verifierIndex: index + 1,
53836
54183
  name,
53837
- artifactPath: join13(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
54184
+ artifactPath: join14(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
53838
54185
  });
53839
54186
  }
53840
54187
  }
@@ -53887,8 +54234,8 @@ async function runAdversarialVerification(ctx) {
53887
54234
  const decision = decide_verification(roundResult, { acceptMean, quorumFraction: QUORUM_FRACTION });
53888
54235
  finalDecision = decision;
53889
54236
  finalMean = meanScore(scoreReports);
53890
- scoreTablePath = join13(root, `verification-summary-${round}.json`);
53891
- reviewReportPath = join13(root, `review-${round}.json`);
54237
+ scoreTablePath = join14(root, `verification-summary-${round}.json`);
54238
+ reviewReportPath = join14(root, `review-${round}.json`);
53892
54239
  const summary = {
53893
54240
  scores: scoreReports,
53894
54241
  mean: finalMean,
@@ -54069,7 +54416,7 @@ var GROUNDED_REPORTING2 = "Before reporting progress, audit each claim against a
54069
54416
 
54070
54417
  // dist/builtin/workflows/builtin/classify-and-act-runner.ts
54071
54418
  import { writeFile as writeFile2 } from "node:fs/promises";
54072
- import { join as join14 } from "node:path";
54419
+ import { join as join15 } from "node:path";
54073
54420
  import { Type as Type6 } from "typebox";
54074
54421
  function safeName(value2) {
54075
54422
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -54109,7 +54456,7 @@ async function runClassifyAndAct(ctx) {
54109
54456
  const needsFallback = exactCategory === undefined || confidence < ctx.inputs.confidence_threshold;
54110
54457
  const fallback = needsFallback ? await resolveFallbackCategory(ctx, exactCategory) : undefined;
54111
54458
  const category = fallback?.category ?? exactCategory;
54112
- const classificationPath = join14(artifactDir, "classification.json");
54459
+ const classificationPath = join15(artifactDir, "classification.json");
54113
54460
  await writeFile2(classificationPath, JSON.stringify({
54114
54461
  proposed_category: proposedCategory,
54115
54462
  selected_category: category,
@@ -54119,7 +54466,7 @@ async function runClassifyAndAct(ctx) {
54119
54466
  fallback_used: needsFallback,
54120
54467
  fallback_mode: fallback?.fallbackMode ?? "none"
54121
54468
  }, null, 2));
54122
- const actionPath = join14(artifactDir, `action-${safeName(category)}.md`);
54469
+ const actionPath = join15(artifactDir, `action-${safeName(category)}.md`);
54123
54470
  const action = await ctx.task(`action-${safeName(category)}`, {
54124
54471
  tools: actionTools(category),
54125
54472
  prompt: actionPrompt({ prompt: ctx.inputs.prompt, category, classificationPath }),
@@ -54259,7 +54606,7 @@ var GROUNDED_REPORTING3 = "Before reporting progress, audit each claim against a
54259
54606
 
54260
54607
  // dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts
54261
54608
  import { writeFile as writeFile3 } from "node:fs/promises";
54262
- import { join as join15 } from "node:path";
54609
+ import { join as join16 } from "node:path";
54263
54610
  import { Type as Type8 } from "typebox";
54264
54611
  function safeName2(value2, index) {
54265
54612
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -54290,9 +54637,9 @@ async function runFanOutAndSynthesize(ctx) {
54290
54637
  context: "fresh"
54291
54638
  });
54292
54639
  const partitions = parsedPartitions(plan.structured, ctx.inputs.max_branches, ctx.inputs.prompt);
54293
- const partitionPath = join15(artifactDir, "partition-plan.json");
54640
+ const partitionPath = join16(artifactDir, "partition-plan.json");
54294
54641
  await writeFile3(partitionPath, JSON.stringify({ task: ctx.inputs.prompt, partitions }, null, 2));
54295
- const branchPaths = partitions.map((partition, index) => join15(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
54642
+ const branchPaths = partitions.map((partition, index) => join16(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
54296
54643
  const steps = partitions.map((partition, index) => ({
54297
54644
  name: `branch-${safeName2(partition.label, index)}`,
54298
54645
  prompt: branchPrompt({ prompt: ctx.inputs.prompt, ...partition }),
@@ -54302,13 +54649,13 @@ async function runFanOutAndSynthesize(ctx) {
54302
54649
  outputMode: "file-only"
54303
54650
  }));
54304
54651
  await ctx.parallel(steps, { concurrency: Math.min(ctx.inputs.max_concurrency, partitions.length), failFast: false });
54305
- const manifestPath = join15(artifactDir, "manifest.json");
54652
+ const manifestPath = join16(artifactDir, "manifest.json");
54306
54653
  await writeFile3(manifestPath, JSON.stringify({
54307
54654
  task: ctx.inputs.prompt,
54308
54655
  partition_plan: partitionPath,
54309
54656
  branches: partitions.map((partition, index) => ({ ...partition, artifact_path: branchPaths[index] }))
54310
54657
  }, null, 2));
54311
- const synthesisPath = join15(artifactDir, "synthesis.md");
54658
+ const synthesisPath = join16(artifactDir, "synthesis.md");
54312
54659
  const synthesis = await ctx.task("synthesize", {
54313
54660
  prompt: synthesisPrompt(ctx.inputs.prompt, manifestPath),
54314
54661
  context: "fresh",
@@ -54473,7 +54820,7 @@ var init_generate_and_filter_prompts = __esm(() => {
54473
54820
 
54474
54821
  // dist/builtin/workflows/builtin/generate-and-filter-runner.ts
54475
54822
  import { readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
54476
- import { join as join16 } from "node:path";
54823
+ import { join as join17 } from "node:path";
54477
54824
  import { Type as Type10 } from "typebox";
54478
54825
  function isRecord4(value2) {
54479
54826
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -54492,7 +54839,7 @@ function judgeDecision(value2) {
54492
54839
  }
54493
54840
  async function runGenerateAndFilter(ctx) {
54494
54841
  const root = await stableArtifactRoot(ctx, "generate-and-filter");
54495
- const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join16(root, `candidate-${index + 1}.md`));
54842
+ const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join17(root, `candidate-${index + 1}.md`));
54496
54843
  const shortlistLimit = Math.min(ctx.inputs.shortlist_size, ctx.inputs.num_candidates);
54497
54844
  await ctx.parallel(candidatePaths.map((path, index) => ({
54498
54845
  name: `generate-${index + 1}`,
@@ -54501,9 +54848,9 @@ async function runGenerateAndFilter(ctx) {
54501
54848
  output: path,
54502
54849
  outputMode: "file-only"
54503
54850
  })), { concurrency: ctx.inputs.max_concurrency, failFast: false });
54504
- const manifestPath = join16(root, "manifest.json");
54851
+ const manifestPath = join17(root, "manifest.json");
54505
54852
  await writeFile4(manifestPath, JSON.stringify({ task: ctx.inputs.prompt, candidate_artifact_paths: candidatePaths }, null, 2));
54506
- const filterPath = join16(root, "filter.json");
54853
+ const filterPath = join17(root, "filter.json");
54507
54854
  const filtered = await ctx.task("dedupe-and-filter", {
54508
54855
  prompt: renderFilterPrompt(ctx.inputs.prompt, candidatePaths, shortlistLimit),
54509
54856
  context: "fresh",
@@ -54520,7 +54867,7 @@ async function runGenerateAndFilter(ctx) {
54520
54867
  let judgePath = null;
54521
54868
  let decisionPath = filterPath;
54522
54869
  if (ctx.inputs.use_judge) {
54523
- judgePath = join16(root, "judge.json");
54870
+ judgePath = join17(root, "judge.json");
54524
54871
  const judgeCandidates = await Promise.all(shortlist.map(async (path) => ({ path, body: await readFile3(path, "utf8") })));
54525
54872
  const judgePrompt = renderJudgePrompt(ctx.inputs.prompt, filterPath, shortlistLimit, judgeCandidates);
54526
54873
  const judged = await ctx.task("judge", {
@@ -54536,7 +54883,7 @@ async function runGenerateAndFilter(ctx) {
54536
54883
  shortlist = judgedShortlist.length > 0 ? judgedShortlist : shortlist;
54537
54884
  decisionPath = judgePath;
54538
54885
  }
54539
- const finalPath = join16(root, "shortlist.md");
54886
+ const finalPath = join17(root, "shortlist.md");
54540
54887
  const finalShortlist = await ctx.task("final-shortlist", {
54541
54888
  prompt: renderFinalShortlistPrompt(ctx.inputs.prompt, decisionPath),
54542
54889
  context: "fresh",
@@ -55065,7 +55412,7 @@ var init_review_convergence = __esm(() => {
55065
55412
 
55066
55413
  // dist/builtin/workflows/builtin/goal-artifacts.ts
55067
55414
  import { writeFile as writeFile5 } from "node:fs/promises";
55068
- import { join as join17 } from "node:path";
55415
+ import { join as join18 } from "node:path";
55069
55416
  function artifactSafeName(value2) {
55070
55417
  const safe = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
55071
55418
  return safe.length > 0 ? safe : "artifact";
@@ -55076,7 +55423,7 @@ function withoutTurn(value2) {
55076
55423
  return copy;
55077
55424
  }
55078
55425
  async function writeReviewArtifact(artifactDir, reviewer, decision, rawText, convergenceDecision) {
55079
- const artifactPath = join17(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
55426
+ const artifactPath = join18(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
55080
55427
  await writeFile5(artifactPath, `${JSON.stringify({ reviewer, decision, convergence_decision: convergenceDecision, raw_text: rawText }, null, 2)}
55081
55428
  `, { encoding: "utf8" });
55082
55429
  return artifactPath;
@@ -55085,7 +55432,7 @@ async function writeReviewRoundArtifact(artifactDir, reviews, consolidatedFindin
55085
55432
  reviewer: review.reviewer,
55086
55433
  findings: review.findings
55087
55434
  }))), reverification = []) {
55088
- const artifactPath = join17(artifactDir, "review-round-latest.json");
55435
+ const artifactPath = join18(artifactDir, "review-round-latest.json");
55089
55436
  const visibleReviews = reviews.map(withoutTurn);
55090
55437
  await writeFile5(artifactPath, `${JSON.stringify({ reviews: visibleReviews, consolidated_findings: consolidatedFindings, reverification }, null, 2)}
55091
55438
  `, { encoding: "utf8" });
@@ -55315,7 +55662,7 @@ var init_goal_review = __esm(() => {
55315
55662
  // dist/builtin/workflows/builtin/goal-ledger.ts
55316
55663
  import { randomUUID as randomUUID9 } from "node:crypto";
55317
55664
  import { readFile as readFile4, rename, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
55318
- import { dirname as dirname9, join as join18 } from "node:path";
55665
+ import { dirname as dirname10, join as join19 } from "node:path";
55319
55666
  import { isDeepStrictEqual } from "node:util";
55320
55667
  function withoutTurn2(value2) {
55321
55668
  const copy = { ...value2 };
@@ -55340,7 +55687,7 @@ function modelVisibleLedger(ledger) {
55340
55687
  };
55341
55688
  }
55342
55689
  function goalLedgerStatePath(ledgerPath) {
55343
- return join18(dirname9(ledgerPath), LEDGER_STATE_FILENAME);
55690
+ return join19(dirname10(ledgerPath), LEDGER_STATE_FILENAME);
55344
55691
  }
55345
55692
  function appendLifecycleEvent(ledger, event, summary, turn = ledger.turns) {
55346
55693
  ledger.lifecycle.push({
@@ -55416,7 +55763,7 @@ function recoverLegacyExecutionInterruption(ledger) {
55416
55763
  return true;
55417
55764
  }
55418
55765
  async function createGoalLedger(objective, acceptanceCriteria, artifactDir) {
55419
- const ledgerPath = join18(artifactDir, LEDGER_FILENAME);
55766
+ const ledgerPath = join19(artifactDir, LEDGER_FILENAME);
55420
55767
  const existing = await readExistingGoalLedger(ledgerPath);
55421
55768
  if (existing !== undefined) {
55422
55769
  if (recoverLegacyExecutionInterruption(existing))
@@ -55923,7 +56270,7 @@ var init_goal_orchestrator_prompts = __esm(() => {
55923
56270
  });
55924
56271
 
55925
56272
  // dist/builtin/workflows/builtin/goal-runner.ts
55926
- import { join as join19 } from "node:path";
56273
+ import { join as join20 } from "node:path";
55927
56274
  function positiveInteger(value2, fallback) {
55928
56275
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 <= 0) {
55929
56276
  return fallback;
@@ -55974,7 +56321,7 @@ async function runGoalWorkflow(ctx, options) {
55974
56321
  appendLifecycleEvent(ledger, "work_turn_started", "Orchestrator started.", turn);
55975
56322
  await writeGoalLedger(ledgerPath, ledger);
55976
56323
  }
55977
- const orchestratorReceiptPath = join19(artifactDir, "orchestrator-receipt.md");
56324
+ const orchestratorReceiptPath = join20(artifactDir, "orchestrator-receipt.md");
55978
56325
  const orchestratorForkOptions = forkContinuationOptions(previousOrchestratorSessionId);
55979
56326
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? renderGoalOrchestratorPrompt({
55980
56327
  ledger,
@@ -56045,7 +56392,7 @@ async function runGoalWorkflow(ctx, options) {
56045
56392
  const reviewerName = result.name ?? result.stageName;
56046
56393
  const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
56047
56394
  const parsed = reviewerContractError === undefined ? parsedReviewDecisionFromResult(result, reviewerName) : { decision: reviewerErrorDecision(reviewerContractError.message), parsed: false, diagnostics: [reviewerContractError.message] };
56048
- const reviewArtifactPath = join19(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
56395
+ const reviewArtifactPath = join20(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
56049
56396
  const record = reviewDecisionToRecord({
56050
56397
  turn,
56051
56398
  reviewer: normalizedReviewerName,
@@ -56248,7 +56595,7 @@ var init_goal = __esm(() => {
56248
56595
  }),
56249
56596
  git_worktree_dir: Type15.String({
56250
56597
  default: "",
56251
- 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."
56598
+ 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."
56252
56599
  }),
56253
56600
  create_pr: Type15.Boolean({
56254
56601
  default: false,
@@ -56366,7 +56713,7 @@ var GROUNDED_REPORTING5 = "Before reporting progress, audit each claim against a
56366
56713
 
56367
56714
  // dist/builtin/workflows/builtin/loop-until-done-runner.ts
56368
56715
  import { mkdir as mkdir3, writeFile as writeFile7 } from "node:fs/promises";
56369
- import { join as join20 } from "node:path";
56716
+ import { join as join21 } from "node:path";
56370
56717
  import { Type as Type16 } from "typebox";
56371
56718
  function progressCurve(entries) {
56372
56719
  return entries.flatMap((entry) => entry.progress === undefined ? [] : [entry.progress.score]);
@@ -56449,18 +56796,18 @@ async function writeLedger(path, task, maxIterations, status, entries) {
56449
56796
  }
56450
56797
  async function runLoopUntilDone(ctx) {
56451
56798
  const artifactDir = await stableArtifactRoot(ctx, "loop-until-done");
56452
- const iterationsDir = join20(artifactDir, "iterations");
56453
- const evaluationsDir = join20(artifactDir, "evaluations");
56799
+ const iterationsDir = join21(artifactDir, "iterations");
56800
+ const evaluationsDir = join21(artifactDir, "evaluations");
56454
56801
  await mkdir3(iterationsDir, { recursive: true });
56455
56802
  await mkdir3(evaluationsDir, { recursive: true });
56456
- const ledgerPath = join20(artifactDir, "progress-ledger.json");
56803
+ const ledgerPath = join21(artifactDir, "progress-ledger.json");
56457
56804
  const entries = [];
56458
56805
  const iterationArtifactPaths = [];
56459
56806
  const evaluationArtifactPaths = [];
56460
56807
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, "active", entries);
56461
56808
  for (let iteration = 1;iteration <= ctx.inputs.max_iterations; iteration += 1) {
56462
- const iterationPath = join20(iterationsDir, `iteration-${iteration}.md`);
56463
- const evaluationPath = join20(evaluationsDir, `evaluation-${iteration}.json`);
56809
+ const iterationPath = join21(iterationsDir, `iteration-${iteration}.md`);
56810
+ const evaluationPath = join21(evaluationsDir, `evaluation-${iteration}.json`);
56464
56811
  iterationArtifactPaths.push(iterationPath);
56465
56812
  evaluationArtifactPaths.push(evaluationPath);
56466
56813
  await ctx.task(`iteration-${iteration}`, {
@@ -56509,7 +56856,7 @@ async function runLoopUntilDone(ctx) {
56509
56856
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, decision.done ? "complete" : "active", entries);
56510
56857
  if (decision.done) {
56511
56858
  const report = progressReport(entries);
56512
- const resultPath = join20(artifactDir, "result.md");
56859
+ const resultPath = join21(artifactDir, "result.md");
56513
56860
  const final = await ctx.task("completion-summary", {
56514
56861
  prompt: renderCompletionPrompt({ task: ctx.inputs.prompt, ledgerPath, iterationPath }),
56515
56862
  context: "fresh",
@@ -56626,9 +56973,9 @@ var init_loop_until_done = __esm(() => {
56626
56973
 
56627
56974
  // dist/builtin/workflows/builtin/open-claude-design-utils.ts
56628
56975
  import { spawnSync as spawnSync3 } from "node:child_process";
56629
- import { mkdirSync as mkdirSync5 } from "node:fs";
56976
+ import { mkdirSync as mkdirSync6 } from "node:fs";
56630
56977
  import { tmpdir, userInfo } from "node:os";
56631
- import { join as join21 } from "node:path";
56978
+ import { join as join22 } from "node:path";
56632
56979
  import { Type as Type18 } from "typebox";
56633
56980
  import { createChildProcessEnvironment as createChildProcessEnvironment3 } from "@bastani/atomic";
56634
56981
  function taggedPrompt3(sections) {
@@ -56671,32 +57018,32 @@ function tmpArtifactBase() {
56671
57018
  try {
56672
57019
  user = userInfo().username.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
56673
57020
  } catch {}
56674
- return join21(tmpdir(), `open-claude-design-${user}`);
57021
+ return join22(tmpdir(), `open-claude-design-${user}`);
56675
57022
  }
56676
57023
  function prepareArtifactDir(cwd = process.cwd()) {
56677
57024
  const runId = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
56678
57025
  const tmpCandidates = [
56679
- join21(tmpArtifactBase(), runId),
56680
- join21(tmpdir(), "open-claude-design", runId)
57026
+ join22(tmpArtifactBase(), runId),
57027
+ join22(tmpdir(), "open-claude-design", runId)
56681
57028
  ];
56682
- const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join21(cwd, "specs", "design", runId), ...tmpCandidates];
57029
+ const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join22(cwd, "specs", "design", runId), ...tmpCandidates];
56683
57030
  for (const candidate of candidates) {
56684
57031
  try {
56685
- mkdirSync5(candidate, { recursive: true });
57032
+ mkdirSync6(candidate, { recursive: true });
56686
57033
  return {
56687
57034
  runId,
56688
57035
  artifactDir: candidate,
56689
- previewPath: join21(candidate, "preview.html"),
56690
- specPath: join21(candidate, "spec.html")
57036
+ previewPath: join22(candidate, "preview.html"),
57037
+ specPath: join22(candidate, "spec.html")
56691
57038
  };
56692
57039
  } catch {}
56693
57040
  }
56694
- const fallback = join21(tmpArtifactBase(), runId);
57041
+ const fallback = join22(tmpArtifactBase(), runId);
56695
57042
  return {
56696
57043
  runId,
56697
57044
  artifactDir: fallback,
56698
- previewPath: join21(fallback, "preview.html"),
56699
- specPath: join21(fallback, "spec.html")
57045
+ previewPath: join22(fallback, "preview.html"),
57046
+ specPath: join22(fallback, "spec.html")
56700
57047
  };
56701
57048
  }
56702
57049
  function ensureAgentBrowser() {
@@ -57030,8 +57377,8 @@ var init_open_claude_design_live_protocol = __esm(() => {
57030
57377
  });
57031
57378
 
57032
57379
  // dist/builtin/workflows/builtin/open-claude-design-setup.ts
57033
- import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync3 } from "node:fs";
57034
- import { join as join22 } from "node:path";
57380
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "node:fs";
57381
+ import { join as join23 } from "node:path";
57035
57382
  function renderDiscoveryContext(discovery) {
57036
57383
  return [
57037
57384
  `Confirmed design brief: ${discovery.brief}`,
@@ -57096,10 +57443,10 @@ async function runDiscoveryAndInit(args) {
57096
57443
  };
57097
57444
  }
57098
57445
  function designContextPath(artifactDir) {
57099
- return join22(artifactDir, DESIGN_CONTEXT_FILENAME);
57446
+ return join23(artifactDir, DESIGN_CONTEXT_FILENAME);
57100
57447
  }
57101
57448
  function referencesBriefPath(artifactDir) {
57102
- return join22(artifactDir, REFERENCES_BRIEF_FILENAME);
57449
+ return join23(artifactDir, REFERENCES_BRIEF_FILENAME);
57103
57450
  }
57104
57451
  function buildReferenceDiscoveryPrompt(args) {
57105
57452
  const siteList = REFERENCE_DESIGN_SITES.map((site, index) => `${index + 1}. ${site.name} — ${site.url}`).join(`
@@ -57125,8 +57472,8 @@ function buildReferenceDiscoveryPrompt(args) {
57125
57472
  [
57126
57473
  "Use the agent-browser skill to open each gallery; if `agent-browser` reports a missing browser executable, follow the bootstrap rules and retry once.",
57127
57474
  "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.",
57128
- `Capture motion across the entire page: start \`agent-browser record start ${join22(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\`.`,
57129
- `Also run \`agent-browser screenshot ${join22(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
57475
+ `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\`.`,
57476
+ `Also run \`agent-browser screenshot ${join23(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
57130
57477
  "Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
57131
57478
  "Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
57132
57479
  "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.",
@@ -57151,8 +57498,8 @@ function buildReferenceDiscoveryPrompt(args) {
57151
57498
  }
57152
57499
  function writeRequiredContextArtifact(artifactDir, filePath, content, label) {
57153
57500
  try {
57154
- mkdirSync6(artifactDir, { recursive: true });
57155
- writeFileSync3(filePath, `${content}
57501
+ mkdirSync7(artifactDir, { recursive: true });
57502
+ writeFileSync4(filePath, `${content}
57156
57503
  `);
57157
57504
  } catch (error) {
57158
57505
  const detail = error instanceof Error ? error.message : String(error);
@@ -57703,7 +58050,7 @@ var init_ralph_review_gate = __esm(() => {
57703
58050
 
57704
58051
  // dist/builtin/workflows/builtin/ralph-core.ts
57705
58052
  import { mkdir as mkdir4, writeFile as writeFile8 } from "node:fs/promises";
57706
- import { dirname as dirname10, join as join23 } from "node:path";
58053
+ import { dirname as dirname11, join as join24 } from "node:path";
57707
58054
  import { Type as Type20 } from "typebox";
57708
58055
  function taggedPrompt4(sections) {
57709
58056
  return sections.map(([tag, content]) => {
@@ -57743,11 +58090,11 @@ function slugifyResearchTopic(prompt) {
57743
58090
  }
57744
58091
  function defaultResearchPath(prompt, now = new Date) {
57745
58092
  const date = now.toISOString().slice(0, 10);
57746
- return join23(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
58093
+ return join24(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
57747
58094
  }
57748
58095
  async function createImplementationNotesFile(prompt, runId) {
57749
58096
  const notesDir = await createWorkflowArtifactDirectory(runId);
57750
- const notesPath = join23(notesDir, IMPLEMENTATION_NOTES_FILENAME);
58097
+ const notesPath = join24(notesDir, IMPLEMENTATION_NOTES_FILENAME);
57751
58098
  const initialNotes = [
57752
58099
  "# Implementation Notes",
57753
58100
  "",
@@ -57768,7 +58115,7 @@ async function createImplementationNotesFile(prompt, runId) {
57768
58115
  }
57769
58116
  async function createQaEvidenceVideoPath(runId) {
57770
58117
  const qaDir = await createWorkflowArtifactDirectory(runId);
57771
- return join23(qaDir, QA_E2E_VIDEO_FILENAME);
58118
+ return join24(qaDir, QA_E2E_VIDEO_FILENAME);
57772
58119
  }
57773
58120
  function renderQaE2eVideoGuidance(qaVideoPath) {
57774
58121
  return [
@@ -57834,7 +58181,7 @@ function artifactSafeName2(value2) {
57834
58181
  return safe.length > 0 ? safe : "artifact";
57835
58182
  }
57836
58183
  async function writeJsonArtifact(path, content) {
57837
- await mkdir4(dirname10(path), { recursive: true });
58184
+ await mkdir4(dirname11(path), { recursive: true });
57838
58185
  await writeFile8(path, `${JSON.stringify(content, null, 2)}
57839
58186
  `, {
57840
58187
  encoding: "utf8"
@@ -58172,7 +58519,7 @@ var init_ralph_models = __esm(() => {
58172
58519
 
58173
58520
  // dist/builtin/workflows/builtin/ralph-runner.ts
58174
58521
  import { existsSync as existsSync4 } from "node:fs";
58175
- import { join as join24, resolve as resolve9 } from "node:path";
58522
+ import { join as join25, resolve as resolve10 } from "node:path";
58176
58523
  async function runRalphWorkflow(ctx, options) {
58177
58524
  const { prompt, acceptanceCriteria, maxLoops, comparisonBaseBranch, workflowStartCwd, createPr, runId } = options;
58178
58525
  let latestReviewReportPath;
@@ -58184,7 +58531,7 @@ async function runRalphWorkflow(ctx, options) {
58184
58531
  let finalPrReport;
58185
58532
  const workflowCwdContext = workflowCwdContextSection(workflowStartCwd);
58186
58533
  const workflowPrompt = prompt;
58187
- const workflowResearchPath = resolve9(workflowStartCwd, defaultResearchPath(workflowPrompt));
58534
+ const workflowResearchPath = resolve10(workflowStartCwd, defaultResearchPath(workflowPrompt));
58188
58535
  const implementationNotesPath = await createImplementationNotesFile(workflowPrompt, runId);
58189
58536
  const qaVideoPath = await createQaEvidenceVideoPath(runId);
58190
58537
  const artifactDir = await createWorkflowArtifactDirectory(runId);
@@ -58233,7 +58580,7 @@ async function runRalphWorkflow(ctx, options) {
58233
58580
  const researchPath = workflowResearchPath;
58234
58581
  finalResearchPath = researchPath;
58235
58582
  finalPlanPath = researchPath;
58236
- const orchestratorReportPath = join24(artifactDir, "orchestrator-report.md");
58583
+ const orchestratorReportPath = join25(artifactDir, "orchestrator-report.md");
58237
58584
  const orchestratorForkOptions = forkContinuationOptions3(previousOrchestratorSessionId);
58238
58585
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? taggedPrompt4([
58239
58586
  ["acceptance_criteria", keepContext(acceptanceCriteria)],
@@ -58369,7 +58716,7 @@ Read it before implementation or delegation because it is the primary current im
58369
58716
  diagnostics: parsed.diagnostics,
58370
58717
  allowFinalActionRemaining: createPr
58371
58718
  });
58372
- const artifactPath = join24(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
58719
+ const artifactPath = join25(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
58373
58720
  await writeJsonArtifact(artifactPath, {
58374
58721
  reviewer,
58375
58722
  decision: parsed.decision,
@@ -58425,7 +58772,7 @@ Read it before implementation or delegation because it is the primary current im
58425
58772
  usage: fold_usage([orchestrator, ...reviews, ...reverifyResults])
58426
58773
  }));
58427
58774
  }
58428
- latestReviewReportPath = await writeJsonArtifact(join24(artifactDir, "review-round-latest.json"), {
58775
+ latestReviewReportPath = await writeJsonArtifact(join25(artifactDir, "review-round-latest.json"), {
58429
58776
  convergence_decision: roundConvergenceDecision,
58430
58777
  convergence: convergenceEntries,
58431
58778
  consolidated_findings: reverified.batch,
@@ -58574,7 +58921,7 @@ var init_ralph = __esm(() => {
58574
58921
  }),
58575
58922
  git_worktree_dir: Type21.String({
58576
58923
  default: "",
58577
- 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."
58924
+ 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."
58578
58925
  }),
58579
58926
  create_pr: Type21.Boolean({
58580
58927
  default: false,
@@ -58794,7 +59141,7 @@ var init_tournament_prompts = __esm(() => {
58794
59141
 
58795
59142
  // dist/builtin/workflows/builtin/tournament-runner.ts
58796
59143
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile9 } from "node:fs/promises";
58797
- import { join as join25, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve10 } from "node:path";
59144
+ import { join as join26, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve11 } from "node:path";
58798
59145
  import { Type as Type22 } from "typebox";
58799
59146
  function serializableObject2(value2) {
58800
59147
  if (value2 === null || Array.isArray(value2) || typeof value2 !== "object")
@@ -58831,8 +59178,8 @@ function criterionSlug(id) {
58831
59178
  }
58832
59179
  function judgeArtifactPath(judgesDir, job, criterionIndex) {
58833
59180
  const filename = `judge-${job.a}-${job.b}-c${criterionIndex}-${criterionSlug(job.criterionId)}-r${job.rep}.json`;
58834
- const root = resolve10(judgesDir);
58835
- const path = resolve10(judgesDir, filename);
59181
+ const root = resolve11(judgesDir);
59182
+ const path = resolve11(judgesDir, filename);
58836
59183
  const fromRoot = relative5(root, path);
58837
59184
  if (fromRoot.startsWith("..") || isAbsolute9(fromRoot)) {
58838
59185
  throw new Error(`tournament: judge artifact escaped its directory: ${path}`);
@@ -58883,16 +59230,16 @@ function combineUsage(totals) {
58883
59230
  }
58884
59231
  async function runTournament(ctx) {
58885
59232
  const artifactDir = await stableArtifactRoot(ctx, "tournament");
58886
- const attemptsDir = join25(artifactDir, "attempts");
59233
+ const attemptsDir = join26(artifactDir, "attempts");
58887
59234
  const numAttempts = ctx.inputs.num_attempts ?? 4;
58888
59235
  const maxConcurrency = ctx.inputs.max_concurrency ?? 4;
58889
59236
  const nEvaluations = ctx.inputs.n_evaluations ?? 2;
58890
59237
  const pivotCount = ctx.inputs.pivots ?? 1;
58891
59238
  const seed = ctx.inputs.seed ?? 0;
58892
- const judgesDir = join25(artifactDir, "judges");
59239
+ const judgesDir = join26(artifactDir, "judges");
58893
59240
  await mkdir5(attemptsDir, { recursive: true });
58894
59241
  await mkdir5(judgesDir, { recursive: true });
58895
- const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join25(attemptsDir, `attempt-${index + 1}.md`));
59242
+ const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join26(attemptsDir, `attempt-${index + 1}.md`));
58896
59243
  const models = ctx.inputs.models;
58897
59244
  const attemptResults = await ctx.parallel(attemptArtifactPaths.map((path, index) => ({
58898
59245
  name: `attempt-${index + 1}`,
@@ -59057,7 +59404,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
59057
59404
  const outputRanking = ranking.map(({ label, meanPreference }) => ({ label, meanPreference }));
59058
59405
  const budgetPivots = Math.min(pivotCount, entrants.length);
59059
59406
  const comparisonBudget = (entrants.length + budgetPivots * (entrants.length - budgetPivots) + budgetPivots * (budgetPivots - 1) / 2) * criteria.length * nEvaluations;
59060
- const comparisonPath = join25(artifactDir, "comparisons.json");
59407
+ const comparisonPath = join26(artifactDir, "comparisons.json");
59061
59408
  const assignment = modelAssignment(entrants, models);
59062
59409
  const phaseUsage = {
59063
59410
  attempts: fold_usage(attemptResults),
@@ -59093,7 +59440,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
59093
59440
  await writeLedger(fold_usage([]));
59094
59441
  const winner = ranking[0];
59095
59442
  const winnerEntrant = entrants[winner.index];
59096
- const resultPath = join25(artifactDir, "winner.md");
59443
+ const resultPath = join26(artifactDir, "winner.md");
59097
59444
  const reducer = await ctx.task("comparisons-reducer", {
59098
59445
  prompt: renderComparisonsReducerPrompt({
59099
59446
  task: ctx.inputs.prompt,
@@ -59999,7 +60346,7 @@ class SqlPoolQueue {
59999
60346
  throw new Error("Stale pool coordinator authority", { cause: error });
60000
60347
  throw error;
60001
60348
  });
60002
- const row = await this.current(tx, lease, token);
60349
+ const row = await this.current(tx, lease, token, true);
60003
60350
  if (row.epoch !== lease.epoch)
60004
60351
  throw new Error(STALE_WORK_LEASE);
60005
60352
  assertSession();
@@ -62233,7 +62580,7 @@ function isBrokerStatusReport(value2) {
62233
62580
 
62234
62581
  // dist/builtin/intercom/broker/paths.ts
62235
62582
  import { homedir as homedir2 } from "os";
62236
- import { join as join26 } from "path";
62583
+ import { join as join27 } from "path";
62237
62584
  function getHomeDir() {
62238
62585
  if (process.platform === "win32") {
62239
62586
  if (process.env.USERPROFILE)
@@ -62250,7 +62597,7 @@ function expandTildePath(path) {
62250
62597
  if (path === "~")
62251
62598
  return getHomeDir();
62252
62599
  if (path.startsWith("~/") || process.platform === "win32" && path.startsWith("~\\")) {
62253
- return join26(getHomeDir(), path.slice(2));
62600
+ return join27(getHomeDir(), path.slice(2));
62254
62601
  }
62255
62602
  return path;
62256
62603
  }
@@ -62261,31 +62608,31 @@ function getAgentDir5() {
62261
62608
  const piAgentDir = process.env.PI_CODING_AGENT_DIR;
62262
62609
  if (piAgentDir)
62263
62610
  return expandTildePath(piAgentDir);
62264
- return join26(getHomeDir(), ".atomic", "agent");
62611
+ return join27(getHomeDir(), ".atomic", "agent");
62265
62612
  }
62266
62613
  function sanitizePipeSegment(value2) {
62267
62614
  return value2.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "default";
62268
62615
  }
62269
62616
  function getIntercomDirPath(agentDir = getAgentDir5()) {
62270
- return join26(agentDir, "intercom");
62617
+ return join27(agentDir, "intercom");
62271
62618
  }
62272
62619
  function getBrokerPidPath(agentDir = getAgentDir5()) {
62273
- return join26(getIntercomDirPath(agentDir), "broker.pid");
62620
+ return join27(getIntercomDirPath(agentDir), "broker.pid");
62274
62621
  }
62275
62622
  function getBrokerSpawnLockPath(agentDir = getAgentDir5()) {
62276
- return join26(getIntercomDirPath(agentDir), "broker.spawn.lock");
62623
+ return join27(getIntercomDirPath(agentDir), "broker.spawn.lock");
62277
62624
  }
62278
62625
  function getBrokerLogPath(agentDir = getAgentDir5()) {
62279
- return join26(getIntercomDirPath(agentDir), "broker.log");
62626
+ return join27(getIntercomDirPath(agentDir), "broker.log");
62280
62627
  }
62281
62628
  function getBrokerStartAnnouncementPath(agentDir = getAgentDir5()) {
62282
- return join26(getIntercomDirPath(agentDir), "broker.starting");
62629
+ return join27(getIntercomDirPath(agentDir), "broker.starting");
62283
62630
  }
62284
62631
  function getBrokerSocketPath(platform = process.platform, agentDir = getAgentDir5()) {
62285
62632
  if (platform === "win32") {
62286
62633
  return `\\\\.\\pipe\\pi-intercom-${sanitizePipeSegment(agentDir)}`;
62287
62634
  }
62288
- return join26(getIntercomDirPath(agentDir), "broker.sock");
62635
+ return join27(getIntercomDirPath(agentDir), "broker.sock");
62289
62636
  }
62290
62637
  var BROKER_STORAGE_ENV = "ATOMIC_STORAGE";
62291
62638
  var init_paths = () => {};
@@ -63969,11 +64316,11 @@ var init_client = __esm(() => {
63969
64316
  var BROKER_READY_TIMEOUT_MS = 30000, MIN_BROKER_STARTUP_TIMEOUT_MS = 1000;
63970
64317
 
63971
64318
  // dist/builtin/intercom/broker/start-announcement.ts
63972
- import { readFileSync as readFileSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
64319
+ import { readFileSync as readFileSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
63973
64320
  function readBrokerStartAnnouncement(announcement) {
63974
64321
  let text;
63975
64322
  try {
63976
- text = readFileSync3(announcement.path, "utf-8");
64323
+ text = readFileSync5(announcement.path, "utf-8");
63977
64324
  } catch {
63978
64325
  return;
63979
64326
  }
@@ -63992,26 +64339,26 @@ var init_start_announcement = () => {};
63992
64339
  // dist/builtin/intercom/broker/spawn.ts
63993
64340
  import { spawn } from "child_process";
63994
64341
  import { randomUUID as randomUUID14 } from "crypto";
63995
- import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync7, openSync as openSync3, readFileSync as readFileSync4, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "fs";
63996
- import { join as join27, dirname as dirname11 } from "path";
64342
+ import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync6, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
64343
+ import { join as join28, dirname as dirname12 } from "path";
63997
64344
  import { fileURLToPath as fileURLToPath4 } from "url";
63998
64345
  import { createRequire as createRequire3 } from "module";
63999
64346
  import { createChildProcessEnvironment as createChildProcessEnvironment4, isBunBinary, processSharedStorageSelection } from "@bastani/atomic";
64000
64347
  function isIntercomPackageRoot(dir) {
64001
- return existsSync5(join27(dir, "package.json")) && existsSync5(join27(dir, "broker"));
64348
+ return existsSync5(join28(dir, "package.json")) && existsSync5(join28(dir, "broker"));
64002
64349
  }
64003
64350
  function resolveIntercomPackageRoot(moduleHref) {
64004
- const here = dirname11(fileURLToPath4(moduleHref));
64351
+ const here = dirname12(fileURLToPath4(moduleHref));
64005
64352
  if (isIntercomPackageRoot(here))
64006
64353
  return here;
64007
- return join27(here, "..");
64354
+ return join28(here, "..");
64008
64355
  }
64009
64356
  function resolveBrokerEntrypoint(packageRoot) {
64010
- const bundled = join27(packageRoot, "broker", "broker.bundle.mjs");
64011
- return existsSync5(bundled) ? bundled : join27(packageRoot, "broker", "broker.ts");
64357
+ const bundled = join28(packageRoot, "broker", "broker.bundle.mjs");
64358
+ return existsSync5(bundled) ? bundled : join28(packageRoot, "broker", "broker.ts");
64012
64359
  }
64013
64360
  function ensurePrivateDirectory(path) {
64014
- mkdirSync7(path, { recursive: true, mode: 448 });
64361
+ mkdirSync8(path, { recursive: true, mode: 448 });
64015
64362
  if (process.platform !== "win32")
64016
64363
  chmodSync(path, 448);
64017
64364
  }
@@ -64024,14 +64371,14 @@ function getCurrentBrokerRuntime() {
64024
64371
  return isBunBinary ? "bun-binary" : "bun-source";
64025
64372
  }
64026
64373
  function requireFromExtensionDir(extensionDir) {
64027
- return createRequire3(join27(extensionDir, "package.json"));
64374
+ return createRequire3(join28(extensionDir, "package.json"));
64028
64375
  }
64029
64376
  function getJitiCliPath(extensionDir = EXTENSION_DIR) {
64030
64377
  try {
64031
64378
  const jitiPackage = requireFromExtensionDir(extensionDir).resolve("jiti/package.json");
64032
- return join27(dirname11(jitiPackage), "lib", "jiti-cli.mjs");
64379
+ return join28(dirname12(jitiPackage), "lib", "jiti-cli.mjs");
64033
64380
  } catch {
64034
- return join27(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
64381
+ return join28(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
64035
64382
  }
64036
64383
  }
64037
64384
  function getDefaultBrokerRunnerPath(extensionDir) {
@@ -64053,7 +64400,7 @@ function quoteWindowsArg(value2) {
64053
64400
  return `"${value2.replace(/"/g, '""')}"`;
64054
64401
  }
64055
64402
  function getWindowsHiddenLauncherPath(intercomDir = INTERCOM_DIR) {
64056
- return join27(intercomDir, "broker-launch.vbs");
64403
+ return join28(intercomDir, "broker-launch.vbs");
64057
64404
  }
64058
64405
  function usesDefaultBrokerCommand(brokerCommand, brokerArgs) {
64059
64406
  return brokerCommand === "npx" && brokerArgs.length === 2 && brokerArgs[0] === "--no-install" && brokerArgs[1] === "tsx";
@@ -64080,8 +64427,8 @@ function getWindowsHiddenLauncherScript(commandLine) {
64080
64427
  `);
64081
64428
  }
64082
64429
  function writeWindowsHiddenLauncher(commandLine, launcherPath = getWindowsHiddenLauncherPath()) {
64083
- ensurePrivateDirectory(dirname11(launcherPath));
64084
- writeFileSync5(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
64430
+ ensurePrivateDirectory(dirname12(launcherPath));
64431
+ writeFileSync6(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
64085
64432
  return launcherPath;
64086
64433
  }
64087
64434
  function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath, runtime = getCurrentBrokerRuntime(), logPath = BROKER_LOG) {
@@ -64124,14 +64471,14 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore",
64124
64471
  };
64125
64472
  }
64126
64473
  function resetBrokerLog(logPath = BROKER_LOG) {
64127
- ensurePrivateDirectory(dirname11(logPath));
64474
+ ensurePrivateDirectory(dirname12(logPath));
64128
64475
  try {
64129
64476
  const previous = readBrokerLogTail(logPath);
64130
64477
  closeSync3(openSync3(logPath, "w"));
64131
64478
  if (previous.length > 0) {
64132
64479
  try {
64133
64480
  const previousPath = `${logPath}.previous`;
64134
- writeFileSync5(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
64481
+ writeFileSync6(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
64135
64482
  if (process.platform !== "win32")
64136
64483
  chmodSync(previousPath, 384);
64137
64484
  } catch {}
@@ -64275,7 +64622,7 @@ async function isBrokerRunning() {
64275
64622
  if (!existsSync5(BROKER_PID))
64276
64623
  return false;
64277
64624
  try {
64278
- const pid = parseInt(readFileSync4(BROKER_PID, "utf-8").trim(), 10);
64625
+ const pid = parseInt(readFileSync6(BROKER_PID, "utf-8").trim(), 10);
64279
64626
  if (!Number.isFinite(pid))
64280
64627
  return false;
64281
64628
  process.kill(pid, 0);
@@ -64300,7 +64647,7 @@ function handSpawnLockToBroker(pid, owner) {
64300
64647
  }
64301
64648
  function ownsSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
64302
64649
  try {
64303
- return readFileSync4(lockPath, "utf-8").startsWith(owner);
64650
+ return readFileSync6(lockPath, "utf-8").startsWith(owner);
64304
64651
  } catch {
64305
64652
  return false;
64306
64653
  }
@@ -64312,7 +64659,7 @@ function acquireSpawnLock() {
64312
64659
  ${Date.now()}
64313
64660
  `;
64314
64661
  try {
64315
- writeFileSync5(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
64662
+ writeFileSync6(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
64316
64663
  return owner;
64317
64664
  } catch (error) {
64318
64665
  if (!(error instanceof Error) || error.code !== "EEXIST") {
@@ -64342,7 +64689,7 @@ function isSpawnLockStale(lockPath = BROKER_SPAWN_LOCK, nowMs = Date.now()) {
64342
64689
  return false;
64343
64690
  }
64344
64691
  try {
64345
- const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync4(lockPath, "utf-8").trim().split(`
64692
+ const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync6(lockPath, "utf-8").trim().split(`
64346
64693
  `);
64347
64694
  const spawnerPid = Number.parseInt(spawnerLine, 10);
64348
64695
  const createdAt = Number.parseInt(createdAtLine, 10);
@@ -64420,14 +64767,14 @@ var init_reply_waiter = __esm(() => {
64420
64767
  });
64421
64768
 
64422
64769
  // dist/builtin/intercom/config.ts
64423
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
64770
+ import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
64424
64771
  import { getAgentConfigPaths } from "@bastani/atomic";
64425
64772
  function loadConfig() {
64426
64773
  if (!existsSync6(CONFIG_PATH)) {
64427
64774
  return { ...defaults };
64428
64775
  }
64429
64776
  try {
64430
- const raw = readFileSync5(CONFIG_PATH, "utf-8");
64777
+ const raw = readFileSync7(CONFIG_PATH, "utf-8");
64431
64778
  const parsed = JSON.parse(raw);
64432
64779
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
64433
64780
  throw new Error("Config must be a JSON object");
@@ -65010,12 +65357,12 @@ var init_sql_pool_usage = __esm(() => {
65010
65357
 
65011
65358
  // dist/builtin/workflows/src/workers/pooled-watch-trace.ts
65012
65359
  import { appendFileSync as appendFileSync2 } from "node:fs";
65013
- import { dirname as dirname12, join as join28, resolve as resolve11 } from "node:path";
65360
+ import { dirname as dirname13, join as join29, resolve as resolve12 } from "node:path";
65014
65361
  function configurePooledWatchTrace(journalPath, processRole) {
65015
65362
  if (setting === undefined || setting === "" || setting === "0")
65016
65363
  return;
65017
65364
  role = processRole;
65018
- file = setting === "1" ? join28(dirname12(resolve11(journalPath)), "pooled-watch-trace.jsonl") : resolve11(setting);
65365
+ file = setting === "1" ? join29(dirname13(resolve12(journalPath)), "pooled-watch-trace.jsonl") : resolve12(setting);
65019
65366
  }
65020
65367
  function tracePooledWatch(step, detail) {
65021
65368
  if (file === undefined)
@@ -65209,7 +65556,7 @@ import { fork } from "node:child_process";
65209
65556
  import { randomUUID as randomUUID16 } from "node:crypto";
65210
65557
  import { createWriteStream } from "node:fs";
65211
65558
  import { appendFile, mkdir as mkdir6, rm as rm3, rmdir } from "node:fs/promises";
65212
- import { dirname as dirname13, join as join29, resolve as resolve12 } from "node:path";
65559
+ import { dirname as dirname14, join as join30, resolve as resolve13 } from "node:path";
65213
65560
  import { setTimeout as delay2 } from "node:timers/promises";
65214
65561
  function isRootLeaseLost(error) {
65215
65562
  return error instanceof StaleLeaseError || error.message.startsWith("Stale lease for run ");
@@ -65218,7 +65565,7 @@ function unconfirmedCleanup(groups) {
65218
65565
  return new Error(`Local worker process cleanup unconfirmed; ${groups.length > 0 ? `process groups ${groups.join(", ")} still running after SIGKILL; ` : ""}permits quarantined`);
65219
65566
  }
65220
65567
  function workerLogDirectory(journalPath, root) {
65221
- return join29(dirname13(resolve12(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
65568
+ return join30(dirname14(resolve13(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
65222
65569
  }
65223
65570
  function token(work) {
65224
65571
  return {
@@ -65406,6 +65753,7 @@ class PoolCoordinator {
65406
65753
  cleanups = new Set;
65407
65754
  controlAcks = new Map;
65408
65755
  lastHeard = new Map;
65756
+ awaiting = new Map;
65409
65757
  pendingActivity = new Map;
65410
65758
  batches = new Map;
65411
65759
  publicationFailures = new Map;
@@ -66149,7 +66497,7 @@ class PoolCoordinator {
66149
66497
  this.slots.add(slot);
66150
66498
  let ready = false;
66151
66499
  let serial = Promise.resolve();
66152
- const logPath = join29(this.logDirectory, `${worker}.log`);
66500
+ const logPath = join30(this.logDirectory, `${worker}.log`);
66153
66501
  this.logs.set(child, logPath);
66154
66502
  let logFailure;
66155
66503
  const log = createWriteStream(logPath, { flags: "a" });
@@ -66205,6 +66553,7 @@ class PoolCoordinator {
66205
66553
  this.readyWorkers.delete(worker);
66206
66554
  this.controlAcks.delete(worker);
66207
66555
  this.lastHeard.delete(worker);
66556
+ this.awaiting.delete(worker);
66208
66557
  this.slots.delete(slot);
66209
66558
  this.endStageWatches((watch) => watch.slot === slot, "worker_exited");
66210
66559
  for (const settle of slot.stageCommands.values())
@@ -66462,8 +66811,19 @@ class PoolCoordinator {
66462
66811
  await this.sendResult(work.id);
66463
66812
  });
66464
66813
  const response = handled.then((value2) => routeReady ?? value2);
66465
- if (message.kind !== "delivery" && message.kind !== "delivery-ready")
66466
- serial = handled.then(() => {}, () => {});
66814
+ if (message.kind !== "delivery" && message.kind !== "delivery-ready") {
66815
+ this.awaiting.set(worker, (this.awaiting.get(worker) ?? 0) + 1);
66816
+ const answered = () => {
66817
+ const left = (this.awaiting.get(worker) ?? 1) - 1;
66818
+ if (left > 0)
66819
+ this.awaiting.set(worker, left);
66820
+ else
66821
+ this.awaiting.delete(worker);
66822
+ if (this.incarnations.get(worker) === child)
66823
+ this.lastHeard.set(worker, { at: performance.now(), stalled: this.stalledMs });
66824
+ };
66825
+ serial = handled.then(answered, answered);
66826
+ }
66467
66827
  response.then((value2) => child.send({ id: message.id, value: value2 }, replied), (error) => {
66468
66828
  const rootLeaseLost = isRootLeaseLost(error);
66469
66829
  if (rootLeaseLost)
@@ -66533,7 +66893,10 @@ class PoolCoordinator {
66533
66893
  if (work.epoch < lease.epoch)
66534
66894
  await this.releaseRetained(work);
66535
66895
  else
66536
- await queue.expire(lease, work);
66896
+ await queue.expire(lease, work).catch((error) => {
66897
+ if (error.message !== STALE_WORK_LEASE)
66898
+ throw error;
66899
+ });
66537
66900
  }
66538
66901
  })().finally(() => {
66539
66902
  this.recovering = undefined;
@@ -66551,7 +66914,7 @@ class PoolCoordinator {
66551
66914
  isLive(worker, child) {
66552
66915
  this.observeResponsiveness();
66553
66916
  const heard = this.lastHeard.get(worker);
66554
- return child.exitCode === null && child.signalCode === null && child.connected && heard !== undefined && performance.now() - heard.at - (this.stalledMs - heard.stalled) < this.options.leaseMs;
66917
+ 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);
66555
66918
  }
66556
66919
  async stop(child) {
66557
66920
  const pid = child.pid;
@@ -66737,26 +67100,6 @@ function isWorkflowPendingStageDeliveryFailure(error) {
66737
67100
  return true;
66738
67101
  return error?.code === "pending_stage_delivery_failed";
66739
67102
  }
66740
- function untilDrainedOrStalled(drain) {
66741
- let lastProgressAt = Date.now();
66742
- const running = drain(() => {
66743
- lastProgressAt = Date.now();
66744
- });
66745
- return new Promise((resolve, reject) => {
66746
- let timer;
66747
- const check = () => {
66748
- const remaining = lastProgressAt + PENDING_STAGE_READY_STALL_MS - Date.now();
66749
- if (remaining <= 0) {
66750
- resolve();
66751
- return;
66752
- }
66753
- timer = setTimeout(check, remaining);
66754
- timer.unref?.();
66755
- };
66756
- running.then(resolve, reject).finally(() => clearTimeout(timer));
66757
- check();
66758
- });
66759
- }
66760
67103
  function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action(), options = {}) {
66761
67104
  let resolveReady;
66762
67105
  let rejectReady;
@@ -66949,7 +67292,7 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
66949
67292
  };
66950
67293
  }
66951
67294
  async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient) {
66952
- const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient);
67295
+ const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, recipient?.receivedMessageIds);
66953
67296
  const candidateIds = new Set([
66954
67297
  ...activeStore.pendingStageMessagesFor(runId, stageId),
66955
67298
  ...activeStore.pendingStageMessagesFor(runId, stageName),
@@ -67005,7 +67348,7 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
67005
67348
  }
67006
67349
  }
67007
67350
  }
67008
- function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient) {
67351
+ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, receivedByEndedStage = []) {
67009
67352
  const runs = activeStore.runs();
67010
67353
  const rootRunId = durableRootRunIdForRun(runs, runId);
67011
67354
  if (rootRunId === undefined)
@@ -67014,22 +67357,28 @@ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageNam
67014
67357
  if (rootRun === undefined)
67015
67358
  return [];
67016
67359
  const stage = runs.find((run) => run.id === runId)?.stages.find((candidate) => candidate.id === stageId);
67017
- if (stage?.status === "completed" || stage?.status === "skipped")
67360
+ const ended = stage?.status === "completed" || stage?.status === "skipped";
67361
+ if (ended && receivedByEndedStage.length === 0)
67018
67362
  return [];
67019
67363
  const hops = workflowBoundaryHops(runs, runId);
67020
67364
  if (hops === undefined)
67021
67365
  return [];
67022
67366
  return (rootRun.pendingStageMessages ?? []).filter((entry) => {
67023
- if (entry.sticky !== true || entry.status !== "queued")
67024
- return false;
67025
- const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
67026
- if (parsed === undefined || parsed.rootRunId !== rootRunId)
67027
- return false;
67028
67367
  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)))))
67029
67368
  return false;
67030
- return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
67369
+ if (ended && !receivedByEndedStage.includes(entry.message.id))
67370
+ return false;
67371
+ return stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName);
67031
67372
  });
67032
67373
  }
67374
+ function stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName) {
67375
+ if (entry.sticky !== true || entry.status !== "queued")
67376
+ return false;
67377
+ const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
67378
+ if (parsed === undefined || parsed.rootRunId !== rootRunId)
67379
+ return false;
67380
+ return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
67381
+ }
67033
67382
  function claimPendingDelivery(store, runId, stageKey, messageId) {
67034
67383
  let claims = pendingDeliveryClaims.get(store);
67035
67384
  if (claims === undefined) {
@@ -67093,6 +67442,7 @@ class PoolStageHandoff {
67093
67442
  owners = new Map;
67094
67443
  publications = new Map;
67095
67444
  drains = new Map;
67445
+ deliveryIssues = 0;
67096
67446
  constructor(backend, store, queue, lease, claimRun) {
67097
67447
  this.backend = backend;
67098
67448
  this.store = store;
@@ -67173,11 +67523,23 @@ class PoolStageHandoff {
67173
67523
  this.drains.set(stage, drain);
67174
67524
  try {
67175
67525
  await drain;
67526
+ } catch (error) {
67527
+ const current = this.attempts.get(work.id) === attempt && !attempt.fenced;
67528
+ if (current && attempt.sessions.get(stage) === recipient.sessionId && error.message !== STALE)
67529
+ this.recordDeliveryIssue(error);
67530
+ throw error;
67176
67531
  } finally {
67177
67532
  if (this.drains.get(stage) === drain)
67178
67533
  this.drains.delete(stage);
67179
67534
  }
67180
67535
  }
67536
+ recordDeliveryIssue(error) {
67537
+ this.deliveryIssues++;
67538
+ const drains = this.deliveryIssues === 1 ? "1 stage drain" : `${this.deliveryIssues} stage drains`;
67539
+ this.store.recordRunExecutionState(this.lease.runId, {
67540
+ intercomDeliveryIssue: `${drains} on local workers failed; undelivered messages stay queued and arrive live or on the stage's next drain (last: ${error.message})`
67541
+ });
67542
+ }
67181
67543
  async complete(work) {
67182
67544
  const root = this.lease.runId;
67183
67545
  const result = await this.queue.result(root, work.id);
@@ -68533,7 +68895,7 @@ var init_pooled_stage_registry = __esm(() => {
68533
68895
  // dist/builtin/workflows/src/workers/local-pool.ts
68534
68896
  import { fork as fork2 } from "node:child_process";
68535
68897
  import { randomUUID as randomUUID18 } from "node:crypto";
68536
- import { resolve as resolve13 } from "node:path";
68898
+ import { resolve as resolve14 } from "node:path";
68537
68899
  import { setTimeout as delay3 } from "node:timers/promises";
68538
68900
  import { fileURLToPath as fileURLToPath5 } from "node:url";
68539
68901
  import {
@@ -68767,7 +69129,7 @@ class LocalWorkerPool {
68767
69129
  async poolJournal() {
68768
69130
  const journal = this.backend.journal;
68769
69131
  if (this.options.durable === undefined) {
68770
- if (!(journal instanceof SqlRunJournal) || resolve13(this.options.journalPath) !== resolve13(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
69132
+ if (!(journal instanceof SqlRunJournal) || resolve14(this.options.journalPath) !== resolve14(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
68771
69133
  throw new Error("Local workers require the same default-prefix SQLite journal");
68772
69134
  return journal;
68773
69135
  }
@@ -69794,7 +70156,7 @@ var init_local_pool = __esm(() => {
69794
70156
  var DEFAULT_POOLED_STAGE_START_MAX_LOAD_PER_CPU = 3;
69795
70157
 
69796
70158
  // dist/builtin/workflows/src/workers/public-pool.ts
69797
- import { resolve as resolve14 } from "node:path";
70159
+ import { resolve as resolve15 } from "node:path";
69798
70160
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
69799
70161
  async function restoreWorkerOptions(backend, options) {
69800
70162
  const source = options.continuation?.source.id ?? options.runId;
@@ -69844,16 +70206,16 @@ async function activatePublicPool(backend, options) {
69844
70206
  startupTimeoutMs: undefined,
69845
70207
  leaseMs: undefined,
69846
70208
  maxLoadPerCpu: undefined,
69847
- definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve14(cwd, source.path) }))
70209
+ definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve15(cwd, source.path) }))
69848
70210
  };
69849
70211
  const admission = options.admission && {
69850
70212
  ...options.admission,
69851
- ...options.admission.userDatabase ? { userDatabase: resolve14(cwd, options.admission.userDatabase) } : {}
70213
+ ...options.admission.userDatabase ? { userDatabase: resolve15(cwd, options.admission.userDatabase) } : {}
69852
70214
  };
69853
70215
  if (durable !== undefined && admission?.userLimits) {
69854
- if (admission.userDatabase !== undefined && admission.userDatabase !== resolve14(poolPath))
69855
- throw new Error(`admission.userDatabase must be omitted, or ${resolve14(poolPath)}, for a journal that is not a local SQLite file`);
69856
- admission.userDatabase = resolve14(poolPath);
70216
+ if (admission.userDatabase !== undefined && admission.userDatabase !== resolve15(poolPath))
70217
+ throw new Error(`admission.userDatabase must be omitted, or ${resolve15(poolPath)}, for a journal that is not a local SQLite file`);
70218
+ admission.userDatabase = resolve15(poolPath);
69857
70219
  }
69858
70220
  const sources = localWorkers && await Promise.all(localWorkers.definitions.map(async (source) => ({ ...source, digest: await definitionDigest(source.path) })));
69859
70221
  const resources = JSON.parse(JSON.stringify({
@@ -70459,6 +70821,7 @@ function createTaskPrimitive(runtime) {
70459
70821
  }
70460
70822
  })();
70461
70823
  const stageMeta = stage.__modelFallbackMeta();
70824
+ stage.__releaseIfIdle?.();
70462
70825
  return {
70463
70826
  name,
70464
70827
  stageName: name,
@@ -71257,7 +71620,7 @@ function hasUsableContentBlock(block) {
71257
71620
 
71258
71621
  // dist/builtin/workflows/src/shared/stage-session-store.ts
71259
71622
  import { randomUUID as randomUUID20 } from "node:crypto";
71260
- import { dirname as dirname14, resolve as resolve15 } from "node:path";
71623
+ import { dirname as dirname15, resolve as resolve16 } from "node:path";
71261
71624
  import {
71262
71625
  JsonlSessionStore,
71263
71626
  resolveSessionStore,
@@ -71293,11 +71656,11 @@ async function forkStageSession(store, sessionId, cwd, options, destination = st
71293
71656
  async function migrateLegacyStageSession(store, sessionId, sessionFile) {
71294
71657
  if (sessionFile === undefined || await store.readHeader(sessionId) !== undefined)
71295
71658
  return;
71296
- const location = resolve15(sessionFile);
71297
- const legacy = await JsonlSessionStore.open(dirname14(location), { exactDirectory: true, scanExisting: false });
71659
+ const location = resolve16(sessionFile);
71660
+ const legacy = await JsonlSessionStore.open(dirname15(location), { exactDirectory: true, scanExisting: false });
71298
71661
  try {
71299
71662
  for await (const file of legacy.scanFiles()) {
71300
- if (resolve15(file.location) !== location || file.header.id !== sessionId)
71663
+ if (resolve16(file.location) !== location || file.header.id !== sessionId)
71301
71664
  continue;
71302
71665
  const snapshot = await file.read();
71303
71666
  if (await store.readHeader(sessionId) === undefined)
@@ -74123,6 +74486,8 @@ function createTrackedStageCaller(input) {
74123
74486
  await runtime.releaseLiveHandle().catch(() => {});
74124
74487
  }
74125
74488
  runtime.state.sessionCheckpointed = finalizationError === undefined;
74489
+ if (runtime.state.contextUnreachable)
74490
+ runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId);
74126
74491
  input.limiter.release();
74127
74492
  if (finalizationError !== undefined)
74128
74493
  throwFinalizationError(finalizationError.error);
@@ -74286,7 +74651,8 @@ function createStageContext(input) {
74286
74651
  recordStageNotice({ kind: "abort", to: "interrupted" });
74287
74652
  await innerCtx.abort();
74288
74653
  },
74289
- __modelFallbackMeta: () => innerCtx.__modelFallbackMeta()
74654
+ __modelFallbackMeta: () => innerCtx.__modelFallbackMeta(),
74655
+ __releaseIfIdle: () => runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId)
74290
74656
  };
74291
74657
  }
74292
74658
 
@@ -75975,10 +76341,10 @@ function isRetryableSameCandidateFailure(error) {
75975
76341
  return isTransientExtensionStartupFailure(error);
75976
76342
  return isRetryableSameModelFailure(error);
75977
76343
  }
75978
- function mayAdvanceToNextCandidate(error) {
76344
+ function mayAdvanceToNextCandidate(error, options) {
75979
76345
  if (isExtensionStartupFailure(error))
75980
76346
  return isTransientExtensionStartupFailure(error);
75981
- return isRetryableModelFailure(error);
76347
+ return isRetryableModelFailure(error, options);
75982
76348
  }
75983
76349
  function hasMeaningfulUsage(usage) {
75984
76350
  if (usage === undefined)
@@ -76070,6 +76436,7 @@ class StageSessionController {
76070
76436
  structuredOutputExecutionFailureValue;
76071
76437
  structuredOutputCycleAttemptMark;
76072
76438
  unsubscribeTerminateWatcher;
76439
+ unbindAbortSignal;
76073
76440
  sessionInternalRetries = 0;
76074
76441
  unresolvedContextOverflowMessage;
76075
76442
  generationSealed = false;
@@ -76559,6 +76926,8 @@ class StageSessionController {
76559
76926
  this.pendingListeners.clear();
76560
76927
  this.unsubscribeTerminateWatcher?.();
76561
76928
  this.unsubscribeTerminateWatcher = undefined;
76929
+ this.unbindAbortSignal?.();
76930
+ this.unbindAbortSignal = undefined;
76562
76931
  this.terminatingToolCallIds.clear();
76563
76932
  this.messageAdmission.dispose();
76564
76933
  this.deliveryActivity.dispose();
@@ -76653,8 +77022,10 @@ class StageSessionController {
76653
77022
  };
76654
77023
  if (signal.aborted)
76655
77024
  onAbort();
76656
- else
77025
+ else {
76657
77026
  signal.addEventListener("abort", onAbort, { once: true });
77027
+ this.unbindAbortSignal = () => signal.removeEventListener("abort", onAbort);
77028
+ }
76658
77029
  }
76659
77030
  markAbort(reason) {
76660
77031
  this.abortGeneration += 1;
@@ -76681,6 +77052,9 @@ class StageSessionController {
76681
77052
  state.controller.abort(reason);
76682
77053
  this.thrownErrorRetryStates.clear();
76683
77054
  }
77055
+ fallbackFailureOptions() {
77056
+ return { fallbackOnContentFilter: this.retrySettings()?.fallbackOnContentFilter !== false };
77057
+ }
76684
77058
  retrySettings() {
76685
77059
  const managers = [
76686
77060
  this.sessionSettingsManager,
@@ -76955,7 +77329,7 @@ class StageSessionController {
76955
77329
  const errorSettingsManager = retrySettingsManagerFromError(error);
76956
77330
  if (errorSettingsManager !== undefined)
76957
77331
  this.sessionSettingsManager = errorSettingsManager;
76958
- const retryableFailure = isRetryableModelFailure(error);
77332
+ const retryableFailure = isRetryableModelFailure(error, this.fallbackFailureOptions());
76959
77333
  const sameCandidateRetryable = isRetryableSameModelFailure(error) && !isUnresolvedContextOverflowFailure(error);
76960
77334
  recordProviderRateLimit(this.currentProvider(), error, modelIdForModel(this.currentModelValue()));
76961
77335
  if (this.hasExplicitModelFallbackConfig && isProviderRateLimit(error)) {
@@ -77580,7 +77954,7 @@ class StageSessionController {
77580
77954
  }
77581
77955
  throw new WorkflowPromptModelFailure(terminalFailure);
77582
77956
  } catch (err) {
77583
- if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
77957
+ if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
77584
77958
  this.artifactCapture.settleAttempt(true);
77585
77959
  const usage = this.takeAttemptUsage(resumedSession);
77586
77960
  this.modelAttempts.push({
@@ -77602,7 +77976,7 @@ class StageSessionController {
77602
77976
  ...usage === undefined ? {} : { usage },
77603
77977
  error: message
77604
77978
  });
77605
- if (this.opts.signal?.aborted || !isRetryableModelFailure(err)) {
77979
+ if (this.opts.signal?.aborted || !isRetryableModelFailure(err, this.fallbackFailureOptions())) {
77606
77980
  this.modelWarnings.push(...this.pendingFallbackWarnings);
77607
77981
  this.pendingFallbackWarnings.length = 0;
77608
77982
  this.notifyModelFallbackMetaChange();
@@ -77651,7 +78025,7 @@ class StageSessionController {
77651
78025
  throw err;
77652
78026
  const message = errorMessage3(err);
77653
78027
  const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
77654
- if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
78028
+ if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
77655
78029
  this.recordSuccessfulAttempt(candidate);
77656
78030
  return "handled";
77657
78031
  }
@@ -77668,7 +78042,7 @@ class StageSessionController {
77668
78042
  if (walk !== undefined) {
77669
78043
  this.recordCandidateFailure(walk, index, err, candidates);
77670
78044
  nextIndex = undefined;
77671
- if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err)) {
78045
+ if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err, this.fallbackFailureOptions())) {
77672
78046
  try {
77673
78047
  nextIndex = await this.selectReadyCandidate(candidates, walk, index + 1);
77674
78048
  } catch (error) {
@@ -77681,7 +78055,7 @@ class StageSessionController {
77681
78055
  }
77682
78056
  }
77683
78057
  }
77684
- if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err) || nextIndex === undefined) {
78058
+ if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err, this.fallbackFailureOptions()) || nextIndex === undefined) {
77685
78059
  await this.settleFailedCandidate();
77686
78060
  return "throw";
77687
78061
  }
@@ -77776,7 +78150,7 @@ var init_stage_runner_controller = __esm(() => {
77776
78150
  // dist/builtin/workflows/src/runs/foreground/stage-runner-output.ts
77777
78151
  import { createHash as createHash5 } from "node:crypto";
77778
78152
  import { mkdir as mkdir7, writeFile as writeFile10 } from "node:fs/promises";
77779
- import { basename as basename5, dirname as dirname15, isAbsolute as isAbsolute11, join as join30, resolve as resolve16 } from "node:path";
78153
+ import { basename as basename5, dirname as dirname16, isAbsolute as isAbsolute11, join as join31, resolve as resolve17 } from "node:path";
77780
78154
  function normalizeMaxOutput2(maxOutput) {
77781
78155
  return {
77782
78156
  bytes: maxOutput?.bytes ?? DEFAULT_MAX_OUTPUT_BYTES,
@@ -77839,7 +78213,7 @@ function formatByteSize(bytes) {
77839
78213
  }
77840
78214
  function transcriptPath(runId, outputPath) {
77841
78215
  const digest = createHash5("sha256").update(outputPath).digest("hex").slice(0, 16);
77842
- return join30(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename5(outputPath)}.transcript.md`);
78216
+ return join31(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename5(outputPath)}.transcript.md`);
77843
78217
  }
77844
78218
  function appendContent(lines, content) {
77845
78219
  if (typeof content === "string") {
@@ -77884,7 +78258,7 @@ function renderTranscript(messages, fallbackOutput) {
77884
78258
  `);
77885
78259
  }
77886
78260
  function savedOutputReference(outputPath, fullOutput, transcriptPathValue, transcriptText, transcriptAvailable, warning) {
77887
- const absolutePath = resolve16(outputPath);
78261
+ const absolutePath = resolve17(outputPath);
77888
78262
  const bytes = Buffer.byteLength(fullOutput, "utf8");
77889
78263
  const lines = countLines(fullOutput);
77890
78264
  const transcriptBytes = Buffer.byteLength(transcriptText, "utf8");
@@ -77899,8 +78273,8 @@ function resolveOutputPath(output, runtimeCwd, requestedCwd) {
77899
78273
  return;
77900
78274
  if (isAbsolute11(output))
77901
78275
  return output;
77902
- const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve16(runtimeCwd, requestedCwd);
77903
- return resolve16(baseCwd, output);
78276
+ const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve17(runtimeCwd, requestedCwd);
78277
+ return resolve17(baseCwd, output);
77904
78278
  }
77905
78279
  function degenerateWarning(fullOutput) {
77906
78280
  return fullOutput.trim().length === 0 ? "WARNING: the stage artifact is empty; search the companion transcript for this stage's work." : undefined;
@@ -77959,7 +78333,7 @@ async function finalizePromptOutput(fullOutput, outputOptions, runtimeCwd, runId
77959
78333
  const transcriptFile = transcriptPath(runId, outputPath);
77960
78334
  const transcript = renderTranscript(messages, fullOutput);
77961
78335
  try {
77962
- await mkdir7(dirname15(outputPath), { recursive: true });
78336
+ await mkdir7(dirname16(outputPath), { recursive: true });
77963
78337
  await writeFile10(outputPath, fullOutput, "utf8");
77964
78338
  } catch (err) {
77965
78339
  return `${displayOutput}
@@ -77971,7 +78345,7 @@ ${err instanceof Error ? err.message : String(err)}`;
77971
78345
  let transcriptError;
77972
78346
  try {
77973
78347
  await ensureWorkflowArtifactRunDirectory(runId);
77974
- await mkdir7(dirname15(transcriptFile), { recursive: true });
78348
+ await mkdir7(dirname16(transcriptFile), { recursive: true });
77975
78349
  await writeFile10(transcriptFile, transcript, "utf8");
77976
78350
  transcriptAvailable = true;
77977
78351
  } catch (err) {
@@ -78482,7 +78856,8 @@ function createWorkflowStageFactory(input) {
78482
78856
  stageFinalized: false,
78483
78857
  sessionCheckpointed: false,
78484
78858
  skippedForParallelFailFast: false,
78485
- stageControlDropped: false
78859
+ stageControlDropped: false,
78860
+ contextUnreachable: false
78486
78861
  };
78487
78862
  const activeAskUserQuestionCalls = new Set;
78488
78863
  const hasActiveAskUserQuestion = () => activeAskUserQuestionCalls.size > 0 || state.activeAskUserQuestionAnonymousCalls > 0;
@@ -78728,9 +79103,18 @@ function createWorkflowStageFactory(input) {
78728
79103
  hasContinuation: input.opts.continuation !== undefined,
78729
79104
  hasScopedParents: stageFailFastScope?.parentIds !== undefined
78730
79105
  });
78731
- return createStageContext({ runtime, runTrackedStageCall });
79106
+ const context = createStageContext({ runtime, runTrackedStageCall });
79107
+ unreachableStageContexts.register(context, releaseWhenUnreachable(state, input.stageRegistry, input.runId, stageId));
79108
+ return context;
79109
+ };
79110
+ }
79111
+ function releaseWhenUnreachable(state, registry, runId, stageId) {
79112
+ return () => {
79113
+ state.contextUnreachable = true;
79114
+ registry.releaseIdle(runId, stageId);
78732
79115
  };
78733
79116
  }
79117
+ var unreachableStageContexts;
78734
79118
  var init_executor_stage_factory = __esm(() => {
78735
79119
  init_intercom_group();
78736
79120
  init_pending_stage_route_readiness();
@@ -78745,6 +79129,7 @@ var init_executor_stage_factory = __esm(() => {
78745
79129
  init_pending_stage_delivery2();
78746
79130
  init_stage_runner();
78747
79131
  init_stage_runner_session();
79132
+ unreachableStageContexts = new FinalizationRegistry((release) => release());
78748
79133
  });
78749
79134
 
78750
79135
  // dist/builtin/workflows/src/engine/runtime.ts
@@ -79086,7 +79471,7 @@ async function executeRun(def, resolvedInputs, opts) {
79086
79471
  const ownsCancellationRegistration = opts.signal === undefined && opts.cancellation !== undefined;
79087
79472
  const tracker = new GraphFrontierTracker;
79088
79473
  const inputConcurrency = resolveInputConcurrency(def.inputs, resolvedInputs);
79089
- const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache);
79474
+ const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache, runId);
79090
79475
  const gitWorktreeSetupCache = gitWorktreeSetupCacheOwner.cache;
79091
79476
  const workflowInvocationCwd = opts.cwd ?? process.cwd();
79092
79477
  let workflowCwd;
@@ -80185,8 +80570,8 @@ var init_workflows_host_module = __esm(() => {
80185
80570
 
80186
80571
  // dist/builtin/workflows/src/workers/pool-journal.ts
80187
80572
  import { createHash as createHash6, randomUUID as randomUUID22 } from "node:crypto";
80188
- import { existsSync as existsSync7, mkdirSync as mkdirSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
80189
- import { basename as basename6, dirname as dirname16, join as join31, resolve as resolve17 } from "node:path";
80573
+ import { existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "node:fs";
80574
+ import { basename as basename6, dirname as dirname17, join as join32, resolve as resolve18 } from "node:path";
80190
80575
  import { storageSelectionKey as storageSelectionKey2 } from "@bastani/atomic/storage";
80191
80576
  function encodeOption(value2) {
80192
80577
  if (typeof value2 === "bigint")
@@ -80208,7 +80593,7 @@ function isReopenableSelection(selection) {
80208
80593
  }
80209
80594
  function encodeSelection(selection) {
80210
80595
  if (selection.kind === "sqlite")
80211
- return JSON.stringify({ ...selection, path: resolve17(selection.path) });
80596
+ return JSON.stringify({ ...selection, path: resolve18(selection.path) });
80212
80597
  return JSON.stringify({
80213
80598
  ...selection,
80214
80599
  ...selection.options === undefined ? {} : {
@@ -80240,7 +80625,7 @@ function openDurableJournal(durable) {
80240
80625
  return openSelectedRunJournal(decodeSelection(durable.selection), durable.agentDir);
80241
80626
  }
80242
80627
  function poolStateDirectory(agentDir) {
80243
- return join31(dirname16(agentDir), "workflows", "pool");
80628
+ return join32(dirname17(agentDir), "workflows", "pool");
80244
80629
  }
80245
80630
  function databaseIdentity(selection, agentDir) {
80246
80631
  return storageSelectionKey2(selection.kind === "adapter" ? { ...selection, secrets: undefined } : selection, agentDir);
@@ -80248,16 +80633,16 @@ function databaseIdentity(selection, agentDir) {
80248
80633
  function coordinationPath(durable) {
80249
80634
  const selection = decodeSelection(durable.selection);
80250
80635
  const identity = createHash6("sha256").update(databaseIdentity(selection, durable.agentDir)).digest("hex");
80251
- return join31(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
80636
+ return join32(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
80252
80637
  }
80253
80638
  function coordinationDatabase(durable) {
80254
80639
  return basename6(coordinationPath(durable), ".sqlite");
80255
80640
  }
80256
80641
  function openCoordinationJournal(path) {
80257
- const file = resolve17(path);
80642
+ const file = resolve18(path);
80258
80643
  let opened = coordinationJournals.get(file);
80259
80644
  if (opened === undefined) {
80260
- mkdirSync8(dirname16(file), { recursive: true });
80645
+ mkdirSync9(dirname17(file), { recursive: true });
80261
80646
  opened = resolveRunJournal({ journal: { path: file } });
80262
80647
  coordinationJournals.set(file, opened);
80263
80648
  opened.catch(() => {
@@ -80274,20 +80659,20 @@ function poolJournalFor(journal) {
80274
80659
  return coordinations.get(journal) ?? journal;
80275
80660
  }
80276
80661
  function poolHostId(agentDir) {
80277
- const file = join31(poolStateDirectory(agentDir), "host-id");
80662
+ const file = join32(poolStateDirectory(agentDir), "host-id");
80278
80663
  try {
80279
- const existing = readFileSync6(file, "utf8").trim();
80664
+ const existing = readFileSync8(file, "utf8").trim();
80280
80665
  if (existing !== "")
80281
80666
  return existing;
80282
80667
  } catch {}
80283
- mkdirSync8(dirname16(file), { recursive: true });
80668
+ mkdirSync9(dirname17(file), { recursive: true });
80284
80669
  const id = randomUUID22();
80285
80670
  try {
80286
- writeFileSync6(file, `${id}
80671
+ writeFileSync7(file, `${id}
80287
80672
  `, { flag: "wx" });
80288
80673
  return id;
80289
80674
  } catch {
80290
- return readFileSync6(file, "utf8").trim();
80675
+ return readFileSync8(file, "utf8").trim();
80291
80676
  }
80292
80677
  }
80293
80678
  var POOL_DURABLE_JOURNAL_ENV = "ATOMIC_POOL_DURABLE_JOURNAL", coordinationJournals, coordinations;
@@ -80310,7 +80695,6 @@ init_run();
80310
80695
  init_run_tool_control_registry();
80311
80696
  init_workflow_tool_abort();
80312
80697
  init_wiring();
80313
- init_pending_stage_delivery2();
80314
80698
  init_stage_control_registry();
80315
80699
  init_stage_queued_user_messages();
80316
80700
  init_stage_ui_broker();
@@ -80336,6 +80720,94 @@ function poolWorkerCommit(input) {
80336
80720
  return receipt;
80337
80721
  };
80338
80722
  }
80723
+ // dist/builtin/workflows/src/workers/pooled-stage-delivery.ts
80724
+ init_pending_stage_delivery2();
80725
+ init_pending_stage_delivery();
80726
+ init_store_pending_stage_delivery_methods();
80727
+ function pooledStageQueuedEntries(journal, store, root, stage) {
80728
+ const messages = journal.getWorkflow(root)?.pendingStageMessages ?? [];
80729
+ const runs = store.runs();
80730
+ const run = runs.find((candidate) => candidate.id === stage.runId);
80731
+ if (run === undefined)
80732
+ return [];
80733
+ const exact = new Set;
80734
+ for (const key of new Set([stage.stageId, stage.stageName]))
80735
+ for (const entry of pendingStageMessagesFor(messages, stage.runId, key, resolvePendingStageIdentity(run, key)))
80736
+ exact.add(entry);
80737
+ const hops = pooledStageHops(journal, runs, root, stage.runId);
80738
+ const sticky = hops === undefined ? [] : messages.filter((entry) => entry.runId === root && stickyEntryTargetsStage(entry, root, hops, stage.stageId, stage.stageName));
80739
+ return [
80740
+ ...[...exact].map((entry) => ({ entry, index: messages.indexOf(entry) })),
80741
+ ...sticky.map((entry) => ({ entry, index: Number.MAX_SAFE_INTEGER }))
80742
+ ].map(({ entry, index }) => ({ entry, index, order: pendingStageMessageAdmissionOrder(entry) })).sort((left, right) => left.order - right.order || left.index - right.index).map(({ entry }) => entry);
80743
+ }
80744
+ function pooledStageHops(journal, runs, root, runId) {
80745
+ const byId = new Map(runs.map((run) => [run.id, run]));
80746
+ const hops = [];
80747
+ let current = byId.get(runId);
80748
+ while (current !== undefined && current.parentRunId !== root) {
80749
+ const child = current;
80750
+ const parent = child.parentRunId === undefined ? undefined : byId.get(child.parentRunId);
80751
+ const boundary = parent?.stages.find((stage) => stage.id === child.parentStageId);
80752
+ if (parent === undefined || boundary === undefined)
80753
+ return;
80754
+ hops.unshift({ name: boundary.name, runId: child.id });
80755
+ current = parent;
80756
+ }
80757
+ if (current === undefined)
80758
+ return;
80759
+ const childRunId = current.id;
80760
+ const boundary = journal.listCheckpoints(root).find((checkpoint) => checkpoint.kind === "stage" && checkpoint.topology?.boundary?.child.runId === childRunId);
80761
+ if (boundary === undefined)
80762
+ return;
80763
+ hops.unshift({ name: boundary.name, runId: childRunId });
80764
+ return hops;
80765
+ }
80766
+ function createPooledStageDelivery(options) {
80767
+ const admissions = new Map;
80768
+ const sinks = new Map;
80769
+ return {
80770
+ routeCapability: options.routeCapability,
80771
+ async deliverPending(deliver, recipient) {
80772
+ const sessionId = recipient?.sessionId ?? "";
80773
+ sinks.set(sessionId, deliver);
80774
+ let admitted = admissions.get(sessionId);
80775
+ if (admitted === undefined) {
80776
+ admitted = new Map;
80777
+ admissions.set(sessionId, admitted);
80778
+ }
80779
+ const held = admitted;
80780
+ for (const id of recipient?.receivedMessageIds ?? [])
80781
+ if (!held.has(id))
80782
+ held.set(id, Promise.resolve());
80783
+ const admit = (from, message) => {
80784
+ const existing = held.get(message.id);
80785
+ if (existing !== undefined)
80786
+ return existing;
80787
+ const sink = sinks.get(sessionId) ?? deliver;
80788
+ const delivery = Promise.resolve().then(() => sink(from, message));
80789
+ held.set(message.id, delivery);
80790
+ delivery.catch(() => {
80791
+ if (held.get(message.id) === delivery)
80792
+ held.delete(message.id);
80793
+ });
80794
+ return delivery;
80795
+ };
80796
+ try {
80797
+ for (const entry of await options.queued())
80798
+ await admit(toPendingStageSender(entry), entry.message);
80799
+ } catch {}
80800
+ const deliveries = [...held];
80801
+ const settled = await Promise.allSettled(deliveries.map(([, delivery]) => delivery));
80802
+ const receivedMessageIds = deliveries.flatMap(([id], index) => settled[index]?.status === "fulfilled" ? [id] : []);
80803
+ options.forward({ sessionId, receivedMessageIds }, admit).catch(() => {});
80804
+ },
80805
+ ready() {
80806
+ return;
80807
+ },
80808
+ fail: options.fail
80809
+ };
80810
+ }
80339
80811
 
80340
80812
  // dist/builtin/workflows/src/workers/local-worker.ts
80341
80813
  init_pooled_watch_trace();
@@ -81470,25 +81942,18 @@ async function runWorker(start) {
81470
81942
  const capability = await request({ kind: "route", runId: meta.runId });
81471
81943
  if (typeof capability !== "string")
81472
81944
  throw new Error("Worker root route is unavailable");
81473
- const pendingStageDelivery = {
81945
+ const pendingStageDelivery = createPooledStageDelivery({
81474
81946
  routeCapability: capability,
81475
- async deliverPending(deliver, recipient) {
81476
- await publication;
81477
- await untilDrainedOrStalled((progress) => request({ kind: "delivery", ...identity, recipient }, async (from, message) => {
81478
- progress();
81479
- try {
81480
- await deliver(from, message);
81481
- } finally {
81482
- progress();
81483
- }
81484
- }).then(() => {}));
81947
+ queued: async () => {
81948
+ await reader.catchUpWorkflow(start.root);
81949
+ return pooledStageQueuedEntries(reader, store, start.root, identity);
81485
81950
  },
81486
- async ready(sessionId) {
81951
+ forward: async (recipient, deliver) => {
81487
81952
  await publication;
81488
- await request({ kind: "delivery-ready", ...identity, sessionId });
81953
+ await request({ kind: "delivery", ...identity, recipient }, deliver);
81489
81954
  },
81490
81955
  fail: options.orchestrationContext.pendingStageDelivery.fail
81491
- };
81956
+ });
81492
81957
  return baseAdapter.create({ ...options, orchestrationContext: { ...options.orchestrationContext, pendingStageDelivery } }, meta);
81493
81958
  }
81494
81959
  };
@@ -81504,7 +81969,18 @@ async function runWorker(start) {
81504
81969
  const resourceAdmission = {
81505
81970
  async acquire(kind, signal, requestOptions) {
81506
81971
  await awaitAdmission(signal);
81507
- return admission ? admission.acquire(kind, signal, requestOptions) : async () => {};
81972
+ if (!admission)
81973
+ return async () => {};
81974
+ try {
81975
+ return await admission.acquire(kind, signal, requestOptions);
81976
+ } catch (error) {
81977
+ if (error instanceof QuarantinedCapacityError && !attemptFenced) {
81978
+ poolFault = error.message;
81979
+ attemptFenced = true;
81980
+ controller.abort(new WorkAttemptFencedError(error.message));
81981
+ }
81982
+ throw error;
81983
+ }
81508
81984
  }
81509
81985
  };
81510
81986
  const admitted = admittedSessionAdapter(adapter, resourceAdmission, async (signal) => {