@bastani/atomic 0.9.54 → 0.9.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +14 -0
  3. package/dist/builtin/intercom/README.md +2 -1
  4. package/dist/builtin/intercom/broker/announce-on-import.ts +5 -0
  5. package/dist/builtin/intercom/broker/broker.ts +28 -0
  6. package/dist/builtin/intercom/broker/client.ts +48 -3
  7. package/dist/builtin/intercom/broker/paths.ts +9 -0
  8. package/dist/builtin/intercom/broker/socket-writes.ts +5 -0
  9. package/dist/builtin/intercom/broker/spawn.ts +58 -6
  10. package/dist/builtin/intercom/broker/start-announcement.ts +77 -0
  11. package/dist/builtin/intercom/broker/startup-timeout.ts +23 -0
  12. package/dist/builtin/intercom/index.bundle.mjs +184 -73
  13. package/dist/builtin/intercom/package.json +1 -1
  14. package/dist/builtin/intercom/recoverable-disconnect.ts +38 -2
  15. package/dist/builtin/mcp/package.json +1 -1
  16. package/dist/builtin/subagents/package.json +1 -1
  17. package/dist/builtin/web-access/package.json +1 -1
  18. package/dist/builtin/workflows/CHANGELOG.md +26 -0
  19. package/dist/builtin/workflows/package.json +1 -1
  20. package/dist/builtin/workflows/src/durable/journal/resolution.d.ts +7 -0
  21. package/dist/builtin/workflows/src/extension/index.bundle.mjs +8458 -7874
  22. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +687 -111
  23. package/dist/builtin/workflows/src/index.js +834 -264
  24. package/dist/builtin/workflows/src/local-worker-entry.mjs +687 -111
  25. package/dist/builtin/workflows/src/workers/public-options.d.ts +8 -0
  26. package/dist/core/extension-startup-failure.d.ts.map +1 -1
  27. package/dist/core/extension-startup-failure.js +1 -0
  28. package/dist/core/extension-startup-failure.js.map +1 -1
  29. package/dist/core/storage/session/jsonl-session-store.d.ts +27 -0
  30. package/dist/core/storage/session/jsonl-session-store.d.ts.map +1 -1
  31. package/dist/core/storage/session/jsonl-session-store.js +99 -7
  32. package/dist/core/storage/session/jsonl-session-store.js.map +1 -1
  33. package/docs/settings.md +2 -2
  34. package/docs/storage.md +2 -0
  35. package/docs/workflows/api-reference.md +3 -3
  36. package/docs/workflows/operations.md +3 -3
  37. package/npm-shrinkwrap.json +32 -32
  38. package/package.json +3 -3
@@ -1996,10 +1996,16 @@ function selectRunJournal(options = {}) {
1996
1996
  async function resolveRunJournal(options = {}) {
1997
1997
  return openSelectedRunJournal(selectRunJournal(options), options.agentDir);
1998
1998
  }
1999
+ function runJournalOrigin(journal) {
2000
+ return journalOrigins.get(journal);
2001
+ }
1999
2002
  async function openSelectedRunJournal(selection, agentDir = getAgentDir()) {
2000
2003
  if ("createRun" in selection)
2001
2004
  return selection;
2002
- return withRunJournalConfigSource(selection, () => provider.openRunJournal(selection, { agentDir, domain: "journal" }));
2005
+ const journal = await withRunJournalConfigSource(selection, () => provider.openRunJournal(selection, { agentDir, domain: "journal" }));
2006
+ if (!journalOrigins.has(journal))
2007
+ journalOrigins.set(journal, { selection, agentDir });
2008
+ return journal;
2003
2009
  }
2004
2010
  async function withRunJournalConfigSource(selection, open) {
2005
2011
  if ("createRun" in selection)
@@ -2017,7 +2023,7 @@ async function withRunJournalConfigSource(selection, open) {
2017
2023
  throw error;
2018
2024
  }
2019
2025
  }
2020
- var hostModules, provider, origins;
2026
+ var hostModules, provider, origins, journalOrigins;
2021
2027
  var init_resolution = __esm(() => {
2022
2028
  init_memory_run_journal();
2023
2029
  init_sql_run_journal();
@@ -2030,6 +2036,7 @@ var init_resolution = __esm(() => {
2030
2036
  }
2031
2037
  });
2032
2038
  origins = new WeakMap;
2039
+ journalOrigins = new WeakMap;
2033
2040
  });
2034
2041
 
2035
2042
  // dist/builtin/workflows/src/durable/journal/sqlite-run-journal.ts
@@ -16762,9 +16769,126 @@ var init_possible_stages = __esm(() => {
16762
16769
  TRACKED_NODE_METHODS = new Set(["stage", "task", "chain", "parallel", "workflow", "tool"]);
16763
16770
  });
16764
16771
 
16772
+ // dist/builtin/workflows/src/workers/pool-journal.ts
16773
+ import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
16774
+ import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
16775
+ import { basename as basename5, dirname as dirname9, join as join12, resolve as resolve9 } from "node:path";
16776
+ import { storageSelectionKey as storageSelectionKey2 } from "@bastani/atomic/storage";
16777
+ function encodeOption(value2) {
16778
+ if (typeof value2 === "bigint")
16779
+ return { $bigint: value2.toString() };
16780
+ if (value2 instanceof Uint8Array)
16781
+ return { $bytes: Buffer.from(value2).toString("base64") };
16782
+ return value2;
16783
+ }
16784
+ function decodeOption(value2) {
16785
+ if (value2 !== null && typeof value2 === "object") {
16786
+ if ("$bigint" in value2)
16787
+ return BigInt(value2.$bigint);
16788
+ return new Uint8Array(Buffer.from(value2.$bytes, "base64"));
16789
+ }
16790
+ return value2;
16791
+ }
16792
+ function isReopenableSelection(selection) {
16793
+ return selection.kind === "sqlite" || selection.kind === "adapter";
16794
+ }
16795
+ function encodeSelection(selection) {
16796
+ if (selection.kind === "sqlite")
16797
+ return JSON.stringify({ ...selection, path: resolve9(selection.path) });
16798
+ return JSON.stringify({
16799
+ ...selection,
16800
+ ...selection.options === undefined ? {} : {
16801
+ options: Object.fromEntries(Object.entries(selection.options).map(([key, value2]) => [key, encodeOption(value2)]))
16802
+ }
16803
+ });
16804
+ }
16805
+ function decodeSelection(text) {
16806
+ const value2 = JSON.parse(text);
16807
+ if (value2.kind === "sqlite" || value2.options === undefined)
16808
+ return value2;
16809
+ return {
16810
+ ...value2,
16811
+ options: Object.fromEntries(Object.entries(value2.options).map(([key, option]) => [key, decodeOption(option)]))
16812
+ };
16813
+ }
16814
+ function isLocalPoolJournal(journal) {
16815
+ return journal instanceof SqlRunJournal && journal.descriptor.adapter === "node-sqlite" && journal.path !== ":memory:" && sqlPoolStorage(journal)?.tables.runs === "wf_runs";
16816
+ }
16817
+ function poolDurableJournal(journal) {
16818
+ const origin = runJournalOrigin(journal);
16819
+ if (origin === undefined)
16820
+ throw new Error("Local workers cannot reopen a journal passed as an object; select the journal with workflows.journal, --storage or ATOMIC_WORKFLOWS_JOURNAL so every worker process can open it");
16821
+ if (!isReopenableSelection(origin.selection))
16822
+ throw new Error(`Local workers need a journal their processes can open by selection, a SQLite file or a storage adapter, not ${origin.selection.kind}`);
16823
+ return { selection: encodeSelection(origin.selection), agentDir: origin.agentDir };
16824
+ }
16825
+ function openDurableJournal(durable) {
16826
+ return openSelectedRunJournal(decodeSelection(durable.selection), durable.agentDir);
16827
+ }
16828
+ function poolStateDirectory(agentDir) {
16829
+ return join12(dirname9(agentDir), "workflows", "pool");
16830
+ }
16831
+ function databaseIdentity(selection, agentDir) {
16832
+ return storageSelectionKey2(selection.kind === "adapter" ? { ...selection, secrets: undefined } : selection, agentDir);
16833
+ }
16834
+ function coordinationPath(durable) {
16835
+ const selection = decodeSelection(durable.selection);
16836
+ const identity = createHash3("sha256").update(databaseIdentity(selection, durable.agentDir)).digest("hex");
16837
+ return join12(poolStateDirectory(durable.agentDir), `${identity.slice(0, 24)}.sqlite`);
16838
+ }
16839
+ function coordinationDatabase(durable) {
16840
+ return basename5(coordinationPath(durable), ".sqlite");
16841
+ }
16842
+ function openCoordinationJournal(path) {
16843
+ const file = resolve9(path);
16844
+ let opened = coordinationJournals.get(file);
16845
+ if (opened === undefined) {
16846
+ mkdirSync5(dirname9(file), { recursive: true });
16847
+ opened = resolveRunJournal({ journal: { path: file } });
16848
+ coordinationJournals.set(file, opened);
16849
+ opened.catch(() => {
16850
+ if (coordinationJournals.get(file) === opened)
16851
+ coordinationJournals.delete(file);
16852
+ });
16853
+ }
16854
+ return opened;
16855
+ }
16856
+ function registerPoolJournal(durable, coordination) {
16857
+ coordinations.set(durable, coordination);
16858
+ }
16859
+ function poolJournalFor(journal) {
16860
+ return coordinations.get(journal) ?? journal;
16861
+ }
16862
+ function poolHostId(agentDir) {
16863
+ const file = join12(poolStateDirectory(agentDir), "host-id");
16864
+ try {
16865
+ const existing = readFileSync2(file, "utf8").trim();
16866
+ if (existing !== "")
16867
+ return existing;
16868
+ } catch {}
16869
+ mkdirSync5(dirname9(file), { recursive: true });
16870
+ const id = randomUUID6();
16871
+ try {
16872
+ writeFileSync3(file, `${id}
16873
+ `, { flag: "wx" });
16874
+ return id;
16875
+ } catch {
16876
+ return readFileSync2(file, "utf8").trim();
16877
+ }
16878
+ }
16879
+ var POOL_DURABLE_JOURNAL_ENV = "ATOMIC_POOL_DURABLE_JOURNAL", coordinationJournals, coordinations;
16880
+ var init_pool_journal = __esm(() => {
16881
+ init_internal();
16882
+ init_workflows_host_module();
16883
+ init_resolution();
16884
+ init_sql_run_journal();
16885
+ coordinationJournals = new Map;
16886
+ coordinations = new WeakMap;
16887
+ });
16888
+
16765
16889
  // dist/builtin/workflows/src/workers/admission-host.ts
16766
16890
  import { execFile, execFileSync } from "node:child_process";
