@bastani/atomic 0.9.60 → 0.9.61-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -0
- package/dist/builtin/intercom/index.bundle.mjs +3 -3
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +12 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +14 -0
- package/dist/builtin/workflows/README.md +9 -7
- package/dist/builtin/workflows/builtin/{chunk-h6bt0r0g.js → chunk-a2j0x1a6.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-g3b2zf8r.js → chunk-vzbec50q.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +1 -1
- package/dist/builtin/workflows/builtin/index.js +2 -2
- package/dist/builtin/workflows/builtin/ralph.js +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +922 -473
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +1006 -484
- package/dist/builtin/workflows/src/index.js +892 -448
- package/dist/builtin/workflows/src/local-worker-entry.mjs +1006 -484
- package/dist/builtin/workflows/src/shared/workflow-infrastructure-error.d.ts +6 -0
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +12 -3
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/model-fallback-failures.d.ts +14 -4
- package/dist/core/model-fallback-failures.d.ts.map +1 -1
- package/dist/core/model-fallback-failures.js +43 -15
- package/dist/core/model-fallback-failures.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -0
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -0
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +2 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-schema.d.ts +2 -0
- package/dist/core/settings-schema.d.ts.map +1 -1
- package/dist/core/settings-schema.js +4 -0
- package/dist/core/settings-schema.js.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-startup-chat-container.d.ts +2 -0
- package/dist/modes/interactive/interactive-startup-chat-container.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup-chat-container.js +6 -0
- package/dist/modes/interactive/interactive-startup-chat-container.js.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.d.ts +27 -5
- package/dist/modes/interactive-engine/remote-renderer.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.js +76 -16
- package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
- package/docs/intercom/reference.md +1 -1
- package/docs/models/evals.md +30 -2
- package/docs/settings.md +3 -0
- package/docs/subagents/reference.md +3 -1
- package/docs/workflows/api-reference.md +9 -6
- package/docs/workflows/builtins.md +1 -1
- package/docs/workflows/operations.md +6 -4
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- package/schemas/settings.schema.json +5 -0
|
@@ -13456,9 +13456,104 @@ var init_workflow_artifacts = __esm(() => {
|
|
|
13456
13456
|
pendingArtifactPrunes = new Map;
|
|
13457
13457
|
});
|
|
13458
13458
|
|
|
13459
|
-
// dist/builtin/workflows/src/runs/shared/worktree-
|
|
13459
|
+
// dist/builtin/workflows/src/runs/shared/worktree-allocation.ts
|
|
13460
|
+
import { randomBytes } from "node:crypto";
|
|
13460
13461
|
import * as fs from "node:fs";
|
|
13461
13462
|
import * as path from "node:path";
|
|
13463
|
+
function nextBucketId() {
|
|
13464
|
+
return nextBucketIdOverride?.() ?? randomBytes(2).toString("hex");
|
|
13465
|
+
}
|
|
13466
|
+
function errorCode(error) {
|
|
13467
|
+
return error && typeof error === "object" && "code" in error ? String(error.code) : undefined;
|
|
13468
|
+
}
|
|
13469
|
+
function allocateWorktreeCheckoutPath(root, repositoryName) {
|
|
13470
|
+
for (let attempt = 0;attempt < MAX_BUCKET_ATTEMPTS; attempt++) {
|
|
13471
|
+
const bucket = path.join(root, nextBucketId());
|
|
13472
|
+
try {
|
|
13473
|
+
fs.mkdirSync(bucket);
|
|
13474
|
+
return path.join(bucket, repositoryName);
|
|
13475
|
+
} catch (error) {
|
|
13476
|
+
if (errorCode(error) === "EEXIST")
|
|
13477
|
+
continue;
|
|
13478
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13479
|
+
throw new Error(`Failed to create worktree bucket ${bucket} under gitWorktreeDir ${root}: ${message}`);
|
|
13480
|
+
}
|
|
13481
|
+
}
|
|
13482
|
+
throw new Error(`Every worktree bucket identifier under gitWorktreeDir ${root} is already in use.`);
|
|
13483
|
+
}
|
|
13484
|
+
function removeEmptyWorktreeBucket(checkout) {
|
|
13485
|
+
try {
|
|
13486
|
+
fs.rmdirSync(path.dirname(checkout));
|
|
13487
|
+
} catch {}
|
|
13488
|
+
}
|
|
13489
|
+
function linkedGitDirectory(checkout) {
|
|
13490
|
+
let pointer;
|
|
13491
|
+
try {
|
|
13492
|
+
if (!fs.lstatSync(path.join(checkout, ".git")).isFile())
|
|
13493
|
+
return;
|
|
13494
|
+
pointer = fs.readFileSync(path.join(checkout, ".git"), "utf8");
|
|
13495
|
+
} catch {
|
|
13496
|
+
return;
|
|
13497
|
+
}
|
|
13498
|
+
if (!pointer.startsWith("gitdir:"))
|
|
13499
|
+
return;
|
|
13500
|
+
const gitDir = pointer.slice("gitdir:".length).trim();
|
|
13501
|
+
return gitDir ? path.resolve(checkout, gitDir) : undefined;
|
|
13502
|
+
}
|
|
13503
|
+
function readWorktreeOwner(gitDir) {
|
|
13504
|
+
let contents;
|
|
13505
|
+
try {
|
|
13506
|
+
contents = fs.readFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), "utf8");
|
|
13507
|
+
} catch {
|
|
13508
|
+
return;
|
|
13509
|
+
}
|
|
13510
|
+
try {
|
|
13511
|
+
const record = JSON.parse(contents);
|
|
13512
|
+
return record.version === WORKTREE_OWNER_VERSION && typeof record.ownerRunId === "string" && record.ownerRunId ? record.ownerRunId : undefined;
|
|
13513
|
+
} catch {
|
|
13514
|
+
return;
|
|
13515
|
+
}
|
|
13516
|
+
}
|
|
13517
|
+
function findOwnedWorktreeCheckouts(root, repositoryName, ownerRunId) {
|
|
13518
|
+
let entries;
|
|
13519
|
+
try {
|
|
13520
|
+
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
13521
|
+
} catch {
|
|
13522
|
+
return [];
|
|
13523
|
+
}
|
|
13524
|
+
const owned = [];
|
|
13525
|
+
for (const entry of entries) {
|
|
13526
|
+
if (!entry.isDirectory() || !BUCKET_PATTERN.test(entry.name))
|
|
13527
|
+
continue;
|
|
13528
|
+
const checkout = path.join(root, entry.name, repositoryName);
|
|
13529
|
+
try {
|
|
13530
|
+
if (!fs.lstatSync(checkout).isDirectory())
|
|
13531
|
+
continue;
|
|
13532
|
+
} catch {
|
|
13533
|
+
continue;
|
|
13534
|
+
}
|
|
13535
|
+
const gitDir = linkedGitDirectory(checkout);
|
|
13536
|
+
if (gitDir !== undefined && readWorktreeOwner(gitDir) === ownerRunId)
|
|
13537
|
+
owned.push(checkout);
|
|
13538
|
+
}
|
|
13539
|
+
return owned.sort();
|
|
13540
|
+
}
|
|
13541
|
+
function bindWorktreeOwner(gitDir, ownerRunId) {
|
|
13542
|
+
const record = { version: WORKTREE_OWNER_VERSION, ownerRunId };
|
|
13543
|
+
fs.writeFileSync(path.join(gitDir, WORKTREE_OWNER_FILENAME), `${JSON.stringify(record)}
|
|
13544
|
+
`, {
|
|
13545
|
+
encoding: "utf8",
|
|
13546
|
+
flag: "wx"
|
|
13547
|
+
});
|
|
13548
|
+
}
|
|
13549
|
+
var WORKTREE_OWNER_FILENAME = "atomic-workflow-run.json", WORKTREE_OWNER_VERSION = 1, BUCKET_PATTERN, MAX_BUCKET_ATTEMPTS = 65536, nextBucketIdOverride;
|
|
13550
|
+
var init_worktree_allocation = __esm(() => {
|
|
13551
|
+
BUCKET_PATTERN = /^[0-9a-f]{4}$/;
|
|
13552
|
+
});
|
|
13553
|
+
|
|
13554
|
+
// dist/builtin/workflows/src/runs/shared/worktree-generation.ts
|
|
13555
|
+
import * as fs2 from "node:fs";
|
|
13556
|
+
import * as path2 from "node:path";
|
|
13462
13557
|
function sameFileIdentity(left, right) {
|
|
13463
13558
|
return left.dev === right.dev && left.ino === right.ino;
|
|
13464
13559
|
}
|
|
@@ -13468,7 +13563,7 @@ function openMainCheckoutAnchor(gitDir) {
|
|
|
13468
13563
|
assertCurrent() {
|
|
13469
13564
|
if (disposed)
|
|
13470
13565
|
throw new Error(`cached .git identity anchor is already disposed: ${gitDir}`);
|
|
13471
|
-
if (!
|
|
13566
|
+
if (!fs2.lstatSync(gitDir).isDirectory()) {
|
|
13472
13567
|
throw new Error(`cached main-checkout .git directory is no longer current: ${gitDir}`);
|
|
13473
13568
|
}
|
|
13474
13569
|
},
|
|
@@ -13478,17 +13573,17 @@ function openMainCheckoutAnchor(gitDir) {
|
|
|
13478
13573
|
};
|
|
13479
13574
|
}
|
|
13480
13575
|
function openGitWorktreeGenerationAnchor(worktreeRoot) {
|
|
13481
|
-
const gitFile =
|
|
13482
|
-
if (
|
|
13576
|
+
const gitFile = path2.join(worktreeRoot, ".git");
|
|
13577
|
+
if (fs2.lstatSync(gitFile).isDirectory())
|
|
13483
13578
|
return openMainCheckoutAnchor(gitFile);
|
|
13484
|
-
const descriptor =
|
|
13579
|
+
const descriptor = fs2.openSync(gitFile, "r");
|
|
13485
13580
|
let disposed = false;
|
|
13486
13581
|
const anchor = {
|
|
13487
13582
|
assertCurrent() {
|
|
13488
13583
|
if (disposed)
|
|
13489
13584
|
throw new Error(`cached .git identity anchor is already disposed: ${gitFile}`);
|
|
13490
|
-
const held =
|
|
13491
|
-
const current =
|
|
13585
|
+
const held = fs2.fstatSync(descriptor, { bigint: true });
|
|
13586
|
+
const current = fs2.lstatSync(gitFile, { bigint: true });
|
|
13492
13587
|
if (!current.isFile() || !sameFileIdentity(held, current)) {
|
|
13493
13588
|
throw new Error(`cached .git identity anchor no longer matches the selected checkout: ${gitFile}`);
|
|
13494
13589
|
}
|
|
@@ -13497,7 +13592,7 @@ function openGitWorktreeGenerationAnchor(worktreeRoot) {
|
|
|
13497
13592
|
if (disposed)
|
|
13498
13593
|
return;
|
|
13499
13594
|
disposed = true;
|
|
13500
|
-
|
|
13595
|
+
fs2.closeSync(descriptor);
|
|
13501
13596
|
}
|
|
13502
13597
|
};
|
|
13503
13598
|
try {
|
|
@@ -13611,84 +13706,84 @@ var init_worktree_git_runner = __esm(() => {
|
|
|
13611
13706
|
});
|
|
13612
13707
|
|
|
13613
13708
|
// dist/builtin/workflows/src/runs/shared/worktree-root.ts
|
|
13614
|
-
import * as
|
|
13615
|
-
import * as
|
|
13709
|
+
import * as fs3 from "node:fs";
|
|
13710
|
+
import * as path3 from "node:path";
|
|
13616
13711
|
function pathFromPointer(contents, prefix, base) {
|
|
13617
13712
|
if (!contents.startsWith(prefix))
|
|
13618
13713
|
return;
|
|
13619
13714
|
const value2 = contents.slice(prefix.length).trim();
|
|
13620
13715
|
if (!value2)
|
|
13621
13716
|
return;
|
|
13622
|
-
return
|
|
13717
|
+
return path3.resolve(base, value2);
|
|
13623
13718
|
}
|
|
13624
13719
|
function readText(file) {
|
|
13625
13720
|
try {
|
|
13626
|
-
return
|
|
13721
|
+
return fs3.readFileSync(file, "utf8");
|
|
13627
13722
|
} catch {
|
|
13628
13723
|
return;
|
|
13629
13724
|
}
|
|
13630
13725
|
}
|
|
13631
13726
|
function samePath(left, right) {
|
|
13632
13727
|
try {
|
|
13633
|
-
const a =
|
|
13634
|
-
const b =
|
|
13728
|
+
const a = fs3.realpathSync.native(left);
|
|
13729
|
+
const b = fs3.realpathSync.native(right);
|
|
13635
13730
|
return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
13636
13731
|
} catch {
|
|
13637
13732
|
return false;
|
|
13638
13733
|
}
|
|
13639
13734
|
}
|
|
13640
13735
|
function findGitRoot(cwd) {
|
|
13641
|
-
let current =
|
|
13736
|
+
let current = path3.resolve(cwd);
|
|
13642
13737
|
try {
|
|
13643
|
-
if (!
|
|
13644
|
-
current =
|
|
13738
|
+
if (!fs3.statSync(current).isDirectory())
|
|
13739
|
+
current = path3.dirname(current);
|
|
13645
13740
|
} catch {
|
|
13646
13741
|
return;
|
|
13647
13742
|
}
|
|
13648
13743
|
while (true) {
|
|
13649
13744
|
try {
|
|
13650
|
-
const entry =
|
|
13745
|
+
const entry = fs3.statSync(path3.join(current, ".git"));
|
|
13651
13746
|
if (entry.isDirectory() || entry.isFile())
|
|
13652
13747
|
return current;
|
|
13653
13748
|
} catch {}
|
|
13654
|
-
const parent =
|
|
13749
|
+
const parent = path3.dirname(current);
|
|
13655
13750
|
if (parent === current)
|
|
13656
13751
|
return;
|
|
13657
13752
|
current = parent;
|
|
13658
13753
|
}
|
|
13659
13754
|
}
|
|
13660
13755
|
function resolveMainRepoRoot(repoRoot) {
|
|
13661
|
-
const gitEntry =
|
|
13756
|
+
const gitEntry = path3.join(repoRoot, ".git");
|
|
13662
13757
|
let stats;
|
|
13663
13758
|
try {
|
|
13664
|
-
stats =
|
|
13759
|
+
stats = fs3.statSync(gitEntry);
|
|
13665
13760
|
} catch {
|
|
13666
13761
|
return;
|
|
13667
13762
|
}
|
|
13668
13763
|
if (stats.isDirectory())
|
|
13669
|
-
return
|
|
13764
|
+
return path3.resolve(repoRoot);
|
|
13670
13765
|
if (!stats.isFile())
|
|
13671
13766
|
return;
|
|
13672
13767
|
const pointer = readText(gitEntry);
|
|
13673
13768
|
if (pointer === undefined)
|
|
13674
13769
|
return;
|
|
13675
13770
|
const gitDir = pathFromPointer(pointer, "gitdir:", repoRoot);
|
|
13676
|
-
if (gitDir === undefined ||
|
|
13771
|
+
if (gitDir === undefined || path3.basename(path3.dirname(gitDir)) !== "worktrees")
|
|
13677
13772
|
return;
|
|
13678
|
-
const commonGitDir =
|
|
13679
|
-
if (
|
|
13773
|
+
const commonGitDir = path3.dirname(path3.dirname(gitDir));
|
|
13774
|
+
if (path3.basename(commonGitDir) !== ".git")
|
|
13680
13775
|
return;
|
|
13681
|
-
const backPointer = readText(
|
|
13682
|
-
const commonPointer = readText(
|
|
13776
|
+
const backPointer = readText(path3.join(gitDir, "gitdir"));
|
|
13777
|
+
const commonPointer = readText(path3.join(gitDir, "commondir"));
|
|
13683
13778
|
if (backPointer === undefined || commonPointer === undefined)
|
|
13684
13779
|
return;
|
|
13685
|
-
const linkedGitEntry =
|
|
13686
|
-
const declaredCommonDir =
|
|
13780
|
+
const linkedGitEntry = path3.resolve(gitDir, backPointer.trim());
|
|
13781
|
+
const declaredCommonDir = path3.resolve(gitDir, commonPointer.trim());
|
|
13687
13782
|
if (!backPointer.trim() || !commonPointer.trim())
|
|
13688
13783
|
return;
|
|
13689
13784
|
if (!samePath(linkedGitEntry, gitEntry) || !samePath(declaredCommonDir, commonGitDir))
|
|
13690
13785
|
return;
|
|
13691
|
-
return
|
|
13786
|
+
return path3.dirname(commonGitDir);
|
|
13692
13787
|
}
|
|
13693
13788
|
function findCanonicalGitRoot(cwd) {
|
|
13694
13789
|
const repoRoot = findGitRoot(cwd);
|
|
@@ -13697,33 +13792,31 @@ function findCanonicalGitRoot(cwd) {
|
|
|
13697
13792
|
var init_worktree_root = () => {};
|
|
13698
13793
|
|
|
13699
13794
|
// dist/builtin/workflows/src/runs/shared/worktree-git.ts
|
|
13700
|
-
import * as
|
|
13701
|
-
import * as
|
|
13702
|
-
function gitWorktreeSetupCacheKey(
|
|
13703
|
-
const repoRoot = repositoryRootForGitWorktree(options.cwd);
|
|
13704
|
-
const { logicalRepoRoot } = cwdWithinGitRepository(options.cwd, repoRoot);
|
|
13705
|
-
const worktreeRoot = resolveGitWorktreePath(options.gitWorktreeDir, logicalRepoRoot);
|
|
13795
|
+
import * as fs4 from "node:fs";
|
|
13796
|
+
import * as path4 from "node:path";
|
|
13797
|
+
function gitWorktreeSetupCacheKey(request) {
|
|
13706
13798
|
return JSON.stringify([
|
|
13707
|
-
|
|
13708
|
-
comparablePathThroughExistingAncestor(
|
|
13799
|
+
comparablePathThroughExistingAncestor(request.options.cwd),
|
|
13800
|
+
comparablePathThroughExistingAncestor(request.target)
|
|
13709
13801
|
]);
|
|
13710
13802
|
}
|
|
13711
|
-
function createGitWorktreeSetupCache() {
|
|
13803
|
+
function createGitWorktreeSetupCache(ownerRunId) {
|
|
13712
13804
|
const results = new Map;
|
|
13713
13805
|
let disposed = false;
|
|
13714
13806
|
return {
|
|
13715
13807
|
get(options) {
|
|
13716
13808
|
if (disposed)
|
|
13717
13809
|
throw new Error("Git worktree setup cache is already disposed");
|
|
13718
|
-
const
|
|
13810
|
+
const request = resolveGitWorktreeSetupRequest(options);
|
|
13811
|
+
const key = gitWorktreeSetupCacheKey(request);
|
|
13719
13812
|
const cached = results.get(key);
|
|
13720
13813
|
if (cached !== undefined) {
|
|
13721
13814
|
assertCachedGitWorktreeIdentity(cached, options);
|
|
13722
13815
|
return cached.result;
|
|
13723
13816
|
}
|
|
13724
|
-
const
|
|
13725
|
-
results.set(key, {
|
|
13726
|
-
return result;
|
|
13817
|
+
const setup = setupGitWorktreeFromRequest(request, ownerRunId);
|
|
13818
|
+
results.set(key, { ...setup, identity: captureGitWorktreeIdentity(setup) });
|
|
13819
|
+
return setup.result;
|
|
13727
13820
|
},
|
|
13728
13821
|
dispose() {
|
|
13729
13822
|
if (disposed)
|
|
@@ -13755,10 +13848,10 @@ function worktreeRecoveryCommand(repositoryRoot, worktreeDir) {
|
|
|
13755
13848
|
return `git -C ${quoteShellArg(repositoryRoot)} worktree remove --force ${quoteShellArg(worktreeDir)}`;
|
|
13756
13849
|
}
|
|
13757
13850
|
function hasGrandparent(value2) {
|
|
13758
|
-
const parent =
|
|
13851
|
+
const parent = path4.dirname(value2);
|
|
13759
13852
|
if (parent === value2)
|
|
13760
13853
|
return false;
|
|
13761
|
-
const grandparent =
|
|
13854
|
+
const grandparent = path4.dirname(parent);
|
|
13762
13855
|
return grandparent !== parent;
|
|
13763
13856
|
}
|
|
13764
13857
|
function pathAncestors(value2) {
|
|
@@ -13766,7 +13859,7 @@ function pathAncestors(value2) {
|
|
|
13766
13859
|
let current = value2;
|
|
13767
13860
|
while (true) {
|
|
13768
13861
|
ancestors.push(current);
|
|
13769
|
-
const parent =
|
|
13862
|
+
const parent = path4.dirname(current);
|
|
13770
13863
|
if (parent === current)
|
|
13771
13864
|
return ancestors;
|
|
13772
13865
|
current = parent;
|
|
@@ -13775,89 +13868,167 @@ function pathAncestors(value2) {
|
|
|
13775
13868
|
function shouldPreserveLogicalPath(logicalPath) {
|
|
13776
13869
|
return pathAncestors(logicalPath).some((ancestor) => {
|
|
13777
13870
|
try {
|
|
13778
|
-
return
|
|
13871
|
+
return fs4.lstatSync(ancestor).isSymbolicLink() && hasGrandparent(ancestor);
|
|
13779
13872
|
} catch {
|
|
13780
13873
|
return false;
|
|
13781
13874
|
}
|
|
13782
13875
|
});
|
|
13783
13876
|
}
|
|
13784
13877
|
function canonicalizePreservingSymlinks(value2) {
|
|
13785
|
-
const logicalPath =
|
|
13878
|
+
const logicalPath = path4.resolve(value2);
|
|
13786
13879
|
const preserveLogicalPath = shouldPreserveLogicalPath(logicalPath);
|
|
13787
13880
|
try {
|
|
13788
|
-
const canonical =
|
|
13881
|
+
const canonical = fs4.realpathSync.native(logicalPath);
|
|
13789
13882
|
return preserveLogicalPath && canonical !== logicalPath ? logicalPath : canonical;
|
|
13790
13883
|
} catch {
|
|
13791
13884
|
return logicalPath;
|
|
13792
13885
|
}
|
|
13793
13886
|
}
|
|
13794
|
-
function resolveGitWorktreePath(value2,
|
|
13887
|
+
function resolveGitWorktreePath(value2, baseDir) {
|
|
13795
13888
|
const trimmed = value2.trim();
|
|
13796
13889
|
if (!trimmed)
|
|
13797
13890
|
throw new Error("gitWorktreeDir cannot be empty");
|
|
13798
13891
|
if (trimmed.includes("\x00")) {
|
|
13799
13892
|
throw new Error("gitWorktreeDir contains an unusable null byte; provide a valid path or omit gitWorktreeDir.");
|
|
13800
13893
|
}
|
|
13801
|
-
return canonicalizePreservingSymlinks(
|
|
13894
|
+
return canonicalizePreservingSymlinks(path4.isAbsolute(trimmed) ? trimmed : path4.resolve(baseDir, trimmed));
|
|
13802
13895
|
}
|
|
13803
13896
|
function comparableRealPath(value2) {
|
|
13804
|
-
const realpath =
|
|
13897
|
+
const realpath = fs4.realpathSync.native(value2).replace(/\\/g, "/");
|
|
13805
13898
|
return process.platform === "win32" ? realpath.toLowerCase() : realpath;
|
|
13806
13899
|
}
|
|
13807
|
-
function
|
|
13808
|
-
let existing =
|
|
13900
|
+
function nearestExistingAncestor(value2) {
|
|
13901
|
+
let existing = path4.resolve(value2);
|
|
13809
13902
|
const missing = [];
|
|
13810
13903
|
while (!pathExistsSync(existing)) {
|
|
13811
|
-
const parent =
|
|
13904
|
+
const parent = path4.dirname(existing);
|
|
13812
13905
|
if (parent === existing)
|
|
13813
13906
|
break;
|
|
13814
|
-
missing.unshift(
|
|
13907
|
+
missing.unshift(path4.basename(existing));
|
|
13815
13908
|
existing = parent;
|
|
13816
13909
|
}
|
|
13817
|
-
|
|
13910
|
+
return { existing, missing };
|
|
13911
|
+
}
|
|
13912
|
+
function comparablePathThroughExistingAncestor(value2) {
|
|
13913
|
+
const { existing, missing } = nearestExistingAncestor(value2);
|
|
13914
|
+
const resolved = path4.resolve(comparableRealPath(existing), ...missing).replace(/\\/g, "/");
|
|
13818
13915
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
13819
13916
|
}
|
|
13917
|
+
function isFileOrLink(value2) {
|
|
13918
|
+
try {
|
|
13919
|
+
const entry = fs4.lstatSync(value2);
|
|
13920
|
+
return entry.isFile() || entry.isSymbolicLink();
|
|
13921
|
+
} catch {
|
|
13922
|
+
return false;
|
|
13923
|
+
}
|
|
13924
|
+
}
|
|
13925
|
+
function isDirectory(value2) {
|
|
13926
|
+
try {
|
|
13927
|
+
return fs4.statSync(value2).isDirectory();
|
|
13928
|
+
} catch {
|
|
13929
|
+
return false;
|
|
13930
|
+
}
|
|
13931
|
+
}
|
|
13932
|
+
function looksLikeGitDirectory(directory) {
|
|
13933
|
+
if (!isDirectory(directory))
|
|
13934
|
+
return false;
|
|
13935
|
+
if (path4.basename(directory) === ".git")
|
|
13936
|
+
return true;
|
|
13937
|
+
if (!isFileOrLink(path4.join(directory, "HEAD")))
|
|
13938
|
+
return false;
|
|
13939
|
+
if (isFileOrLink(path4.join(directory, "commondir")))
|
|
13940
|
+
return true;
|
|
13941
|
+
return isDirectory(path4.join(directory, "objects")) && isDirectory(path4.join(directory, "refs"));
|
|
13942
|
+
}
|
|
13943
|
+
function enclosingGitMetadataDirectory(target) {
|
|
13944
|
+
const { existing } = nearestExistingAncestor(target);
|
|
13945
|
+
let realExisting = existing;
|
|
13946
|
+
try {
|
|
13947
|
+
realExisting = fs4.realpathSync.native(existing);
|
|
13948
|
+
} catch {}
|
|
13949
|
+
for (const candidate of new Set([...pathAncestors(existing), ...pathAncestors(realExisting)])) {
|
|
13950
|
+
if (looksLikeGitDirectory(candidate))
|
|
13951
|
+
return candidate;
|
|
13952
|
+
}
|
|
13953
|
+
const insideGitDir = runGitReadOnlyProbe(existing, ["rev-parse", "--is-inside-git-dir"]);
|
|
13954
|
+
if (insideGitDir.status !== 0 && isGitTimeoutResult(insideGitDir)) {
|
|
13955
|
+
throw new Error(`Timed out while validating gitWorktreeDir ${target}. Git reported: ${gitFailureMessage(insideGitDir)}`);
|
|
13956
|
+
}
|
|
13957
|
+
return insideGitDir.status === 0 && insideGitDir.stdout.trim() === "true" ? existing : undefined;
|
|
13958
|
+
}
|
|
13959
|
+
function assertSafeGitWorktreeTarget(target, invokingRoot) {
|
|
13960
|
+
const gitDirectory = enclosingGitMetadataDirectory(target);
|
|
13961
|
+
if (gitDirectory !== undefined) {
|
|
13962
|
+
throw new Error(`gitWorktreeDir must not be inside Git metadata: ${target} is inside the Git directory ${gitDirectory}. Choose a worktree root or a plain directory outside Git metadata.`);
|
|
13963
|
+
}
|
|
13964
|
+
if (invokingRoot !== undefined)
|
|
13965
|
+
validateWorktreeOutsideInvokingCheckout(target, invokingRoot);
|
|
13966
|
+
const { existing, missing } = nearestExistingAncestor(target);
|
|
13967
|
+
const workingTree = gitTopLevel(existing);
|
|
13968
|
+
if (workingTree === undefined)
|
|
13969
|
+
return;
|
|
13970
|
+
if (missing.length === 0 && comparableRealPath(target) === comparableRealPath(workingTree))
|
|
13971
|
+
return;
|
|
13972
|
+
throw new Error(`gitWorktreeDir must not be inside another Git working tree: ${target} is inside ${workingTree}. Pass that checkout's root to reuse it, or a path outside every Git checkout.`);
|
|
13973
|
+
}
|
|
13820
13974
|
function validateWorktreeOutsideInvokingCheckout(worktreeRoot, repoRoot) {
|
|
13821
13975
|
const repository = comparableRealPath(repoRoot);
|
|
13822
13976
|
const candidate = comparablePathThroughExistingAncestor(worktreeRoot);
|
|
13823
|
-
const relativePath =
|
|
13977
|
+
const relativePath = path4.relative(repository, candidate);
|
|
13824
13978
|
if (relativePath === "") {
|
|
13825
|
-
throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate
|
|
13979
|
+
throw new Error("gitWorktreeDir must not resolve to the invoking checkout; provide a separate worktree path outside it.");
|
|
13826
13980
|
}
|
|
13827
|
-
if (!relativePath.startsWith(`..${
|
|
13828
|
-
throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate
|
|
13981
|
+
if (!relativePath.startsWith(`..${path4.sep}`) && relativePath !== ".." && !path4.isAbsolute(relativePath)) {
|
|
13982
|
+
throw new Error("gitWorktreeDir must be outside the invoking checkout; provide a separate worktree path outside it.");
|
|
13829
13983
|
}
|
|
13830
13984
|
}
|
|
13831
13985
|
function gitPathFromOutput(value2, cwd) {
|
|
13832
13986
|
const trimmed = value2.trim();
|
|
13833
13987
|
if (!trimmed)
|
|
13834
13988
|
return;
|
|
13835
|
-
return
|
|
13989
|
+
return path4.isAbsolute(trimmed) ? path4.resolve(trimmed) : path4.resolve(cwd, trimmed);
|
|
13836
13990
|
}
|
|
13837
13991
|
function pathExistsSync(value2) {
|
|
13992
|
+
return pathStatSync(value2) !== undefined;
|
|
13993
|
+
}
|
|
13994
|
+
function pathStatSync(value2) {
|
|
13838
13995
|
try {
|
|
13839
|
-
|
|
13840
|
-
return true;
|
|
13996
|
+
return fs4.statSync(value2);
|
|
13841
13997
|
} catch (error) {
|
|
13842
13998
|
const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
|
|
13843
13999
|
if (code === "ENOENT" || code === "ENOTDIR")
|
|
13844
|
-
return
|
|
14000
|
+
return;
|
|
13845
14001
|
throw error;
|
|
13846
14002
|
}
|
|
13847
14003
|
}
|
|
13848
|
-
function
|
|
14004
|
+
function probeInvokingRepository(cwd) {
|
|
13849
14005
|
const result = runGitReadOnlyProbe(cwd, ["rev-parse", "--show-toplevel"]);
|
|
13850
14006
|
if (result.status !== 0) {
|
|
13851
14007
|
if (isGitTimeoutResult(result)) {
|
|
13852
14008
|
throw new Error(`Timed out while checking the Git repository for gitWorktreeDir from ${cwd}. Git reported: ${gitFailureMessage(result)}`);
|
|
13853
14009
|
}
|
|
13854
|
-
|
|
14010
|
+
return { failure: gitFailureMessage(result) };
|
|
13855
14011
|
}
|
|
13856
|
-
const
|
|
13857
|
-
if (
|
|
14012
|
+
const root = gitPathFromOutput(result.stdout, cwd);
|
|
14013
|
+
if (root === undefined) {
|
|
13858
14014
|
throw new Error(`gitWorktreeDir could not resolve the repository top level from ${cwd}: git returned an empty path.`);
|
|
13859
14015
|
}
|
|
13860
|
-
return
|
|
14016
|
+
return { repository: { root, ...cwdWithinGitRepository(cwd, root) } };
|
|
14017
|
+
}
|
|
14018
|
+
function resolveGitWorktreeSetupRequest(options) {
|
|
14019
|
+
const probe = probeInvokingRepository(options.cwd);
|
|
14020
|
+
if ("repository" in probe) {
|
|
14021
|
+
return {
|
|
14022
|
+
options,
|
|
14023
|
+
repository: probe.repository,
|
|
14024
|
+
target: resolveGitWorktreePath(options.gitWorktreeDir, probe.repository.logicalRoot)
|
|
14025
|
+
};
|
|
14026
|
+
}
|
|
14027
|
+
return {
|
|
14028
|
+
options,
|
|
14029
|
+
repositoryProbeFailure: probe.failure,
|
|
14030
|
+
target: resolveGitWorktreePath(options.gitWorktreeDir, canonicalizePreservingSymlinks(options.cwd))
|
|
14031
|
+
};
|
|
13861
14032
|
}
|
|
13862
14033
|
function gitTopLevelFromResult(result, cwd, description) {
|
|
13863
14034
|
if (result.status !== 0) {
|
|
@@ -13893,25 +14064,25 @@ function dirnameForEachRelativeComponent(base, relativePath) {
|
|
|
13893
14064
|
continue;
|
|
13894
14065
|
if (component === "..")
|
|
13895
14066
|
return;
|
|
13896
|
-
current =
|
|
14067
|
+
current = path4.dirname(current);
|
|
13897
14068
|
}
|
|
13898
14069
|
return current;
|
|
13899
14070
|
}
|
|
13900
14071
|
function cwdWithinGitRepository(cwd, repoRoot) {
|
|
13901
|
-
const sourceCwd =
|
|
13902
|
-
const sourceRepoRoot =
|
|
13903
|
-
const relativeCwd =
|
|
13904
|
-
const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") ||
|
|
14072
|
+
const sourceCwd = fs4.realpathSync.native(cwd);
|
|
14073
|
+
const sourceRepoRoot = fs4.realpathSync.native(repoRoot);
|
|
14074
|
+
const relativeCwd = path4.relative(sourceRepoRoot, sourceCwd);
|
|
14075
|
+
const safeRelativeCwd = relativeCwd === "" || relativeCwd.startsWith("..") || path4.isAbsolute(relativeCwd) ? "" : relativeCwd;
|
|
13905
14076
|
const logicalCwd = canonicalizePreservingSymlinks(cwd);
|
|
13906
14077
|
return {
|
|
13907
14078
|
relativeCwd: safeRelativeCwd,
|
|
13908
|
-
|
|
14079
|
+
logicalRoot: dirnameForEachRelativeComponent(logicalCwd, safeRelativeCwd) ?? repoRoot
|
|
13909
14080
|
};
|
|
13910
14081
|
}
|
|
13911
14082
|
function workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd) {
|
|
13912
|
-
return relativeCwd === "" ? worktreeRoot :
|
|
14083
|
+
return relativeCwd === "" ? worktreeRoot : path4.join(worktreeRoot, relativeCwd);
|
|
13913
14084
|
}
|
|
13914
|
-
function
|
|
14085
|
+
function validateGitWorktreeRoot(worktreeRoot) {
|
|
13915
14086
|
const topLevel = gitTopLevel(worktreeRoot);
|
|
13916
14087
|
if (topLevel === undefined) {
|
|
13917
14088
|
throw new Error(`gitWorktreeDir already exists but is not a Git worktree: ${worktreeRoot}`);
|
|
@@ -13919,8 +14090,18 @@ function validateExistingGitWorktreeRoot(worktreeRoot, repoRoot) {
|
|
|
13919
14090
|
if (comparableRealPath(worktreeRoot) !== comparableRealPath(topLevel)) {
|
|
13920
14091
|
throw new Error(`gitWorktreeDir already exists but is not a Git worktree root: ${worktreeRoot}. Git top-level checkout is ${topLevel}`);
|
|
13921
14092
|
}
|
|
13922
|
-
|
|
13923
|
-
|
|
14093
|
+
return gitCommonDirForWorktree(topLevel);
|
|
14094
|
+
}
|
|
14095
|
+
function existingGitWorktreeCommonDir(directory) {
|
|
14096
|
+
return gitTopLevel(directory) === undefined ? undefined : validateGitWorktreeRoot(directory);
|
|
14097
|
+
}
|
|
14098
|
+
function sameGitCommonDir(left, right) {
|
|
14099
|
+
return comparableRealPath(left) === comparableRealPath(right);
|
|
14100
|
+
}
|
|
14101
|
+
function validateCreatedGitWorktree(worktreeRoot, repository) {
|
|
14102
|
+
assertSafeGitWorktreeTarget(worktreeRoot, repository.root);
|
|
14103
|
+
if (!sameGitCommonDir(validateGitWorktreeRoot(worktreeRoot), gitCommonDirForWorktree(repository.root))) {
|
|
14104
|
+
throw new Error(`gitWorktreeDir does not belong to the invoking Git repository: ${worktreeRoot}`);
|
|
13924
14105
|
}
|
|
13925
14106
|
}
|
|
13926
14107
|
function gitDirectoryForWorktree(cwd) {
|
|
@@ -13934,26 +14115,27 @@ function gitDirectoryForWorktree(cwd) {
|
|
|
13934
14115
|
return gitDir;
|
|
13935
14116
|
}
|
|
13936
14117
|
function captureGitWorktreeIdentitySnapshot(setup) {
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
const
|
|
14118
|
+
const { worktreeRoot, repositoryRoot } = setup.result;
|
|
14119
|
+
assertSafeGitWorktreeTarget(worktreeRoot, setup.invokingRoot);
|
|
14120
|
+
const commonDir = validateGitWorktreeRoot(worktreeRoot);
|
|
14121
|
+
const stats = fs4.statSync(worktreeRoot);
|
|
13940
14122
|
return {
|
|
13941
|
-
worktreeRealPath: comparableRealPath(
|
|
13942
|
-
repositoryRealPath: comparableRealPath(
|
|
13943
|
-
gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(
|
|
13944
|
-
commonDirRealPath: comparableRealPath(
|
|
14123
|
+
worktreeRealPath: comparableRealPath(worktreeRoot),
|
|
14124
|
+
repositoryRealPath: comparableRealPath(repositoryRoot),
|
|
14125
|
+
gitDirRealPath: comparableRealPath(gitDirectoryForWorktree(worktreeRoot)),
|
|
14126
|
+
commonDirRealPath: comparableRealPath(commonDir),
|
|
13945
14127
|
device: stats.dev,
|
|
13946
14128
|
inode: stats.ino
|
|
13947
14129
|
};
|
|
13948
14130
|
}
|
|
13949
14131
|
function captureGitWorktreeIdentity(setup) {
|
|
13950
14132
|
const snapshot = captureGitWorktreeIdentitySnapshot(setup);
|
|
13951
|
-
return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.worktreeRoot) };
|
|
14133
|
+
return { ...snapshot, generation: openGitWorktreeGenerationAnchor(setup.result.worktreeRoot) };
|
|
13952
14134
|
}
|
|
13953
14135
|
function assertCachedGitWorktreeIdentity(cached, options) {
|
|
13954
14136
|
let current;
|
|
13955
14137
|
try {
|
|
13956
|
-
current = captureGitWorktreeIdentitySnapshot(cached
|
|
14138
|
+
current = captureGitWorktreeIdentitySnapshot(cached);
|
|
13957
14139
|
cached.identity.generation.assertCurrent();
|
|
13958
14140
|
} catch (error) {
|
|
13959
14141
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -13961,34 +14143,58 @@ function assertCachedGitWorktreeIdentity(cached, options) {
|
|
|
13961
14143
|
}
|
|
13962
14144
|
const expected = cached.identity;
|
|
13963
14145
|
if (current.worktreeRealPath !== expected.worktreeRealPath || current.repositoryRealPath !== expected.repositoryRealPath || current.gitDirRealPath !== expected.gitDirRealPath || current.commonDirRealPath !== expected.commonDirRealPath || current.device !== expected.device || current.inode !== expected.inode) {
|
|
13964
|
-
throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended
|
|
13965
|
-
}
|
|
14146
|
+
throw new Error(`Cached gitWorktreeDir changed before reuse: ${options.gitWorktreeDir}. Start a new run with the intended worktree.`);
|
|
14147
|
+
}
|
|
14148
|
+
}
|
|
14149
|
+
function requireInvokingRepository(request, action) {
|
|
14150
|
+
if (request.repository !== undefined)
|
|
14151
|
+
return request.repository;
|
|
14152
|
+
throw new Error([
|
|
14153
|
+
`gitWorktreeDir requires the workflow to be invoked from inside a Git repository to ${action}.`,
|
|
14154
|
+
"Start the workflow from a checkout of the repository the new worktree should come from, or set gitWorktreeDir to the root of an existing Git worktree to reuse it from any directory.",
|
|
14155
|
+
`Git reported: ${request.repositoryProbeFailure ?? "no repository"}`
|
|
14156
|
+
].join(" "));
|
|
14157
|
+
}
|
|
14158
|
+
function setupGitWorktreeFromRequest(request, ownerRunId) {
|
|
14159
|
+
const { repository, target } = request;
|
|
14160
|
+
assertSafeGitWorktreeTarget(target, repository?.root);
|
|
14161
|
+
const entry = pathStatSync(target);
|
|
14162
|
+
if (entry === undefined)
|
|
14163
|
+
return createGitWorktreeAtPath(request, false);
|
|
14164
|
+
if (!entry.isDirectory())
|
|
14165
|
+
throw new Error(`gitWorktreeDir already exists but is not a directory: ${target}`);
|
|
14166
|
+
if (fs4.readdirSync(target).length === 0)
|
|
14167
|
+
return createGitWorktreeAtPath(request, true);
|
|
14168
|
+
const commonDir = existingGitWorktreeCommonDir(target);
|
|
14169
|
+
if (commonDir === undefined)
|
|
14170
|
+
return allocateGitWorktree(request, ownerRunId);
|
|
14171
|
+
const sameRepository = repository !== undefined && sameGitCommonDir(commonDir, gitCommonDirForWorktree(repository.root));
|
|
14172
|
+
return {
|
|
14173
|
+
result: {
|
|
14174
|
+
worktreeRoot: target,
|
|
14175
|
+
cwd: sameRepository ? workspaceCwdForGitWorktreeRoot(target, repository.relativeCwd) : target,
|
|
14176
|
+
repositoryRoot: sameRepository ? repository.root : target,
|
|
14177
|
+
created: false
|
|
14178
|
+
},
|
|
14179
|
+
...repository !== undefined ? { invokingRoot: repository.root } : {}
|
|
14180
|
+
};
|
|
13966
14181
|
}
|
|
13967
|
-
function
|
|
13968
|
-
const
|
|
13969
|
-
const
|
|
14182
|
+
function createGitWorktreeAtPath(request, existingEmptyDirectory) {
|
|
14183
|
+
const { target: worktreeRoot } = request;
|
|
14184
|
+
const repository = requireInvokingRepository(request, `create a new worktree at ${worktreeRoot}`);
|
|
14185
|
+
const mainRoot = findCanonicalGitRoot(repository.root);
|
|
13970
14186
|
if (mainRoot === undefined) {
|
|
13971
|
-
throw new Error(`Unable to resolve the canonical main Git repository root from ${
|
|
14187
|
+
throw new Error(`Unable to resolve the canonical main Git repository root from ${repository.root}.`);
|
|
13972
14188
|
}
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, relativeCwd),
|
|
13981
|
-
repositoryRoot: repoRoot,
|
|
13982
|
-
created: false
|
|
13983
|
-
};
|
|
13984
|
-
}
|
|
13985
|
-
try {
|
|
13986
|
-
fs3.mkdirSync(path3.dirname(worktreeRoot), { recursive: true });
|
|
13987
|
-
} catch (error) {
|
|
13988
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
13989
|
-
throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
|
|
14189
|
+
if (!existingEmptyDirectory) {
|
|
14190
|
+
try {
|
|
14191
|
+
fs4.mkdirSync(path4.dirname(worktreeRoot), { recursive: true });
|
|
14192
|
+
} catch (error) {
|
|
14193
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14194
|
+
throw new Error(`Failed to create parent directory for requested gitWorktreeDir ${worktreeRoot}: ${message}`);
|
|
14195
|
+
}
|
|
13990
14196
|
}
|
|
13991
|
-
const baseRef = options.baseBranch?.trim() || "HEAD";
|
|
14197
|
+
const baseRef = request.options.baseBranch?.trim() || "HEAD";
|
|
13992
14198
|
const result = runGit(mainRoot, ["worktree", "add", "--detach", worktreeRoot, baseRef]);
|
|
13993
14199
|
if (result.status !== 0) {
|
|
13994
14200
|
throw new Error([
|
|
@@ -13998,30 +14204,127 @@ function setupGitWorktree(options) {
|
|
|
13998
14204
|
`));
|
|
13999
14205
|
}
|
|
14000
14206
|
try {
|
|
14001
|
-
|
|
14002
|
-
validateExistingGitWorktreeRoot(worktreeRoot, repoRoot);
|
|
14207
|
+
validateCreatedGitWorktree(worktreeRoot, repository);
|
|
14003
14208
|
} catch (error) {
|
|
14004
14209
|
runGit(mainRoot, ["worktree", "remove", "--force", worktreeRoot]);
|
|
14005
14210
|
const message = error instanceof Error ? error.message : String(error);
|
|
14006
14211
|
throw new Error(`Created gitWorktreeDir failed post-creation validation: ${message}`);
|
|
14007
14212
|
}
|
|
14008
14213
|
return {
|
|
14009
|
-
|
|
14010
|
-
|
|
14011
|
-
|
|
14012
|
-
|
|
14214
|
+
result: {
|
|
14215
|
+
worktreeRoot,
|
|
14216
|
+
cwd: workspaceCwdForGitWorktreeRoot(worktreeRoot, repository.relativeCwd),
|
|
14217
|
+
repositoryRoot: repository.root,
|
|
14218
|
+
created: true
|
|
14219
|
+
},
|
|
14220
|
+
invokingRoot: repository.root
|
|
14013
14221
|
};
|
|
14014
14222
|
}
|
|
14223
|
+
function containedWorktreeCwd(checkout, relativeCwd) {
|
|
14224
|
+
const cwd = workspaceCwdForGitWorktreeRoot(checkout, relativeCwd);
|
|
14225
|
+
let resolved;
|
|
14226
|
+
try {
|
|
14227
|
+
resolved = fs4.realpathSync.native(cwd);
|
|
14228
|
+
} catch {
|
|
14229
|
+
resolved = "";
|
|
14230
|
+
}
|
|
14231
|
+
const relative2 = resolved === "" ? undefined : path4.relative(fs4.realpathSync.native(checkout), resolved);
|
|
14232
|
+
if (relative2 === undefined || relative2 === ".." || relative2.startsWith(`..${path4.sep}`) || path4.isAbsolute(relative2) || !fs4.statSync(resolved).isDirectory()) {
|
|
14233
|
+
throw new Error(`The selected base does not contain a working directory ${relativeCwd || "."} inside the worktree ${checkout}.`);
|
|
14234
|
+
}
|
|
14235
|
+
return cwd;
|
|
14236
|
+
}
|
|
14237
|
+
function allocatedGitWorktreeSetup(checkout, repository, created) {
|
|
14238
|
+
return {
|
|
14239
|
+
result: {
|
|
14240
|
+
worktreeRoot: checkout,
|
|
14241
|
+
cwd: containedWorktreeCwd(checkout, repository.relativeCwd),
|
|
14242
|
+
repositoryRoot: repository.root,
|
|
14243
|
+
created
|
|
14244
|
+
},
|
|
14245
|
+
invokingRoot: repository.root
|
|
14246
|
+
};
|
|
14247
|
+
}
|
|
14248
|
+
function validateOwnedGitWorktree(checkout, repository) {
|
|
14249
|
+
validateCreatedGitWorktree(checkout, repository);
|
|
14250
|
+
const gitDir = gitDirectoryForWorktree(checkout);
|
|
14251
|
+
if (sameGitCommonDir(gitDir, gitCommonDirForWorktree(checkout))) {
|
|
14252
|
+
throw new Error(`${checkout} is not a linked worktree`);
|
|
14253
|
+
}
|
|
14254
|
+
const backlink = fs4.readFileSync(path4.join(gitDir, "gitdir"), "utf8").trim();
|
|
14255
|
+
if (!backlink || comparableRealPath(path4.resolve(gitDir, backlink)) !== comparableRealPath(path4.join(checkout, ".git"))) {
|
|
14256
|
+
throw new Error(`the Git directory of ${checkout} belongs to another checkout`);
|
|
14257
|
+
}
|
|
14258
|
+
}
|
|
14259
|
+
function findOwnedGitWorktree(root, repository, ownerRunId) {
|
|
14260
|
+
const [checkout] = findOwnedWorktreeCheckouts(root, path4.basename(repository.root), ownerRunId);
|
|
14261
|
+
if (checkout === undefined)
|
|
14262
|
+
return;
|
|
14263
|
+
try {
|
|
14264
|
+
validateOwnedGitWorktree(checkout, repository);
|
|
14265
|
+
return allocatedGitWorktreeSetup(checkout, repository, false);
|
|
14266
|
+
} catch (error) {
|
|
14267
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14268
|
+
throw new Error(`The worktree this workflow run allocated under gitWorktreeDir ${root} can no longer be reused: ${checkout}. ${message}`);
|
|
14269
|
+
}
|
|
14270
|
+
}
|
|
14271
|
+
function allocateGitWorktree(request, ownerRunId) {
|
|
14272
|
+
const { target: root } = request;
|
|
14273
|
+
const repository = requireInvokingRepository(request, `create a new worktree under ${root}`);
|
|
14274
|
+
if (ownerRunId !== undefined) {
|
|
14275
|
+
const owned = findOwnedGitWorktree(root, repository, ownerRunId);
|
|
14276
|
+
if (owned !== undefined)
|
|
14277
|
+
return owned;
|
|
14278
|
+
}
|
|
14279
|
+
const baseRef = request.options.baseBranch?.trim() || "HEAD";
|
|
14280
|
+
const revision = runGit(repository.root, ["rev-parse", "--verify", "--end-of-options", `${baseRef}^{commit}`]);
|
|
14281
|
+
const commit = revision.status === 0 ? revision.stdout.trim() : "";
|
|
14282
|
+
if (commit === "") {
|
|
14283
|
+
throw new Error(`Failed to resolve ${baseRef} to a commit for gitWorktreeDir ${root}. Git reported: ${gitFailureMessage(revision)}`);
|
|
14284
|
+
}
|
|
14285
|
+
const checkout = allocateWorktreeCheckoutPath(root, path4.basename(repository.root));
|
|
14286
|
+
const add = runGit(repository.root, ["worktree", "add", "--detach", "--no-checkout", checkout, commit]);
|
|
14287
|
+
if (add.status !== 0) {
|
|
14288
|
+
removeEmptyWorktreeBucket(checkout);
|
|
14289
|
+
throw new Error(`Failed to create git worktree at ${checkout} under gitWorktreeDir ${root} from ${baseRef}. Git reported: ${gitFailureMessage(add)}`);
|
|
14290
|
+
}
|
|
14291
|
+
try {
|
|
14292
|
+
const gitDir = gitDirectoryForWorktree(checkout);
|
|
14293
|
+
runGitOrThrow(checkout, ["config", "--file", path4.join(gitDir, "config.worktree"), "core.worktree", checkout]);
|
|
14294
|
+
runGitOrThrow(checkout, ["--work-tree=.", "reset", "--hard", "--no-recurse-submodules", commit]);
|
|
14295
|
+
validateCreatedGitWorktree(checkout, repository);
|
|
14296
|
+
const setup = allocatedGitWorktreeSetup(checkout, repository, true);
|
|
14297
|
+
if (ownerRunId !== undefined)
|
|
14298
|
+
bindWorktreeOwner(gitDir, ownerRunId);
|
|
14299
|
+
return setup;
|
|
14300
|
+
} catch (error) {
|
|
14301
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14302
|
+
const removal = runGit(repository.root, ["worktree", "remove", "--force", checkout]);
|
|
14303
|
+
removeEmptyWorktreeBucket(checkout);
|
|
14304
|
+
const rollback = removal.status === 0 ? "" : ` Rolling back the incomplete worktree also failed; remove it with: ${worktreeRecoveryCommand(repository.root, checkout)}`;
|
|
14305
|
+
throw new Error(`Failed to set up git worktree at ${checkout} under gitWorktreeDir ${root}: ${message}${rollback}`);
|
|
14306
|
+
}
|
|
14307
|
+
}
|
|
14308
|
+
function runGitOrThrow(cwd, args) {
|
|
14309
|
+
const result = runGit(cwd, args);
|
|
14310
|
+
if (result.status !== 0)
|
|
14311
|
+
throw new Error(gitFailureMessage(result));
|
|
14312
|
+
}
|
|
14313
|
+
function setupGitWorktree(options) {
|
|
14314
|
+
return setupGitWorktreeFromRequest(resolveGitWorktreeSetupRequest(options)).result;
|
|
14315
|
+
}
|
|
14015
14316
|
var init_worktree_git = __esm(() => {
|
|
14317
|
+
init_worktree_allocation();
|
|
14016
14318
|
init_worktree_generation();
|
|
14017
14319
|
init_worktree_git_runner();
|
|
14018
14320
|
init_worktree_root();
|
|
14321
|
+
init_worktree_allocation();
|
|
14019
14322
|
init_worktree_git_runner();
|
|
14020
14323
|
});
|
|
14021
14324
|
|
|
14022
14325
|
// dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts
|
|
14023
|
-
function createGitWorktreeSetupCacheOwner(suppliedCache) {
|
|
14024
|
-
const cache = suppliedCache ?? createGitWorktreeSetupCache();
|
|
14326
|
+
function createGitWorktreeSetupCacheOwner(suppliedCache, ownerRunId) {
|
|
14327
|
+
const cache = suppliedCache ?? createGitWorktreeSetupCache(ownerRunId);
|
|
14025
14328
|
const ownsCache = suppliedCache === undefined;
|
|
14026
14329
|
let released = false;
|
|
14027
14330
|
return {
|
|
@@ -14042,20 +14345,20 @@ var init_worktree_cache_lifecycle = __esm(() => {
|
|
|
14042
14345
|
});
|
|
14043
14346
|
|
|
14044
14347
|
// dist/builtin/workflows/src/runs/shared/worktree-diff.ts
|
|
14045
|
-
import * as
|
|
14046
|
-
import * as
|
|
14348
|
+
import * as fs5 from "node:fs";
|
|
14349
|
+
import * as path5 from "node:path";
|
|
14047
14350
|
function safePatchAgentName(agent) {
|
|
14048
14351
|
return agent.replace(/[^\w.-]/g, "_");
|
|
14049
14352
|
}
|
|
14050
14353
|
function removeSyntheticPath(worktree, syntheticPath) {
|
|
14051
|
-
const resolved =
|
|
14052
|
-
const relative =
|
|
14053
|
-
if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${
|
|
14354
|
+
const resolved = path5.resolve(worktree.path, syntheticPath);
|
|
14355
|
+
const relative = path5.relative(worktree.path, resolved);
|
|
14356
|
+
if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path5.sep}`) || path5.isAbsolute(relative)) {
|
|
14054
14357
|
return;
|
|
14055
14358
|
}
|
|
14056
14359
|
let stat;
|
|
14057
14360
|
try {
|
|
14058
|
-
stat =
|
|
14361
|
+
stat = fs5.lstatSync(resolved);
|
|
14059
14362
|
} catch (error) {
|
|
14060
14363
|
const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
|
|
14061
14364
|
if (code === "ENOENT")
|
|
@@ -14063,14 +14366,14 @@ function removeSyntheticPath(worktree, syntheticPath) {
|
|
|
14063
14366
|
throw error;
|
|
14064
14367
|
}
|
|
14065
14368
|
if (stat.isSymbolicLink()) {
|
|
14066
|
-
|
|
14369
|
+
fs5.unlinkSync(resolved);
|
|
14067
14370
|
return;
|
|
14068
14371
|
}
|
|
14069
14372
|
if (stat.isDirectory()) {
|
|
14070
|
-
|
|
14373
|
+
fs5.rmSync(resolved, { recursive: true, force: true });
|
|
14071
14374
|
return;
|
|
14072
14375
|
}
|
|
14073
|
-
|
|
14376
|
+
fs5.rmSync(resolved, { force: true });
|
|
14074
14377
|
}
|
|
14075
14378
|
function removeSyntheticPathsBeforeDiff(worktree) {
|
|
14076
14379
|
if (worktree.syntheticPaths.length === 0)
|
|
@@ -14119,7 +14422,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
|
|
|
14119
14422
|
const diffStat = runGitChecked(worktree.path, ["diff", "--cached", "--stat", setup.baseCommit]).trim();
|
|
14120
14423
|
const patch = runGitChecked(worktree.path, ["diff", "--cached", setup.baseCommit]);
|
|
14121
14424
|
const numstat = runGitChecked(worktree.path, ["diff", "--cached", "--numstat", setup.baseCommit]);
|
|
14122
|
-
|
|
14425
|
+
fs5.writeFileSync(patchPath, patch, "utf-8");
|
|
14123
14426
|
if (!patch.trim()) {
|
|
14124
14427
|
return emptyDiff(worktree.index, agent, worktree.branch, patchPath);
|
|
14125
14428
|
}
|
|
@@ -14137,7 +14440,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
|
|
|
14137
14440
|
}
|
|
14138
14441
|
function writeEmptyPatch(patchPath) {
|
|
14139
14442
|
try {
|
|
14140
|
-
|
|
14443
|
+
fs5.writeFileSync(patchPath, "", "utf-8");
|
|
14141
14444
|
} catch {}
|
|
14142
14445
|
}
|
|
14143
14446
|
function hasWorktreeChanges(diff) {
|
|
@@ -14145,7 +14448,7 @@ function hasWorktreeChanges(diff) {
|
|
|
14145
14448
|
}
|
|
14146
14449
|
function diffWorktrees(setup, agents, diffsDir) {
|
|
14147
14450
|
try {
|
|
14148
|
-
|
|
14451
|
+
fs5.mkdirSync(diffsDir, { recursive: true });
|
|
14149
14452
|
} catch {
|
|
14150
14453
|
return [];
|
|
14151
14454
|
}
|
|
@@ -14153,7 +14456,7 @@ function diffWorktrees(setup, agents, diffsDir) {
|
|
|
14153
14456
|
for (let index = 0;index < setup.worktrees.length; index++) {
|
|
14154
14457
|
const worktree = setup.worktrees[index];
|
|
14155
14458
|
const agent = agents[index] ?? `task-${index + 1}`;
|
|
14156
|
-
const patchPath =
|
|
14459
|
+
const patchPath = path5.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
|
|
14157
14460
|
try {
|
|
14158
14461
|
diffs.push(captureWorktreeDiff(setup, worktree, agent, patchPath));
|
|
14159
14462
|
} catch {
|
|
@@ -14175,7 +14478,7 @@ function formatWorktreeDiffSummary(diffs) {
|
|
|
14175
14478
|
}
|
|
14176
14479
|
lines.push("");
|
|
14177
14480
|
}
|
|
14178
|
-
const patchesDir =
|
|
14481
|
+
const patchesDir = path5.dirname(changed[0].patchPath);
|
|
14179
14482
|
lines.push(`Full patches: ${patchesDir}`);
|
|
14180
14483
|
return lines.join(`
|
|
14181
14484
|
`).trimEnd();
|
|
@@ -14185,8 +14488,8 @@ var init_worktree_diff = __esm(() => {
|
|
|
14185
14488
|
});
|
|
14186
14489
|
|
|
14187
14490
|
// dist/builtin/workflows/src/runs/shared/worktree-post-create.ts
|
|
14188
|
-
import * as
|
|
14189
|
-
import * as
|
|
14491
|
+
import * as fs6 from "node:fs";
|
|
14492
|
+
import * as path6 from "node:path";
|
|
14190
14493
|
function tracked(repo, relativePath) {
|
|
14191
14494
|
const result = runGit(repo, ["ls-files", "--error-unmatch", "--", relativePath]);
|
|
14192
14495
|
return result.status === 0;
|
|
@@ -14206,12 +14509,12 @@ function hasTrackedPathComponent(repo, relativePath) {
|
|
|
14206
14509
|
return false;
|
|
14207
14510
|
}
|
|
14208
14511
|
function copyUntrackedFile(mainRoot, worktreeRoot, relativePath) {
|
|
14209
|
-
const source =
|
|
14210
|
-
const destination =
|
|
14211
|
-
if (!
|
|
14512
|
+
const source = path6.join(mainRoot, relativePath);
|
|
14513
|
+
const destination = path6.join(worktreeRoot, relativePath);
|
|
14514
|
+
if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
|
|
14212
14515
|
return false;
|
|
14213
|
-
|
|
14214
|
-
|
|
14516
|
+
fs6.mkdirSync(path6.dirname(destination), { recursive: true });
|
|
14517
|
+
fs6.copyFileSync(source, destination);
|
|
14215
14518
|
return true;
|
|
14216
14519
|
}
|
|
14217
14520
|
function propagateLocalSettings(mainRoot, worktreeRoot) {
|
|
@@ -14224,14 +14527,14 @@ function propagateLocalSettings(mainRoot, worktreeRoot) {
|
|
|
14224
14527
|
return copied;
|
|
14225
14528
|
}
|
|
14226
14529
|
function populatedHooksDirectory(mainRoot) {
|
|
14227
|
-
const husky =
|
|
14530
|
+
const husky = path6.join(mainRoot, ".husky");
|
|
14228
14531
|
try {
|
|
14229
|
-
if (
|
|
14532
|
+
if (fs6.statSync(husky).isDirectory())
|
|
14230
14533
|
return husky;
|
|
14231
14534
|
} catch {}
|
|
14232
|
-
const hooks =
|
|
14535
|
+
const hooks = path6.join(mainRoot, ".git", "hooks");
|
|
14233
14536
|
try {
|
|
14234
|
-
const populated =
|
|
14537
|
+
const populated = fs6.readdirSync(hooks, { withFileTypes: true }).some((entry) => entry.isFile() && !entry.name.endsWith(".sample"));
|
|
14235
14538
|
return populated ? hooks : undefined;
|
|
14236
14539
|
} catch {
|
|
14237
14540
|
return;
|
|
@@ -14242,7 +14545,7 @@ function configureSharedHooksPath(mainRoot) {
|
|
|
14242
14545
|
if (desired === undefined)
|
|
14243
14546
|
return;
|
|
14244
14547
|
const current = runGitPlain(mainRoot, ["config", "--get", "core.hooksPath"]);
|
|
14245
|
-
if (current.status === 0 &&
|
|
14548
|
+
if (current.status === 0 && path6.resolve(mainRoot, current.stdout.trim()) === desired)
|
|
14246
14549
|
return;
|
|
14247
14550
|
const configured = runGitPlain(mainRoot, ["config", "core.hooksPath", desired]);
|
|
14248
14551
|
if (configured.status !== 0) {
|
|
@@ -14251,10 +14554,10 @@ function configureSharedHooksPath(mainRoot) {
|
|
|
14251
14554
|
}
|
|
14252
14555
|
function normalizeSymlinkDirectory(value2) {
|
|
14253
14556
|
const trimmed = value2.trim();
|
|
14254
|
-
if (!trimmed ||
|
|
14557
|
+
if (!trimmed || path6.isAbsolute(trimmed))
|
|
14255
14558
|
return;
|
|
14256
|
-
const normalized =
|
|
14257
|
-
if (normalized === "." || normalized === ".." || normalized.startsWith(`..${
|
|
14559
|
+
const normalized = path6.normalize(trimmed);
|
|
14560
|
+
if (normalized === "." || normalized === ".." || normalized.startsWith(`..${path6.sep}`))
|
|
14258
14561
|
return;
|
|
14259
14562
|
return normalized;
|
|
14260
14563
|
}
|
|
@@ -14264,20 +14567,20 @@ function symlinkConfiguredDirectories(mainRoot, worktreeRoot, directories) {
|
|
|
14264
14567
|
const relativePath = normalizeSymlinkDirectory(rawDirectory);
|
|
14265
14568
|
if (relativePath === undefined || synthetic.includes(relativePath))
|
|
14266
14569
|
continue;
|
|
14267
|
-
const source =
|
|
14268
|
-
const destination =
|
|
14269
|
-
if (!
|
|
14570
|
+
const source = path6.join(mainRoot, relativePath);
|
|
14571
|
+
const destination = path6.join(worktreeRoot, relativePath);
|
|
14572
|
+
if (!fs6.existsSync(source) || fs6.existsSync(destination) || hasTrackedPathComponent(worktreeRoot, relativePath))
|
|
14270
14573
|
continue;
|
|
14271
|
-
|
|
14574
|
+
fs6.mkdirSync(path6.dirname(destination), { recursive: true });
|
|
14272
14575
|
try {
|
|
14273
|
-
|
|
14576
|
+
fs6.symlinkSync(source, destination, process.platform === "win32" ? "junction" : undefined);
|
|
14274
14577
|
synthetic.push(relativePath);
|
|
14275
14578
|
} catch {}
|
|
14276
14579
|
}
|
|
14277
14580
|
return synthetic;
|
|
14278
14581
|
}
|
|
14279
14582
|
function copyWorktreeIncludes(mainRoot, worktreeRoot) {
|
|
14280
|
-
if (!
|
|
14583
|
+
if (!fs6.existsSync(path6.join(mainRoot, ".worktreeinclude")))
|
|
14281
14584
|
return;
|
|
14282
14585
|
const ignored = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-standard"]);
|
|
14283
14586
|
const included = runGit(mainRoot, ["ls-files", "--others", "--ignored", "--exclude-from=.worktreeinclude"]);
|
|
@@ -14287,13 +14590,13 @@ function copyWorktreeIncludes(mainRoot, worktreeRoot) {
|
|
|
14287
14590
|
for (const relativePath of included.stdout.split(/\r?\n/).filter(Boolean)) {
|
|
14288
14591
|
if (!ignoredPaths.has(relativePath) || hasTrackedPathComponent(worktreeRoot, relativePath))
|
|
14289
14592
|
continue;
|
|
14290
|
-
const source =
|
|
14291
|
-
const destination =
|
|
14593
|
+
const source = path6.join(mainRoot, relativePath);
|
|
14594
|
+
const destination = path6.join(worktreeRoot, relativePath);
|
|
14292
14595
|
try {
|
|
14293
|
-
if (!
|
|
14596
|
+
if (!fs6.statSync(source).isFile() || fs6.existsSync(destination))
|
|
14294
14597
|
continue;
|
|
14295
|
-
|
|
14296
|
-
|
|
14598
|
+
fs6.mkdirSync(path6.dirname(destination), { recursive: true });
|
|
14599
|
+
fs6.copyFileSync(source, destination);
|
|
14297
14600
|
} catch {}
|
|
14298
14601
|
}
|
|
14299
14602
|
}
|
|
@@ -14310,9 +14613,9 @@ var init_worktree_post_create = __esm(() => {
|
|
|
14310
14613
|
|
|
14311
14614
|
// dist/builtin/workflows/src/runs/shared/worktree-setup.ts
|
|
14312
14615
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
14313
|
-
import * as
|
|
14616
|
+
import * as fs7 from "node:fs";
|
|
14314
14617
|
import * as os from "node:os";
|
|
14315
|
-
import * as
|
|
14618
|
+
import * as path7 from "node:path";
|
|
14316
14619
|
import { createChildProcessEnvironment as createChildProcessEnvironment2 } from "@bastani/atomic";
|
|
14317
14620
|
function originDefaultBranch(mainRoot) {
|
|
14318
14621
|
const symbolic = runGit(mainRoot, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]);
|
|
@@ -14332,7 +14635,7 @@ function originDefaultBranch(mainRoot) {
|
|
|
14332
14635
|
}
|
|
14333
14636
|
function resolveRepoState(cwd, explicitBaseBranch) {
|
|
14334
14637
|
const cwdRelative = resolveRepoCwdRelative(cwd);
|
|
14335
|
-
const toplevel =
|
|
14638
|
+
const toplevel = path7.resolve(runGitChecked(cwd, ["rev-parse", "--show-toplevel"]).trim());
|
|
14336
14639
|
const mainRoot = findCanonicalGitRoot(toplevel);
|
|
14337
14640
|
if (mainRoot === undefined)
|
|
14338
14641
|
throw new Error(`unable to resolve canonical main Git repository root from ${toplevel}`);
|
|
@@ -14345,9 +14648,9 @@ function resolveRepoState(cwd, explicitBaseBranch) {
|
|
|
14345
14648
|
return { toplevel, mainRoot, cwdRelative, baseCommit, baseRef };
|
|
14346
14649
|
}
|
|
14347
14650
|
function normalizeComparableCwd(cwd) {
|
|
14348
|
-
const resolved =
|
|
14651
|
+
const resolved = path7.resolve(cwd);
|
|
14349
14652
|
try {
|
|
14350
|
-
return
|
|
14653
|
+
return fs7.realpathSync(resolved);
|
|
14351
14654
|
} catch {
|
|
14352
14655
|
return resolved;
|
|
14353
14656
|
}
|
|
@@ -14358,7 +14661,7 @@ function findWorktreeTaskCwdConflict(tasks, sharedCwd) {
|
|
|
14358
14661
|
const task = tasks[index];
|
|
14359
14662
|
if (!task.cwd)
|
|
14360
14663
|
continue;
|
|
14361
|
-
const taskCwd =
|
|
14664
|
+
const taskCwd = path7.isAbsolute(task.cwd) ? task.cwd : path7.resolve(sharedCwd, task.cwd);
|
|
14362
14665
|
if (normalizeComparableCwd(taskCwd) === normalizedSharedCwd)
|
|
14363
14666
|
continue;
|
|
14364
14667
|
return { index, agent: task.agent, cwd: task.cwd };
|
|
@@ -14375,12 +14678,12 @@ function buildWorktreeBranch(runId, index) {
|
|
|
14375
14678
|
return `worktree-${flattenedWorktreeName(runId, index)}`;
|
|
14376
14679
|
}
|
|
14377
14680
|
function buildWorktreePath(mainRoot, runId, index) {
|
|
14378
|
-
return
|
|
14681
|
+
return path7.join(mainRoot, ".atomic", "worktrees", flattenedWorktreeName(runId, index));
|
|
14379
14682
|
}
|
|
14380
14683
|
function ensureWorktreeIgnore(mainRoot) {
|
|
14381
|
-
const worktreesRoot =
|
|
14382
|
-
|
|
14383
|
-
|
|
14684
|
+
const worktreesRoot = path7.join(mainRoot, ".atomic", "worktrees");
|
|
14685
|
+
fs7.mkdirSync(worktreesRoot, { recursive: true });
|
|
14686
|
+
fs7.writeFileSync(path7.join(worktreesRoot, ".gitignore"), `*
|
|
14384
14687
|
`, "utf8");
|
|
14385
14688
|
}
|
|
14386
14689
|
function resolveRepoCwdRelative(cwd) {
|
|
@@ -14389,7 +14692,7 @@ function resolveRepoCwdRelative(cwd) {
|
|
|
14389
14692
|
throw new Error("worktree isolation requires a git repository");
|
|
14390
14693
|
}
|
|
14391
14694
|
const rawPrefix = runGitChecked(cwd, ["rev-parse", "--show-prefix"]).trim();
|
|
14392
|
-
const normalizedPrefix = rawPrefix ?
|
|
14695
|
+
const normalizedPrefix = rawPrefix ? path7.normalize(rawPrefix.replace(/[\\/]+$/, "")) : "";
|
|
14393
14696
|
return normalizedPrefix === "." ? "" : normalizedPrefix;
|
|
14394
14697
|
}
|
|
14395
14698
|
function parseHookTimeout(timeoutMs) {
|
|
@@ -14407,19 +14710,19 @@ function resolveWorktreeSetupHook(repoRoot, config) {
|
|
|
14407
14710
|
if (!hookPath) {
|
|
14408
14711
|
throw new Error("worktree setup hook path cannot be empty");
|
|
14409
14712
|
}
|
|
14410
|
-
const expandedHookPath = hookPath.startsWith("~/") ?
|
|
14713
|
+
const expandedHookPath = hookPath.startsWith("~/") ? path7.join(os.homedir(), hookPath.slice(2)) : hookPath;
|
|
14411
14714
|
let resolvedPath;
|
|
14412
|
-
if (
|
|
14715
|
+
if (path7.isAbsolute(expandedHookPath)) {
|
|
14413
14716
|
resolvedPath = expandedHookPath;
|
|
14414
14717
|
} else if (expandedHookPath.includes("/") || expandedHookPath.includes("\\")) {
|
|
14415
|
-
resolvedPath =
|
|
14718
|
+
resolvedPath = path7.resolve(repoRoot, expandedHookPath);
|
|
14416
14719
|
} else {
|
|
14417
14720
|
throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
|
|
14418
14721
|
}
|
|
14419
|
-
if (!
|
|
14722
|
+
if (!fs7.existsSync(resolvedPath)) {
|
|
14420
14723
|
throw new Error(`worktree setup hook not found: ${resolvedPath}`);
|
|
14421
14724
|
}
|
|
14422
|
-
if (
|
|
14725
|
+
if (fs7.statSync(resolvedPath).isDirectory()) {
|
|
14423
14726
|
throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
|
|
14424
14727
|
}
|
|
14425
14728
|
return {
|
|
@@ -14431,17 +14734,17 @@ function normalizeSyntheticPath(worktreePath, rawPath) {
|
|
|
14431
14734
|
const trimmed = rawPath.trim();
|
|
14432
14735
|
if (!trimmed)
|
|
14433
14736
|
throw new Error("synthetic path cannot be empty");
|
|
14434
|
-
if (
|
|
14737
|
+
if (path7.isAbsolute(trimmed))
|
|
14435
14738
|
throw new Error(`synthetic path must be relative: ${rawPath}`);
|
|
14436
|
-
const resolved =
|
|
14437
|
-
const relative =
|
|
14739
|
+
const resolved = path7.resolve(worktreePath, trimmed);
|
|
14740
|
+
const relative = path7.relative(worktreePath, resolved);
|
|
14438
14741
|
if (!relative || relative === ".") {
|
|
14439
14742
|
throw new Error(`synthetic path cannot target the worktree root: ${rawPath}`);
|
|
14440
14743
|
}
|
|
14441
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
14744
|
+
if (relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative)) {
|
|
14442
14745
|
throw new Error(`synthetic path escapes the worktree root: ${rawPath}`);
|
|
14443
14746
|
}
|
|
14444
|
-
return
|
|
14747
|
+
return path7.normalize(relative);
|
|
14445
14748
|
}
|
|
14446
14749
|
function hasTrackedEntries(worktreePath, relativePath) {
|
|
14447
14750
|
const result = runGit(worktreePath, ["ls-files", "--", relativePath]);
|
|
@@ -14513,16 +14816,16 @@ function waitForGitLockRelease() {
|
|
|
14513
14816
|
}
|
|
14514
14817
|
function unlinkWorktreeLinks(worktreePath, relativePaths) {
|
|
14515
14818
|
for (const relativePath of new Set(relativePaths)) {
|
|
14516
|
-
const target =
|
|
14517
|
-
const relative =
|
|
14518
|
-
if (!relative || relative === ".." || relative.startsWith(`..${
|
|
14819
|
+
const target = path7.resolve(worktreePath, relativePath);
|
|
14820
|
+
const relative = path7.relative(worktreePath, target);
|
|
14821
|
+
if (!relative || relative === ".." || relative.startsWith(`..${path7.sep}`) || path7.isAbsolute(relative))
|
|
14519
14822
|
continue;
|
|
14520
14823
|
let current = worktreePath;
|
|
14521
|
-
for (const component of relative.split(
|
|
14522
|
-
current =
|
|
14824
|
+
for (const component of relative.split(path7.sep)) {
|
|
14825
|
+
current = path7.join(current, component);
|
|
14523
14826
|
let stat;
|
|
14524
14827
|
try {
|
|
14525
|
-
stat =
|
|
14828
|
+
stat = fs7.lstatSync(current);
|
|
14526
14829
|
} catch (error) {
|
|
14527
14830
|
const code = error.code;
|
|
14528
14831
|
if (code === "ENOENT" || code === "ENOTDIR")
|
|
@@ -14532,7 +14835,7 @@ function unlinkWorktreeLinks(worktreePath, relativePaths) {
|
|
|
14532
14835
|
if (!stat.isSymbolicLink())
|
|
14533
14836
|
continue;
|
|
14534
14837
|
if (current === target)
|
|
14535
|
-
|
|
14838
|
+
fs7.unlinkSync(current);
|
|
14536
14839
|
break;
|
|
14537
14840
|
}
|
|
14538
14841
|
}
|
|
@@ -14560,7 +14863,7 @@ function createSingleWorktree(mainRoot, cwdRelative, runId, index, baseRef, base
|
|
|
14560
14863
|
cleanupSingleWorktree(mainRoot, { path: worktreePath, branch }, []);
|
|
14561
14864
|
throw new Error(message);
|
|
14562
14865
|
}
|
|
14563
|
-
const agentCwd = cwdRelative ?
|
|
14866
|
+
const agentCwd = cwdRelative ? path7.join(worktreePath, cwdRelative) : worktreePath;
|
|
14564
14867
|
const syntheticPaths = [];
|
|
14565
14868
|
try {
|
|
14566
14869
|
syntheticPaths.push(...performPostCreationSetup(mainRoot, worktreePath, symlinkDirectories));
|
|
@@ -14629,8 +14932,8 @@ var init_worktree = __esm(() => {
|
|
|
14629
14932
|
});
|
|
14630
14933
|
|
|
14631
14934
|
// dist/builtin/workflows/src/runs/shared/worktree-cwd.ts
|
|
14632
|
-
import { lstatSync as
|
|
14633
|
-
import { dirname as
|
|
14935
|
+
import { lstatSync as lstatSync6, realpathSync as realpathSync4 } from "node:fs";
|
|
14936
|
+
import { dirname as dirname9, isAbsolute as isAbsolute6, relative as relative4, resolve as resolve7, sep as sep5 } from "node:path";
|
|
14634
14937
|
function relativePathWithin(root, candidate) {
|
|
14635
14938
|
const path = relative4(root, candidate);
|
|
14636
14939
|
return path === ".." || path.startsWith(`..${sep5}`) || isAbsolute6(path) ? undefined : path;
|
|
@@ -14649,14 +14952,14 @@ function resolveWorktreeStageCwd(cwd, setup) {
|
|
|
14649
14952
|
if (cwd === undefined || cwd.length === 0)
|
|
14650
14953
|
return;
|
|
14651
14954
|
const absoluteInput = isAbsolute6(cwd);
|
|
14652
|
-
const candidate = absoluteInput ? cwd :
|
|
14955
|
+
const candidate = absoluteInput ? cwd : resolve7(setup.cwd, cwd);
|
|
14653
14956
|
if (!absoluteInput && relativePathWithin(setup.worktreeRoot, candidate) === undefined) {
|
|
14654
14957
|
throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a cwd inside the worktree.`);
|
|
14655
14958
|
}
|
|
14656
14959
|
const candidateRealPath = existingRealPath(candidate, "cwd");
|
|
14657
14960
|
const worktreeRelative = relativePathWithin(worktreeRoot, candidateRealPath);
|
|
14658
14961
|
if (worktreeRelative !== undefined)
|
|
14659
|
-
return
|
|
14962
|
+
return resolve7(setup.worktreeRoot, worktreeRelative);
|
|
14660
14963
|
if (!isAbsolute6(cwd)) {
|
|
14661
14964
|
throw new Error(`atomic-workflows: relative cwd ${cwd} escapes gitWorktreeDir ${setup.worktreeRoot}; choose a path that remains inside the selected worktree.`);
|
|
14662
14965
|
}
|
|
@@ -14665,9 +14968,9 @@ function resolveWorktreeStageCwd(cwd, setup) {
|
|
|
14665
14968
|
}
|
|
14666
14969
|
const repositoryRelative = absoluteInput ? relativePathWithin(repositoryRoot, candidateRealPath) : undefined;
|
|
14667
14970
|
if (repositoryRelative === undefined) {
|
|
14668
|
-
throw new Error(`atomic-workflows: cwd ${cwd} is outside gitWorktreeDir ${setup.worktreeRoot}; use a cwd inside the invoking repository so Atomic can remap it, or omit cwd.`);
|
|
14971
|
+
throw new Error(repositoryRoot === worktreeRoot ? `atomic-workflows: cwd ${cwd} is outside gitWorktreeDir ${setup.worktreeRoot}, which belongs to a different repository than the invoking cwd; choose a cwd inside the worktree, or omit cwd.` : `atomic-workflows: cwd ${cwd} is outside gitWorktreeDir ${setup.worktreeRoot}; use a cwd inside the invoking repository so Atomic can remap it, or omit cwd.`);
|
|
14669
14972
|
}
|
|
14670
|
-
const mappedCwd =
|
|
14973
|
+
const mappedCwd = resolve7(setup.worktreeRoot, repositoryRelative);
|
|
14671
14974
|
const mappedRealPath = existingRealPath(mappedCwd, "remapped worktree cwd");
|
|
14672
14975
|
if (relativePathWithin(worktreeRoot, mappedRealPath) === undefined) {
|
|
14673
14976
|
throw new Error(`atomic-workflows: cwd ${cwd} remaps through a path that resolves outside gitWorktreeDir ${setup.worktreeRoot}; remove the escaping symlink or omit cwd.`);
|
|
@@ -14678,7 +14981,7 @@ var init_worktree_cwd = () => {};
|
|
|
14678
14981
|
|
|
14679
14982
|
// dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts
|
|
14680
14983
|
import { existsSync as existsSync3 } from "node:fs";
|
|
14681
|
-
import { isAbsolute as isAbsolute7, resolve as
|
|
14984
|
+
import { isAbsolute as isAbsolute7, resolve as resolve8 } from "node:path";
|
|
14682
14985
|
function normalizeTaskContexts(previous) {
|
|
14683
14986
|
if (previous === undefined)
|
|
14684
14987
|
return [];
|
|
@@ -14731,7 +15034,7 @@ function taskPrevious(options) {
|
|
|
14731
15034
|
function resolveWorkflowPath(filePath, baseDir) {
|
|
14732
15035
|
if (isAbsolute7(filePath))
|
|
14733
15036
|
return filePath;
|
|
14734
|
-
return
|
|
15037
|
+
return resolve8(baseDir ?? process.cwd(), filePath);
|
|
14735
15038
|
}
|
|
14736
15039
|
function taskBaseDir(options) {
|
|
14737
15040
|
if (typeof options.chainDir === "string" && options.chainDir.trim().length > 0) {
|
|
@@ -14886,7 +15189,7 @@ function taskWithSharedDefaults(taskOptions, options) {
|
|
|
14886
15189
|
var init_executor_task_prompts = () => {};
|
|
14887
15190
|
|
|
14888
15191
|
// dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts
|
|
14889
|
-
import { isAbsolute as isAbsolute8, join as
|
|
15192
|
+
import { isAbsolute as isAbsolute8, join as join12, resolve as resolve9 } from "node:path";
|
|
14890
15193
|
import { CONFIG_DIR_NAME } from "@bastani/atomic";
|
|
14891
15194
|
function positiveConcurrency(value2) {
|
|
14892
15195
|
if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 < 1)
|
|
@@ -15039,10 +15342,10 @@ function workflowInvocationMetadata(inputDefaults, workflowInvocationCwd, cache,
|
|
|
15039
15342
|
function resolvedTaskCwd(cwd, workflowInvocationCwd) {
|
|
15040
15343
|
if (cwd === undefined)
|
|
15041
15344
|
return;
|
|
15042
|
-
return isAbsolute8(cwd) ? cwd :
|
|
15345
|
+
return isAbsolute8(cwd) ? cwd : resolve9(workflowInvocationCwd, cwd);
|
|
15043
15346
|
}
|
|
15044
15347
|
function taskWorktreeOutputsRoot(runId) {
|
|
15045
|
-
return
|
|
15348
|
+
return join12(workflowArtifactRunPath(runId), "task-outputs");
|
|
15046
15349
|
}
|
|
15047
15350
|
function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCwd = process.cwd(), symlinkDirectories) {
|
|
15048
15351
|
if (options.worktree !== true && !tasks.some((task) => task.worktree === true)) {
|
|
@@ -15052,7 +15355,7 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
|
|
|
15052
15355
|
throw new Error("atomic-workflows: worktree and gitWorktreeDir are mutually exclusive; use gitWorktreeDir for a reusable worktree or worktree:true for temporary isolated worktrees.");
|
|
15053
15356
|
}
|
|
15054
15357
|
const explicitCwd = tasks.find((task) => typeof task.cwd === "string")?.cwd;
|
|
15055
|
-
const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd :
|
|
15358
|
+
const sharedCwd = explicitCwd === undefined ? workflowInvocationCwd : isAbsolute8(explicitCwd) ? explicitCwd : resolve9(workflowInvocationCwd, explicitCwd);
|
|
15056
15359
|
const conflict = findWorktreeTaskCwdConflict(tasks.map((task) => ({ agent: task.name, cwd: resolvedTaskCwd(task.cwd, workflowInvocationCwd) })), sharedCwd);
|
|
15057
15360
|
if (conflict !== undefined)
|
|
15058
15361
|
throw new Error(formatWorktreeTaskCwdConflict(conflict, sharedCwd));
|
|
@@ -15067,9 +15370,9 @@ function prepareTaskWorktrees(tasks, options, runId, scope, workflowInvocationCw
|
|
|
15067
15370
|
tasks: tasks.map((task, index) => ({ ...task, cwd: setup.worktrees[index].agentCwd })),
|
|
15068
15371
|
setup,
|
|
15069
15372
|
agents,
|
|
15070
|
-
diffsDir:
|
|
15373
|
+
diffsDir: join12(setup.cwd, CONFIG_DIR_NAME, "workflows", "worktree-diffs", runId, scope),
|
|
15071
15374
|
outputIsolations: tasks.map((_, index) => ({
|
|
15072
|
-
baseDir:
|
|
15375
|
+
baseDir: join12(trustedRoot, runId, scope, String(index)),
|
|
15073
15376
|
trustedRoot
|
|
15074
15377
|
}))
|
|
15075
15378
|
};
|
|
@@ -16796,8 +17099,12 @@ function createStageControlRegistry() {
|
|
|
16796
17099
|
}
|
|
16797
17100
|
await disposeEntries(entries);
|
|
16798
17101
|
},
|
|
16799
|
-
async releaseIdle(runId) {
|
|
16800
|
-
|
|
17102
|
+
async releaseIdle(runId, only) {
|
|
17103
|
+
const runMap = _byRun.get(runId);
|
|
17104
|
+
const entries = only === undefined ? [...runMap ?? []] : [[only, runMap?.get(only)]];
|
|
17105
|
+
for (const [stageId, entry] of entries) {
|
|
17106
|
+
if (entry === undefined)
|
|
17107
|
+
continue;
|
|
16801
17108
|
try {
|
|
16802
17109
|
await releaseIdleEntry(runId, stageId, entry);
|
|
16803
17110
|
} catch (error) {
|
|
@@ -16858,8 +17165,8 @@ var init_possible_stages = __esm(() => {
|
|
|
16858
17165
|
|
|
16859
17166
|
// dist/builtin/workflows/src/workers/pool-journal.ts
|
|
16860
17167
|
import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
|
|
16861
|
-
import { existsSync as existsSync4, mkdirSync as
|
|
16862
|
-
import { basename as basename5, dirname as
|
|
17168
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
17169
|
+
import { basename as basename5, dirname as dirname10, join as join13, resolve as resolve10 } from "node:path";
|
|
16863
17170
|
import { storageSelectionKey as storageSelectionKey2 } from "@bastani/atomic/storage";
|
|
16864
17171
|
function encodeOption(value2) {
|
|
16865
17172
|
if (typeof value2 === "bigint")
|
|
@@ -16881,7 +17188,7 @@ function isReopenableSelection(selection) {
|
|
|
16881
17188
|
}
|
|
16882
17189
|
function encodeSelection(selection) {
|
|
16883
17190
|
if (selection.kind === "sqlite")
|
|
16884
|
-
return JSON.stringify({ ...selection, path:
|
|
17191
|
+
return JSON.stringify({ ...selection, path: resolve10(selection.path) });
|
|
16885
17192
|
return JSON.stringify({
|
|
16886
17193
|
...selection,
|
|
16887
17194
|
...selection.options === undefined ? {} : {
|
|
@@ -16913,7 +17220,7 @@ function openDurableJournal(durable) {
|
|
|
16913
17220
|
return openSelectedRunJournal(decodeSelection(durable.selection), durable.agentDir);
|
|
16914
17221
|
}
|
|
16915
17222
|
function poolStateDirectory(agentDir) {
|
|
16916
|
-
return
|
|
17223
|
+
return join13(dirname10(agentDir), "workflows", "pool");
|
|
16917
17224
|
}
|
|
16918
17225
|
function databaseIdentity(selection, agentDir) {
|
|
16919
17226
|
return storageSelectionKey2(selection.kind === "adapter" ? { ...selection, secrets: undefined } : selection, agentDir);
|
|
@@ -16921,16 +17228,16 @@ function databaseIdentity(selection, agentDir) {
|
|
|
16921
17228
|
function coordinationPath(durable) {
|
|
16922
17229
|
const selection = decodeSelection(durable.selection);
|
|
16923
17230
|
const identity = createHash3("sha256").update(databaseIdentity(selection, durable.agentDir)).digest("hex");
|
|
16924
|
-
return
|
|
17231
|
+
return join13(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
|
|
16925
17232
|
}
|
|
16926
17233
|
function coordinationDatabase(durable) {
|
|
16927
17234
|
return basename5(coordinationPath(durable), ".sqlite");
|
|
16928
17235
|
}
|
|
16929
17236
|
function openCoordinationJournal(path) {
|
|
16930
|
-
const file =
|
|
17237
|
+
const file = resolve10(path);
|
|
16931
17238
|
let opened = coordinationJournals.get(file);
|
|
16932
17239
|
if (opened === undefined) {
|
|
16933
|
-
|
|
17240
|
+
mkdirSync6(dirname10(file), { recursive: true });
|
|
16934
17241
|
opened = resolveRunJournal({ journal: { path: file } });
|
|
16935
17242
|
coordinationJournals.set(file, opened);
|
|
16936
17243
|
opened.catch(() => {
|
|
@@ -16947,20 +17254,20 @@ function poolJournalFor(journal) {
|
|
|
16947
17254
|
return coordinations.get(journal) ?? journal;
|
|
16948
17255
|
}
|
|
16949
17256
|
function poolHostId(agentDir) {
|
|
16950
|
-
const file =
|
|
17257
|
+
const file = join13(poolStateDirectory(agentDir), "host-id");
|
|
16951
17258
|
try {
|
|
16952
|
-
const existing =
|
|
17259
|
+
const existing = readFileSync4(file, "utf8").trim();
|
|
16953
17260
|
if (existing !== "")
|
|
16954
17261
|
return existing;
|
|
16955
17262
|
} catch {}
|
|
16956
|
-
|
|
17263
|
+
mkdirSync6(dirname10(file), { recursive: true });
|
|
16957
17264
|
const id = randomUUID6();
|
|
16958
17265
|
try {
|
|
16959
|
-
|
|
17266
|
+
writeFileSync4(file, `${id}
|
|
16960
17267
|
`, { flag: "wx" });
|
|
16961
17268
|
return id;
|
|
16962
17269
|
} catch {
|
|
16963
|
-
return
|
|
17270
|
+
return readFileSync4(file, "utf8").trim();
|
|
16964
17271
|
}
|
|
16965
17272
|
}
|
|
16966
17273
|
var POOL_DURABLE_JOURNAL_ENV = "ATOMIC_POOL_DURABLE_JOURNAL", coordinationJournals, coordinations;
|
|
@@ -16975,7 +17282,7 @@ var init_pool_journal = __esm(() => {
|
|
|
16975
17282
|
|
|
16976
17283
|
// dist/builtin/workflows/src/workers/admission-host.ts
|
|
16977
17284
|
import { execFile, execFileSync } from "node:child_process";
|
|
16978
|
-
import { readdirSync as
|
|
17285
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
16979
17286
|
import { readFile } from "node:fs/promises";
|
|
16980
17287
|
import { hostname } from "node:os";
|
|
16981
17288
|
function admissionBootIdentity() {
|
|
@@ -17001,13 +17308,32 @@ function admissionProcessStopped(pid) {
|
|
|
17001
17308
|
return error.code === "ESRCH";
|
|
17002
17309
|
}
|
|
17003
17310
|
}
|
|
17311
|
+
function workerProcessExited(pid, final = false) {
|
|
17312
|
+
if (admissionProcessStopped(pid))
|
|
17313
|
+
return true;
|
|
17314
|
+
if (process.platform === "linux") {
|
|
17315
|
+
try {
|
|
17316
|
+
const stat = readFileSync5(`/proc/${pid}/stat`, "utf8");
|
|
17317
|
+
return stat.slice(stat.lastIndexOf(")") + 2).startsWith("Z");
|
|
17318
|
+
} catch {
|
|
17319
|
+
return admissionProcessStopped(pid);
|
|
17320
|
+
}
|
|
17321
|
+
}
|
|
17322
|
+
if (!final)
|
|
17323
|
+
return false;
|
|
17324
|
+
try {
|
|
17325
|
+
return execFileSync("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8", timeout: 5000 }).trim().startsWith("Z");
|
|
17326
|
+
} catch {
|
|
17327
|
+
return admissionProcessStopped(pid);
|
|
17328
|
+
}
|
|
17329
|
+
}
|
|
17004
17330
|
function scanProcessGroup(group) {
|
|
17005
17331
|
const members = new Map;
|
|
17006
17332
|
if (process.platform === "linux") {
|
|
17007
17333
|
let complete = true;
|
|
17008
17334
|
let entries;
|
|
17009
17335
|
try {
|
|
17010
|
-
entries =
|
|
17336
|
+
entries = readdirSync4("/proc");
|
|
17011
17337
|
} catch {
|
|
17012
17338
|
return { members, complete: false };
|
|
17013
17339
|
}
|
|
@@ -17016,7 +17342,7 @@ function scanProcessGroup(group) {
|
|
|
17016
17342
|
continue;
|
|
17017
17343
|
let stat;
|
|
17018
17344
|
try {
|
|
17019
|
-
stat =
|
|
17345
|
+
stat = readFileSync5(`/proc/${entry}/stat`, "utf8");
|
|
17020
17346
|
} catch {
|
|
17021
17347
|
complete = false;
|
|
17022
17348
|
continue;
|
|
@@ -53755,10 +54081,10 @@ var init_verification_prompts = __esm(() => {
|
|
|
53755
54081
|
// dist/builtin/workflows/builtin/pattern-artifact-root.ts
|
|
53756
54082
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
53757
54083
|
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
53758
|
-
import { join as
|
|
54084
|
+
import { join as join14 } from "node:path";
|
|
53759
54085
|
async function stableArtifactRoot(ctx, workflowName) {
|
|
53760
54086
|
const cwd = ctx.cwd ?? process.cwd();
|
|
53761
|
-
const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () =>
|
|
54087
|
+
const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join14(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
|
|
53762
54088
|
await mkdir2(artifactDir, { recursive: true });
|
|
53763
54089
|
return artifactDir;
|
|
53764
54090
|
}
|
|
@@ -53798,7 +54124,7 @@ function fold_usage(results) {
|
|
|
53798
54124
|
|
|
53799
54125
|
// dist/builtin/workflows/builtin/adversarial-verification-runner.ts
|
|
53800
54126
|
import { readFile as readFile2, writeFile } from "node:fs/promises";
|
|
53801
|
-
import { join as
|
|
54127
|
+
import { join as join15 } from "node:path";
|
|
53802
54128
|
import { Type as Type4 } from "typebox";
|
|
53803
54129
|
function isRecord3(value2) {
|
|
53804
54130
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
@@ -53893,8 +54219,8 @@ async function writeInvalid(path, stage) {
|
|
|
53893
54219
|
}
|
|
53894
54220
|
async function runAdversarialVerification(ctx) {
|
|
53895
54221
|
const root = await stableArtifactRoot(ctx, "adversarial-verification");
|
|
53896
|
-
const criteriaPath =
|
|
53897
|
-
const candidatePath =
|
|
54222
|
+
const criteriaPath = join15(root, "criteria.md");
|
|
54223
|
+
const candidatePath = join15(root, "candidate.md");
|
|
53898
54224
|
const resolvedCriteria = resolveCriteria(ctx.inputs.criteria);
|
|
53899
54225
|
await writeFile(criteriaPath, renderCriteriaMarkdown(resolvedCriteria));
|
|
53900
54226
|
await ctx.task("worker", { prompt: renderWorkerPrompt(ctx.inputs.task), context: "fresh", output: candidatePath, outputMode: "file-only" });
|
|
@@ -53926,7 +54252,7 @@ async function runAdversarialVerification(ctx) {
|
|
|
53926
54252
|
criterion,
|
|
53927
54253
|
verifierIndex: index + 1,
|
|
53928
54254
|
name,
|
|
53929
|
-
artifactPath:
|
|
54255
|
+
artifactPath: join15(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
|
|
53930
54256
|
});
|
|
53931
54257
|
}
|
|
53932
54258
|
}
|
|
@@ -53979,8 +54305,8 @@ async function runAdversarialVerification(ctx) {
|
|
|
53979
54305
|
const decision = decide_verification(roundResult, { acceptMean, quorumFraction: QUORUM_FRACTION });
|
|
53980
54306
|
finalDecision = decision;
|
|
53981
54307
|
finalMean = meanScore(scoreReports);
|
|
53982
|
-
scoreTablePath =
|
|
53983
|
-
reviewReportPath =
|
|
54308
|
+
scoreTablePath = join15(root, `verification-summary-${round}.json`);
|
|
54309
|
+
reviewReportPath = join15(root, `review-${round}.json`);
|
|
53984
54310
|
const summary = {
|
|
53985
54311
|
scores: scoreReports,
|
|
53986
54312
|
mean: finalMean,
|
|
@@ -54161,7 +54487,7 @@ var GROUNDED_REPORTING2 = "Before reporting progress, audit each claim against a
|
|
|
54161
54487
|
|
|
54162
54488
|
// dist/builtin/workflows/builtin/classify-and-act-runner.ts
|
|
54163
54489
|
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
54164
|
-
import { join as
|
|
54490
|
+
import { join as join16 } from "node:path";
|
|
54165
54491
|
import { Type as Type6 } from "typebox";
|
|
54166
54492
|
function safeName(value2) {
|
|
54167
54493
|
const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
@@ -54201,7 +54527,7 @@ async function runClassifyAndAct(ctx) {
|
|
|
54201
54527
|
const needsFallback = exactCategory === undefined || confidence < ctx.inputs.confidence_threshold;
|
|
54202
54528
|
const fallback = needsFallback ? await resolveFallbackCategory(ctx, exactCategory) : undefined;
|
|
54203
54529
|
const category = fallback?.category ?? exactCategory;
|
|
54204
|
-
const classificationPath =
|
|
54530
|
+
const classificationPath = join16(artifactDir, "classification.json");
|
|
54205
54531
|
await writeFile2(classificationPath, JSON.stringify({
|
|
54206
54532
|
proposed_category: proposedCategory,
|
|
54207
54533
|
selected_category: category,
|
|
@@ -54211,7 +54537,7 @@ async function runClassifyAndAct(ctx) {
|
|
|
54211
54537
|
fallback_used: needsFallback,
|
|
54212
54538
|
fallback_mode: fallback?.fallbackMode ?? "none"
|
|
54213
54539
|
}, null, 2));
|
|
54214
|
-
const actionPath =
|
|
54540
|
+
const actionPath = join16(artifactDir, `action-${safeName(category)}.md`);
|
|
54215
54541
|
const action = await ctx.task(`action-${safeName(category)}`, {
|
|
54216
54542
|
tools: actionTools(category),
|
|
54217
54543
|
prompt: actionPrompt({ prompt: ctx.inputs.prompt, category, classificationPath }),
|
|
@@ -54351,7 +54677,7 @@ var GROUNDED_REPORTING3 = "Before reporting progress, audit each claim against a
|
|
|
54351
54677
|
|
|
54352
54678
|
// dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts
|
|
54353
54679
|
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
54354
|
-
import { join as
|
|
54680
|
+
import { join as join17 } from "node:path";
|
|
54355
54681
|
import { Type as Type8 } from "typebox";
|
|
54356
54682
|
function safeName2(value2, index) {
|
|
54357
54683
|
const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
@@ -54382,9 +54708,9 @@ async function runFanOutAndSynthesize(ctx) {
|
|
|
54382
54708
|
context: "fresh"
|
|
54383
54709
|
});
|
|
54384
54710
|
const partitions = parsedPartitions(plan.structured, ctx.inputs.max_branches, ctx.inputs.prompt);
|
|
54385
|
-
const partitionPath =
|
|
54711
|
+
const partitionPath = join17(artifactDir, "partition-plan.json");
|
|
54386
54712
|
await writeFile3(partitionPath, JSON.stringify({ task: ctx.inputs.prompt, partitions }, null, 2));
|
|
54387
|
-
const branchPaths = partitions.map((partition, index) =>
|
|
54713
|
+
const branchPaths = partitions.map((partition, index) => join17(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
|
|
54388
54714
|
const steps = partitions.map((partition, index) => ({
|
|
54389
54715
|
name: `branch-${safeName2(partition.label, index)}`,
|
|
54390
54716
|
prompt: branchPrompt({ prompt: ctx.inputs.prompt, ...partition }),
|
|
@@ -54394,13 +54720,13 @@ async function runFanOutAndSynthesize(ctx) {
|
|
|
54394
54720
|
outputMode: "file-only"
|
|
54395
54721
|
}));
|
|
54396
54722
|
await ctx.parallel(steps, { concurrency: Math.min(ctx.inputs.max_concurrency, partitions.length), failFast: false });
|
|
54397
|
-
const manifestPath =
|
|
54723
|
+
const manifestPath = join17(artifactDir, "manifest.json");
|
|
54398
54724
|
await writeFile3(manifestPath, JSON.stringify({
|
|
54399
54725
|
task: ctx.inputs.prompt,
|
|
54400
54726
|
partition_plan: partitionPath,
|
|
54401
54727
|
branches: partitions.map((partition, index) => ({ ...partition, artifact_path: branchPaths[index] }))
|
|
54402
54728
|
}, null, 2));
|
|
54403
|
-
const synthesisPath =
|
|
54729
|
+
const synthesisPath = join17(artifactDir, "synthesis.md");
|
|
54404
54730
|
const synthesis = await ctx.task("synthesize", {
|
|
54405
54731
|
prompt: synthesisPrompt(ctx.inputs.prompt, manifestPath),
|
|
54406
54732
|
context: "fresh",
|
|
@@ -54565,7 +54891,7 @@ var init_generate_and_filter_prompts = __esm(() => {
|
|
|
54565
54891
|
|
|
54566
54892
|
// dist/builtin/workflows/builtin/generate-and-filter-runner.ts
|
|
54567
54893
|
import { readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
|
|
54568
|
-
import { join as
|
|
54894
|
+
import { join as join18 } from "node:path";
|
|
54569
54895
|
import { Type as Type10 } from "typebox";
|
|
54570
54896
|
function isRecord4(value2) {
|
|
54571
54897
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
@@ -54584,7 +54910,7 @@ function judgeDecision(value2) {
|
|
|
54584
54910
|
}
|
|
54585
54911
|
async function runGenerateAndFilter(ctx) {
|
|
54586
54912
|
const root = await stableArtifactRoot(ctx, "generate-and-filter");
|
|
54587
|
-
const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) =>
|
|
54913
|
+
const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join18(root, `candidate-${index + 1}.md`));
|
|
54588
54914
|
const shortlistLimit = Math.min(ctx.inputs.shortlist_size, ctx.inputs.num_candidates);
|
|
54589
54915
|
await ctx.parallel(candidatePaths.map((path, index) => ({
|
|
54590
54916
|
name: `generate-${index + 1}`,
|
|
@@ -54593,9 +54919,9 @@ async function runGenerateAndFilter(ctx) {
|
|
|
54593
54919
|
output: path,
|
|
54594
54920
|
outputMode: "file-only"
|
|
54595
54921
|
})), { concurrency: ctx.inputs.max_concurrency, failFast: false });
|
|
54596
|
-
const manifestPath =
|
|
54922
|
+
const manifestPath = join18(root, "manifest.json");
|
|
54597
54923
|
await writeFile4(manifestPath, JSON.stringify({ task: ctx.inputs.prompt, candidate_artifact_paths: candidatePaths }, null, 2));
|
|
54598
|
-
const filterPath =
|
|
54924
|
+
const filterPath = join18(root, "filter.json");
|
|
54599
54925
|
const filtered = await ctx.task("dedupe-and-filter", {
|
|
54600
54926
|
prompt: renderFilterPrompt(ctx.inputs.prompt, candidatePaths, shortlistLimit),
|
|
54601
54927
|
context: "fresh",
|
|
@@ -54612,7 +54938,7 @@ async function runGenerateAndFilter(ctx) {
|
|
|
54612
54938
|
let judgePath = null;
|
|
54613
54939
|
let decisionPath = filterPath;
|
|
54614
54940
|
if (ctx.inputs.use_judge) {
|
|
54615
|
-
judgePath =
|
|
54941
|
+
judgePath = join18(root, "judge.json");
|
|
54616
54942
|
const judgeCandidates = await Promise.all(shortlist.map(async (path) => ({ path, body: await readFile3(path, "utf8") })));
|
|
54617
54943
|
const judgePrompt = renderJudgePrompt(ctx.inputs.prompt, filterPath, shortlistLimit, judgeCandidates);
|
|
54618
54944
|
const judged = await ctx.task("judge", {
|
|
@@ -54628,7 +54954,7 @@ async function runGenerateAndFilter(ctx) {
|
|
|
54628
54954
|
shortlist = judgedShortlist.length > 0 ? judgedShortlist : shortlist;
|
|
54629
54955
|
decisionPath = judgePath;
|
|
54630
54956
|
}
|
|
54631
|
-
const finalPath =
|
|
54957
|
+
const finalPath = join18(root, "shortlist.md");
|
|
54632
54958
|
const finalShortlist = await ctx.task("final-shortlist", {
|
|
54633
54959
|
prompt: renderFinalShortlistPrompt(ctx.inputs.prompt, decisionPath),
|
|
54634
54960
|
context: "fresh",
|
|
@@ -55157,7 +55483,7 @@ var init_review_convergence = __esm(() => {
|
|
|
55157
55483
|
|
|
55158
55484
|
// dist/builtin/workflows/builtin/goal-artifacts.ts
|
|
55159
55485
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
55160
|
-
import { join as
|
|
55486
|
+
import { join as join19 } from "node:path";
|
|
55161
55487
|
function artifactSafeName(value2) {
|
|
55162
55488
|
const safe = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
55163
55489
|
return safe.length > 0 ? safe : "artifact";
|
|
@@ -55168,7 +55494,7 @@ function withoutTurn(value2) {
|
|
|
55168
55494
|
return copy;
|
|
55169
55495
|
}
|
|
55170
55496
|
async function writeReviewArtifact(artifactDir, reviewer, decision, rawText, convergenceDecision) {
|
|
55171
|
-
const artifactPath =
|
|
55497
|
+
const artifactPath = join19(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
|
|
55172
55498
|
await writeFile5(artifactPath, `${JSON.stringify({ reviewer, decision, convergence_decision: convergenceDecision, raw_text: rawText }, null, 2)}
|
|
55173
55499
|
`, { encoding: "utf8" });
|
|
55174
55500
|
return artifactPath;
|
|
@@ -55177,7 +55503,7 @@ async function writeReviewRoundArtifact(artifactDir, reviews, consolidatedFindin
|
|
|
55177
55503
|
reviewer: review.reviewer,
|
|
55178
55504
|
findings: review.findings
|
|
55179
55505
|
}))), reverification = []) {
|
|
55180
|
-
const artifactPath =
|
|
55506
|
+
const artifactPath = join19(artifactDir, "review-round-latest.json");
|
|
55181
55507
|
const visibleReviews = reviews.map(withoutTurn);
|
|
55182
55508
|
await writeFile5(artifactPath, `${JSON.stringify({ reviews: visibleReviews, consolidated_findings: consolidatedFindings, reverification }, null, 2)}
|
|
55183
55509
|
`, { encoding: "utf8" });
|
|
@@ -55407,7 +55733,7 @@ var init_goal_review = __esm(() => {
|
|
|
55407
55733
|
// dist/builtin/workflows/builtin/goal-ledger.ts
|
|
55408
55734
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
55409
55735
|
import { readFile as readFile4, rename, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
|
|
55410
|
-
import { dirname as
|
|
55736
|
+
import { dirname as dirname11, join as join20 } from "node:path";
|
|
55411
55737
|
import { isDeepStrictEqual } from "node:util";
|
|
55412
55738
|
function withoutTurn2(value2) {
|
|
55413
55739
|
const copy = { ...value2 };
|
|
@@ -55432,7 +55758,7 @@ function modelVisibleLedger(ledger) {
|
|
|
55432
55758
|
};
|
|
55433
55759
|
}
|
|
55434
55760
|
function goalLedgerStatePath(ledgerPath) {
|
|
55435
|
-
return
|
|
55761
|
+
return join20(dirname11(ledgerPath), LEDGER_STATE_FILENAME);
|
|
55436
55762
|
}
|
|
55437
55763
|
function appendLifecycleEvent(ledger, event, summary, turn = ledger.turns) {
|
|
55438
55764
|
ledger.lifecycle.push({
|
|
@@ -55508,7 +55834,7 @@ function recoverLegacyExecutionInterruption(ledger) {
|
|
|
55508
55834
|
return true;
|
|
55509
55835
|
}
|
|
55510
55836
|
async function createGoalLedger(objective, acceptanceCriteria, artifactDir) {
|
|
55511
|
-
const ledgerPath =
|
|
55837
|
+
const ledgerPath = join20(artifactDir, LEDGER_FILENAME);
|
|
55512
55838
|
const existing = await readExistingGoalLedger(ledgerPath);
|
|
55513
55839
|
if (existing !== undefined) {
|
|
55514
55840
|
if (recoverLegacyExecutionInterruption(existing))
|
|
@@ -56015,7 +56341,7 @@ var init_goal_orchestrator_prompts = __esm(() => {
|
|
|
56015
56341
|
});
|
|
56016
56342
|
|
|
56017
56343
|
// dist/builtin/workflows/builtin/goal-runner.ts
|
|
56018
|
-
import { join as
|
|
56344
|
+
import { join as join21 } from "node:path";
|
|
56019
56345
|
function positiveInteger(value2, fallback) {
|
|
56020
56346
|
if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 <= 0) {
|
|
56021
56347
|
return fallback;
|
|
@@ -56066,7 +56392,7 @@ async function runGoalWorkflow(ctx, options) {
|
|
|
56066
56392
|
appendLifecycleEvent(ledger, "work_turn_started", "Orchestrator started.", turn);
|
|
56067
56393
|
await writeGoalLedger(ledgerPath, ledger);
|
|
56068
56394
|
}
|
|
56069
|
-
const orchestratorReceiptPath =
|
|
56395
|
+
const orchestratorReceiptPath = join21(artifactDir, "orchestrator-receipt.md");
|
|
56070
56396
|
const orchestratorForkOptions = forkContinuationOptions(previousOrchestratorSessionId);
|
|
56071
56397
|
const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? renderGoalOrchestratorPrompt({
|
|
56072
56398
|
ledger,
|
|
@@ -56137,7 +56463,7 @@ async function runGoalWorkflow(ctx, options) {
|
|
|
56137
56463
|
const reviewerName = result.name ?? result.stageName;
|
|
56138
56464
|
const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
|
|
56139
56465
|
const parsed = reviewerContractError === undefined ? parsedReviewDecisionFromResult(result, reviewerName) : { decision: reviewerErrorDecision(reviewerContractError.message), parsed: false, diagnostics: [reviewerContractError.message] };
|
|
56140
|
-
const reviewArtifactPath =
|
|
56466
|
+
const reviewArtifactPath = join21(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
|
|
56141
56467
|
const record = reviewDecisionToRecord({
|
|
56142
56468
|
turn,
|
|
56143
56469
|
reviewer: normalizedReviewerName,
|
|
@@ -56340,7 +56666,7 @@ var init_goal = __esm(() => {
|
|
|
56340
56666
|
}),
|
|
56341
56667
|
git_worktree_dir: Type15.String({
|
|
56342
56668
|
default: "",
|
|
56343
|
-
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own.
|
|
56669
|
+
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Absolute paths are used as-is; relative paths resolve from the invoking repo root (or the invoking cwd outside a Git repo). An existing Git worktree root of any repository is reused as-is, even from another repository or a non-Git cwd. Creating a worktree requires starting inside the source Git repo: a missing path or an empty directory becomes a new worktree from base_branch, and a non-empty non-Git directory is treated as a worktree root that gets this run's own <dir>/<4-hex>/<repo-name> checkout, reused on resume."
|
|
56344
56670
|
}),
|
|
56345
56671
|
create_pr: Type15.Boolean({
|
|
56346
56672
|
default: false,
|
|
@@ -56458,7 +56784,7 @@ var GROUNDED_REPORTING5 = "Before reporting progress, audit each claim against a
|
|
|
56458
56784
|
|
|
56459
56785
|
// dist/builtin/workflows/builtin/loop-until-done-runner.ts
|
|
56460
56786
|
import { mkdir as mkdir3, writeFile as writeFile7 } from "node:fs/promises";
|
|
56461
|
-
import { join as
|
|
56787
|
+
import { join as join22 } from "node:path";
|
|
56462
56788
|
import { Type as Type16 } from "typebox";
|
|
56463
56789
|
function progressCurve(entries) {
|
|
56464
56790
|
return entries.flatMap((entry) => entry.progress === undefined ? [] : [entry.progress.score]);
|
|
@@ -56541,18 +56867,18 @@ async function writeLedger(path, task, maxIterations, status, entries) {
|
|
|
56541
56867
|
}
|
|
56542
56868
|
async function runLoopUntilDone(ctx) {
|
|
56543
56869
|
const artifactDir = await stableArtifactRoot(ctx, "loop-until-done");
|
|
56544
|
-
const iterationsDir =
|
|
56545
|
-
const evaluationsDir =
|
|
56870
|
+
const iterationsDir = join22(artifactDir, "iterations");
|
|
56871
|
+
const evaluationsDir = join22(artifactDir, "evaluations");
|
|
56546
56872
|
await mkdir3(iterationsDir, { recursive: true });
|
|
56547
56873
|
await mkdir3(evaluationsDir, { recursive: true });
|
|
56548
|
-
const ledgerPath =
|
|
56874
|
+
const ledgerPath = join22(artifactDir, "progress-ledger.json");
|
|
56549
56875
|
const entries = [];
|
|
56550
56876
|
const iterationArtifactPaths = [];
|
|
56551
56877
|
const evaluationArtifactPaths = [];
|
|
56552
56878
|
await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, "active", entries);
|
|
56553
56879
|
for (let iteration = 1;iteration <= ctx.inputs.max_iterations; iteration += 1) {
|
|
56554
|
-
const iterationPath =
|
|
56555
|
-
const evaluationPath =
|
|
56880
|
+
const iterationPath = join22(iterationsDir, `iteration-${iteration}.md`);
|
|
56881
|
+
const evaluationPath = join22(evaluationsDir, `evaluation-${iteration}.json`);
|
|
56556
56882
|
iterationArtifactPaths.push(iterationPath);
|
|
56557
56883
|
evaluationArtifactPaths.push(evaluationPath);
|
|
56558
56884
|
await ctx.task(`iteration-${iteration}`, {
|
|
@@ -56601,7 +56927,7 @@ async function runLoopUntilDone(ctx) {
|
|
|
56601
56927
|
await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, decision.done ? "complete" : "active", entries);
|
|
56602
56928
|
if (decision.done) {
|
|
56603
56929
|
const report = progressReport(entries);
|
|
56604
|
-
const resultPath =
|
|
56930
|
+
const resultPath = join22(artifactDir, "result.md");
|
|
56605
56931
|
const final = await ctx.task("completion-summary", {
|
|
56606
56932
|
prompt: renderCompletionPrompt({ task: ctx.inputs.prompt, ledgerPath, iterationPath }),
|
|
56607
56933
|
context: "fresh",
|
|
@@ -56718,9 +57044,9 @@ var init_loop_until_done = __esm(() => {
|
|
|
56718
57044
|
|
|
56719
57045
|
// dist/builtin/workflows/builtin/open-claude-design-utils.ts
|
|
56720
57046
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
56721
|
-
import { mkdirSync as
|
|
57047
|
+
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
56722
57048
|
import { tmpdir, userInfo } from "node:os";
|
|
56723
|
-
import { join as
|
|
57049
|
+
import { join as join23 } from "node:path";
|
|
56724
57050
|
import { Type as Type18 } from "typebox";
|
|
56725
57051
|
import { createChildProcessEnvironment as createChildProcessEnvironment3 } from "@bastani/atomic";
|
|
56726
57052
|
function taggedPrompt3(sections) {
|
|
@@ -56763,32 +57089,32 @@ function tmpArtifactBase() {
|
|
|
56763
57089
|
try {
|
|
56764
57090
|
user = userInfo().username.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
|
|
56765
57091
|
} catch {}
|
|
56766
|
-
return
|
|
57092
|
+
return join23(tmpdir(), `open-claude-design-${user}`);
|
|
56767
57093
|
}
|
|
56768
57094
|
function prepareArtifactDir(cwd = process.cwd()) {
|
|
56769
57095
|
const runId = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
|
|
56770
57096
|
const tmpCandidates = [
|
|
56771
|
-
|
|
56772
|
-
|
|
57097
|
+
join23(tmpArtifactBase(), runId),
|
|
57098
|
+
join23(tmpdir(), "open-claude-design", runId)
|
|
56773
57099
|
];
|
|
56774
|
-
const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [
|
|
57100
|
+
const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join23(cwd, "specs", "design", runId), ...tmpCandidates];
|
|
56775
57101
|
for (const candidate of candidates) {
|
|
56776
57102
|
try {
|
|
56777
|
-
|
|
57103
|
+
mkdirSync7(candidate, { recursive: true });
|
|
56778
57104
|
return {
|
|
56779
57105
|
runId,
|
|
56780
57106
|
artifactDir: candidate,
|
|
56781
|
-
previewPath:
|
|
56782
|
-
specPath:
|
|
57107
|
+
previewPath: join23(candidate, "preview.html"),
|
|
57108
|
+
specPath: join23(candidate, "spec.html")
|
|
56783
57109
|
};
|
|
56784
57110
|
} catch {}
|
|
56785
57111
|
}
|
|
56786
|
-
const fallback =
|
|
57112
|
+
const fallback = join23(tmpArtifactBase(), runId);
|
|
56787
57113
|
return {
|
|
56788
57114
|
runId,
|
|
56789
57115
|
artifactDir: fallback,
|
|
56790
|
-
previewPath:
|
|
56791
|
-
specPath:
|
|
57116
|
+
previewPath: join23(fallback, "preview.html"),
|
|
57117
|
+
specPath: join23(fallback, "spec.html")
|
|
56792
57118
|
};
|
|
56793
57119
|
}
|
|
56794
57120
|
function ensureAgentBrowser() {
|
|
@@ -57122,8 +57448,8 @@ var init_open_claude_design_live_protocol = __esm(() => {
|
|
|
57122
57448
|
});
|
|
57123
57449
|
|
|
57124
57450
|
// dist/builtin/workflows/builtin/open-claude-design-setup.ts
|
|
57125
|
-
import { mkdirSync as
|
|
57126
|
-
import { join as
|
|
57451
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync5 } from "node:fs";
|
|
57452
|
+
import { join as join24 } from "node:path";
|
|
57127
57453
|
function renderDiscoveryContext(discovery) {
|
|
57128
57454
|
return [
|
|
57129
57455
|
`Confirmed design brief: ${discovery.brief}`,
|
|
@@ -57188,10 +57514,10 @@ async function runDiscoveryAndInit(args) {
|
|
|
57188
57514
|
};
|
|
57189
57515
|
}
|
|
57190
57516
|
function designContextPath(artifactDir) {
|
|
57191
|
-
return
|
|
57517
|
+
return join24(artifactDir, DESIGN_CONTEXT_FILENAME);
|
|
57192
57518
|
}
|
|
57193
57519
|
function referencesBriefPath(artifactDir) {
|
|
57194
|
-
return
|
|
57520
|
+
return join24(artifactDir, REFERENCES_BRIEF_FILENAME);
|
|
57195
57521
|
}
|
|
57196
57522
|
function buildReferenceDiscoveryPrompt(args) {
|
|
57197
57523
|
const siteList = REFERENCE_DESIGN_SITES.map((site, index) => `${index + 1}. ${site.name} — ${site.url}`).join(`
|
|
@@ -57217,8 +57543,8 @@ function buildReferenceDiscoveryPrompt(args) {
|
|
|
57217
57543
|
[
|
|
57218
57544
|
"Use the agent-browser skill to open each gallery; if `agent-browser` reports a missing browser executable, follow the bootstrap rules and retry once.",
|
|
57219
57545
|
"From each gallery, choose 1-3 fitting designs and CLICK INTO each actual live or project-detail page; do not capture only the grid or thumbnail.",
|
|
57220
|
-
`Capture motion across the entire page: start \`agent-browser record start ${
|
|
57221
|
-
`Also run \`agent-browser screenshot ${
|
|
57546
|
+
`Capture motion across the entire page: start \`agent-browser record start ${join24(args.artifactDir, "ref-<site>-<n>.webm")}\`, scroll smoothly in small increments with waits (using repeated \`agent-browser scroll down 600\` or \`agent-browser mouse wheel 600\`) so animations fire and lazy content loads, then run \`agent-browser record stop\`.`,
|
|
57547
|
+
`Also run \`agent-browser screenshot ${join24(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
|
|
57222
57548
|
"Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
|
|
57223
57549
|
"Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
|
|
57224
57550
|
"Use ask_user_question to ask which reference direction they prefer, offering 2-4 strongest options plus `None of these fit`. If none fit, ask them to provide a reference image, screenshot, URL, or local file path and record the answer.",
|
|
@@ -57243,8 +57569,8 @@ function buildReferenceDiscoveryPrompt(args) {
|
|
|
57243
57569
|
}
|
|
57244
57570
|
function writeRequiredContextArtifact(artifactDir, filePath, content, label) {
|
|
57245
57571
|
try {
|
|
57246
|
-
|
|
57247
|
-
|
|
57572
|
+
mkdirSync8(artifactDir, { recursive: true });
|
|
57573
|
+
writeFileSync5(filePath, `${content}
|
|
57248
57574
|
`);
|
|
57249
57575
|
} catch (error) {
|
|
57250
57576
|
const detail = error instanceof Error ? error.message : String(error);
|
|
@@ -57795,7 +58121,7 @@ var init_ralph_review_gate = __esm(() => {
|
|
|
57795
58121
|
|
|
57796
58122
|
// dist/builtin/workflows/builtin/ralph-core.ts
|
|
57797
58123
|
import { mkdir as mkdir4, writeFile as writeFile8 } from "node:fs/promises";
|
|
57798
|
-
import { dirname as
|
|
58124
|
+
import { dirname as dirname12, join as join25 } from "node:path";
|
|
57799
58125
|
import { Type as Type20 } from "typebox";
|
|
57800
58126
|
function taggedPrompt4(sections) {
|
|
57801
58127
|
return sections.map(([tag, content]) => {
|
|
@@ -57835,11 +58161,11 @@ function slugifyResearchTopic(prompt) {
|
|
|
57835
58161
|
}
|
|
57836
58162
|
function defaultResearchPath(prompt, now = new Date) {
|
|
57837
58163
|
const date = now.toISOString().slice(0, 10);
|
|
57838
|
-
return
|
|
58164
|
+
return join25(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
|
|
57839
58165
|
}
|
|
57840
58166
|
async function createImplementationNotesFile(prompt, runId) {
|
|
57841
58167
|
const notesDir = await createWorkflowArtifactDirectory(runId);
|
|
57842
|
-
const notesPath =
|
|
58168
|
+
const notesPath = join25(notesDir, IMPLEMENTATION_NOTES_FILENAME);
|
|
57843
58169
|
const initialNotes = [
|
|
57844
58170
|
"# Implementation Notes",
|
|
57845
58171
|
"",
|
|
@@ -57860,7 +58186,7 @@ async function createImplementationNotesFile(prompt, runId) {
|
|
|
57860
58186
|
}
|
|
57861
58187
|
async function createQaEvidenceVideoPath(runId) {
|
|
57862
58188
|
const qaDir = await createWorkflowArtifactDirectory(runId);
|
|
57863
|
-
return
|
|
58189
|
+
return join25(qaDir, QA_E2E_VIDEO_FILENAME);
|
|
57864
58190
|
}
|
|
57865
58191
|
function renderQaE2eVideoGuidance(qaVideoPath) {
|
|
57866
58192
|
return [
|
|
@@ -57926,7 +58252,7 @@ function artifactSafeName2(value2) {
|
|
|
57926
58252
|
return safe.length > 0 ? safe : "artifact";
|
|
57927
58253
|
}
|
|
57928
58254
|
async function writeJsonArtifact(path, content) {
|
|
57929
|
-
await mkdir4(
|
|
58255
|
+
await mkdir4(dirname12(path), { recursive: true });
|
|
57930
58256
|
await writeFile8(path, `${JSON.stringify(content, null, 2)}
|
|
57931
58257
|
`, {
|
|
57932
58258
|
encoding: "utf8"
|
|
@@ -58264,7 +58590,7 @@ var init_ralph_models = __esm(() => {
|
|
|
58264
58590
|
|
|
58265
58591
|
// dist/builtin/workflows/builtin/ralph-runner.ts
|
|
58266
58592
|
import { existsSync as existsSync5 } from "node:fs";
|
|
58267
|
-
import { join as
|
|
58593
|
+
import { join as join26, resolve as resolve11 } from "node:path";
|
|
58268
58594
|
async function runRalphWorkflow(ctx, options) {
|
|
58269
58595
|
const { prompt, acceptanceCriteria, maxLoops, comparisonBaseBranch, workflowStartCwd, createPr, runId } = options;
|
|
58270
58596
|
let latestReviewReportPath;
|
|
@@ -58276,7 +58602,7 @@ async function runRalphWorkflow(ctx, options) {
|
|
|
58276
58602
|
let finalPrReport;
|
|
58277
58603
|
const workflowCwdContext = workflowCwdContextSection(workflowStartCwd);
|
|
58278
58604
|
const workflowPrompt = prompt;
|
|
58279
|
-
const workflowResearchPath =
|
|
58605
|
+
const workflowResearchPath = resolve11(workflowStartCwd, defaultResearchPath(workflowPrompt));
|
|
58280
58606
|
const implementationNotesPath = await createImplementationNotesFile(workflowPrompt, runId);
|
|
58281
58607
|
const qaVideoPath = await createQaEvidenceVideoPath(runId);
|
|
58282
58608
|
const artifactDir = await createWorkflowArtifactDirectory(runId);
|
|
@@ -58325,7 +58651,7 @@ async function runRalphWorkflow(ctx, options) {
|
|
|
58325
58651
|
const researchPath = workflowResearchPath;
|
|
58326
58652
|
finalResearchPath = researchPath;
|
|
58327
58653
|
finalPlanPath = researchPath;
|
|
58328
|
-
const orchestratorReportPath =
|
|
58654
|
+
const orchestratorReportPath = join26(artifactDir, "orchestrator-report.md");
|
|
58329
58655
|
const orchestratorForkOptions = forkContinuationOptions3(previousOrchestratorSessionId);
|
|
58330
58656
|
const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? taggedPrompt4([
|
|
58331
58657
|
["acceptance_criteria", keepContext(acceptanceCriteria)],
|
|
@@ -58461,7 +58787,7 @@ Read it before implementation or delegation because it is the primary current im
|
|
|
58461
58787
|
diagnostics: parsed.diagnostics,
|
|
58462
58788
|
allowFinalActionRemaining: createPr
|
|
58463
58789
|
});
|
|
58464
|
-
const artifactPath =
|
|
58790
|
+
const artifactPath = join26(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
|
|
58465
58791
|
await writeJsonArtifact(artifactPath, {
|
|
58466
58792
|
reviewer,
|
|
58467
58793
|
decision: parsed.decision,
|
|
@@ -58517,7 +58843,7 @@ Read it before implementation or delegation because it is the primary current im
|
|
|
58517
58843
|
usage: fold_usage([orchestrator, ...reviews, ...reverifyResults])
|
|
58518
58844
|
}));
|
|
58519
58845
|
}
|
|
58520
|
-
latestReviewReportPath = await writeJsonArtifact(
|
|
58846
|
+
latestReviewReportPath = await writeJsonArtifact(join26(artifactDir, "review-round-latest.json"), {
|
|
58521
58847
|
convergence_decision: roundConvergenceDecision,
|
|
58522
58848
|
convergence: convergenceEntries,
|
|
58523
58849
|
consolidated_findings: reverified.batch,
|
|
@@ -58666,7 +58992,7 @@ var init_ralph = __esm(() => {
|
|
|
58666
58992
|
}),
|
|
58667
58993
|
git_worktree_dir: Type21.String({
|
|
58668
58994
|
default: "",
|
|
58669
|
-
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own.
|
|
58995
|
+
description: "Optional Git worktree path. Leave at the default unless the user explicitly requested worktree isolation — stages never create git worktrees on their own. Absolute paths are used as-is; relative paths resolve from the invoking repo root (or the invoking cwd outside a Git repo). An existing Git worktree root of any repository is reused as-is, even from another repository or a non-Git cwd. Creating a worktree requires starting inside the source Git repo: a missing path or an empty directory becomes a new worktree from base_branch, and a non-empty non-Git directory is treated as a worktree root that gets this run's own <dir>/<4-hex>/<repo-name> checkout, reused on resume."
|
|
58670
58996
|
}),
|
|
58671
58997
|
create_pr: Type21.Boolean({
|
|
58672
58998
|
default: false,
|
|
@@ -58886,7 +59212,7 @@ var init_tournament_prompts = __esm(() => {
|
|
|
58886
59212
|
|
|
58887
59213
|
// dist/builtin/workflows/builtin/tournament-runner.ts
|
|
58888
59214
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile9 } from "node:fs/promises";
|
|
58889
|
-
import { join as
|
|
59215
|
+
import { join as join27, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve12 } from "node:path";
|
|
58890
59216
|
import { Type as Type22 } from "typebox";
|
|
58891
59217
|
function serializableObject2(value2) {
|
|
58892
59218
|
if (value2 === null || Array.isArray(value2) || typeof value2 !== "object")
|
|
@@ -58923,8 +59249,8 @@ function criterionSlug(id) {
|
|
|
58923
59249
|
}
|
|
58924
59250
|
function judgeArtifactPath(judgesDir, job, criterionIndex) {
|
|
58925
59251
|
const filename = `judge-${job.a}-${job.b}-c${criterionIndex}-${criterionSlug(job.criterionId)}-r${job.rep}.json`;
|
|
58926
|
-
const root =
|
|
58927
|
-
const path =
|
|
59252
|
+
const root = resolve12(judgesDir);
|
|
59253
|
+
const path = resolve12(judgesDir, filename);
|
|
58928
59254
|
const fromRoot = relative5(root, path);
|
|
58929
59255
|
if (fromRoot.startsWith("..") || isAbsolute9(fromRoot)) {
|
|
58930
59256
|
throw new Error(`tournament: judge artifact escaped its directory: ${path}`);
|
|
@@ -58975,16 +59301,16 @@ function combineUsage(totals) {
|
|
|
58975
59301
|
}
|
|
58976
59302
|
async function runTournament(ctx) {
|
|
58977
59303
|
const artifactDir = await stableArtifactRoot(ctx, "tournament");
|
|
58978
|
-
const attemptsDir =
|
|
59304
|
+
const attemptsDir = join27(artifactDir, "attempts");
|
|
58979
59305
|
const numAttempts = ctx.inputs.num_attempts ?? 4;
|
|
58980
59306
|
const maxConcurrency = ctx.inputs.max_concurrency ?? 4;
|
|
58981
59307
|
const nEvaluations = ctx.inputs.n_evaluations ?? 2;
|
|
58982
59308
|
const pivotCount = ctx.inputs.pivots ?? 1;
|
|
58983
59309
|
const seed = ctx.inputs.seed ?? 0;
|
|
58984
|
-
const judgesDir =
|
|
59310
|
+
const judgesDir = join27(artifactDir, "judges");
|
|
58985
59311
|
await mkdir5(attemptsDir, { recursive: true });
|
|
58986
59312
|
await mkdir5(judgesDir, { recursive: true });
|
|
58987
|
-
const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) =>
|
|
59313
|
+
const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join27(attemptsDir, `attempt-${index + 1}.md`));
|
|
58988
59314
|
const models = ctx.inputs.models;
|
|
58989
59315
|
const attemptResults = await ctx.parallel(attemptArtifactPaths.map((path, index) => ({
|
|
58990
59316
|
name: `attempt-${index + 1}`,
|
|
@@ -59149,7 +59475,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
|
|
|
59149
59475
|
const outputRanking = ranking.map(({ label, meanPreference }) => ({ label, meanPreference }));
|
|
59150
59476
|
const budgetPivots = Math.min(pivotCount, entrants.length);
|
|
59151
59477
|
const comparisonBudget = (entrants.length + budgetPivots * (entrants.length - budgetPivots) + budgetPivots * (budgetPivots - 1) / 2) * criteria.length * nEvaluations;
|
|
59152
|
-
const comparisonPath =
|
|
59478
|
+
const comparisonPath = join27(artifactDir, "comparisons.json");
|
|
59153
59479
|
const assignment = modelAssignment(entrants, models);
|
|
59154
59480
|
const phaseUsage = {
|
|
59155
59481
|
attempts: fold_usage(attemptResults),
|
|
@@ -59185,7 +59511,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
|
|
|
59185
59511
|
await writeLedger(fold_usage([]));
|
|
59186
59512
|
const winner = ranking[0];
|
|
59187
59513
|
const winnerEntrant = entrants[winner.index];
|
|
59188
|
-
const resultPath =
|
|
59514
|
+
const resultPath = join27(artifactDir, "winner.md");
|
|
59189
59515
|
const reducer = await ctx.task("comparisons-reducer", {
|
|
59190
59516
|
prompt: renderComparisonsReducerPrompt({
|
|
59191
59517
|
task: ctx.inputs.prompt,
|
|
@@ -59494,17 +59820,26 @@ function isSameCheckpointValue(stored, next) {
|
|
|
59494
59820
|
const hash = (value2) => durableHash(value2);
|
|
59495
59821
|
return hash(stored) === hash(next);
|
|
59496
59822
|
}
|
|
59823
|
+
function withTimesOf(later, recorded) {
|
|
59824
|
+
const both = (key) => typeof recorded[key] === "number" && typeof later[key] === "number";
|
|
59825
|
+
return {
|
|
59826
|
+
...later,
|
|
59827
|
+
...both("startedAt") ? { startedAt: recorded.startedAt } : {},
|
|
59828
|
+
...both("endedAt") ? { endedAt: recorded.endedAt } : {},
|
|
59829
|
+
...both("completedAt") ? { completedAt: recorded.completedAt } : {}
|
|
59830
|
+
};
|
|
59831
|
+
}
|
|
59497
59832
|
function isRecordedCheckpointValue(stored, next) {
|
|
59498
59833
|
const recorded = stored;
|
|
59499
59834
|
if (isSameCheckpointValue(recorded, next))
|
|
59500
59835
|
return true;
|
|
59501
|
-
|
|
59502
|
-
if (typeof completedAt !== "number")
|
|
59836
|
+
if (typeof recorded.completedAt !== "number")
|
|
59503
59837
|
return false;
|
|
59504
59838
|
const later = next;
|
|
59505
|
-
if (startedAt === undefined !== (later.startedAt === undefined))
|
|
59839
|
+
if (recorded.startedAt === undefined !== (later.startedAt === undefined))
|
|
59506
59840
|
return false;
|
|
59507
|
-
|
|
59841
|
+
const retimed = withTimesOf(later, recorded);
|
|
59842
|
+
return isSameCheckpointValue(recorded.topology !== undefined && later.topology !== undefined ? { ...retimed, topology: withTimesOf(later.topology, recorded.topology) } : retimed, recorded);
|
|
59508
59843
|
}
|
|
59509
59844
|
var MIRROR_FRESH_MS = 2000;
|
|
59510
59845
|
var init_pool_remote_journal = __esm(() => {
|
|
@@ -60082,7 +60417,7 @@ class SqlPoolQueue {
|
|
|
60082
60417
|
throw new Error("Stale pool coordinator authority", { cause: error });
|
|
60083
60418
|
throw error;
|
|
60084
60419
|
});
|
|
60085
|
-
const row = await this.current(tx, lease, token);
|
|
60420
|
+
const row = await this.current(tx, lease, token, true);
|
|
60086
60421
|
if (row.epoch !== lease.epoch)
|
|
60087
60422
|
throw new Error(STALE_WORK_LEASE);
|
|
60088
60423
|
assertSession();
|
|
@@ -60540,15 +60875,7 @@ class SqlPoolQueue {
|
|
|
60540
60875
|
}
|
|
60541
60876
|
}
|
|
60542
60877
|
function isRecordedCheckpoint(stored, payload) {
|
|
60543
|
-
|
|
60544
|
-
return true;
|
|
60545
|
-
const { completedAt, startedAt } = JSON.parse(stored);
|
|
60546
|
-
if (typeof completedAt !== "number")
|
|
60547
|
-
return false;
|
|
60548
|
-
const next = JSON.parse(payload);
|
|
60549
|
-
if (startedAt === undefined !== (next.startedAt === undefined))
|
|
60550
|
-
return false;
|
|
60551
|
-
return serializeJson({ ...next, completedAt, ...startedAt === undefined ? {} : { startedAt } }) === stored;
|
|
60878
|
+
return stored === payload || isRecordedCheckpointValue(JSON.parse(stored), JSON.parse(payload));
|
|
60552
60879
|
}
|
|
60553
60880
|
function openSqlPoolQueue(journal, remote) {
|
|
60554
60881
|
const storage = sqlPoolStorage(journal);
|
|
@@ -62324,7 +62651,7 @@ function isBrokerStatusReport(value2) {
|
|
|
62324
62651
|
|
|
62325
62652
|
// dist/builtin/intercom/broker/paths.ts
|
|
62326
62653
|
import { homedir as homedir2 } from "os";
|
|
62327
|
-
import { join as
|
|
62654
|
+
import { join as join28 } from "path";
|
|
62328
62655
|
function getHomeDir() {
|
|
62329
62656
|
if (process.platform === "win32") {
|
|
62330
62657
|
if (process.env.USERPROFILE)
|
|
@@ -62341,7 +62668,7 @@ function expandTildePath(path) {
|
|
|
62341
62668
|
if (path === "~")
|
|
62342
62669
|
return getHomeDir();
|
|
62343
62670
|
if (path.startsWith("~/") || process.platform === "win32" && path.startsWith("~\\")) {
|
|
62344
|
-
return
|
|
62671
|
+
return join28(getHomeDir(), path.slice(2));
|
|
62345
62672
|
}
|
|
62346
62673
|
return path;
|
|
62347
62674
|
}
|
|
@@ -62352,31 +62679,31 @@ function getAgentDir5() {
|
|
|
62352
62679
|
const piAgentDir = process.env.PI_CODING_AGENT_DIR;
|
|
62353
62680
|
if (piAgentDir)
|
|
62354
62681
|
return expandTildePath(piAgentDir);
|
|
62355
|
-
return
|
|
62682
|
+
return join28(getHomeDir(), ".atomic", "agent");
|
|
62356
62683
|
}
|
|
62357
62684
|
function sanitizePipeSegment(value2) {
|
|
62358
62685
|
return value2.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "default";
|
|
62359
62686
|
}
|
|
62360
62687
|
function getIntercomDirPath(agentDir = getAgentDir5()) {
|
|
62361
|
-
return
|
|
62688
|
+
return join28(agentDir, "intercom");
|
|
62362
62689
|
}
|
|
62363
62690
|
function getBrokerPidPath(agentDir = getAgentDir5()) {
|
|
62364
|
-
return
|
|
62691
|
+
return join28(getIntercomDirPath(agentDir), "broker.pid");
|
|
62365
62692
|
}
|
|
62366
62693
|
function getBrokerSpawnLockPath(agentDir = getAgentDir5()) {
|
|
62367
|
-
return
|
|
62694
|
+
return join28(getIntercomDirPath(agentDir), "broker.spawn.lock");
|
|
62368
62695
|
}
|
|
62369
62696
|
function getBrokerLogPath(agentDir = getAgentDir5()) {
|
|
62370
|
-
return
|
|
62697
|
+
return join28(getIntercomDirPath(agentDir), "broker.log");
|
|
62371
62698
|
}
|
|
62372
62699
|
function getBrokerStartAnnouncementPath(agentDir = getAgentDir5()) {
|
|
62373
|
-
return
|
|
62700
|
+
return join28(getIntercomDirPath(agentDir), "broker.starting");
|
|
62374
62701
|
}
|
|
62375
62702
|
function getBrokerSocketPath(platform = process.platform, agentDir = getAgentDir5()) {
|
|
62376
62703
|
if (platform === "win32") {
|
|
62377
62704
|
return `\\\\.\\pipe\\pi-intercom-${sanitizePipeSegment(agentDir)}`;
|
|
62378
62705
|
}
|
|
62379
|
-
return
|
|
62706
|
+
return join28(getIntercomDirPath(agentDir), "broker.sock");
|
|
62380
62707
|
}
|
|
62381
62708
|
var BROKER_STORAGE_ENV = "ATOMIC_STORAGE";
|
|
62382
62709
|
var init_paths = () => {};
|
|
@@ -64060,11 +64387,11 @@ var init_client = __esm(() => {
|
|
|
64060
64387
|
var BROKER_READY_TIMEOUT_MS = 30000, MIN_BROKER_STARTUP_TIMEOUT_MS = 1000;
|
|
64061
64388
|
|
|
64062
64389
|
// dist/builtin/intercom/broker/start-announcement.ts
|
|
64063
|
-
import { readFileSync as
|
|
64390
|
+
import { readFileSync as readFileSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
64064
64391
|
function readBrokerStartAnnouncement(announcement) {
|
|
64065
64392
|
let text;
|
|
64066
64393
|
try {
|
|
64067
|
-
text =
|
|
64394
|
+
text = readFileSync6(announcement.path, "utf-8");
|
|
64068
64395
|
} catch {
|
|
64069
64396
|
return;
|
|
64070
64397
|
}
|
|
@@ -64083,26 +64410,26 @@ var init_start_announcement = () => {};
|
|
|
64083
64410
|
// dist/builtin/intercom/broker/spawn.ts
|
|
64084
64411
|
import { spawn } from "child_process";
|
|
64085
64412
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
64086
|
-
import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync6, mkdirSync as
|
|
64087
|
-
import { join as
|
|
64413
|
+
import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync7, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
64414
|
+
import { join as join29, dirname as dirname13 } from "path";
|
|
64088
64415
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
64089
64416
|
import { createRequire as createRequire3 } from "module";
|
|
64090
64417
|
import { createChildProcessEnvironment as createChildProcessEnvironment4, isBunBinary, processSharedStorageSelection } from "@bastani/atomic";
|
|
64091
64418
|
function isIntercomPackageRoot(dir) {
|
|
64092
|
-
return existsSync6(
|
|
64419
|
+
return existsSync6(join29(dir, "package.json")) && existsSync6(join29(dir, "broker"));
|
|
64093
64420
|
}
|
|
64094
64421
|
function resolveIntercomPackageRoot(moduleHref) {
|
|
64095
|
-
const here =
|
|
64422
|
+
const here = dirname13(fileURLToPath4(moduleHref));
|
|
64096
64423
|
if (isIntercomPackageRoot(here))
|
|
64097
64424
|
return here;
|
|
64098
|
-
return
|
|
64425
|
+
return join29(here, "..");
|
|
64099
64426
|
}
|
|
64100
64427
|
function resolveBrokerEntrypoint(packageRoot) {
|
|
64101
|
-
const bundled =
|
|
64102
|
-
return existsSync6(bundled) ? bundled :
|
|
64428
|
+
const bundled = join29(packageRoot, "broker", "broker.bundle.mjs");
|
|
64429
|
+
return existsSync6(bundled) ? bundled : join29(packageRoot, "broker", "broker.ts");
|
|
64103
64430
|
}
|
|
64104
64431
|
function ensurePrivateDirectory(path) {
|
|
64105
|
-
|
|
64432
|
+
mkdirSync9(path, { recursive: true, mode: 448 });
|
|
64106
64433
|
if (process.platform !== "win32")
|
|
64107
64434
|
chmodSync(path, 448);
|
|
64108
64435
|
}
|
|
@@ -64115,14 +64442,14 @@ function getCurrentBrokerRuntime() {
|
|
|
64115
64442
|
return isBunBinary ? "bun-binary" : "bun-source";
|
|
64116
64443
|
}
|
|
64117
64444
|
function requireFromExtensionDir(extensionDir) {
|
|
64118
|
-
return createRequire3(
|
|
64445
|
+
return createRequire3(join29(extensionDir, "package.json"));
|
|
64119
64446
|
}
|
|
64120
64447
|
function getJitiCliPath(extensionDir = EXTENSION_DIR) {
|
|
64121
64448
|
try {
|
|
64122
64449
|
const jitiPackage = requireFromExtensionDir(extensionDir).resolve("jiti/package.json");
|
|
64123
|
-
return
|
|
64450
|
+
return join29(dirname13(jitiPackage), "lib", "jiti-cli.mjs");
|
|
64124
64451
|
} catch {
|
|
64125
|
-
return
|
|
64452
|
+
return join29(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
|
|
64126
64453
|
}
|
|
64127
64454
|
}
|
|
64128
64455
|
function getDefaultBrokerRunnerPath(extensionDir) {
|
|
@@ -64144,7 +64471,7 @@ function quoteWindowsArg(value2) {
|
|
|
64144
64471
|
return `"${value2.replace(/"/g, '""')}"`;
|
|
64145
64472
|
}
|
|
64146
64473
|
function getWindowsHiddenLauncherPath(intercomDir = INTERCOM_DIR) {
|
|
64147
|
-
return
|
|
64474
|
+
return join29(intercomDir, "broker-launch.vbs");
|
|
64148
64475
|
}
|
|
64149
64476
|
function usesDefaultBrokerCommand(brokerCommand, brokerArgs) {
|
|
64150
64477
|
return brokerCommand === "npx" && brokerArgs.length === 2 && brokerArgs[0] === "--no-install" && brokerArgs[1] === "tsx";
|
|
@@ -64171,8 +64498,8 @@ function getWindowsHiddenLauncherScript(commandLine) {
|
|
|
64171
64498
|
`);
|
|
64172
64499
|
}
|
|
64173
64500
|
function writeWindowsHiddenLauncher(commandLine, launcherPath = getWindowsHiddenLauncherPath()) {
|
|
64174
|
-
ensurePrivateDirectory(
|
|
64175
|
-
|
|
64501
|
+
ensurePrivateDirectory(dirname13(launcherPath));
|
|
64502
|
+
writeFileSync7(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
|
|
64176
64503
|
return launcherPath;
|
|
64177
64504
|
}
|
|
64178
64505
|
function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath, runtime = getCurrentBrokerRuntime(), logPath = BROKER_LOG) {
|
|
@@ -64215,14 +64542,14 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore",
|
|
|
64215
64542
|
};
|
|
64216
64543
|
}
|
|
64217
64544
|
function resetBrokerLog(logPath = BROKER_LOG) {
|
|
64218
|
-
ensurePrivateDirectory(
|
|
64545
|
+
ensurePrivateDirectory(dirname13(logPath));
|
|
64219
64546
|
try {
|
|
64220
64547
|
const previous = readBrokerLogTail(logPath);
|
|
64221
64548
|
closeSync3(openSync3(logPath, "w"));
|
|
64222
64549
|
if (previous.length > 0) {
|
|
64223
64550
|
try {
|
|
64224
64551
|
const previousPath = `${logPath}.previous`;
|
|
64225
|
-
|
|
64552
|
+
writeFileSync7(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
|
|
64226
64553
|
if (process.platform !== "win32")
|
|
64227
64554
|
chmodSync(previousPath, 384);
|
|
64228
64555
|
} catch {}
|
|
@@ -64366,7 +64693,7 @@ async function isBrokerRunning() {
|
|
|
64366
64693
|
if (!existsSync6(BROKER_PID))
|
|
64367
64694
|
return false;
|
|
64368
64695
|
try {
|
|
64369
|
-
const pid = parseInt(
|
|
64696
|
+
const pid = parseInt(readFileSync7(BROKER_PID, "utf-8").trim(), 10);
|
|
64370
64697
|
if (!Number.isFinite(pid))
|
|
64371
64698
|
return false;
|
|
64372
64699
|
process.kill(pid, 0);
|
|
@@ -64391,7 +64718,7 @@ function handSpawnLockToBroker(pid, owner) {
|
|
|
64391
64718
|
}
|
|
64392
64719
|
function ownsSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
|
|
64393
64720
|
try {
|
|
64394
|
-
return
|
|
64721
|
+
return readFileSync7(lockPath, "utf-8").startsWith(owner);
|
|
64395
64722
|
} catch {
|
|
64396
64723
|
return false;
|
|
64397
64724
|
}
|
|
@@ -64403,7 +64730,7 @@ function acquireSpawnLock() {
|
|
|
64403
64730
|
${Date.now()}
|
|
64404
64731
|
`;
|
|
64405
64732
|
try {
|
|
64406
|
-
|
|
64733
|
+
writeFileSync7(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
|
|
64407
64734
|
return owner;
|
|
64408
64735
|
} catch (error) {
|
|
64409
64736
|
if (!(error instanceof Error) || error.code !== "EEXIST") {
|
|
@@ -64433,7 +64760,7 @@ function isSpawnLockStale(lockPath = BROKER_SPAWN_LOCK, nowMs = Date.now()) {
|
|
|
64433
64760
|
return false;
|
|
64434
64761
|
}
|
|
64435
64762
|
try {
|
|
64436
|
-
const [spawnerLine = "", createdAtLine = "", brokerLine = ""] =
|
|
64763
|
+
const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync7(lockPath, "utf-8").trim().split(`
|
|
64437
64764
|
`);
|
|
64438
64765
|
const spawnerPid = Number.parseInt(spawnerLine, 10);
|
|
64439
64766
|
const createdAt = Number.parseInt(createdAtLine, 10);
|
|
@@ -64511,14 +64838,14 @@ var init_reply_waiter = __esm(() => {
|
|
|
64511
64838
|
});
|
|
64512
64839
|
|
|
64513
64840
|
// dist/builtin/intercom/config.ts
|
|
64514
|
-
import { existsSync as existsSync7, readFileSync as
|
|
64841
|
+
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
64515
64842
|
import { getAgentConfigPaths } from "@bastani/atomic";
|
|
64516
64843
|
function loadConfig() {
|
|
64517
64844
|
if (!existsSync7(CONFIG_PATH)) {
|
|
64518
64845
|
return { ...defaults };
|
|
64519
64846
|
}
|
|
64520
64847
|
try {
|
|
64521
|
-
const raw =
|
|
64848
|
+
const raw = readFileSync8(CONFIG_PATH, "utf-8");
|
|
64522
64849
|
const parsed = JSON.parse(raw);
|
|
64523
64850
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
64524
64851
|
throw new Error("Config must be a JSON object");
|
|
@@ -65101,12 +65428,12 @@ var init_sql_pool_usage = __esm(() => {
|
|
|
65101
65428
|
|
|
65102
65429
|
// dist/builtin/workflows/src/workers/pooled-watch-trace.ts
|
|
65103
65430
|
import { appendFileSync as appendFileSync2 } from "node:fs";
|
|
65104
|
-
import { dirname as
|
|
65431
|
+
import { dirname as dirname14, join as join30, resolve as resolve13 } from "node:path";
|
|
65105
65432
|
function configurePooledWatchTrace(journalPath, processRole) {
|
|
65106
65433
|
if (setting === undefined || setting === "" || setting === "0")
|
|
65107
65434
|
return;
|
|
65108
65435
|
role = processRole;
|
|
65109
|
-
file = setting === "1" ?
|
|
65436
|
+
file = setting === "1" ? join30(dirname14(resolve13(journalPath)), "pooled-watch-trace.jsonl") : resolve13(setting);
|
|
65110
65437
|
}
|
|
65111
65438
|
function tracePooledWatch(step, detail) {
|
|
65112
65439
|
if (file === undefined)
|
|
@@ -65299,8 +65626,8 @@ var init_startup_timeout = () => {};
|
|
|
65299
65626
|
import { fork } from "node:child_process";
|
|
65300
65627
|
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
65301
65628
|
import { createWriteStream } from "node:fs";
|
|
65302
|
-
import { mkdir as mkdir6, rm as rm3, rmdir } from "node:fs/promises";
|
|
65303
|
-
import { dirname as
|
|
65629
|
+
import { appendFile, mkdir as mkdir6, rm as rm3, rmdir } from "node:fs/promises";
|
|
65630
|
+
import { dirname as dirname15, join as join31, resolve as resolve14 } from "node:path";
|
|
65304
65631
|
import { setTimeout as delay2 } from "node:timers/promises";
|
|
65305
65632
|
function isRootLeaseLost(error) {
|
|
65306
65633
|
return error instanceof StaleLeaseError || error.message.startsWith("Stale lease for run ");
|
|
@@ -65309,7 +65636,7 @@ function unconfirmedCleanup(groups) {
|
|
|
65309
65636
|
return new Error(`Local worker process cleanup unconfirmed; ${groups.length > 0 ? `process groups ${groups.join(", ")} still running after SIGKILL; ` : ""}permits quarantined`);
|
|
65310
65637
|
}
|
|
65311
65638
|
function workerLogDirectory(journalPath, root) {
|
|
65312
|
-
return
|
|
65639
|
+
return join31(dirname15(resolve14(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
|
|
65313
65640
|
}
|
|
65314
65641
|
function token(work) {
|
|
65315
65642
|
return {
|
|
@@ -65491,9 +65818,13 @@ class PoolCoordinator {
|
|
|
65491
65818
|
incarnations = new Map;
|
|
65492
65819
|
readyWorkers = new Set;
|
|
65493
65820
|
logs = new Map;
|
|
65821
|
+
keptLogs = new Set;
|
|
65822
|
+
unconfirmedExits = new WeakSet;
|
|
65823
|
+
failed = false;
|
|
65494
65824
|
cleanups = new Set;
|
|
65495
65825
|
controlAcks = new Map;
|
|
65496
65826
|
lastHeard = new Map;
|
|
65827
|
+
awaiting = new Map;
|
|
65497
65828
|
pendingActivity = new Map;
|
|
65498
65829
|
batches = new Map;
|
|
65499
65830
|
publicationFailures = new Map;
|
|
@@ -65538,7 +65869,6 @@ class PoolCoordinator {
|
|
|
65538
65869
|
nextRecoveryAt = 0;
|
|
65539
65870
|
cleanupFailure;
|
|
65540
65871
|
held = new Set;
|
|
65541
|
-
quarantined = new Set;
|
|
65542
65872
|
unreaped = [];
|
|
65543
65873
|
retained = new Map;
|
|
65544
65874
|
retainedTransitions = Promise.resolve();
|
|
@@ -65731,18 +66061,15 @@ class PoolCoordinator {
|
|
|
65731
66061
|
try {
|
|
65732
66062
|
const { survivors, unprobeable } = await reapProcessGroups(this.journal, this.root, { attempt: work });
|
|
65733
66063
|
if (survivors.length > 0) {
|
|
65734
|
-
this.quarantined.add(work.id);
|
|
65735
66064
|
this.unreaped.push({ attempt: work });
|
|
65736
|
-
this.
|
|
65737
|
-
return;
|
|
66065
|
+
this.reportHealth(undefined, `${unconfirmedCleanup(survivors).message}; child ${work.childRunId} of an earlier incarnation replays`);
|
|
65738
66066
|
}
|
|
65739
66067
|
if (unprobeable.length === 0)
|
|
65740
66068
|
await this.releaseRetained(work);
|
|
65741
66069
|
} catch (error) {
|
|
65742
66070
|
this.cleanupFailure ??= error instanceof Error ? error : new Error(String(error));
|
|
65743
66071
|
} finally {
|
|
65744
|
-
|
|
65745
|
-
this.held.delete(work.id);
|
|
66072
|
+
this.held.delete(work.id);
|
|
65746
66073
|
}
|
|
65747
66074
|
}
|
|
65748
66075
|
releaseRetained(work) {
|
|
@@ -65873,6 +66200,7 @@ class PoolCoordinator {
|
|
|
65873
66200
|
});
|
|
65874
66201
|
}
|
|
65875
66202
|
fail(error) {
|
|
66203
|
+
this.failed = true;
|
|
65876
66204
|
this.port.send({ kind: "failure", error: error.message });
|
|
65877
66205
|
}
|
|
65878
66206
|
failWork(work, error) {
|
|
@@ -66240,7 +66568,7 @@ class PoolCoordinator {
|
|
|
66240
66568
|
this.slots.add(slot);
|
|
66241
66569
|
let ready = false;
|
|
66242
66570
|
let serial = Promise.resolve();
|
|
66243
|
-
const logPath =
|
|
66571
|
+
const logPath = join31(this.logDirectory, `${worker}.log`);
|
|
66244
66572
|
this.logs.set(child, logPath);
|
|
66245
66573
|
let logFailure;
|
|
66246
66574
|
const log = createWriteStream(logPath, { flags: "a" });
|
|
@@ -66281,7 +66609,11 @@ class PoolCoordinator {
|
|
|
66281
66609
|
terminate();
|
|
66282
66610
|
});
|
|
66283
66611
|
const closed = new Promise((resolve) => child.once("close", () => resolve()));
|
|
66284
|
-
|
|
66612
|
+
let retired = false;
|
|
66613
|
+
const retire = () => {
|
|
66614
|
+
if (retired)
|
|
66615
|
+
return;
|
|
66616
|
+
retired = true;
|
|
66285
66617
|
Promise.race([closed, delay2(STDERR_DRAIN_GRACE_MS)]).then(() => reject(diagnosed(timedOut ? startupTimeoutMessage(startupTimeoutMs) : "Local worker exited before readiness")));
|
|
66286
66618
|
this.children.delete(child);
|
|
66287
66619
|
this.logs.delete(child);
|
|
@@ -66292,6 +66624,7 @@ class PoolCoordinator {
|
|
|
66292
66624
|
this.readyWorkers.delete(worker);
|
|
66293
66625
|
this.controlAcks.delete(worker);
|
|
66294
66626
|
this.lastHeard.delete(worker);
|
|
66627
|
+
this.awaiting.delete(worker);
|
|
66295
66628
|
this.slots.delete(slot);
|
|
66296
66629
|
this.endStageWatches((watch) => watch.slot === slot, "worker_exited");
|
|
66297
66630
|
for (const settle of slot.stageCommands.values())
|
|
@@ -66305,7 +66638,7 @@ class PoolCoordinator {
|
|
|
66305
66638
|
const held = slot.work;
|
|
66306
66639
|
if (held)
|
|
66307
66640
|
this.held.add(held.id);
|
|
66308
|
-
let
|
|
66641
|
+
let unconfirmed;
|
|
66309
66642
|
const cleanup = disconnected.then(() => serial).then(async () => {
|
|
66310
66643
|
try {
|
|
66311
66644
|
const admission = this.admission;
|
|
@@ -66318,18 +66651,13 @@ class PoolCoordinator {
|
|
|
66318
66651
|
throw unconfirmedCleanup(alive);
|
|
66319
66652
|
if (alive.length === 0)
|
|
66320
66653
|
return;
|
|
66321
|
-
|
|
66322
|
-
|
|
66323
|
-
this.quarantined.add(held.id);
|
|
66324
|
-
slot.work = undefined;
|
|
66325
|
-
childFailed = true;
|
|
66326
|
-
this.port.send({ kind: "work-failure", workId: held.id, error: error.message });
|
|
66327
|
-
}
|
|
66654
|
+
unconfirmed = unconfirmedCleanup(alive);
|
|
66655
|
+
this.reportHealth(logPath, `${unconfirmed.message}; the worker was retired and replaced`);
|
|
66328
66656
|
} catch (error) {
|
|
66329
66657
|
this.cleanupFailure = error instanceof Error ? error : new Error(String(error));
|
|
66330
66658
|
throw this.cleanupFailure;
|
|
66331
66659
|
} finally {
|
|
66332
|
-
if (held
|
|
66660
|
+
if (held)
|
|
66333
66661
|
this.held.delete(held.id);
|
|
66334
66662
|
}
|
|
66335
66663
|
}).then(async () => {
|
|
@@ -66350,8 +66678,8 @@ class PoolCoordinator {
|
|
|
66350
66678
|
const settled = attempt !== undefined && await this.whileRootLate(queue, () => exhausted ? queue.failExited(lease, attempt) : queue.releaseExited(lease, attempt));
|
|
66351
66679
|
const superseded = work !== undefined && !settled && await this.superseded(work);
|
|
66352
66680
|
if (work !== undefined && exhausted && !superseded)
|
|
66353
|
-
this.failWork(work, diagnosed(childRetryLimit(work, "lost its worker")));
|
|
66354
|
-
if (work === undefined &&
|
|
66681
|
+
this.failWork(work, diagnosed(`${childRetryLimit(work, "lost its worker")}${unconfirmed === undefined ? "" : `; ${unconfirmed.message}`}`));
|
|
66682
|
+
if (work === undefined && ++this.replacements > 3)
|
|
66355
66683
|
this.fail(diagnosed("Local worker retry limit"));
|
|
66356
66684
|
else
|
|
66357
66685
|
await this.spawn();
|
|
@@ -66360,7 +66688,9 @@ class PoolCoordinator {
|
|
|
66360
66688
|
});
|
|
66361
66689
|
this.cleanups.add(cleanup);
|
|
66362
66690
|
cleanup.finally(() => this.cleanups.delete(cleanup));
|
|
66363
|
-
}
|
|
66691
|
+
};
|
|
66692
|
+
slot.retire = retire;
|
|
66693
|
+
child.once("exit", retire);
|
|
66364
66694
|
child.on("message", (message) => {
|
|
66365
66695
|
this.observeResponsiveness();
|
|
66366
66696
|
this.lastHeard.set(worker, { at: performance.now(), stalled: this.stalledMs });
|
|
@@ -66434,10 +66764,11 @@ class PoolCoordinator {
|
|
|
66434
66764
|
const fenced = slot.work;
|
|
66435
66765
|
slot.work = undefined;
|
|
66436
66766
|
if (fenced && !await this.superseded(fenced)) {
|
|
66767
|
+
this.fence(fenced);
|
|
66437
66768
|
if (this.attempts(fenced) < MAX_CHILD_ATTEMPTS)
|
|
66438
66769
|
await leased(() => queue.releaseExited(lease, fenced));
|
|
66439
66770
|
else if (await leased(() => queue.failExited(lease, fenced)))
|
|
66440
|
-
this.failWork(fenced, new Error(childRetryLimit(fenced, "was refused by the root as stale on every attempt")));
|
|
66771
|
+
this.failWork(fenced, new Error(childRetryLimit(fenced, message.fault === undefined ? "was refused by the root as stale on every attempt" : `failed on a fault of the pool on every attempt (last: ${message.fault})`)));
|
|
66441
66772
|
}
|
|
66442
66773
|
return;
|
|
66443
66774
|
}
|
|
@@ -66551,8 +66882,19 @@ class PoolCoordinator {
|
|
|
66551
66882
|
await this.sendResult(work.id);
|
|
66552
66883
|
});
|
|
66553
66884
|
const response = handled.then((value2) => routeReady ?? value2);
|
|
66554
|
-
if (message.kind !== "delivery" && message.kind !== "delivery-ready")
|
|
66555
|
-
|
|
66885
|
+
if (message.kind !== "delivery" && message.kind !== "delivery-ready") {
|
|
66886
|
+
this.awaiting.set(worker, (this.awaiting.get(worker) ?? 0) + 1);
|
|
66887
|
+
const answered = () => {
|
|
66888
|
+
const left = (this.awaiting.get(worker) ?? 1) - 1;
|
|
66889
|
+
if (left > 0)
|
|
66890
|
+
this.awaiting.set(worker, left);
|
|
66891
|
+
else
|
|
66892
|
+
this.awaiting.delete(worker);
|
|
66893
|
+
if (this.incarnations.get(worker) === child)
|
|
66894
|
+
this.lastHeard.set(worker, { at: performance.now(), stalled: this.stalledMs });
|
|
66895
|
+
};
|
|
66896
|
+
serial = handled.then(answered, answered);
|
|
66897
|
+
}
|
|
66556
66898
|
response.then((value2) => child.send({ id: message.id, value: value2 }, replied), (error) => {
|
|
66557
66899
|
const rootLeaseLost = isRootLeaseLost(error);
|
|
66558
66900
|
if (rootLeaseLost)
|
|
@@ -66598,8 +66940,6 @@ class PoolCoordinator {
|
|
|
66598
66940
|
return;
|
|
66599
66941
|
}
|
|
66600
66942
|
for (const work of expired) {
|
|
66601
|
-
if (this.quarantined.has(work.id))
|
|
66602
|
-
continue;
|
|
66603
66943
|
if (this.held.has(work.id)) {
|
|
66604
66944
|
await queue.extend(lease, work, leaseMs).catch((error) => {
|
|
66605
66945
|
if (error.message !== STALE_WORK_LEASE)
|
|
@@ -66615,16 +66955,19 @@ class PoolCoordinator {
|
|
|
66615
66955
|
});
|
|
66616
66956
|
continue;
|
|
66617
66957
|
}
|
|
66618
|
-
if (child && !await this.stop(child)
|
|
66619
|
-
|
|
66620
|
-
if (this.held.has(work.id)
|
|
66958
|
+
if (child && !await this.stop(child))
|
|
66959
|
+
this.retireUnconfirmed(child);
|
|
66960
|
+
if (this.held.has(work.id))
|
|
66621
66961
|
continue;
|
|
66622
66962
|
if ((await unconfirmedProcessGroups(this.journal, root, { attempt: work })).length > 0)
|
|
66623
66963
|
continue;
|
|
66624
66964
|
if (work.epoch < lease.epoch)
|
|
66625
66965
|
await this.releaseRetained(work);
|
|
66626
66966
|
else
|
|
66627
|
-
await queue.expire(lease, work)
|
|
66967
|
+
await queue.expire(lease, work).catch((error) => {
|
|
66968
|
+
if (error.message !== STALE_WORK_LEASE)
|
|
66969
|
+
throw error;
|
|
66970
|
+
});
|
|
66628
66971
|
}
|
|
66629
66972
|
})().finally(() => {
|
|
66630
66973
|
this.recovering = undefined;
|
|
@@ -66642,19 +66985,51 @@ class PoolCoordinator {
|
|
|
66642
66985
|
isLive(worker, child) {
|
|
66643
66986
|
this.observeResponsiveness();
|
|
66644
66987
|
const heard = this.lastHeard.get(worker);
|
|
66645
|
-
return child.exitCode === null && child.signalCode === null && child.connected && heard !== undefined && performance.now() - heard.at - (this.stalledMs - heard.stalled) < this.options.leaseMs;
|
|
66988
|
+
return child.exitCode === null && child.signalCode === null && child.connected && heard !== undefined && ((this.awaiting.get(worker) ?? 0) > 0 || performance.now() - heard.at - (this.stalledMs - heard.stalled) < this.options.leaseMs);
|
|
66646
66989
|
}
|
|
66647
|
-
stop(child) {
|
|
66648
|
-
|
|
66649
|
-
|
|
66650
|
-
|
|
66651
|
-
|
|
66652
|
-
|
|
66653
|
-
|
|
66654
|
-
|
|
66655
|
-
|
|
66656
|
-
|
|
66657
|
-
|
|
66990
|
+
async stop(child) {
|
|
66991
|
+
const pid = child.pid;
|
|
66992
|
+
const exited = () => child.exitCode !== null || child.signalCode !== null;
|
|
66993
|
+
if (pid === undefined || exited())
|
|
66994
|
+
return true;
|
|
66995
|
+
const exit = new Promise((resolve) => child.once("exit", () => resolve()));
|
|
66996
|
+
const confirmed = async () => {
|
|
66997
|
+
await Promise.race([exit, delay2(WORKER_EXIT_CONFIRMATION_MS)]);
|
|
66998
|
+
return true;
|
|
66999
|
+
};
|
|
67000
|
+
this.observeResponsiveness();
|
|
67001
|
+
child.kill("SIGKILL");
|
|
67002
|
+
const since = performance.now();
|
|
67003
|
+
const stalledAt = this.stalledMs;
|
|
67004
|
+
for (;; ) {
|
|
67005
|
+
await Promise.race([exit, delay2(WORKER_EXIT_POLL_MS)]);
|
|
67006
|
+
if (exited())
|
|
67007
|
+
return true;
|
|
67008
|
+
if (workerProcessExited(pid))
|
|
67009
|
+
return confirmed();
|
|
67010
|
+
this.observeResponsiveness();
|
|
67011
|
+
if (performance.now() - since - (this.stalledMs - stalledAt) >= WORKER_EXIT_CONFIRMATION_MS)
|
|
67012
|
+
return exited() || workerProcessExited(pid, true) && confirmed();
|
|
67013
|
+
}
|
|
67014
|
+
}
|
|
67015
|
+
retireUnconfirmed(child) {
|
|
67016
|
+
if (this.unconfirmedExits.has(child))
|
|
67017
|
+
return;
|
|
67018
|
+
this.unconfirmedExits.add(child);
|
|
67019
|
+
this.reportHealth(this.logs.get(child), `Local worker cleanup was not confirmed: worker process ${child.pid} was still running ${WORKER_EXIT_CONFIRMATION_MS} ms after SIGKILL; it was retired and replaced`);
|
|
67020
|
+
if (child.connected)
|
|
67021
|
+
child.disconnect();
|
|
67022
|
+
for (const slot of this.slots)
|
|
67023
|
+
if (slot.child === child)
|
|
67024
|
+
slot.retire?.();
|
|
67025
|
+
}
|
|
67026
|
+
reportHealth(log, message) {
|
|
67027
|
+
if (log !== undefined) {
|
|
67028
|
+
this.keptLogs.add(log);
|
|
67029
|
+
appendFile(log, `[atomic ${new Date().toISOString()}] ${message}
|
|
67030
|
+
`).catch(() => {});
|
|
67031
|
+
}
|
|
67032
|
+
this.port.send({ kind: "health", message: log === undefined ? message : `${message} (worker log: ${log})` });
|
|
66658
67033
|
}
|
|
66659
67034
|
async close() {
|
|
66660
67035
|
this.closed = true;
|
|
@@ -66664,10 +67039,15 @@ class PoolCoordinator {
|
|
|
66664
67039
|
this.rateLimitOutbox.close();
|
|
66665
67040
|
let failure;
|
|
66666
67041
|
let stopping = [];
|
|
67042
|
+
let confirmed = [];
|
|
66667
67043
|
try {
|
|
66668
67044
|
await this.recovering?.catch(() => {});
|
|
66669
67045
|
stopping = [...this.children].map((child) => ({ child, log: this.logs.get(child) }));
|
|
66670
|
-
await Promise.all(stopping.map(({ child }) => this.stop(child)));
|
|
67046
|
+
confirmed = await Promise.all(stopping.map(({ child }) => this.stop(child)));
|
|
67047
|
+
stopping.forEach(({ child }, index) => {
|
|
67048
|
+
if (!confirmed[index])
|
|
67049
|
+
this.retireUnconfirmed(child);
|
|
67050
|
+
});
|
|
66671
67051
|
await Promise.all([...this.cleanups]);
|
|
66672
67052
|
if (this.cleanupFailure)
|
|
66673
67053
|
throw this.cleanupFailure;
|
|
@@ -66679,15 +67059,15 @@ class PoolCoordinator {
|
|
|
66679
67059
|
if (alive.length > 0)
|
|
66680
67060
|
throw unconfirmedCleanup(alive);
|
|
66681
67061
|
if (this.desiredControl !== "quit" && this.queue !== undefined && this.lease !== undefined)
|
|
66682
|
-
await this.queue.releaseClosed(this.lease
|
|
67062
|
+
await this.queue.releaseClosed(this.lease).catch((error) => {
|
|
66683
67063
|
if (!(error instanceof StaleLeaseError))
|
|
66684
67064
|
throw error;
|
|
66685
67065
|
});
|
|
66686
67066
|
} catch (error) {
|
|
66687
67067
|
failure = error;
|
|
66688
67068
|
}
|
|
66689
|
-
if (failure === undefined) {
|
|
66690
|
-
const stopped = stopping.flatMap(({
|
|
67069
|
+
if (failure === undefined && !this.failed) {
|
|
67070
|
+
const stopped = stopping.flatMap(({ log }, index) => log !== undefined && !this.keptLogs.has(log) && confirmed[index] === true ? [log] : []);
|
|
66691
67071
|
await Promise.all(stopped.map((log) => rm3(log, { force: true }).catch(() => {})));
|
|
66692
67072
|
if (this.logDirectory !== undefined)
|
|
66693
67073
|
await rmdir(this.logDirectory).catch(() => {});
|
|
@@ -66713,7 +67093,7 @@ function childRetryLimit(work, reason) {
|
|
|
66713
67093
|
const exportName = work.definition.slice(work.definition.lastIndexOf("#") + 1);
|
|
66714
67094
|
return `Local worker retry limit: child ${work.childRunId} (${exportName}) ${reason} ${MAX_CHILD_ATTEMPTS} times`;
|
|
66715
67095
|
}
|
|
66716
|
-
var CONTROL_ACKNOWLEDGEMENT_STALL_MS = 5000, RECOVERY_INTERVAL_MS = 500, TICK_INTERVAL_MS = 100, STALL_THRESHOLD_MS = 500, COORDINATOR_LEASE_MS, LATE_ROOT_POLL_MS, MIRROR_INTERVAL_MS = 1e4, STDERR_TAIL_CHARACTERS = 8192, STDERR_DRAIN_GRACE_MS = 1000, MAX_CHILD_ATTEMPTS = 3, ROUTE_REGISTRATION_WAIT_MS = 120000, STAGE_WATCH_BACKLOG_EVENTS = 2000, STAGE_WATCH_BACKLOG_BYTES, PENDING_STAGE_MESSAGE_EVENT2 = "atomic:workflow-pending-stage-message", STICKY_LIVE_DELIVERED_EVENT2 = "atomic:workflow-sticky-live-delivered", PENDING_STAGE_UNDELIVERABLE_EVENT2 = "atomic:workflow-pending-stage-undeliverable", ENDED_WATCHES_REMEMBERED = 1024;
|
|
67096
|
+
var CONTROL_ACKNOWLEDGEMENT_STALL_MS = 5000, RECOVERY_INTERVAL_MS = 500, TICK_INTERVAL_MS = 100, STALL_THRESHOLD_MS = 500, COORDINATOR_LEASE_MS, LATE_ROOT_POLL_MS, MIRROR_INTERVAL_MS = 1e4, STDERR_TAIL_CHARACTERS = 8192, STDERR_DRAIN_GRACE_MS = 1000, WORKER_EXIT_CONFIRMATION_MS = 5000, WORKER_EXIT_POLL_MS = 50, MAX_CHILD_ATTEMPTS = 3, ROUTE_REGISTRATION_WAIT_MS = 120000, STAGE_WATCH_BACKLOG_EVENTS = 2000, STAGE_WATCH_BACKLOG_BYTES, PENDING_STAGE_MESSAGE_EVENT2 = "atomic:workflow-pending-stage-message", STICKY_LIVE_DELIVERED_EVENT2 = "atomic:workflow-sticky-live-delivered", PENDING_STAGE_UNDELIVERABLE_EVENT2 = "atomic:workflow-pending-stage-undeliverable", ENDED_WATCHES_REMEMBERED = 1024;
|
|
66717
67097
|
var init_pool_coordinator = __esm(() => {
|
|
66718
67098
|
init_internal();
|
|
66719
67099
|
init_pool_remote_journal();
|
|
@@ -66728,6 +67108,7 @@ var init_pool_coordinator = __esm(() => {
|
|
|
66728
67108
|
init_pending_stage_route_readiness();
|
|
66729
67109
|
init_store();
|
|
66730
67110
|
init_workflow_infrastructure_error();
|
|
67111
|
+
init_admission_host();
|
|
66731
67112
|
init_pool_journal();
|
|
66732
67113
|
init_pooled_watch_trace();
|
|
66733
67114
|
init_resource_admission();
|
|
@@ -66956,7 +67337,7 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
66956
67337
|
};
|
|
66957
67338
|
}
|
|
66958
67339
|
async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient) {
|
|
66959
|
-
const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient);
|
|
67340
|
+
const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, recipient?.receivedMessageIds);
|
|
66960
67341
|
const candidateIds = new Set([
|
|
66961
67342
|
...activeStore.pendingStageMessagesFor(runId, stageId),
|
|
66962
67343
|
...activeStore.pendingStageMessagesFor(runId, stageName),
|
|
@@ -67012,7 +67393,7 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
|
|
|
67012
67393
|
}
|
|
67013
67394
|
}
|
|
67014
67395
|
}
|
|
67015
|
-
function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient) {
|
|
67396
|
+
function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient, receivedByEndedStage = []) {
|
|
67016
67397
|
const runs = activeStore.runs();
|
|
67017
67398
|
const rootRunId = durableRootRunIdForRun(runs, runId);
|
|
67018
67399
|
if (rootRunId === undefined)
|
|
@@ -67021,22 +67402,28 @@ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageNam
|
|
|
67021
67402
|
if (rootRun === undefined)
|
|
67022
67403
|
return [];
|
|
67023
67404
|
const stage = runs.find((run) => run.id === runId)?.stages.find((candidate) => candidate.id === stageId);
|
|
67024
|
-
|
|
67405
|
+
const ended = stage?.status === "completed" || stage?.status === "skipped";
|
|
67406
|
+
if (ended && receivedByEndedStage.length === 0)
|
|
67025
67407
|
return [];
|
|
67026
67408
|
const hops = workflowBoundaryHops(runs, runId);
|
|
67027
67409
|
if (hops === undefined)
|
|
67028
67410
|
return [];
|
|
67029
67411
|
return (rootRun.pendingStageMessages ?? []).filter((entry) => {
|
|
67030
|
-
if (entry.sticky !== true || entry.status !== "queued")
|
|
67031
|
-
return false;
|
|
67032
|
-
const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
|
|
67033
|
-
if (parsed === undefined || parsed.rootRunId !== rootRunId)
|
|
67034
|
-
return false;
|
|
67035
67412
|
if ((entry.deliveries ?? []).some((delivery) => delivery.runId === runId && delivery.stageId === stageId && (recipient === undefined || delivery.admission === "context" && delivery.sessionId === recipient.sessionId && (recipient.receivedMessageIds === undefined || recipient.receivedMessageIds.includes(entry.message.id)))))
|
|
67036
67413
|
return false;
|
|
67037
|
-
|
|
67414
|
+
if (ended && !receivedByEndedStage.includes(entry.message.id))
|
|
67415
|
+
return false;
|
|
67416
|
+
return stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName);
|
|
67038
67417
|
});
|
|
67039
67418
|
}
|
|
67419
|
+
function stickyEntryTargetsStage(entry, rootRunId, hops, stageId, stageName) {
|
|
67420
|
+
if (entry.sticky !== true || entry.status !== "queued")
|
|
67421
|
+
return false;
|
|
67422
|
+
const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
|
|
67423
|
+
if (parsed === undefined || parsed.rootRunId !== rootRunId)
|
|
67424
|
+
return false;
|
|
67425
|
+
return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
|
|
67426
|
+
}
|
|
67040
67427
|
function claimPendingDelivery(store, runId, stageKey, messageId) {
|
|
67041
67428
|
let claims = pendingDeliveryClaims.get(store);
|
|
67042
67429
|
if (claims === undefined) {
|
|
@@ -67100,6 +67487,7 @@ class PoolStageHandoff {
|
|
|
67100
67487
|
owners = new Map;
|
|
67101
67488
|
publications = new Map;
|
|
67102
67489
|
drains = new Map;
|
|
67490
|
+
deliveryIssues = 0;
|
|
67103
67491
|
constructor(backend, store, queue, lease, claimRun) {
|
|
67104
67492
|
this.backend = backend;
|
|
67105
67493
|
this.store = store;
|
|
@@ -67180,11 +67568,23 @@ class PoolStageHandoff {
|
|
|
67180
67568
|
this.drains.set(stage, drain);
|
|
67181
67569
|
try {
|
|
67182
67570
|
await drain;
|
|
67571
|
+
} catch (error) {
|
|
67572
|
+
const current = this.attempts.get(work.id) === attempt && !attempt.fenced;
|
|
67573
|
+
if (current && attempt.sessions.get(stage) === recipient.sessionId && error.message !== STALE)
|
|
67574
|
+
this.recordDeliveryIssue(error);
|
|
67575
|
+
throw error;
|
|
67183
67576
|
} finally {
|
|
67184
67577
|
if (this.drains.get(stage) === drain)
|
|
67185
67578
|
this.drains.delete(stage);
|
|
67186
67579
|
}
|
|
67187
67580
|
}
|
|
67581
|
+
recordDeliveryIssue(error) {
|
|
67582
|
+
this.deliveryIssues++;
|
|
67583
|
+
const drains = this.deliveryIssues === 1 ? "1 stage drain" : `${this.deliveryIssues} stage drains`;
|
|
67584
|
+
this.store.recordRunExecutionState(this.lease.runId, {
|
|
67585
|
+
intercomDeliveryIssue: `${drains} on local workers failed; undelivered messages stay queued and arrive live or on the stage's next drain (last: ${error.message})`
|
|
67586
|
+
});
|
|
67587
|
+
}
|
|
67188
67588
|
async complete(work) {
|
|
67189
67589
|
const root = this.lease.runId;
|
|
67190
67590
|
const result = await this.queue.result(root, work.id);
|
|
@@ -68540,7 +68940,7 @@ var init_pooled_stage_registry = __esm(() => {
|
|
|
68540
68940
|
// dist/builtin/workflows/src/workers/local-pool.ts
|
|
68541
68941
|
import { fork as fork2 } from "node:child_process";
|
|
68542
68942
|
import { randomUUID as randomUUID19 } from "node:crypto";
|
|
68543
|
-
import { resolve as
|
|
68943
|
+
import { resolve as resolve15 } from "node:path";
|
|
68544
68944
|
import { setTimeout as delay3 } from "node:timers/promises";
|
|
68545
68945
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
68546
68946
|
import {
|
|
@@ -68658,6 +69058,7 @@ class LocalWorkerPool {
|
|
|
68658
69058
|
works = new Map;
|
|
68659
69059
|
attempts = new Map;
|
|
68660
69060
|
results = new Map;
|
|
69061
|
+
healthEvents = [];
|
|
68661
69062
|
workFailures = new Map;
|
|
68662
69063
|
changed = Promise.withResolvers();
|
|
68663
69064
|
waiting = 0;
|
|
@@ -68715,6 +69116,9 @@ class LocalWorkerPool {
|
|
|
68715
69116
|
if (options.admission && options.rootId === undefined)
|
|
68716
69117
|
workflowResourceAdmission.set(backend, options.admission);
|
|
68717
69118
|
}
|
|
69119
|
+
get health() {
|
|
69120
|
+
return this.healthEvents;
|
|
69121
|
+
}
|
|
68718
69122
|
get workerPids() {
|
|
68719
69123
|
return [...this.pids];
|
|
68720
69124
|
}
|
|
@@ -68770,7 +69174,7 @@ class LocalWorkerPool {
|
|
|
68770
69174
|
async poolJournal() {
|
|
68771
69175
|
const journal = this.backend.journal;
|
|
68772
69176
|
if (this.options.durable === undefined) {
|
|
68773
|
-
if (!(journal instanceof SqlRunJournal) ||
|
|
69177
|
+
if (!(journal instanceof SqlRunJournal) || resolve15(this.options.journalPath) !== resolve15(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
|
|
68774
69178
|
throw new Error("Local workers require the same default-prefix SQLite journal");
|
|
68775
69179
|
return journal;
|
|
68776
69180
|
}
|
|
@@ -69308,14 +69712,8 @@ class LocalWorkerPool {
|
|
|
69308
69712
|
try {
|
|
69309
69713
|
return await this.dispatch(definition, inputs, options);
|
|
69310
69714
|
} catch (error) {
|
|
69311
|
-
if (
|
|
69312
|
-
|
|
69313
|
-
try {
|
|
69314
|
-
if (this.desiredControl !== "quit" || !findWorkflowGracefulQuit(error))
|
|
69315
|
-
await this.shutdown();
|
|
69316
|
-
} catch (closeError) {
|
|
69317
|
-
throw asWorkflowInfrastructureError(closeError) ?? closeError;
|
|
69318
|
-
}
|
|
69715
|
+
if (this.failure !== undefined || this.coordinatorLost !== undefined)
|
|
69716
|
+
await this.shutdown().catch(() => {});
|
|
69319
69717
|
throw asWorkflowInfrastructureError(error) ?? error;
|
|
69320
69718
|
}
|
|
69321
69719
|
}
|
|
@@ -69383,8 +69781,13 @@ class LocalWorkerPool {
|
|
|
69383
69781
|
try {
|
|
69384
69782
|
for (;; ) {
|
|
69385
69783
|
options.signal?.throwIfAborted();
|
|
69386
|
-
if (this.closed)
|
|
69387
|
-
|
|
69784
|
+
if (!this.results.has(work.id) && (this.closed || this.failure !== undefined)) {
|
|
69785
|
+
const recorded = await this.queue?.result(root, work.id).catch(() => {
|
|
69786
|
+
return;
|
|
69787
|
+
});
|
|
69788
|
+
if (recorded !== undefined)
|
|
69789
|
+
this.results.set(work.id, recorded);
|
|
69790
|
+
}
|
|
69388
69791
|
const result = this.results.get(work.id);
|
|
69389
69792
|
if (result) {
|
|
69390
69793
|
this.completing++;
|
|
@@ -69408,6 +69811,8 @@ class LocalWorkerPool {
|
|
|
69408
69811
|
this.endFailedChild(work, failed);
|
|
69409
69812
|
throw failed;
|
|
69410
69813
|
}
|
|
69814
|
+
if (this.closed)
|
|
69815
|
+
throw this.closedError(root);
|
|
69411
69816
|
if (this.failure)
|
|
69412
69817
|
throw this.failure;
|
|
69413
69818
|
if (this.budgetBlocked)
|
|
@@ -69442,6 +69847,19 @@ class LocalWorkerPool {
|
|
|
69442
69847
|
if (this.reconnectingViews.size > 0 || this.outboxes.size > 0)
|
|
69443
69848
|
this.reconnectStageViews();
|
|
69444
69849
|
}
|
|
69850
|
+
recordHealth(message) {
|
|
69851
|
+
this.healthEvents.push(message);
|
|
69852
|
+
const root = this.root;
|
|
69853
|
+
if (root === undefined || this.store === undefined)
|
|
69854
|
+
return;
|
|
69855
|
+
this.store.recordNotice({
|
|
69856
|
+
id: `local-worker-health:${root}:${this.healthEvents.length}`,
|
|
69857
|
+
runId: root,
|
|
69858
|
+
level: "warning",
|
|
69859
|
+
message: `Local worker pool: ${message}`,
|
|
69860
|
+
createdAt: Date.now()
|
|
69861
|
+
});
|
|
69862
|
+
}
|
|
69445
69863
|
evaluateBudget() {
|
|
69446
69864
|
const decision = this.rootBudget?.checkpoint();
|
|
69447
69865
|
const blocked = decision?.kind === "exhausted" || decision?.kind === "wrap_up";
|
|
@@ -69560,6 +69978,9 @@ class LocalWorkerPool {
|
|
|
69560
69978
|
this.failure ??= new Error(event.error);
|
|
69561
69979
|
this.signalChange();
|
|
69562
69980
|
return;
|
|
69981
|
+
case "health":
|
|
69982
|
+
this.recordHealth(event.message);
|
|
69983
|
+
return;
|
|
69563
69984
|
case "stage-events":
|
|
69564
69985
|
this.stageWatches.get(event.watch)?.({ kind: "events", events: event.events });
|
|
69565
69986
|
this.notice({ kind: "stage-events-applied", watch: event.watch });
|
|
@@ -69780,7 +70201,7 @@ var init_local_pool = __esm(() => {
|
|
|
69780
70201
|
var DEFAULT_POOLED_STAGE_START_MAX_LOAD_PER_CPU = 3;
|
|
69781
70202
|
|
|
69782
70203
|
// dist/builtin/workflows/src/workers/public-pool.ts
|
|
69783
|
-
import { resolve as
|
|
70204
|
+
import { resolve as resolve16 } from "node:path";
|
|
69784
70205
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
69785
70206
|
async function restoreWorkerOptions(backend, options) {
|
|
69786
70207
|
const source = options.continuation?.source.id ?? options.runId;
|
|
@@ -69830,16 +70251,16 @@ async function activatePublicPool(backend, options) {
|
|
|
69830
70251
|
startupTimeoutMs: undefined,
|
|
69831
70252
|
leaseMs: undefined,
|
|
69832
70253
|
maxLoadPerCpu: undefined,
|
|
69833
|
-
definitions: options.localWorkers.definitions.map((source) => ({ ...source, path:
|
|
70254
|
+
definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve16(cwd, source.path) }))
|
|
69834
70255
|
};
|
|
69835
70256
|
const admission = options.admission && {
|
|
69836
70257
|
...options.admission,
|
|
69837
|
-
...options.admission.userDatabase ? { userDatabase:
|
|
70258
|
+
...options.admission.userDatabase ? { userDatabase: resolve16(cwd, options.admission.userDatabase) } : {}
|
|
69838
70259
|
};
|
|
69839
70260
|
if (durable !== undefined && admission?.userLimits) {
|
|
69840
|
-
if (admission.userDatabase !== undefined && admission.userDatabase !==
|
|
69841
|
-
throw new Error(`admission.userDatabase must be omitted, or ${
|
|
69842
|
-
admission.userDatabase =
|
|
70261
|
+
if (admission.userDatabase !== undefined && admission.userDatabase !== resolve16(poolPath))
|
|
70262
|
+
throw new Error(`admission.userDatabase must be omitted, or ${resolve16(poolPath)}, for a journal that is not a local SQLite file`);
|
|
70263
|
+
admission.userDatabase = resolve16(poolPath);
|
|
69843
70264
|
}
|
|
69844
70265
|
const sources = localWorkers && await Promise.all(localWorkers.definitions.map(async (source) => ({ ...source, digest: await definitionDigest(source.path) })));
|
|
69845
70266
|
const resources = JSON.parse(JSON.stringify({
|
|
@@ -70445,6 +70866,7 @@ function createTaskPrimitive(runtime) {
|
|
|
70445
70866
|
}
|
|
70446
70867
|
})();
|
|
70447
70868
|
const stageMeta = stage.__modelFallbackMeta();
|
|
70869
|
+
stage.__releaseIfIdle?.();
|
|
70448
70870
|
return {
|
|
70449
70871
|
name,
|
|
70450
70872
|
stageName: name,
|
|
@@ -71243,7 +71665,7 @@ function hasUsableContentBlock(block) {
|
|
|
71243
71665
|
|
|
71244
71666
|
// dist/builtin/workflows/src/shared/stage-session-store.ts
|
|
71245
71667
|
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
71246
|
-
import { dirname as
|
|
71668
|
+
import { dirname as dirname16, resolve as resolve17 } from "node:path";
|
|
71247
71669
|
import {
|
|
71248
71670
|
JsonlSessionStore,
|
|
71249
71671
|
resolveSessionStore,
|
|
@@ -71279,11 +71701,11 @@ async function forkStageSession(store, sessionId, cwd, options, destination = st
|
|
|
71279
71701
|
async function migrateLegacyStageSession(store, sessionId, sessionFile) {
|
|
71280
71702
|
if (sessionFile === undefined || await store.readHeader(sessionId) !== undefined)
|
|
71281
71703
|
return;
|
|
71282
|
-
const location =
|
|
71283
|
-
const legacy = await JsonlSessionStore.open(
|
|
71704
|
+
const location = resolve17(sessionFile);
|
|
71705
|
+
const legacy = await JsonlSessionStore.open(dirname16(location), { exactDirectory: true, scanExisting: false });
|
|
71284
71706
|
try {
|
|
71285
71707
|
for await (const file of legacy.scanFiles()) {
|
|
71286
|
-
if (
|
|
71708
|
+
if (resolve17(file.location) !== location || file.header.id !== sessionId)
|
|
71287
71709
|
continue;
|
|
71288
71710
|
const snapshot = await file.read();
|
|
71289
71711
|
if (await store.readHeader(sessionId) === undefined)
|
|
@@ -74109,6 +74531,8 @@ function createTrackedStageCaller(input) {
|
|
|
74109
74531
|
await runtime.releaseLiveHandle().catch(() => {});
|
|
74110
74532
|
}
|
|
74111
74533
|
runtime.state.sessionCheckpointed = finalizationError === undefined;
|
|
74534
|
+
if (runtime.state.contextUnreachable)
|
|
74535
|
+
runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId);
|
|
74112
74536
|
input.limiter.release();
|
|
74113
74537
|
if (finalizationError !== undefined)
|
|
74114
74538
|
throwFinalizationError(finalizationError.error);
|
|
@@ -74272,7 +74696,8 @@ function createStageContext(input) {
|
|
|
74272
74696
|
recordStageNotice({ kind: "abort", to: "interrupted" });
|
|
74273
74697
|
await innerCtx.abort();
|
|
74274
74698
|
},
|
|
74275
|
-
__modelFallbackMeta: () => innerCtx.__modelFallbackMeta()
|
|
74699
|
+
__modelFallbackMeta: () => innerCtx.__modelFallbackMeta(),
|
|
74700
|
+
__releaseIfIdle: () => runtime.stageRegistry.releaseIdle(runtime.runId, runtime.stageId)
|
|
74276
74701
|
};
|
|
74277
74702
|
}
|
|
74278
74703
|
|
|
@@ -75961,10 +76386,10 @@ function isRetryableSameCandidateFailure(error) {
|
|
|
75961
76386
|
return isTransientExtensionStartupFailure(error);
|
|
75962
76387
|
return isRetryableSameModelFailure(error);
|
|
75963
76388
|
}
|
|
75964
|
-
function mayAdvanceToNextCandidate(error) {
|
|
76389
|
+
function mayAdvanceToNextCandidate(error, options) {
|
|
75965
76390
|
if (isExtensionStartupFailure(error))
|
|
75966
76391
|
return isTransientExtensionStartupFailure(error);
|
|
75967
|
-
return isRetryableModelFailure(error);
|
|
76392
|
+
return isRetryableModelFailure(error, options);
|
|
75968
76393
|
}
|
|
75969
76394
|
function hasMeaningfulUsage(usage) {
|
|
75970
76395
|
if (usage === undefined)
|
|
@@ -76056,6 +76481,7 @@ class StageSessionController {
|
|
|
76056
76481
|
structuredOutputExecutionFailureValue;
|
|
76057
76482
|
structuredOutputCycleAttemptMark;
|
|
76058
76483
|
unsubscribeTerminateWatcher;
|
|
76484
|
+
unbindAbortSignal;
|
|
76059
76485
|
sessionInternalRetries = 0;
|
|
76060
76486
|
unresolvedContextOverflowMessage;
|
|
76061
76487
|
generationSealed = false;
|
|
@@ -76545,6 +76971,8 @@ class StageSessionController {
|
|
|
76545
76971
|
this.pendingListeners.clear();
|
|
76546
76972
|
this.unsubscribeTerminateWatcher?.();
|
|
76547
76973
|
this.unsubscribeTerminateWatcher = undefined;
|
|
76974
|
+
this.unbindAbortSignal?.();
|
|
76975
|
+
this.unbindAbortSignal = undefined;
|
|
76548
76976
|
this.terminatingToolCallIds.clear();
|
|
76549
76977
|
this.messageAdmission.dispose();
|
|
76550
76978
|
this.deliveryActivity.dispose();
|
|
@@ -76639,8 +77067,10 @@ class StageSessionController {
|
|
|
76639
77067
|
};
|
|
76640
77068
|
if (signal.aborted)
|
|
76641
77069
|
onAbort();
|
|
76642
|
-
else
|
|
77070
|
+
else {
|
|
76643
77071
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
77072
|
+
this.unbindAbortSignal = () => signal.removeEventListener("abort", onAbort);
|
|
77073
|
+
}
|
|
76644
77074
|
}
|
|
76645
77075
|
markAbort(reason) {
|
|
76646
77076
|
this.abortGeneration += 1;
|
|
@@ -76667,6 +77097,9 @@ class StageSessionController {
|
|
|
76667
77097
|
state.controller.abort(reason);
|
|
76668
77098
|
this.thrownErrorRetryStates.clear();
|
|
76669
77099
|
}
|
|
77100
|
+
fallbackFailureOptions() {
|
|
77101
|
+
return { fallbackOnContentFilter: this.retrySettings()?.fallbackOnContentFilter !== false };
|
|
77102
|
+
}
|
|
76670
77103
|
retrySettings() {
|
|
76671
77104
|
const managers = [
|
|
76672
77105
|
this.sessionSettingsManager,
|
|
@@ -76941,7 +77374,7 @@ class StageSessionController {
|
|
|
76941
77374
|
const errorSettingsManager = retrySettingsManagerFromError(error);
|
|
76942
77375
|
if (errorSettingsManager !== undefined)
|
|
76943
77376
|
this.sessionSettingsManager = errorSettingsManager;
|
|
76944
|
-
const retryableFailure = isRetryableModelFailure(error);
|
|
77377
|
+
const retryableFailure = isRetryableModelFailure(error, this.fallbackFailureOptions());
|
|
76945
77378
|
const sameCandidateRetryable = isRetryableSameModelFailure(error) && !isUnresolvedContextOverflowFailure(error);
|
|
76946
77379
|
recordProviderRateLimit(this.currentProvider(), error, modelIdForModel(this.currentModelValue()));
|
|
76947
77380
|
if (this.hasExplicitModelFallbackConfig && isProviderRateLimit(error)) {
|
|
@@ -77566,7 +77999,7 @@ class StageSessionController {
|
|
|
77566
77999
|
}
|
|
77567
78000
|
throw new WorkflowPromptModelFailure(terminalFailure);
|
|
77568
78001
|
} catch (err) {
|
|
77569
|
-
if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
|
|
78002
|
+
if (this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
|
|
77570
78003
|
this.artifactCapture.settleAttempt(true);
|
|
77571
78004
|
const usage = this.takeAttemptUsage(resumedSession);
|
|
77572
78005
|
this.modelAttempts.push({
|
|
@@ -77588,7 +78021,7 @@ class StageSessionController {
|
|
|
77588
78021
|
...usage === undefined ? {} : { usage },
|
|
77589
78022
|
error: message
|
|
77590
78023
|
});
|
|
77591
|
-
if (this.opts.signal?.aborted || !isRetryableModelFailure(err)) {
|
|
78024
|
+
if (this.opts.signal?.aborted || !isRetryableModelFailure(err, this.fallbackFailureOptions())) {
|
|
77592
78025
|
this.modelWarnings.push(...this.pendingFallbackWarnings);
|
|
77593
78026
|
this.pendingFallbackWarnings.length = 0;
|
|
77594
78027
|
this.notifyModelFallbackMetaChange();
|
|
@@ -77637,7 +78070,7 @@ class StageSessionController {
|
|
|
77637
78070
|
throw err;
|
|
77638
78071
|
const message = errorMessage3(err);
|
|
77639
78072
|
const terminalStageDelivery = isWorkflowPendingStageDeliveryFailure(err);
|
|
77640
|
-
if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err)) {
|
|
78073
|
+
if (!terminalStageDelivery && this.capturedStructuredOutputForAttempt() && isRetryableModelFailure(err, this.fallbackFailureOptions())) {
|
|
77641
78074
|
this.recordSuccessfulAttempt(candidate);
|
|
77642
78075
|
return "handled";
|
|
77643
78076
|
}
|
|
@@ -77654,7 +78087,7 @@ class StageSessionController {
|
|
|
77654
78087
|
if (walk !== undefined) {
|
|
77655
78088
|
this.recordCandidateFailure(walk, index, err, candidates);
|
|
77656
78089
|
nextIndex = undefined;
|
|
77657
|
-
if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err)) {
|
|
78090
|
+
if (!this.opts.signal?.aborted && !this.startupWait.signal.aborted && !terminalStageDelivery && mayAdvanceToNextCandidate(err, this.fallbackFailureOptions())) {
|
|
77658
78091
|
try {
|
|
77659
78092
|
nextIndex = await this.selectReadyCandidate(candidates, walk, index + 1);
|
|
77660
78093
|
} catch (error) {
|
|
@@ -77667,7 +78100,7 @@ class StageSessionController {
|
|
|
77667
78100
|
}
|
|
77668
78101
|
}
|
|
77669
78102
|
}
|
|
77670
|
-
if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err) || nextIndex === undefined) {
|
|
78103
|
+
if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !mayAdvanceToNextCandidate(err, this.fallbackFailureOptions()) || nextIndex === undefined) {
|
|
77671
78104
|
await this.settleFailedCandidate();
|
|
77672
78105
|
return "throw";
|
|
77673
78106
|
}
|
|
@@ -77762,7 +78195,7 @@ var init_stage_runner_controller = __esm(() => {
|
|
|
77762
78195
|
// dist/builtin/workflows/src/runs/foreground/stage-runner-output.ts
|
|
77763
78196
|
import { createHash as createHash6 } from "node:crypto";
|
|
77764
78197
|
import { mkdir as mkdir7, writeFile as writeFile10 } from "node:fs/promises";
|
|
77765
|
-
import { basename as basename6, dirname as
|
|
78198
|
+
import { basename as basename6, dirname as dirname17, isAbsolute as isAbsolute11, join as join32, resolve as resolve18 } from "node:path";
|
|
77766
78199
|
function normalizeMaxOutput2(maxOutput) {
|
|
77767
78200
|
return {
|
|
77768
78201
|
bytes: maxOutput?.bytes ?? DEFAULT_MAX_OUTPUT_BYTES,
|
|
@@ -77825,7 +78258,7 @@ function formatByteSize(bytes) {
|
|
|
77825
78258
|
}
|
|
77826
78259
|
function transcriptPath(runId, outputPath) {
|
|
77827
78260
|
const digest = createHash6("sha256").update(outputPath).digest("hex").slice(0, 16);
|
|
77828
|
-
return
|
|
78261
|
+
return join32(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename6(outputPath)}.transcript.md`);
|
|
77829
78262
|
}
|
|
77830
78263
|
function appendContent(lines, content) {
|
|
77831
78264
|
if (typeof content === "string") {
|
|
@@ -77870,7 +78303,7 @@ function renderTranscript(messages, fallbackOutput) {
|
|
|
77870
78303
|
`);
|
|
77871
78304
|
}
|
|
77872
78305
|
function savedOutputReference(outputPath, fullOutput, transcriptPathValue, transcriptText, transcriptAvailable, warning) {
|
|
77873
|
-
const absolutePath =
|
|
78306
|
+
const absolutePath = resolve18(outputPath);
|
|
77874
78307
|
const bytes = Buffer.byteLength(fullOutput, "utf8");
|
|
77875
78308
|
const lines = countLines(fullOutput);
|
|
77876
78309
|
const transcriptBytes = Buffer.byteLength(transcriptText, "utf8");
|
|
@@ -77885,8 +78318,8 @@ function resolveOutputPath(output, runtimeCwd, requestedCwd) {
|
|
|
77885
78318
|
return;
|
|
77886
78319
|
if (isAbsolute11(output))
|
|
77887
78320
|
return output;
|
|
77888
|
-
const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd :
|
|
77889
|
-
return
|
|
78321
|
+
const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve18(runtimeCwd, requestedCwd);
|
|
78322
|
+
return resolve18(baseCwd, output);
|
|
77890
78323
|
}
|
|
77891
78324
|
function degenerateWarning(fullOutput) {
|
|
77892
78325
|
return fullOutput.trim().length === 0 ? "WARNING: the stage artifact is empty; search the companion transcript for this stage's work." : undefined;
|
|
@@ -77945,7 +78378,7 @@ async function finalizePromptOutput(fullOutput, outputOptions, runtimeCwd, runId
|
|
|
77945
78378
|
const transcriptFile = transcriptPath(runId, outputPath);
|
|
77946
78379
|
const transcript = renderTranscript(messages, fullOutput);
|
|
77947
78380
|
try {
|
|
77948
|
-
await mkdir7(
|
|
78381
|
+
await mkdir7(dirname17(outputPath), { recursive: true });
|
|
77949
78382
|
await writeFile10(outputPath, fullOutput, "utf8");
|
|
77950
78383
|
} catch (err) {
|
|
77951
78384
|
return `${displayOutput}
|
|
@@ -77957,7 +78390,7 @@ ${err instanceof Error ? err.message : String(err)}`;
|
|
|
77957
78390
|
let transcriptError;
|
|
77958
78391
|
try {
|
|
77959
78392
|
await ensureWorkflowArtifactRunDirectory(runId);
|
|
77960
|
-
await mkdir7(
|
|
78393
|
+
await mkdir7(dirname17(transcriptFile), { recursive: true });
|
|
77961
78394
|
await writeFile10(transcriptFile, transcript, "utf8");
|
|
77962
78395
|
transcriptAvailable = true;
|
|
77963
78396
|
} catch (err) {
|
|
@@ -78468,7 +78901,8 @@ function createWorkflowStageFactory(input) {
|
|
|
78468
78901
|
stageFinalized: false,
|
|
78469
78902
|
sessionCheckpointed: false,
|
|
78470
78903
|
skippedForParallelFailFast: false,
|
|
78471
|
-
stageControlDropped: false
|
|
78904
|
+
stageControlDropped: false,
|
|
78905
|
+
contextUnreachable: false
|
|
78472
78906
|
};
|
|
78473
78907
|
const activeAskUserQuestionCalls = new Set;
|
|
78474
78908
|
const hasActiveAskUserQuestion = () => activeAskUserQuestionCalls.size > 0 || state.activeAskUserQuestionAnonymousCalls > 0;
|
|
@@ -78714,9 +79148,18 @@ function createWorkflowStageFactory(input) {
|
|
|
78714
79148
|
hasContinuation: input.opts.continuation !== undefined,
|
|
78715
79149
|
hasScopedParents: stageFailFastScope?.parentIds !== undefined
|
|
78716
79150
|
});
|
|
78717
|
-
|
|
79151
|
+
const context = createStageContext({ runtime, runTrackedStageCall });
|
|
79152
|
+
unreachableStageContexts.register(context, releaseWhenUnreachable(state, input.stageRegistry, input.runId, stageId));
|
|
79153
|
+
return context;
|
|
79154
|
+
};
|
|
79155
|
+
}
|
|
79156
|
+
function releaseWhenUnreachable(state, registry, runId, stageId) {
|
|
79157
|
+
return () => {
|
|
79158
|
+
state.contextUnreachable = true;
|
|
79159
|
+
registry.releaseIdle(runId, stageId);
|
|
78718
79160
|
};
|
|
78719
79161
|
}
|
|
79162
|
+
var unreachableStageContexts;
|
|
78720
79163
|
var init_executor_stage_factory = __esm(() => {
|
|
78721
79164
|
init_intercom_group();
|
|
78722
79165
|
init_pending_stage_route_readiness();
|
|
@@ -78731,6 +79174,7 @@ var init_executor_stage_factory = __esm(() => {
|
|
|
78731
79174
|
init_pending_stage_delivery2();
|
|
78732
79175
|
init_stage_runner();
|
|
78733
79176
|
init_stage_runner_session();
|
|
79177
|
+
unreachableStageContexts = new FinalizationRegistry((release) => release());
|
|
78734
79178
|
});
|
|
78735
79179
|
|
|
78736
79180
|
// dist/builtin/workflows/src/engine/runtime.ts
|
|
@@ -79072,7 +79516,7 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
79072
79516
|
const ownsCancellationRegistration = opts.signal === undefined && opts.cancellation !== undefined;
|
|
79073
79517
|
const tracker = new GraphFrontierTracker;
|
|
79074
79518
|
const inputConcurrency = resolveInputConcurrency(def.inputs, resolvedInputs);
|
|
79075
|
-
const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache);
|
|
79519
|
+
const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs), gitWorktreeSetupCacheOwner = createGitWorktreeSetupCacheOwner(opts.gitWorktreeSetupCache, runId);
|
|
79076
79520
|
const gitWorktreeSetupCache = gitWorktreeSetupCacheOwner.cache;
|
|
79077
79521
|
const workflowInvocationCwd = opts.cwd ?? process.cwd();
|
|
79078
79522
|
let workflowCwd;
|