@gobing-ai/spur 0.3.77 → 0.3.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/spur.js CHANGED
@@ -45,9 +45,10 @@ var __export = (target, all) => {
45
45
  });
46
46
  };
47
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
+ var __promiseAll = (args) => Promise.all(args);
48
49
  var __require = import.meta.require;
49
50
 
50
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/errors.js
51
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/errors.js
51
52
  var ErrorCode, AppError, ValidationError;
52
53
  var init_errors = __esm(() => {
53
54
  ErrorCode = {
@@ -72,7 +73,7 @@ var init_errors = __esm(() => {
72
73
  };
73
74
  });
74
75
 
75
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/api-response.js
76
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/api-response.js
76
77
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
77
78
  var init_api_response = __esm(() => {
78
79
  init_errors();
@@ -95,13 +96,13 @@ var init_api_response = __esm(() => {
95
96
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
96
97
  });
97
98
 
98
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/cursor.js
99
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/cursor.js
99
100
  var init_cursor = () => {};
100
101
 
101
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
102
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
102
103
  var init_event_severity = () => {};
103
104
 
104
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/object.js
105
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/object.js
105
106
  function isPlainObject(value) {
106
107
  return typeof value === "object" && value !== null && !Array.isArray(value);
107
108
  }
@@ -119,7 +120,7 @@ function deepMerge(target, source) {
119
120
  return result;
120
121
  }
121
122
 
122
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/output.js
123
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/output.js
123
124
  function processStream(name) {
124
125
  const proc = globalThis.process;
125
126
  const stream = proc?.[name];
@@ -140,7 +141,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
140
141
  }
141
142
  var defaultStdoutTarget, defaultStderrTarget;
142
143
 
143
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.57/node_modules/@gobing-ai/ts-utils/dist/index.js
144
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.60/node_modules/@gobing-ai/ts-utils/dist/index.js
144
145
  var init_dist = __esm(() => {
145
146
  init_api_response();
146
147
  init_cursor();
@@ -21763,7 +21764,7 @@ var init_zod = __esm(() => {
21763
21764
  init_external();
21764
21765
  });
21765
21766
 
21766
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/config.js
21767
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/config.js
21767
21768
  function getProcessEnv() {
21768
21769
  return process.env;
21769
21770
  }
@@ -21841,7 +21842,7 @@ var init_config = __esm(() => {
21841
21842
  };
21842
21843
  });
21843
21844
 
21844
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21845
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21845
21846
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
21846
21847
  import { dirname, resolve as resolvePath } from "path";
21847
21848
  function createNodeFileSystem(root, paths) {
@@ -21928,7 +21929,7 @@ function findProjectRoot(startDir) {
21928
21929
  }
21929
21930
  var init_file_system_node = () => {};
21930
21931
 
21931
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
21932
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
21932
21933
  var DbModuleNotInstalledError;
21933
21934
  var init_db_errors = __esm(() => {
21934
21935
  DbModuleNotInstalledError = class DbModuleNotInstalledError extends Error {
@@ -29139,12 +29140,12 @@ var init_execa = __esm(() => {
29139
29140
  } = getIpcExport());
29140
29141
  });
29141
29142
 
29142
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
29143
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
29143
29144
  import { isatty } from "tty";
29144
29145
  function processEventSeverity(reason, exitCode) {
29145
29146
  if (reason === "error")
29146
29147
  return "error";
29147
- if (reason === "timeout")
29148
+ if (reason === "timeout" || reason === "cancelled")
29148
29149
  return "warning";
29149
29150
  if (exitCode !== null && exitCode !== 0)
29150
29151
  return "warning";
@@ -29171,15 +29172,19 @@ class NodeProcessExecutor {
29171
29172
  }
29172
29173
  async runUntraced(options) {
29173
29174
  const args = options.args ?? [];
29175
+ const deadline = resolveDeadline(options.timeout, this.config.defaultTimeout);
29176
+ const killGraceMs = resolveKillGraceMs(options.killGraceMs);
29177
+ const groupOwned = process.platform !== "win32" && (typeof deadline === "number" || options.signal !== undefined);
29174
29178
  const execaOptions = buildExecaOptions({
29175
29179
  cwd: options.cwd ?? this.config.paths?.cwd,
29176
29180
  env: options.env,
29177
- timeout: options.timeout ?? this.config.defaultTimeout,
29181
+ timeout: typeof deadline === "number" ? deadline : undefined,
29178
29182
  maxOutput: options.maxOutput ?? this.config.defaultMaxOutput,
29179
29183
  rejectOnError: options.rejectOnError ?? false,
29180
29184
  outputPolicy: this.config.output,
29181
29185
  forceBuffered: options.forceBuffered ?? false,
29182
- signal: options.signal
29186
+ signal: options.signal,
29187
+ groupOwned
29183
29188
  });
29184
29189
  const startedAt = Date.now();
29185
29190
  const startedIso = new Date(startedAt).toISOString();
@@ -29200,8 +29205,17 @@ class NodeProcessExecutor {
29200
29205
  severity: "info",
29201
29206
  ...options.label !== undefined ? { label: options.label } : {}
29202
29207
  });
29208
+ let ownership;
29203
29209
  try {
29204
29210
  const subprocess = execa(options.command, args, execaOptions);
29211
+ if (groupOwned && subprocess.pid !== undefined) {
29212
+ ownership = ownProcessGroupLifecycle({
29213
+ pid: subprocess.pid,
29214
+ deadlineMs: typeof deadline === "number" ? deadline : undefined,
29215
+ signal: options.signal,
29216
+ graceMs: killGraceMs
29217
+ });
29218
+ }
29205
29219
  if (subprocess.pid !== undefined) {
29206
29220
  this.config.registry?.update(registryId, { pid: subprocess.pid });
29207
29221
  if (options.onSpawn !== undefined) {
@@ -29210,10 +29224,11 @@ class NodeProcessExecutor {
29210
29224
  } catch {}
29211
29225
  }
29212
29226
  }
29213
- const stopGroupCancellation = observeProcessGroupCancellation(subprocess, options.signal);
29227
+ const stopOwnedTermination = () => ownership?.stop();
29214
29228
  observeOutput(subprocess.stdout, "stdout", options.onOutput);
29215
29229
  observeOutput(subprocess.stderr, "stderr", options.onOutput);
29216
- const result = await subprocess.finally(stopGroupCancellation);
29230
+ const result = await subprocess.finally(stopOwnedTermination);
29231
+ const ownedOutcome = ownership !== undefined ? await ownership.finish() : undefined;
29217
29232
  const processResult = {
29218
29233
  command: options.command,
29219
29234
  args,
@@ -29221,13 +29236,15 @@ class NodeProcessExecutor {
29221
29236
  stdout: asString(result.stdout),
29222
29237
  stderr: asString(result.stderr),
29223
29238
  ...result.signalDescription !== undefined ? { signal: result.signalDescription } : {},
29224
- durationMs: result.durationMs
29239
+ durationMs: result.durationMs,
29240
+ outcome: ownedOutcome ?? (result.signalDescription !== undefined ? "signal" : "exit")
29225
29241
  };
29226
29242
  this.completeRegistry(registryId, processResult.exitCode);
29227
29243
  this.emitExitedFromResult(options, processResult, result);
29228
29244
  return processResult;
29229
29245
  } catch (error51) {
29230
29246
  const failed = error51;
29247
+ const ownedOutcome = ownership !== undefined ? await ownership.finish() : undefined;
29231
29248
  const processResult = {
29232
29249
  command: options.command,
29233
29250
  args,
@@ -29235,7 +29252,8 @@ class NodeProcessExecutor {
29235
29252
  stdout: asString(failed.stdout),
29236
29253
  stderr: asString(failed.stderr),
29237
29254
  ...failed.signalDescription !== undefined ? { signal: failed.signalDescription } : failed.signal !== undefined ? { signal: failed.signal } : {},
29238
- durationMs: failed.durationMs ?? Date.now() - startedAt
29255
+ durationMs: failed.durationMs ?? Date.now() - startedAt,
29256
+ outcome: ownedOutcome ?? classifyFailedCompletion(failed)
29239
29257
  };
29240
29258
  this.completeRegistry(registryId, processResult.exitCode);
29241
29259
  this.emitExitedFromResult(options, processResult, error51, error51);
@@ -29335,7 +29353,7 @@ class NodeProcessExecutor {
29335
29353
  });
29336
29354
  }
29337
29355
  emitExitedFromResult(options, result, completion, error51) {
29338
- const reason = isTimedOut(completion) ? "timeout" : result.signal !== undefined ? "signal" : error51 ? "error" : "exit";
29356
+ const reason = result.outcome ?? (isTimedOut(completion) ? "timeout" : result.signal !== undefined ? "signal" : error51 ? "error" : "exit");
29339
29357
  this.emitProcessEvent("process.exited", {
29340
29358
  command: result.command,
29341
29359
  args: result.args,
@@ -29442,30 +29460,110 @@ function buildExecaOptions(opts) {
29442
29460
  ...mode === "pipe" ? { stdout: "pipe", stderr: "pipe" } : streamToTerminal ? { stdout: ["inherit", "pipe"], stderr: ["inherit", "pipe"] } : { all: true },
29443
29461
  ...opts.cwd !== undefined ? { cwd: opts.cwd } : {},
29444
29462
  ...opts.env !== undefined ? { env: opts.env } : {},
29445
- ...opts.timeout !== undefined ? { timeout: opts.timeout } : {},
29463
+ ...opts.timeout !== undefined && !opts.groupOwned ? { timeout: opts.timeout } : {},
29446
29464
  ...opts.maxOutput !== undefined ? { maxBuffer: opts.maxOutput } : {},
29447
- ...opts.signal !== undefined ? {
29448
- cancelSignal: opts.signal,
29449
- ...process.platform !== "win32" ? { detached: true } : {}
29450
- } : {}
29465
+ ...opts.groupOwned ? { detached: true } : {},
29466
+ ...opts.signal !== undefined && !opts.groupOwned ? { cancelSignal: opts.signal } : {}
29451
29467
  };
29452
29468
  }
29453
- function observeProcessGroupCancellation(subprocess, signal) {
29454
- const pid = subprocess.pid;
29455
- if (signal === undefined || process.platform === "win32" || pid === undefined)
29456
- return () => {};
29457
- const abort = () => {
29458
- try {
29459
- process.kill(-pid, "SIGTERM");
29460
- } catch {
29461
- subprocess.kill("SIGTERM");
29469
+ function resolveDeadline(optionTimeout, defaultTimeout) {
29470
+ if (optionTimeout === null)
29471
+ return null;
29472
+ const candidate = optionTimeout === undefined ? defaultTimeout : optionTimeout;
29473
+ if (candidate === undefined || candidate === null)
29474
+ return candidate;
29475
+ if (!Number.isInteger(candidate) || candidate <= 0 || candidate > MAX_TIMEOUT_MS) {
29476
+ throw new TypeError(`Process timeout must be a positive integer within the native timer range (1-${MAX_TIMEOUT_MS} ms), got ${String(candidate)}`);
29477
+ }
29478
+ return candidate;
29479
+ }
29480
+ function resolveKillGraceMs(optionGraceMs) {
29481
+ if (optionGraceMs === undefined)
29482
+ return DEFAULT_KILL_GRACE_MS;
29483
+ if (!Number.isInteger(optionGraceMs) || optionGraceMs < 0 || optionGraceMs > MAX_TIMEOUT_MS) {
29484
+ throw new TypeError(`Process killGraceMs must be a non-negative integer within the native timer range (0-${MAX_TIMEOUT_MS} ms), got ${String(optionGraceMs)}`);
29485
+ }
29486
+ return optionGraceMs;
29487
+ }
29488
+ function groupExists(pid) {
29489
+ try {
29490
+ process.kill(-pid, 0);
29491
+ return true;
29492
+ } catch (error51) {
29493
+ return error51.code === "EPERM";
29494
+ }
29495
+ }
29496
+ function signalGroup(pid, signal) {
29497
+ try {
29498
+ process.kill(-pid, signal);
29499
+ return true;
29500
+ } catch {
29501
+ return false;
29502
+ }
29503
+ }
29504
+ async function waitForGroupExit(pid, budgetMs) {
29505
+ const giveUpAt = Date.now() + budgetMs;
29506
+ while (groupExists(pid)) {
29507
+ if (Date.now() >= giveUpAt)
29508
+ return false;
29509
+ await new Promise((resolve) => setTimeout(resolve, GROUP_POLL_INTERVAL_MS));
29510
+ }
29511
+ return true;
29512
+ }
29513
+ async function reapProcessGroup(pid, graceMs) {
29514
+ if (!signalGroup(pid, "SIGTERM"))
29515
+ return false;
29516
+ if (await waitForGroupExit(pid, graceMs))
29517
+ return true;
29518
+ signalGroup(pid, "SIGKILL");
29519
+ await waitForGroupExit(pid, GROUP_KILL_PATIENCE_MS);
29520
+ return true;
29521
+ }
29522
+ function ownProcessGroupLifecycle(ownership) {
29523
+ const { pid, graceMs } = ownership;
29524
+ let trigger;
29525
+ let termination;
29526
+ let timer;
29527
+ const initiate = (reason) => {
29528
+ if (trigger !== undefined)
29529
+ return;
29530
+ trigger = reason;
29531
+ termination = reapProcessGroup(pid, graceMs);
29532
+ };
29533
+ if (ownership.deadlineMs !== undefined) {
29534
+ timer = setTimeout(() => initiate("timeout"), ownership.deadlineMs);
29535
+ }
29536
+ const onAbort = () => initiate("cancelled");
29537
+ if (ownership.signal !== undefined) {
29538
+ if (ownership.signal.aborted)
29539
+ onAbort();
29540
+ else
29541
+ ownership.signal.addEventListener("abort", onAbort, { once: true });
29542
+ }
29543
+ return {
29544
+ finish: async () => {
29545
+ if (trigger === undefined) {
29546
+ await reapProcessGroup(pid, graceMs);
29547
+ return;
29548
+ }
29549
+ return await termination ? trigger : undefined;
29550
+ },
29551
+ stop: () => {
29552
+ if (timer !== undefined)
29553
+ clearTimeout(timer);
29554
+ ownership.signal?.removeEventListener("abort", onAbort);
29462
29555
  }
29463
29556
  };
29464
- if (signal.aborted)
29465
- abort();
29466
- else
29467
- signal.addEventListener("abort", abort, { once: true });
29468
- return () => signal.removeEventListener("abort", abort);
29557
+ }
29558
+ function classifyFailedCompletion(error51) {
29559
+ if (error51.timedOut === true)
29560
+ return "timeout";
29561
+ if (error51.isCanceled === true)
29562
+ return "cancelled";
29563
+ if (error51.isTerminated === true || error51.signalDescription !== undefined || error51.signal !== undefined) {
29564
+ return "signal";
29565
+ }
29566
+ return "error";
29469
29567
  }
29470
29568
  function observeOutput(stream, name, observer) {
29471
29569
  if (!stream || !observer)
@@ -29498,12 +29596,13 @@ function isTimedOut(error51) {
29498
29596
  function errorMessage(error51) {
29499
29597
  return error51 instanceof Error ? error51.message : String(error51);
29500
29598
  }
29599
+ var MAX_TIMEOUT_MS = 2147483647, DEFAULT_KILL_GRACE_MS = 5000, GROUP_POLL_INTERVAL_MS = 25, GROUP_KILL_PATIENCE_MS = 2000;
29501
29600
  var init_process_executor = __esm(() => {
29502
29601
  init_execa();
29503
29602
  init_config();
29504
29603
  });
29505
29604
 
29506
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
29605
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
29507
29606
  function getNodeFileSystem() {
29508
29607
  if (!_nodeFileSystem)
29509
29608
  _nodeFileSystem = createNodeFileSystem();
@@ -29563,7 +29662,7 @@ var init_runtime_node_bun = __esm(() => {
29563
29662
  };
29564
29663
  });
29565
29664
 
29566
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/context.js
29665
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/context.js
29567
29666
  class RuntimeContext {
29568
29667
  scope;
29569
29668
  runtimeName;
@@ -29633,7 +29732,7 @@ var init_context = __esm(() => {
29633
29732
  init_runtime_node_bun();
29634
29733
  });
29635
29734
 
29636
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/path.js
29735
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/path.js
29637
29736
  function normalizeSeparators(path6) {
29638
29737
  return path6.replaceAll("\\", "/");
29639
29738
  }
@@ -29694,17 +29793,17 @@ var init_path = __esm(() => {
29694
29793
  SEP = globalThis.process?.platform === "win32" ? "\\" : "/";
29695
29794
  });
29696
29795
 
29697
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
29796
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
29698
29797
  var REMOTE_SCHEMA_MAX_BYTES;
29699
29798
  var init_schema_validation = __esm(() => {
29700
29799
  init_dist2();
29701
29800
  REMOTE_SCHEMA_MAX_BYTES = 5 * 1024 * 1024;
29702
29801
  });
29703
29802
 
29704
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/types.js
29803
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/types.js
29705
29804
  var init_types = () => {};
29706
29805
 
29707
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/index.js
29806
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/index.js
29708
29807
  var init_dist3 = __esm(() => {
29709
29808
  init_config();
29710
29809
  init_context();
@@ -29713,7 +29812,7 @@ var init_dist3 = __esm(() => {
29713
29812
  init_types();
29714
29813
  });
29715
29814
 
29716
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+91f4e61e91341aed/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
29815
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+c1fd52b57c6e210c/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
29717
29816
  import { Database } from "bun:sqlite";
29718
29817
  var init_bun_sqlite = () => {};
29719
29818
 
@@ -34143,7 +34242,7 @@ var init_bun_sqlite2 = __esm(() => {
34143
34242
  init_session2();
34144
34243
  });
34145
34244
 
34146
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
34245
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
34147
34246
  var inboxMessages;
34148
34247
  var init_inbox_messages = __esm(() => {
34149
34248
  init_sqlite_core();
@@ -34162,7 +34261,7 @@ var init_inbox_messages = __esm(() => {
34162
34261
  }, (table2) => [index("idx_inbox_messages_to_status").on(table2.toId, table2.status)]);
34163
34262
  });
34164
34263
 
34165
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/common.js
34264
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/common.js
34166
34265
  function nowTimestamp() {
34167
34266
  return Date.now();
34168
34267
  }
@@ -34191,7 +34290,7 @@ var init_common3 = __esm(() => {
34191
34290
  appendOnlyColumns = buildAppendOnlyColumns();
34192
34291
  });
34193
34292
 
34194
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
34293
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
34195
34294
  var queueJobs;
34196
34295
  var init_queue_jobs = __esm(() => {
34197
34296
  init_sqlite_core();
@@ -34207,11 +34306,15 @@ var init_queue_jobs = __esm(() => {
34207
34306
  nextRetryAt: integer2("next_retry_at"),
34208
34307
  lastError: text("last_error"),
34209
34308
  processingAt: integer2("processing_at"),
34210
- expiresAt: integer2("expires_at")
34309
+ expiresAt: integer2("expires_at"),
34310
+ timeoutMs: integer2("timeout_ms"),
34311
+ timeoutUnlimited: integer2("timeout_unlimited").notNull().default(0),
34312
+ attemptToken: text("attempt_token"),
34313
+ leaseExpiresAt: integer2("lease_expires_at")
34211
34314
  }, (table2) => [index("queue_jobs_ready_idx").on(table2.status, table2.nextRetryAt, table2.createdAt)]);
34212
34315
  });
34213
34316
 
34214
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
34317
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
34215
34318
  var exports_runtime = {};
34216
34319
  __export(exports_runtime, {
34217
34320
  queueJobs: () => queueJobs,
@@ -34222,7 +34325,7 @@ var init_runtime = __esm(() => {
34222
34325
  init_queue_jobs();
34223
34326
  });
34224
34327
 
34225
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
34328
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
34226
34329
  var exports_bun_sqlite = {};
34227
34330
  __export(exports_bun_sqlite, {
34228
34331
  BunSqliteAdapter: () => BunSqliteAdapter
@@ -34533,7 +34636,7 @@ var init_d1 = __esm(() => {
34533
34636
  init_session3();
34534
34637
  });
34535
34638
 
34536
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
34639
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
34537
34640
  var exports_d1 = {};
34538
34641
  __export(exports_d1, {
34539
34642
  D1Adapter: () => D1Adapter
@@ -34597,7 +34700,7 @@ var init_d12 = __esm(() => {
34597
34700
  init_runtime();
34598
34701
  });
34599
34702
 
34600
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/adapter.js
34703
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/adapter.js
34601
34704
  async function createDbAdapter(config3) {
34602
34705
  switch (config3.driver) {
34603
34706
  case "bun-sqlite": {
@@ -34631,7 +34734,7 @@ var init_drizzle_orm = __esm(() => {
34631
34734
  init_view_common();
34632
34735
  });
34633
34736
 
34634
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/query-spec.js
34737
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/query-spec.js
34635
34738
  function compilePredicate(predicate) {
34636
34739
  if ("and" in predicate) {
34637
34740
  const parts = predicate.and.map(compilePredicate).filter((p) => p !== undefined);
@@ -34669,7 +34772,7 @@ var init_query_spec = __esm(() => {
34669
34772
  };
34670
34773
  });
34671
34774
 
34672
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/base-dao.js
34775
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/base-dao.js
34673
34776
  function asSelectQuery(query) {
34674
34777
  return query;
34675
34778
  }
@@ -34711,7 +34814,7 @@ var init_base_dao = __esm(() => {
34711
34814
  init_query_spec();
34712
34815
  });
34713
34816
 
34714
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/embedded-migrations.js
34817
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/embedded-migrations.js
34715
34818
  var embeddedMigrations;
34716
34819
  var init_embedded_migrations = __esm(() => {
34717
34820
  embeddedMigrations = [
@@ -34739,11 +34842,16 @@ var init_embedded_migrations = __esm(() => {
34739
34842
  tag: "0004_inbox_messages_to_status_idx",
34740
34843
  sql: "CREATE INDEX `idx_inbox_messages_to_status` ON `inbox_messages` (`to_id`,`status`);",
34741
34844
  hash: "3c00f1bce4f569e442f3142df31ff478d6c9b3d460824d46575f50a324bfae61"
34845
+ },
34846
+ {
34847
+ tag: "0005_queue_attempt_ownership",
34848
+ sql: "ALTER TABLE `queue_jobs` ADD `timeout_ms` integer;\nALTER TABLE `queue_jobs` ADD `timeout_unlimited` integer DEFAULT 0 NOT NULL;\nALTER TABLE `queue_jobs` ADD `attempt_token` text;\nALTER TABLE `queue_jobs` ADD `lease_expires_at` integer;",
34849
+ hash: "f6a4eaf11eee838f424515e57eca3a46539260bb2fb5b0b112870ca5ed38d040"
34742
34850
  }
34743
34851
  ];
34744
34852
  });
34745
34853
 
34746
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
34854
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
34747
34855
  var EntityDao;
34748
34856
  var init_entity_dao = __esm(() => {
34749
34857
  init_drizzle_orm();
@@ -34905,7 +35013,7 @@ var init_entity_dao = __esm(() => {
34905
35013
  };
34906
35014
  });
34907
35015
 
34908
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/inbox-message-dao.js
35016
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/inbox-message-dao.js
34909
35017
  function isPromiseLike(value) {
34910
35018
  return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
34911
35019
  }
@@ -35083,7 +35191,7 @@ var init_migrator2 = __esm(() => {
35083
35191
  init_migrator();
35084
35192
  });
35085
35193
 
35086
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/migrate.js
35194
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/migrate.js
35087
35195
  async function ensureJournalTable(adapter, table3) {
35088
35196
  await adapter.exec(`CREATE TABLE IF NOT EXISTS "${table3}" (` + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "hash text NOT NULL, " + "created_at numeric" + ")");
35089
35197
  }
@@ -35158,7 +35266,19 @@ var init_migrate = __esm(() => {
35158
35266
  init_embedded_migrations();
35159
35267
  });
35160
35268
 
35161
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/queue-job-dao.js
35269
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/queue-job-dao.js
35270
+ function assertValidTimeoutMs(value) {
35271
+ if (value === undefined || value === null)
35272
+ return;
35273
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
35274
+ throw new RangeError(`enqueue timeoutMs must be a positive integer or null; received ${String(value)}`);
35275
+ }
35276
+ }
35277
+ function timeoutColumns(timeoutMs) {
35278
+ if (timeoutMs === undefined)
35279
+ return {};
35280
+ return timeoutMs === null ? { timeoutUnlimited: 1 } : { timeoutMs };
35281
+ }
35162
35282
  var QueueJobDao;
35163
35283
  var init_queue_job_dao = __esm(() => {
35164
35284
  init_drizzle_orm();
@@ -35169,6 +35289,7 @@ var init_queue_job_dao = __esm(() => {
35169
35289
  super(adapter, queueJobs, [queueJobs.id], "queue_jobs");
35170
35290
  }
35171
35291
  async enqueue(type, payload, options) {
35292
+ assertValidTimeoutMs(options?.timeoutMs);
35172
35293
  const now = this.now();
35173
35294
  const id = crypto.randomUUID();
35174
35295
  await this.create({
@@ -35179,11 +35300,15 @@ var init_queue_job_dao = __esm(() => {
35179
35300
  attempts: 0,
35180
35301
  maxRetries: options?.maxRetries ?? 3,
35181
35302
  nextRetryAt: options?.delay !== undefined ? now + options.delay : now,
35182
- ...options?.ttlMs !== undefined ? { expiresAt: now + options.ttlMs } : {}
35303
+ ...options?.ttlMs !== undefined ? { expiresAt: now + options.ttlMs } : {},
35304
+ ...timeoutColumns(options?.timeoutMs)
35183
35305
  });
35184
35306
  return id;
35185
35307
  }
35186
35308
  async enqueueBatch(jobs) {
35309
+ for (const job of jobs) {
35310
+ assertValidTimeoutMs(job.timeoutMs);
35311
+ }
35187
35312
  const now = this.now();
35188
35313
  const ids = [];
35189
35314
  const rows = jobs.map((job) => {
@@ -35197,7 +35322,8 @@ var init_queue_job_dao = __esm(() => {
35197
35322
  attempts: 0,
35198
35323
  maxRetries: job.maxRetries ?? 3,
35199
35324
  nextRetryAt: job.delay !== undefined ? now + job.delay : now,
35200
- ...job.ttlMs !== undefined ? { expiresAt: now + job.ttlMs } : {}
35325
+ ...job.ttlMs !== undefined ? { expiresAt: now + job.ttlMs } : {},
35326
+ ...timeoutColumns(job.timeoutMs)
35201
35327
  };
35202
35328
  });
35203
35329
  if (rows.length > 0) {
@@ -35235,20 +35361,37 @@ var init_queue_job_dao = __esm(() => {
35235
35361
  const result = await this.db.select().from(queueJobs).where(sql`${queueJobs.status} = 'pending' AND (${queueJobs.nextRetryAt} IS NULL OR ${queueJobs.nextRetryAt} <= ${now})`).orderBy(queueJobs.createdAt).limit(batchSize);
35236
35362
  return result;
35237
35363
  }
35238
- async claimReady(batchSize) {
35364
+ async claimReady(batchSize, options) {
35239
35365
  const limit = Math.floor(batchSize);
35240
35366
  if (limit <= 0)
35241
35367
  return [];
35242
35368
  const now = this.now();
35243
- const result = await this.db.update(queueJobs).set({ status: "processing", processingAt: now, updatedAt: now }).where(sql`${queueJobs.id} IN (
35369
+ const leaseMs = options?.leaseMs;
35370
+ const leased = leaseMs !== undefined;
35371
+ const leaseExpiresAt = leased ? now + leaseMs : null;
35372
+ const reclaimable = sql`(
35373
+ ${queueJobs.status} = 'pending'
35374
+ AND (${queueJobs.nextRetryAt} IS NULL OR ${queueJobs.nextRetryAt} <= ${now})
35375
+ ) OR (
35376
+ ${queueJobs.status} = 'processing'
35377
+ AND ${queueJobs.attemptToken} IS NOT NULL
35378
+ AND ${queueJobs.leaseExpiresAt} IS NOT NULL
35379
+ AND ${queueJobs.leaseExpiresAt} <= ${now}
35380
+ )`;
35381
+ const result = await this.db.update(queueJobs).set({
35382
+ status: "processing",
35383
+ processingAt: now,
35384
+ updatedAt: now,
35385
+ attemptToken: leased ? sql`lower(hex(randomblob(16)))` : null,
35386
+ leaseExpiresAt
35387
+ }).where(sql`${queueJobs.id} IN (
35244
35388
  SELECT id
35245
35389
  FROM ${queueJobs}
35246
- WHERE status = 'pending'
35247
- AND (next_retry_at IS NULL OR next_retry_at <= ${now})
35390
+ WHERE ${reclaimable}
35248
35391
  ORDER BY created_at
35249
35392
  LIMIT ${limit}
35250
35393
  )
35251
- AND ${queueJobs.status} = 'pending'`).returning();
35394
+ AND ${reclaimable}`).returning();
35252
35395
  return result;
35253
35396
  }
35254
35397
  async markProcessing(ids) {
@@ -35257,32 +35400,53 @@ var init_queue_job_dao = __esm(() => {
35257
35400
  const now = this.now();
35258
35401
  await this.db.update(queueJobs).set({ status: "processing", processingAt: now, updatedAt: now }).where(and(inArray(queueJobs.id, ids), eq(queueJobs.status, "pending")));
35259
35402
  }
35260
- async markCompleted(id) {
35261
- await this.update(id, {
35403
+ async markCompleted(id, attemptToken) {
35404
+ const where = attemptToken === undefined ? eq(queueJobs.id, id) : and(eq(queueJobs.id, id), eq(queueJobs.attemptToken, attemptToken));
35405
+ const result = await this.db.update(queueJobs).set({
35262
35406
  status: "completed",
35263
- processingAt: null
35264
- });
35265
- }
35266
- async markFailed(id, attempts, error51) {
35267
- await this.update(id, {
35407
+ processingAt: null,
35408
+ attemptToken: null,
35409
+ leaseExpiresAt: null,
35410
+ updatedAt: this.now()
35411
+ }).where(where);
35412
+ return result.changes === 1;
35413
+ }
35414
+ async markFailed(id, attempts, error51, attemptToken) {
35415
+ const where = attemptToken === undefined ? eq(queueJobs.id, id) : and(eq(queueJobs.id, id), eq(queueJobs.attemptToken, attemptToken));
35416
+ const result = await this.db.update(queueJobs).set({
35268
35417
  status: "failed",
35269
35418
  attempts,
35270
35419
  lastError: error51,
35271
- processingAt: null
35272
- });
35273
- }
35274
- async markForRetry(id, attempts, errorMessage2, nextRetryAt) {
35275
- await this.update(id, {
35420
+ processingAt: null,
35421
+ attemptToken: null,
35422
+ leaseExpiresAt: null,
35423
+ updatedAt: this.now()
35424
+ }).where(where);
35425
+ return result.changes === 1;
35426
+ }
35427
+ async markForRetry(id, attempts, errorMessage2, nextRetryAt, attemptToken) {
35428
+ const where = attemptToken === undefined ? eq(queueJobs.id, id) : and(eq(queueJobs.id, id), eq(queueJobs.attemptToken, attemptToken));
35429
+ const result = await this.db.update(queueJobs).set({
35276
35430
  status: "pending",
35277
35431
  attempts,
35278
35432
  lastError: errorMessage2,
35279
35433
  nextRetryAt,
35280
- processingAt: null
35281
- });
35434
+ processingAt: null,
35435
+ attemptToken: null,
35436
+ leaseExpiresAt: null,
35437
+ updatedAt: this.now()
35438
+ }).where(where);
35439
+ return result.changes === 1;
35440
+ }
35441
+ async renewLease(id, attemptToken, leaseMs) {
35442
+ const now = this.now();
35443
+ const result = await this.db.update(queueJobs).set({ leaseExpiresAt: now + leaseMs, updatedAt: now }).where(and(eq(queueJobs.id, id), eq(queueJobs.attemptToken, attemptToken), eq(queueJobs.status, "processing")));
35444
+ return result.changes === 1;
35282
35445
  }
35283
35446
  async resetStuckJobs(visibilityTimeout) {
35284
35447
  const cutoff = this.now() - visibilityTimeout;
35285
- const result = await this.db.update(queueJobs).set({ status: "pending", processingAt: null, updatedAt: this.now() }).where(sql`${queueJobs.status} = 'processing' AND ${queueJobs.processingAt} IS NOT NULL AND ${queueJobs.processingAt} <= ${cutoff}`);
35448
+ const result = await this.db.update(queueJobs).set({ status: "pending", processingAt: null, updatedAt: this.now() }).where(sql`${queueJobs.status} = 'processing' AND ${queueJobs.processingAt} IS NOT NULL AND ${queueJobs.processingAt} <= ${cutoff}
35449
+ AND ${queueJobs.attemptToken} IS NULL`);
35286
35450
  return result.changes;
35287
35451
  }
35288
35452
  async failExpiredJobs() {
@@ -35299,7 +35463,7 @@ var init_queue_job_dao = __esm(() => {
35299
35463
  };
35300
35464
  });
35301
35465
 
35302
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/index.js
35466
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/index.js
35303
35467
  var exports_dist = {};
35304
35468
  __export(exports_dist, {
35305
35469
  embeddedMigrations: () => embeddedMigrations,
@@ -37432,7 +37596,7 @@ var require_extra_typings = __commonJS((exports, module) => {
37432
37596
  exports.createArgument = (name, description) => new commander.Argument(name, description);
37433
37597
  });
37434
37598
 
37435
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/config.js
37599
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/config.js
37436
37600
  function parseYamlObject(text3) {
37437
37601
  let parsed;
37438
37602
  try {
@@ -37559,7 +37723,7 @@ var init_config2 = __esm(() => {
37559
37723
  };
37560
37724
  });
37561
37725
 
37562
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
37726
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
37563
37727
  import { appendFileSync as appendFileSync3, cpSync as cpSync2, createReadStream as createReadStream3, createWriteStream as createWriteStream3, existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync4, realpathSync as realpathSync2, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
37564
37728
  import { dirname as dirname2, resolve as resolvePath3 } from "path";
37565
37729
  function createNodeFileSystem3(root, paths) {
@@ -37646,7 +37810,7 @@ function findProjectRoot3(startDir) {
37646
37810
  }
37647
37811
  var init_file_system_node2 = () => {};
37648
37812
 
37649
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
37813
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
37650
37814
  var D1NotConfiguredError2, DbModuleNotInstalledError3;
37651
37815
  var init_db_errors2 = __esm(() => {
37652
37816
  D1NotConfiguredError2 = class D1NotConfiguredError2 extends Error {
@@ -37663,7 +37827,7 @@ var init_db_errors2 = __esm(() => {
37663
37827
  };
37664
37828
  });
37665
37829
 
37666
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/file-system-cf.js
37830
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/file-system-cf.js
37667
37831
  function createCfFileSystem2() {
37668
37832
  return {
37669
37833
  getProjectRoot: () => "/bundle",
@@ -37702,7 +37866,7 @@ function createCfFileSystem2() {
37702
37866
  }
37703
37867
  var UNSUPPORTED = "FileSystem is not available on Cloudflare Workers. Use D1, KV, or R2 for persistent storage.";
37704
37868
 
37705
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/runtime-cf.js
37869
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/runtime-cf.js
37706
37870
  var exports_runtime_cf = {};
37707
37871
  __export(exports_runtime_cf, {
37708
37872
  cloudflareWorkersFactory: () => cloudflareWorkersFactory2
@@ -37740,12 +37904,12 @@ var init_runtime_cf = __esm(() => {
37740
37904
  };
37741
37905
  });
37742
37906
 
37743
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
37907
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
37744
37908
  import { isatty as isatty2 } from "tty";
37745
37909
  function processEventSeverity2(reason, exitCode) {
37746
37910
  if (reason === "error")
37747
37911
  return "error";
37748
- if (reason === "timeout")
37912
+ if (reason === "timeout" || reason === "cancelled")
37749
37913
  return "warning";
37750
37914
  if (exitCode !== null && exitCode !== 0)
37751
37915
  return "warning";
@@ -37772,15 +37936,19 @@ class NodeProcessExecutor3 {
37772
37936
  }
37773
37937
  async runUntraced(options) {
37774
37938
  const args = options.args ?? [];
37939
+ const deadline = resolveDeadline2(options.timeout, this.config.defaultTimeout);
37940
+ const killGraceMs = resolveKillGraceMs2(options.killGraceMs);
37941
+ const groupOwned = process.platform !== "win32" && (typeof deadline === "number" || options.signal !== undefined);
37775
37942
  const execaOptions = buildExecaOptions2({
37776
37943
  cwd: options.cwd ?? this.config.paths?.cwd,
37777
37944
  env: options.env,
37778
- timeout: options.timeout ?? this.config.defaultTimeout,
37945
+ timeout: typeof deadline === "number" ? deadline : undefined,
37779
37946
  maxOutput: options.maxOutput ?? this.config.defaultMaxOutput,
37780
37947
  rejectOnError: options.rejectOnError ?? false,
37781
37948
  outputPolicy: this.config.output,
37782
37949
  forceBuffered: options.forceBuffered ?? false,
37783
- signal: options.signal
37950
+ signal: options.signal,
37951
+ groupOwned
37784
37952
  });
37785
37953
  const startedAt = Date.now();
37786
37954
  const startedIso = new Date(startedAt).toISOString();
@@ -37801,8 +37969,17 @@ class NodeProcessExecutor3 {
37801
37969
  severity: "info",
37802
37970
  ...options.label !== undefined ? { label: options.label } : {}
37803
37971
  });
37972
+ let ownership;
37804
37973
  try {
37805
37974
  const subprocess = execa(options.command, args, execaOptions);
37975
+ if (groupOwned && subprocess.pid !== undefined) {
37976
+ ownership = ownProcessGroupLifecycle2({
37977
+ pid: subprocess.pid,
37978
+ deadlineMs: typeof deadline === "number" ? deadline : undefined,
37979
+ signal: options.signal,
37980
+ graceMs: killGraceMs
37981
+ });
37982
+ }
37806
37983
  if (subprocess.pid !== undefined) {
37807
37984
  this.config.registry?.update(registryId, { pid: subprocess.pid });
37808
37985
  if (options.onSpawn !== undefined) {
@@ -37811,10 +37988,11 @@ class NodeProcessExecutor3 {
37811
37988
  } catch {}
37812
37989
  }
37813
37990
  }
37814
- const stopGroupCancellation = observeProcessGroupCancellation2(subprocess, options.signal);
37991
+ const stopOwnedTermination = () => ownership?.stop();
37815
37992
  observeOutput2(subprocess.stdout, "stdout", options.onOutput);
37816
37993
  observeOutput2(subprocess.stderr, "stderr", options.onOutput);
37817
- const result = await subprocess.finally(stopGroupCancellation);
37994
+ const result = await subprocess.finally(stopOwnedTermination);
37995
+ const ownedOutcome = ownership !== undefined ? await ownership.finish() : undefined;
37818
37996
  const processResult = {
37819
37997
  command: options.command,
37820
37998
  args,
@@ -37822,13 +38000,15 @@ class NodeProcessExecutor3 {
37822
38000
  stdout: asString2(result.stdout),
37823
38001
  stderr: asString2(result.stderr),
37824
38002
  ...result.signalDescription !== undefined ? { signal: result.signalDescription } : {},
37825
- durationMs: result.durationMs
38003
+ durationMs: result.durationMs,
38004
+ outcome: ownedOutcome ?? (result.signalDescription !== undefined ? "signal" : "exit")
37826
38005
  };
37827
38006
  this.completeRegistry(registryId, processResult.exitCode);
37828
38007
  this.emitExitedFromResult(options, processResult, result);
37829
38008
  return processResult;
37830
38009
  } catch (error51) {
37831
38010
  const failed = error51;
38011
+ const ownedOutcome = ownership !== undefined ? await ownership.finish() : undefined;
37832
38012
  const processResult = {
37833
38013
  command: options.command,
37834
38014
  args,
@@ -37836,7 +38016,8 @@ class NodeProcessExecutor3 {
37836
38016
  stdout: asString2(failed.stdout),
37837
38017
  stderr: asString2(failed.stderr),
37838
38018
  ...failed.signalDescription !== undefined ? { signal: failed.signalDescription } : failed.signal !== undefined ? { signal: failed.signal } : {},
37839
- durationMs: failed.durationMs ?? Date.now() - startedAt
38019
+ durationMs: failed.durationMs ?? Date.now() - startedAt,
38020
+ outcome: ownedOutcome ?? classifyFailedCompletion2(failed)
37840
38021
  };
37841
38022
  this.completeRegistry(registryId, processResult.exitCode);
37842
38023
  this.emitExitedFromResult(options, processResult, error51, error51);
@@ -37936,7 +38117,7 @@ class NodeProcessExecutor3 {
37936
38117
  });
37937
38118
  }
37938
38119
  emitExitedFromResult(options, result, completion, error51) {
37939
- const reason = isTimedOut2(completion) ? "timeout" : result.signal !== undefined ? "signal" : error51 ? "error" : "exit";
38120
+ const reason = result.outcome ?? (isTimedOut2(completion) ? "timeout" : result.signal !== undefined ? "signal" : error51 ? "error" : "exit");
37940
38121
  this.emitProcessEvent("process.exited", {
37941
38122
  command: result.command,
37942
38123
  args: result.args,
@@ -38083,30 +38264,110 @@ function buildExecaOptions2(opts) {
38083
38264
  ...mode === "pipe" ? { stdout: "pipe", stderr: "pipe" } : streamToTerminal ? { stdout: ["inherit", "pipe"], stderr: ["inherit", "pipe"] } : { all: true },
38084
38265
  ...opts.cwd !== undefined ? { cwd: opts.cwd } : {},
38085
38266
  ...opts.env !== undefined ? { env: opts.env } : {},
38086
- ...opts.timeout !== undefined ? { timeout: opts.timeout } : {},
38267
+ ...opts.timeout !== undefined && !opts.groupOwned ? { timeout: opts.timeout } : {},
38087
38268
  ...opts.maxOutput !== undefined ? { maxBuffer: opts.maxOutput } : {},
38088
- ...opts.signal !== undefined ? {
38089
- cancelSignal: opts.signal,
38090
- ...process.platform !== "win32" ? { detached: true } : {}
38091
- } : {}
38269
+ ...opts.groupOwned ? { detached: true } : {},
38270
+ ...opts.signal !== undefined && !opts.groupOwned ? { cancelSignal: opts.signal } : {}
38092
38271
  };
38093
38272
  }
38094
- function observeProcessGroupCancellation2(subprocess, signal) {
38095
- const pid = subprocess.pid;
38096
- if (signal === undefined || process.platform === "win32" || pid === undefined)
38097
- return () => {};
38098
- const abort = () => {
38099
- try {
38100
- process.kill(-pid, "SIGTERM");
38101
- } catch {
38102
- subprocess.kill("SIGTERM");
38273
+ function resolveDeadline2(optionTimeout, defaultTimeout) {
38274
+ if (optionTimeout === null)
38275
+ return null;
38276
+ const candidate = optionTimeout === undefined ? defaultTimeout : optionTimeout;
38277
+ if (candidate === undefined || candidate === null)
38278
+ return candidate;
38279
+ if (!Number.isInteger(candidate) || candidate <= 0 || candidate > MAX_TIMEOUT_MS2) {
38280
+ throw new TypeError(`Process timeout must be a positive integer within the native timer range (1-${MAX_TIMEOUT_MS2} ms), got ${String(candidate)}`);
38281
+ }
38282
+ return candidate;
38283
+ }
38284
+ function resolveKillGraceMs2(optionGraceMs) {
38285
+ if (optionGraceMs === undefined)
38286
+ return DEFAULT_KILL_GRACE_MS2;
38287
+ if (!Number.isInteger(optionGraceMs) || optionGraceMs < 0 || optionGraceMs > MAX_TIMEOUT_MS2) {
38288
+ throw new TypeError(`Process killGraceMs must be a non-negative integer within the native timer range (0-${MAX_TIMEOUT_MS2} ms), got ${String(optionGraceMs)}`);
38289
+ }
38290
+ return optionGraceMs;
38291
+ }
38292
+ function groupExists2(pid) {
38293
+ try {
38294
+ process.kill(-pid, 0);
38295
+ return true;
38296
+ } catch (error51) {
38297
+ return error51.code === "EPERM";
38298
+ }
38299
+ }
38300
+ function signalGroup2(pid, signal) {
38301
+ try {
38302
+ process.kill(-pid, signal);
38303
+ return true;
38304
+ } catch {
38305
+ return false;
38306
+ }
38307
+ }
38308
+ async function waitForGroupExit2(pid, budgetMs) {
38309
+ const giveUpAt = Date.now() + budgetMs;
38310
+ while (groupExists2(pid)) {
38311
+ if (Date.now() >= giveUpAt)
38312
+ return false;
38313
+ await new Promise((resolve) => setTimeout(resolve, GROUP_POLL_INTERVAL_MS2));
38314
+ }
38315
+ return true;
38316
+ }
38317
+ async function reapProcessGroup2(pid, graceMs) {
38318
+ if (!signalGroup2(pid, "SIGTERM"))
38319
+ return false;
38320
+ if (await waitForGroupExit2(pid, graceMs))
38321
+ return true;
38322
+ signalGroup2(pid, "SIGKILL");
38323
+ await waitForGroupExit2(pid, GROUP_KILL_PATIENCE_MS2);
38324
+ return true;
38325
+ }
38326
+ function ownProcessGroupLifecycle2(ownership) {
38327
+ const { pid, graceMs } = ownership;
38328
+ let trigger;
38329
+ let termination;
38330
+ let timer;
38331
+ const initiate = (reason) => {
38332
+ if (trigger !== undefined)
38333
+ return;
38334
+ trigger = reason;
38335
+ termination = reapProcessGroup2(pid, graceMs);
38336
+ };
38337
+ if (ownership.deadlineMs !== undefined) {
38338
+ timer = setTimeout(() => initiate("timeout"), ownership.deadlineMs);
38339
+ }
38340
+ const onAbort = () => initiate("cancelled");
38341
+ if (ownership.signal !== undefined) {
38342
+ if (ownership.signal.aborted)
38343
+ onAbort();
38344
+ else
38345
+ ownership.signal.addEventListener("abort", onAbort, { once: true });
38346
+ }
38347
+ return {
38348
+ finish: async () => {
38349
+ if (trigger === undefined) {
38350
+ await reapProcessGroup2(pid, graceMs);
38351
+ return;
38352
+ }
38353
+ return await termination ? trigger : undefined;
38354
+ },
38355
+ stop: () => {
38356
+ if (timer !== undefined)
38357
+ clearTimeout(timer);
38358
+ ownership.signal?.removeEventListener("abort", onAbort);
38103
38359
  }
38104
38360
  };
38105
- if (signal.aborted)
38106
- abort();
38107
- else
38108
- signal.addEventListener("abort", abort, { once: true });
38109
- return () => signal.removeEventListener("abort", abort);
38361
+ }
38362
+ function classifyFailedCompletion2(error51) {
38363
+ if (error51.timedOut === true)
38364
+ return "timeout";
38365
+ if (error51.isCanceled === true)
38366
+ return "cancelled";
38367
+ if (error51.isTerminated === true || error51.signalDescription !== undefined || error51.signal !== undefined) {
38368
+ return "signal";
38369
+ }
38370
+ return "error";
38110
38371
  }
38111
38372
  function observeOutput2(stream, name, observer) {
38112
38373
  if (!stream || !observer)
@@ -38144,14 +38405,14 @@ function isTimedOut2(error51) {
38144
38405
  function errorMessage2(error51) {
38145
38406
  return error51 instanceof Error ? error51.message : String(error51);
38146
38407
  }
38147
- var ProcessExecutor2;
38408
+ var ProcessExecutor2, MAX_TIMEOUT_MS2 = 2147483647, DEFAULT_KILL_GRACE_MS2 = 5000, GROUP_POLL_INTERVAL_MS2 = 25, GROUP_KILL_PATIENCE_MS2 = 2000;
38148
38409
  var init_process_executor2 = __esm(() => {
38149
38410
  init_execa();
38150
38411
  init_config2();
38151
38412
  ProcessExecutor2 = NodeProcessExecutor3;
38152
38413
  });
38153
38414
 
38154
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
38415
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
38155
38416
  var exports_runtime_node_bun = {};
38156
38417
  __export(exports_runtime_node_bun, {
38157
38418
  nodeBunFactory: () => nodeBunFactory3,
@@ -38219,7 +38480,7 @@ var init_runtime_node_bun2 = __esm(() => {
38219
38480
  };
38220
38481
  });
38221
38482
 
38222
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/platform.js
38483
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/platform.js
38223
38484
  function isCloudflareWorkerRuntime2() {
38224
38485
  return globalThis.navigator?.userAgent?.startsWith("Cloudflare-Workers") ?? false;
38225
38486
  }
@@ -38249,7 +38510,7 @@ function _resetRuntimeFactory2() {
38249
38510
  }
38250
38511
  var _factory, _runtimeName;
38251
38512
 
38252
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/context.js
38513
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/context.js
38253
38514
  class RuntimeContext2 {
38254
38515
  scope;
38255
38516
  runtimeName;
@@ -38339,7 +38600,7 @@ var init_context2 = __esm(() => {
38339
38600
  init_runtime_node_bun2();
38340
38601
  });
38341
38602
 
38342
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/path.js
38603
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/path.js
38343
38604
  function normalizeSeparators2(path7) {
38344
38605
  return path7.replaceAll("\\", "/");
38345
38606
  }
@@ -38462,7 +38723,7 @@ var init_path2 = __esm(() => {
38462
38723
  SEP2 = globalThis.process?.platform === "win32" ? "\\" : "/";
38463
38724
  });
38464
38725
 
38465
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/fs.js
38726
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/fs.js
38466
38727
  async function ensureDirForFile2(path7, fs2 = createNodeFileSystem3()) {
38467
38728
  await fs2.ensureDir(dirnamePath(path7));
38468
38729
  }
@@ -38530,7 +38791,7 @@ var init_fs = __esm(() => {
38530
38791
  init_path2();
38531
38792
  });
38532
38793
 
38533
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/process-registry.js
38794
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/process-registry.js
38534
38795
  function allocateId() {
38535
38796
  nextIdSeq += 1;
38536
38797
  return `pe_${Date.now().toString(36)}_${nextIdSeq.toString(36)}`;
@@ -38654,7 +38915,7 @@ function createInMemoryProcessRegistry2(options) {
38654
38915
  }
38655
38916
  var nextIdSeq = 0;
38656
38917
 
38657
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/runtime-paths.js
38918
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/runtime-paths.js
38658
38919
  function ambientRuntimePaths2() {
38659
38920
  const cwd = getProcessCwd2();
38660
38921
  return { cwd, home: getHomeDir() ?? cwd };
@@ -38664,7 +38925,7 @@ var init_runtime_paths = __esm(() => {
38664
38925
  init_path2();
38665
38926
  });
38666
38927
 
38667
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
38928
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
38668
38929
  async function loadStructuredConfig(path7, options = {}) {
38669
38930
  const content = await (options.fileSystem ?? createNodeFileSystem3()).readFile(path7);
38670
38931
  return await parseStructuredConfig(content, path7, options);
@@ -38947,10 +39208,10 @@ var init_schema_validation2 = __esm(() => {
38947
39208
  defaultResolve = typeof Bun !== "undefined" ? (specifier, from) => Bun.resolveSync(specifier, from) : undefined;
38948
39209
  });
38949
39210
 
38950
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/types.js
39211
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/types.js
38951
39212
  var init_types2 = () => {};
38952
39213
 
38953
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/index.js
39214
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/index.js
38954
39215
  var exports_dist2 = {};
38955
39216
  __export(exports_dist2, {
38956
39217
  writeJsonFile: () => writeJsonFile2,
@@ -42006,7 +42267,7 @@ var init_mod = __esm(() => {
42006
42267
  init_config3();
42007
42268
  });
42008
42269
 
42009
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/logger.js
42270
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/logger.js
42010
42271
  function toLogTapeLevel(level) {
42011
42272
  return level === "warn" ? "warning" : level;
42012
42273
  }
@@ -43559,7 +43820,7 @@ var require_src = __commonJS((exports) => {
43559
43820
  };
43560
43821
  });
43561
43822
 
43562
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/telemetry/sdk.js
43823
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/telemetry/sdk.js
43563
43824
  function getTelemetryConfig(configPartial = {}) {
43564
43825
  return {
43565
43826
  enabled: configPartial.enabled ?? CONFIG_DEFAULTS.enabled,
@@ -43595,7 +43856,7 @@ var init_sdk = __esm(() => {
43595
43856
  resolvedConfig = getTelemetryConfig();
43596
43857
  });
43597
43858
 
43598
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
43859
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
43599
43860
  function isSuppressed(tracer2) {
43600
43861
  return tracer2 === undefined && !getResolvedConfig().enabled;
43601
43862
  }
@@ -43635,7 +43896,7 @@ var init_tracing2 = __esm(() => {
43635
43896
  import_api2 = __toESM(require_src(), 1);
43636
43897
  });
43637
43898
 
43638
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
43899
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
43639
43900
  function getMeter() {
43640
43901
  return import_api3.metrics.getMeter(METER_NAME, METER_VERSION);
43641
43902
  }
@@ -43732,7 +43993,7 @@ var init_metrics = __esm(() => {
43732
43993
  instruments = {};
43733
43994
  });
43734
43995
 
43735
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/event-bus/event-bus.js
43996
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/event-bus/event-bus.js
43736
43997
  function busLogger() {
43737
43998
  if (!_busLogger)
43738
43999
  _busLogger = getLogger2("event-bus");
@@ -43985,7 +44246,7 @@ var init_event_bus = __esm(() => {
43985
44246
  init_metrics();
43986
44247
  });
43987
44248
 
43988
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/event-bus/default-observers.js
44249
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/event-bus/default-observers.js
43989
44250
  function obsLogger() {
43990
44251
  if (!_obsLogger)
43991
44252
  _obsLogger = getLogger2("event-bus.observers");
@@ -44049,7 +44310,7 @@ var init_default_observers = __esm(() => {
44049
44310
  init_event_bus();
44050
44311
  });
44051
44312
 
44052
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/event-bus/file-observer.js
44313
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/event-bus/file-observer.js
44053
44314
  function parentDir(filePath) {
44054
44315
  const idx = filePath.lastIndexOf("/");
44055
44316
  return idx <= 0 ? "." : filePath.slice(0, idx);
@@ -44147,7 +44408,84 @@ var init_file_observer = __esm(() => {
44147
44408
  init_logger3();
44148
44409
  });
44149
44410
 
44150
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/internals/drain.js
44411
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/execution-policy.js
44412
+ function resolveExecutionTimeoutMs(scope, value, inherited) {
44413
+ if (value === undefined) {
44414
+ return inherited ?? null;
44415
+ }
44416
+ if (value === null) {
44417
+ return null;
44418
+ }
44419
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
44420
+ throw new RangeError(`${scope} timeoutMs must be a positive integer or null; received ${String(value)}`);
44421
+ }
44422
+ return value;
44423
+ }
44424
+ async function runWithExecutionDeadline(action, options) {
44425
+ const deadlineMs = options.timeoutMs ?? null;
44426
+ const controller = new AbortController;
44427
+ const cancellation = { reason: undefined };
44428
+ const context4 = {
44429
+ signal: controller.signal,
44430
+ deadlineMs,
44431
+ get cancellationReason() {
44432
+ return cancellation.reason;
44433
+ }
44434
+ };
44435
+ if (options.signal !== undefined) {
44436
+ if (options.signal.aborted) {
44437
+ cancellation.reason = "cancelled";
44438
+ controller.abort();
44439
+ } else {
44440
+ const abortFromCaller = () => {
44441
+ if (cancellation.reason === undefined)
44442
+ cancellation.reason = "cancelled";
44443
+ controller.abort();
44444
+ };
44445
+ options.signal.addEventListener("abort", abortFromCaller, { once: true });
44446
+ }
44447
+ }
44448
+ const startMs = performance.now();
44449
+ let timer;
44450
+ if (deadlineMs !== null) {
44451
+ timer = setTimeout(() => {
44452
+ if (cancellation.reason === undefined)
44453
+ cancellation.reason = "timeout";
44454
+ controller.abort();
44455
+ }, deadlineMs);
44456
+ }
44457
+ let result;
44458
+ let error51;
44459
+ let failed = false;
44460
+ try {
44461
+ result = await action(context4);
44462
+ } catch (caught) {
44463
+ error51 = caught;
44464
+ failed = true;
44465
+ } finally {
44466
+ if (timer !== undefined)
44467
+ clearTimeout(timer);
44468
+ }
44469
+ const elapsedMs = performance.now() - startMs;
44470
+ const timedOut = cancellation.reason === "timeout";
44471
+ if (failed) {
44472
+ return { outcome: "error", error: error51, elapsedMs, timedOut };
44473
+ }
44474
+ if (timedOut) {
44475
+ return {
44476
+ outcome: "timeout",
44477
+ error: new Error(`execution deadline (${String(deadlineMs)}ms) expired`),
44478
+ elapsedMs,
44479
+ timedOut
44480
+ };
44481
+ }
44482
+ if (cancellation.reason === "cancelled") {
44483
+ return { outcome: "cancelled", elapsedMs, timedOut };
44484
+ }
44485
+ return { outcome: "completed", result, elapsedMs, timedOut };
44486
+ }
44487
+
44488
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/internals/drain.js
44151
44489
  function settleWithin(promise2, deadline) {
44152
44490
  const remaining = deadline - Date.now();
44153
44491
  if (remaining <= 0)
@@ -54277,8 +54615,8 @@ END`;
54277
54615
  ];
54278
54616
  });
54279
54617
 
54280
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/errors.js
54281
- var HistoryImportError;
54618
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/errors.js
54619
+ var HistoryImportError, ImportCancelledError;
54282
54620
  var init_errors5 = __esm(() => {
54283
54621
  HistoryImportError = class HistoryImportError extends Error {
54284
54622
  details;
@@ -54288,10 +54626,18 @@ var init_errors5 = __esm(() => {
54288
54626
  this.name = "HistoryImportError";
54289
54627
  }
54290
54628
  };
54629
+ ImportCancelledError = class ImportCancelledError extends HistoryImportError {
54630
+ abortReason;
54631
+ constructor(message = "Import cancelled by abort signal", abortReason) {
54632
+ super(message, abortReason);
54633
+ this.abortReason = abortReason;
54634
+ this.name = "ImportCancelledError";
54635
+ }
54636
+ };
54291
54637
  });
54292
54638
 
54293
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
54294
- var HISTORY_IMPORT_SCHEMA_VERSION = "0.4.56", HISTORY_IMPORT_SCHEMA_SQL;
54639
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
54640
+ var HISTORY_IMPORT_SCHEMA_VERSION = "0.4.60", HISTORY_IMPORT_SCHEMA_SQL;
54295
54641
  var init_schema_sql = __esm(() => {
54296
54642
  HISTORY_IMPORT_SCHEMA_SQL = `
54297
54643
  CREATE TABLE IF NOT EXISTS history_import_checkpoint (
@@ -54413,7 +54759,7 @@ CREATE INDEX IF NOT EXISTS idx_history_skill_call_invocation_kind
54413
54759
  `.trim();
54414
54760
  });
54415
54761
 
54416
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
54762
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
54417
54763
  import { createHash as createHash3 } from "crypto";
54418
54764
  function stableJson(value) {
54419
54765
  if (Array.isArray(value)) {
@@ -54430,7 +54776,7 @@ function sha256(value) {
54430
54776
  }
54431
54777
  var init_hash = () => {};
54432
54778
 
54433
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/mappers.js
54779
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/mappers.js
54434
54780
  function identityFieldMap(keys) {
54435
54781
  const map2 = {};
54436
54782
  for (const key of keys) {
@@ -56004,7 +56350,7 @@ var init_mappers = __esm(() => {
56004
56350
  GEMINI_SCHEMA = passthroughSchema;
56005
56351
  });
56006
56352
 
56007
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
56353
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
56008
56354
  function firstString(...values) {
56009
56355
  for (const value of values) {
56010
56356
  if (typeof value === "string" && value.length > 0)
@@ -56161,7 +56507,7 @@ var init_sources = __esm(() => {
56161
56507
  };
56162
56508
  });
56163
56509
 
56164
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/jsonl-importer-dao.js
56510
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/jsonl-importer-dao.js
56165
56511
  function targetTableFor(table3) {
56166
56512
  if (!VALID_TABLE_NAME.test(table3)) {
56167
56513
  throw new HistoryImportError(`Invalid history ETL target table: ${table3}`, { table: table3 });
@@ -56604,7 +56950,7 @@ var init_jsonl_importer_dao = __esm(() => {
56604
56950
  ARGS_TOOL_NAME_KEYS = ["tool", "tool_name", "toolName", "name", "command"];
56605
56951
  });
56606
56952
 
56607
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/assistant-duration.js
56953
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/assistant-duration.js
56608
56954
  async function deriveAssistantDurations(db2) {
56609
56955
  const rows = await findAssistantDurationCandidates(db2);
56610
56956
  let derived = 0;
@@ -56627,7 +56973,17 @@ var init_assistant_duration = __esm(() => {
56627
56973
  DERIVED_DURATION_CEILING_MS = 30 * 60 * 1000;
56628
56974
  });
56629
56975
 
56630
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
56976
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/cancellation.js
56977
+ function throwIfImportAborted(signal) {
56978
+ if (signal?.aborted) {
56979
+ throw new ImportCancelledError("Import cancelled by abort signal", signal.reason);
56980
+ }
56981
+ }
56982
+ var init_cancellation = __esm(() => {
56983
+ init_errors5();
56984
+ });
56985
+
56986
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
56631
56987
  function redactValue(value, rules = DEFAULT_REDACTION_RULES) {
56632
56988
  if (typeof value === "string") {
56633
56989
  return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
@@ -56679,7 +57035,7 @@ var init_redaction = __esm(() => {
56679
57035
  ];
56680
57036
  });
56681
57037
 
56682
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/importer.js
57038
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/importer.js
56683
57039
  function toolCallKey(source, sessionId, callId) {
56684
57040
  return `${source}${TOOL_CALL_KEY_SEP}${sessionId}${TOOL_CALL_KEY_SEP}${callId}`;
56685
57041
  }
@@ -56708,12 +57064,14 @@ function attachableDuration(timing, messageTsMs) {
56708
57064
  };
56709
57065
  }
56710
57066
  async function runJsonlImport(source, options) {
57067
+ throwIfImportAborted(options.signal);
56711
57068
  const definition = resolveSourceDefinition(source);
56712
57069
  const resolvedSource = definition.source;
56713
57070
  const fileSystem = options.fileSystem ?? createNodeFileSystem3();
56714
57071
  await applyHistoryImportSchema(options.db);
56715
57072
  const mode = options.mode ?? "incremental";
56716
57073
  const files = await discoverFiles(definition, options.roots, options.files, fileSystem, options.paths);
57074
+ throwIfImportAborted(options.signal);
56717
57075
  if (mode === "full" && !options.dryRun) {
56718
57076
  await resetCheckpoints(options.db, resolvedSource, files);
56719
57077
  }
@@ -56732,6 +57090,7 @@ async function runJsonlImport(source, options) {
56732
57090
  const codexLastAssistant = new Map;
56733
57091
  const checkpoints = mode === "incremental" ? await loadSourceCheckpoints(options.db, resolvedSource) : undefined;
56734
57092
  for (const file2 of files) {
57093
+ throwIfImportAborted(options.signal);
56735
57094
  const entry = checkpoints?.get(file2);
56736
57095
  const checkpoint = entry?.line ?? 0;
56737
57096
  if (checkpoints !== undefined && entry !== undefined && entry.size !== null && entry.mtimeMs !== null) {
@@ -56743,6 +57102,7 @@ async function runJsonlImport(source, options) {
56743
57102
  }
56744
57103
  let lineNumber = 0;
56745
57104
  for await (const rawLine of readLines(fileSystem, file2)) {
57105
+ throwIfImportAborted(options.signal);
56746
57106
  lineNumber += 1;
56747
57107
  const line = rawLine.trim();
56748
57108
  if (line.length === 0 || lineNumber <= checkpoint)
@@ -56913,22 +57273,23 @@ async function runJsonlImport(source, options) {
56913
57273
  checkpointUpdates += 1;
56914
57274
  }
56915
57275
  }
56916
- if (!options.dryRun && mode === "incremental") {
56917
- const statAfter = await safeStat(fileSystem, file2);
56918
- const identityDegraded = entry !== undefined && entry.size === null && entry.mtimeMs === null;
56919
- const identityChanged = entry !== undefined && (entry.size !== (statAfter?.size ?? null) || entry.mtimeMs !== (statAfter?.mtimeMs ?? null));
56920
- if (statAfter !== null && !identityDegraded && (entry === undefined || identityChanged)) {
56921
- await options.db.batch([
56922
- checkpointUpsertOp(resolvedSource, file2, Math.max(lineNumber, checkpoint), options.now, {
56923
- size: statAfter.size,
56924
- mtimeMs: statAfter.mtimeMs
56925
- })
56926
- ]);
56927
- checkpointUpdates += 1;
56928
- }
57276
+ }
57277
+ if (!options.dryRun && mode === "incremental") {
57278
+ const statAfter = await safeStat(fileSystem, file2);
57279
+ const identityDegraded = entry !== undefined && entry.size === null && entry.mtimeMs === null;
57280
+ const identityChanged = entry !== undefined && (entry.size !== (statAfter?.size ?? null) || entry.mtimeMs !== (statAfter?.mtimeMs ?? null));
57281
+ if (statAfter !== null && !identityDegraded && (entry === undefined || identityChanged)) {
57282
+ await options.db.batch([
57283
+ checkpointUpsertOp(resolvedSource, file2, Math.max(lineNumber, checkpoint), options.now, {
57284
+ size: statAfter.size,
57285
+ mtimeMs: statAfter.mtimeMs
57286
+ })
57287
+ ]);
57288
+ checkpointUpdates += 1;
56929
57289
  }
56930
57290
  }
56931
57291
  }
57292
+ throwIfImportAborted(options.signal);
56932
57293
  let reconciliation;
56933
57294
  if (mode === "full") {
56934
57295
  reconciliation = await reconcileFullImport(options.db, resolvedSource, desiredHashes, files, options.dryRun ?? false);
@@ -57076,6 +57437,7 @@ async function* readLines(fileSystem, file2) {
57076
57437
  var TOOL_CALL_KEY_SEP = "\x00";
57077
57438
  var init_importer = __esm(() => {
57078
57439
  init_dist5();
57440
+ init_cancellation();
57079
57441
  init_hash();
57080
57442
  init_jsonl_importer_dao();
57081
57443
  init_mappers();
@@ -57083,8 +57445,9 @@ var init_importer = __esm(() => {
57083
57445
  init_sources();
57084
57446
  });
57085
57447
 
57086
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/opencode-importer.js
57448
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/opencode-importer.js
57087
57449
  async function runOpenCodeImport(options) {
57450
+ throwIfImportAborted(options.signal);
57088
57451
  const paths = options.paths ?? ambientRuntimePaths2();
57089
57452
  const sourceDatabase = options.sourceDatabase ?? joinPath2(paths.home, ".local/share/opencode/opencode.db");
57090
57453
  const fileSystem = options.fileSystem ?? createNodeFileSystem3();
@@ -57110,6 +57473,7 @@ async function runOpenCodeImport(options) {
57110
57473
  let reconciliation;
57111
57474
  try {
57112
57475
  while (true) {
57476
+ throwIfImportAborted(options.signal);
57113
57477
  const messages = await readOpenCodeMessages(sourceDb, lastTime, lastId, PAGE_SIZE);
57114
57478
  if (messages.length === 0)
57115
57479
  break;
@@ -57173,6 +57537,7 @@ async function runOpenCodeImport(options) {
57173
57537
  }
57174
57538
  reconciliation = { staleTargetRows, staleLedgerRows, staleCheckpointRows };
57175
57539
  }
57540
+ throwIfImportAborted(options.signal);
57176
57541
  if (operations2.length > 0)
57177
57542
  await options.db.batch(operations2);
57178
57543
  } finally {
@@ -57365,13 +57730,14 @@ var SOURCE = "opencode", PAGE_SIZE = 250;
57365
57730
  var init_opencode_importer = __esm(() => {
57366
57731
  init_dist4();
57367
57732
  init_dist5();
57733
+ init_cancellation();
57368
57734
  init_hash();
57369
57735
  init_jsonl_importer_dao();
57370
57736
  init_mappers();
57371
57737
  init_redaction();
57372
57738
  });
57373
57739
 
57374
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/tables.js
57740
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/tables.js
57375
57741
  var BOOKKEEPING_HISTORY_TABLES, IMPORTER_OWNED_TABLES;
57376
57742
  var init_tables = __esm(() => {
57377
57743
  init_jsonl_importer_dao();
@@ -57384,7 +57750,7 @@ var init_tables = __esm(() => {
57384
57750
  ];
57385
57751
  });
57386
57752
 
57387
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.57+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/index.js
57753
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.60+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/index.js
57388
57754
  var init_dist6 = __esm(() => {
57389
57755
  init_assistant_duration();
57390
57756
  init_importer();
@@ -60241,7 +60607,7 @@ function observationIsNewer(leftAt, leftId, rightAt, rightId) {
60241
60607
  }
60242
60608
  var AGENT_EXECUTOR_UPDATE_COLUMNS = "project_id, executor_name, observation_id, observed_at, agent, model, disabled, applied_observation_id, applied_at, attempts, retry_after, last_error";
60243
60609
 
60244
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
60610
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
60245
60611
  function sqlExpressionToText(value) {
60246
60612
  if (typeof value !== "object" || value === null || !("queryChunks" in value)) {
60247
60613
  return;
@@ -60264,7 +60630,7 @@ function getDrizzleTableName(table3) {
60264
60630
  return String(table3[nameSym]);
60265
60631
  }
60266
60632
 
60267
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
60633
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
60268
60634
  function quoteIdent(name) {
60269
60635
  return `"${name.replace(/"/g, '""')}"`;
60270
60636
  }
@@ -60636,7 +61002,7 @@ var init_drizzle_zod = __esm(() => {
60636
61002
  };
60637
61003
  });
60638
61004
 
60639
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
61005
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
60640
61006
  function defineTable(name, columns2) {
60641
61007
  const table3 = sqliteTable(name, columns2);
60642
61008
  let insert2;
@@ -60670,7 +61036,7 @@ var init_define_table = __esm(() => {
60670
61036
  init_ddl();
60671
61037
  });
60672
61038
 
60673
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.57+2c070f091b619667/node_modules/@gobing-ai/ts-db/dist/schema/index.js
61039
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.60+268b1f55075ec56a/node_modules/@gobing-ai/ts-db/dist/schema/index.js
60674
61040
  var exports_schema = {};
60675
61041
  __export(exports_schema, {
60676
61042
  text: () => text,
@@ -61365,7 +61731,7 @@ var init_dao = __esm(() => {
61365
61731
  init_workspace_dao();
61366
61732
  });
61367
61733
 
61368
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/errors.js
61734
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/errors.js
61369
61735
  var WorkflowValidationError, FSMError, RunCollisionError, WorkflowResumeError;
61370
61736
  var init_errors6 = __esm(() => {
61371
61737
  WorkflowValidationError = class WorkflowValidationError extends Error {
@@ -61400,12 +61766,12 @@ var init_errors6 = __esm(() => {
61400
61766
  };
61401
61767
  });
61402
61768
 
61403
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/event-bus/index.js
61769
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/event-bus/index.js
61404
61770
  var init_event_bus2 = __esm(() => {
61405
61771
  init_event_bus();
61406
61772
  });
61407
61773
 
61408
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/api-client.js
61774
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/api-client.js
61409
61775
  function sanitizeUrlForObservability(url2) {
61410
61776
  try {
61411
61777
  const parsed = new URL(url2);
@@ -61636,12 +62002,12 @@ var init_api_client = __esm(() => {
61636
62002
  };
61637
62003
  });
61638
62004
 
61639
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
62005
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
61640
62006
  var init_telemetry = __esm(() => {
61641
62007
  init_tracing2();
61642
62008
  });
61643
62009
 
61644
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/index.js
62010
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/index.js
61645
62011
  var init_dist7 = __esm(() => {
61646
62012
  init_api_client();
61647
62013
  init_event_bus2();
@@ -61649,7 +62015,7 @@ var init_dist7 = __esm(() => {
61649
62015
  init_telemetry();
61650
62016
  });
61651
62017
 
61652
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/run-lifecycle.js
62018
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/run-lifecycle.js
61653
62019
  function runtimeBuiltins(workflowName, stateOrNodeId, runId, transitionsTaken, mode) {
61654
62020
  return {
61655
62021
  workflow: workflowName,
@@ -61933,7 +62299,7 @@ var init_run_lifecycle = __esm(() => {
61933
62299
  ];
61934
62300
  });
61935
62301
 
61936
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/extension/capability-registry.js
62302
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/extension/capability-registry.js
61937
62303
  class CapabilityRegistry {
61938
62304
  kind;
61939
62305
  capabilities = new Map;
@@ -61964,7 +62330,7 @@ class CapabilityRegistry {
61964
62330
  }
61965
62331
  }
61966
62332
 
61967
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-path.js
62333
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-path.js
61968
62334
  function assertRelativeExtensionPath(path9, options = {}) {
61969
62335
  const where = options.sourceName !== undefined ? ` declared by "${options.sourceName}"` : "";
61970
62336
  if (/^([/\\]|[A-Za-z]:[/\\])/.test(path9)) {
@@ -61975,7 +62341,7 @@ function assertRelativeExtensionPath(path9, options = {}) {
61975
62341
  }
61976
62342
  }
61977
62343
 
61978
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-loader.js
62344
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-loader.js
61979
62345
  import { isAbsolute, resolve } from "path";
61980
62346
  async function loadExtensionModules(refs, options, register) {
61981
62347
  if (refs.length === 0)
@@ -62014,17 +62380,17 @@ async function loadExtensionModules(refs, options, register) {
62014
62380
  }
62015
62381
  var init_extension_loader = () => {};
62016
62382
 
62017
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/extension/index.js
62383
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/extension/index.js
62018
62384
  var init_extension = __esm(() => {
62019
62385
  init_extension_loader();
62020
62386
  });
62021
62387
 
62022
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.57+a23fed366e68a588/node_modules/@gobing-ai/ts-runtime/dist/extension.js
62388
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.60+6762e3bd69bdd076/node_modules/@gobing-ai/ts-runtime/dist/extension.js
62023
62389
  var init_extension2 = __esm(() => {
62024
62390
  init_extension();
62025
62391
  });
62026
62392
 
62027
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema.js
62393
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema.js
62028
62394
  var RESERVED_VAR_NAMES, IDENTIFIER, VarsSchema, EnvSchema, relativeExtensionPath, WorkflowExtensionsSchema, ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema;
62029
62395
  var init_schema2 = __esm(() => {
62030
62396
  init_extension2();
@@ -62126,7 +62492,7 @@ var init_schema2 = __esm(() => {
62126
62492
  WorkflowDefSchema = exports_external.union([StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema]);
62127
62493
  });
62128
62494
 
62129
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/config.js
62495
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/config.js
62130
62496
  async function loadWorkflowDef(path9, options = {}) {
62131
62497
  return parseWorkflowDef(await loadStructuredConfig(path9, options), path9);
62132
62498
  }
@@ -62293,7 +62659,7 @@ var init_config4 = __esm(() => {
62293
62659
  RUNTIME_TEMPLATE_NAMESPACES = new Set(RUNTIME_BUILTIN_KEYS);
62294
62660
  });
62295
62661
 
62296
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/extensions.js
62662
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/extensions.js
62297
62663
  function collectWorkflowExtensions(sourceName, sourceDir, extensions) {
62298
62664
  if (extensions === undefined)
62299
62665
  return [];
@@ -62357,7 +62723,7 @@ var init_extensions = __esm(() => {
62357
62723
  init_errors6();
62358
62724
  });
62359
62725
 
62360
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/host.js
62726
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/host.js
62361
62727
  class WorkflowEngineHost {
62362
62728
  lifecycleBus;
62363
62729
  actions = new CapabilityRegistry("workflow action");
@@ -62527,7 +62893,7 @@ var init_host = __esm(() => {
62527
62893
  init_errors6();
62528
62894
  });
62529
62895
 
62530
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
62896
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
62531
62897
  var WORKFLOW_ENGINE_SCHEMA_SQL;
62532
62898
  var init_schema_sql2 = __esm(() => {
62533
62899
  WORKFLOW_ENGINE_SCHEMA_SQL = `
@@ -62600,7 +62966,7 @@ CREATE TABLE IF NOT EXISTS action_runs (
62600
62966
  `.trim();
62601
62967
  });
62602
62968
 
62603
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/persistence.js
62969
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/persistence.js
62604
62970
  async function applyWorkflowEngineSchema(db2) {
62605
62971
  for (const statement of WORKFLOW_ENGINE_SCHEMA_SQL.split(";")) {
62606
62972
  const sql4 = statement.trim();
@@ -62916,7 +63282,7 @@ var init_persistence = __esm(() => {
62916
63282
  init_schema_sql2();
62917
63283
  });
62918
63284
 
62919
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/variables.js
63285
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/variables.js
62920
63286
  function mergeVars(workflowVars = {}, overrideVars = {}) {
62921
63287
  return { ...workflowVars, ...overrideVars };
62922
63288
  }
@@ -62976,7 +63342,7 @@ var init_variables = __esm(() => {
62976
63342
  TEMPLATE_REF = /\$\{([^}]+)\}/g;
62977
63343
  });
62978
63344
 
62979
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/action-step.js
63345
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/action-step.js
62980
63346
  async function runActionStep(action, vars, deps) {
62981
63347
  const { host, persistence, lifecycle, stateOrNodeId, runId } = deps;
62982
63348
  const resolved = resolveTemplates(action.options ?? {}, {
@@ -63040,7 +63406,7 @@ var init_action_step = __esm(() => {
63040
63406
  init_variables();
63041
63407
  });
63042
63408
 
63043
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/state-machine.js
63409
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/state-machine.js
63044
63410
  class StateMachineDriver {
63045
63411
  options;
63046
63412
  constructor(options) {
@@ -63176,7 +63542,7 @@ var init_state_machine = __esm(() => {
63176
63542
  EMPTY_OUTCOME = { outcome: "completed", result: undefined, setVars: undefined };
63177
63543
  });
63178
63544
 
63179
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/transition-flow.js
63545
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/transition-flow.js
63180
63546
  class TransitionFlowDriver {
63181
63547
  options;
63182
63548
  constructor(options) {
@@ -63295,7 +63661,7 @@ var init_transition_flow = __esm(() => {
63295
63661
  init_variables();
63296
63662
  });
63297
63663
 
63298
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/service.js
63664
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/service.js
63299
63665
  class WorkflowService {
63300
63666
  host;
63301
63667
  persistence;
@@ -63520,7 +63886,7 @@ var init_service = __esm(() => {
63520
63886
  init_variables();
63521
63887
  });
63522
63888
 
63523
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/index.js
63889
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/index.js
63524
63890
  var init_dist8 = __esm(() => {
63525
63891
  init_config4();
63526
63892
  init_extensions();
@@ -63530,7 +63896,7 @@ var init_dist8 = __esm(() => {
63530
63896
  init_service();
63531
63897
  });
63532
63898
 
63533
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/config/extensions.js
63899
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/config/extensions.js
63534
63900
  function collectExtensions(sourceName, sourceDir, extensions) {
63535
63901
  if (extensions === undefined)
63536
63902
  return [];
@@ -63544,7 +63910,7 @@ function collectExtensions(sourceName, sourceDir, extensions) {
63544
63910
  }
63545
63911
  var init_extensions2 = () => {};
63546
63912
 
63547
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/types.js
63913
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/types.js
63548
63914
  function createFinding(rule, message, filePath, extras = {}) {
63549
63915
  return {
63550
63916
  ruleId: rule.id,
@@ -63615,7 +63981,7 @@ var init_types3 = __esm(() => {
63615
63981
  });
63616
63982
  });
63617
63983
 
63618
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/config/loader.js
63984
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/config/loader.js
63619
63985
  async function loadPreset(name, options) {
63620
63986
  const merged = await buildMergedRoots(options.roots.map((root) => resolvePath4(root)), options.fileSystem);
63621
63987
  const presetPath = findMergedPreset(merged, name);
@@ -63830,7 +64196,7 @@ var init_loader2 = __esm(() => {
63830
64196
  FIX_MODE_AUTHORITY = { none: 0, suggest: 1, auto: 2 };
63831
64197
  });
63832
64198
 
63833
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/test-stub-fixer.js
64199
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/test-stub-fixer.js
63834
64200
  function normalizeFindingPath(filePath) {
63835
64201
  if (!filePath || isAbsolutePath2(filePath))
63836
64202
  return null;
@@ -63895,7 +64261,7 @@ var init_test_stub_fixer = __esm(() => {
63895
64261
  realFileSystem = createNodeFileSystem3();
63896
64262
  });
63897
64263
 
63898
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/fixers.js
64264
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/fixers.js
63899
64265
  function registerBuiltinFixers(host, exec) {
63900
64266
  const regexFixer = new RegexFixerProvider;
63901
64267
  const pathFixer = new PathFixerProvider;
@@ -64098,7 +64464,7 @@ var init_fixers = __esm(() => {
64098
64464
  };
64099
64465
  });
64100
64466
 
64101
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
64467
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
64102
64468
  function getAgentSessionCapability(agent) {
64103
64469
  return AGENT_SESSION_CAPABILITY[agent];
64104
64470
  }
@@ -64394,7 +64760,7 @@ var init_shims = __esm(() => {
64394
64760
  ALIAS_TO_CANONICAL = Object.fromEntries(Object.values(AGENT_SHIMS).flatMap((shim) => (shim.aliases ?? []).map((alias3) => [alias3, shim.name])));
64395
64761
  });
64396
64762
 
64397
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/identity.js
64763
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/identity.js
64398
64764
  function buildIdentityPreamble(ctx) {
64399
64765
  const sections = [
64400
64766
  `You are agent \`${ctx.agentId}\` (${ctx.agentType}) in workspace \`${ctx.workspace}\`.`
@@ -64470,7 +64836,7 @@ var init_identity = __esm(() => {
64470
64836
  init_dist5();
64471
64837
  });
64472
64838
 
64473
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/quota.js
64839
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/quota.js
64474
64840
  import { createHash as createHash4 } from "crypto";
64475
64841
  function classifyQuotaErrorRecord(record2) {
64476
64842
  const bounded = record2.length > MAX_QUOTA_EVIDENCE_BYTES ? record2.slice(-MAX_QUOTA_EVIDENCE_BYTES) : record2;
@@ -64571,7 +64937,7 @@ var init_quota = __esm(() => {
64571
64937
  ]);
64572
64938
  });
64573
64939
 
64574
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/slash-command.js
64940
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/slash-command.js
64575
64941
  function isClaudeStyleSlashCommand(input) {
64576
64942
  return SLASH_COMMAND_RE2.test(input);
64577
64943
  }
@@ -64599,7 +64965,7 @@ var init_slash_command = __esm(() => {
64599
64965
  SLASH_COMMAND_RE2 = /^\/([a-zA-Z0-9._-]+):([a-zA-Z0-9._-]+)(\s.*)?$/;
64600
64966
  });
64601
64967
 
64602
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
64968
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
64603
64969
  function buildCorrelationEnv(correlation) {
64604
64970
  return {
64605
64971
  [AGENT_RUN_ID_ENV]: correlation.runId,
@@ -64757,7 +65123,7 @@ var init_ai_runner = __esm(() => {
64757
65123
  init_slash_command();
64758
65124
  });
64759
65125
 
64760
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
65126
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
64761
65127
  class AgentDetector {
64762
65128
  runner;
64763
65129
  timeout;
@@ -64833,7 +65199,7 @@ var init_agent_detector = __esm(() => {
64833
65199
  VERSION_PATTERN = /(?<version>\d+\.\d+(?:\.\d+)?)/;
64834
65200
  });
64835
65201
 
64836
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/agent-spec.js
65202
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/agent-spec.js
64837
65203
  function validateAgentId(id) {
64838
65204
  if (!/^[a-z][a-z0-9_-]{1,63}$/.test(id)) {
64839
65205
  throw new ValueError(`Invalid agent id "${id}": expected 2-64 chars, lowercase alphanumeric, "_" or "-"`);
@@ -64932,7 +65298,7 @@ var init_agent_spec = __esm(() => {
64932
65298
  };
64933
65299
  });
64934
65300
 
64935
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/agents/auth-shims.js
65301
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/agents/auth-shims.js
64936
65302
  function isNonEmpty(value) {
64937
65303
  return value !== undefined && value.trim().length > 0;
64938
65304
  }
@@ -65057,7 +65423,7 @@ var init_auth_shims = __esm(() => {
65057
65423
  };
65058
65424
  });
65059
65425
 
65060
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/model-health-probe.js
65426
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/model-health-probe.js
65061
65427
  class ModelHealthProbeRegistry {
65062
65428
  probes = new Map;
65063
65429
  register(providerPrefix, probe) {
@@ -65181,7 +65547,7 @@ var init_model_health_probe = __esm(() => {
65181
65547
  };
65182
65548
  });
65183
65549
 
65184
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/doctor-runner.js
65550
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/doctor-runner.js
65185
65551
  class DoctorRunner {
65186
65552
  detector;
65187
65553
  runner;
@@ -65321,15 +65687,15 @@ var init_doctor_runner = __esm(() => {
65321
65687
  init_model_health_probe();
65322
65688
  });
65323
65689
 
65324
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/events.js
65690
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/events.js
65325
65691
  var init_events = () => {};
65326
65692
 
65327
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/messages.js
65693
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/messages.js
65328
65694
  function formatMessage(msg) {
65329
65695
  return `[task from=${msg.fromId ?? "operator"} id=${msg.id}] ${msg.body}`;
65330
65696
  }
65331
65697
 
65332
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/team-agent-process.js
65698
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/team-agent-process.js
65333
65699
  import { Buffer as Buffer5 } from "buffer";
65334
65700
 
65335
65701
  class TeamAgentProcess {
@@ -65494,7 +65860,7 @@ var init_team_agent_process = __esm(() => {
65494
65860
  init_quota();
65495
65861
  });
65496
65862
 
65497
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/team-orchestrator.js
65863
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/team-orchestrator.js
65498
65864
  class TeamOrchestrator {
65499
65865
  configDir;
65500
65866
  inbox;
@@ -65635,7 +66001,7 @@ var init_team_orchestrator = __esm(() => {
65635
66001
  init_team_agent_process();
65636
66002
  });
65637
66003
 
65638
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.57+ad4f281a0a4e1620/node_modules/@gobing-ai/ts-ai-runner/dist/index.js
66004
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.60+ad62c713c21127cb/node_modules/@gobing-ai/ts-ai-runner/dist/index.js
65639
66005
  var exports_dist3 = {};
65640
66006
  __export(exports_dist3, {
65641
66007
  validateAgentId: () => validateAgentId,
@@ -65695,7 +66061,7 @@ var init_dist9 = __esm(() => {
65695
66061
  init_team_orchestrator();
65696
66062
  });
65697
66063
 
65698
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/config-access.js
66064
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/config-access.js
65699
66065
  function stringArray(value) {
65700
66066
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : undefined;
65701
66067
  }
@@ -65733,7 +66099,7 @@ function parseInlineFlags(source) {
65733
66099
  return { flags, rest: source.slice(match[0].length) };
65734
66100
  }
65735
66101
 
65736
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/glob-match.js
66102
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/glob-match.js
65737
66103
  function matchesAny(path9, patterns) {
65738
66104
  if (patterns === undefined || patterns.length === 0)
65739
66105
  return true;
@@ -65781,7 +66147,7 @@ function escapeRegExp(value) {
65781
66147
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
65782
66148
  }
65783
66149
 
65784
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-discovery.js
66150
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-discovery.js
65785
66151
  async function discoverFiles2(options) {
65786
66152
  const fs3 = options.fs ?? createNodeFileSystem3();
65787
66153
  const allFiles = await walkDir2(options.workdir, fs3, DEFAULT_EXCLUDES);
@@ -65812,12 +66178,12 @@ var init_file_discovery = __esm(() => {
65812
66178
  DEFAULT_EXCLUDES = new Set([".git", "node_modules", "dist", ".coverage", ".astro", ".wrangler"]);
65813
66179
  });
65814
66180
 
65815
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-utils.js
66181
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-utils.js
65816
66182
  var init_file_utils = __esm(() => {
65817
66183
  init_file_discovery();
65818
66184
  });
65819
66185
 
65820
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/agent-detection-evaluator.js
66186
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/agent-detection-evaluator.js
65821
66187
  class AgentDetectionEvaluator {
65822
66188
  detector;
65823
66189
  constructor(detector = new AgentDetector) {
@@ -65845,7 +66211,7 @@ var init_agent_detection_evaluator = __esm(() => {
65845
66211
  init_file_utils();
65846
66212
  });
65847
66213
 
65848
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/coverage-gate-evaluator.js
66214
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/coverage-gate-evaluator.js
65849
66215
  class CoverageGateEvaluator {
65850
66216
  constructor() {}
65851
66217
  async evaluate(rule, context4) {
@@ -65929,7 +66295,7 @@ var init_coverage_gate_evaluator = __esm(() => {
65929
66295
  init_file_utils();
65930
66296
  });
65931
66297
 
65932
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/exit-code-evaluator.js
66298
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/exit-code-evaluator.js
65933
66299
  class ExitCodeEvaluator {
65934
66300
  executor;
65935
66301
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -65965,7 +66331,7 @@ var init_exit_code_evaluator = __esm(() => {
65965
66331
  init_file_utils();
65966
66332
  });
65967
66333
 
65968
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/forbidden-import-evaluator.js
66334
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/forbidden-import-evaluator.js
65969
66335
  class ForbiddenImportEvaluator {
65970
66336
  constructor() {}
65971
66337
  async evaluate(rule, context4) {
@@ -66046,7 +66412,7 @@ var init_forbidden_import_evaluator = __esm(() => {
66046
66412
  init_file_utils();
66047
66413
  });
66048
66414
 
66049
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/import-boundary-evaluator.js
66415
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/import-boundary-evaluator.js
66050
66416
  class ImportBoundaryEvaluator {
66051
66417
  async evaluate(rule, context4) {
66052
66418
  const config4 = rule.evaluator.config ?? {};
@@ -66139,7 +66505,7 @@ var init_import_boundary_evaluator = __esm(() => {
66139
66505
  init_file_utils();
66140
66506
  });
66141
66507
 
66142
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/path-evaluator.js
66508
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/path-evaluator.js
66143
66509
  class PathEvaluator {
66144
66510
  constructor() {}
66145
66511
  async evaluate(rule, context4) {
@@ -66200,7 +66566,7 @@ var init_path_evaluator = __esm(() => {
66200
66566
  init_file_utils();
66201
66567
  });
66202
66568
 
66203
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/regex-evaluator.js
66569
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/regex-evaluator.js
66204
66570
  class RegexEvaluator {
66205
66571
  constructor() {}
66206
66572
  async evaluate(rule, context4) {
@@ -66278,7 +66644,7 @@ var init_regex_evaluator = __esm(() => {
66278
66644
  init_file_utils();
66279
66645
  });
66280
66646
 
66281
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/ripgrep-evaluator.js
66647
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/ripgrep-evaluator.js
66282
66648
  class RipgrepEvaluator {
66283
66649
  executor;
66284
66650
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -66371,7 +66737,7 @@ var init_ripgrep_evaluator = __esm(() => {
66371
66737
  init_file_utils();
66372
66738
  });
66373
66739
 
66374
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/schema-artifact-evaluator.js
66740
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/schema-artifact-evaluator.js
66375
66741
  class SchemaArtifactEvaluator {
66376
66742
  constructor() {}
66377
66743
  async evaluate(rule, context4) {
@@ -66449,7 +66815,7 @@ var init_schema_artifact_evaluator = __esm(() => {
66449
66815
  init_file_utils();
66450
66816
  });
66451
66817
 
66452
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/secrets-scanner-evaluator.js
66818
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/secrets-scanner-evaluator.js
66453
66819
  class SecretsScannerEvaluator {
66454
66820
  constructor() {}
66455
66821
  async evaluate(rule, context4) {
@@ -66517,7 +66883,7 @@ var init_secrets_scanner_evaluator = __esm(() => {
66517
66883
  ALL_CATEGORIES = Object.keys(BUILTIN_PATTERNS);
66518
66884
  });
66519
66885
 
66520
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/sg-evaluator.js
66886
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/sg-evaluator.js
66521
66887
  class SgEvaluator {
66522
66888
  executor;
66523
66889
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -66614,7 +66980,7 @@ var init_sg_evaluator = __esm(() => {
66614
66980
  init_file_utils();
66615
66981
  });
66616
66982
 
66617
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/resolvers/test-path-resolver.js
66983
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/resolvers/test-path-resolver.js
66618
66984
  class TypeScriptTestPathResolver {
66619
66985
  name = "typescript";
66620
66986
  constructor() {}
@@ -66697,7 +67063,7 @@ function testify(rel) {
66697
67063
  return `${dir}test_${base2}`;
66698
67064
  }
66699
67065
 
66700
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/test-location-evaluator.js
67066
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/test-location-evaluator.js
66701
67067
  class TestLocationEvaluator {
66702
67068
  resolvers;
66703
67069
  constructor(resolvers) {
@@ -66772,7 +67138,7 @@ var init_test_location_evaluator = __esm(() => {
66772
67138
  TYPESCRIPT_FALLBACK = new TypeScriptTestPathResolver;
66773
67139
  });
66774
67140
 
66775
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/tsdoc-export-evaluator.js
67141
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/tsdoc-export-evaluator.js
66776
67142
  class TsdocExportEvaluator {
66777
67143
  constructor() {}
66778
67144
  async evaluate(rule, context4) {
@@ -66857,7 +67223,7 @@ var init_tsdoc_export_evaluator = __esm(() => {
66857
67223
  };
66858
67224
  });
66859
67225
 
66860
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/json.js
67226
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/json.js
66861
67227
  class JsonFormatter {
66862
67228
  constructor() {}
66863
67229
  format(result) {
@@ -66865,7 +67231,7 @@ class JsonFormatter {
66865
67231
  }
66866
67232
  }
66867
67233
 
66868
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/text.js
67234
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/text.js
66869
67235
  class TextFormatter {
66870
67236
  constructor() {}
66871
67237
  format(result) {
@@ -66879,7 +67245,7 @@ class TextFormatter {
66879
67245
  }
66880
67246
  }
66881
67247
 
66882
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/host/builtins.js
67248
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/host/builtins.js
66883
67249
  function registerBuiltins(host, executor) {
66884
67250
  const path9 = new PathEvaluator;
66885
67251
  host.evaluators.register("regex", new RegexEvaluator, "builtin");
@@ -66919,7 +67285,7 @@ var init_builtins = __esm(() => {
66919
67285
  init_tsdoc_export_evaluator();
66920
67286
  });
66921
67287
 
66922
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/host/rule-engine-host.js
67288
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/host/rule-engine-host.js
66923
67289
  class RuleEngineHost {
66924
67290
  evaluators;
66925
67291
  formatters;
@@ -66936,7 +67302,7 @@ var init_rule_engine_host = __esm(() => {
66936
67302
  init_extension2();
66937
67303
  });
66938
67304
 
66939
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/engine.js
67305
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/engine.js
66940
67306
  class RuleEngine {
66941
67307
  host;
66942
67308
  events;
@@ -67122,7 +67488,7 @@ var init_engine = __esm(() => {
67122
67488
  init_types3();
67123
67489
  });
67124
67490
 
67125
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/host/bundled-rules.js
67491
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/host/bundled-rules.js
67126
67492
  async function bundledRulesRoot() {
67127
67493
  if (cachedRoot2 !== undefined)
67128
67494
  return cachedRoot2;
@@ -67173,7 +67539,7 @@ var init_bundled_rules = __esm(() => {
67173
67539
  init_dist5();
67174
67540
  });
67175
67541
 
67176
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/db-adapter.js
67542
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/db-adapter.js
67177
67543
  class DbRulePersistenceAdapter {
67178
67544
  db;
67179
67545
  constructor(db2) {
@@ -67207,7 +67573,7 @@ class DbRulePersistenceAdapter {
67207
67573
  }
67208
67574
  }
67209
67575
 
67210
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
67576
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
67211
67577
  var RULE_ENGINE_SCHEMA_SQL = `
67212
67578
  CREATE TABLE IF NOT EXISTS rule_runs (
67213
67579
  id TEXT PRIMARY KEY,
@@ -67253,10 +67619,10 @@ CREATE TABLE IF NOT EXISTS rule_eval_runs (
67253
67619
  CREATE INDEX IF NOT EXISTS idx_rule_eval_runs_run_id ON rule_eval_runs (run_id);
67254
67620
  `;
67255
67621
 
67256
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/index.js
67622
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/index.js
67257
67623
  var init_persistence2 = () => {};
67258
67624
 
67259
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.57+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/index.js
67625
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.60+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/index.js
67260
67626
  var init_dist10 = __esm(() => {
67261
67627
  init_extensions2();
67262
67628
  init_loader2();
@@ -67482,7 +67848,11 @@ CREATE TABLE IF NOT EXISTS queue_jobs (
67482
67848
  next_retry_at INTEGER,
67483
67849
  last_error TEXT,
67484
67850
  processing_at INTEGER,
67485
- expires_at INTEGER
67851
+ expires_at INTEGER,
67852
+ timeout_ms INTEGER,
67853
+ timeout_unlimited INTEGER NOT NULL DEFAULT 0,
67854
+ attempt_token TEXT,
67855
+ lease_expires_at INTEGER
67486
67856
  );
67487
67857
 
67488
67858
  CREATE INDEX IF NOT EXISTS queue_jobs_ready_idx ON queue_jobs (status, next_retry_at, created_at);
@@ -68273,7 +68643,7 @@ ${HISTORY_TASK_SESSION_SCHEMA_SQL}
68273
68643
  ];
68274
68644
  });
68275
68645
 
68276
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/job-queue/db-job-queue.js
68646
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/job-queue/db-job-queue.js
68277
68647
  function queueLogger() {
68278
68648
  if (!_queueLogger)
68279
68649
  _queueLogger = getLogger2("job-queue");
@@ -68329,6 +68699,9 @@ class DBQueueConsumer {
68329
68699
  baseDelay;
68330
68700
  maxDelay;
68331
68701
  drainTimeoutMs;
68702
+ drainPolicy;
68703
+ defaultTimeoutMs;
68704
+ activeAttempts = new Map;
68332
68705
  eventSink;
68333
68706
  timer = null;
68334
68707
  running = false;
@@ -68343,6 +68716,11 @@ class DBQueueConsumer {
68343
68716
  this.baseDelay = nonNegativeFiniteConfig("baseDelay", config4.baseDelay ?? 1000);
68344
68717
  this.maxDelay = nonNegativeFiniteConfig("maxDelay", config4.maxDelay ?? 60000);
68345
68718
  this.drainTimeoutMs = nonNegativeFiniteConfig("drainTimeoutMs", config4.drainTimeoutMs ?? 30000);
68719
+ this.drainPolicy = config4.drainPolicy ?? "bounded";
68720
+ if (config4.defaultTimeoutMs !== undefined && config4.defaultTimeoutMs !== null && (typeof config4.defaultTimeoutMs !== "number" || !Number.isInteger(config4.defaultTimeoutMs) || config4.defaultTimeoutMs <= 0)) {
68721
+ throw new RangeError(`Queue consumer defaultTimeoutMs must be a positive integer or null; received ${String(config4.defaultTimeoutMs)}`);
68722
+ }
68723
+ this.defaultTimeoutMs = config4.defaultTimeoutMs ?? null;
68346
68724
  this.eventSink = resolveEventSink(config4);
68347
68725
  }
68348
68726
  register(type, handler) {
@@ -68373,13 +68751,24 @@ class DBQueueConsumer {
68373
68751
  clearTimeout(this.timer);
68374
68752
  this.timer = null;
68375
68753
  }
68754
+ const drainToCompletion = this.drainPolicy === "drain-to-completion";
68376
68755
  const deadline = Date.now() + this.drainTimeoutMs;
68377
68756
  const pending = this.pollPromise;
68378
68757
  if (pending !== null) {
68379
- await settleWithin(pending, deadline);
68758
+ if (drainToCompletion) {
68759
+ await pending;
68760
+ } else {
68761
+ await settleWithin(pending, deadline);
68762
+ }
68380
68763
  }
68381
- while (this.inFlight > 0 && Date.now() < deadline) {
68382
- await sleep(10);
68764
+ if (drainToCompletion) {
68765
+ while (this.inFlight > 0) {
68766
+ await sleep(10);
68767
+ }
68768
+ } else {
68769
+ while (this.inFlight > 0 && Date.now() < deadline) {
68770
+ await sleep(10);
68771
+ }
68383
68772
  }
68384
68773
  if (wasRunning) {
68385
68774
  const drained = this.inFlight === 0;
@@ -68396,6 +68785,14 @@ class DBQueueConsumer {
68396
68785
  }
68397
68786
  }
68398
68787
  }
68788
+ async cancel(jobId) {
68789
+ const attempt = this.activeAttempts.get(jobId);
68790
+ if (attempt === undefined)
68791
+ return false;
68792
+ attempt.state.cancelled = true;
68793
+ attempt.controller.abort();
68794
+ return true;
68795
+ }
68399
68796
  async stats() {
68400
68797
  return this.dao.getStats();
68401
68798
  }
@@ -68403,7 +68800,7 @@ class DBQueueConsumer {
68403
68800
  return traceAsync("queue.poll", async () => {
68404
68801
  await this.dao.resetStuckJobs(this.visibilityTimeout);
68405
68802
  await this.dao.failExpiredJobs();
68406
- const jobs = await this.dao.claimReady(this.batchSize);
68803
+ const jobs = await this.dao.claimReady(this.batchSize, { leaseMs: this.visibilityTimeout });
68407
68804
  let processed = 0;
68408
68805
  for (let index2 = 0;index2 < jobs.length; index2 += this.maxConcurrency) {
68409
68806
  const batch = jobs.slice(index2, index2 + this.maxConcurrency);
@@ -68449,7 +68846,7 @@ class DBQueueConsumer {
68449
68846
  try {
68450
68847
  job = toJob(record2);
68451
68848
  } catch (error51) {
68452
- await this.failOrRetry(record2, error51, 0);
68849
+ await this.failOrRetry(record2, error51, 0, record2.attemptToken ?? undefined);
68453
68850
  return;
68454
68851
  }
68455
68852
  return traceAsync("queue.job.process", async () => {
@@ -68459,37 +68856,109 @@ class DBQueueConsumer {
68459
68856
  "queue.job_attempt": job.attempts
68460
68857
  });
68461
68858
  const handler = this.handlers.get(job.type);
68859
+ const token = record2.attemptToken ?? undefined;
68462
68860
  if (handler === undefined) {
68463
- await this.failOrRetry(job, new Error(`No handler registered for job type "${job.type}"`), 0);
68861
+ await this.failOrRetry(job, new Error(`No handler registered for job type "${job.type}"`), 0, token);
68464
68862
  return;
68465
68863
  }
68466
- const startMs = performance.now();
68864
+ let attemptWake;
68865
+ const attempt = { lost: false, cancelled: false, settled: false };
68866
+ const attemptAbort = new AbortController;
68867
+ if (token !== undefined) {
68868
+ const { promise: settledSignal, resolve: resolveSettled } = Promise.withResolvers();
68869
+ attempt.settledSignal = settledSignal;
68870
+ attemptWake = resolveSettled;
68871
+ this.activeAttempts.set(record2.id, { controller: attemptAbort, state: attempt });
68872
+ }
68873
+ const renewal = token === undefined ? undefined : this.renewUntilSettled(record2.id, token, attempt, attemptAbort).catch(() => {});
68467
68874
  try {
68468
- await handler(job);
68469
- await this.dao.markCompleted(job.id);
68470
- const durationMs = performance.now() - startMs;
68471
- getQueueJobCompletedTotal().add(1, { type: job.type });
68472
- getQueueJobProcessingDuration().record(durationMs, { type: job.type });
68473
- const completed = {
68474
- jobId: job.id,
68475
- type: job.type,
68476
- durationMs: Number.isFinite(durationMs) ? durationMs : 0,
68477
- attempt: job.attempts,
68478
- severity: "info"
68479
- };
68480
- await this.eventSink?.bus.emit("queue.job.completed", completed);
68481
- } catch (error51) {
68875
+ const resolvedTimeout = resolveExecutionTimeoutMs(`job "${job.type}"`, record2.timeoutUnlimited === 1 ? null : record2.timeoutMs ?? undefined, this.defaultTimeoutMs);
68876
+ const startMs = performance.now();
68877
+ const outcome = await runWithExecutionDeadline((context4) => handler(job, context4), {
68878
+ timeoutMs: resolvedTimeout,
68879
+ signal: attemptAbort.signal
68880
+ });
68881
+ attempt.settled = true;
68882
+ attemptWake?.();
68482
68883
  const durationMs = performance.now() - startMs;
68483
- getQueueJobProcessingDuration().record(durationMs, { type: job.type });
68484
- await this.failOrRetry(job, error51, Number.isFinite(durationMs) ? durationMs : 0);
68884
+ getQueueJobProcessingDuration().record(Number.isFinite(durationMs) ? durationMs : 0, {
68885
+ type: job.type
68886
+ });
68887
+ if (attempt.lost) {
68888
+ queueLogger().warn("queue attempt lost lease ownership; acknowledgement fenced", {
68889
+ jobId: record2.id,
68890
+ type: job.type,
68891
+ outcome: outcome.outcome
68892
+ });
68893
+ return;
68894
+ }
68895
+ if (outcome.outcome === "error") {
68896
+ await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
68897
+ } else if (outcome.timedOut) {
68898
+ await this.failOrRetry(job, outcome.error, Number.isFinite(durationMs) ? durationMs : 0, token);
68899
+ } else if (attempt.cancelled) {
68900
+ const message = "job cancelled";
68901
+ const applied = await this.dao.markFailed(record2.id, job.attempts + 1, message, token);
68902
+ if (applied) {
68903
+ getQueueJobFailedTotal().add(1, { type: job.type });
68904
+ await this.eventSink?.bus.emit("queue.job.failed", {
68905
+ jobId: job.id,
68906
+ type: job.type,
68907
+ error: message,
68908
+ attempt: job.attempts + 1,
68909
+ maxRetries: job.maxRetries,
68910
+ durationMs: Number.isFinite(durationMs) ? durationMs : 0,
68911
+ severity: "warning"
68912
+ });
68913
+ }
68914
+ } else {
68915
+ await this.dao.markCompleted(record2.id, token);
68916
+ getQueueJobCompletedTotal().add(1, { type: job.type });
68917
+ const completed = {
68918
+ jobId: job.id,
68919
+ type: job.type,
68920
+ durationMs: Number.isFinite(durationMs) ? durationMs : 0,
68921
+ attempt: job.attempts,
68922
+ severity: "info"
68923
+ };
68924
+ await this.eventSink?.bus.emit("queue.job.completed", completed);
68925
+ }
68926
+ } finally {
68927
+ attempt.settled = true;
68928
+ attemptWake?.();
68929
+ if (renewal !== undefined)
68930
+ await renewal;
68931
+ if (token !== undefined)
68932
+ this.activeAttempts.delete(record2.id);
68485
68933
  }
68486
68934
  });
68487
68935
  }
68488
- async failOrRetry(job, error51, durationMs) {
68936
+ async renewUntilSettled(id, token, attempt, attemptAbort) {
68937
+ const intervalMs = Math.max(1, Math.floor(this.visibilityTimeout / 3));
68938
+ while (!attempt.settled) {
68939
+ await Promise.race([sleep(intervalMs), attempt.settledSignal]);
68940
+ if (attempt.settled)
68941
+ return;
68942
+ let renewed = false;
68943
+ try {
68944
+ renewed = await this.dao.renewLease(id, token, this.visibilityTimeout);
68945
+ } catch {
68946
+ renewed = false;
68947
+ }
68948
+ if (attempt.settled)
68949
+ return;
68950
+ if (!renewed) {
68951
+ attempt.lost = true;
68952
+ attemptAbort.abort();
68953
+ return;
68954
+ }
68955
+ }
68956
+ }
68957
+ async failOrRetry(job, error51, durationMs, attemptToken) {
68489
68958
  const attempts = job.attempts + 1;
68490
68959
  const message = error51 instanceof Error ? error51.message : String(error51);
68491
68960
  if (attempts >= job.maxRetries) {
68492
- await this.dao.markFailed(job.id, attempts, message);
68961
+ await this.dao.markFailed(job.id, attempts, message, attemptToken);
68493
68962
  getQueueJobFailedTotal().add(1, { type: job.type });
68494
68963
  const failed = {
68495
68964
  jobId: job.id,
@@ -68505,7 +68974,7 @@ class DBQueueConsumer {
68505
68974
  }
68506
68975
  const delay = Math.min(this.maxDelay, this.baseDelay * 2 ** Math.max(0, attempts - 1));
68507
68976
  const nextRetryAt = Date.now() + delay;
68508
- await this.dao.markForRetry(job.id, attempts, message, nextRetryAt);
68977
+ await this.dao.markForRetry(job.id, attempts, message, nextRetryAt, attemptToken);
68509
68978
  const retrying = {
68510
68979
  jobId: job.id,
68511
68980
  type: job.type,
@@ -68530,7 +68999,8 @@ function toJob(record2) {
68530
68999
  updatedAt: record2.updatedAt,
68531
69000
  nextRetryAt: record2.nextRetryAt,
68532
69001
  lastError: record2.lastError,
68533
- processingAt: record2.processingAt
69002
+ processingAt: record2.processingAt,
69003
+ timeoutMs: record2.timeoutUnlimited === 1 ? null : record2.timeoutMs ?? undefined
68534
69004
  };
68535
69005
  }
68536
69006
  function sleep(ms) {
@@ -68576,7 +69046,7 @@ var init_db_job_queue = __esm(() => {
68576
69046
  init_tracing2();
68577
69047
  });
68578
69048
 
68579
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/job-queue-db.js
69049
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/job-queue-db.js
68580
69050
  var exports_job_queue_db = {};
68581
69051
  __export(exports_job_queue_db, {
68582
69052
  DBQueueConsumer: () => DBQueueConsumer,
@@ -68893,8 +69363,9 @@ async function failStaleSchedulerCustomJob(db2, id, now, reason) {
68893
69363
  const changed = await db2.queryFirst("SELECT changes() AS n");
68894
69364
  return (changed?.n ?? 0) > 0;
68895
69365
  }
68896
- async function failOrphanedProcessingJobs(db2, now) {
68897
- const orphan = await db2.queryFirst(`SELECT count(*) AS cnt FROM queue_jobs WHERE status = 'processing'`);
69366
+ async function failOrphanedProcessingJobs(db2, now, exemptJobNames = []) {
69367
+ const exemptFilter = exemptJobNames.length === 0 ? "" : ` AND NOT (type = 'scheduler.custom' AND json_extract(payload, '$.name') IN (${exemptJobNames.map(() => "?").join(", ")}))`;
69368
+ const orphan = await db2.queryFirst(`SELECT count(*) AS cnt FROM queue_jobs WHERE status = 'processing'${exemptFilter}`, ...exemptJobNames);
68898
69369
  const count3 = orphan?.cnt ?? 0;
68899
69370
  if (count3 > 0) {
68900
69371
  await db2.run(`UPDATE queue_jobs
@@ -68902,7 +69373,7 @@ async function failOrphanedProcessingJobs(db2, now) {
68902
69373
  last_error = 'Process terminated: server restarted while job was in flight',
68903
69374
  processing_at = NULL,
68904
69375
  updated_at = ?
68905
- WHERE status = 'processing'`, now);
69376
+ WHERE status = 'processing'${exemptFilter}`, now, ...exemptJobNames);
68906
69377
  }
68907
69378
  return count3;
68908
69379
  }
@@ -72459,19 +72930,36 @@ function buildWorkflowSteps(def) {
72459
72930
  };
72460
72931
  });
72461
72932
  }
72933
+ function columnLabel(index2) {
72934
+ let n2 = Math.max(0, Math.floor(index2));
72935
+ let label = "";
72936
+ do {
72937
+ label = String.fromCharCode(65 + n2 % 26) + label;
72938
+ n2 = Math.floor(n2 / 26) - 1;
72939
+ } while (n2 >= 0);
72940
+ return label;
72941
+ }
72942
+ function buildStepLabels(count3) {
72943
+ const labels = [];
72944
+ for (let i2 = 0;i2 < Math.max(0, Math.floor(count3)); i2++)
72945
+ labels.push(columnLabel(i2));
72946
+ return labels;
72947
+ }
72462
72948
  function renderWorkflowTodo(def) {
72463
72949
  const kind = def.kind ?? "state-machine";
72464
72950
  const lines = [`# ${def.name} (${kind}) \u2014 declared steps`, ""];
72465
72951
  if (kind === "state-machine") {
72466
72952
  lines.push("Declared step inventory in declaration order, not a predicted execution path.", "");
72467
72953
  }
72468
- for (const step of buildWorkflowSteps(def)) {
72469
- lines.push(formatWorkflowStepLine(step));
72470
- }
72954
+ const steps = buildWorkflowSteps(def);
72955
+ const labels = buildStepLabels(steps.length);
72956
+ steps.forEach((step, i2) => {
72957
+ lines.push(formatWorkflowStepLine(step, labels[i2]));
72958
+ });
72471
72959
  return lines.join(`
72472
72960
  `);
72473
72961
  }
72474
- function formatWorkflowStepLine(step) {
72962
+ function formatWorkflowStepLine(step, label) {
72475
72963
  const markers = [
72476
72964
  step.initial ? "initial" : undefined,
72477
72965
  step.terminal ? "terminal" : undefined,
@@ -72481,13 +72969,16 @@ function formatWorkflowStepLine(step) {
72481
72969
  step.conditional ? "conditional" : undefined,
72482
72970
  step.nodeType !== undefined && step.nodeType !== "action" ? step.nodeType : undefined
72483
72971
  ].filter((m) => m !== undefined);
72484
- return markers.length > 0 ? `- [ ] ${step.id} \u2014 ${markers.join(" \xB7 ")}` : `- [ ] ${step.id}`;
72972
+ const head = label === undefined ? step.id : `${label}. ${step.id}`;
72973
+ return markers.length > 0 ? `- [ ] ${head} \u2014 ${markers.join(" \xB7 ")}` : `- [ ] ${head}`;
72485
72974
  }
72486
72975
  function renderRunPlan(def) {
72487
72976
  const kind = def.kind ?? "state-machine";
72977
+ const steps = buildWorkflowSteps(def);
72978
+ const labels = buildStepLabels(steps.length);
72488
72979
  return [
72489
72980
  `plan (${kind}) \u2014 declared inventory, not a predicted route:`,
72490
- ...buildWorkflowSteps(def).map(formatWorkflowStepLine)
72981
+ ...steps.map((step, i2) => formatWorkflowStepLine(step, labels[i2]))
72491
72982
  ].join(`
72492
72983
  `);
72493
72984
  }
@@ -72522,6 +73013,7 @@ function formatUsageSummary(usage) {
72522
73013
  return parts.length > 0 ? ` \xB7 usage ${parts.join(", ")}` : " \xB7 usage measured";
72523
73014
  }
72524
73015
  var isAgentExecution = (e) => ("executionId" in e), isActionOutput = (e) => ("stream" in e) && ("chunk" in e) && !("executionId" in e), isActionStarted = (e) => ("kind" in e) && ("node" in e), isActionFinished = (e) => ("durationMs" in e) && ("ok" in e), isPhase = (e) => ("phase" in e), isTransition = (e) => ("from" in e) && ("to" in e);
73016
+ var init_step_reporter = () => {};
72525
73017
 
72526
73018
  // ../../packages/app/src/observability/workflow-run-log-sink.ts
72527
73019
  import { closeSync as closeSync2, mkdirSync as mkdirSync5, openSync as openSync2, writeSync as writeSync2 } from "fs";
@@ -72702,6 +73194,7 @@ var DEFAULT_RUN_LOG_MAX_BYTES, MAX_STEERING_NOTE_CHARS = 1024, TRUNCATION_MARKER
72702
73194
  `, RUN_LOG_EVENT_NAMES;
72703
73195
  var init_workflow_run_log_sink = __esm(() => {
72704
73196
  init_observability();
73197
+ init_step_reporter();
72705
73198
  DEFAULT_RUN_LOG_MAX_BYTES = 1024 * 1024;
72706
73199
  RUN_LOG_EVENT_NAMES = [
72707
73200
  "workflow.run.started",
@@ -75197,66 +75690,40 @@ var init_anchor_qualifier = __esm(() => {
75197
75690
  });
75198
75691
 
75199
75692
  // ../../packages/app/src/services/bounded-child-run.ts
75200
- function resolveKillGraceMs(env) {
75693
+ function resolveKillGraceMs3(env) {
75201
75694
  const raw = env.SPUR_SCHEDULER_KILL_GRACE_MS;
75202
75695
  if (raw === undefined || raw.trim() === "")
75203
75696
  return CHILD_KILL_GRACE_MS;
75204
75697
  const parsed = Number(raw);
75205
75698
  return Number.isInteger(parsed) && parsed > 0 ? parsed : CHILD_KILL_GRACE_MS;
75206
75699
  }
75207
- function escalateGroupKill(pid) {
75208
- if (pid === undefined || process.platform === "win32")
75209
- return;
75210
- try {
75211
- process.kill(-pid, "SIGKILL");
75212
- } catch {
75213
- try {
75214
- process.kill(pid, "SIGKILL");
75215
- } catch {}
75216
- }
75217
- }
75218
75700
  async function runBoundedChild(executor, options) {
75219
- const killGraceMs = options.killGraceMs ?? CHILD_KILL_GRACE_MS;
75220
- const controller = new AbortController;
75221
- let pid;
75222
- let timedOut = false;
75223
- const deadline = setTimeout(() => {
75224
- timedOut = true;
75225
- controller.abort();
75226
- }, options.timeoutMs);
75227
- let escalation;
75228
- controller.signal.addEventListener("abort", () => {
75229
- escalation = setTimeout(() => escalateGroupKill(pid), killGraceMs);
75230
- }, { once: true });
75231
- try {
75232
- const result = await executor.run({
75233
- command: options.command,
75234
- ...options.args !== undefined ? { args: options.args } : {},
75235
- ...options.cwd !== undefined ? { cwd: options.cwd } : {},
75236
- ...options.env !== undefined ? { env: options.env } : {},
75237
- timeout: options.timeoutMs,
75238
- ...options.maxOutput !== undefined ? { maxOutput: options.maxOutput } : {},
75239
- forceBuffered: true,
75240
- signal: controller.signal,
75241
- onSpawn: (spawned) => {
75242
- pid = spawned;
75243
- }
75244
- });
75245
- const elapsedMs = result.durationMs;
75246
- let terminationReason;
75247
- if (timedOut) {
75248
- terminationReason = "timeout";
75249
- } else if (result.exitCode === null) {
75250
- terminationReason = "signal";
75251
- } else {
75252
- terminationReason = "exit";
75253
- }
75254
- return { result, timedOut, deadlineMs: options.timeoutMs, elapsedMs, terminationReason };
75255
- } finally {
75256
- clearTimeout(deadline);
75257
- if (escalation !== undefined)
75258
- clearTimeout(escalation);
75701
+ const result = await executor.run({
75702
+ command: options.command,
75703
+ ...options.args !== undefined ? { args: options.args } : {},
75704
+ ...options.cwd !== undefined ? { cwd: options.cwd } : {},
75705
+ ...options.env !== undefined ? { env: options.env } : {},
75706
+ timeout: options.timeoutMs,
75707
+ ...options.killGraceMs !== undefined ? { killGraceMs: options.killGraceMs } : {},
75708
+ ...options.maxOutput !== undefined ? { maxOutput: options.maxOutput } : {},
75709
+ forceBuffered: true
75710
+ });
75711
+ const elapsedMs = result.durationMs;
75712
+ let terminationReason;
75713
+ if (result.outcome === "timeout") {
75714
+ terminationReason = "timeout";
75715
+ } else if (result.exitCode === null) {
75716
+ terminationReason = "signal";
75717
+ } else {
75718
+ terminationReason = "exit";
75259
75719
  }
75720
+ return {
75721
+ result,
75722
+ timedOut: terminationReason === "timeout",
75723
+ deadlineMs: options.timeoutMs,
75724
+ elapsedMs,
75725
+ terminationReason
75726
+ };
75260
75727
  }
75261
75728
  function describeBoundedFailure(parts) {
75262
75729
  const { subject, outcome, outputTail } = parts;
@@ -80981,6 +81448,41 @@ var init_event_names = __esm(() => {
80981
81448
  }));
80982
81449
  });
80983
81450
 
81451
+ // ../../packages/app/src/services/execution-policy.ts
81452
+ function parseTimeoutInput(raw) {
81453
+ const normalized = raw.trim();
81454
+ if (normalized.toLowerCase() === "none")
81455
+ return null;
81456
+ if (!/^[0-9]+$/.test(normalized)) {
81457
+ throw new Error(`invalid timeout "${raw}": expected a positive integer number of milliseconds or 'none'`);
81458
+ }
81459
+ const value = Number(normalized);
81460
+ if (value === 0 || value > MAX_TIMEOUT_INPUT_MS) {
81461
+ throw new Error(`invalid timeout "${raw}": expected a positive integer number of milliseconds or 'none'`);
81462
+ }
81463
+ return value;
81464
+ }
81465
+ function normalizeLegacyTimeoutMs(raw, fallbackMs) {
81466
+ if (raw === undefined || raw.trim() === "")
81467
+ return fallbackMs;
81468
+ if (raw.trim().toLowerCase() === "none")
81469
+ return null;
81470
+ const parsed = Number(raw);
81471
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : fallbackMs;
81472
+ }
81473
+ function assertCanonicalTimeoutMs(value) {
81474
+ if (value === undefined)
81475
+ return;
81476
+ if (value === null)
81477
+ return null;
81478
+ if (typeof value === "number" && Number.isInteger(value) && value > 0 && value <= MAX_TIMEOUT_INPUT_MS) {
81479
+ return value;
81480
+ }
81481
+ throw new Error(`invalid canonical timeout ${JSON.stringify(value)}: expected undefined, null, or a positive integer \u2264 ${MAX_TIMEOUT_INPUT_MS}`);
81482
+ }
81483
+ var MAX_TIMEOUT_INPUT_MS = 2147483647;
81484
+ var init_execution_policy = () => {};
81485
+
80984
81486
  // ../../packages/app/src/services/feature-service.ts
80985
81487
  function isFeatureActionName(action) {
80986
81488
  return FEATURE_ACTION_NAMES.includes(action);
@@ -84413,22 +84915,14 @@ var init_job_exclusion_guard = __esm(() => {
84413
84915
 
84414
84916
  // ../../packages/app/src/services/scheduler-custom-job-service.ts
84415
84917
  function resolveSchedulerCustomTimeoutMs(env) {
84416
- const raw = env.SPUR_SCHEDULER_CUSTOM_TIMEOUT_MS;
84417
- if (raw === undefined || raw.trim() === "")
84418
- return SCHEDULER_CUSTOM_TIMEOUT_MS;
84419
- const parsed = Number(raw);
84420
- return Number.isInteger(parsed) && parsed > 0 ? parsed : SCHEDULER_CUSTOM_TIMEOUT_MS;
84918
+ return normalizeLegacyTimeoutMs(env.SPUR_SCHEDULER_CUSTOM_TIMEOUT_MS, SCHEDULER_CUSTOM_TIMEOUT_MS);
84421
84919
  }
84422
84920
  function schedulerJobTimeoutEnvName(name) {
84423
84921
  const snake = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([^A-Za-z0-9]+)/g, "_").toUpperCase().replace(/^_+|_+$/g, "");
84424
84922
  return `SPUR_SCHEDULER_TIMEOUT_${snake}_MS`;
84425
84923
  }
84426
84924
  function resolveSchedulerJobTimeoutMs(name, env, fallbackMs) {
84427
- const raw = env[schedulerJobTimeoutEnvName(name)];
84428
- if (raw === undefined || raw.trim() === "")
84429
- return fallbackMs;
84430
- const parsed = Number(raw);
84431
- return Number.isInteger(parsed) && parsed > 0 ? parsed : fallbackMs;
84925
+ return normalizeLegacyTimeoutMs(env[schedulerJobTimeoutEnvName(name)], fallbackMs);
84432
84926
  }
84433
84927
  function outputTail(text4) {
84434
84928
  const trimmed = text4.trim();
@@ -84466,7 +84960,8 @@ async function handleSchedulerCustomJob(deps, job) {
84466
84960
  acquireExclusiveJob(exclusiveKey, `scheduler job "${payload.name}"`);
84467
84961
  }
84468
84962
  activeJobs.add(payload.name);
84469
- const timeoutMs = deps.resolveTimeoutMs?.(payload.name) ?? deps.timeoutMs ?? SCHEDULER_CUSTOM_TIMEOUT_MS;
84963
+ const resolvedPerJob = deps.resolveTimeoutMs?.(payload.name);
84964
+ const timeoutMs = resolvedPerJob !== undefined ? resolvedPerJob : deps.timeoutMs !== undefined ? deps.timeoutMs : SCHEDULER_CUSTOM_TIMEOUT_MS;
84470
84965
  try {
84471
84966
  const outcome = await runBoundedChild(deps.executor, {
84472
84967
  command: "/bin/sh",
@@ -84496,6 +84991,7 @@ async function handleSchedulerCustomJob(deps, job) {
84496
84991
  }
84497
84992
  var SCHEDULER_CUSTOM_JOB = "scheduler.custom", SCHEDULER_CUSTOM_TIMEOUT_MS = 600000, SCHEDULER_CUSTOM_MAX_OUTPUT = 1e6, activeJobs;
84498
84993
  var init_scheduler_custom_job_service = __esm(() => {
84994
+ init_execution_policy();
84499
84995
  init_job_exclusion_guard();
84500
84996
  activeJobs = new Set;
84501
84997
  });
@@ -84503,13 +84999,15 @@ var init_scheduler_custom_job_service = __esm(() => {
84503
84999
  // ../../packages/app/src/services/history-refresh-service.ts
84504
85000
  function parsePayload(raw) {
84505
85001
  const candidate = typeof raw === "string" ? safeJsonParse(raw) : raw;
85002
+ const candidateTimeoutMs = candidate?.timeoutMs;
84506
85003
  const trigger = candidate?.trigger === "task-done" || candidate?.trigger === "pipeline-run" || candidate?.trigger === "manual" || candidate?.trigger === "schedule" ? candidate.trigger : "task-done";
84507
85004
  return {
84508
85005
  trigger,
84509
85006
  triggerId: typeof candidate?.triggerId === "string" ? candidate.triggerId : null,
84510
85007
  windowStart: typeof candidate?.windowStart === "number" ? candidate.windowStart : 0,
84511
85008
  windowEnd: typeof candidate?.windowEnd === "number" ? candidate.windowEnd : 0,
84512
- ...candidate?.importMode === "full" || candidate?.importMode === "incremental" ? { importMode: candidate.importMode } : {}
85009
+ ...candidate?.importMode === "full" || candidate?.importMode === "incremental" ? { importMode: candidate.importMode } : {},
85010
+ ...candidateTimeoutMs === null || typeof candidateTimeoutMs === "number" && Number.isInteger(candidateTimeoutMs) && candidateTimeoutMs > 0 ? { timeoutMs: candidateTimeoutMs } : {}
84513
85011
  };
84514
85012
  }
84515
85013
  function safeJsonParse(raw) {
@@ -84546,12 +85044,14 @@ function validateHistoryRefreshPayload(raw) {
84546
85044
  if (importMode !== undefined && importMode !== "full" && importMode !== "incremental") {
84547
85045
  throw new Error(`history refresh payload has invalid importMode: ${JSON.stringify(importMode)}`);
84548
85046
  }
85047
+ const timeoutMs = assertCanonicalTimeoutMs(candidate.timeoutMs);
84549
85048
  return {
84550
85049
  trigger,
84551
85050
  triggerId,
84552
85051
  windowStart,
84553
85052
  windowEnd,
84554
- ...importMode !== undefined ? { importMode } : {}
85053
+ ...importMode !== undefined ? { importMode } : {},
85054
+ ...timeoutMs !== undefined ? { timeoutMs } : {}
84555
85055
  };
84556
85056
  }
84557
85057
  function parseHistoryRefreshContext(raw) {
@@ -84567,6 +85067,7 @@ function parseHistoryRefreshContext(raw) {
84567
85067
  }
84568
85068
  async function enqueueHistoryRefresh(db2, options) {
84569
85069
  const triggerConfig = resolveHistoryRefreshTrigger(options.config);
85070
+ const explicitTimeoutMs = assertCanonicalTimeoutMs(options.timeoutMs);
84570
85071
  let enabled = triggerConfig.onCompletion;
84571
85072
  if (options.trigger === "manual")
84572
85073
  enabled = true;
@@ -84579,7 +85080,8 @@ async function enqueueHistoryRefresh(db2, options) {
84579
85080
  triggerId: options.triggerId ?? null,
84580
85081
  windowStart: now2,
84581
85082
  windowEnd: now2,
84582
- ...options.importMode !== undefined ? { importMode: options.importMode } : {}
85083
+ ...options.importMode !== undefined ? { importMode: options.importMode } : {},
85084
+ ...explicitTimeoutMs !== undefined ? { timeoutMs: explicitTimeoutMs } : {}
84583
85085
  };
84584
85086
  const result = await enqueueCoalesced(db2, {
84585
85087
  type: HISTORY_REFRESH_JOB,
@@ -84596,25 +85098,32 @@ async function enqueueHistoryRefresh(db2, options) {
84596
85098
  triggerId: prev.triggerId,
84597
85099
  windowStart: Math.min(prev.windowStart, curr.windowStart),
84598
85100
  windowEnd: Math.max(prev.windowEnd, curr.windowEnd),
84599
- ...importMode !== undefined ? { importMode } : {}
85101
+ ...importMode !== undefined ? { importMode } : {},
85102
+ ...prev.timeoutMs !== undefined ? { timeoutMs: prev.timeoutMs } : {},
85103
+ ...prev.timeoutMs === undefined && curr.timeoutMs !== undefined ? { timeoutMs: curr.timeoutMs } : {}
84600
85104
  };
84601
85105
  }
84602
85106
  });
84603
85107
  return { status: result.status, jobId: result.jobId, payload: parsePayload(result.payload) };
84604
85108
  }
84605
- function resolveHistoryRefreshTimeoutMs(env) {
84606
- const raw = env.SPUR_HISTORY_REFRESH_TIMEOUT_MS;
84607
- if (raw === undefined || raw.trim() === "")
84608
- return SCHEDULER_CUSTOM_TIMEOUT_MS;
84609
- const parsed = Number(raw);
84610
- return Number.isInteger(parsed) && parsed > 0 ? parsed : SCHEDULER_CUSTOM_TIMEOUT_MS;
85109
+ function resolveHistoryRefreshTimeoutMs(env, canonical) {
85110
+ if (canonical !== undefined)
85111
+ return assertCanonicalTimeoutMs(canonical);
85112
+ return normalizeLegacyTimeoutMs(env.SPUR_HISTORY_REFRESH_TIMEOUT_MS, SCHEDULER_CUSTOM_TIMEOUT_MS);
84611
85113
  }
84612
85114
  async function handleHistoryRefreshJob(deps, job) {
84613
85115
  const payload = validateHistoryRefreshPayload(job.payload);
84614
85116
  const split = splitLaunchCommand(deps.invocation, 'history refresh "invocation"');
84615
85117
  if ("error" in split)
84616
85118
  throw new Error(split.error);
84617
- const timeoutMs = deps.timeoutMs ?? SCHEDULER_CUSTOM_TIMEOUT_MS;
85119
+ const resolvedCanonical = payload.timeoutMs;
85120
+ const timeoutMs = resolvedCanonical !== undefined ? resolvedCanonical : deps.timeoutMs !== undefined ? deps.timeoutMs : SCHEDULER_CUSTOM_TIMEOUT_MS;
85121
+ let propagatedSourceTimeout;
85122
+ if (timeoutMs === null) {
85123
+ propagatedSourceTimeout = "none";
85124
+ } else if (timeoutMs !== SCHEDULER_CUSTOM_TIMEOUT_MS) {
85125
+ propagatedSourceTimeout = String(timeoutMs);
85126
+ }
84618
85127
  acquireExclusiveJob(HISTORY_PRODUCER_EXCLUSIVE_KEY, "history.refresh");
84619
85128
  let outcome;
84620
85129
  try {
@@ -84623,7 +85132,11 @@ async function handleHistoryRefreshJob(deps, job) {
84623
85132
  args: [...split.leadingArgs, "--no-logo", "history", "daily"],
84624
85133
  cwd: deps.cwd,
84625
85134
  timeoutMs,
84626
- ...deps.databaseUrl !== undefined ? { env: { [HISTORY_REFRESH_CONTEXT_ENV]: JSON.stringify(payload), DATABASE_URL: deps.databaseUrl } } : { env: { [HISTORY_REFRESH_CONTEXT_ENV]: JSON.stringify(payload) } },
85135
+ env: {
85136
+ [HISTORY_REFRESH_CONTEXT_ENV]: JSON.stringify(payload),
85137
+ ...propagatedSourceTimeout !== undefined ? { [HISTORY_SOURCE_TIMEOUT_ENV]: propagatedSourceTimeout } : {},
85138
+ ...deps.databaseUrl !== undefined ? { DATABASE_URL: deps.databaseUrl } : {}
85139
+ },
84627
85140
  maxOutput: HISTORY_REFRESH_MAX_OUTPUT
84628
85141
  });
84629
85142
  } finally {
@@ -84647,11 +85160,12 @@ async function handleHistoryRefreshJob(deps, job) {
84647
85160
  throw new Error(`history daily exited ${result.exitCode}${stdoutDetail || stderrDetail}`);
84648
85161
  }
84649
85162
  }
84650
- var HISTORY_REFRESH_JOB = "history.refresh", HISTORY_REFRESH_CONTEXT_ENV = "SPUR_HISTORY_REFRESH_CONTEXT", HISTORY_REFRESH_MAX_OUTPUT = 1e6;
85163
+ var HISTORY_SOURCE_TIMEOUT_ENV = "SPUR_HISTORY_SOURCE_TIMEOUT_MS", HISTORY_REFRESH_JOB = "history.refresh", HISTORY_REFRESH_CONTEXT_ENV = "SPUR_HISTORY_REFRESH_CONTEXT", HISTORY_REFRESH_MAX_OUTPUT = 1e6;
84651
85164
  var init_history_refresh_service = __esm(() => {
84652
85165
  init_src();
84653
85166
  init_src2();
84654
85167
  init_split_launch_command();
85168
+ init_execution_policy();
84655
85169
  init_job_exclusion_guard();
84656
85170
  init_scheduler_custom_job_service();
84657
85171
  });
@@ -84918,6 +85432,23 @@ function assertPiImporterSafe(input) {
84918
85432
  }
84919
85433
  throw new UnsafeHistoryImporterError(`refusing full pi history import \u2014 installed @gobing-ai/ts-llm-jsonl-importer version ` + `${input.importerVersion ?? "unknown"} destroys history_tool_call.args_raw on pi imports ` + `(todo-tool arguments collapse to their first line; bash commands are lost). ` + `Minimum safe version: ${MIN_SAFE_PI_BASH_IMPORTER_VERSION}. ` + `Remedy: upgrade or relink @gobing-ai/ts-libs to a release containing ts-libs commit 96762d5, ` + `or preview the import with --dry-run.`, input.importerVersion ?? "unknown");
84920
85434
  }
85435
+ async function raceSourceImport(importPromise, source, timeoutMs) {
85436
+ const abort = new AbortController;
85437
+ const timer = setTimeout(() => abort.abort(new Error(`source '${source}' exceeded ${timeoutMs}ms timeout`)), timeoutMs);
85438
+ const timeoutPromise = new Promise((_, reject) => {
85439
+ abort.signal.addEventListener("abort", () => reject(abort.signal.reason));
85440
+ });
85441
+ try {
85442
+ await Promise.race([importPromise, timeoutPromise]);
85443
+ return "completed";
85444
+ } catch (e) {
85445
+ if (abort.signal.aborted)
85446
+ return "timeout";
85447
+ throw e;
85448
+ } finally {
85449
+ clearTimeout(timer);
85450
+ }
85451
+ }
84921
85452
  async function buildRefreshCoverage(db2, selector, fanOut) {
84922
85453
  const statusBySource = new Map(fanOut.entries.map((e) => [e.source, e.status]));
84923
85454
  const refreshed = FULL_FIDELITY_SOURCES.filter((s3) => statusBySource.has(s3) && statusBySource.get(s3) !== "failed");
@@ -85176,7 +85707,7 @@ class HistoryService {
85176
85707
  dryRun: opts.dryRun === true,
85177
85708
  sources
85178
85709
  });
85179
- const timeoutMs = opts.sourceTimeout ?? DEFAULT_SOURCE_TIMEOUT_MS;
85710
+ const timeoutMs = opts.sourceTimeout !== undefined ? opts.sourceTimeout : DEFAULT_SOURCE_TIMEOUT_MS;
85180
85711
  const entries = [];
85181
85712
  const warnings = [];
85182
85713
  const attribution2 = emptyAttributionSummary();
@@ -85281,16 +85812,11 @@ class HistoryService {
85281
85812
  mode: opts.mode ?? (opts.file !== undefined && opts.file.length > 0 ? "force-file" : "incremental"),
85282
85813
  dryRun: opts.dryRun
85283
85814
  });
85284
- const abort = new AbortController;
85285
- const timer = setTimeout(() => abort.abort(new Error(`source '${source}' exceeded ${timeoutMs}ms timeout`)), timeoutMs);
85286
- const timeoutPromise = new Promise((_, reject) => {
85287
- abort.signal.addEventListener("abort", () => reject(abort.signal.reason));
85288
- });
85289
85815
  let result;
85290
- try {
85291
- result = await Promise.race([importPromise, timeoutPromise]);
85292
- } catch (e) {
85293
- if (abort.signal.aborted) {
85816
+ if (timeoutMs === null) {
85817
+ result = await importPromise;
85818
+ } else {
85819
+ if (await raceSourceImport(importPromise, source, timeoutMs) === "timeout") {
85294
85820
  const elapsedMs = Date.now() - attemptStartedAt;
85295
85821
  const detail = `source '${source}' exceeded its ${timeoutMs}ms budget ` + `(elapsed ${elapsedMs}ms); import attempt was abandoned mid-flight and may still hold the write lock until the process exits`;
85296
85822
  sourceWarnings.push({ code: "source-timeout", source, detail });
@@ -85313,9 +85839,7 @@ class HistoryService {
85313
85839
  sourceAttribution: null
85314
85840
  };
85315
85841
  }
85316
- throw e;
85317
- } finally {
85318
- clearTimeout(timer);
85842
+ result = await importPromise;
85319
85843
  }
85320
85844
  const hasDegradedInput = result.parseErrors.length > 0 || result.validationErrors.length > 0;
85321
85845
  const status = result.scannedFiles === 0 ? DEFERRED_SOURCES.includes(source) ? "deferred" : "empty" : hasDegradedInput ? "degraded" : "ok";
@@ -87745,10 +88269,10 @@ class HttpRequestActionRunner {
87745
88269
  if (!Object.hasOwn(ALLOWED_METHODS, method)) {
87746
88270
  return { ok: false, error: `http.request: unsupported method: ${method}` };
87747
88271
  }
87748
- if (timeoutMs <= 0 || timeoutMs > MAX_TIMEOUT_MS2) {
88272
+ if (timeoutMs <= 0 || timeoutMs > MAX_TIMEOUT_MS4) {
87749
88273
  return {
87750
88274
  ok: false,
87751
- error: `http.request: timeoutMs must be 1\u2013${MAX_TIMEOUT_MS2}, got ${timeoutMs}`
88275
+ error: `http.request: timeoutMs must be 1\u2013${MAX_TIMEOUT_MS4}, got ${timeoutMs}`
87752
88276
  };
87753
88277
  }
87754
88278
  if (maxResponseBytes <= 0) {
@@ -87857,7 +88381,7 @@ function asNumberArray(value) {
87857
88381
  return [];
87858
88382
  return value.filter((v) => typeof v === "number" && !Number.isNaN(v));
87859
88383
  }
87860
- var KIND10 = "http.request", ALLOWED_METHODS, DEFAULT_TIMEOUT_MS3 = 30000, MAX_TIMEOUT_MS2 = 120000, DEFAULT_MAX_RESPONSE_BYTES = 1048576, HEADER_NAME_RE, HEADER_VALUE_RE;
88384
+ var KIND10 = "http.request", ALLOWED_METHODS, DEFAULT_TIMEOUT_MS3 = 30000, MAX_TIMEOUT_MS4 = 120000, DEFAULT_MAX_RESPONSE_BYTES = 1048576, HEADER_NAME_RE, HEADER_VALUE_RE;
87861
88385
  var init_http_request = __esm(() => {
87862
88386
  ALLOWED_METHODS = {
87863
88387
  GET: true,
@@ -88436,7 +88960,7 @@ class RunArtifactActionRunner {
88436
88960
  };
88437
88961
  }
88438
88962
  const db2 = await this.getDb();
88439
- const runRow = await new RunDao(db2).traceRowById(context4.runId);
88963
+ const runRow = await new RunDao(db2).traceRowById(context4.runId) ?? undefined;
88440
88964
  if (runRow === undefined) {
88441
88965
  return {
88442
88966
  ok: false,
@@ -90129,7 +90653,7 @@ var init_workflow_service = __esm(() => {
90129
90653
  });
90130
90654
 
90131
90655
  // ../../packages/app/src/services/inline-run-setup.ts
90132
- import { resolve as resolve11 } from "path";
90656
+ import { join as join24, resolve as resolve11 } from "path";
90133
90657
  function parseIdentityMetadata(raw) {
90134
90658
  if (raw.trim() === "")
90135
90659
  return {};
@@ -90143,9 +90667,7 @@ function parseIdentityMetadata(raw) {
90143
90667
  }
90144
90668
  }
90145
90669
  async function openInlineRunProjectDb(workdir) {
90146
- const { join: join24, resolve: resolve12 } = await import("path");
90147
- const { mkdirSync: mkdirSync7 } = await import("fs");
90148
- const url2 = join24(resolve12(workdir), ".spur", "spur.db");
90670
+ const url2 = join24(resolve11(workdir), ".spur", "spur.db");
90149
90671
  mkdirSync7(join24(url2, ".."), { recursive: true });
90150
90672
  const adapter = await createMigratedDb({ url: url2 });
90151
90673
  return { adapter, close: () => adapter.close() };
@@ -90238,9 +90760,12 @@ async function createOrAttachInlineRun(input) {
90238
90760
  status: "running",
90239
90761
  started_at: new Date().toISOString(),
90240
90762
  completed_at: null,
90241
- metadata_json: "{}"
90763
+ metadata_json: JSON.stringify({
90764
+ definitionDigest: digest,
90765
+ workflowVersion: version3,
90766
+ definitionSource: source
90767
+ })
90242
90768
  });
90243
- await runDao.stampRunIdentity(runId, digest, version3, source);
90244
90769
  return {
90245
90770
  ok: true,
90246
90771
  attached: false,
@@ -90254,11 +90779,13 @@ async function createOrAttachInlineRun(input) {
90254
90779
  status: "running"
90255
90780
  };
90256
90781
  }
90257
- var init_inline_run_setup = __esm(() => {
90782
+ var mkdirSync7;
90783
+ var init_inline_run_setup = __esm(async () => {
90258
90784
  init_src2();
90259
90785
  init_dist8();
90260
90786
  init_workflow_resolver();
90261
90787
  init_workflow_service();
90788
+ ({ mkdirSync: mkdirSync7 } = await import("fs"));
90262
90789
  });
90263
90790
 
90264
90791
  // ../../packages/app/src/services/job-worker-service.ts
@@ -90955,17 +91482,17 @@ var init_process_inventory_service = __esm(() => {
90955
91482
  });
90956
91483
 
90957
91484
  // ../../packages/app/src/services/project-registry.ts
90958
- import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync9, realpathSync as realpathSync5, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
91485
+ import { existsSync as existsSync6, mkdirSync as mkdirSync8, readFileSync as readFileSync9, realpathSync as realpathSync5, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
90959
91486
  import { connect, createServer } from "net";
90960
91487
  import { homedir as homedir7 } from "os";
90961
- import { dirname as dirname17, join as join24, resolve as resolve12 } from "path";
91488
+ import { dirname as dirname17, join as join25, resolve as resolve12 } from "path";
90962
91489
  function normalizeProjectPath(pathInput) {
90963
91490
  const trimmed = pathInput.trim();
90964
91491
  let expanded = trimmed;
90965
91492
  if (trimmed === "~") {
90966
91493
  expanded = homedir7();
90967
91494
  } else if (trimmed.startsWith("~/")) {
90968
- expanded = join24(homedir7(), trimmed.slice(2));
91495
+ expanded = join25(homedir7(), trimmed.slice(2));
90969
91496
  } else {
90970
91497
  expanded = resolve12(trimmed);
90971
91498
  }
@@ -91062,7 +91589,7 @@ class ProjectRegistry {
91062
91589
  const lockParent = dirname17(this.lockDir);
91063
91590
  if (!existsSync6(lockParent)) {
91064
91591
  try {
91065
- mkdirSync7(lockParent, { recursive: true });
91592
+ mkdirSync8(lockParent, { recursive: true });
91066
91593
  } catch (err) {
91067
91594
  const code = err?.code;
91068
91595
  if (code === "EPERM" || code === "EACCES") {
@@ -91075,7 +91602,7 @@ class ProjectRegistry {
91075
91602
  let acquired = false;
91076
91603
  for (let i2 = 0;i2 < maxTries; i2++) {
91077
91604
  try {
91078
- mkdirSync7(this.lockDir);
91605
+ mkdirSync8(this.lockDir);
91079
91606
  acquired = true;
91080
91607
  break;
91081
91608
  } catch (err) {
@@ -91089,7 +91616,7 @@ class ProjectRegistry {
91089
91616
  if (!acquired) {
91090
91617
  try {
91091
91618
  rmSync5(this.lockDir, { recursive: true, force: true });
91092
- mkdirSync7(this.lockDir);
91619
+ mkdirSync8(this.lockDir);
91093
91620
  acquired = true;
91094
91621
  } catch {
91095
91622
  throw new Error(`Failed to acquire lock for project registry: ${this.lockDir}`);
@@ -91120,7 +91647,7 @@ class ProjectRegistry {
91120
91647
  writeRaw(data) {
91121
91648
  const parentDir2 = dirname17(this.filePath);
91122
91649
  if (!existsSync6(parentDir2)) {
91123
- mkdirSync7(parentDir2, { recursive: true });
91650
+ mkdirSync8(parentDir2, { recursive: true });
91124
91651
  }
91125
91652
  const tmpFile = `${this.filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
91126
91653
  const content = JSON.stringify(data, null, 2);
@@ -91405,7 +91932,7 @@ var init_project_start = __esm(() => {
91405
91932
 
91406
91933
  // ../../packages/app/src/services/rule-service.ts
91407
91934
  import { homedir as homedir8 } from "os";
91408
- import { delimiter, join as join25, relative as relative4, resolve as resolve14 } from "path";
91935
+ import { delimiter, join as join26, relative as relative4, resolve as resolve14 } from "path";
91409
91936
 
91410
91937
  class RuleService {
91411
91938
  context;
@@ -91600,13 +92127,13 @@ ${ruleIds.join(`
91600
92127
  const hasGlobalOverride = globalOverride !== undefined && globalOverride.length > 0;
91601
92128
  layers.push({
91602
92129
  id: "global",
91603
- path: hasGlobalOverride ? resolve14(cwd, globalOverride) : join25(homedir8(), GLOBAL_RULES_DIR),
92130
+ path: hasGlobalOverride ? resolve14(cwd, globalOverride) : join26(homedir8(), GLOBAL_RULES_DIR),
91604
92131
  priority: 10
91605
92132
  });
91606
92133
  if (opts.includeBundled && !hasGlobalOverride) {
91607
92134
  const bundledConfig = bundledConfigRoot();
91608
92135
  if (bundledConfig !== null) {
91609
- layers.push({ id: "bundled-config", path: join25(bundledConfig, "rules"), priority: 15 });
92136
+ layers.push({ id: "bundled-config", path: join26(bundledConfig, "rules"), priority: 15 });
91610
92137
  }
91611
92138
  const bundled = await bundledRulesRoot();
91612
92139
  if (bundled !== null)
@@ -91819,7 +92346,7 @@ ${ruleIds.join(`
91819
92346
  const { fs: fs3 } = this.context;
91820
92347
  for (const root of await this.ruleRoots()) {
91821
92348
  for (const ext of ["yaml", "yml", "json"]) {
91822
- if (await fs3.exists(join25(root, `${name}.${ext}`)))
92349
+ if (await fs3.exists(join26(root, `${name}.${ext}`)))
91823
92350
  return true;
91824
92351
  }
91825
92352
  }
@@ -91855,7 +92382,7 @@ ${ruleIds.join(`
91855
92382
  for (const layer of await this.existingRuleSourceLayers()) {
91856
92383
  const entries = await this.context.fs.readDir(layer.path);
91857
92384
  const named = entries.map((entry) => ({ entry, name: entry.match(/^([\w-]+)\.(?:ya?ml|json)$/i)?.[1] ?? "" })).filter(({ name }) => name.length > 0);
91858
- const stats = await Promise.all(named.map(({ entry }) => this.context.fs.stat(join25(layer.path, entry))));
92385
+ const stats = await Promise.all(named.map(({ entry }) => this.context.fs.stat(join26(layer.path, entry))));
91859
92386
  named.forEach(({ name }, i2) => {
91860
92387
  if (stats[i2]?.isFile())
91861
92388
  candidates.add(name);
@@ -91877,7 +92404,7 @@ ${ruleIds.join(`
91877
92404
  for (const layer of layers) {
91878
92405
  for (const file2 of await this.listRuleFilesInLayer(layer.path)) {
91879
92406
  if (!merged.has(file2))
91880
- merged.set(file2, { absolutePath: join25(layer.path, file2), source: layer.id });
92407
+ merged.set(file2, { absolutePath: join26(layer.path, file2), source: layer.id });
91881
92408
  }
91882
92409
  }
91883
92410
  const files = [];
@@ -91945,7 +92472,7 @@ ${ruleIds.join(`
91945
92472
  for (const entry of entries.sort()) {
91946
92473
  if (entry === "presets")
91947
92474
  continue;
91948
- const stat2 = await this.context.fs.stat(join25(root, entry));
92475
+ const stat2 = await this.context.fs.stat(join26(root, entry));
91949
92476
  if (stat2?.isDirectory())
91950
92477
  dirs.push(entry);
91951
92478
  }
@@ -91953,12 +92480,12 @@ ${ruleIds.join(`
91953
92480
  }
91954
92481
  async listRuleFiles(root, relativeDir) {
91955
92482
  const { fs: fs3 } = this.context;
91956
- const dir = join25(root, relativeDir);
92483
+ const dir = join26(root, relativeDir);
91957
92484
  const entries = await fs3.readDir(dir);
91958
92485
  const files = [];
91959
92486
  for (const entry of entries.sort()) {
91960
- const relativePath2 = relativeDir.length === 0 ? entry : join25(relativeDir, entry);
91961
- const absolutePath = join25(root, relativePath2);
92487
+ const relativePath2 = relativeDir.length === 0 ? entry : join26(relativeDir, entry);
92488
+ const absolutePath = join26(root, relativePath2);
91962
92489
  const stat2 = await fs3.stat(absolutePath);
91963
92490
  if (stat2?.isDirectory()) {
91964
92491
  files.push(...await this.listRuleFiles(root, relativePath2));
@@ -92092,8 +92619,8 @@ var init_rule_service = __esm(() => {
92092
92619
  init_dist10();
92093
92620
  init_agent_execution();
92094
92621
  init_system_event_envelope();
92095
- LOCAL_RULES_DIR = join25(".spur", "rules");
92096
- GLOBAL_RULES_DIR = join25(".config", "spur", "rules");
92622
+ LOCAL_RULES_DIR = join26(".spur", "rules");
92623
+ GLOBAL_RULES_DIR = join26(".config", "spur", "rules");
92097
92624
  SEVERITY_RANK2 = {
92098
92625
  info: 0,
92099
92626
  warning: 1,
@@ -93228,7 +93755,7 @@ var init_task_size_precheck = __esm(() => {
93228
93755
  });
93229
93756
 
93230
93757
  // ../../packages/app/src/services/task-service.ts
93231
- import { dirname as dirname19, isAbsolute as isAbsolute7, join as join26, relative as relative5 } from "path";
93758
+ import { dirname as dirname19, isAbsolute as isAbsolute7, join as join27, relative as relative5 } from "path";
93232
93759
  function renderRosterTable(rows) {
93233
93760
  const header = `| WBS | Sub-task | Status |
93234
93761
  | --- | -------- | ------ |`;
@@ -93719,7 +94246,7 @@ ${templateBackground}`;
93719
94246
  if (!featureId2 || featureId2.length === 0)
93720
94247
  return [];
93721
94248
  const tasksDir = dirname19(taskFilePath);
93722
- const featuresDir = join26(tasksDir, "..", "features");
94249
+ const featuresDir = join27(tasksDir, "..", "features");
93723
94250
  const featurePath = await (async () => {
93724
94251
  try {
93725
94252
  for (const name of await this.ctx.fs.readDir(featuresDir)) {
@@ -94503,7 +95030,7 @@ var init_task_verdict = __esm(() => {
94503
95030
  });
94504
95031
 
94505
95032
  // ../../packages/app/src/services/team-service.ts
94506
- import { join as join27, resolve as resolve15 } from "path";
95033
+ import { join as join28, resolve as resolve15 } from "path";
94507
95034
 
94508
95035
  class TeamService {
94509
95036
  ctx;
@@ -94511,7 +95038,7 @@ class TeamService {
94511
95038
  orchestratorPromise;
94512
95039
  constructor(ctx) {
94513
95040
  this.ctx = ctx;
94514
- this.configDir = join27(ctx.cwd, ".spur", "agents");
95041
+ this.configDir = join28(ctx.cwd, ".spur", "agents");
94515
95042
  }
94516
95043
  async sendMessage(fromId, toId, body, replyTo) {
94517
95044
  validateAgentId(toId);
@@ -94983,7 +95510,7 @@ class TeamService {
94983
95510
  async resolveTaskFile(taskId) {
94984
95511
  const fs3 = this.ctx.fs;
94985
95512
  const { foldersConfig } = await resolvePlanningFolders(fs3);
94986
- const dirs = [...new Set([foldersConfig.active_folder, ...Object.keys(foldersConfig.folders)])].map((dir) => join27(this.ctx.cwd, dir));
95513
+ const dirs = [...new Set([foldersConfig.active_folder, ...Object.keys(foldersConfig.folders)])].map((dir) => join28(this.ctx.cwd, dir));
94987
95514
  return await TaskLocator.forDirs(fs3, dirs).findPathByWbs(taskId);
94988
95515
  }
94989
95516
  }
@@ -95020,7 +95547,7 @@ var init_team_service = __esm(() => {
95020
95547
 
95021
95548
  // ../../packages/app/src/services/token-ledger-service.ts
95022
95549
  import { closeSync as closeSync3, existsSync as existsSync8, fstatSync, openSync as openSync3, readSync } from "fs";
95023
- import { join as join28 } from "path";
95550
+ import { join as join29 } from "path";
95024
95551
  function isSparseToolActivity(events2) {
95025
95552
  return events2.length === 0 || !events2.some((e) => TOOL_ACTIVITY_TYPES.has(e.type));
95026
95553
  }
@@ -95121,7 +95648,7 @@ class TokenLedgerService {
95121
95648
  ledgerPath;
95122
95649
  chunkSize;
95123
95650
  constructor(options) {
95124
- this.ledgerPath = options.ledgerPath ?? join28(options.cwd, TOKEN_LEDGER_RELATIVE_PATH);
95651
+ this.ledgerPath = options.ledgerPath ?? join29(options.cwd, TOKEN_LEDGER_RELATIVE_PATH);
95125
95652
  this.chunkSize = options.chunkSize ?? DEFAULT_CHUNK;
95126
95653
  }
95127
95654
  get path() {
@@ -95162,7 +95689,7 @@ class TokenLedgerService {
95162
95689
  var TOOL_ACTIVITY_TYPES, TOKEN_LEDGER_DEFAULT_LIMIT = 200, TOKEN_LEDGER_MAX_LIMIT = 1000, TOKEN_LEDGER_RELATIVE_PATH, DEFAULT_CHUNK;
95163
95690
  var init_token_ledger_service = __esm(() => {
95164
95691
  TOOL_ACTIVITY_TYPES = new Set(["read", "write", "bash", "grep", "glob"]);
95165
- TOKEN_LEDGER_RELATIVE_PATH = join28(".spur", "context", "token-ledger.jsonl");
95692
+ TOKEN_LEDGER_RELATIVE_PATH = join29(".spur", "context", "token-ledger.jsonl");
95166
95693
  DEFAULT_CHUNK = 64 * 1024;
95167
95694
  });
95168
95695
 
@@ -96098,7 +96625,7 @@ var init_progress_follow = __esm(() => {
96098
96625
  });
96099
96626
 
96100
96627
  // ../../packages/app/src/workflow/trace-writer.ts
96101
- import { dirname as dirname20, join as join29 } from "path";
96628
+ import { dirname as dirname20, join as join30 } from "path";
96102
96629
 
96103
96630
  class WorkflowTraceWriter {
96104
96631
  path;
@@ -96106,7 +96633,7 @@ class WorkflowTraceWriter {
96106
96633
  pending = Promise.resolve();
96107
96634
  constructor(cwd, runId) {
96108
96635
  const safeRunId = runId.replace(/[^A-Za-z0-9._-]/g, "_");
96109
- this.path = join29(cwd, ".spur", "workflow", `${safeRunId}.jsonl`);
96636
+ this.path = join30(cwd, ".spur", "workflow", `${safeRunId}.jsonl`);
96110
96637
  }
96111
96638
  attach(bus) {
96112
96639
  bus.on("workflow.run.started", (event) => this.enqueue("workflow.run.started", event));
@@ -96141,6 +96668,69 @@ var init_trace_writer = __esm(() => {
96141
96668
  init_dist5();
96142
96669
  });
96143
96670
 
96671
+ // ../../packages/app/src/workflow/workflow-inventory.ts
96672
+ function parseWorkflowInventory(json3) {
96673
+ if (typeof json3 !== "object" || json3 === null) {
96674
+ return { ok: false, error: "workflow inventory: projection is not an object" };
96675
+ }
96676
+ const obj = json3;
96677
+ const name = typeof obj.name === "string" ? obj.name : "";
96678
+ const kind = typeof obj.kind === "string" ? obj.kind : "";
96679
+ const format2 = typeof obj.format === "string" ? obj.format : "";
96680
+ const version3 = typeof obj.version === "string" || typeof obj.version === "number" ? String(obj.version) : "";
96681
+ const definitionDigest = typeof obj.definitionDigest === "string" ? obj.definitionDigest : "";
96682
+ if (name === "")
96683
+ return { ok: false, error: "workflow inventory: missing name" };
96684
+ if (kind === "")
96685
+ return { ok: false, error: "workflow inventory: missing kind" };
96686
+ if (definitionDigest === "")
96687
+ return { ok: false, error: "workflow inventory: missing definitionDigest" };
96688
+ if (!Array.isArray(obj.steps) || obj.steps.length === 0) {
96689
+ return { ok: false, error: "workflow inventory: no declared steps" };
96690
+ }
96691
+ const steps = [];
96692
+ for (const raw of obj.steps) {
96693
+ if (typeof raw !== "object" || raw === null) {
96694
+ return { ok: false, error: "workflow inventory: a step is not an object" };
96695
+ }
96696
+ const s3 = raw;
96697
+ if (typeof s3.id !== "string" || s3.id === "") {
96698
+ return { ok: false, error: "workflow inventory: a step is missing its id" };
96699
+ }
96700
+ steps.push({
96701
+ id: s3.id,
96702
+ initial: s3.initial === true,
96703
+ terminal: s3.terminal === true,
96704
+ failure: s3.failure === true,
96705
+ pause: s3.pause === true,
96706
+ loopBack: s3.loopBack === true,
96707
+ conditional: s3.conditional === true,
96708
+ ...typeof s3.nodeType === "string" ? { nodeType: s3.nodeType } : {},
96709
+ ...typeof s3.description === "string" ? { description: s3.description } : {}
96710
+ });
96711
+ }
96712
+ return {
96713
+ ok: true,
96714
+ inventory: { name, kind, format: format2, version: version3, definitionDigest, steps }
96715
+ };
96716
+ }
96717
+ function assertInventoryIdentity(inventory, expectedDigest) {
96718
+ if (expectedDigest === "") {
96719
+ return { ok: false, error: "workflow inventory: no expected definition digest to bind against" };
96720
+ }
96721
+ if (inventory.definitionDigest !== expectedDigest) {
96722
+ return {
96723
+ ok: false,
96724
+ error: `workflow inventory: identity drift \u2014 projected ${inventory.definitionDigest} \u2260 execution ${expectedDigest}`
96725
+ };
96726
+ }
96727
+ return { ok: true };
96728
+ }
96729
+ function renderEventTrace(events2) {
96730
+ return events2.map((e) => `${e.at} ${e.kind}${e.detail !== undefined && e.detail !== "" ? ` \u2014 ${e.detail}` : ""}`).join(`
96731
+ `);
96732
+ }
96733
+
96144
96734
  // ../../packages/app/src/index.ts
96145
96735
  var exports_src2 = {};
96146
96736
  __export(exports_src2, {
@@ -96177,7 +96767,7 @@ __export(exports_src2, {
96177
96767
  resolveRetentionQuotas: () => resolveRetentionQuotas,
96178
96768
  resolvePlanningFolders: () => resolvePlanningFolders,
96179
96769
  resolveOutputLogConfig: () => resolveOutputLogConfig,
96180
- resolveKillGraceMs: () => resolveKillGraceMs,
96770
+ resolveKillGraceMs: () => resolveKillGraceMs3,
96181
96771
  resolveHistoryRefreshTimeoutMs: () => resolveHistoryRefreshTimeoutMs,
96182
96772
  resolveFogRange: () => resolveFogRange,
96183
96773
  resolveConfiguredTaskDirs: () => resolveConfiguredTaskDirs,
@@ -96190,6 +96780,7 @@ __export(exports_src2, {
96190
96780
  renderSolutionFromDiff: () => renderSolutionFromDiff,
96191
96781
  renderRunPlan: () => renderRunPlan,
96192
96782
  renderReview: () => renderReview,
96783
+ renderEventTrace: () => renderEventTrace,
96193
96784
  renderEscalationMarkdown: () => renderEscalationMarkdown,
96194
96785
  renderActionHeartbeat: () => renderActionHeartbeat,
96195
96786
  releaseExclusiveJob: () => releaseExclusiveJob,
@@ -96214,7 +96805,9 @@ __export(exports_src2, {
96214
96805
  prepareBatchTaskReady: () => prepareBatchTaskReady,
96215
96806
  portBindingAvailable: () => portBindingAvailable,
96216
96807
  permissionFailureEvidence: () => permissionFailureEvidence,
96808
+ parseWorkflowInventory: () => parseWorkflowInventory,
96217
96809
  parseVerdict: () => parseVerdict,
96810
+ parseTimeoutInput: () => parseTimeoutInput,
96218
96811
  parseSteeringPolicy: () => parseSteeringPolicy,
96219
96812
  parsePsOutput: () => parsePsOutput,
96220
96813
  parseLedgerLine: () => parseLedgerLine,
@@ -96224,6 +96817,7 @@ __export(exports_src2, {
96224
96817
  openInlineRunProjectDb: () => openInlineRunProjectDb,
96225
96818
  normalizeSystemEventPayload: () => normalizeSystemEventPayload,
96226
96819
  normalizeProjectPath: () => normalizeProjectPath,
96820
+ normalizeLegacyTimeoutMs: () => normalizeLegacyTimeoutMs,
96227
96821
  looksLikeOpaqueId: () => looksLikeOpaqueId,
96228
96822
  isSystemEventEnvelopeV2: () => isSystemEventEnvelopeV2,
96229
96823
  isRecordAuthoredReview: () => isRecordAuthoredReview,
@@ -96294,6 +96888,8 @@ __export(exports_src2, {
96294
96888
  attributeSessions: () => attributeSessions,
96295
96889
  attachAgentQuotaUpdates: () => attachAgentQuotaUpdates,
96296
96890
  assertPiImporterSafe: () => assertPiImporterSafe,
96891
+ assertInventoryIdentity: () => assertInventoryIdentity,
96892
+ assertCanonicalTimeoutMs: () => assertCanonicalTimeoutMs,
96297
96893
  anchorQualify: () => anchorQualify,
96298
96894
  aggregateBatchVerdicts: () => aggregateBatchVerdicts,
96299
96895
  acquireExclusiveJob: () => acquireExclusiveJob,
@@ -96363,6 +96959,7 @@ __export(exports_src2, {
96363
96959
  ObservableWorkflowAdapter: () => ObservableWorkflowAdapter,
96364
96960
  MockHistoryBoardService: () => MockHistoryBoardService,
96365
96961
  MIN_SAFE_PI_BASH_IMPORTER_VERSION: () => MIN_SAFE_PI_BASH_IMPORTER_VERSION,
96962
+ MAX_TIMEOUT_INPUT_MS: () => MAX_TIMEOUT_INPUT_MS,
96366
96963
  MAX_QUOTA_DRAIN_ATTEMPTS_PER_ACTIVATION: () => MAX_QUOTA_DRAIN_ATTEMPTS_PER_ACTIVATION,
96367
96964
  LockTimeoutError: () => LockTimeoutError,
96368
96965
  LiveHistoryBoardService: () => LiveHistoryBoardService,
@@ -96372,6 +96969,7 @@ __export(exports_src2, {
96372
96969
  HitlInputActionRunner: () => HitlInputActionRunner,
96373
96970
  HitlConfirmActionRunner: () => HitlConfirmActionRunner,
96374
96971
  HistoryService: () => HistoryService,
96972
+ HISTORY_SOURCE_TIMEOUT_ENV: () => HISTORY_SOURCE_TIMEOUT_ENV,
96375
96973
  HISTORY_REFRESH_JOB: () => HISTORY_REFRESH_JOB,
96376
96974
  HISTORY_REFRESH_CONTEXT_ENV: () => HISTORY_REFRESH_CONTEXT_ENV,
96377
96975
  HISTORY_PRODUCER_EXCLUSIVE_KEY: () => HISTORY_PRODUCER_EXCLUSIVE_KEY,
@@ -96394,6 +96992,7 @@ __export(exports_src2, {
96394
96992
  DependencyMutationError: () => DependencyMutationError,
96395
96993
  DEFAULT_SYSTEM_EVENT_RETENTION_QUOTA: () => DEFAULT_SYSTEM_EVENT_RETENTION_QUOTA,
96396
96994
  DEFAULT_STALL_MS: () => DEFAULT_STALL_MS,
96995
+ DEFAULT_SOURCE_TIMEOUT_MS: () => DEFAULT_SOURCE_TIMEOUT_MS,
96397
96996
  DEFAULT_RUN_LOG_MAX_BYTES: () => DEFAULT_RUN_LOG_MAX_BYTES,
96398
96997
  DEFAULT_READY_PREPARE_TIMEOUT_MS: () => DEFAULT_READY_PREPARE_TIMEOUT_MS,
96399
96998
  DEFAULT_FEATURE_MATRIX: () => DEFAULT_FEATURE_MATRIX,
@@ -96423,6 +97022,7 @@ var init_src3 = __esm(async () => {
96423
97022
  init_done_transition_guard();
96424
97023
  init_event_bridge();
96425
97024
  init_event_names();
97025
+ init_execution_policy();
96426
97026
  init_failure_classification();
96427
97027
  init_feature_check();
96428
97028
  init_feature_service();
@@ -96432,7 +97032,6 @@ var init_src3 = __esm(async () => {
96432
97032
  init_history_board_service();
96433
97033
  init_history_refresh_service();
96434
97034
  init_history_service();
96435
- init_inline_run_setup();
96436
97035
  init_job_exclusion_guard();
96437
97036
  init_occupant_wait();
96438
97037
  init_pipeline_run_link();
@@ -96481,8 +97080,12 @@ var init_src3 = __esm(async () => {
96481
97080
  init_progress_projection();
96482
97081
  init_proof_input_fingerprint();
96483
97082
  init_steering();
97083
+ init_step_reporter();
96484
97084
  init_trace_writer();
96485
- await init_idea_handoff_cli();
97085
+ await __promiseAll([
97086
+ init_inline_run_setup(),
97087
+ init_idea_handoff_cli()
97088
+ ]);
96486
97089
  });
96487
97090
 
96488
97091
  // ../../node_modules/.bun/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
@@ -96568,19 +97171,19 @@ var {
96568
97171
  // src/index.ts
96569
97172
  init_loader();
96570
97173
 
96571
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/application-node.js
97174
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/application-node.js
96572
97175
  init_dist4();
96573
97176
  init_dist5();
96574
97177
  import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
96575
97178
  import { dirname as dirname6 } from "path";
96576
97179
 
96577
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/application/index.js
97180
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/application/index.js
96578
97181
  init_default_observers();
96579
97182
  init_event_bus();
96580
97183
  init_file_observer();
96581
97184
  init_logger3();
96582
97185
 
96583
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/scheduler/noop.js
97186
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/scheduler/noop.js
96584
97187
  class NoopSchedulerAdapter {
96585
97188
  constructor() {}
96586
97189
  register(_cron, _action) {}
@@ -96588,7 +97191,7 @@ class NoopSchedulerAdapter {
96588
97191
  async stop() {}
96589
97192
  }
96590
97193
 
96591
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/scheduler/factory.js
97194
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/scheduler/factory.js
96592
97195
  function initScheduler(adapter, cronEntries) {
96593
97196
  const resolved = adapter ?? new NoopSchedulerAdapter;
96594
97197
  if (cronEntries) {
@@ -96599,7 +97202,7 @@ function initScheduler(adapter, cronEntries) {
96599
97202
  return resolved;
96600
97203
  }
96601
97204
 
96602
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/application/plugins/builtins.js
97205
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/application/plugins/builtins.js
96603
97206
  init_logger3();
96604
97207
  init_metrics();
96605
97208
  init_sdk();
@@ -96692,7 +97295,7 @@ function dbPlugin(db2) {
96692
97295
  };
96693
97296
  }
96694
97297
 
96695
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/application/plugins/host.js
97298
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/application/plugins/host.js
96696
97299
  init_logger3();
96697
97300
 
96698
97301
  class PluginHost {
@@ -96780,7 +97383,7 @@ class PluginHost {
96780
97383
  }
96781
97384
  }
96782
97385
 
96783
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/application/index.js
97386
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/application/index.js
96784
97387
  async function performShutdown(state, reason) {
96785
97388
  if (state.stopped)
96786
97389
  return;
@@ -96811,7 +97414,8 @@ async function runApplication(options) {
96811
97414
  const schedulerConfig = {
96812
97415
  enabled: schedOpts?.enabled ?? false,
96813
97416
  autoStart: schedOpts?.autoStart ?? true,
96814
- jobs: schedOpts?.jobs ?? []
97417
+ jobs: schedOpts?.jobs ?? [],
97418
+ timeoutMs: resolveExecutionTimeoutMs("bootstrap.scheduler", schedOpts?.timeoutMs)
96815
97419
  };
96816
97420
  const eventsEnabled = options.config?.events?.enabled ?? true;
96817
97421
  const eventsLifecycle = options.config?.events?.lifecycle ?? true;
@@ -96891,8 +97495,7 @@ async function runApplication(options) {
96891
97495
  throw error51;
96892
97496
  }
96893
97497
  }
96894
-
96895
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/scheduler/cron.js
97498
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/scheduler/cron.js
96896
97499
  var MAX_SCAN_MINUTES = 8 * 366 * 24 * 60;
96897
97500
  var DAYS_OF_WEEK = 7;
96898
97501
  function parseField(raw, min, max) {
@@ -97006,7 +97609,8 @@ function nextCronTime(expr, nowMs) {
97006
97609
  throw new RangeError(`unsupported cron expression "${expr.source}": no matching time within 8 years`);
97007
97610
  }
97008
97611
 
97009
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/scheduler/node.js
97612
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/scheduler/node.js
97613
+ init_logger3();
97010
97614
  init_metrics();
97011
97615
  var MAX_TIMEOUT = 2147483647;
97012
97616
  function parseInterval(cron) {
@@ -97031,6 +97635,7 @@ function parseInterval(cron) {
97031
97635
  class NodeSchedulerAdapter {
97032
97636
  entries = [];
97033
97637
  drainTimeoutMs;
97638
+ defaultTimeoutMs;
97034
97639
  now;
97035
97640
  running = false;
97036
97641
  inflight = new Set;
@@ -97040,23 +97645,25 @@ class NodeSchedulerAdapter {
97040
97645
  throw new RangeError(`NodeSchedulerAdapter drainTimeoutMs must be a non-negative finite number; received ${drainTimeoutMs}`);
97041
97646
  }
97042
97647
  this.drainTimeoutMs = drainTimeoutMs ?? 30000;
97648
+ this.defaultTimeoutMs = resolveExecutionTimeoutMs("NodeSchedulerAdapter", config4.timeoutMs ?? undefined);
97043
97649
  this.now = now ?? (() => Date.now());
97044
97650
  }
97045
- register(cron, action) {
97046
- const entry = this.parseEntry(cron, action);
97651
+ register(cron, action, options) {
97652
+ const entry = this.parseEntry(cron, action, options);
97047
97653
  this.entries.push(entry);
97048
97654
  if (this.running) {
97049
97655
  this.startEntry(entry);
97050
97656
  }
97051
97657
  }
97052
- parseEntry(cron, action) {
97658
+ parseEntry(cron, action, options) {
97659
+ const timeoutMs = resolveExecutionTimeoutMs(`scheduler entry "${cron}"`, options?.timeoutMs, this.defaultTimeoutMs);
97053
97660
  const intervalMs = parseInterval(cron);
97054
97661
  if (intervalMs !== undefined) {
97055
- return { kind: "interval", cron, action, intervalMs };
97662
+ return { kind: "interval", cron, action, intervalMs, timeoutMs };
97056
97663
  }
97057
97664
  const expr = parseCronExpression(cron);
97058
97665
  const target = nextCronTime(expr, this.now()).getTime();
97059
- return { kind: "cron", cron, action, expr, target };
97666
+ return { kind: "cron", cron, action, expr, target, timeoutMs };
97060
97667
  }
97061
97668
  async start() {
97062
97669
  if (this.running)
@@ -97138,7 +97745,17 @@ class NodeSchedulerAdapter {
97138
97745
  const startMs = performance.now();
97139
97746
  getSchedulerJobExecutedTotal().add(1, { cron: entry.cron });
97140
97747
  try {
97141
- await entry.action();
97748
+ const outcome = await runWithExecutionDeadline(entry.action, { timeoutMs: entry.timeoutMs });
97749
+ if (outcome.timedOut) {
97750
+ getSchedulerJobFailedTotal().add(1, { cron: entry.cron });
97751
+ getLogger2("scheduler").warn("scheduled tick exceeded its execution deadline", {
97752
+ cron: entry.cron,
97753
+ timeoutMs: entry.timeoutMs,
97754
+ elapsedMs: Math.round(outcome.elapsedMs)
97755
+ });
97756
+ } else if (outcome.outcome === "error") {
97757
+ getSchedulerJobFailedTotal().add(1, { cron: entry.cron });
97758
+ }
97142
97759
  } catch {
97143
97760
  getSchedulerJobFailedTotal().add(1, { cron: entry.cron });
97144
97761
  } finally {
@@ -97146,7 +97763,7 @@ class NodeSchedulerAdapter {
97146
97763
  }
97147
97764
  }
97148
97765
  }
97149
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
97766
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
97150
97767
  var import_api14 = __toESM(require_src(), 1);
97151
97768
 
97152
97769
  // ../../node_modules/.bun/@opentelemetry+exporter-metrics-otlp-http@0.218.0+e40b0dfdd726a224/node_modules/@opentelemetry/exporter-metrics-otlp-http/build/esm/OTLPMetricExporterBase.js
@@ -100162,7 +100779,7 @@ class OTLPTraceExporter extends import_otlp_exporter_base2.OTLPExporterBase {
100162
100779
  }), JsonTraceSerializer));
100163
100780
  }
100164
100781
  }
100165
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
100782
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
100166
100783
  var import_resources2 = __toESM(require_src4(), 1);
100167
100784
  var import_sdk_trace_node = __toESM(require_src8(), 1);
100168
100785
  var import_semantic_conventions = __toESM(require_src2(), 1);
@@ -100213,14 +100830,14 @@ async function shutdownNodeTelemetry() {
100213
100830
  await Promise.all(pending);
100214
100831
  }
100215
100832
 
100216
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.57+33b96fa7d4032676/node_modules/@gobing-ai/ts-infra/dist/application-node.js
100833
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.60+ebc5bc10f06d9cb0/node_modules/@gobing-ai/ts-infra/dist/application-node.js
100217
100834
  class ConfigValidationError extends Error {
100218
100835
  constructor(message) {
100219
100836
  super(message);
100220
100837
  this.name = "ConfigValidationError";
100221
100838
  }
100222
100839
  }
100223
- var MAX_TIMEOUT_MS = 2147483647;
100840
+ var MAX_TIMEOUT_MS3 = 2147483647;
100224
100841
  function validateAppConfig(validator, raw, section, filePath) {
100225
100842
  if (typeof validator === "object" && "safeParse" in validator) {
100226
100843
  const result = validator.safeParse(raw);
@@ -100241,7 +100858,14 @@ function validateAppConfig(validator, raw, section, filePath) {
100241
100858
  }
100242
100859
  throw new ConfigValidationError(`Unsupported validator shape for section "${section}"`);
100243
100860
  }
100244
- var MAX_INTERVAL_MINUTES = Math.floor(MAX_TIMEOUT_MS / 60000);
100861
+ function resolveBootstrapSchedulerTimeout(value) {
100862
+ try {
100863
+ return resolveExecutionTimeoutMs("bootstrap.scheduler", value);
100864
+ } catch {
100865
+ throw new ConfigValidationError(`bootstrap.scheduler.timeoutMs must be a positive integer or null; received ${String(value)}`);
100866
+ }
100867
+ }
100868
+ var MAX_INTERVAL_MINUTES = Math.floor(MAX_TIMEOUT_MS3 / 60000);
100245
100869
  function normalizeSchedulerJobs(raw) {
100246
100870
  if (raw === undefined || raw === null)
100247
100871
  return [];
@@ -100259,6 +100883,14 @@ function normalizeSchedulerJobs(raw) {
100259
100883
  const command = typeof entry.command === "string" ? entry.command.trim() : "";
100260
100884
  const cron = typeof entry.cron === "string" ? entry.cron.trim() : "";
100261
100885
  const interval = entry.intervalMinutes;
100886
+ const rawTimeout = entry.timeoutMs;
100887
+ let timeoutMs;
100888
+ if (rawTimeout !== undefined) {
100889
+ if (rawTimeout !== null && (typeof rawTimeout !== "number" || !Number.isInteger(rawTimeout) || rawTimeout <= 0)) {
100890
+ throw new ConfigValidationError(`bootstrap.scheduler.jobs.${index2}.timeoutMs must be a positive integer or null`);
100891
+ }
100892
+ timeoutMs = rawTimeout;
100893
+ }
100262
100894
  if (name === "") {
100263
100895
  throw new ConfigValidationError(`bootstrap.scheduler.jobs.${index2}.name must be a non-empty string`);
100264
100896
  }
@@ -100278,7 +100910,7 @@ function normalizeSchedulerJobs(raw) {
100278
100910
  if (typeof interval !== "number" || !Number.isInteger(interval) || interval < 1 || interval > MAX_INTERVAL_MINUTES) {
100279
100911
  throw new ConfigValidationError(`bootstrap.scheduler.jobs.${index2}.intervalMinutes must be an integer in 1..${MAX_INTERVAL_MINUTES}`);
100280
100912
  }
100281
- jobs.push({ name, command, intervalMinutes: interval });
100913
+ jobs.push({ name, command, intervalMinutes: interval, timeoutMs });
100282
100914
  } else {
100283
100915
  if (cron === "") {
100284
100916
  throw new ConfigValidationError(`bootstrap.scheduler.jobs.${index2}.cron must be a non-empty string`);
@@ -100289,7 +100921,7 @@ function normalizeSchedulerJobs(raw) {
100289
100921
  const detail = error51 instanceof Error ? error51.message : String(error51);
100290
100922
  throw new ConfigValidationError(`bootstrap.scheduler.jobs.${index2}.cron: ${detail}`);
100291
100923
  }
100292
- jobs.push({ name, command, cron });
100924
+ jobs.push({ name, command, cron, timeoutMs });
100293
100925
  }
100294
100926
  });
100295
100927
  return jobs;
@@ -100358,10 +100990,11 @@ async function runNodeApplication(options) {
100358
100990
  const schedulerConfig = {
100359
100991
  enabled: schedulerOpts.enabled === true,
100360
100992
  autoStart: schedulerOpts.autoStart,
100361
- jobs: normalizeSchedulerJobs(schedulerOpts.jobs)
100993
+ jobs: normalizeSchedulerJobs(schedulerOpts.jobs),
100994
+ timeoutMs: resolveBootstrapSchedulerTimeout(schedulerOpts.timeoutMs)
100362
100995
  };
100363
100996
  if (schedulerConfig.enabled) {
100364
- schedulerConfig.adapter = schedulerOpts.adapter ?? new NodeSchedulerAdapter;
100997
+ schedulerConfig.adapter = schedulerOpts.adapter ?? new NodeSchedulerAdapter({ timeoutMs: schedulerConfig.timeoutMs });
100365
100998
  if (schedulerOpts.entries) {
100366
100999
  schedulerConfig.entries = schedulerOpts.entries;
100367
101000
  }
@@ -104719,7 +105352,7 @@ function waitFail(context4, options, code, message) {
104719
105352
  // src/release-ops.ts
104720
105353
  init_dist5();
104721
105354
  import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
104722
- import { join as join30 } from "path";
105355
+ import { join as join31 } from "path";
104723
105356
  var SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/;
104724
105357
  function releaseTag(config4, version3) {
104725
105358
  return `${config4.packageName}${config4.tagVersionSeparator}${version3}`;
@@ -104765,7 +105398,7 @@ async function readJson(path9) {
104765
105398
  function rootWorkspaceGlobs(repoRoot) {
104766
105399
  let root;
104767
105400
  try {
104768
- root = JSON.parse(readFileSync10(join30(repoRoot, "package.json"), "utf8"));
105401
+ root = JSON.parse(readFileSync10(join31(repoRoot, "package.json"), "utf8"));
104769
105402
  } catch {
104770
105403
  return [];
104771
105404
  }
@@ -104782,11 +105415,11 @@ function workspaceDirs(repoRoot) {
104782
105415
  if (!glob.endsWith("/*"))
104783
105416
  continue;
104784
105417
  const parent = glob.slice(0, -2);
104785
- const parentAbs = join30(repoRoot, parent);
105418
+ const parentAbs = join31(repoRoot, parent);
104786
105419
  if (!existsSync10(parentAbs))
104787
105420
  continue;
104788
105421
  for (const entry of readdirSync7(parentAbs, { withFileTypes: true })) {
104789
- if (entry.isDirectory() && existsSync10(join30(parentAbs, entry.name, "package.json"))) {
105422
+ if (entry.isDirectory() && existsSync10(join31(parentAbs, entry.name, "package.json"))) {
104790
105423
  dirs.push(`${parent}/${entry.name}`);
104791
105424
  }
104792
105425
  }
@@ -104794,14 +105427,14 @@ function workspaceDirs(repoRoot) {
104794
105427
  return dirs;
104795
105428
  }
104796
105429
  async function releaseContext(repoRoot) {
104797
- const rootManifest = await readJson(join30(repoRoot, "package.json"));
105430
+ const rootManifest = await readJson(join31(repoRoot, "package.json"));
104798
105431
  if (rootManifest === null) {
104799
105432
  throw new Error(`no package.json found at ${repoRoot} \u2014 builder operates on a package workspace root.`);
104800
105433
  }
104801
105434
  const rootName = typeof rootManifest.name === "string" ? rootManifest.name : "root";
104802
105435
  const workspaces2 = [];
104803
105436
  for (const dir of workspaceDirs(repoRoot)) {
104804
- const manifest = await readJson(join30(repoRoot, dir, "package.json"));
105437
+ const manifest = await readJson(join31(repoRoot, dir, "package.json"));
104805
105438
  if (manifest === null)
104806
105439
  continue;
104807
105440
  workspaces2.push({
@@ -104814,7 +105447,7 @@ async function releaseContext(repoRoot) {
104814
105447
  const shortName = (name) => name.split("/").pop() ?? name;
104815
105448
  const packages = new Map;
104816
105449
  for (const ws of workspaces2) {
104817
- const versionSourceFile = existsSync10(join30(repoRoot, ws.dir, "src", "config.ts")) ? `${ws.dir}/src/config.ts` : undefined;
105450
+ const versionSourceFile = existsSync10(join31(repoRoot, ws.dir, "src", "config.ts")) ? `${ws.dir}/src/config.ts` : undefined;
104818
105451
  packages.set(shortName(ws.name), {
104819
105452
  packageDir: ws.dir,
104820
105453
  packageName: ws.name,
@@ -104849,7 +105482,7 @@ async function updateWorkspacePins(ctx, pkgName, oldVersion, newVersion, output2
104849
105482
  const changed = [];
104850
105483
  for (const dir of workspaceDirs(ctx.repoRoot)) {
104851
105484
  const relPath = `${dir}/package.json`;
104852
- const manifest = await readJson(join30(ctx.repoRoot, relPath));
105485
+ const manifest = await readJson(join31(ctx.repoRoot, relPath));
104853
105486
  if (manifest === null)
104854
105487
  continue;
104855
105488
  let dirty = false;
@@ -104866,7 +105499,7 @@ async function updateWorkspacePins(ctx, pkgName, oldVersion, newVersion, output2
104866
105499
  }
104867
105500
  }
104868
105501
  if (dirty) {
104869
- await Bun.write(join30(ctx.repoRoot, relPath), `${JSON.stringify(manifest, null, 4)}
105502
+ await Bun.write(join31(ctx.repoRoot, relPath), `${JSON.stringify(manifest, null, 4)}
104870
105503
  `);
104871
105504
  output2.write(` \u21B3 ${relPath}: ${pkgName} workspace pin ${oldVersion} \u2192 ${newVersion}`);
104872
105505
  changed.push(relPath);
@@ -104875,7 +105508,7 @@ async function updateWorkspacePins(ctx, pkgName, oldVersion, newVersion, output2
104875
105508
  return changed;
104876
105509
  }
104877
105510
  async function updateVersionSourceFile(ctx, filePath, previous, next, output2) {
104878
- const absPath = join30(ctx.repoRoot, filePath);
105511
+ const absPath = join31(ctx.repoRoot, filePath);
104879
105512
  const content = await Bun.file(absPath).text();
104880
105513
  const updated = content.replace(/(binaryVersion:\s*['"])\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?(['"])/, `$1${next}$2`);
104881
105514
  if (updated === content) {
@@ -104887,7 +105520,7 @@ async function updateVersionSourceFile(ctx, filePath, previous, next, output2) {
104887
105520
  return true;
104888
105521
  }
104889
105522
  async function syncMarketplaceAndPlugins(ctx, version3, staged, output2) {
104890
- const marketplacePath = join30(ctx.repoRoot, ".claude-plugin", "marketplace.json");
105523
+ const marketplacePath = join31(ctx.repoRoot, ".claude-plugin", "marketplace.json");
104891
105524
  const marketplaceFile = Bun.file(marketplacePath);
104892
105525
  if (!await marketplaceFile.exists())
104893
105526
  return;
@@ -104917,7 +105550,7 @@ async function syncMarketplaceAndPlugins(ctx, version3, staged, output2) {
104917
105550
  output2.write(`Bumped marketplace plugins to ${version3}`);
104918
105551
  }
104919
105552
  for (const entry of plugins) {
104920
- const pluginJsonPath = join30(ctx.repoRoot, entry.source, "plugin.json");
105553
+ const pluginJsonPath = join31(ctx.repoRoot, entry.source, "plugin.json");
104921
105554
  const pluginJson = await readJson(pluginJsonPath);
104922
105555
  if (pluginJson === null) {
104923
105556
  output2.write(` \u26A0 plugin.json not found at ${entry.source}/plugin.json \u2014 skipping`);
@@ -104966,7 +105599,7 @@ async function bumpVersion(ctx, config4, version3, options, output2) {
104966
105599
  if (await npmViewVersion(ctx.repoRoot, config4.packageName, version3)) {
104967
105600
  throw new Error(`${config4.packageName}@${version3} is already published on npm. Use a new version.`);
104968
105601
  }
104969
- const manifestPath = join30(ctx.repoRoot, config4.packageDir, "package.json");
105602
+ const manifestPath = join31(ctx.repoRoot, config4.packageDir, "package.json");
104970
105603
  const manifest = await readJson(manifestPath);
104971
105604
  if (manifest === null)
104972
105605
  throw new Error(`missing or malformed manifest at ${config4.packageDir}/package.json`);
@@ -104983,7 +105616,7 @@ async function bumpVersion(ctx, config4, version3, options, output2) {
104983
105616
  }
104984
105617
  staged.push(...await updateWorkspacePins(ctx, config4.packageName, previous, version3, output2));
104985
105618
  await syncMarketplaceAndPlugins(ctx, version3, staged, output2);
104986
- const lockPath = join30(ctx.repoRoot, "bun.lock");
105619
+ const lockPath = join31(ctx.repoRoot, "bun.lock");
104987
105620
  if (existsSync10(lockPath) && Bun.file(lockPath).size > 0)
104988
105621
  staged.push("bun.lock");
104989
105622
  await git2(ctx.repoRoot, ["add", ...staged]);
@@ -105039,7 +105672,7 @@ async function bumpAll(ctx, version3, options, output2) {
105039
105672
  }
105040
105673
  const staged = [];
105041
105674
  for (const config4 of configs) {
105042
- const manifestPath = join30(ctx.repoRoot, config4.packageDir, "package.json");
105675
+ const manifestPath = join31(ctx.repoRoot, config4.packageDir, "package.json");
105043
105676
  const manifest = await readJson(manifestPath);
105044
105677
  if (manifest === null) {
105045
105678
  throw new Error(`missing or malformed manifest at ${config4.packageDir}/package.json`);
@@ -105058,7 +105691,7 @@ async function bumpAll(ctx, version3, options, output2) {
105058
105691
  staged.push(...await updateWorkspacePins(ctx, config4.packageName, previous, version3, output2));
105059
105692
  }
105060
105693
  await syncMarketplaceAndPlugins(ctx, version3, staged, output2);
105061
- const lockPath = join30(ctx.repoRoot, "bun.lock");
105694
+ const lockPath = join31(ctx.repoRoot, "bun.lock");
105062
105695
  if (existsSync10(lockPath) && Bun.file(lockPath).size > 0)
105063
105696
  staged.push("bun.lock");
105064
105697
  await git2(ctx.repoRoot, ["add", ...staged]);
@@ -105721,13 +106354,18 @@ import { createRequire } from "module";
105721
106354
  var CLI_CONFIG = {
105722
106355
  binaryName: "spur",
105723
106356
  binaryLabel: "spur",
105724
- binaryVersion: "0.3.77",
106357
+ binaryVersion: "0.3.78",
105725
106358
  configDir: ".spur",
105726
106359
  configFile: ".spur/config.yaml",
105727
106360
  databaseFile: ".spur/spur.db"
105728
106361
  };
105729
106362
 
105730
106363
  // src/commands/history.ts
106364
+ function resolveCliSourceTimeout(explicit, env) {
106365
+ if (explicit !== undefined)
106366
+ return parseTimeoutInput(explicit);
106367
+ return normalizeLegacyTimeoutMs(env[HISTORY_SOURCE_TIMEOUT_ENV], DEFAULT_SOURCE_TIMEOUT_MS);
106368
+ }
105731
106369
  async function resolveImportProvenance(fs3) {
105732
106370
  const binary = process.argv[1] ?? "unknown";
105733
106371
  let importer = "unknown";
@@ -105768,7 +106406,7 @@ function registerHistoryCommand(program2, context4) {
105768
106406
  cwd: context4.cwd
105769
106407
  });
105770
106408
  };
105771
- noun.command("import").description("Import agent conversation JSONL. `--source all` fans out across all sources with " + "per-source failure isolation (task 0470). A single source is the n=1 case of " + "the same contract \u2014 never two import paths.").option(...SHARED_OPTIONS.sourceHistory, "all").option(...SHARED_OPTIONS.fileHistoryJsonl).option("--root <path>", "Scan a history root").option(...SHARED_OPTIONS.modeHistory).option(...SHARED_OPTIONS.dryRunHistoryScan).option("--source-timeout <ms>", "Per-source timeout in milliseconds (default 600000 = 10 min)", "600000").option(...SHARED_OPTIONS.jsonSupported).option(...SHARED_OPTIONS.jsonEnvelope).action(async (options) => {
106409
+ noun.command("import").description("Import agent conversation JSONL. `--source all` fans out across all sources with " + "per-source failure isolation (task 0470). A single source is the n=1 case of " + "the same contract \u2014 never two import paths.").option(...SHARED_OPTIONS.sourceHistory, "all").option(...SHARED_OPTIONS.fileHistoryJsonl).option("--root <path>", "Scan a history root").option(...SHARED_OPTIONS.modeHistory).option(...SHARED_OPTIONS.dryRunHistoryScan).option("--source-timeout <ms|none>", `Per-source timeout in milliseconds or 'none' (default ${DEFAULT_SOURCE_TIMEOUT_MS} = 10 min)`).option(...SHARED_OPTIONS.jsonSupported).option(...SHARED_OPTIONS.jsonEnvelope).action(async (options) => {
105772
106410
  const source = options.source ?? "all";
105773
106411
  if (options.file && source === "all") {
105774
106412
  context4.output.write(options.json ? toEnvelopeJson({ status: "error", message: '--file requires a single --source, not "all".' }, {
@@ -105782,7 +106420,18 @@ function registerHistoryCommand(program2, context4) {
105782
106420
  context4.setExitCode(1);
105783
106421
  return;
105784
106422
  }
105785
- const sourceTimeout = Number.parseInt(options.sourceTimeout ?? "600000", 10) || 600000;
106423
+ let sourceTimeout;
106424
+ try {
106425
+ sourceTimeout = resolveCliSourceTimeout(options.sourceTimeout, process.env);
106426
+ } catch (e) {
106427
+ const timeoutMsg = `spur history import: ${e instanceof Error ? e.message : String(e)}`;
106428
+ context4.output.write(options.json ? toEnvelopeJson({ status: "error", message: timeoutMsg }, {
106429
+ enveloped: options.jsonEnvelope,
106430
+ error: { code: "INTERNAL_ERROR", message: timeoutMsg, details: { cliCode: "usage" } }
106431
+ }) : timeoutMsg);
106432
+ context4.setExitCode(1);
106433
+ return;
106434
+ }
105786
106435
  const mode = options.mode ?? (options.file ? "force-file" : "incremental");
105787
106436
  if (mode !== "full" && mode !== "incremental" && mode !== "force-file") {
105788
106437
  const modeMsg = `Invalid history import mode "${mode}". Expected one of: full, incremental, force-file`;
@@ -105924,9 +106573,20 @@ ${formatFanOutResult(fanOut)}`);
105924
106573
  context4.setExitCode(1);
105925
106574
  }
105926
106575
  });
105927
- noun.command("daily").description("Run-once daily pipeline: import-all (fan-out, per-source isolation) \u2192 analyze \u2192 write " + "artifact \u2192 prune reports older than 90 days (task 0470 R6). Import uses checkpoint " + "resume, so a missed night self-heals on the next run with no gap and no double-count.").option("--since <iso>", "Inclusive lower bound on message timestamp for the report (not the import)").option("--until <iso>", "Inclusive upper bound on message timestamp for the report").option("--source-timeout <ms>", "Per-source import timeout in milliseconds (default 600000 = 10 min)", "600000").option("--root <path>", "History root override (default: per-source platform dir)").option(...SHARED_OPTIONS.jsonDaily).option(...SHARED_OPTIONS.jsonEnvelope).option("--mode <name>", "Render the artifact as a .md sidecar in this mode after analyze (e.g. forensics)").action(async (options) => {
106576
+ noun.command("daily").description("Run-once daily pipeline: import-all (fan-out, per-source isolation) \u2192 analyze \u2192 write " + "artifact \u2192 prune reports older than 90 days (task 0470 R6). Import uses checkpoint " + "resume, so a missed night self-heals on the next run with no gap and no double-count.").option("--since <iso>", "Inclusive lower bound on message timestamp for the report (not the import)").option("--until <iso>", "Inclusive upper bound on message timestamp for the report").option("--source-timeout <ms|none>", `Per-source import timeout in milliseconds or 'none' (default ${DEFAULT_SOURCE_TIMEOUT_MS} = 10 min)`).option("--root <path>", "History root override (default: per-source platform dir)").option(...SHARED_OPTIONS.jsonDaily).option(...SHARED_OPTIONS.jsonEnvelope).option("--mode <name>", "Render the artifact as a .md sidecar in this mode after analyze (e.g. forensics)").action(async (options) => {
106577
+ let sourceTimeout;
106578
+ try {
106579
+ sourceTimeout = resolveCliSourceTimeout(options.sourceTimeout, process.env);
106580
+ } catch (e) {
106581
+ const timeoutMsg = `spur history daily: ${e instanceof Error ? e.message : String(e)}`;
106582
+ context4.output.write(options.json ? toEnvelopeJson({ error: timeoutMsg }, {
106583
+ enveloped: options.jsonEnvelope,
106584
+ error: { code: "INTERNAL_ERROR", message: timeoutMsg }
106585
+ }) : timeoutMsg);
106586
+ context4.setExitCode(1);
106587
+ return;
106588
+ }
105928
106589
  const svc = await makeService2();
105929
- const sourceTimeout = Number.parseInt(options.sourceTimeout ?? "600000", 10) || 600000;
105930
106590
  let refresh;
105931
106591
  try {
105932
106592
  refresh = parseHistoryRefreshContext(process.env[HISTORY_REFRESH_CONTEXT_ENV]);
@@ -106106,7 +106766,7 @@ init_loader();
106106
106766
  init_src2();
106107
106767
  init_dist10();
106108
106768
  import { homedir as homedir9 } from "os";
106109
- import { join as join31, resolve as resolve17 } from "path";
106769
+ import { join as join32, resolve as resolve17 } from "path";
106110
106770
 
106111
106771
  // src/config/scaffold-manifest.ts
106112
106772
  var SCAFFOLD_MANIFEST = [
@@ -106135,8 +106795,8 @@ var SCAFFOLD_MANIFEST = [
106135
106795
  ];
106136
106796
 
106137
106797
  // src/commands/init.ts
106138
- var GLOBAL_CONFIG_DIR = join31(".config", "spur");
106139
- var GLOBAL_RULES_DIR2 = join31(GLOBAL_CONFIG_DIR, "rules");
106798
+ var GLOBAL_CONFIG_DIR = join32(".config", "spur");
106799
+ var GLOBAL_RULES_DIR2 = join32(GLOBAL_CONFIG_DIR, "rules");
106140
106800
  var GLOBAL_CONFIG_EXAMPLE = BUNDLED_GLOBAL_CONFIG;
106141
106801
  var GLOBAL_CONFIG_FILE2 = "config.yaml";
106142
106802
  var INDEXED_CONTEXT_MARKER = "## Indexed context";
@@ -106167,7 +106827,7 @@ If \`.spur/context/\` is absent, proceed normally. Never block work on its absen
106167
106827
  `;
106168
106828
  function globalRulesRoot(context4) {
106169
106829
  const override = context4.env.SPUR_GLOBAL_RULES_DIR;
106170
- return override !== undefined && override.length > 0 ? resolve17(context4.cwd, override) : join31(homedir9(), GLOBAL_RULES_DIR2);
106830
+ return override !== undefined && override.length > 0 ? resolve17(context4.cwd, override) : join32(homedir9(), GLOBAL_RULES_DIR2);
106171
106831
  }
106172
106832
  async function writeIfNew(context4, path9, content, force, result) {
106173
106833
  if (!force && await context4.fs.exists(path9)) {
@@ -106184,18 +106844,18 @@ async function seedGlobalRules(context4) {
106184
106844
  const target = globalRulesRoot(context4);
106185
106845
  let written = 0;
106186
106846
  for (const relPath of await listBundledRuleFiles()) {
106187
- const destination = join31(target, relPath);
106847
+ const destination = join32(target, relPath);
106188
106848
  if (await context4.fs.exists(destination))
106189
106849
  continue;
106190
- await context4.fs.ensureDir(join31(target, ...relPath.split("/").slice(0, -1)));
106191
- await context4.fs.writeFile(destination, await context4.fs.readFile(join31(source, relPath)));
106850
+ await context4.fs.ensureDir(join32(target, ...relPath.split("/").slice(0, -1)));
106851
+ await context4.fs.writeFile(destination, await context4.fs.readFile(join32(source, relPath)));
106192
106852
  written += 1;
106193
106853
  }
106194
106854
  return written;
106195
106855
  }
106196
106856
  function resolveGlobalConfigDir(context4) {
106197
106857
  const globalOverride = context4.env.SPUR_GLOBAL_RULES_DIR;
106198
- return globalOverride !== undefined && globalOverride.length > 0 ? resolve17(context4.cwd, globalOverride) : join31(homedir9(), GLOBAL_CONFIG_DIR);
106858
+ return globalOverride !== undefined && globalOverride.length > 0 ? resolve17(context4.cwd, globalOverride) : join32(homedir9(), GLOBAL_CONFIG_DIR);
106199
106859
  }
106200
106860
  async function seedGlobalConfig(context4) {
106201
106861
  const source = bundledConfigRoot();
@@ -106206,15 +106866,15 @@ async function seedGlobalConfig(context4) {
106206
106866
  for (const relPath of listBundledConfigFiles()) {
106207
106867
  if (relPath === GLOBAL_CONFIG_EXAMPLE)
106208
106868
  continue;
106209
- const destination = join31(target, relPath);
106869
+ const destination = join32(target, relPath);
106210
106870
  if (await context4.fs.exists(destination))
106211
106871
  continue;
106212
- await context4.fs.ensureDir(join31(target, ...relPath.split("/").slice(0, -1)));
106213
- await context4.fs.writeFile(destination, await context4.fs.readFile(join31(source, relPath)));
106872
+ await context4.fs.ensureDir(join32(target, ...relPath.split("/").slice(0, -1)));
106873
+ await context4.fs.writeFile(destination, await context4.fs.readFile(join32(source, relPath)));
106214
106874
  written += 1;
106215
106875
  }
106216
- const examplePath = join31(source, GLOBAL_CONFIG_EXAMPLE);
106217
- const globalConfigPath = join31(target, GLOBAL_CONFIG_FILE2);
106876
+ const examplePath = join32(source, GLOBAL_CONFIG_EXAMPLE);
106877
+ const globalConfigPath = join32(target, GLOBAL_CONFIG_FILE2);
106218
106878
  if (await context4.fs.exists(examplePath) && !await context4.fs.exists(globalConfigPath)) {
106219
106879
  await context4.fs.ensureDir(target);
106220
106880
  await context4.fs.writeFile(globalConfigPath, await context4.fs.readFile(examplePath));
@@ -106229,10 +106889,10 @@ function registerInitCommand(program2, context4, options = {}) {
106229
106889
  const minimal = options2.minimal === true;
106230
106890
  const adoptGlobal = options2.adoptGlobalConfig === true;
106231
106891
  const projectName = options2.name ?? "default";
106232
- const configPath = join31(context4.cwd, CLI_CONFIG.configFile);
106892
+ const configPath = join32(context4.cwd, CLI_CONFIG.configFile);
106233
106893
  const result = { created: [], skipped: [] };
106234
106894
  const globalConfigDir = resolveGlobalConfigDir(context4);
106235
- const globalConfigPath = join31(globalConfigDir, GLOBAL_CONFIG_FILE2);
106895
+ const globalConfigPath = join32(globalConfigDir, GLOBAL_CONFIG_FILE2);
106236
106896
  const globalConfigExists = await context4.fs.exists(globalConfigPath);
106237
106897
  let misplacedKeys = [];
106238
106898
  if (globalConfigExists) {
@@ -106245,20 +106905,20 @@ function registerInitCommand(program2, context4, options = {}) {
106245
106905
  const configRoot = bundledConfigRoot();
106246
106906
  if (configRoot !== null && !minimal) {
106247
106907
  for (const relPath of listBundledProjectSeedFiles()) {
106248
- const sourcePath = join31(configRoot, relPath);
106908
+ const sourcePath = join32(configRoot, relPath);
106249
106909
  if (!await context4.fs.exists(sourcePath))
106250
106910
  continue;
106251
- const targetPath = join31(context4.cwd, CLI_CONFIG.configDir, relPath);
106252
- await context4.fs.ensureDir(join31(targetPath, ".."));
106911
+ const targetPath = join32(context4.cwd, CLI_CONFIG.configDir, relPath);
106912
+ await context4.fs.ensureDir(join32(targetPath, ".."));
106253
106913
  await writeIfNew(context4, targetPath, await context4.fs.readFile(sourcePath), false, result);
106254
106914
  }
106255
106915
  for (const entry of SCAFFOLD_MANIFEST) {
106256
- const sourcePath = join31(configRoot, entry.source);
106916
+ const sourcePath = join32(configRoot, entry.source);
106257
106917
  if (!await context4.fs.exists(sourcePath))
106258
106918
  continue;
106259
- const baseDir = entry.root === true ? context4.cwd : join31(context4.cwd, CLI_CONFIG.configDir);
106260
- const targetPath = join31(baseDir, entry.target);
106261
- await context4.fs.ensureDir(join31(targetPath, ".."));
106919
+ const baseDir = entry.root === true ? context4.cwd : join32(context4.cwd, CLI_CONFIG.configDir);
106920
+ const targetPath = join32(baseDir, entry.target);
106921
+ await context4.fs.ensureDir(join32(targetPath, ".."));
106262
106922
  const entryForce = false;
106263
106923
  let body = await context4.fs.readFile(sourcePath);
106264
106924
  if (entry.target === "AGENTS.md") {
@@ -106275,7 +106935,7 @@ function registerInitCommand(program2, context4, options = {}) {
106275
106935
  const backupPath = `${globalConfigPath}.bak-${new Date().toISOString().replace(/[:.]/g, "-")}`;
106276
106936
  await context4.fs.writeFile(backupPath, await context4.fs.readFile(globalConfigPath));
106277
106937
  const bundledRoot = bundledConfigRoot();
106278
- const examplePath = bundledRoot !== null ? join31(bundledRoot, GLOBAL_CONFIG_EXAMPLE) : null;
106938
+ const examplePath = bundledRoot !== null ? join32(bundledRoot, GLOBAL_CONFIG_EXAMPLE) : null;
106279
106939
  if (examplePath !== null && await context4.fs.exists(examplePath)) {
106280
106940
  await context4.fs.writeFile(globalConfigPath, await context4.fs.readFile(examplePath));
106281
106941
  adoptedGlobal = true;
@@ -106345,13 +107005,13 @@ function registerInitCommand(program2, context4, options = {}) {
106345
107005
  ].join(`
106346
107006
  `)}
106347
107007
  `;
106348
- await context4.fs.ensureDir(join31(context4.cwd, CLI_CONFIG.configDir));
107008
+ await context4.fs.ensureDir(join32(context4.cwd, CLI_CONFIG.configDir));
106349
107009
  await context4.fs.writeFile(configPath, configYaml);
106350
107010
  result.created.push(configPath);
106351
- const agentsDir = join31(context4.cwd, CLI_CONFIG.configDir, "agents");
107011
+ const agentsDir = join32(context4.cwd, CLI_CONFIG.configDir, "agents");
106352
107012
  await context4.fs.ensureDir(agentsDir);
106353
- await writeIfNew(context4, join31(agentsDir, ".gitkeep"), "", force, result);
106354
- const gitignorePath = join31(context4.cwd, ".gitignore");
107013
+ await writeIfNew(context4, join32(agentsDir, ".gitkeep"), "", force, result);
107014
+ const gitignorePath = join32(context4.cwd, ".gitignore");
106355
107015
  const contextEntry = ".spur/context/";
106356
107016
  if (await context4.fs.exists(gitignorePath)) {
106357
107017
  const existing = await context4.fs.readFile(gitignorePath);
@@ -106371,20 +107031,20 @@ ${contextEntry}
106371
107031
  const configRoot = bundledConfigRoot();
106372
107032
  if (configRoot !== null) {
106373
107033
  for (const relPath of listBundledProjectSeedFiles()) {
106374
- const sourcePath = join31(configRoot, relPath);
107034
+ const sourcePath = join32(configRoot, relPath);
106375
107035
  if (!await context4.fs.exists(sourcePath))
106376
107036
  continue;
106377
- const targetPath = join31(context4.cwd, CLI_CONFIG.configDir, relPath);
106378
- await context4.fs.ensureDir(join31(targetPath, ".."));
107037
+ const targetPath = join32(context4.cwd, CLI_CONFIG.configDir, relPath);
107038
+ await context4.fs.ensureDir(join32(targetPath, ".."));
106379
107039
  await writeIfNew(context4, targetPath, await context4.fs.readFile(sourcePath), force, result);
106380
107040
  }
106381
107041
  for (const entry of SCAFFOLD_MANIFEST) {
106382
- const sourcePath = join31(configRoot, entry.source);
107042
+ const sourcePath = join32(configRoot, entry.source);
106383
107043
  if (!await context4.fs.exists(sourcePath))
106384
107044
  continue;
106385
- const baseDir = entry.root === true ? context4.cwd : join31(context4.cwd, CLI_CONFIG.configDir);
106386
- const targetPath = join31(baseDir, entry.target);
106387
- await context4.fs.ensureDir(join31(targetPath, ".."));
107045
+ const baseDir = entry.root === true ? context4.cwd : join32(context4.cwd, CLI_CONFIG.configDir);
107046
+ const targetPath = join32(baseDir, entry.target);
107047
+ await context4.fs.ensureDir(join32(targetPath, ".."));
106388
107048
  const entryForce = entry.preserve === true ? false : force;
106389
107049
  let body = await context4.fs.readFile(sourcePath);
106390
107050
  if (entry.target === "AGENTS.md") {
@@ -106397,7 +107057,7 @@ ${contextEntry}
106397
107057
  }
106398
107058
  }
106399
107059
  }
106400
- const agentsMdPath = join31(context4.cwd, "AGENTS.md");
107060
+ const agentsMdPath = join32(context4.cwd, "AGENTS.md");
106401
107061
  if (await context4.fs.exists(agentsMdPath)) {
106402
107062
  const existing = await context4.fs.readFile(agentsMdPath);
106403
107063
  if (!existing.includes(INDEXED_CONTEXT_MARKER)) {
@@ -106438,11 +107098,11 @@ ${contextEntry}
106438
107098
  // src/commands/maintain.ts
106439
107099
  init_src();
106440
107100
  init_src2();
106441
- import { join as join32 } from "path";
107101
+ import { join as join33 } from "path";
106442
107102
  function registerMaintainCommand(program2, context4, options = {}) {
106443
107103
  program2.command("maintain", { hidden: options.hidden === true }).summary("run database maintenance (optimize, WAL checkpoint truncation, optional VACUUM)").description("Run database maintenance: PRAGMA optimize, WAL checkpoint truncation; optionally VACUUM compaction.").option("--vacuum", "Run VACUUM defragmentation and page compaction", false).option(...SHARED_OPTIONS.jsonSupported).option(...SHARED_OPTIONS.jsonEnvelope).action(async (options2) => {
106444
107104
  const db2 = await context4.getDb();
106445
- const dbPath = context4.env.DATABASE_URL ?? join32(context4.cwd, DEFAULT_DATABASE_URL);
107105
+ const dbPath = context4.env.DATABASE_URL ?? join33(context4.cwd, DEFAULT_DATABASE_URL);
106446
107106
  const result = await maintainDatabase(db2, {
106447
107107
  vacuum: options2.vacuum === true,
106448
107108
  dbPath: dbPath.startsWith(":memory:") ? undefined : dbPath
@@ -106842,10 +107502,10 @@ async function waitForPendingDrain(agentService, teamService, pin, timeoutMs, si
106842
107502
 
106843
107503
  // src/commands/migrate.ts
106844
107504
  init_src2();
106845
- import { join as join33 } from "path";
107505
+ import { join as join34 } from "path";
106846
107506
  function registerMigrateCommand(program2, context4, options = {}) {
106847
107507
  program2.command("migrate", { hidden: options.hidden === true }).summary("apply CLI-owned schema migrations").option(...SHARED_OPTIONS.json).option(...SHARED_OPTIONS.jsonEnvelope).action(async (options2) => {
106848
- const migrations = await loadSqlMigrations(join33(context4.cwd, "drizzle")).catch(() => {
107508
+ const migrations = await loadSqlMigrations(join34(context4.cwd, "drizzle")).catch(() => {
106849
107509
  return;
106850
107510
  });
106851
107511
  const applied = await applyCliMigrations(await context4.getDb(), migrations);
@@ -107285,7 +107945,7 @@ function formatTraceDetail(detail) {
107285
107945
  // src/commands/serve.ts
107286
107946
  init_src();
107287
107947
  import { statSync as statSync7 } from "fs";
107288
- import { join as join37, resolve as resolve19 } from "path";
107948
+ import { join as join38, resolve as resolve19 } from "path";
107289
107949
 
107290
107950
  // ../server/src/index.ts
107291
107951
  init_src();
@@ -107295,11 +107955,11 @@ init_src();
107295
107955
  init_loader();
107296
107956
  init_src2();
107297
107957
  await init_src3();
107298
- import { basename as basename13, dirname as dirname22, isAbsolute as isAbsolute8, join as join36 } from "path";
107958
+ import { basename as basename13, dirname as dirname22, isAbsolute as isAbsolute8, join as join37 } from "path";
107299
107959
  init_dist5();
107300
107960
 
107301
107961
  // ../server/src/bootstrap.ts
107302
- import { join as join34 } from "path";
107962
+ import { join as join35 } from "path";
107303
107963
 
107304
107964
  // ../../node_modules/.bun/radash@12.1.1/node_modules/radash/dist/esm/async.mjs
107305
107965
  var guard = (func, shouldGuard) => {
@@ -117066,7 +117726,7 @@ function createApp(appRt, opts) {
117066
117726
  app.use("*", async (c3, next) => {
117067
117727
  const pathname = c3.req.path === "/" ? "/index.html" : c3.req.path;
117068
117728
  try {
117069
- const file2 = Bun.file(join34(webDistPath, pathname));
117729
+ const file2 = Bun.file(join35(webDistPath, pathname));
117070
117730
  if (await file2.exists()) {
117071
117731
  const headers = new Headers({ "content-type": file2.type });
117072
117732
  return new Response(file2.stream(), { headers });
@@ -117079,7 +117739,7 @@ function createApp(appRt, opts) {
117079
117739
  return c3.json({ error: "Not Found" }, 404);
117080
117740
  }
117081
117741
  try {
117082
- const indexFile = Bun.file(join34(webDistPath, "index.html"));
117742
+ const indexFile = Bun.file(join35(webDistPath, "index.html"));
117083
117743
  if (await indexFile.exists()) {
117084
117744
  return new Response(indexFile.stream(), {
117085
117745
  headers: { "content-type": "text/html; charset=utf-8" }
@@ -117101,7 +117761,7 @@ init_loader();
117101
117761
  init_src2();
117102
117762
  init_dist5();
117103
117763
  await init_src3();
117104
- import { dirname as dirname21, join as join35 } from "path";
117764
+ import { dirname as dirname21, join as join36 } from "path";
117105
117765
  var NOOP_OUTPUT = { write: (_s) => {}, error: (_s) => {} };
117106
117766
 
117107
117767
  class LazyPlanningEventEmitter {
@@ -117137,7 +117797,7 @@ class NotConfiguredError extends Error {
117137
117797
  function createServerContext(appRt, options) {
117138
117798
  const cwd = options.cwd;
117139
117799
  const fs3 = options.fs;
117140
- const dbUrl = options.dbUrl ?? join35(cwd, DEFAULT_DATABASE_URL);
117800
+ const dbUrl = options.dbUrl ?? join36(cwd, DEFAULT_DATABASE_URL);
117141
117801
  const eventsBus = options.eventsBus ?? appRt.events;
117142
117802
  const jobQueueEnabled = options.jobQueueEnabled ?? false;
117143
117803
  const eventProjectContext = systemEventProjectContext(cwd);
@@ -117436,7 +118096,7 @@ async function loadServerSectionMatrix(projectRoot) {
117436
118096
  }
117437
118097
  const root = bundledConfigRoot();
117438
118098
  if (root !== null) {
117439
- const matrixPath = join36(root, "tasks", "section-matrix.yaml");
118099
+ const matrixPath = join37(root, "tasks", "section-matrix.yaml");
117440
118100
  if (await nodeFs.exists(matrixPath)) {
117441
118101
  return await loadStructuredSpurConfig(matrixPath, {
117442
118102
  validateJsonSchema: false
@@ -117445,7 +118105,7 @@ async function loadServerSectionMatrix(projectRoot) {
117445
118105
  }
117446
118106
  throw new Error(`no canonical section-matrix found for task creation (F92 R1); tried:
117447
118107
  ` + ` - ${localPath}
117448
- ` + (root !== null ? ` - ${join36(root, "tasks", "section-matrix.yaml")}
118108
+ ` + (root !== null ? ` - ${join37(root, "tasks", "section-matrix.yaml")}
117449
118109
  ` : "") + "copy/generate section-matrix.yaml from the canonical build-time matrix asset (repo `config` `tasks` tree) into one of those paths");
117450
118110
  }
117451
118111
  var SYSTEM_EVENTS_PRUNE_JOB = "system-events-prune";
@@ -117464,8 +118124,8 @@ var defaultDeps = {
117464
118124
  resolveConfigFile
117465
118125
  };
117466
118126
  function registerSchedulerEntries(scheduler3, ctx, jobs = [], options = {}) {
117467
- const timeoutMs = options.timeoutMs ?? resolveSchedulerCustomTimeoutMs(process.env);
117468
118127
  const env = options.env ?? process.env;
118128
+ const timeoutMs = options.timeoutMs !== undefined ? options.timeoutMs : resolveSchedulerCustomTimeoutMs(env);
117469
118129
  const registrations = [];
117470
118130
  const now2 = Date.now();
117471
118131
  const register = (cron, name, action) => {
@@ -117509,14 +118169,15 @@ function registerSchedulerEntries(scheduler3, ctx, jobs = [], options = {}) {
117509
118169
  });
117510
118170
  for (const job of jobs) {
117511
118171
  const schedule = job.cron ?? String(job.intervalMinutes * 60000);
117512
- const sweepThresholdMs = resolveSchedulerJobTimeoutMs(job.name, env, timeoutMs) + resolveKillGraceMs(env);
118172
+ const jobPolicy = resolveSchedulerJobTimeoutMs(job.name, env, timeoutMs);
118173
+ const sweepThresholdMs = jobPolicy === null ? null : jobPolicy + resolveKillGraceMs3(env);
117513
118174
  register(schedule, `${SCHEDULER_CUSTOM_JOB}:${job.name}`, async () => {
117514
118175
  const queue = await ctx.jobQueue();
117515
118176
  const db2 = await ctx.getDb();
117516
118177
  const active = await findActiveSchedulerCustomJob(db2, job.name);
117517
118178
  if (active !== undefined) {
117518
118179
  const now3 = Date.now();
117519
- const stale = active.status === "processing" && now3 - (active.processingAt ?? active.updatedAt) > sweepThresholdMs;
118180
+ const stale = sweepThresholdMs !== null && active.status === "processing" && now3 - (active.processingAt ?? active.updatedAt) > sweepThresholdMs;
117520
118181
  if (stale) {
117521
118182
  const reason = `watchdog: processing exceeded ${sweepThresholdMs}ms`;
117522
118183
  const swept = await failStaleSchedulerCustomJob(db2, active.id, now3, reason);
@@ -117661,15 +118322,15 @@ async function handleFeatureActionJob(ctx, env, payload) {
117661
118322
  await runFeatureActionJob(ctx, env, payload);
117662
118323
  }
117663
118324
  async function resolveWebDistPath(configuredPath, projectRoot = process.cwd()) {
117664
- const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute8(configuredPath) ? configuredPath : join36(projectRoot, configuredPath)] : [
117665
- join36(projectRoot, "dist/web"),
117666
- join36(import.meta.dir, "web"),
117667
- join36(dirname22(process.execPath), "web"),
117668
- join36(dirname22(process.execPath), "../web"),
117669
- join36(import.meta.dir, "../../../dist/web")
118325
+ const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute8(configuredPath) ? configuredPath : join37(projectRoot, configuredPath)] : [
118326
+ join37(projectRoot, "dist/web"),
118327
+ join37(import.meta.dir, "web"),
118328
+ join37(dirname22(process.execPath), "web"),
118329
+ join37(dirname22(process.execPath), "../web"),
118330
+ join37(import.meta.dir, "../../../dist/web")
117670
118331
  ];
117671
118332
  for (const candidate of candidates) {
117672
- if (await Bun.file(join36(candidate, "index.html")).exists()) {
118333
+ if (await Bun.file(join37(candidate, "index.html")).exists()) {
117673
118334
  return candidate;
117674
118335
  }
117675
118336
  }
@@ -117803,7 +118464,8 @@ async function startServer(options, deps = defaultDeps) {
117803
118464
  resolveTimeoutMs: (name) => resolveSchedulerJobTimeoutMs(name, env, schedulerCustomTimeoutMs)
117804
118465
  }, job);
117805
118466
  });
117806
- const orphanCount = await failOrphanedProcessingJobs(await ctx.getDb(), Date.now());
118467
+ const unlimitedJobNames = appRt.config.scheduler.jobs.filter((job) => resolveSchedulerJobTimeoutMs(job.name, env, schedulerCustomTimeoutMs) === null).map((job) => job.name);
118468
+ const orphanCount = await failOrphanedProcessingJobs(await ctx.getDb(), Date.now(), unlimitedJobNames);
117807
118469
  if (orphanCount > 0) {
117808
118470
  appRt.logger.warn("Swept orphaned processing jobs at startup", {
117809
118471
  count: orphanCount
@@ -117926,7 +118588,7 @@ var SQLITE_BUSY_MESSAGE_CONSTANTS = Object.freeze({
117926
118588
 
117927
118589
  // src/commands/serve.ts
117928
118590
  function resolveServeDbUrl(cwd, env, configuredUrl) {
117929
- return env.DATABASE_URL === undefined ? join37(cwd, DEFAULT_DATABASE_URL) : configuredUrl;
118591
+ return env.DATABASE_URL === undefined ? join38(cwd, DEFAULT_DATABASE_URL) : configuredUrl;
117930
118592
  }
117931
118593
  function resolveServeCwd(cwd) {
117932
118594
  const resolved = resolve19(cwd);
@@ -117972,7 +118634,7 @@ function registerServeCommand(program2, context4, options = {}) {
117972
118634
  ...projectRoot !== undefined ? { cwd: projectRoot } : {}
117973
118635
  });
117974
118636
  } catch (err) {
117975
- writeJsonError(context4.output, options2, err instanceof Error ? err.message : String(err));
118637
+ writeJsonError(context4.output, options2, errorMessage4(err));
117976
118638
  if (context4.env?.SPUR_DEBUG === "1" && err instanceof Error && err.stack) {
117977
118639
  writeJsonError(context4.output, options2, err.stack, "INTERNAL_ERROR");
117978
118640
  }
@@ -117982,7 +118644,7 @@ function registerServeCommand(program2, context4, options = {}) {
117982
118644
  }
117983
118645
 
117984
118646
  // src/commands/status.ts
117985
- import { join as join38 } from "path";
118647
+ import { join as join39 } from "path";
117986
118648
 
117987
118649
  // src/git-context.ts
117988
118650
  init_dist5();
@@ -118030,8 +118692,8 @@ function registerStatusCommand(program2, context4, options = {}) {
118030
118692
  }
118031
118693
  async function runStatusCore(path9, options, context4) {
118032
118694
  const [packageJsonExists, spurConfigExists, git3, agentSpecs] = await Promise.all([
118033
- context4.fs.exists(join38(context4.cwd, "package.json")),
118034
- context4.fs.exists(join38(context4.cwd, ".spur", "config.yaml")),
118695
+ context4.fs.exists(join39(context4.cwd, "package.json")),
118696
+ context4.fs.exists(join39(context4.cwd, ".spur", "config.yaml")),
118035
118697
  gitContext(context4.cwd),
118036
118698
  listAgentSpecIds(context4)
118037
118699
  ]);
@@ -118059,14 +118721,14 @@ async function runStatusCore(path9, options, context4) {
118059
118721
  return status.ok ? 0 : 1;
118060
118722
  }
118061
118723
  async function listAgentSpecIds(context4) {
118062
- const dir = join38(context4.cwd, ".spur", "agents");
118724
+ const dir = join39(context4.cwd, ".spur", "agents");
118063
118725
  if (!await context4.fs.exists(dir))
118064
118726
  return [];
118065
118727
  const entries = await context4.fs.readDir(dir);
118066
118728
  return entries.filter((entry) => entry.endsWith(".yaml") || entry.endsWith(".yml")).map((entry) => entry.replace(/\.ya?ml$/, "")).sort();
118067
118729
  }
118068
118730
  async function readTargetStatus(context4, targetPath) {
118069
- const resolved = join38(context4.cwd, targetPath);
118731
+ const resolved = join39(context4.cwd, targetPath);
118070
118732
  const stat2 = await context4.fs.stat(resolved);
118071
118733
  if (stat2 === null)
118072
118734
  throw new CommandError(`status failed: path does not exist at ${resolved}`);
@@ -118081,7 +118743,7 @@ await init_src3();
118081
118743
  import { existsSync as existsSync11, readFileSync as readFileSync11 } from "fs";
118082
118744
  import { rm, writeFile } from "fs/promises";
118083
118745
  import { tmpdir as tmpdir3 } from "os";
118084
- import { dirname as dirname23, join as join39 } from "path";
118746
+ import { dirname as dirname23, join as join40 } from "path";
118085
118747
  // schemas/section-matrix.schema.json
118086
118748
  var section_matrix_schema_default = {
118087
118749
  $schema: "http://json-schema.org/draft-07/schema#",
@@ -119240,7 +119902,7 @@ ${result.content}`);
119240
119902
  let forcedDoneVerdict;
119241
119903
  if (status === "done") {
119242
119904
  const current = await svc.show(wbs);
119243
- const verdictDir = options.verdictDir ?? join39(context4.cwd, ".spur", "run");
119905
+ const verdictDir = options.verdictDir ?? join40(context4.cwd, ".spur", "run");
119244
119906
  const loaded = await readVerdictArtifact(context4.fs, verdictDir, wbs);
119245
119907
  const guardOutcome = evaluateDoneTransition({
119246
119908
  wbs,
@@ -119550,7 +120212,7 @@ ${result.content}`);
119550
120212
  agentSelector: options.agent,
119551
120213
  cwd: context4.cwd
119552
120214
  });
119553
- tmpPath = join39(tmpdir3(), `spur-ready-batch-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`);
120215
+ tmpPath = join40(tmpdir3(), `spur-ready-batch-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`);
119554
120216
  await writeFile(tmpPath, `${JSON.stringify(prepared.items, null, 2)}
119555
120217
  `);
119556
120218
  batchFile = tmpPath;
@@ -119963,13 +120625,13 @@ function loadTemplateBodies(projectRoot, variant) {
119963
120625
  if (cached2 !== undefined)
119964
120626
  return cached2;
119965
120627
  let bodies = {};
119966
- const localPath = join39(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
120628
+ const localPath = join40(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
119967
120629
  if (existsSync11(localPath)) {
119968
120630
  bodies = extractTemplateBodies(readFileSync11(localPath, "utf8"));
119969
120631
  } else {
119970
120632
  const root = bundledConfigRoot();
119971
120633
  if (root !== null) {
119972
- const templatePath = join39(root, "templates", "task", `${variant}.md`);
120634
+ const templatePath = join40(root, "templates", "task", `${variant}.md`);
119973
120635
  if (existsSync11(templatePath)) {
119974
120636
  bodies = extractTemplateBodies(readFileSync11(templatePath, "utf8"));
119975
120637
  }
@@ -120027,7 +120689,7 @@ async function loadSectionMatrixUncached(projectRoot) {
120027
120689
  }
120028
120690
  const root = bundledConfigRoot();
120029
120691
  if (root !== null) {
120030
- const matrixPath = join39(root, "tasks", "section-matrix.yaml");
120692
+ const matrixPath = join40(root, "tasks", "section-matrix.yaml");
120031
120693
  if (await fs3.exists(matrixPath)) {
120032
120694
  const data = await loadStructuredSpurConfig(matrixPath, {
120033
120695
  validateJsonSchema: true,
@@ -120038,7 +120700,7 @@ async function loadSectionMatrixUncached(projectRoot) {
120038
120700
  }
120039
120701
  throw new Error(`no canonical section-matrix found for task section authority (F92 R1); tried:
120040
120702
  ` + ` - ${localPath}
120041
- ` + (root !== null ? ` - ${join39(root, "tasks", "section-matrix.yaml")}
120703
+ ` + (root !== null ? ` - ${join40(root, "tasks", "section-matrix.yaml")}
120042
120704
  ` : "") + "copy/generate section-matrix.yaml from the canonical build-time matrix asset (repo `config` `tasks` tree) into one of those paths");
120043
120705
  }
120044
120706
 
@@ -120335,7 +120997,7 @@ init_dist7();
120335
120997
  init_dist5();
120336
120998
  await init_src3();
120337
120999
  import { closeSync as closeSync5, fstatSync as fstatSync3, openSync as openSync5, readSync as readSync3 } from "fs";
120338
- import { join as join40 } from "path";
121000
+ import { join as join41 } from "path";
120339
121001
  import { createInterface } from "readline";
120340
121002
  import { setTimeout as sleep5 } from "timers/promises";
120341
121003
 
@@ -120514,9 +121176,9 @@ async function writeWorkflowPlanArtifact(cwd, runId, resolved, secretValues) {
120514
121176
  }))
120515
121177
  });
120516
121178
  const { mkdir, writeFile: writeFile2 } = await import("fs/promises");
120517
- const artifactsDir = join40(cwd, ".spur", "run");
121179
+ const artifactsDir = join41(cwd, ".spur", "run");
120518
121180
  await mkdir(artifactsDir, { recursive: true });
120519
- const artifactPath = join40(artifactsDir, `${runId}-workflow-plan.json`);
121181
+ const artifactPath = join41(artifactsDir, `${runId}-workflow-plan.json`);
120520
121182
  await writeFile2(artifactPath, payload);
120521
121183
  return artifactPath;
120522
121184
  }
@@ -120574,7 +121236,7 @@ function resolveWorkflowPaths(config4) {
120574
121236
  for (const path9 of paths) {
120575
121237
  if (path9.startsWith(BUNDLED_PATH_PREFIX)) {
120576
121238
  if (bundledRoot !== null)
120577
- expanded.push(join40(bundledRoot, path9.slice(BUNDLED_PATH_PREFIX.length)));
121239
+ expanded.push(join41(bundledRoot, path9.slice(BUNDLED_PATH_PREFIX.length)));
120578
121240
  } else {
120579
121241
  expanded.push(path9);
120580
121242
  }
@@ -120813,7 +121475,7 @@ Monitor with: spur workflow trace ${runId2} --follow`);
120813
121475
  }
120814
121476
  const runLog = options.log === false ? undefined : new WorkflowRunLogSink({
120815
121477
  bus,
120816
- dir: join40(context4.cwd, ".spur", "run"),
121478
+ dir: join41(context4.cwd, ".spur", "run"),
120817
121479
  runId,
120818
121480
  ...planPreview !== undefined ? { planPreview } : {},
120819
121481
  ...resolveOutputLogConfig(context4.spurConfig ?? null)
@@ -121083,14 +121745,21 @@ Monitor with: spur workflow trace ${runId2} --follow`);
121083
121745
  const def = resolvedDefinition.workflow;
121084
121746
  if (options.json) {
121085
121747
  if (options.format === "todo") {
121086
- context4.output.write(toJson2({
121748
+ const projection = {
121087
121749
  name: def.name,
121088
121750
  kind: def.kind ?? "state-machine",
121089
121751
  format: "todo",
121090
121752
  version: resolvedDefinition.workflow.version ?? null,
121091
121753
  definitionDigest: resolvedDefinition.digest,
121092
121754
  steps: buildWorkflowSteps(def)
121093
- }));
121755
+ };
121756
+ const parsed = parseWorkflowInventory(projection);
121757
+ if (!parsed.ok) {
121758
+ writeJsonError(context4.output, options, `workflow show: invalid todo projection \u2014 ${parsed.error}`, "VALIDATION_FAILED");
121759
+ context4.setExitCode(1);
121760
+ return;
121761
+ }
121762
+ context4.output.write(toJson2(projection));
121094
121763
  } else {
121095
121764
  context4.output.write(toJson2({
121096
121765
  name: def.name,
@@ -121345,7 +122014,7 @@ function readRunLogChunk(logPath, offset) {
121345
122014
  }
121346
122015
  }
121347
122016
  async function followRunLog(service, runId, dir, pollMs, write, wait = (ms) => sleep5(ms)) {
121348
- const logPath = join40(dir, ".spur", "run", `${runId}.log`);
122017
+ const logPath = join41(dir, ".spur", "run", `${runId}.log`);
121349
122018
  let offset = 0;
121350
122019
  let everRead = false;
121351
122020
  while (true) {
@@ -121408,7 +122077,7 @@ init_src();
121408
122077
  init_src2();
121409
122078
  init_dist5();
121410
122079
  await init_src3();
121411
- import { dirname as dirname24, join as join41, resolve as resolve20 } from "path";
122080
+ import { dirname as dirname24, join as join42, resolve as resolve20 } from "path";
121412
122081
  import { isatty as isatty4 } from "tty";
121413
122082
 
121414
122083
  // ../../node_modules/.bun/@clack+core@1.4.1/node_modules/@clack/core/dist/index.mjs
@@ -122873,7 +123542,7 @@ function createCliContext(options) {
122873
123542
  function noopSetExitCode(_code) {}
122874
123543
  async function createMigratedDbAdapter(cwd = process.cwd(), env = process.env, dbUrl) {
122875
123544
  const config4 = buildConfigFromEnv(env);
122876
- const configuredUrl = env.DATABASE_URL === undefined ? join41(cwd, DEFAULT_DATABASE_URL) : config4.database.url;
123545
+ const configuredUrl = env.DATABASE_URL === undefined ? join42(cwd, DEFAULT_DATABASE_URL) : config4.database.url;
122877
123546
  const url2 = dbUrl ?? configuredUrl;
122878
123547
  if (url2 !== IN_MEMORY_DATABASE_URL) {
122879
123548
  await createNodeFileSystem3().ensureDir(dirname24(url2));