16767
- import { readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
16891
+ import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
16768
16892
  import { readFile } from "node:fs/promises";
16769
16893
  import { hostname } from "node:os";
16770
16894
  function admissionBootIdentity() {
@@ -16805,7 +16929,7 @@ function scanProcessGroup(group) {
16805
16929
  continue;
16806
16930
  let stat;
16807
16931
  try {
16808
- stat = readFileSync2(`/proc/${entry}/stat`, "utf8");
16932
+ stat = readFileSync3(`/proc/${entry}/stat`, "utf8");
16809
16933
  } catch {
16810
16934
  complete = false;
16811
16935
  continue;
@@ -16869,7 +16993,7 @@ var init_admission_host = __esm(() => {
16869
16993
  });
16870
16994
 
16871
16995
  // dist/builtin/workflows/src/workers/resource-admission.ts
16872
- import { randomUUID as randomUUID6 } from "node:crypto";
16996
+ import { randomUUID as randomUUID7 } from "node:crypto";
16873
16997
  import { realpath } from "node:fs/promises";
16874
16998
  import { cpus, freemem, loadavg } from "node:os";
16875
16999
  import { setTimeout as delay } from "node:timers/promises";
@@ -16884,7 +17008,7 @@ class SqlResourceAdmission {
16884
17008
  permits;
16885
17009
  configuration;
16886
17010
  owners;
16887
- owner = randomUUID6();
17011
+ owner = randomUUID7();
16888
17012
  nextReconciliation = 0;
16889
17013
  constructor(storage, options) {
16890
17014
  this.storage = storage;
@@ -16991,7 +17115,7 @@ class SqlResourceAdmission {
16991
17115
  }
16992
17116
  async acquire(kind, signal, request) {
16993
17117
  signal?.throwIfAborted();
16994
- const operation = randomUUID6();
17118
+ const operation = randomUUID7();
16995
17119
  const release = (reason = "resource cleanup confirmed") => this.storage.transaction(async (tx) => {
16996
17120
  await tx.run(`UPDATE ${this.permits} SET state = 'released', reason = ? WHERE operation = ? AND state != 'released'`, reason, operation);
16997
17121
  });
@@ -17214,7 +17338,7 @@ var init_resource_admission = __esm(() => {
17214
17338
  });
17215
17339
 
17216
17340
  // dist/builtin/workflows/src/workers/admission-binding.ts
17217
- import { randomUUID as randomUUID7 } from "node:crypto";
17341
+ import { randomUUID as randomUUID8 } from "node:crypto";
17218
17342
  import { withResourceAdmission } from "@bastani/atomic";
17219
17343
 
17220
17344
  class SessionCapacitySlot {
@@ -17289,10 +17413,10 @@ async function admitWorkflowSessions(backend, opts, callback) {
17289
17413
  return callback(opts);
17290
17414
  if (!(rootBackend instanceof JournalDurableBackend))
17291
17415
  throw new Error("Resource admission requires a journal backend");
17292
- const admission = await SqlResourceAdmission.open(rootBackend.journal, {
17416
+ const admission = await SqlResourceAdmission.open(poolJournalFor(rootBackend.journal), {
17293
17417
  ...config,
17294
17418
  root: opts.parentRun?.rootRunId ?? opts.runId,
17295
- holder: randomUUID7()
17419
+ holder: randomUUID8()
17296
17420
  });
17297
17421
  return withResourceAdmission(admission, () => callback({
17298
17422
  ...opts,
@@ -17307,6 +17431,7 @@ var init_admission_binding = __esm(() => {
17307
17431
  init_journal_backend();
17308
17432
  init_wiring();
17309
17433
  init_stage_runner_session_options();
17434
+ init_pool_journal();
17310
17435
  init_resource_admission();
17311
17436
  workflowResourceAdmission = new WeakMap;
17312
17437
  });
@@ -53509,12 +53634,12 @@ var init_verification_prompts = __esm(() => {
53509
53634
  });
53510
53635
 
53511
53636
  // dist/builtin/workflows/builtin/pattern-artifact-root.ts
53512
- import { randomUUID as randomUUID8 } from "node:crypto";
53637
+ import { randomUUID as randomUUID9 } from "node:crypto";
53513
53638
  import { mkdir as mkdir2 } from "node:fs/promises";
53514
- import { join as join12 } from "node:path";
53639
+ import { join as join13 } from "node:path";
53515
53640
  async function stableArtifactRoot(ctx, workflowName) {
53516
53641
  const cwd = ctx.cwd ?? process.cwd();
53517
- const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join12(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID8()}`));
53642
+ const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join13(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
53518
53643
  await mkdir2(artifactDir, { recursive: true });
53519
53644
  return artifactDir;
53520
53645
  }
@@ -53554,7 +53679,7 @@ function fold_usage(results) {
53554
53679
 
53555
53680
  // dist/builtin/workflows/builtin/adversarial-verification-runner.ts
53556
53681
  import { readFile as readFile2, writeFile } from "node:fs/promises";
53557
- import { join as join13 } from "node:path";
53682
+ import { join as join14 } from "node:path";
53558
53683
  import { Type as Type4 } from "typebox";
53559
53684
  function isRecord3(value2) {
53560
53685
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -53649,8 +53774,8 @@ async function writeInvalid(path, stage) {
53649
53774
  }
53650
53775
  async function runAdversarialVerification(ctx) {
53651
53776
  const root = await stableArtifactRoot(ctx, "adversarial-verification");
53652
- const criteriaPath = join13(root, "criteria.md");
53653
- const candidatePath = join13(root, "candidate.md");
53777
+ const criteriaPath = join14(root, "criteria.md");
53778
+ const candidatePath = join14(root, "candidate.md");
53654
53779
  const resolvedCriteria = resolveCriteria(ctx.inputs.criteria);
53655
53780
  await writeFile(criteriaPath, renderCriteriaMarkdown(resolvedCriteria));
53656
53781
  await ctx.task("worker", { prompt: renderWorkerPrompt(ctx.inputs.task), context: "fresh", output: candidatePath, outputMode: "file-only" });
@@ -53682,7 +53807,7 @@ async function runAdversarialVerification(ctx) {
53682
53807
  criterion,
53683
53808
  verifierIndex: index + 1,
53684
53809
  name,
53685
- artifactPath: join13(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
53810
+ artifactPath: join14(root, `verification-${round}-${criterion.id}-${index + 1}.json`)
53686
53811
  });
53687
53812
  }
53688
53813
  }
@@ -53735,8 +53860,8 @@ async function runAdversarialVerification(ctx) {
53735
53860
  const decision = decide_verification(roundResult, { acceptMean, quorumFraction: QUORUM_FRACTION });
53736
53861
  finalDecision = decision;
53737
53862
  finalMean = meanScore(scoreReports);
53738
- scoreTablePath = join13(root, `verification-summary-${round}.json`);
53739
- reviewReportPath = join13(root, `review-${round}.json`);
53863
+ scoreTablePath = join14(root, `verification-summary-${round}.json`);
53864
+ reviewReportPath = join14(root, `review-${round}.json`);
53740
53865
  const summary = {
53741
53866
  scores: scoreReports,
53742
53867
  mean: finalMean,
@@ -53917,7 +54042,7 @@ var GROUNDED_REPORTING2 = "Before reporting progress, audit each claim against a
53917
54042
 
53918
54043
  // dist/builtin/workflows/builtin/classify-and-act-runner.ts
53919
54044
  import { writeFile as writeFile2 } from "node:fs/promises";
53920
- import { join as join14 } from "node:path";
54045
+ import { join as join15 } from "node:path";
53921
54046
  import { Type as Type6 } from "typebox";
53922
54047
  function safeName(value2) {
53923
54048
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -53957,7 +54082,7 @@ async function runClassifyAndAct(ctx) {
53957
54082
  const needsFallback = exactCategory === undefined || confidence < ctx.inputs.confidence_threshold;
53958
54083
  const fallback = needsFallback ? await resolveFallbackCategory(ctx, exactCategory) : undefined;
53959
54084
  const category = fallback?.category ?? exactCategory;
53960
- const classificationPath = join14(artifactDir, "classification.json");
54085
+ const classificationPath = join15(artifactDir, "classification.json");
53961
54086
  await writeFile2(classificationPath, JSON.stringify({
53962
54087
  proposed_category: proposedCategory,
53963
54088
  selected_category: category,
@@ -53967,7 +54092,7 @@ async function runClassifyAndAct(ctx) {
53967
54092
  fallback_used: needsFallback,
53968
54093
  fallback_mode: fallback?.fallbackMode ?? "none"
53969
54094
  }, null, 2));
53970
- const actionPath = join14(artifactDir, `action-${safeName(category)}.md`);
54095
+ const actionPath = join15(artifactDir, `action-${safeName(category)}.md`);
53971
54096
  const action = await ctx.task(`action-${safeName(category)}`, {
53972
54097
  tools: actionTools(category),
53973
54098
  prompt: actionPrompt({ prompt: ctx.inputs.prompt, category, classificationPath }),
@@ -54107,7 +54232,7 @@ var GROUNDED_REPORTING3 = "Before reporting progress, audit each claim against a
54107
54232
 
54108
54233
  // dist/builtin/workflows/builtin/fan-out-and-synthesize-runner.ts
54109
54234
  import { writeFile as writeFile3 } from "node:fs/promises";
54110
- import { join as join15 } from "node:path";
54235
+ import { join as join16 } from "node:path";
54111
54236
  import { Type as Type8 } from "typebox";
54112
54237
  function safeName2(value2, index) {
54113
54238
  const normalized = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -54138,9 +54263,9 @@ async function runFanOutAndSynthesize(ctx) {
54138
54263
  context: "fresh"
54139
54264
  });
54140
54265
  const partitions = parsedPartitions(plan.structured, ctx.inputs.max_branches, ctx.inputs.prompt);
54141
- const partitionPath = join15(artifactDir, "partition-plan.json");
54266
+ const partitionPath = join16(artifactDir, "partition-plan.json");
54142
54267
  await writeFile3(partitionPath, JSON.stringify({ task: ctx.inputs.prompt, partitions }, null, 2));
54143
- const branchPaths = partitions.map((partition, index) => join15(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
54268
+ const branchPaths = partitions.map((partition, index) => join16(artifactDir, `branch-${safeName2(partition.label, index)}.md`));
54144
54269
  const steps = partitions.map((partition, index) => ({
54145
54270
  name: `branch-${safeName2(partition.label, index)}`,
54146
54271
  prompt: branchPrompt({ prompt: ctx.inputs.prompt, ...partition }),
@@ -54150,13 +54275,13 @@ async function runFanOutAndSynthesize(ctx) {
54150
54275
  outputMode: "file-only"
54151
54276
  }));
54152
54277
  await ctx.parallel(steps, { concurrency: Math.min(ctx.inputs.max_concurrency, partitions.length), failFast: false });
54153
- const manifestPath = join15(artifactDir, "manifest.json");
54278
+ const manifestPath = join16(artifactDir, "manifest.json");
54154
54279
  await writeFile3(manifestPath, JSON.stringify({
54155
54280
  task: ctx.inputs.prompt,
54156
54281
  partition_plan: partitionPath,
54157
54282
  branches: partitions.map((partition, index) => ({ ...partition, artifact_path: branchPaths[index] }))
54158
54283
  }, null, 2));
54159
- const synthesisPath = join15(artifactDir, "synthesis.md");
54284
+ const synthesisPath = join16(artifactDir, "synthesis.md");
54160
54285
  const synthesis = await ctx.task("synthesize", {
54161
54286
  prompt: synthesisPrompt(ctx.inputs.prompt, manifestPath),
54162
54287
  context: "fresh",
@@ -54321,7 +54446,7 @@ var init_generate_and_filter_prompts = __esm(() => {
54321
54446
 
54322
54447
  // dist/builtin/workflows/builtin/generate-and-filter-runner.ts
54323
54448
  import { readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
54324
- import { join as join16 } from "node:path";
54449
+ import { join as join17 } from "node:path";
54325
54450
  import { Type as Type10 } from "typebox";
54326
54451
  function isRecord4(value2) {
54327
54452
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
@@ -54340,7 +54465,7 @@ function judgeDecision(value2) {
54340
54465
  }
54341
54466
  async function runGenerateAndFilter(ctx) {
54342
54467
  const root = await stableArtifactRoot(ctx, "generate-and-filter");
54343
- const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join16(root, `candidate-${index + 1}.md`));
54468
+ const candidatePaths = Array.from({ length: ctx.inputs.num_candidates }, (_, index) => join17(root, `candidate-${index + 1}.md`));
54344
54469
  const shortlistLimit = Math.min(ctx.inputs.shortlist_size, ctx.inputs.num_candidates);
54345
54470
  await ctx.parallel(candidatePaths.map((path, index) => ({
54346
54471
  name: `generate-${index + 1}`,
@@ -54349,9 +54474,9 @@ async function runGenerateAndFilter(ctx) {
54349
54474
  output: path,
54350
54475
  outputMode: "file-only"
54351
54476
  })), { concurrency: ctx.inputs.max_concurrency, failFast: false });
54352
- const manifestPath = join16(root, "manifest.json");
54477
+ const manifestPath = join17(root, "manifest.json");
54353
54478
  await writeFile4(manifestPath, JSON.stringify({ task: ctx.inputs.prompt, candidate_artifact_paths: candidatePaths }, null, 2));
54354
- const filterPath = join16(root, "filter.json");
54479
+ const filterPath = join17(root, "filter.json");
54355
54480
  const filtered = await ctx.task("dedupe-and-filter", {
54356
54481
  prompt: renderFilterPrompt(ctx.inputs.prompt, candidatePaths, shortlistLimit),
54357
54482
  context: "fresh",
@@ -54368,7 +54493,7 @@ async function runGenerateAndFilter(ctx) {
54368
54493
  let judgePath = null;
54369
54494
  let decisionPath = filterPath;
54370
54495
  if (ctx.inputs.use_judge) {
54371
- judgePath = join16(root, "judge.json");
54496
+ judgePath = join17(root, "judge.json");
54372
54497
  const judgeCandidates = await Promise.all(shortlist.map(async (path) => ({ path, body: await readFile3(path, "utf8") })));
54373
54498
  const judgePrompt = renderJudgePrompt(ctx.inputs.prompt, filterPath, shortlistLimit, judgeCandidates);
54374
54499
  const judged = await ctx.task("judge", {
@@ -54384,7 +54509,7 @@ async function runGenerateAndFilter(ctx) {
54384
54509
  shortlist = judgedShortlist.length > 0 ? judgedShortlist : shortlist;
54385
54510
  decisionPath = judgePath;
54386
54511
  }
54387
- const finalPath = join16(root, "shortlist.md");
54512
+ const finalPath = join17(root, "shortlist.md");
54388
54513
  const finalShortlist = await ctx.task("final-shortlist", {
54389
54514
  prompt: renderFinalShortlistPrompt(ctx.inputs.prompt, decisionPath),
54390
54515
  context: "fresh",
@@ -54913,7 +55038,7 @@ var init_review_convergence = __esm(() => {
54913
55038
 
54914
55039
  // dist/builtin/workflows/builtin/goal-artifacts.ts
54915
55040
  import { writeFile as writeFile5 } from "node:fs/promises";
54916
- import { join as join17 } from "node:path";
55041
+ import { join as join18 } from "node:path";
54917
55042
  function artifactSafeName(value2) {
54918
55043
  const safe = value2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
54919
55044
  return safe.length > 0 ? safe : "artifact";
@@ -54924,7 +55049,7 @@ function withoutTurn(value2) {
54924
55049
  return copy;
54925
55050
  }
54926
55051
  async function writeReviewArtifact(artifactDir, reviewer, decision, rawText, convergenceDecision) {
54927
- const artifactPath = join17(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
55052
+ const artifactPath = join18(artifactDir, `review-${artifactSafeName(reviewer)}.json`);
54928
55053
  await writeFile5(artifactPath, `${JSON.stringify({ reviewer, decision, convergence_decision: convergenceDecision, raw_text: rawText }, null, 2)}
54929
55054
  `, { encoding: "utf8" });
54930
55055
  return artifactPath;
@@ -54933,7 +55058,7 @@ async function writeReviewRoundArtifact(artifactDir, reviews, consolidatedFindin
54933
55058
  reviewer: review.reviewer,
54934
55059
  findings: review.findings
54935
55060
  }))), reverification = []) {
54936
- const artifactPath = join17(artifactDir, "review-round-latest.json");
55061
+ const artifactPath = join18(artifactDir, "review-round-latest.json");
54937
55062
  const visibleReviews = reviews.map(withoutTurn);
54938
55063
  await writeFile5(artifactPath, `${JSON.stringify({ reviews: visibleReviews, consolidated_findings: consolidatedFindings, reverification }, null, 2)}
54939
55064
  `, { encoding: "utf8" });
@@ -55161,9 +55286,9 @@ var init_goal_review = __esm(() => {
55161
55286
  });
55162
55287
 
55163
55288
  // dist/builtin/workflows/builtin/goal-ledger.ts
55164
- import { randomUUID as randomUUID9 } from "node:crypto";
55289
+ import { randomUUID as randomUUID10 } from "node:crypto";
55165
55290
  import { readFile as readFile4, rename, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
55166
- import { dirname as dirname9, join as join18 } from "node:path";
55291
+ import { dirname as dirname10, join as join19 } from "node:path";
55167
55292
  import { isDeepStrictEqual } from "node:util";
55168
55293
  function withoutTurn2(value2) {
55169
55294
  const copy = { ...value2 };
@@ -55188,7 +55313,7 @@ function modelVisibleLedger(ledger) {
55188
55313
  };
55189
55314
  }
55190
55315
  function goalLedgerStatePath(ledgerPath) {
55191
- return join18(dirname9(ledgerPath), LEDGER_STATE_FILENAME);
55316
+ return join19(dirname10(ledgerPath), LEDGER_STATE_FILENAME);
55192
55317
  }
55193
55318
  function appendLifecycleEvent(ledger, event, summary, turn = ledger.turns) {
55194
55319
  ledger.lifecycle.push({
@@ -55264,14 +55389,14 @@ function recoverLegacyExecutionInterruption(ledger) {
55264
55389
  return true;
55265
55390
  }
55266
55391
  async function createGoalLedger(objective, acceptanceCriteria, artifactDir) {
55267
- const ledgerPath = join18(artifactDir, LEDGER_FILENAME);
55392
+ const ledgerPath = join19(artifactDir, LEDGER_FILENAME);
55268
55393
  const existing = await readExistingGoalLedger(ledgerPath);
55269
55394
  if (existing !== undefined) {
55270
55395
  if (recoverLegacyExecutionInterruption(existing))
55271
55396
  await writeGoalLedger(ledgerPath, existing);
55272
55397
  return { ledger: existing, ledgerPath, artifactDir };
55273
55398
  }
55274
- const goalId = randomUUID9();
55399
+ const goalId = randomUUID10();
55275
55400
  const now = new Date().toISOString();
55276
55401
  const ledger = {
55277
55402
  goal_id: goalId,
@@ -55300,7 +55425,7 @@ async function writeGoalLedger(ledgerPath, ledger) {
55300
55425
  const stateContents = `${JSON.stringify(ledger, null, 2)}
55301
55426
  `;
55302
55427
  const statePath = goalLedgerStatePath(ledgerPath);
55303
- const pendingStatePath = `${statePath}.${randomUUID9()}.tmp`;
55428
+ const pendingStatePath = `${statePath}.${randomUUID10()}.tmp`;
55304
55429
  await writeFile6(pendingStatePath, stateContents, { encoding: "utf8" });
55305
55430
  try {
55306
55431
  await rename(pendingStatePath, statePath);
@@ -55771,7 +55896,7 @@ var init_goal_orchestrator_prompts = __esm(() => {
55771
55896
  });
55772
55897
 
55773
55898
  // dist/builtin/workflows/builtin/goal-runner.ts
55774
- import { join as join19 } from "node:path";
55899
+ import { join as join20 } from "node:path";
55775
55900
  function positiveInteger(value2, fallback) {
55776
55901
  if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 <= 0) {
55777
55902
  return fallback;
@@ -55822,7 +55947,7 @@ async function runGoalWorkflow(ctx, options) {
55822
55947
  appendLifecycleEvent(ledger, "work_turn_started", "Orchestrator started.", turn);
55823
55948
  await writeGoalLedger(ledgerPath, ledger);
55824
55949
  }
55825
- const orchestratorReceiptPath = join19(artifactDir, "orchestrator-receipt.md");
55950
+ const orchestratorReceiptPath = join20(artifactDir, "orchestrator-receipt.md");
55826
55951
  const orchestratorForkOptions = forkContinuationOptions(previousOrchestratorSessionId);
55827
55952
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? renderGoalOrchestratorPrompt({
55828
55953
  ledger,
@@ -55893,7 +56018,7 @@ async function runGoalWorkflow(ctx, options) {
55893
56018
  const reviewerName = result.name ?? result.stageName;
55894
56019
  const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
55895
56020
  const parsed = reviewerContractError === undefined ? parsedReviewDecisionFromResult(result, reviewerName) : { decision: reviewerErrorDecision(reviewerContractError.message), parsed: false, diagnostics: [reviewerContractError.message] };
55896
- const reviewArtifactPath = join19(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
56021
+ const reviewArtifactPath = join20(artifactDir, `review-${artifactSafeName(normalizedReviewerName)}.json`);
55897
56022
  const record = reviewDecisionToRecord({
55898
56023
  turn,
55899
56024
  reviewer: normalizedReviewerName,
@@ -56214,7 +56339,7 @@ var GROUNDED_REPORTING5 = "Before reporting progress, audit each claim against a
56214
56339
 
56215
56340
  // dist/builtin/workflows/builtin/loop-until-done-runner.ts
56216
56341
  import { mkdir as mkdir3, writeFile as writeFile7 } from "node:fs/promises";
56217
- import { join as join20 } from "node:path";
56342
+ import { join as join21 } from "node:path";
56218
56343
  import { Type as Type16 } from "typebox";
56219
56344
  function progressCurve(entries) {
56220
56345
  return entries.flatMap((entry) => entry.progress === undefined ? [] : [entry.progress.score]);
@@ -56297,18 +56422,18 @@ async function writeLedger(path, task, maxIterations, status, entries) {
56297
56422
  }
56298
56423
  async function runLoopUntilDone(ctx) {
56299
56424
  const artifactDir = await stableArtifactRoot(ctx, "loop-until-done");
56300
- const iterationsDir = join20(artifactDir, "iterations");
56301
- const evaluationsDir = join20(artifactDir, "evaluations");
56425
+ const iterationsDir = join21(artifactDir, "iterations");
56426
+ const evaluationsDir = join21(artifactDir, "evaluations");
56302
56427
  await mkdir3(iterationsDir, { recursive: true });
56303
56428
  await mkdir3(evaluationsDir, { recursive: true });
56304
- const ledgerPath = join20(artifactDir, "progress-ledger.json");
56429
+ const ledgerPath = join21(artifactDir, "progress-ledger.json");
56305
56430
  const entries = [];
56306
56431
  const iterationArtifactPaths = [];
56307
56432
  const evaluationArtifactPaths = [];
56308
56433
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, "active", entries);
56309
56434
  for (let iteration = 1;iteration <= ctx.inputs.max_iterations; iteration += 1) {
56310
- const iterationPath = join20(iterationsDir, `iteration-${iteration}.md`);
56311
- const evaluationPath = join20(evaluationsDir, `evaluation-${iteration}.json`);
56435
+ const iterationPath = join21(iterationsDir, `iteration-${iteration}.md`);
56436
+ const evaluationPath = join21(evaluationsDir, `evaluation-${iteration}.json`);
56312
56437
  iterationArtifactPaths.push(iterationPath);
56313
56438
  evaluationArtifactPaths.push(evaluationPath);
56314
56439
  await ctx.task(`iteration-${iteration}`, {
@@ -56357,7 +56482,7 @@ async function runLoopUntilDone(ctx) {
56357
56482
  await writeLedger(ledgerPath, ctx.inputs.prompt, ctx.inputs.max_iterations, decision.done ? "complete" : "active", entries);
56358
56483
  if (decision.done) {
56359
56484
  const report = progressReport(entries);
56360
- const resultPath = join20(artifactDir, "result.md");
56485
+ const resultPath = join21(artifactDir, "result.md");
56361
56486
  const final = await ctx.task("completion-summary", {
56362
56487
  prompt: renderCompletionPrompt({ task: ctx.inputs.prompt, ledgerPath, iterationPath }),
56363
56488
  context: "fresh",
@@ -56474,9 +56599,9 @@ var init_loop_until_done = __esm(() => {
56474
56599
 
56475
56600
  // dist/builtin/workflows/builtin/open-claude-design-utils.ts
56476
56601
  import { spawnSync as spawnSync3 } from "node:child_process";
56477
- import { mkdirSync as mkdirSync5 } from "node:fs";
56602
+ import { mkdirSync as mkdirSync6 } from "node:fs";
56478
56603
  import { tmpdir, userInfo } from "node:os";
56479
- import { join as join21 } from "node:path";
56604
+ import { join as join22 } from "node:path";
56480
56605
  import { Type as Type18 } from "typebox";
56481
56606
  import { createChildProcessEnvironment as createChildProcessEnvironment3 } from "@bastani/atomic";
56482
56607
  function taggedPrompt3(sections) {
@@ -56519,32 +56644,32 @@ function tmpArtifactBase() {
56519
56644
  try {
56520
56645
  user = userInfo().username.replace(/[^A-Za-z0-9._-]/g, "_") || "default";
56521
56646
  } catch {}
56522
- return join21(tmpdir(), `open-claude-design-${user}`);
56647
+ return join22(tmpdir(), `open-claude-design-${user}`);
56523
56648
  }
56524
56649
  function prepareArtifactDir(cwd = process.cwd()) {
56525
56650
  const runId = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
56526
56651
  const tmpCandidates = [
56527
- join21(tmpArtifactBase(), runId),
56528
- join21(tmpdir(), "open-claude-design", runId)
56652
+ join22(tmpArtifactBase(), runId),
56653
+ join22(tmpdir(), "open-claude-design", runId)
56529
56654
  ];
56530
- const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join21(cwd, "specs", "design", runId), ...tmpCandidates];
56655
+ const candidates = process.env.NODE_ENV === "test" ? tmpCandidates : [join22(cwd, "specs", "design", runId), ...tmpCandidates];
56531
56656
  for (const candidate of candidates) {
56532
56657
  try {
56533
- mkdirSync5(candidate, { recursive: true });
56658
+ mkdirSync6(candidate, { recursive: true });
56534
56659
  return {
56535
56660
  runId,
56536
56661
  artifactDir: candidate,
56537
- previewPath: join21(candidate, "preview.html"),
56538
- specPath: join21(candidate, "spec.html")
56662
+ previewPath: join22(candidate, "preview.html"),
56663
+ specPath: join22(candidate, "spec.html")
56539
56664
  };
56540
56665
  } catch {}
56541
56666
  }
56542
- const fallback = join21(tmpArtifactBase(), runId);
56667
+ const fallback = join22(tmpArtifactBase(), runId);
56543
56668
  return {
56544
56669
  runId,
56545
56670
  artifactDir: fallback,
56546
- previewPath: join21(fallback, "preview.html"),
56547
- specPath: join21(fallback, "spec.html")
56671
+ previewPath: join22(fallback, "preview.html"),
56672
+ specPath: join22(fallback, "spec.html")
56548
56673
  };
56549
56674
  }
56550
56675
  function ensureAgentBrowser() {
@@ -56878,8 +57003,8 @@ var init_open_claude_design_live_protocol = __esm(() => {
56878
57003
  });
56879
57004
 
56880
57005
  // dist/builtin/workflows/builtin/open-claude-design-setup.ts
56881
- import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync3 } from "node:fs";
56882
- import { join as join22 } from "node:path";
57006
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "node:fs";
57007
+ import { join as join23 } from "node:path";
56883
57008
  function renderDiscoveryContext(discovery) {
56884
57009
  return [
56885
57010
  `Confirmed design brief: ${discovery.brief}`,
@@ -56944,10 +57069,10 @@ async function runDiscoveryAndInit(args) {
56944
57069
  };
56945
57070
  }
56946
57071
  function designContextPath(artifactDir) {
56947
- return join22(artifactDir, DESIGN_CONTEXT_FILENAME);
57072
+ return join23(artifactDir, DESIGN_CONTEXT_FILENAME);
56948
57073
  }
56949
57074
  function referencesBriefPath(artifactDir) {
56950
- return join22(artifactDir, REFERENCES_BRIEF_FILENAME);
57075
+ return join23(artifactDir, REFERENCES_BRIEF_FILENAME);
56951
57076
  }
56952
57077
  function buildReferenceDiscoveryPrompt(args) {
56953
57078
  const siteList = REFERENCE_DESIGN_SITES.map((site, index) => `${index + 1}. ${site.name} — ${site.url}`).join(`
@@ -56973,8 +57098,8 @@ function buildReferenceDiscoveryPrompt(args) {
56973
57098
  [
56974
57099
  "Use the agent-browser skill to open each gallery; if `agent-browser` reports a missing browser executable, follow the bootstrap rules and retry once.",
56975
57100
  "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.",
56976
- `Capture motion across the entire page: start \`agent-browser record start ${join22(args.artifactDir, "ref-<site>-<n>.webm")}\`, scroll smoothly in small increments with waits (using repeated \`agent-browser scroll down 600\` or \`agent-browser mouse wheel 600\`) so animations fire and lazy content loads, then run \`agent-browser record stop\`.`,
56977
- `Also run \`agent-browser screenshot ${join22(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
57101
+ `Capture motion across the entire page: start \`agent-browser record start ${join23(args.artifactDir, "ref-<site>-<n>.webm")}\`, scroll smoothly in small increments with waits (using repeated \`agent-browser scroll down 600\` or \`agent-browser mouse wheel 600\`) so animations fire and lazy content loads, then run \`agent-browser record stop\`.`,
57102
+ `Also run \`agent-browser screenshot ${join23(args.artifactDir, "ref-<site>-<n>.png")} --full\`; this still is the minimum when video is unavailable.`,
56978
57103
  "Record the actual destination URL, title, and author. For each reference, cite observed layout, typography, color, spacing, and motion traits rather than inferred traits.",
56979
57104
  "Assess fit against DESIGN.md, PRODUCT.md, and the ds-* discovery evidence in the design-context file; prefer on-brand references and flag departures.",
56980
57105
  "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.",
@@ -56999,8 +57124,8 @@ function buildReferenceDiscoveryPrompt(args) {
56999
57124
  }
57000
57125
  function writeRequiredContextArtifact(artifactDir, filePath, content, label) {
57001
57126
  try {
57002
- mkdirSync6(artifactDir, { recursive: true });
57003
- writeFileSync3(filePath, `${content}
57127
+ mkdirSync7(artifactDir, { recursive: true });
57128
+ writeFileSync4(filePath, `${content}
57004
57129
  `);
57005
57130
  } catch (error) {
57006
57131
  const detail = error instanceof Error ? error.message : String(error);
@@ -57551,7 +57676,7 @@ var init_ralph_review_gate = __esm(() => {
57551
57676
 
57552
57677
  // dist/builtin/workflows/builtin/ralph-core.ts
57553
57678
  import { mkdir as mkdir4, writeFile as writeFile8 } from "node:fs/promises";
57554
- import { dirname as dirname10, join as join23 } from "node:path";
57679
+ import { dirname as dirname11, join as join24 } from "node:path";
57555
57680
  import { Type as Type20 } from "typebox";
57556
57681
  function taggedPrompt4(sections) {
57557
57682
  return sections.map(([tag, content]) => {
@@ -57591,11 +57716,11 @@ function slugifyResearchTopic(prompt) {
57591
57716
  }
57592
57717
  function defaultResearchPath(prompt, now = new Date) {
57593
57718
  const date = now.toISOString().slice(0, 10);
57594
- return join23(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
57719
+ return join24(DEFAULT_RESEARCH_DIR, `${date}-${slugifyResearchTopic(prompt)}.md`);
57595
57720
  }
57596
57721
  async function createImplementationNotesFile(prompt, runId) {
57597
57722
  const notesDir = await createWorkflowArtifactDirectory(runId);
57598
- const notesPath = join23(notesDir, IMPLEMENTATION_NOTES_FILENAME);
57723
+ const notesPath = join24(notesDir, IMPLEMENTATION_NOTES_FILENAME);
57599
57724
  const initialNotes = [
57600
57725
  "# Implementation Notes",
57601
57726
  "",
@@ -57616,7 +57741,7 @@ async function createImplementationNotesFile(prompt, runId) {
57616
57741
  }
57617
57742
  async function createQaEvidenceVideoPath(runId) {
57618
57743
  const qaDir = await createWorkflowArtifactDirectory(runId);
57619
- return join23(qaDir, QA_E2E_VIDEO_FILENAME);
57744
+ return join24(qaDir, QA_E2E_VIDEO_FILENAME);
57620
57745
  }
57621
57746
  function renderQaE2eVideoGuidance(qaVideoPath) {
57622
57747
  return [
@@ -57682,7 +57807,7 @@ function artifactSafeName2(value2) {
57682
57807
  return safe.length > 0 ? safe : "artifact";
57683
57808
  }
57684
57809
  async function writeJsonArtifact(path, content) {
57685
- await mkdir4(dirname10(path), { recursive: true });
57810
+ await mkdir4(dirname11(path), { recursive: true });
57686
57811
  await writeFile8(path, `${JSON.stringify(content, null, 2)}
57687
57812
  `, {
57688
57813
  encoding: "utf8"
@@ -58019,8 +58144,8 @@ var init_ralph_models = __esm(() => {
58019
58144
  });
58020
58145
 
58021
58146
  // dist/builtin/workflows/builtin/ralph-runner.ts
58022
- import { existsSync as existsSync4 } from "node:fs";
58023
- import { join as join24, resolve as resolve9 } from "node:path";
58147
+ import { existsSync as existsSync5 } from "node:fs";
58148
+ import { join as join25, resolve as resolve10 } from "node:path";
58024
58149
  async function runRalphWorkflow(ctx, options) {
58025
58150
  const { prompt, acceptanceCriteria, maxLoops, comparisonBaseBranch, workflowStartCwd, createPr, runId } = options;
58026
58151
  let latestReviewReportPath;
@@ -58032,7 +58157,7 @@ async function runRalphWorkflow(ctx, options) {
58032
58157
  let finalPrReport;
58033
58158
  const workflowCwdContext = workflowCwdContextSection(workflowStartCwd);
58034
58159
  const workflowPrompt = prompt;
58035
- const workflowResearchPath = resolve9(workflowStartCwd, defaultResearchPath(workflowPrompt));
58160
+ const workflowResearchPath = resolve10(workflowStartCwd, defaultResearchPath(workflowPrompt));
58036
58161
  const implementationNotesPath = await createImplementationNotesFile(workflowPrompt, runId);
58037
58162
  const qaVideoPath = await createQaEvidenceVideoPath(runId);
58038
58163
  const artifactDir = await createWorkflowArtifactDirectory(runId);
@@ -58081,7 +58206,7 @@ async function runRalphWorkflow(ctx, options) {
58081
58206
  const researchPath = workflowResearchPath;
58082
58207
  finalResearchPath = researchPath;
58083
58208
  finalPlanPath = researchPath;
58084
- const orchestratorReportPath = join24(artifactDir, "orchestrator-report.md");
58209
+ const orchestratorReportPath = join25(artifactDir, "orchestrator-report.md");
58085
58210
  const orchestratorForkOptions = forkContinuationOptions3(previousOrchestratorSessionId);
58086
58211
  const orchestratorPrompt = orchestratorForkOptions.forkFromSessionId === undefined ? taggedPrompt4([
58087
58212
  ["acceptance_criteria", keepContext(acceptanceCriteria)],
@@ -58217,7 +58342,7 @@ Read it before implementation or delegation because it is the primary current im
58217
58342
  diagnostics: parsed.diagnostics,
58218
58343
  allowFinalActionRemaining: createPr
58219
58344
  });
58220
- const artifactPath = join24(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
58345
+ const artifactPath = join25(artifactDir, `review-${artifactSafeName2(reviewer)}.json`);
58221
58346
  await writeJsonArtifact(artifactPath, {
58222
58347
  reviewer,
58223
58348
  decision: parsed.decision,
@@ -58273,7 +58398,7 @@ Read it before implementation or delegation because it is the primary current im
58273
58398
  usage: fold_usage([orchestrator, ...reviews, ...reverifyResults])
58274
58399
  }));
58275
58400
  }
58276
- latestReviewReportPath = await writeJsonArtifact(join24(artifactDir, "review-round-latest.json"), {
58401
+ latestReviewReportPath = await writeJsonArtifact(join25(artifactDir, "review-round-latest.json"), {
58277
58402
  convergence_decision: roundConvergenceDecision,
58278
58403
  convergence: convergenceEntries,
58279
58404
  consolidated_findings: reverified.batch,
@@ -58283,7 +58408,7 @@ Read it before implementation or delegation because it is the primary current im
58283
58408
  if (approved)
58284
58409
  break;
58285
58410
  }
58286
- const qaVideoAvailable = existsSync4(qaVideoPath);
58411
+ const qaVideoAvailable = existsSync5(qaVideoPath);
58287
58412
  const unapprovedHandoff = createPr === true && !approved;
58288
58413
  const escalationEvidence = unapprovedHandoff ? convergence_escalation_evidence(convergenceEntries) : [];
58289
58414
  if (createPr === true) {
@@ -58642,7 +58767,7 @@ var init_tournament_prompts = __esm(() => {
58642
58767
 
58643
58768
  // dist/builtin/workflows/builtin/tournament-runner.ts
58644
58769
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile9 } from "node:fs/promises";
58645
- import { join as join25, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve10 } from "node:path";
58770
+ import { join as join26, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve11 } from "node:path";
58646
58771
  import { Type as Type22 } from "typebox";
58647
58772
  function serializableObject2(value2) {
58648
58773
  if (value2 === null || Array.isArray(value2) || typeof value2 !== "object")
@@ -58679,8 +58804,8 @@ function criterionSlug(id) {
58679
58804
  }
58680
58805
  function judgeArtifactPath(judgesDir, job, criterionIndex) {
58681
58806
  const filename = `judge-${job.a}-${job.b}-c${criterionIndex}-${criterionSlug(job.criterionId)}-r${job.rep}.json`;
58682
- const root = resolve10(judgesDir);
58683
- const path = resolve10(judgesDir, filename);
58807
+ const root = resolve11(judgesDir);
58808
+ const path = resolve11(judgesDir, filename);
58684
58809
  const fromRoot = relative5(root, path);
58685
58810
  if (fromRoot.startsWith("..") || isAbsolute9(fromRoot)) {
58686
58811
  throw new Error(`tournament: judge artifact escaped its directory: ${path}`);
@@ -58731,16 +58856,16 @@ function combineUsage(totals) {
58731
58856
  }
58732
58857
  async function runTournament(ctx) {
58733
58858
  const artifactDir = await stableArtifactRoot(ctx, "tournament");
58734
- const attemptsDir = join25(artifactDir, "attempts");
58859
+ const attemptsDir = join26(artifactDir, "attempts");
58735
58860
  const numAttempts = ctx.inputs.num_attempts ?? 4;
58736
58861
  const maxConcurrency = ctx.inputs.max_concurrency ?? 4;
58737
58862
  const nEvaluations = ctx.inputs.n_evaluations ?? 2;
58738
58863
  const pivotCount = ctx.inputs.pivots ?? 1;
58739
58864
  const seed = ctx.inputs.seed ?? 0;
58740
- const judgesDir = join25(artifactDir, "judges");
58865
+ const judgesDir = join26(artifactDir, "judges");
58741
58866
  await mkdir5(attemptsDir, { recursive: true });
58742
58867
  await mkdir5(judgesDir, { recursive: true });
58743
- const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join25(attemptsDir, `attempt-${index + 1}.md`));
58868
+ const attemptArtifactPaths = Array.from({ length: numAttempts }, (_, index) => join26(attemptsDir, `attempt-${index + 1}.md`));
58744
58869
  const models = ctx.inputs.models;
58745
58870
  const attemptResults = await ctx.parallel(attemptArtifactPaths.map((path, index) => ({
58746
58871
  name: `attempt-${index + 1}`,
@@ -58905,7 +59030,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
58905
59030
  const outputRanking = ranking.map(({ label, meanPreference }) => ({ label, meanPreference }));
58906
59031
  const budgetPivots = Math.min(pivotCount, entrants.length);
58907
59032
  const comparisonBudget = (entrants.length + budgetPivots * (entrants.length - budgetPivots) + budgetPivots * (budgetPivots - 1) / 2) * criteria.length * nEvaluations;
58908
- const comparisonPath = join25(artifactDir, "comparisons.json");
59033
+ const comparisonPath = join26(artifactDir, "comparisons.json");
58909
59034
  const assignment = modelAssignment(entrants, models);
58910
59035
  const phaseUsage = {
58911
59036
  attempts: fold_usage(attemptResults),
@@ -58941,7 +59066,7 @@ The previous report was invalid. Return the required JSON schema exactly once.`,
58941
59066
  await writeLedger(fold_usage([]));
58942
59067
  const winner = ranking[0];
58943
59068
  const winnerEntrant = entrants[winner.index];
58944
- const resultPath = join25(artifactDir, "winner.md");
59069
+ const resultPath = join26(artifactDir, "winner.md");
58945
59070
  const reducer = await ctx.task("comparisons-reducer", {
58946
59071
  prompt: renderComparisonsReducerPrompt({
58947
59072
  task: ctx.inputs.prompt,
@@ -59159,7 +59284,7 @@ var init_workflow_module_loader = __esm(() => {
59159
59284
  });
59160
59285
 
59161
59286
  // dist/builtin/workflows/src/workers/definitions.ts
59162
- import { createHash as createHash3 } from "node:crypto";
59287
+ import { createHash as createHash4 } from "node:crypto";
59163
59288
  import { readFile as readFile6 } from "node:fs/promises";
59164
59289
  import { isAbsolute as isAbsolute10 } from "node:path";
59165
59290
  async function loadWorkerDefinition(source) {
@@ -59177,7 +59302,7 @@ async function loadWorkerWorkflow(path, exportName = "default") {
59177
59302
  return loadWorkerDefinition({ path, exportName, digest: await definitionDigest(path) });
59178
59303
  }
59179
59304
  async function definitionDigest(path) {
59180
- return createHash3("sha256").update(await readFile6(path)).digest("hex");
59305
+ return createHash4("sha256").update(await readFile6(path)).digest("hex");
59181
59306
  }
59182
59307
  var workerDefinitionSources;
59183
59308
  var init_definitions = __esm(() => {
@@ -59191,6 +59316,84 @@ var init_host_options = __esm(() => {
59191
59316
  hostWorkerBindings = Symbol("host-worker-bindings");
59192
59317
  });
59193
59318
 
59319
+ // dist/builtin/workflows/src/durable/journal/pool-remote-journal.ts
59320
+ class PoolRemoteJournal {
59321
+ journal;
59322
+ storage;
59323
+ mirrored;
59324
+ mirroring;
59325
+ constructor(journal, storage) {
59326
+ this.journal = journal;
59327
+ this.storage = storage;
59328
+ }
59329
+ async mirror(lease) {
59330
+ const root = lease.runId;
59331
+ const sampledAt = performance.now();
59332
+ const [run, state] = await Promise.all([this.journal.getRun(root), this.journal.leaseState(root)]);
59333
+ if (run === undefined)
59334
+ throw new RunNotFoundError(root);
59335
+ const { runs, leases } = this.storage.tables;
59336
+ await this.storage.transaction(async (tx) => {
59337
+ await tx.run(`INSERT INTO ${runs}(run_id, name, cwd, created_at, status, header_json) VALUES (?, ?, ?, ?, ?, ?)
59338
+ ON CONFLICT(run_id) DO UPDATE SET status = excluded.status`, root, run.name, run.cwd, run.createdAt, run.status, serializeJson({ runId: root, name: run.name, cwd: run.cwd, createdAt: run.createdAt, status: run.status }));
59339
+ if (state === undefined)
59340
+ await tx.run(`DELETE FROM ${leases} WHERE run_id = ?`, root);
59341
+ else
59342
+ await tx.run(`INSERT INTO ${leases}(run_id, holder_id, epoch, renewed_at) VALUES (?, ?, ?, CAST(unixepoch('subsec') * 1000 AS INTEGER) - ?)
59343
+ ON CONFLICT(run_id) DO UPDATE SET holder_id = excluded.holder_id, epoch = excluded.epoch, renewed_at = excluded.renewed_at`, root, state.holderId, state.epoch, Math.ceil(Math.max(0, state.ageMs) + (performance.now() - sampledAt)));
59344
+ });
59345
+ if (state === undefined || state.holderId !== lease.holderId || state.epoch !== lease.epoch)
59346
+ throw new StaleLeaseError(root, lease.epoch, state?.epoch ?? 0);
59347
+ this.mirrored = { lease, at: sampledAt };
59348
+ }
59349
+ async fresh(lease, maxAgeMs = MIRROR_FRESH_MS) {
59350
+ const known = this.mirrored;
59351
+ if (known !== undefined && known.lease.holderId === lease.holderId && known.lease.epoch === lease.epoch && performance.now() - known.at < maxAgeMs)
59352
+ return;
59353
+ this.mirroring ??= this.mirror(lease).finally(() => {
59354
+ this.mirroring = undefined;
59355
+ });
59356
+ try {
59357
+ await this.mirroring;
59358
+ } catch (error) {
59359
+ if (error instanceof StaleLeaseError || error instanceof RunNotFoundError)
59360
+ throw error;
59361
+ }
59362
+ }
59363
+ entry(root, key) {
59364
+ return this.journal.readKey(root, key);
59365
+ }
59366
+ append(lease, key, checkpoint) {
59367
+ const event = { type: RUN_EVENT_TYPES.checkpointRecorded, payload: checkpoint };
59368
+ return this.journal.append(lease, event, { key });
59369
+ }
59370
+ events(root) {
59371
+ return (fromSeq) => this.journal.read(root, fromSeq);
59372
+ }
59373
+ }
59374
+ function isSameCheckpointValue(stored, next) {
59375
+ const hash = (value2) => durableHash(value2);
59376
+ return hash(stored) === hash(next);
59377
+ }
59378
+ function isRecordedCheckpointValue(stored, next) {
59379
+ const recorded = stored;
59380
+ if (isSameCheckpointValue(recorded, next))
59381
+ return true;
59382
+ const { completedAt, startedAt } = recorded;
59383
+ if (typeof completedAt !== "number")
59384
+ return false;
59385
+ const later = next;
59386
+ if (startedAt === undefined !== (later.startedAt === undefined))
59387
+ return false;
59388
+ return isSameCheckpointValue({ ...later, completedAt, ...startedAt === undefined ? {} : { startedAt } }, recorded);
59389
+ }
59390
+ var MIRROR_FRESH_MS = 2000;
59391
+ var init_pool_remote_journal = __esm(() => {
59392
+ init_durable_hash();
59393
+ init_types();
59394
+ init_values();
59395
+ });
59396
+
59194
59397
  // dist/builtin/workflows/src/durable/journal/pool-checkpoint-index.ts
59195
59398
  function push(map, key, value2) {
59196
59399
  if (key === undefined)
@@ -59258,6 +59461,11 @@ class PoolCheckpointRead {
59258
59461
  this.pending = apply;
59259
59462
  });
59260
59463
  }
59464
+ readEntries(stream) {
59465
+ return this.index.readEntries(this.root, stream, (apply) => {
59466
+ this.pending = apply;
59467
+ });
59468
+ }
59261
59469
  commit() {
59262
59470
  this.pending?.();
59263
59471
  this.pending = undefined;
@@ -59280,7 +59488,6 @@ class PoolCheckpointIndex {
59280
59488
  }
59281
59489
  const from = base?.seq ?? 0;
59282
59490
  const to = head ? Number(head.seq) : 0;
59283
- const delta = new Partitions;
59284
59491
  const added = [];
59285
59492
  if (to > from) {
59286
59493
  const rows = await tx.all(`SELECT seq, key, payload FROM ${events} WHERE run_id = ? AND seq > ? AND seq <= ? AND type = ? ORDER BY seq`, root, from, to, RUN_EVENT_TYPES.checkpointRecorded);
@@ -59288,15 +59495,57 @@ class PoolCheckpointIndex {
59288
59495
  const checkpoint = JSON.parse(String(row.payload));
59289
59496
  if (checkpoint.kind === "ui")
59290
59497
  continue;
59291
- const entry = {
59498
+ added.push({
59292
59499
  seq: Number(row.seq),
59293
59500
  order: row.key === null ? Buffer.alloc(0) : Buffer.from(row.key, "utf8"),
59294
59501
  checkpoint
59295
- };
59296
- delta.add(entry);
59297
- added.push(entry);
59502
+ });
59298
59503
  }
59299
59504
  }
59505
+ return this.view(root, current, base, from, to, head, added, onCommit);
59506
+ }
59507
+ async readEntries(root, stream, onCommit) {
59508
+ const current = this.roots.get(root);
59509
+ let base = current;
59510
+ for (;; ) {
59511
+ const mark = base !== undefined && base.seq > 0 ? { seq: base.seq, key: base.key, at: base.at } : undefined;
59512
+ let verified = mark === undefined;
59513
+ let mismatch = false;
59514
+ let head;
59515
+ const added = [];
59516
+ for await (const entry of stream(mark === undefined ? 1 : mark.seq)) {
59517
+ if (mark !== undefined && entry.seq === mark.seq) {
59518
+ if ((entry.key ?? null) !== mark.key || entry.at !== mark.at) {
59519
+ mismatch = true;
59520
+ break;
59521
+ }
59522
+ verified = true;
59523
+ head = { seq: entry.seq, key: entry.key ?? null, at: entry.at };
59524
+ continue;
59525
+ }
59526
+ head = { seq: entry.seq, key: entry.key ?? null, at: entry.at };
59527
+ if (entry.event.type !== RUN_EVENT_TYPES.checkpointRecorded)
59528
+ continue;
59529
+ const checkpoint = entry.event.payload;
59530
+ if (checkpoint.kind === "ui")
59531
+ continue;
59532
+ added.push({
59533
+ seq: entry.seq,
59534
+ order: entry.key === undefined ? Buffer.alloc(0) : Buffer.from(entry.key, "utf8"),
59535
+ checkpoint
59536
+ });
59537
+ }
59538
+ if (mark !== undefined && (mismatch || !verified)) {
59539
+ base = undefined;
59540
+ continue;
59541
+ }
59542
+ return this.view(root, current, base, mark?.seq ?? 0, head?.seq ?? 0, head, added, onCommit);
59543
+ }
59544
+ }
59545
+ view(root, current, base, from, to, head, added, onCommit) {
59546
+ const delta = new Partitions;
59547
+ for (const entry of added)
59548
+ delta.add(entry);
59300
59549
  onCommit(() => {
59301
59550
  const latest = this.roots.get(root);
59302
59551
  if (!base) {
@@ -59525,10 +59774,10 @@ var init_pool_stage_usage = __esm(() => {
59525
59774
  });
59526
59775
 
59527
59776
  // dist/builtin/workflows/src/durable/journal/sql-pool-queue.ts
59528
- import { createHash as createHash4, randomUUID as randomUUID10 } from "node:crypto";
59777
+ import { createHash as createHash5, randomUUID as randomUUID11 } from "node:crypto";
59529
59778
  import { assertStorageSchemaVersion as assertStorageSchemaVersion2, StorageError as StorageError2 } from "@bastani/atomic/storage";
59530
59779
  function requestIdentity(request) {
59531
- return createHash4("sha256").update(request).digest("hex");
59780
+ return createHash5("sha256").update(request).digest("hex");
59532
59781
  }
59533
59782
  function fromRow(row) {
59534
59783
  return {
@@ -59559,15 +59808,21 @@ function expiry(now, duration) {
59559
59808
 
59560
59809
  class SqlPoolQueue {
59561
59810
  storage;
59811
+ remote;
59562
59812
  meta;
59563
59813
  roots;
59564
59814
  work;
59565
59815
  operations;
59816
+ outbox;
59566
59817
  transaction;
59567
59818
  journal;
59568
59819
  checkpoints = new PoolCheckpointIndex;
59569
- constructor(storage) {
59820
+ committing = new Map;
59821
+ draining;
59822
+ outboxPending = false;
59823
+ constructor(storage, remote) {
59570
59824
  this.storage = storage;
59825
+ this.remote = remote;
59571
59826
  const { transaction, tables: journal } = storage;
59572
59827
  this.transaction = transaction;
59573
59828
  this.journal = journal;
@@ -59575,10 +59830,11 @@ class SqlPoolQueue {
59575
59830
  this.roots = `${journal.runs}_pool`;
59576
59831
  this.work = `${journal.runs}_work`;
59577
59832
  this.operations = `${journal.runs}_pool_operations`;
59833
+ this.outbox = `${journal.runs}_pool_outbox`;
59578
59834
  }
59579
- static async open(storage) {
59835
+ static async open(storage, remote) {
59580
59836
  const journal = storage.tables;
59581
- const pool = new SqlPoolQueue(storage);
59837
+ const pool = new SqlPoolQueue(storage, remote);
59582
59838
  await storage.transaction(async (tx) => {
59583
59839
  if ((await tx.get("PRAGMA foreign_keys"))?.foreign_keys !== 1)
59584
59840
  throw new Error("Pool requires SQLite foreign keys");
@@ -59621,6 +59877,15 @@ class SqlPoolQueue {
59621
59877
  state TEXT NOT NULL DEFAULT 'running', revision INTEGER NOT NULL DEFAULT 0
59622
59878
  )`);
59623
59879
  await tx.exec(poolUsageSchema(journal.runs));
59880
+ if (remote)
59881
+ await tx.exec(`CREATE TABLE IF NOT EXISTS ${pool.outbox}(
59882
+ work TEXT NOT NULL REFERENCES ${pool.work}(id) ON DELETE CASCADE,
59883
+ generation INTEGER NOT NULL, operation TEXT NOT NULL, request TEXT NOT NULL,
59884
+ event_key TEXT NOT NULL, payload TEXT NOT NULL, last_seq INTEGER,
59885
+ PRIMARY KEY(work, generation, operation)
59886
+ )`);
59887
+ if (remote)
59888
+ pool.outboxPending = await tx.get(`SELECT 1 AS held FROM ${pool.outbox} LIMIT 1`) !== undefined;
59624
59889
  if (version === 1)
59625
59890
  await pool.migrateFromVersion1(tx);
59626
59891
  });
@@ -59665,6 +59930,7 @@ class SqlPoolQueue {
59665
59930
  });
59666
59931
  }
59667
59932
  async setControl(lease, state) {
59933
+ await this.remote?.fresh(lease);
59668
59934
  return this.transaction(async (tx) => {
59669
59935
  await this.authority(tx, lease);
59670
59936
  await tx.run(`INSERT INTO ${this.roots}_control(root, state, revision) VALUES (?, ?, 1)
@@ -59676,7 +59942,7 @@ class SqlPoolQueue {
59676
59942
  withCurrentAppend(lease, token, assertSession, action) {
59677
59943
  lease = snapshotLease(lease);
59678
59944
  token = { ...token };
59679
- return this.storage.withAppendGuard(async (tx, runId) => {
59945
+ const guard = async (tx, runId) => {
59680
59946
  try {
59681
59947
  if (runId !== lease.runId)
59682
59948
  throw new Error("Pool delivery cannot write another root");
@@ -59694,7 +59960,10 @@ class SqlPoolQueue {
59694
59960
  throw error;
59695
59961
  throw new PoolAppendRefusedError(error.message, { cause: error });
59696
59962
  }
59697
- }, action);
59963
+ };
59964
+ if (this.remote)
59965
+ return this.transaction((tx) => guard(tx, lease.runId)).then(action);
59966
+ return this.storage.withAppendGuard(guard, action);
59698
59967
  }
59699
59968
  async assertCurrent(lease, token) {
59700
59969
  await this.transaction(async (tx) => {
@@ -59727,6 +59996,8 @@ class SqlPoolQueue {
59727
59996
  const payload = serializeJson(boundary);
59728
59997
  const fingerprint = durableHash({ descriptor: JSON.parse(json), boundary: JSON.parse(payload) });
59729
59998
  const key = JSON.stringify([RUN_EVENT_TYPES.checkpointRecorded, boundary.kind, boundary.checkpointId]);
59999
+ if (this.remote)
60000
+ await this.recordBoundaryStart(lease, key, boundary);
59730
60001
  return this.transaction(async (tx) => {
59731
60002
  const { now } = await this.authority(tx, lease);
59732
60003
  const previous = await tx.get(`SELECT * FROM ${this.work} WHERE root = ? AND (boundary = ? OR json_extract(descriptor, '$.scope') = ? OR json_extract(descriptor, '$.childRunId') = ?)`, lease.runId, boundaryId, scope, childRunId);
@@ -59741,23 +60012,49 @@ class SqlPoolQueue {
59741
60012
  const siblings = await tx.all(`SELECT json_extract(descriptor, '$.scope') AS scope FROM ${this.work} WHERE root = ?`, lease.runId);
59742
60013
  if (siblings.some((item) => scope.startsWith(`${item.scope}:`) || item.scope.startsWith(`${scope}:`)))
59743
60014
  throw new Error("Pool work scopes overlap");
59744
- const id = randomUUID10();
60015
+ const id = randomUUID11();
59745
60016
  await tx.run(`INSERT INTO ${this.work}(id, root, boundary, descriptor, fingerprint, epoch, ready_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, id, lease.runId, boundaryId, json, fingerprint, lease.epoch, now);
59746
- const seq = await tx.get(`SELECT COALESCE(MAX(seq), 0) AS seq FROM ${this.journal.events} WHERE run_id = ?`, lease.runId);
59747
- const existing = await tx.get(`SELECT payload FROM ${this.journal.events} WHERE run_id = ? AND key = ?`, lease.runId, key);
59748
- if (existing && existing.payload !== payload)
59749
- throw new Error("Pool boundary identity conflict");
59750
- if (!existing)
59751
- await tx.run(`INSERT INTO ${this.journal.events} VALUES (?, ?, ?, ?, ?, ?, ?)`, lease.runId, journalCounter(lease.runId, "seq", Number(seq.seq) + 1, "overflow"), lease.epoch, key, RUN_EVENT_TYPES.checkpointRecorded, payload, now);
60017
+ if (!this.remote) {
60018
+ const seq = await tx.get(`SELECT COALESCE(MAX(seq), 0) AS seq FROM ${this.journal.events} WHERE run_id = ?`, lease.runId);
60019
+ const existing = await tx.get(`SELECT payload FROM ${this.journal.events} WHERE run_id = ? AND key = ?`, lease.runId, key);
60020
+ if (existing && existing.payload !== payload)
60021
+ throw new Error("Pool boundary identity conflict");
60022
+ if (!existing)
60023
+ await tx.run(`INSERT INTO ${this.journal.events} VALUES (?, ?, ?, ?, ?, ?, ?)`, lease.runId, journalCounter(lease.runId, "seq", Number(seq.seq) + 1, "overflow"), lease.epoch, key, RUN_EVENT_TYPES.checkpointRecorded, payload, now);
60024
+ }
59752
60025
  return fromRow(await tx.get(`SELECT * FROM ${this.work} WHERE id = ?`, id));
59753
60026
  });
59754
60027
  }
60028
+ async recordBoundaryStart(lease, key, boundary) {
60029
+ const remote = this.remote;
60030
+ await remote.fresh(lease);
60031
+ const existing = await remote.entry(lease.runId, key);
60032
+ if (existing) {
60033
+ if (!isSameCheckpointValue(existing.event.payload, boundary))
60034
+ throw new Error("Pool boundary identity conflict");
60035
+ return;
60036
+ }
60037
+ const outcome = await remote.append(lease, key, boundary);
60038
+ if (outcome.status === "exists" && !isSameCheckpointValue(outcome.entry.event.payload, boundary))
60039
+ throw new Error("Pool boundary identity conflict");
60040
+ }
59755
60041
  async claim(lease, worker, definitions, durationMs) {
59756
60042
  positive(durationMs);
59757
60043
  lease = snapshotLease(lease);
59758
60044
  const compatibleDefinitions = definitions.flatMap((d) => [d.definition, d.digest]);
59759
60045
  validateText("holderId", worker);
59760
60046
  const compatible = definitions.map(() => "(json_extract(descriptor, '$.definition') = ? AND json_extract(descriptor, '$.digest') = ?)").join(" OR ");
60047
+ if (this.remote) {
60048
+ await this.remote.fresh(lease);
60049
+ try {
60050
+ while (this.outboxPending || this.draining !== undefined)
60051
+ await this.drainOutbox(lease);
60052
+ } catch (error) {
60053
+ if (error instanceof StaleLeaseError)
60054
+ throw error;
60055
+ return;
60056
+ }
60057
+ }
59761
60058
  return this.transaction(async (tx) => {
59762
60059
  const { now, status } = await this.authority(tx, lease);
59763
60060
  const control = await tx.get(`SELECT state FROM ${this.roots}_control WHERE root = ?`, lease.runId);
@@ -59791,6 +60088,7 @@ class SqlPoolQueue {
59791
60088
  positive(durationMs);
59792
60089
  lease = snapshotLease(lease);
59793
60090
  token = { ...token };
60091
+ await this.remote?.fresh(lease);
59794
60092
  return this.transaction(async (tx) => {
59795
60093
  const { now } = await this.authority(tx, lease);
59796
60094
  const row = await this.current(tx, lease, token);
@@ -59809,6 +60107,8 @@ class SqlPoolQueue {
59809
60107
  const request = serializeJson({ epoch: token.epoch, worker: token.worker, mutation });
59810
60108
  const identity = requestIdentity(request);
59811
60109
  mutation = JSON.parse(request).mutation;
60110
+ if (this.remote && mutation.kind !== "session-append")
60111
+ return this.commitRemote(lease, token, operationId, mutation, identity);
59812
60112
  const checkpoints = this.checkpoints.begin(lease.runId);
59813
60113
  const receipt = await this.transaction(async (tx) => {
59814
60114
  const { now, status } = await this.authority(tx, lease);
@@ -59832,6 +60132,127 @@ class SqlPoolQueue {
59832
60132
  checkpoints.commit();
59833
60133
  return receipt;
59834
60134
  }
60135
+ commitRemote(lease, token, operationId, mutation, identity) {
60136
+ const flight = JSON.stringify([token.id, token.generation, operationId]);
60137
+ const running = this.committing.get(flight);
60138
+ if (running)
60139
+ return running;
60140
+ const commit = this.stageAndDeliver(lease, token, operationId, mutation, identity).finally(() => {
60141
+ this.committing.delete(flight);
60142
+ });
60143
+ this.committing.set(flight, commit);
60144
+ return commit;
60145
+ }
60146
+ async stageAndDeliver(lease, token, operationId, mutation, identity) {
60147
+ const remote = this.remote;
60148
+ await remote.fresh(lease);
60149
+ const checkpoint = mutation.checkpoint;
60150
+ const key = JSON.stringify([RUN_EVENT_TYPES.checkpointRecorded, checkpoint.kind, checkpoint.checkpointId]);
60151
+ const reads = this.checkpoints.begin(lease.runId);
60152
+ const [existing, view] = await Promise.all([
60153
+ remote.entry(lease.runId, key),
60154
+ checkpoint.kind === "ui" ? undefined : reads.readEntries(remote.events(lease.runId))
60155
+ ]);
60156
+ reads.commit();
60157
+ const source = {
60158
+ read: async () => view ?? Promise.reject(new Error("Pool checkpoint view is unavailable"))
60159
+ };
60160
+ const staged = await this.transaction(async (tx) => {
60161
+ const { now, status } = await this.authority(tx, lease);
60162
+ const row = await this.current(tx, lease, token);
60163
+ if (row.epoch !== lease.epoch)
60164
+ throw new Error(STALE_WORK_LEASE);
60165
+ const previous = await tx.get(`SELECT * FROM ${this.operations} WHERE work = ? AND generation = ? AND operation = ?`, token.id, token.generation, operationId);
60166
+ if (previous) {
60167
+ if (previous.request !== identity)
60168
+ throw new Error("Pool operation identity conflict");
60169
+ return { receipt: JSON.parse(previous.receipt) };
60170
+ }
60171
+ const held = await tx.get(`SELECT * FROM ${this.outbox} WHERE work = ? AND generation = ? AND operation = ?`, token.id, token.generation, operationId);
60172
+ if (held) {
60173
+ if (held.request !== identity)
60174
+ throw new Error("Pool operation identity conflict");
60175
+ return { held };
60176
+ }
60177
+ if (row.expires_at < now)
60178
+ throw new Error(STALE_WORK_LEASE);
60179
+ if (!await this.admitsAttemptWrites(tx, lease, status))
60180
+ throw new Error("Pool root is not running");
60181
+ await validatePoolMutation(tx, this.journal, lease.runId, fromRow(row), mutation, source);
60182
+ if (checkpoint.completedAt > Math.max(now, Date.now()) + MAX_WORKER_CLOCK_SKEW_MS)
60183
+ throw new Error("Pool checkpoint timestamp is in the future");
60184
+ assertWorkflowSerializableObject(checkpoint, "Pool checkpoint");
60185
+ if (existing && !isRecordedCheckpointValue(existing.event.payload, checkpoint))
60186
+ throw new Error("Pool checkpoint identity conflict");
60187
+ if (existing && mutation.kind !== "checkpoint")
60188
+ throw new Error("Pool session checkpoint identity conflict");
60189
+ const lastSeq = mutation.kind === "checkpoint" ? undefined : await applyPoolSession(tx, `${this.journal.runs}_pool_`, row.id, mutation);
60190
+ const billed = poolCheckpointUsage(checkpoint);
60191
+ if (billed && !existing)
60192
+ await upsertPoolUsage(tx, this.journal.runs, row.id, token.generation, billed.key, billed.usage);
60193
+ if (existing) {
60194
+ const receipt = { seq: existing.seq, at: existing.at };
60195
+ await tx.run(`INSERT INTO ${this.operations} VALUES (?, ?, ?, ?, ?)`, token.id, token.generation, operationId, identity, JSON.stringify(receipt));
60196
+ return { receipt };
60197
+ }
60198
+ const entry = {
60199
+ work: token.id,
60200
+ generation: token.generation,
60201
+ operation: operationId,
60202
+ request: identity,
60203
+ event_key: key,
60204
+ payload: serializeJson(checkpoint),
60205
+ last_seq: lastSeq ?? null
60206
+ };
60207
+ await tx.run(`INSERT INTO ${this.outbox} VALUES (?, ?, ?, ?, ?, ?, ?)`, entry.work, entry.generation, entry.operation, entry.request, entry.event_key, entry.payload, entry.last_seq);
60208
+ return { held: entry };
60209
+ });
60210
+ if (staged.receipt !== undefined)
60211
+ return staged.receipt;
60212
+ this.outboxPending = true;
60213
+ return this.deliver(lease, staged.held);
60214
+ }
60215
+ async deliver(lease, held) {
60216
+ const remote = this.remote;
60217
+ const checkpoint = JSON.parse(held.payload);
60218
+ const outcome = await remote.append(lease, held.event_key, checkpoint);
60219
+ const forget = (tx) => tx.run(`DELETE FROM ${this.outbox} WHERE work = ? AND generation = ? AND operation = ?`, held.work, held.generation, held.operation);
60220
+ if (outcome.status === "exists" && !isRecordedCheckpointValue(outcome.entry.event.payload, checkpoint)) {
60221
+ await this.transaction(forget);
60222
+ throw new Error("Pool checkpoint identity conflict");
60223
+ }
60224
+ const receipt = {
60225
+ seq: outcome.entry.seq,
60226
+ at: outcome.entry.at,
60227
+ ...held.last_seq === null ? {} : { lastSeq: Number(held.last_seq) }
60228
+ };
60229
+ await this.transaction(async (tx) => {
60230
+ await tx.run(`INSERT OR IGNORE INTO ${this.operations} VALUES (?, ?, ?, ?, ?)`, held.work, held.generation, held.operation, held.request, JSON.stringify(receipt));
60231
+ await forget(tx);
60232
+ });
60233
+ return receipt;
60234
+ }
60235
+ drainOutbox(lease) {
60236
+ if (!this.remote)
60237
+ return Promise.resolve(0);
60238
+ lease = snapshotLease(lease);
60239
+ this.draining ??= this.deliverAll(lease).finally(() => {
60240
+ this.draining = undefined;
60241
+ });
60242
+ return this.draining;
60243
+ }
60244
+ async deliverAll(lease) {
60245
+ this.outboxPending = false;
60246
+ const rows = await this.transaction((tx) => tx.all(`SELECT o.* FROM ${this.outbox} o JOIN ${this.work} w ON w.id = o.work WHERE w.root = ? ORDER BY o.rowid`, lease.runId));
60247
+ try {
60248
+ for (const row of rows)
60249
+ await this.deliver(lease, row);
60250
+ } catch (error) {
60251
+ this.outboxPending = true;
60252
+ throw error;
60253
+ }
60254
+ return rows.length;
60255
+ }
59835
60256
  async appendSession(tx, row, mutation, now) {
59836
60257
  return { at: now, lastSeq: await applyPoolSession(tx, `${this.journal.runs}_pool_`, row.id, mutation) };
59837
60258
  }
@@ -59867,6 +60288,7 @@ class SqlPoolQueue {
59867
60288
  token = { ...token };
59868
60289
  assertWorkflowSerializableObject(result, "Pool result");
59869
60290
  const payload = serializeJson(result);
60291
+ await this.remote?.fresh(lease);
59870
60292
  await this.transaction(async (tx) => {
59871
60293
  const { now, status } = await this.authority(tx, lease);
59872
60294
  const row = await this.current(tx, lease, token, true);
@@ -59882,6 +60304,8 @@ class SqlPoolQueue {
59882
60304
  throw new Error(STALE_WORK_LEASE);
59883
60305
  if (JSON.parse(payload).runId !== fromRow(row).childRunId)
59884
60306
  throw new Error("Pool result identity mismatch");
60307
+ if (this.remote && await tx.get(`SELECT 1 AS held FROM ${this.outbox} WHERE work = ? LIMIT 1`, token.id))
60308
+ throw new Error("Pool work has journal events not yet recorded");
59885
60309
  await tx.run(`INSERT INTO ${this.work}_results VALUES (?, ?)`, token.id, payload);
59886
60310
  await tx.run(`UPDATE ${this.work} SET state = 'completed' WHERE id = ?`, token.id);
59887
60311
  });
@@ -59908,6 +60332,7 @@ class SqlPoolQueue {
59908
60332
  positive(durationMs);
59909
60333
  lease = snapshotLease(lease);
59910
60334
  token = { ...token };
60335
+ await this.remote?.fresh(lease);
59911
60336
  return this.transaction(async (tx) => {
59912
60337
  const { now } = await this.authority(tx, lease);
59913
60338
  const row = await this.current(tx, lease, token);
@@ -59979,11 +60404,11 @@ function isRecordedCheckpoint(stored, payload) {
59979
60404
  return false;
59980
60405
  return serializeJson({ ...next, completedAt, ...startedAt === undefined ? {} : { startedAt } }) === stored;
59981
60406
  }
59982
- function openSqlPoolQueue(journal) {
60407
+ function openSqlPoolQueue(journal, remote) {
59983
60408
  const storage = sqlPoolStorage(journal);
59984
60409
  if (!storage)
59985
60410
  return Promise.reject(new Error("Worker pool requires a SQL run journal"));
59986
- return SqlPoolQueue.open(storage);
60411
+ return SqlPoolQueue.open(storage, remote);
59987
60412
  }
59988
60413
  var STORE_NOW2 = "CAST(unixepoch('subsec') * 1000 AS INTEGER)", MAX_WORKER_CLOCK_SKEW_MS = 1000, POOL_SCHEMA_VERSION = 2, STALE_WORK_LEASE = "Stale work lease", PoolAppendRefusedError;
59989
60414
  var init_sql_pool_queue = __esm(() => {
@@ -59993,6 +60418,7 @@ var init_sql_pool_queue = __esm(() => {
59993
60418
  init_internal();
59994
60419
  init_pool_checkpoint_index();
59995
60420
  init_pool_mutations();
60421
+ init_pool_remote_journal();
59996
60422
  init_pool_stage_usage();
59997
60423
  init_types();
59998
60424
  init_values();
@@ -60064,7 +60490,7 @@ var init_external_run_routes = __esm(() => {
60064
60490
  });
60065
60491
 
60066
60492
  // dist/builtin/workflows/src/shared/pending-stage-route-capability.ts
60067
- import { randomUUID as randomUUID11 } from "node:crypto";
60493
+ import { randomUUID as randomUUID12 } from "node:crypto";
60068
60494
  function capabilitiesFor(store) {
60069
60495
  let capabilities = routeCapabilities.get(store);
60070
60496
  if (capabilities === undefined) {
@@ -60077,13 +60503,13 @@ function workflowPendingStageRouteCapability(store, runId) {
60077
60503
  const capabilities = capabilitiesFor(store);
60078
60504
  let capability = capabilities.get(runId);
60079
60505
  if (capability === undefined) {
60080
- capability = randomUUID11();
60506
+ capability = randomUUID12();
60081
60507
  capabilities.set(runId, capability);
60082
60508
  }
60083
60509
  return capability;
60084
60510
  }
60085
60511
  function rotateWorkflowPendingStageRouteCapability(store, runId) {
60086
- const capability = randomUUID11();
60512
+ const capability = randomUUID12();
60087
60513
  capabilitiesFor(store).set(runId, capability);
60088
60514
  return capability;
60089
60515
  }
@@ -61752,7 +62178,7 @@ function isBrokerStatusReport(value2) {
61752
62178
 
61753
62179
  // dist/builtin/intercom/broker/paths.ts
61754
62180
  import { homedir as homedir2 } from "os";
61755
- import { join as join26 } from "path";
62181
+ import { join as join27 } from "path";
61756
62182
  function getHomeDir() {
61757
62183
  if (process.platform === "win32") {
61758
62184
  if (process.env.USERPROFILE)
@@ -61769,7 +62195,7 @@ function expandTildePath(path) {
61769
62195
  if (path === "~")
61770
62196
  return getHomeDir();
61771
62197
  if (path.startsWith("~/") || process.platform === "win32" && path.startsWith("~\\")) {
61772
- return join26(getHomeDir(), path.slice(2));
62198
+ return join27(getHomeDir(), path.slice(2));
61773
62199
  }
61774
62200
  return path;
61775
62201
  }
@@ -61780,28 +62206,31 @@ function getAgentDir5() {
61780
62206
  const piAgentDir = process.env.PI_CODING_AGENT_DIR;
61781
62207
  if (piAgentDir)
61782
62208
  return expandTildePath(piAgentDir);
61783
- return join26(getHomeDir(), ".atomic", "agent");
62209
+ return join27(getHomeDir(), ".atomic", "agent");
61784
62210
  }
61785
62211
  function sanitizePipeSegment(value2) {
61786
62212
  return value2.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "default";
61787
62213
  }
61788
62214
  function getIntercomDirPath(agentDir = getAgentDir5()) {
61789
- return join26(agentDir, "intercom");
62215
+ return join27(agentDir, "intercom");
61790
62216
  }
61791
62217
  function getBrokerPidPath(agentDir = getAgentDir5()) {
61792
- return join26(getIntercomDirPath(agentDir), "broker.pid");
62218
+ return join27(getIntercomDirPath(agentDir), "broker.pid");
61793
62219
  }
61794
62220
  function getBrokerSpawnLockPath(agentDir = getAgentDir5()) {
61795
- return join26(getIntercomDirPath(agentDir), "broker.spawn.lock");
62221
+ return join27(getIntercomDirPath(agentDir), "broker.spawn.lock");
61796
62222
  }
61797
62223
  function getBrokerLogPath(agentDir = getAgentDir5()) {
61798
- return join26(getIntercomDirPath(agentDir), "broker.log");
62224
+ return join27(getIntercomDirPath(agentDir), "broker.log");
62225
+ }
62226
+ function getBrokerStartAnnouncementPath(agentDir = getAgentDir5()) {
62227
+ return join27(getIntercomDirPath(agentDir), "broker.starting");
61799
62228
  }
61800
62229
  function getBrokerSocketPath(platform = process.platform, agentDir = getAgentDir5()) {
61801
62230
  if (platform === "win32") {
61802
62231
  return `\\\\.\\pipe\\pi-intercom-${sanitizePipeSegment(agentDir)}`;
61803
62232
  }
61804
- return join26(getIntercomDirPath(agentDir), "broker.sock");
62233
+ return join27(getIntercomDirPath(agentDir), "broker.sock");
61805
62234
  }
61806
62235
  var BROKER_STORAGE_ENV = "ATOMIC_STORAGE";
61807
62236
  var init_paths = () => {};
@@ -61828,7 +62257,7 @@ function buildSendSignature(to, options) {
61828
62257
  }
61829
62258
 
61830
62259
  // dist/builtin/intercom/broker/pending-send-registry.ts
61831
- import { randomUUID as randomUUID12 } from "crypto";
62260
+ import { randomUUID as randomUUID13 } from "crypto";
61832
62261
 
61833
62262
  class PendingSendRegistry {
61834
62263
  generationTtlMs;
@@ -61887,7 +62316,7 @@ class PendingSendRegistry {
61887
62316
  const generation = this.nextGeneration(messageId);
61888
62317
  const attempt = {
61889
62318
  messageId,
61890
- attemptId: randomUUID12(),
62319
+ attemptId: randomUUID13(),
61891
62320
  signature,
61892
62321
  promise,
61893
62322
  resolve: resolvePromise,
@@ -62103,7 +62532,7 @@ var init_live_route_refusal = __esm(() => {
62103
62532
  });
62104
62533
 
62105
62534
  // dist/builtin/intercom/recoverable-disconnect.ts
62106
- var RECOVERABLE_DISCONNECT_MESSAGE = "Client disconnected", IntercomClientDisconnectedError, IntercomBrokerTimeoutError;
62535
+ var RECOVERABLE_DISCONNECT_MESSAGE = "Client disconnected", IntercomClientDisconnectedError, IntercomBrokerTimeoutError, BROKER_RETIRING_CODE = "broker_retiring", BROKER_RETIRING_REASON = "Intercom broker is retiring; connect to its replacement", IntercomBrokerRetiringError;
62107
62536
  var init_recoverable_disconnect = __esm(() => {
62108
62537
  init_live_route_refusal();
62109
62538
  IntercomClientDisconnectedError = class IntercomClientDisconnectedError extends Error {
@@ -62120,8 +62549,46 @@ var init_recoverable_disconnect = __esm(() => {
62120
62549
  this.name = "IntercomBrokerTimeoutError";
62121
62550
  }
62122
62551
  };
62552
+ IntercomBrokerRetiringError = class IntercomBrokerRetiringError extends Error {
62553
+ intercomRecoverableDisconnect = true;
62554
+ constructor(message = BROKER_RETIRING_REASON, options) {
62555
+ super(message, options);
62556
+ this.name = "IntercomBrokerRetiringError";
62557
+ }
62558
+ };
62123
62559
  });
62124
62560
 
62561
+ // dist/builtin/intercom/broker/socket-liveness.ts
62562
+ import net from "net";
62563
+ function isSocketAnswering(socketPath, timeoutMs = SOCKET_PROBE_TIMEOUT_MS) {
62564
+ return new Promise((resolve) => {
62565
+ const socket = net.connect(socketPath);
62566
+ const finish = (isConnected) => {
62567
+ clearTimeout(timeout);
62568
+ socket.off("connect", onConnect);
62569
+ socket.off("error", onError);
62570
+ resolve(isConnected);
62571
+ };
62572
+ const onConnect = () => {
62573
+ socket.on("error", () => {});
62574
+ socket.end();
62575
+ finish(true);
62576
+ };
62577
+ const onError = () => {
62578
+ socket.destroy();
62579
+ finish(false);
62580
+ };
62581
+ socket.on("connect", onConnect);
62582
+ socket.on("error", onError);
62583
+ const timeout = setTimeout(() => {
62584
+ socket.destroy();
62585
+ finish(false);
62586
+ }, timeoutMs);
62587
+ });
62588
+ }
62589
+ var SOCKET_PROBE_TIMEOUT_MS = 1000;
62590
+ var init_socket_liveness = () => {};
62591
+
62125
62592
  // dist/builtin/intercom/retry-policy.ts
62126
62593
  var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, SEND_RESPONSE_TIMEOUT_MS = 1e4, RECIPIENT_RECEIPT_TIMEOUT_MS = 8000, RECIPIENT_SAVING_REPORT_INTERVAL_MS;
62127
62594
  var init_retry_policy = __esm(() => {
@@ -62134,8 +62601,8 @@ var init_retry_policy = __esm(() => {
62134
62601
 
62135
62602
  // dist/builtin/intercom/broker/client.ts
62136
62603
  import { EventEmitter } from "events";
62137
- import net from "net";
62138
- import { randomUUID as randomUUID13 } from "crypto";
62604
+ import net2 from "net";
62605
+ import { randomUUID as randomUUID14 } from "crypto";
62139
62606
  function connectAborted() {
62140
62607
  return new IntercomClientDisconnectedError({ cause: new Error("Disconnected before the broker connection registered") });
62141
62608
  }
@@ -62159,6 +62626,19 @@ function isBacklogRefusal(error) {
62159
62626
  const code = error.code;
62160
62627
  return code === "ECONNREFUSED" || code === "EAGAIN";
62161
62628
  }
62629
+ function isLostBrokerSignature(error) {
62630
+ if (error instanceof ConnectionClosedBeforeRegistrationError)
62631
+ return true;
62632
+ const code = error.code;
62633
+ return code === "ENOENT" || code === "ECONNRESET" || code === "EPIPE";
62634
+ }
62635
+ async function classifyRegistrationFailure(error) {
62636
+ if (!isLostBrokerSignature(error) || await isSocketAnswering(BROKER_SOCKET))
62637
+ return error;
62638
+ return new IntercomBrokerRetiringError(`Intercom broker went away before it registered this session: ${error.message}`, {
62639
+ cause: error
62640
+ });
62641
+ }
62162
62642
  function toError(error) {
62163
62643
  return error instanceof Error ? error : new Error(String(error));
62164
62644
  }
@@ -62168,15 +62648,22 @@ function isWorkflowFutureStageRosterEntries(value2) {
62168
62648
  function isWorkflowStageRosterEntries(value2) {
62169
62649
  return Array.isArray(value2) && value2.every((entry) => typeof entry === "object" && entry !== null && entry.kind === "workflow-stage" && typeof entry.runId === "string" && typeof entry.stageId === "string" && typeof entry.stageName === "string" && typeof entry.target === "string" && (entry.lifecycle === "pending" || entry.lifecycle === "running") && typeof entry.group === "string" && (entry.sessionId === undefined || typeof entry.sessionId === "string"));
62170
62650
  }
62171
- var BROKER_SOCKET, BROKER_CONNECT_TIMEOUT_MS = 1e4, PENDING_STAGE_ROUTE_ACK_TIMEOUT_MS = 1e4, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS = 5000, BROKER_BACKLOG_RETRIES = 6, BROKER_BACKLOG_RETRY_BASE_MS = 25, HELD_SEND_GRACE_MS = 5000, IntercomPendingStageRouteRefusedError, PENDING_STAGE_ROUTE_REFUSAL_CODES, IntercomClient;
62651
+ var BROKER_SOCKET, BROKER_CONNECT_TIMEOUT_MS = 1e4, PENDING_STAGE_ROUTE_ACK_TIMEOUT_MS = 1e4, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS = 5000, BROKER_BACKLOG_RETRIES = 6, BROKER_BACKLOG_RETRY_BASE_MS = 25, ConnectionClosedBeforeRegistrationError, HELD_SEND_GRACE_MS = 5000, IntercomPendingStageRouteRefusedError, PENDING_STAGE_ROUTE_REFUSAL_CODES, IntercomClient;
62172
62652
  var init_client = __esm(() => {
62173
62653
  init_paths();
62174
62654
  init_pending_send_registry();
62175
62655
  init_group();
62176
62656
  init_recoverable_disconnect();
62657
+ init_socket_liveness();
62177
62658
  init_live_route_refusal();
62178
62659
  init_retry_policy();
62179
62660
  BROKER_SOCKET = getBrokerSocketPath();
62661
+ ConnectionClosedBeforeRegistrationError = class ConnectionClosedBeforeRegistrationError extends Error {
62662
+ constructor() {
62663
+ super("Connection closed before registration");
62664
+ this.name = "ConnectionClosedBeforeRegistrationError";
62665
+ }
62666
+ };
62180
62667
  IntercomPendingStageRouteRefusedError = class IntercomPendingStageRouteRefusedError extends Error {
62181
62668
  connectionKept;
62182
62669
  code;
@@ -62230,7 +62717,7 @@ var init_client = __esm(() => {
62230
62717
  if (this.socket !== socket || socket.destroyed)
62231
62718
  return this.disconnectError ?? new IntercomClientDisconnectedError;
62232
62719
  if (this.healthCheck?.socket !== socket) {
62233
- const requestId = randomUUID13();
62720
+ const requestId = randomUUID14();
62234
62721
  const result = new Promise((resolve) => {
62235
62722
  const finish = (failure) => {
62236
62723
  clearTimeout(timer);
@@ -62262,7 +62749,7 @@ var init_client = __esm(() => {
62262
62749
  }
62263
62750
  return reported;
62264
62751
  }
62265
- constructor(returnAddress = randomUUID13(), options = {}) {
62752
+ constructor(returnAddress = randomUUID14(), options = {}) {
62266
62753
  super();
62267
62754
  if (returnAddress.length === 0)
62268
62755
  throw new Error("Intercom return address must not be empty");
@@ -62344,8 +62831,14 @@ var init_client = __esm(() => {
62344
62831
  } catch (error) {
62345
62832
  if (attempt.signal.aborted)
62346
62833
  throw connectAborted();
62347
- if (!(error instanceof Error) || !isBacklogRefusal(error) || retry >= BROKER_BACKLOG_RETRIES)
62834
+ if (!(error instanceof Error))
62348
62835
  throw error;
62836
+ if (!isBacklogRefusal(error) || retry >= BROKER_BACKLOG_RETRIES) {
62837
+ const classified = await classifyRegistrationFailure(error);
62838
+ if (attempt.signal.aborted)
62839
+ throw connectAborted();
62840
+ throw classified;
62841
+ }
62349
62842
  const backoff = BROKER_BACKLOG_RETRY_BASE_MS * 2 ** retry;
62350
62843
  await abortableDelay(backoff * (0.5 + Math.random() / 2), attempt.signal);
62351
62844
  }
@@ -62362,7 +62855,7 @@ var init_client = __esm(() => {
62362
62855
  this._messageSource = messageSource ?? readSubagentMessageSource();
62363
62856
  this._groups = normalizeGroups(session.groups, session.group);
62364
62857
  return new Promise((resolve, reject) => {
62365
- const socket = net.connect(BROKER_SOCKET);
62858
+ const socket = net2.connect(BROKER_SOCKET);
62366
62859
  this.socket = socket;
62367
62860
  this.disconnectError = null;
62368
62861
  let settled = false;
@@ -62420,7 +62913,7 @@ var init_client = __esm(() => {
62420
62913
  this.emit("disconnected", disconnectError);
62421
62914
  }
62422
62915
  if (wasConnecting) {
62423
- reject(new Error("Connection closed before registration"));
62916
+ reject(new ConnectionClosedBeforeRegistrationError);
62424
62917
  }
62425
62918
  };
62426
62919
  const onSocketError = (err) => {
@@ -62522,7 +63015,7 @@ var init_client = __esm(() => {
62522
63015
  case "registration_failed": {
62523
63016
  if (typeof brokerMessage.reason !== "string")
62524
63017
  throw new Error("Invalid registration_failed message");
62525
- const refusal = isLiveWorkflowStageRouteRefusalCode(brokerMessage.code) ? new IntercomLiveRouteRefusedError(brokerMessage.code, brokerMessage.reason) : new Error(brokerMessage.reason);
63018
+ const refusal = isLiveWorkflowStageRouteRefusalCode(brokerMessage.code) ? new IntercomLiveRouteRefusedError(brokerMessage.code, brokerMessage.reason) : brokerMessage.code === BROKER_RETIRING_CODE ? new IntercomBrokerRetiringError(brokerMessage.reason) : new Error(brokerMessage.reason);
62526
63019
  if (this._sessionId === null) {
62527
63020
  this.emit("_registration_failed", refusal);
62528
63021
  break;
@@ -62917,7 +63410,7 @@ var init_client = __esm(() => {
62917
63410
  return Promise.reject(toError(error));
62918
63411
  }
62919
63412
  return new Promise((resolve, reject) => {
62920
- const requestId = randomUUID13();
63413
+ const requestId = randomUUID14();
62921
63414
  const timeout = setTimeout(() => {
62922
63415
  if (!this.pendingLists.delete(requestId))
62923
63416
  return;
@@ -62949,7 +63442,7 @@ var init_client = __esm(() => {
62949
63442
  } catch (error) {
62950
63443
  return Promise.reject(toError(error));
62951
63444
  }
62952
- const requestId = randomUUID13();
63445
+ const requestId = randomUUID14();
62953
63446
  return new Promise((resolve, reject) => {
62954
63447
  const timeout = setTimeout(() => {
62955
63448
  if (!this.pendingGroupLists.delete(requestId))
@@ -62984,7 +63477,7 @@ var init_client = __esm(() => {
62984
63477
  }
62985
63478
  if (!this.brokerAnswersStatus)
62986
63479
  return Promise.resolve(undefined);
62987
- const requestId = randomUUID13();
63480
+ const requestId = randomUUID14();
62988
63481
  return new Promise((resolve, reject) => {
62989
63482
  const timeout = setTimeout(() => {
62990
63483
  if (!this.pendingBrokerStatus.delete(requestId))
@@ -63023,7 +63516,7 @@ var init_client = __esm(() => {
63023
63516
  } catch (error) {
63024
63517
  return Promise.reject(toError(error));
63025
63518
  }
63026
- const requestId = randomUUID13();
63519
+ const requestId = randomUUID14();
63027
63520
  return new Promise((resolve, reject) => {
63028
63521
  const timeout = setTimeout(() => {
63029
63522
  if (!this.pendingMemberships.delete(requestId))
@@ -63060,7 +63553,7 @@ var init_client = __esm(() => {
63060
63553
  if (!normalizedChildName)
63061
63554
  return Promise.reject(new Error("Child session name is required"));
63062
63555
  return new Promise((resolve, reject) => {
63063
- const requestId = randomUUID13();
63556
+ const requestId = randomUUID14();
63064
63557
  const timeout = setTimeout(() => {
63065
63558
  if (!this.pendingSupervisorAuthorizations.delete(requestId))
63066
63559
  return;
@@ -63110,7 +63603,7 @@ var init_client = __esm(() => {
63110
63603
  } catch (error) {
63111
63604
  return Promise.reject(toError(error));
63112
63605
  }
63113
- const requestId = randomUUID13();
63606
+ const requestId = randomUUID14();
63114
63607
  return new Promise((resolve, reject) => {
63115
63608
  const timeout = setTimeout(() => {
63116
63609
  if (!this.pendingRestoringRecipientRequests.delete(requestId))
@@ -63167,7 +63660,7 @@ var init_client = __esm(() => {
63167
63660
  });
63168
63661
  }
63169
63662
  return new Promise((resolve, reject) => {
63170
- const requestId = randomUUID13();
63663
+ const requestId = randomUUID14();
63171
63664
  const timeout = setTimeout(() => {
63172
63665
  if (!this.pendingStageRouteRegistrations.delete(requestId))
63173
63666
  return;
@@ -63213,7 +63706,7 @@ var init_client = __esm(() => {
63213
63706
  }
63214
63707
  if (!this.brokerClaimsWorkflowInvocations)
63215
63708
  return Promise.resolve(false);
63216
- const requestId = randomUUID13();
63709
+ const requestId = randomUUID14();
63217
63710
  return new Promise((resolve, reject) => {
63218
63711
  this.pendingWorkflowInvocationClaims.set(requestId, { resolve, reject });
63219
63712
  try {
@@ -63231,7 +63724,7 @@ var init_client = __esm(() => {
63231
63724
  } catch (error) {
63232
63725
  return Promise.reject(toError(error));
63233
63726
  }
63234
- const requestId = randomUUID13();
63727
+ const requestId = randomUUID14();
63235
63728
  return new Promise((resolve, reject) => {
63236
63729
  this.pendingLiveWorkflowStageRoutes.set(requestId, { resolve, reject });
63237
63730
  try {
@@ -63299,7 +63792,7 @@ var init_client = __esm(() => {
63299
63792
  } catch (error) {
63300
63793
  return Promise.reject(toError(error));
63301
63794
  }
63302
- const messageId = options.messageId ?? randomUUID13();
63795
+ const messageId = options.messageId ?? randomUUID14();
63303
63796
  let acquired;
63304
63797
  try {
63305
63798
  const pendingSignature = JSON.stringify({
@@ -63385,7 +63878,7 @@ var init_client = __esm(() => {
63385
63878
  } catch (error) {
63386
63879
  return Promise.reject(toError(error));
63387
63880
  }
63388
- const requestId = randomUUID13();
63881
+ const requestId = randomUUID14();
63389
63882
  return new Promise((resolve, reject) => {
63390
63883
  const wrappedResolve = (group) => {
63391
63884
  clearTimeout(timeout);
@@ -63417,59 +63910,53 @@ var init_client = __esm(() => {
63417
63910
  };
63418
63911
  });
63419
63912
 
63420
- // dist/builtin/intercom/broker/socket-liveness.ts
63421
- import net2 from "net";
63422
- function isSocketAnswering(socketPath, timeoutMs = SOCKET_PROBE_TIMEOUT_MS) {
63423
- return new Promise((resolve) => {
63424
- const socket = net2.connect(socketPath);
63425
- const finish = (isConnected) => {
63426
- clearTimeout(timeout);
63427
- socket.off("connect", onConnect);
63428
- socket.off("error", onError);
63429
- resolve(isConnected);
63430
- };
63431
- const onConnect = () => {
63432
- socket.on("error", () => {});
63433
- socket.end();
63434
- finish(true);
63435
- };
63436
- const onError = () => {
63437
- socket.destroy();
63438
- finish(false);
63439
- };
63440
- socket.on("connect", onConnect);
63441
- socket.on("error", onError);
63442
- const timeout = setTimeout(() => {
63443
- socket.destroy();
63444
- finish(false);
63445
- }, timeoutMs);
63446
- });
63913
+ // dist/builtin/intercom/broker/startup-timeout.ts
63914
+ var BROKER_READY_TIMEOUT_MS = 30000, MIN_BROKER_STARTUP_TIMEOUT_MS = 1000;
63915
+
63916
+ // dist/builtin/intercom/broker/start-announcement.ts
63917
+ import { readFileSync as readFileSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
63918
+ function readBrokerStartAnnouncement(announcement) {
63919
+ let text;
63920
+ try {
63921
+ text = readFileSync4(announcement.path, "utf-8");
63922
+ } catch {
63923
+ return;
63924
+ }
63925
+ if (!text.endsWith(`
63926
+ `))
63927
+ return;
63928
+ const [token, pid, ...rest] = text.trim().split(/\s+/u);
63929
+ if (token !== announcement.token || rest.length > 0)
63930
+ return;
63931
+ const parsed = Number(pid);
63932
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
63447
63933
  }
63448
- var SOCKET_PROBE_TIMEOUT_MS = 1000;
63449
- var init_socket_liveness = () => {};
63934
+ var BROKER_ANNOUNCE_PATH_ENV = "ATOMIC_INTERCOM_BROKER_ANNOUNCE_PATH", BROKER_ANNOUNCE_TOKEN_ENV = "ATOMIC_INTERCOM_BROKER_ANNOUNCE_TOKEN";
63935
+ var init_start_announcement = () => {};
63450
63936
 
63451
63937
  // dist/builtin/intercom/broker/spawn.ts
63452
63938
  import { spawn } from "child_process";
63453
- import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync7, openSync as openSync3, readFileSync as readFileSync3, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
63454
- import { join as join27, dirname as dirname11 } from "path";
63939
+ import { randomUUID as randomUUID15 } from "crypto";
63940
+ import { appendFileSync, chmodSync, closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync5, readSync as readSync2, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
63941
+ import { join as join28, dirname as dirname12 } from "path";
63455
63942
  import { fileURLToPath as fileURLToPath4 } from "url";
63456
63943
  import { createRequire as createRequire3 } from "module";
63457
63944
  import { createChildProcessEnvironment as createChildProcessEnvironment4, isBunBinary, processSharedStorageSelection } from "@bastani/atomic";
63458
63945
  function isIntercomPackageRoot(dir) {
63459
- return existsSync5(join27(dir, "package.json")) && existsSync5(join27(dir, "broker"));
63946
+ return existsSync6(join28(dir, "package.json")) && existsSync6(join28(dir, "broker"));
63460
63947
  }
63461
63948
  function resolveIntercomPackageRoot(moduleHref) {
63462
- const here = dirname11(fileURLToPath4(moduleHref));
63949
+ const here = dirname12(fileURLToPath4(moduleHref));
63463
63950
  if (isIntercomPackageRoot(here))
63464
63951
  return here;
63465
- return join27(here, "..");
63952
+ return join28(here, "..");
63466
63953
  }
63467
63954
  function resolveBrokerEntrypoint(packageRoot) {
63468
- const bundled = join27(packageRoot, "broker", "broker.bundle.mjs");
63469
- return existsSync5(bundled) ? bundled : join27(packageRoot, "broker", "broker.ts");
63955
+ const bundled = join28(packageRoot, "broker", "broker.bundle.mjs");
63956
+ return existsSync6(bundled) ? bundled : join28(packageRoot, "broker", "broker.ts");
63470
63957
  }
63471
63958
  function ensurePrivateDirectory(path) {
63472
- mkdirSync7(path, { recursive: true, mode: 448 });
63959
+ mkdirSync8(path, { recursive: true, mode: 448 });
63473
63960
  if (process.platform !== "win32")
63474
63961
  chmodSync(path, 448);
63475
63962
  }
@@ -63482,14 +63969,14 @@ function getCurrentBrokerRuntime() {
63482
63969
  return isBunBinary ? "bun-binary" : "bun-source";
63483
63970
  }
63484
63971
  function requireFromExtensionDir(extensionDir) {
63485
- return createRequire3(join27(extensionDir, "package.json"));
63972
+ return createRequire3(join28(extensionDir, "package.json"));
63486
63973
  }
63487
63974
  function getJitiCliPath(extensionDir = EXTENSION_DIR) {
63488
63975
  try {
63489
63976
  const jitiPackage = requireFromExtensionDir(extensionDir).resolve("jiti/package.json");
63490
- return join27(dirname11(jitiPackage), "lib", "jiti-cli.mjs");
63977
+ return join28(dirname12(jitiPackage), "lib", "jiti-cli.mjs");
63491
63978
  } catch {
63492
- return join27(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
63979
+ return join28(extensionDir, "node_modules", "jiti", "lib", "jiti-cli.mjs");
63493
63980
  }
63494
63981
  }
63495
63982
  function getDefaultBrokerRunnerPath(extensionDir) {
@@ -63511,7 +63998,7 @@ function quoteWindowsArg(value2) {
63511
63998
  return `"${value2.replace(/"/g, '""')}"`;
63512
63999
  }
63513
64000
  function getWindowsHiddenLauncherPath(intercomDir = INTERCOM_DIR) {
63514
- return join27(intercomDir, "broker-launch.vbs");
64001
+ return join28(intercomDir, "broker-launch.vbs");
63515
64002
  }
63516
64003
  function usesDefaultBrokerCommand(brokerCommand, brokerArgs) {
63517
64004
  return brokerCommand === "npx" && brokerArgs.length === 2 && brokerArgs[0] === "--no-install" && brokerArgs[1] === "tsx";
@@ -63538,8 +64025,8 @@ function getWindowsHiddenLauncherScript(commandLine) {
63538
64025
  `);
63539
64026
  }
63540
64027
  function writeWindowsHiddenLauncher(commandLine, launcherPath = getWindowsHiddenLauncherPath()) {
63541
- ensurePrivateDirectory(dirname11(launcherPath));
63542
- writeFileSync4(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
64028
+ ensurePrivateDirectory(dirname12(launcherPath));
64029
+ writeFileSync6(launcherPath, getWindowsHiddenLauncherScript(commandLine), "utf-8");
63543
64030
  return launcherPath;
63544
64031
  }
63545
64032
  function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir = EXTENSION_DIR, platform = process.platform, intercomDir = INTERCOM_DIR, nodePath = process.execPath, runtime = getCurrentBrokerRuntime(), logPath = BROKER_LOG) {
@@ -63567,7 +64054,7 @@ function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir
63567
64054
  args: [...brokerArgs, brokerPath]
63568
64055
  };
63569
64056
  }
63570
- function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore") {
64057
+ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore", announcement) {
63571
64058
  const storage = processSharedStorageSelection();
63572
64059
  return {
63573
64060
  detached: true,
@@ -63575,20 +64062,21 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore")
63575
64062
  cwd: extensionDir,
63576
64063
  env: createChildProcessEnvironment4({
63577
64064
  NODE_NO_WARNINGS: "1",
63578
- ...storage === undefined ? {} : { [BROKER_STORAGE_ENV]: storage }
64065
+ ...storage === undefined ? {} : { [BROKER_STORAGE_ENV]: storage },
64066
+ ...announcement === undefined ? {} : { [BROKER_ANNOUNCE_PATH_ENV]: announcement.path, [BROKER_ANNOUNCE_TOKEN_ENV]: announcement.token }
63579
64067
  }),
63580
64068
  windowsHide: true
63581
64069
  };
63582
64070
  }
63583
64071
  function resetBrokerLog(logPath = BROKER_LOG) {
63584
- ensurePrivateDirectory(dirname11(logPath));
64072
+ ensurePrivateDirectory(dirname12(logPath));
63585
64073
  try {
63586
64074
  const previous = readBrokerLogTail(logPath);
63587
64075
  closeSync3(openSync3(logPath, "w"));
63588
64076
  if (previous.length > 0) {
63589
64077
  try {
63590
64078
  const previousPath = `${logPath}.previous`;
63591
- writeFileSync4(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
64079
+ writeFileSync6(previousPath, Buffer.from(previous).subarray(-BROKER_LOG_TAIL_BYTES), { mode: 384 });
63592
64080
  if (process.platform !== "win32")
63593
64081
  chmodSync(previousPath, 384);
63594
64082
  } catch {}
@@ -63650,6 +64138,12 @@ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = B
63650
64138
  }
63651
64139
  const brokerPath = resolveBrokerEntrypoint(extensionDir);
63652
64140
  const launch = getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir);
64141
+ const announcement = launch.kind === "windows-launcher" ? { path: BROKER_START_ANNOUNCEMENT, token: randomUUID15() } : undefined;
64142
+ if (announcement !== undefined) {
64143
+ try {
64144
+ unlinkSync4(announcement.path);
64145
+ } catch {}
64146
+ }
63653
64147
  if (launch.kind === "windows-launcher") {
63654
64148
  writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);
63655
64149
  }
@@ -63660,7 +64154,7 @@ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = B
63660
64154
  const logFd = launch.kind === "direct" ? openSync3(BROKER_LOG, "a") : undefined;
63661
64155
  let child;
63662
64156
  try {
63663
- child = spawn(launch.command, launch.args, getBrokerSpawnOptions(extensionDir, logFd ?? "ignore"));
64157
+ child = spawn(launch.command, launch.args, getBrokerSpawnOptions(extensionDir, logFd ?? "ignore", announcement));
63664
64158
  } finally {
63665
64159
  if (logFd !== undefined)
63666
64160
  closeSync3(logFd);
@@ -63696,7 +64190,7 @@ ${describeBrokerLog()}`);
63696
64190
  };
63697
64191
  child.once("error", onError);
63698
64192
  child.once("exit", onExit);
63699
- waitForBroker(readyTimeoutMs).then(() => {
64193
+ waitForBroker(readyTimeoutMs, announcement === undefined ? undefined : () => readBrokerStartAnnouncement(announcement)).then(() => {
63700
64194
  cleanup();
63701
64195
  resolve();
63702
64196
  }, (error) => {
@@ -63714,10 +64208,10 @@ async function isBrokerRunning() {
63714
64208
  if (await checkSocketConnectable()) {
63715
64209
  return true;
63716
64210
  }
63717
- if (!existsSync5(BROKER_PID))
64211
+ if (!existsSync6(BROKER_PID))
63718
64212
  return false;
63719
64213
  try {
63720
- const pid = parseInt(readFileSync3(BROKER_PID, "utf-8").trim(), 10);
64214
+ const pid = parseInt(readFileSync5(BROKER_PID, "utf-8").trim(), 10);
63721
64215
  if (!Number.isFinite(pid))
63722
64216
  return false;
63723
64217
  process.kill(pid, 0);
@@ -63742,7 +64236,7 @@ function handSpawnLockToBroker(pid, owner) {
63742
64236
  }
63743
64237
  function ownsSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
63744
64238
  try {
63745
- return readFileSync3(lockPath, "utf-8").startsWith(owner);
64239
+ return readFileSync5(lockPath, "utf-8").startsWith(owner);
63746
64240
  } catch {
63747
64241
  return false;
63748
64242
  }
@@ -63754,7 +64248,7 @@ function acquireSpawnLock() {
63754
64248
  ${Date.now()}
63755
64249
  `;
63756
64250
  try {
63757
- writeFileSync4(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
64251
+ writeFileSync6(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
63758
64252
  return owner;
63759
64253
  } catch (error) {
63760
64254
  if (!(error instanceof Error) || error.code !== "EEXIST") {
@@ -63762,7 +64256,7 @@ ${Date.now()}
63762
64256
  }
63763
64257
  if (isSpawnLockStale()) {
63764
64258
  try {
63765
- unlinkSync3(BROKER_SPAWN_LOCK);
64259
+ unlinkSync4(BROKER_SPAWN_LOCK);
63766
64260
  } catch {}
63767
64261
  continue;
63768
64262
  }
@@ -63780,11 +64274,11 @@ function isProcessAlive(pid) {
63780
64274
  }
63781
64275
  }
63782
64276
  function isSpawnLockStale(lockPath = BROKER_SPAWN_LOCK, nowMs = Date.now()) {
63783
- if (!existsSync5(lockPath)) {
64277
+ if (!existsSync6(lockPath)) {
63784
64278
  return false;
63785
64279
  }
63786
64280
  try {
63787
- const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync3(lockPath, "utf-8").trim().split(`
64281
+ const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync5(lockPath, "utf-8").trim().split(`
63788
64282
  `);
63789
64283
  const spawnerPid = Number.parseInt(spawnerLine, 10);
63790
64284
  const createdAt = Number.parseInt(createdAtLine, 10);
@@ -63802,25 +64296,34 @@ function releaseSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
63802
64296
  if (!ownsSpawnLock(owner, lockPath))
63803
64297
  return;
63804
64298
  try {
63805
- unlinkSync3(lockPath);
64299
+ unlinkSync4(lockPath);
63806
64300
  } catch {}
63807
64301
  }
63808
- async function waitForBroker(timeoutMs = BROKER_READY_TIMEOUT_MS) {
64302
+ async function waitForBroker(timeoutMs = BROKER_READY_TIMEOUT_MS, announcedPid) {
63809
64303
  const start = Date.now();
63810
64304
  let interval = BROKER_POLL_INITIAL_INTERVAL_MS;
63811
64305
  while (Date.now() - start < timeoutMs) {
63812
64306
  if (await checkSocketConnectable()) {
63813
64307
  return;
63814
64308
  }
64309
+ const pid = announcedPid?.();
64310
+ if (pid !== undefined && !isProcessAlive(pid)) {
64311
+ if (await checkSocketConnectable())
64312
+ return;
64313
+ throw new Error(`Intercom broker exited before startup (pid ${pid})
64314
+ ${describeBrokerLog()}`);
64315
+ }
63815
64316
  await sleep(interval);
63816
64317
  interval = Math.min(interval * 2, BROKER_POLL_MAX_INTERVAL_MS);
63817
64318
  }
63818
- throw new Error(`Broker failed to start within timeout
64319
+ throw new Error(`Broker failed to start within timeout (${timeoutMs} ms)
64320
+ ` + "The broker did not answer on its socket in time; it may still be starting, which a busy machine or an empty jiti " + "cache slows. Try again, or raise `brokerStartupTimeoutMs` in the Intercom config.json (default " + `${BROKER_READY_TIMEOUT_MS} ms).
63819
64321
  ${describeBrokerLog()}`);
63820
64322
  }
63821
- var INTERCOM_DIR, EXTENSION_DIR, BROKER_SOCKET2, BROKER_PID, BROKER_SPAWN_LOCK, BROKER_LOG, BROKER_LOG_TAIL_BYTES, BROKER_POLL_INITIAL_INTERVAL_MS = 10, BROKER_POLL_MAX_INTERVAL_MS = 100, BROKER_READY_TIMEOUT_MS = 5000, BROKER_SPAWN_LOCK_MAX_AGE_MS = 60000, INTERNAL_INTERCOM_BROKER_ARG = "--atomic-internal-intercom-broker";
64323
+ var INTERCOM_DIR, EXTENSION_DIR, BROKER_SOCKET2, BROKER_PID, BROKER_SPAWN_LOCK, BROKER_LOG, BROKER_START_ANNOUNCEMENT, BROKER_LOG_TAIL_BYTES, BROKER_POLL_INITIAL_INTERVAL_MS = 10, BROKER_POLL_MAX_INTERVAL_MS = 100, BROKER_SPAWN_LOCK_MAX_AGE_MS = 60000, INTERNAL_INTERCOM_BROKER_ARG = "--atomic-internal-intercom-broker";
63822
64324
  var init_spawn = __esm(() => {
63823
64325
  init_socket_liveness();
64326
+ init_start_announcement();
63824
64327
  init_paths();
63825
64328
  INTERCOM_DIR = getIntercomDirPath();
63826
64329
  EXTENSION_DIR = resolveIntercomPackageRoot(import.meta.url);
@@ -63828,6 +64331,7 @@ var init_spawn = __esm(() => {
63828
64331
  BROKER_PID = getBrokerPidPath();
63829
64332
  BROKER_SPAWN_LOCK = getBrokerSpawnLockPath();
63830
64333
  BROKER_LOG = getBrokerLogPath();
64334
+ BROKER_START_ANNOUNCEMENT = getBrokerStartAnnouncementPath();
63831
64335
  BROKER_LOG_TAIL_BYTES = 8 * 1024;
63832
64336
  });
63833
64337
 
@@ -63852,14 +64356,14 @@ var init_reply_waiter = __esm(() => {
63852
64356
  });
63853
64357
 
63854
64358
  // dist/builtin/intercom/config.ts
63855
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
64359
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
63856
64360
  import { getAgentConfigPaths } from "@bastani/atomic";
63857
64361
  function loadConfig() {
63858
- if (!existsSync6(CONFIG_PATH)) {
64362
+ if (!existsSync7(CONFIG_PATH)) {
63859
64363
  return { ...defaults };
63860
64364
  }
63861
64365
  try {
63862
- const raw = readFileSync4(CONFIG_PATH, "utf-8");
64366
+ const raw = readFileSync6(CONFIG_PATH, "utf-8");
63863
64367
  const parsed = JSON.parse(raw);
63864
64368
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
63865
64369
  throw new Error("Config must be a JSON object");
@@ -63889,6 +64393,12 @@ function loadConfig() {
63889
64393
  }
63890
64394
  config.brokerArgs = brokerArgs;
63891
64395
  }
64396
+ if (Object.hasOwn(parsedConfig, "brokerStartupTimeoutMs")) {
64397
+ if (!Number.isInteger(parsedConfig.brokerStartupTimeoutMs) || Number(parsedConfig.brokerStartupTimeoutMs) < MIN_BROKER_STARTUP_TIMEOUT_MS) {
64398
+ throw new Error(`"brokerStartupTimeoutMs" must be an integer of at least ${MIN_BROKER_STARTUP_TIMEOUT_MS}`);
64399
+ }
64400
+ config.brokerStartupTimeoutMs = Number(parsedConfig.brokerStartupTimeoutMs);
64401
+ }
63892
64402
  if (Object.hasOwn(parsedConfig, "confirmSend")) {
63893
64403
  if (typeof parsedConfig.confirmSend !== "boolean") {
63894
64404
  throw new Error(`"confirmSend" must be a boolean`);
@@ -63931,11 +64441,12 @@ var init_config = __esm(() => {
63931
64441
  init_diagnostics();
63932
64442
  init_reply_waiter();
63933
64443
  CONFIG_PATHS = getAgentConfigPaths("intercom", "config.json");
63934
- CONFIG_PATH = CONFIG_PATHS.find((path) => existsSync6(path)) ?? CONFIG_PATHS[0];
64444
+ CONFIG_PATH = CONFIG_PATHS.find((path) => existsSync7(path)) ?? CONFIG_PATHS[0];
63935
64445
  DEFAULT_BROKER_ARGS = ["--no-install", "tsx"];
63936
64446
  defaults = {
63937
64447
  brokerCommand: DEFAULT_BROKER_COMMAND,
63938
64448
  brokerArgs: [...DEFAULT_BROKER_ARGS],
64449
+ brokerStartupTimeoutMs: BROKER_READY_TIMEOUT_MS,
63939
64450
  confirmSend: false,
63940
64451
  maxPendingAsks: DEFAULT_MAX_PENDING_REPLY_WAITS,
63941
64452
  replyHint: true
@@ -63956,7 +64467,7 @@ var init_reconnect_backoff = __esm(() => {
63956
64467
  });
63957
64468
 
63958
64469
  // dist/builtin/intercom/workflow-route-owner.ts
63959
- import { randomUUID as randomUUID14 } from "node:crypto";
64470
+ import { randomUUID as randomUUID16 } from "node:crypto";
63960
64471
  import { createEventBus, getBuiltinPackagePaths } from "@bastani/atomic";
63961
64472
  function closedError() {
63962
64473
  return new Error("Workflow Intercom route owner closed");
@@ -63964,7 +64475,7 @@ function closedError() {
63964
64475
  function createWorkflowRouteOwner(cwd) {
63965
64476
  const events = createEventBus();
63966
64477
  const config = loadConfig();
63967
- const id = randomUUID14();
64478
+ const id = randomUUID16();
63968
64479
  const routes = new Map;
63969
64480
  const connections = new Map;
63970
64481
  const isCurrent = (state) => routes.get(state.route.runId) === state;
@@ -64028,7 +64539,7 @@ function createWorkflowRouteOwner(cwd) {
64028
64539
  });
64029
64540
  if (extensionDir === undefined)
64030
64541
  throw new Error("Intercom builtin package is unavailable");
64031
- await spawnBrokerIfNeeded(config.brokerCommand, config.brokerArgs, undefined, extensionDir);
64542
+ await spawnBrokerIfNeeded(config.brokerCommand, config.brokerArgs, config.brokerStartupTimeoutMs, extensionDir);
64032
64543
  if (connections.get(connection.key) !== connection)
64033
64544
  throw closedError();
64034
64545
  const client = new IntercomClient(`${id}:pending-stage-route:${connection.key}`, {
@@ -64486,12 +64997,12 @@ var init_sql_pool_usage = __esm(() => {
64486
64997
 
64487
64998
  // dist/builtin/workflows/src/workers/pooled-watch-trace.ts
64488
64999
  import { appendFileSync as appendFileSync2 } from "node:fs";
64489
- import { dirname as dirname12, join as join28, resolve as resolve11 } from "node:path";
65000
+ import { dirname as dirname13, join as join29, resolve as resolve12 } from "node:path";
64490
65001
  function configurePooledWatchTrace(journalPath, processRole) {
64491
65002
  if (setting === undefined || setting === "" || setting === "0")
64492
65003
  return;
64493
65004
  role = processRole;
64494
- file = setting === "1" ? join28(dirname12(resolve11(journalPath)), "pooled-watch-trace.jsonl") : resolve11(setting);
65005
+ file = setting === "1" ? join29(dirname13(resolve12(journalPath)), "pooled-watch-trace.jsonl") : resolve12(setting);
64495
65006
  }
64496
65007
  function tracePooledWatch(step, detail) {
64497
65008
  if (file === undefined)
@@ -64672,10 +65183,10 @@ var init_startup_timeout = () => {};
64672
65183
 
64673
65184
  // dist/builtin/workflows/src/workers/pool-coordinator.ts
64674
65185
  import { fork } from "node:child_process";
64675
- import { randomUUID as randomUUID15 } from "node:crypto";
65186
+ import { randomUUID as randomUUID17 } from "node:crypto";
64676
65187
  import { createWriteStream } from "node:fs";
64677
65188
  import { mkdir as mkdir6, rm as rm3, rmdir } from "node:fs/promises";
64678
- import { dirname as dirname13, join as join29, resolve as resolve12 } from "node:path";
65189
+ import { dirname as dirname14, join as join30, resolve as resolve13 } from "node:path";
64679
65190
  import { setTimeout as delay2 } from "node:timers/promises";
64680
65191
  function isRootLeaseLost(error) {
64681
65192
  return error instanceof StaleLeaseError || error.message.startsWith("Stale lease for run ");
@@ -64684,7 +65195,7 @@ function unconfirmedCleanup(groups) {
64684
65195
  return new Error(`Local worker process cleanup unconfirmed; ${groups.length > 0 ? `process groups ${groups.join(", ")} still running after SIGKILL; ` : ""}permits quarantined`);
64685
65196
  }
64686
65197
  function workerLogDirectory(journalPath, root) {
64687
- return join29(dirname13(resolve12(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
65198
+ return join30(dirname14(resolve13(journalPath)), "worker-logs", encodeURIComponent(root).replaceAll(".", "%2E"));
64688
65199
  }
64689
65200
  function token(work) {
64690
65201
  return {
@@ -64897,6 +65408,9 @@ class PoolCoordinator {
64897
65408
  lease;
64898
65409
  options;
64899
65410
  journal;
65411
+ durable;
65412
+ remote;
65413
+ mirrorTimer;
64900
65414
  queue;
64901
65415
  usageLedger;
64902
65416
  usageTotal;
@@ -64929,6 +65443,7 @@ class PoolCoordinator {
64929
65443
  while (this.inflight.size > 0)
64930
65444
  await Promise.allSettled([...this.inflight]);
64931
65445
  await this.journal?.close().catch(() => {});
65446
+ await this.durable?.close().catch(() => {});
64932
65447
  }
64933
65448
  receive(message) {
64934
65449
  if (message.kind === "request-reply") {
@@ -65018,11 +65533,21 @@ class PoolCoordinator {
65018
65533
  this.desiredControl ??= control;
65019
65534
  configurePooledWatchTrace(options.journalPath, "coordinator");
65020
65535
  this.journal ??= await resolveRunJournal({ journal: { path: options.journalPath } });
65536
+ if (options.durable !== undefined && this.remote === undefined) {
65537
+ this.durable = await openDurableJournal(options.durable);
65538
+ this.remote = new PoolRemoteJournal(this.durable, sqlPoolStorage(this.journal));
65539
+ }
65540
+ await this.remote?.mirror(lease);
65021
65541
  this.usageLedger ??= await openSqlPoolUsage(this.journal);
65022
65542
  this.usageTotal = await this.usageLedger.total(root);
65023
65543
  this.lease = lease;
65024
- const queue = await openSqlPoolQueue(this.journal);
65544
+ const queue = await openSqlPoolQueue(this.journal, this.remote);
65025
65545
  await queue.initialize(lease, COORDINATOR_LEASE_MS);
65546
+ await queue.drainOutbox(lease);
65547
+ if (this.remote !== undefined) {
65548
+ const remote = this.remote;
65549
+ this.mirrorTimer = setInterval(() => void remote.fresh(lease, 0).catch(() => {}), MIRROR_INTERVAL_MS).unref();
65550
+ }
65026
65551
  const retained = [];
65027
65552
  for (const work of await queue.inspect(root))
65028
65553
  if (work.state === "leased" && work.epoch < lease.epoch && (await unconfirmedProcessGroups(this.journal, root, { attempt: work })).length > 0)
@@ -65155,7 +65680,7 @@ class PoolCoordinator {
65155
65680
  throw new Error("Worker exited before delivery acknowledgement");
65156
65681
  const { slot, workerRequest } = target;
65157
65682
  await new Promise((resolve, reject) => {
65158
- const id = randomUUID15();
65683
+ const id = randomUUID17();
65159
65684
  slot.deliveries.set(id, { resolve, reject });
65160
65685
  slot.child.send({ id: workerRequest, delivery: { id, from: payload.from, message: payload.message } }, (error) => {
65161
65686
  if (error) {
@@ -65496,18 +66021,22 @@ class PoolCoordinator {
65496
66021
  admission: options.admission,
65497
66022
  ...this.promptNodes ? { promptNodes: true } : {}
65498
66023
  })
65499
- ], { stdio: ["ignore", "ignore", "pipe", "ipc"], execArgv: [] });
66024
+ ], {
66025
+ stdio: ["ignore", "ignore", "pipe", "ipc"],
66026
+ execArgv: [],
66027
+ ...options.durable === undefined ? {} : { env: { ...process.env, [POOL_DURABLE_JOURNAL_ENV]: JSON.stringify(options.durable) } }
66028
+ });
65500
66029
  const disconnected = new Promise((resolve) => child.once("disconnect", () => resolve()));
65501
66030
  this.children.add(child);
65502
66031
  if (child.pid !== undefined)
65503
66032
  this.port.send({ kind: "spawned", pid: child.pid });
65504
- const worker = randomUUID15();
66033
+ const worker = randomUUID17();
65505
66034
  this.incarnations.set(worker, child);
65506
66035
  const slot = { worker, child, deliveries: new Map, runs: new Set, stageCommands: new Map };
65507
66036
  this.slots.add(slot);
65508
66037
  let ready = false;
65509
66038
  let serial = Promise.resolve();
65510
- const logPath = join29(this.logDirectory, `${worker}.log`);
66039
+ const logPath = join30(this.logDirectory, `${worker}.log`);
65511
66040
  this.logs.set(child, logPath);
65512
66041
  let logFailure;
65513
66042
  const log = createWriteStream(logPath, { flags: "a" });
@@ -65902,6 +66431,7 @@ class PoolCoordinator {
65902
66431
  this.closed = true;
65903
66432
  clearInterval(this.ticker);
65904
66433
  clearInterval(this.recoveryTimer);
66434
+ clearInterval(this.mirrorTimer);
65905
66435
  this.rateLimitOutbox.close();
65906
66436
  let failure;
65907
66437
  let stopping = [];
@@ -65954,8 +66484,10 @@ function childRetryLimit(work, reason) {
65954
66484
  const exportName = work.definition.slice(work.definition.lastIndexOf("#") + 1);
65955
66485
  return `Local worker retry limit: child ${work.childRunId} (${exportName}) ${reason} ${MAX_CHILD_ATTEMPTS} times`;
65956
66486
  }
65957
- var CONTROL_ACKNOWLEDGEMENT_TIMEOUT_MS = 5000, RECOVERY_INTERVAL_MS = 500, TICK_INTERVAL_MS = 100, STALL_THRESHOLD_MS = 500, COORDINATOR_LEASE_MS, 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;
66487
+ var CONTROL_ACKNOWLEDGEMENT_TIMEOUT_MS = 5000, RECOVERY_INTERVAL_MS = 500, TICK_INTERVAL_MS = 100, STALL_THRESHOLD_MS = 500, COORDINATOR_LEASE_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;
65958
66488
  var init_pool_coordinator = __esm(() => {
66489
+ init_internal();
66490
+ init_pool_remote_journal();
65959
66491
  init_resolution();
65960
66492
  init_workflows_host_module();
65961
66493
  init_sql_pool_queue();
@@ -65966,6 +66498,7 @@ var init_pool_coordinator = __esm(() => {
65966
66498
  init_pending_stage_route_capability();
65967
66499
  init_pending_stage_route_readiness();
65968
66500
  init_store();
66501
+ init_pool_journal();
65969
66502
  init_pooled_watch_trace();
65970
66503
  init_resource_admission();
65971
66504
  init_stage_watch_coalesce();
@@ -66780,7 +67313,7 @@ class StageToolExecutionBuffer {
66780
67313
  }
66781
67314
 
66782
67315
  // dist/builtin/workflows/src/workers/pooled-stage-handle.ts
66783
- import { randomUUID as randomUUID16 } from "node:crypto";
67316
+ import { randomUUID as randomUUID18 } from "node:crypto";
66784
67317
 
66785
67318
  class PooledStageHandle {
66786
67319
  runId;
@@ -67098,7 +67631,7 @@ class PooledStageHandle {
67098
67631
  return Promise.reject(new PooledStageDeliveryError("StageNotLive", this.stageName));
67099
67632
  const outcome = Promise.withResolvers();
67100
67633
  const entry = {
67101
- op: randomUUID16(),
67634
+ op: randomUUID18(),
67102
67635
  text,
67103
67636
  intent,
67104
67637
  ...options === undefined ? {} : { options },
@@ -67556,8 +68089,8 @@ var init_pooled_stage_registry = __esm(() => {
67556
68089
 
67557
68090
  // dist/builtin/workflows/src/workers/local-pool.ts
67558
68091
  import { fork as fork2 } from "node:child_process";
67559
- import { randomUUID as randomUUID17 } from "node:crypto";
67560
- import { resolve as resolve13 } from "node:path";
68092
+ import { randomUUID as randomUUID19 } from "node:crypto";
68093
+ import { resolve as resolve14 } from "node:path";
67561
68094
  import { setTimeout as delay3 } from "node:timers/promises";
67562
68095
  import { fileURLToPath as fileURLToPath5 } from "node:url";
67563
68096
  import {
@@ -67741,8 +68274,7 @@ class LocalWorkerPool {
67741
68274
  async prepare(root, store) {
67742
68275
  if (this.closed)
67743
68276
  throw new Error("Local worker pool is closed");
67744
- if (!(this.backend.journal instanceof SqlRunJournal) || resolve13(this.options.journalPath) !== resolve13(this.backend.journal.path) || sqlPoolStorage(this.backend.journal)?.tables.runs !== "wf_runs")
67745
- throw new Error("Local workers require the same default-prefix SQLite journal");
68277
+ const poolJournal = await this.poolJournal();
67746
68278
  if (this.root !== undefined && this.root !== root)
67747
68279
  throw new Error("Local worker pool belongs to another root");
67748
68280
  this.root = root;
@@ -67759,6 +68291,7 @@ class LocalWorkerPool {
67759
68291
  lease: this.lease,
67760
68292
  options: {
67761
68293
  journalPath: this.options.journalPath,
68294
+ ...this.options.durable === undefined ? {} : { durable: this.options.durable },
67762
68295
  workers: this.options.workers,
67763
68296
  leaseMs: this.leaseMs,
67764
68297
  startupTimeoutMs: this.options.startupTimeoutMs ?? defaultStartupTimeoutMs(this.options.workers),
@@ -67767,7 +68300,20 @@ class LocalWorkerPool {
67767
68300
  },
67768
68301
  ...this.desiredControl === undefined ? {} : { control: this.desiredControl }
67769
68302
  });
67770
- this.queue ??= await openSqlPoolQueue(this.backend.journal);
68303
+ this.queue ??= await openSqlPoolQueue(poolJournal, this.options.durable === undefined ? undefined : new PoolRemoteJournal(this.backend.journal, sqlPoolStorage(poolJournal)));
68304
+ }
68305
+ async poolJournal() {
68306
+ const journal = this.backend.journal;
68307
+ if (this.options.durable === undefined) {
68308
+ if (!(journal instanceof SqlRunJournal) || resolve14(this.options.journalPath) !== resolve14(journal.path) || sqlPoolStorage(journal)?.tables.runs !== "wf_runs")
68309
+ throw new Error("Local workers require the same default-prefix SQLite journal");
68310
+ return journal;
68311
+ }
68312
+ if (isLocalPoolJournal(journal))
68313
+ throw new Error("Local workers share a local SQLite journal as it is; a durable journal selection does not apply");
68314
+ const coordination = await openCoordinationJournal(this.options.journalPath);
68315
+ registerPoolJournal(journal, coordination);
68316
+ return coordination;
67771
68317
  }
67772
68318
  async control(state) {
67773
68319
  this.desiredControl = state;
@@ -67850,7 +68396,7 @@ class LocalWorkerPool {
67850
68396
  return { ok: false, refusal: "PoolClosed" };
67851
68397
  if (this.coordinator === undefined)
67852
68398
  return { ok: false, refusal: "StageNotOnWorker" };
67853
- const watch = randomUUID17();
68399
+ const watch = randomUUID19();
67854
68400
  this.stageWatches.set(watch, listener);
67855
68401
  try {
67856
68402
  const result = await this.command({ kind: "stage-watch", watch, ...ref });
@@ -68734,6 +69280,7 @@ var RECONNECT_ATTEMPT_PUBLICATIONS = 40, INTERNAL_WORKFLOW_WORKER_ARG = "--inter
68734
69280
  var init_local_pool = __esm(() => {
68735
69281
  init_internal();
68736
69282
  init_journal_backend();
69283
+ init_pool_remote_journal();
68737
69284
  init_sql_pool_queue();
68738
69285
  init_sql_run_journal();
68739
69286
  init_workflow_tool_abort();
@@ -68748,6 +69295,7 @@ var init_local_pool = __esm(() => {
68748
69295
  init_held_prompt_answers();
68749
69296
  init_host_options();
68750
69297
  init_pool_coordinator();
69298
+ init_pool_journal();
68751
69299
  init_pooled_stage_sources();
68752
69300
  init_pooled_watch_trace();
68753
69301
  init_stage_handoff();
@@ -68757,7 +69305,7 @@ var init_local_pool = __esm(() => {
68757
69305
  });
68758
69306
 
68759
69307
  // dist/builtin/workflows/src/workers/public-pool.ts
68760
- import { resolve as resolve14 } from "node:path";
69308
+ import { resolve as resolve15 } from "node:path";
68761
69309
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
68762
69310
  async function restoreWorkerOptions(backend, options) {
68763
69311
  const source = options.continuation?.source.id ?? options.runId;
@@ -68789,29 +69337,50 @@ async function activatePublicPool(backend, options) {
68789
69337
  throw new Error("Local worker containment is unavailable on Windows; pooled tool processes cannot be enabled");
68790
69338
  if (process.platform !== "linux" && process.platform !== "darwin" || !await hasNativeProcessIdentity() || !await admissionBootIdentity())
68791
69339
  throw new Error("Local worker containment requires native process identity support");
68792
- if (!(backend instanceof JournalDurableBackend) || !(backend.journal instanceof SqlRunJournal) || backend.journal.path === ":memory:" || sqlPoolStorage(backend.journal)?.tables.runs !== "wf_runs")
68793
- throw new Error("Local workers require a default-prefix local SQLite journal");
69340
+ if (!(backend instanceof JournalDurableBackend))
69341
+ throw new Error("Local workers require a journal backend");
69342
+ const local = isLocalPoolJournal(backend.journal);
69343
+ let durable;
69344
+ let poolJournal = backend.journal;
69345
+ let poolPath = local ? backend.journal.path : "";
69346
+ if (!local) {
69347
+ durable = poolDurableJournal(backend.journal);
69348
+ poolPath = coordinationPath(durable);
69349
+ poolJournal = await openCoordinationJournal(poolPath);
69350
+ registerPoolJournal(backend.journal, poolJournal);
69351
+ }
68794
69352
  const cwd = options.cwd ?? process.cwd();
68795
69353
  const localWorkers = options.localWorkers && {
68796
69354
  ...options.localWorkers,
68797
69355
  startupTimeoutMs: undefined,
68798
69356
  leaseMs: undefined,
68799
- definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve14(cwd, source.path) }))
69357
+ definitions: options.localWorkers.definitions.map((source) => ({ ...source, path: resolve15(cwd, source.path) }))
68800
69358
  };
68801
69359
  const admission = options.admission && {
68802
69360
  ...options.admission,
68803
- ...options.admission.userDatabase ? { userDatabase: resolve14(cwd, options.admission.userDatabase) } : {}
69361
+ ...options.admission.userDatabase ? { userDatabase: resolve15(cwd, options.admission.userDatabase) } : {}
68804
69362
  };
69363
+ if (durable !== undefined && admission?.userLimits) {
69364
+ if (admission.userDatabase !== undefined && admission.userDatabase !== resolve15(poolPath))
69365
+ throw new Error(`admission.userDatabase must be omitted, or ${resolve15(poolPath)}, for a journal that is not a local SQLite file`);
69366
+ admission.userDatabase = resolve15(poolPath);
69367
+ }
68805
69368
  const sources = localWorkers && await Promise.all(localWorkers.definitions.map(async (source) => ({ ...source, digest: await definitionDigest(source.path) })));
68806
69369
  const resources = JSON.parse(JSON.stringify({
68807
69370
  ...localWorkers ? { localWorkers, definitions: sources } : {},
68808
- ...admission ? { admission } : {}
69371
+ ...admission ? { admission } : {},
69372
+ ...durable !== undefined && localWorkers ? { coordinator: { host: poolHostId(durable.agentDir), database: coordinationDatabase(durable) } } : {}
68809
69373
  }));
69374
+ const saved = options.effectiveResources?.coordinator;
69375
+ if (saved !== undefined && resources.coordinator !== undefined && saved.host !== resources.coordinator.host)
69376
+ throw new Error(`This root's local workers ran on another machine (${saved.host}). Their work queue and leases are in that machine's pool database, which this machine cannot see, and its workers may still be running children. Resume the root on that machine.`);
69377
+ if (saved !== undefined && resources.coordinator !== undefined && saved.host === resources.coordinator.host && saved.database !== resources.coordinator.database)
69378
+ throw new Error(`This root's local workers keep their work queue and leases in the pool database ${saved.database} on this machine, but the journal is now selected in a way that uses ${resources.coordinator.database}: its adapter, options, prefix or the agent directory changed. Resume the root with the journal selected as it was when the root started.`);
68810
69379
  if (options.effectiveResources && !isDeepStrictEqual2(options.effectiveResources, resources))
68811
69380
  throw new Error("Worker definition compatibility or immutable resource configuration changed");
68812
69381
  options.effectiveResources = resources;
68813
69382
  if (resources.admission)
68814
- await SqlResourceAdmission.open(backend.journal, {
69383
+ await SqlResourceAdmission.open(poolJournal, {
68815
69384
  ...resources.admission,
68816
69385
  root: options.runId,
68817
69386
  holder: "preflight"
@@ -68821,7 +69390,8 @@ async function activatePublicPool(backend, options) {
68821
69390
  const definitions = await Promise.all((sources ?? []).map(async (source) => ({ ...source, definition: await loadWorkerDefinition(source) })));
68822
69391
  const pool = new LocalWorkerPool(backend, {
68823
69392
  rootId: options.runId,
68824
- journalPath: backend.journal.path,
69393
+ journalPath: poolPath,
69394
+ ...durable === undefined ? {} : { durable },
68825
69395
  workers: localWorkers.count,
68826
69396
  definitions,
68827
69397
  admission: resources.admission ?? {},
@@ -68838,13 +69408,12 @@ async function activatePublicPool(backend, options) {
68838
69408
  }
68839
69409
  }
68840
69410
  var init_public_pool = __esm(() => {
68841
- init_internal();
68842
69411
  init_journal_backend();
68843
- init_sql_run_journal();
68844
69412
  init_admission_host();
68845
69413
  init_definitions();
68846
69414
  init_host_options();
68847
69415
  init_local_pool();
69416
+ init_pool_journal();
68848
69417
  init_resource_admission();
68849
69418
  });
68850
69419
 
@@ -69304,7 +69873,7 @@ var init_run_budget = __esm(() => {
69304
69873
  });
69305
69874
 
69306
69875
  // dist/builtin/workflows/src/engine/primitives/parallel.ts
69307
- import { randomUUID as randomUUID18 } from "node:crypto";
69876
+ import { randomUUID as randomUUID20 } from "node:crypto";
69308
69877
  function createParallelPrimitive(input) {
69309
69878
  return async (steps, options = {}) => {
69310
69879
  input.runtime.exit.throwIfWorkflowExitSelected();
@@ -69312,7 +69881,7 @@ function createParallelPrimitive(input) {
69312
69881
  const normalizedOptions = normalizeGroup(options);
69313
69882
  const normalizedSteps = steps.map(normalizeGroup);
69314
69883
  const needsAutoGroup = normalizedOptions.group === true || normalizedSteps.some((step) => step.group === true);
69315
- const autoGroup = needsAutoGroup ? randomUUID18() : undefined;
69884
+ const autoGroup = needsAutoGroup ? randomUUID20() : undefined;
69316
69885
  const resolveAutoGroup = (value2) => value2.group === true && autoGroup ? { ...value2, group: autoGroup } : value2;
69317
69886
  const resolvedOptions = resolveAutoGroup(normalizedOptions);
69318
69887
  const resolvedSteps = normalizedSteps.map(resolveAutoGroup);
@@ -70196,8 +70765,8 @@ function hasUsableContentBlock(block) {
70196
70765
  }
70197
70766
 
70198
70767
  // dist/builtin/workflows/src/shared/stage-session-store.ts
70199
- import { randomUUID as randomUUID19 } from "node:crypto";
70200
- import { dirname as dirname14, resolve as resolve15 } from "node:path";
70768
+ import { randomUUID as randomUUID21 } from "node:crypto";
70769
+ import { dirname as dirname15, resolve as resolve16 } from "node:path";
70201
70770
  import {
70202
70771
  JsonlSessionStore,
70203
70772
  resolveSessionStore,
@@ -70218,7 +70787,7 @@ async function stageSessionStore(options, defaultSessionDir) {
70218
70787
  }
70219
70788
  async function forkStageSession(store, sessionId, cwd, options, destination = store) {
70220
70789
  const source = await store.load(sessionId);
70221
- const id = randomUUID19();
70790
+ const id = randomUUID21();
70222
70791
  await destination.create({
70223
70792
  id,
70224
70793
  version: 4,
@@ -70233,11 +70802,11 @@ async function forkStageSession(store, sessionId, cwd, options, destination = st
70233
70802
  async function migrateLegacyStageSession(store, sessionId, sessionFile) {
70234
70803
  if (sessionFile === undefined || await store.readHeader(sessionId) !== undefined)
70235
70804
  return;
70236
- const location = resolve15(sessionFile);
70237
- const legacy = await JsonlSessionStore.open(dirname14(location), { exactDirectory: true, scanExisting: false });
70805
+ const location = resolve16(sessionFile);
70806
+ const legacy = await JsonlSessionStore.open(dirname15(location), { exactDirectory: true, scanExisting: false });
70238
70807
  try {
70239
70808
  for await (const file of legacy.scanFiles()) {
70240
- if (resolve15(file.location) !== location || file.header.id !== sessionId)
70809
+ if (resolve16(file.location) !== location || file.header.id !== sessionId)
70241
70810
  continue;
70242
70811
  const snapshot = await file.read();
70243
70812
  if (await store.readHeader(sessionId) === undefined)
@@ -70253,6 +70822,7 @@ var init_stage_session_store = () => {};
70253
70822
  // dist/builtin/workflows/src/workers/pool-session-store.ts
70254
70823
  var init_pool_session_store = __esm(() => {
70255
70824
  init_internal();
70825
+ init_pool_journal();
70256
70826
  });
70257
70827
 
70258
70828
  // dist/builtin/workflows/src/durable/completed-catalog-index.ts
@@ -76713,9 +77283,9 @@ var init_stage_runner_controller = __esm(() => {
76713
77283
  });
76714
77284
 
76715
77285
  // dist/builtin/workflows/src/runs/foreground/stage-runner-output.ts
76716
- import { createHash as createHash5 } from "node:crypto";
77286
+ import { createHash as createHash6 } from "node:crypto";
76717
77287
  import { mkdir as mkdir7, writeFile as writeFile10 } from "node:fs/promises";
76718
- import { basename as basename5, dirname as dirname15, isAbsolute as isAbsolute11, join as join30, resolve as resolve16 } from "node:path";
77288
+ import { basename as basename6, dirname as dirname16, isAbsolute as isAbsolute11, join as join31, resolve as resolve17 } from "node:path";
76719
77289
  function normalizeMaxOutput2(maxOutput) {
76720
77290
  return {
76721
77291
  bytes: maxOutput?.bytes ?? DEFAULT_MAX_OUTPUT_BYTES,
@@ -76777,8 +77347,8 @@ function formatByteSize(bytes) {
76777
77347
  return `${value2.toFixed(1)} ${units[unitIndex]}`;
76778
77348
  }
76779
77349
  function transcriptPath(runId, outputPath) {
76780
- const digest = createHash5("sha256").update(outputPath).digest("hex").slice(0, 16);
76781
- return join30(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename5(outputPath)}.transcript.md`);
77350
+ const digest = createHash6("sha256").update(outputPath).digest("hex").slice(0, 16);
77351
+ return join31(workflowArtifactRunPath(runId), "transcripts", `${digest}-${basename6(outputPath)}.transcript.md`);
76782
77352
  }
76783
77353
  function appendContent(lines, content) {
76784
77354
  if (typeof content === "string") {
@@ -76823,7 +77393,7 @@ function renderTranscript(messages, fallbackOutput) {
76823
77393
  `);
76824
77394
  }
76825
77395
  function savedOutputReference(outputPath, fullOutput, transcriptPathValue, transcriptText, transcriptAvailable, warning) {
76826
- const absolutePath = resolve16(outputPath);
77396
+ const absolutePath = resolve17(outputPath);
76827
77397
  const bytes = Buffer.byteLength(fullOutput, "utf8");
76828
77398
  const lines = countLines(fullOutput);
76829
77399
  const transcriptBytes = Buffer.byteLength(transcriptText, "utf8");
@@ -76838,8 +77408,8 @@ function resolveOutputPath(output, runtimeCwd, requestedCwd) {
76838
77408
  return;
76839
77409
  if (isAbsolute11(output))
76840
77410
  return output;
76841
- const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve16(runtimeCwd, requestedCwd);
76842
- return resolve16(baseCwd, output);
77411
+ const baseCwd = requestedCwd === undefined ? runtimeCwd : isAbsolute11(requestedCwd) ? requestedCwd : resolve17(runtimeCwd, requestedCwd);
77412
+ return resolve17(baseCwd, output);
76843
77413
  }
76844
77414
  function degenerateWarning(fullOutput) {
76845
77415
  return fullOutput.trim().length === 0 ? "WARNING: the stage artifact is empty; search the companion transcript for this stage's work." : undefined;
@@ -76898,7 +77468,7 @@ async function finalizePromptOutput(fullOutput, outputOptions, runtimeCwd, runId
76898
77468
  const transcriptFile = transcriptPath(runId, outputPath);
76899
77469
  const transcript = renderTranscript(messages, fullOutput);
76900
77470
  try {
76901
- await mkdir7(dirname15(outputPath), { recursive: true });
77471
+ await mkdir7(dirname16(outputPath), { recursive: true });
76902
77472
  await writeFile10(outputPath, fullOutput, "utf8");
76903
77473
  } catch (err) {
76904
77474
  return `${displayOutput}
@@ -76910,7 +77480,7 @@ ${err instanceof Error ? err.message : String(err)}`;
76910
77480
  let transcriptError;
76911
77481
  try {
76912
77482
  await ensureWorkflowArtifactRunDirectory(runId);
76913
- await mkdir7(dirname15(transcriptFile), { recursive: true });
77483
+ await mkdir7(dirname16(transcriptFile), { recursive: true });
76914
77484
  await writeFile10(transcriptFile, transcript, "utf8");
76915
77485
  transcriptAvailable = true;
76916
77486
  } catch (err) {
@@ -78941,7 +79511,7 @@ var init_executor = __esm(() => {
78941
79511
  });
78942
79512
 
78943
79513
  // dist/builtin/workflows/src/runs/foreground/sdk-run.ts
78944
- import { randomUUID as randomUUID20 } from "node:crypto";
79514
+ import { randomUUID as randomUUID22 } from "node:crypto";
78945
79515
  async function run2(def, inputs, callerOpts = {}) {
78946
79516
  let opts = callerOpts;
78947
79517
  const store2 = opts.store === undefined || opts.store === store ? currentWorkflowStore() : opts.store;
@@ -78952,7 +79522,7 @@ async function run2(def, inputs, callerOpts = {}) {
78952
79522
  if (opts.journal === undefined && opts.durableBackend === undefined && ownedBackend === undefined) {
78953
79523
  bindStoreDurableBackend(store2, backend);
78954
79524
  }
78955
- const runId = opts.runId ?? randomUUID20();
79525
+ const runId = opts.runId ?? randomUUID22();
78956
79526
  if (sourceRunId !== undefined || opts.localWorkers || opts.admission) {
78957
79527
  opts = await restoreWorkerOptions(backend, { ...opts, runId });
78958
79528
  }