@gobing-ai/spur 0.3.27 → 0.3.29

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
@@ -47,7 +47,7 @@ var __export = (target, all) => {
47
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
48
  var __require = import.meta.require;
49
49
 
50
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.14/node_modules/@gobing-ai/ts-utils/dist/errors.js
50
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/errors.js
51
51
  var ErrorCode;
52
52
  var init_errors = __esm(() => {
53
53
  ErrorCode = {
@@ -58,7 +58,7 @@ var init_errors = __esm(() => {
58
58
  };
59
59
  });
60
60
 
61
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.14/node_modules/@gobing-ai/ts-utils/dist/api-response.js
61
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/api-response.js
62
62
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
63
63
  var init_api_response = __esm(() => {
64
64
  init_errors();
@@ -81,16 +81,18 @@ var init_api_response = __esm(() => {
81
81
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
82
82
  });
83
83
 
84
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.14/node_modules/@gobing-ai/ts-utils/dist/cursor.js
84
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/cursor.js
85
85
  var init_cursor = () => {};
86
86
 
87
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.14/node_modules/@gobing-ai/ts-utils/dist/object.js
87
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/object.js
88
88
  function isPlainObject(value) {
89
89
  return typeof value === "object" && value !== null && !Array.isArray(value);
90
90
  }
91
91
  function deepMerge(target, source) {
92
92
  const result = { ...target };
93
93
  for (const [key, value] of Object.entries(source)) {
94
+ if (key === "__proto__")
95
+ continue;
94
96
  if (isPlainObject(value) && isPlainObject(result[key])) {
95
97
  result[key] = deepMerge(result[key], value);
96
98
  } else {
@@ -100,7 +102,7 @@ function deepMerge(target, source) {
100
102
  return result;
101
103
  }
102
104
 
103
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.14/node_modules/@gobing-ai/ts-utils/dist/output.js
105
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/output.js
104
106
  function processStream(name) {
105
107
  const proc = globalThis.process;
106
108
  const stream = proc?.[name];
@@ -121,7 +123,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
121
123
  }
122
124
  var defaultStdoutTarget, defaultStderrTarget;
123
125
 
124
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.14/node_modules/@gobing-ai/ts-utils/dist/index.js
126
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/index.js
125
127
  var init_dist = __esm(() => {
126
128
  init_api_response();
127
129
  init_cursor();
@@ -21743,7 +21745,7 @@ var init_zod = __esm(() => {
21743
21745
  init_external();
21744
21746
  });
21745
21747
 
21746
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/config.js
21748
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/config.js
21747
21749
  function getProcessEnv() {
21748
21750
  return process.env;
21749
21751
  }
@@ -21821,11 +21823,11 @@ var init_config = __esm(() => {
21821
21823
  };
21822
21824
  });
21823
21825
 
21824
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21826
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21825
21827
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
21826
21828
  import { dirname, resolve as resolvePath } from "path";
21827
- function createNodeFileSystem(root) {
21828
- const projectRoot = root ?? findProjectRoot(process.cwd());
21829
+ function createNodeFileSystem(root, paths) {
21830
+ const projectRoot = root ?? findProjectRoot(paths?.cwd ?? process.cwd());
21829
21831
  return {
21830
21832
  getProjectRoot: () => projectRoot,
21831
21833
  resolve: (...segments) => resolvePath(projectRoot, ...segments),
@@ -21908,7 +21910,7 @@ function findProjectRoot(startDir) {
21908
21910
  }
21909
21911
  var init_file_system_node = () => {};
21910
21912
 
21911
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
21913
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
21912
21914
  var DbModuleNotInstalledError;
21913
21915
  var init_db_errors = __esm(() => {
21914
21916
  DbModuleNotInstalledError = class DbModuleNotInstalledError extends Error {
@@ -29099,7 +29101,7 @@ var init_execa = __esm(() => {
29099
29101
  } = getIpcExport());
29100
29102
  });
29101
29103
 
29102
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
29104
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
29103
29105
  import { isatty } from "tty";
29104
29106
 
29105
29107
  class NodeProcessExecutor {
@@ -29113,7 +29115,7 @@ class NodeProcessExecutor {
29113
29115
  async runUntraced(options) {
29114
29116
  const args = options.args ?? [];
29115
29117
  const execaOptions = buildExecaOptions({
29116
- cwd: options.cwd,
29118
+ cwd: options.cwd ?? this.config.paths?.cwd,
29117
29119
  env: options.env,
29118
29120
  timeout: options.timeout ?? this.config.defaultTimeout,
29119
29121
  maxOutput: options.maxOutput ?? this.config.defaultMaxOutput,
@@ -29429,7 +29431,7 @@ var init_process_executor = __esm(() => {
29429
29431
  init_execa();
29430
29432
  });
29431
29433
 
29432
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
29434
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
29433
29435
  function getNodeFileSystem() {
29434
29436
  if (!_nodeFileSystem)
29435
29437
  _nodeFileSystem = createNodeFileSystem();
@@ -29489,7 +29491,7 @@ var init_runtime_node_bun = __esm(() => {
29489
29491
  };
29490
29492
  });
29491
29493
 
29492
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/context.js
29494
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/context.js
29493
29495
  class RuntimeContext {
29494
29496
  scope;
29495
29497
  runtimeName;
@@ -29559,7 +29561,7 @@ var init_context = __esm(() => {
29559
29561
  init_runtime_node_bun();
29560
29562
  });
29561
29563
 
29562
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/path.js
29564
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/path.js
29563
29565
  function normalizeSeparators(path6) {
29564
29566
  return path6.replaceAll("\\", "/");
29565
29567
  }
@@ -29620,17 +29622,17 @@ var init_path = __esm(() => {
29620
29622
  SEP = globalThis.process?.platform === "win32" ? "\\" : "/";
29621
29623
  });
29622
29624
 
29623
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
29625
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
29624
29626
  var REMOTE_SCHEMA_MAX_BYTES;
29625
29627
  var init_schema_validation = __esm(() => {
29626
29628
  init_dist2();
29627
29629
  REMOTE_SCHEMA_MAX_BYTES = 5 * 1024 * 1024;
29628
29630
  });
29629
29631
 
29630
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/types.js
29632
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/types.js
29631
29633
  var init_types = () => {};
29632
29634
 
29633
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/index.js
29635
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/index.js
29634
29636
  var init_dist3 = __esm(() => {
29635
29637
  init_config();
29636
29638
  init_context();
@@ -29639,7 +29641,7 @@ var init_dist3 = __esm(() => {
29639
29641
  init_types();
29640
29642
  });
29641
29643
 
29642
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+c51d44ed7d8b072c/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
29644
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
29643
29645
  import { Database } from "bun:sqlite";
29644
29646
  var init_bun_sqlite = () => {};
29645
29647
 
@@ -33831,7 +33833,7 @@ var init_bun_sqlite2 = __esm(() => {
33831
33833
  init_session2();
33832
33834
  });
33833
33835
 
33834
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
33836
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
33835
33837
  var inboxMessages;
33836
33838
  var init_inbox_messages = __esm(() => {
33837
33839
  init_sqlite_core();
@@ -33850,7 +33852,7 @@ var init_inbox_messages = __esm(() => {
33850
33852
  }, (table2) => [index("idx_inbox_messages_to_status").on(table2.toId, table2.status)]);
33851
33853
  });
33852
33854
 
33853
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/common.js
33855
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/common.js
33854
33856
  function nowTimestamp() {
33855
33857
  return Date.now();
33856
33858
  }
@@ -33879,7 +33881,7 @@ var init_common3 = __esm(() => {
33879
33881
  appendOnlyColumns = buildAppendOnlyColumns();
33880
33882
  });
33881
33883
 
33882
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
33884
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
33883
33885
  var queueJobs;
33884
33886
  var init_queue_jobs = __esm(() => {
33885
33887
  init_sqlite_core();
@@ -33899,7 +33901,7 @@ var init_queue_jobs = __esm(() => {
33899
33901
  }, (table2) => [index("queue_jobs_ready_idx").on(table2.status, table2.nextRetryAt, table2.createdAt)]);
33900
33902
  });
33901
33903
 
33902
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
33904
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
33903
33905
  var exports_runtime = {};
33904
33906
  __export(exports_runtime, {
33905
33907
  queueJobs: () => queueJobs,
@@ -33910,7 +33912,7 @@ var init_runtime = __esm(() => {
33910
33912
  init_queue_jobs();
33911
33913
  });
33912
33914
 
33913
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
33915
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
33914
33916
  var exports_bun_sqlite = {};
33915
33917
  __export(exports_bun_sqlite, {
33916
33918
  BunSqliteAdapter: () => BunSqliteAdapter
@@ -34199,7 +34201,7 @@ var init_d1 = __esm(() => {
34199
34201
  init_session3();
34200
34202
  });
34201
34203
 
34202
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
34204
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
34203
34205
  var exports_d1 = {};
34204
34206
  __export(exports_d1, {
34205
34207
  D1Adapter: () => D1Adapter
@@ -34263,7 +34265,7 @@ var init_d12 = __esm(() => {
34263
34265
  init_runtime();
34264
34266
  });
34265
34267
 
34266
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/adapter.js
34268
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/adapter.js
34267
34269
  async function createDbAdapter(config3) {
34268
34270
  switch (config3.driver) {
34269
34271
  case "bun-sqlite": {
@@ -34303,7 +34305,7 @@ var init_drizzle_orm = __esm(() => {
34303
34305
  init_view_common();
34304
34306
  });
34305
34307
 
34306
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/query-spec.js
34308
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/query-spec.js
34307
34309
  function compilePredicate(predicate) {
34308
34310
  if ("and" in predicate) {
34309
34311
  const parts = predicate.and.map(compilePredicate).filter((p) => p !== undefined);
@@ -34341,7 +34343,7 @@ var init_query_spec = __esm(() => {
34341
34343
  };
34342
34344
  });
34343
34345
 
34344
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/base-dao.js
34346
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/base-dao.js
34345
34347
  function asSelectQuery(query) {
34346
34348
  return query;
34347
34349
  }
@@ -34383,7 +34385,7 @@ var init_base_dao = __esm(() => {
34383
34385
  init_query_spec();
34384
34386
  });
34385
34387
 
34386
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/embedded-migrations.js
34388
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/embedded-migrations.js
34387
34389
  var embeddedMigrations;
34388
34390
  var init_embedded_migrations = __esm(() => {
34389
34391
  embeddedMigrations = [
@@ -34415,7 +34417,7 @@ var init_embedded_migrations = __esm(() => {
34415
34417
  ];
34416
34418
  });
34417
34419
 
34418
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
34420
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
34419
34421
  var EntityDao;
34420
34422
  var init_entity_dao = __esm(() => {
34421
34423
  init_drizzle_orm();
@@ -34577,7 +34579,7 @@ var init_entity_dao = __esm(() => {
34577
34579
  };
34578
34580
  });
34579
34581
 
34580
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/inbox-message-dao.js
34582
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/inbox-message-dao.js
34581
34583
  function isPromiseLike(value) {
34582
34584
  return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
34583
34585
  }
@@ -34750,7 +34752,7 @@ var init_migrator2 = __esm(() => {
34750
34752
  init_migrator();
34751
34753
  });
34752
34754
 
34753
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/migrate.js
34755
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/migrate.js
34754
34756
  async function ensureJournalTable(adapter, table3) {
34755
34757
  await adapter.exec(`CREATE TABLE IF NOT EXISTS "${table3}" (` + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "hash text NOT NULL, " + "created_at numeric" + ")");
34756
34758
  }
@@ -34825,7 +34827,7 @@ var init_migrate = __esm(() => {
34825
34827
  init_embedded_migrations();
34826
34828
  });
34827
34829
 
34828
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/queue-job-dao.js
34830
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/queue-job-dao.js
34829
34831
  var QueueJobDao;
34830
34832
  var init_queue_job_dao = __esm(() => {
34831
34833
  init_drizzle_orm();
@@ -34966,7 +34968,7 @@ var init_queue_job_dao = __esm(() => {
34966
34968
  };
34967
34969
  });
34968
34970
 
34969
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/index.js
34971
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/index.js
34970
34972
  var exports_dist = {};
34971
34973
  __export(exports_dist, {
34972
34974
  embeddedMigrations: () => embeddedMigrations,
@@ -37119,6 +37121,7 @@ var init_finding_codes = __esm(() => {
37119
37121
  "L3.solution-file-line",
37120
37122
  "L3.review-priority-table",
37121
37123
  "L3.testing-coverage",
37124
+ "L3.required-section-placeholder",
37122
37125
  "L3.plan-format",
37123
37126
  "L3.unchecked-checklist",
37124
37127
  "L3.ac-checklist-text",
@@ -37148,8 +37151,9 @@ var init_finding_codes = __esm(() => {
37148
37151
  "L4.uncovered-feature-scenario",
37149
37152
  "L4.verifying-incomplete-tasks",
37150
37153
  "L4.dogfood-missing",
37151
- "L4.scenario-unverified",
37152
- "L4.stale-line-anchor"
37154
+ "L4.stale-line-anchor",
37155
+ "L4.malformed-verdict-artifact",
37156
+ "L4.scenario-unverified"
37153
37157
  ];
37154
37158
  FINDING_CODES = {
37155
37159
  L1_MARKDOWN_PARSE: "L1.markdown-parse",
@@ -37163,6 +37167,7 @@ var init_finding_codes = __esm(() => {
37163
37167
  L3_SOLUTION_FILE_LINE: "L3.solution-file-line",
37164
37168
  L3_REVIEW_PRIORITY_TABLE: "L3.review-priority-table",
37165
37169
  L3_TESTING_COVERAGE: "L3.testing-coverage",
37170
+ L3_REQUIRED_SECTION_PLACEHOLDER: "L3.required-section-placeholder",
37166
37171
  L3_PLAN_FORMAT: "L3.plan-format",
37167
37172
  L3_UNCHECKED_CHECKLIST: "L3.unchecked-checklist",
37168
37173
  L3_AC_CHECKLIST_TEXT: "L3.ac-checklist-text",
@@ -37190,10 +37195,11 @@ var init_finding_codes = __esm(() => {
37190
37195
  L4_ORPHAN_SCENARIOS: "L4.orphan-scenarios",
37191
37196
  L4_UNCOVERED_TASK_SCENARIO: "L4.uncovered-task-scenario",
37192
37197
  L4_UNCOVERED_FEATURE_SCENARIO: "L4.uncovered-feature-scenario",
37193
- L4_VERIFYING_INCOMPLETE_TASKS: "L4.verifying-incomplete-tasks",
37194
37198
  L4_DOGFOOD_MISSING: "L4.dogfood-missing",
37195
- L4_SCENARIO_UNVERIFIED: "L4.scenario-unverified",
37196
- L4_STALE_LINE_ANCHOR: "L4.stale-line-anchor"
37199
+ L4_VERIFYING_INCOMPLETE_TASKS: "L4.verifying-incomplete-tasks",
37200
+ L4_STALE_LINE_ANCHOR: "L4.stale-line-anchor",
37201
+ L4_MALFORMED_VERDICT_ARTIFACT: "L4.malformed-verdict-artifact",
37202
+ L4_SCENARIO_UNVERIFIED: "L4.scenario-unverified"
37197
37203
  };
37198
37204
  });
37199
37205
 
@@ -37267,7 +37273,7 @@ function buildConfigFromEnv(env = process.env) {
37267
37273
  }
37268
37274
  });
37269
37275
  }
37270
- var SPUR_ENV_VARS, SPUR_LOG_LEVELS, DEFAULT_TASKS_DIR = "docs/tasks", DEFAULT_FEATURES_DIR = "docs/features", DEFAULT_DATABASE_URL = ".spur/spur.db", IN_MEMORY_DATABASE_URL = ":memory:", folderConfigSchema, tasksConfigSchema, featuresConfigSchema, EXECUTOR_CAPABILITY_TIERS, executorCapabilityTierSchema, AgentExecutorConfigSchema, AGENT_ID_REGEX, TeamMemberConfigSchema, TeamConfigSchema, AgentConfigSchema, RulesConfigSchema, WorkflowsConfigSchema, RedactionConfigSchema, spurConfigSchema, configSchema2;
37276
+ var SPUR_ENV_VARS, SPUR_LOG_LEVELS, DEFAULT_TASKS_DIR = "docs/tasks", DEFAULT_FEATURES_DIR = "docs/features", DEFAULT_DATABASE_URL = ".spur/spur.db", IN_MEMORY_DATABASE_URL = ":memory:", folderConfigSchema, tasksConfigSchema, featuresConfigSchema, EXECUTOR_CAPABILITY_TIERS, executorCapabilityTierSchema, AgentExecutorConfigSchema, AGENT_ID_REGEX, TeamMemberConfigSchema, TeamConfigSchema, AgentOutputConfigSchema, AgentConfigSchema, RulesConfigSchema, WorkflowsConfigSchema, RedactionConfigSchema, spurConfigSchema, configSchema2;
37271
37277
  var init_src = __esm(() => {
37272
37278
  init_zod();
37273
37279
  init_finding_codes();
@@ -37337,11 +37343,16 @@ var init_src = __esm(() => {
37337
37343
  autostart: exports_external.boolean().optional(),
37338
37344
  members: exports_external.array(TeamMemberConfigSchema).min(1)
37339
37345
  });
37346
+ AgentOutputConfigSchema = exports_external.object({
37347
+ "max-bytes": exports_external.number().int().positive().optional(),
37348
+ "max-lines": exports_external.number().int().positive().optional()
37349
+ });
37340
37350
  AgentConfigSchema = exports_external.object({
37341
37351
  default: exports_external.string().optional(),
37342
37352
  executors: exports_external.array(AgentExecutorConfigSchema).optional(),
37343
37353
  "default-by-phase": exports_external.record(exports_external.string(), exports_external.string()).optional(),
37344
- team: exports_external.record(exports_external.string(), TeamConfigSchema).optional()
37354
+ team: exports_external.record(exports_external.string(), TeamConfigSchema).optional(),
37355
+ output: AgentOutputConfigSchema.optional()
37345
37356
  }).superRefine((value, ctx) => {
37346
37357
  const executors = value.executors;
37347
37358
  if (executors !== undefined) {
@@ -37354,6 +37365,13 @@ var init_src = __esm(() => {
37354
37365
  path: ["executors", index2, "name"]
37355
37366
  });
37356
37367
  }
37368
+ if (executor.name === "inline" || executor.name === "auto") {
37369
+ ctx.addIssue({
37370
+ code: exports_external.ZodIssueCode.custom,
37371
+ message: `Executor name "${executor.name}" is reserved (the --agent selector value '${executor.name}' has fixed semantics); rename executor at index ${index2}.`,
37372
+ path: ["executors", index2, "name"]
37373
+ });
37374
+ }
37357
37375
  seen.add(executor.name);
37358
37376
  }
37359
37377
  }
@@ -37432,7 +37450,7 @@ var init_src = __esm(() => {
37432
37450
  });
37433
37451
  });
37434
37452
 
37435
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/config.js
37453
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/config.js
37436
37454
  function parseYamlObject(text3) {
37437
37455
  let parsed;
37438
37456
  try {
@@ -37559,11 +37577,11 @@ var init_config2 = __esm(() => {
37559
37577
  };
37560
37578
  });
37561
37579
 
37562
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
37580
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
37563
37581
  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
37582
  import { dirname as dirname2, resolve as resolvePath3 } from "path";
37565
- function createNodeFileSystem3(root) {
37566
- const projectRoot = root ?? findProjectRoot3(process.cwd());
37583
+ function createNodeFileSystem3(root, paths) {
37584
+ const projectRoot = root ?? findProjectRoot3(paths?.cwd ?? process.cwd());
37567
37585
  return {
37568
37586
  getProjectRoot: () => projectRoot,
37569
37587
  resolve: (...segments) => resolvePath3(projectRoot, ...segments),
@@ -37646,7 +37664,7 @@ function findProjectRoot3(startDir) {
37646
37664
  }
37647
37665
  var init_file_system_node2 = () => {};
37648
37666
 
37649
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
37667
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
37650
37668
  var D1NotConfiguredError2, DbModuleNotInstalledError3;
37651
37669
  var init_db_errors2 = __esm(() => {
37652
37670
  D1NotConfiguredError2 = class D1NotConfiguredError2 extends Error {
@@ -37663,7 +37681,7 @@ var init_db_errors2 = __esm(() => {
37663
37681
  };
37664
37682
  });
37665
37683
 
37666
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/file-system-cf.js
37684
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/file-system-cf.js
37667
37685
  function createCfFileSystem2() {
37668
37686
  return {
37669
37687
  getProjectRoot: () => "/bundle",
@@ -37702,7 +37720,7 @@ function createCfFileSystem2() {
37702
37720
  }
37703
37721
  var UNSUPPORTED = "FileSystem is not available on Cloudflare Workers. Use D1, KV, or R2 for persistent storage.";
37704
37722
 
37705
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/runtime-cf.js
37723
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/runtime-cf.js
37706
37724
  var exports_runtime_cf = {};
37707
37725
  __export(exports_runtime_cf, {
37708
37726
  cloudflareWorkersFactory: () => cloudflareWorkersFactory2
@@ -37740,7 +37758,7 @@ var init_runtime_cf = __esm(() => {
37740
37758
  };
37741
37759
  });
37742
37760
 
37743
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
37761
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
37744
37762
  import { isatty as isatty2 } from "tty";
37745
37763
 
37746
37764
  class NodeProcessExecutor3 {
@@ -37754,7 +37772,7 @@ class NodeProcessExecutor3 {
37754
37772
  async runUntraced(options) {
37755
37773
  const args = options.args ?? [];
37756
37774
  const execaOptions = buildExecaOptions2({
37757
- cwd: options.cwd,
37775
+ cwd: options.cwd ?? this.config.paths?.cwd,
37758
37776
  env: options.env,
37759
37777
  timeout: options.timeout ?? this.config.defaultTimeout,
37760
37778
  maxOutput: options.maxOutput ?? this.config.defaultMaxOutput,
@@ -38117,7 +38135,7 @@ var init_process_executor2 = __esm(() => {
38117
38135
  ProcessExecutor2 = NodeProcessExecutor3;
38118
38136
  });
38119
38137
 
38120
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
38138
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
38121
38139
  var exports_runtime_node_bun = {};
38122
38140
  __export(exports_runtime_node_bun, {
38123
38141
  nodeBunFactory: () => nodeBunFactory3,
@@ -38185,7 +38203,7 @@ var init_runtime_node_bun2 = __esm(() => {
38185
38203
  };
38186
38204
  });
38187
38205
 
38188
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/platform.js
38206
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/platform.js
38189
38207
  function isCloudflareWorkerRuntime2() {
38190
38208
  return globalThis.navigator?.userAgent?.startsWith("Cloudflare-Workers") ?? false;
38191
38209
  }
@@ -38215,7 +38233,7 @@ function _resetRuntimeFactory2() {
38215
38233
  }
38216
38234
  var _factory, _runtimeName;
38217
38235
 
38218
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/context.js
38236
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/context.js
38219
38237
  class RuntimeContext2 {
38220
38238
  scope;
38221
38239
  runtimeName;
@@ -38305,7 +38323,7 @@ var init_context2 = __esm(() => {
38305
38323
  init_runtime_node_bun2();
38306
38324
  });
38307
38325
 
38308
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/path.js
38326
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/path.js
38309
38327
  function normalizeSeparators2(path7) {
38310
38328
  return path7.replaceAll("\\", "/");
38311
38329
  }
@@ -38428,7 +38446,7 @@ var init_path2 = __esm(() => {
38428
38446
  SEP2 = globalThis.process?.platform === "win32" ? "\\" : "/";
38429
38447
  });
38430
38448
 
38431
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/fs.js
38449
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/fs.js
38432
38450
  async function ensureDirForFile2(path7, fs2 = createNodeFileSystem3()) {
38433
38451
  await fs2.ensureDir(dirnamePath(path7));
38434
38452
  }
@@ -38479,7 +38497,7 @@ var init_fs = __esm(() => {
38479
38497
  init_path2();
38480
38498
  });
38481
38499
 
38482
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/process-registry.js
38500
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/process-registry.js
38483
38501
  function allocateId() {
38484
38502
  nextIdSeq += 1;
38485
38503
  return `pe_${Date.now().toString(36)}_${nextIdSeq.toString(36)}`;
@@ -38603,7 +38621,17 @@ function createInMemoryProcessRegistry2(options) {
38603
38621
  }
38604
38622
  var nextIdSeq = 0;
38605
38623
 
38606
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
38624
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/runtime-paths.js
38625
+ function ambientRuntimePaths2() {
38626
+ const cwd = getProcessCwd2();
38627
+ return { cwd, home: getHomeDir() ?? cwd };
38628
+ }
38629
+ var init_runtime_paths = __esm(() => {
38630
+ init_config2();
38631
+ init_path2();
38632
+ });
38633
+
38634
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
38607
38635
  async function loadStructuredConfig(path7, options = {}) {
38608
38636
  const content = await (options.fileSystem ?? createNodeFileSystem3()).readFile(path7);
38609
38637
  return await parseStructuredConfig(content, path7, options);
@@ -38880,10 +38908,10 @@ var init_schema_validation2 = __esm(() => {
38880
38908
  defaultResolve = typeof Bun !== "undefined" ? (specifier, from) => Bun.resolveSync(specifier, from) : undefined;
38881
38909
  });
38882
38910
 
38883
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/types.js
38911
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/types.js
38884
38912
  var init_types2 = () => {};
38885
38913
 
38886
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/index.js
38914
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/index.js
38887
38915
  var exports_dist2 = {};
38888
38916
  __export(exports_dist2, {
38889
38917
  writeJsonFile: () => writeJsonFile2,
@@ -38929,6 +38957,7 @@ __export(exports_dist2, {
38929
38957
  basenamePath: () => basenamePath,
38930
38958
  atomicWriteJson: () => atomicWriteJson2,
38931
38959
  atomicWriteFile: () => atomicWriteFile2,
38960
+ ambientRuntimePaths: () => ambientRuntimePaths2,
38932
38961
  _resetRuntimeFactory: () => _resetRuntimeFactory2,
38933
38962
  _resetNodeFileSystem: () => _resetNodeFileSystem2,
38934
38963
  YamlParseError: () => YamlParseError,
@@ -38952,6 +38981,7 @@ var init_dist5 = __esm(() => {
38952
38981
  init_process_executor2();
38953
38982
  init_runtime_cf();
38954
38983
  init_runtime_node_bun2();
38984
+ init_runtime_paths();
38955
38985
  init_process_executor2();
38956
38986
  init_config2();
38957
38987
  init_context2();
@@ -39168,7 +39198,7 @@ async function loadStructuredSpurConfig(configPath, opts) {
39168
39198
  function defaultFoldersConfig() {
39169
39199
  return {
39170
39200
  active_folder: DEFAULT_TASKS_DIR,
39171
- folders: { [DEFAULT_TASKS_DIR]: { base_counter: 0 } }
39201
+ folders: { [DEFAULT_TASKS_DIR]: { baseCounter: 0 } }
39172
39202
  };
39173
39203
  }
39174
39204
  function defaultPlanningFolders() {
@@ -39205,8 +39235,7 @@ async function resolvePlanningFoldersUncached(fs2) {
39205
39235
  const tasks = tasksConfigSchema.parse(parsed.tasks);
39206
39236
  const folders = {};
39207
39237
  for (const [path8, fc] of Object.entries(tasks.folders)) {
39208
- const validated = folderConfigSchema.parse(fc);
39209
- folders[path8] = { base_counter: validated.baseCounter, label: validated.label };
39238
+ folders[path8] = folderConfigSchema.parse(fc);
39210
39239
  }
39211
39240
  const foldersConfig = {
39212
39241
  active_folder: tasks.active,
@@ -41033,7 +41062,7 @@ var init_mod = __esm(() => {
41033
41062
  init_config3();
41034
41063
  });
41035
41064
 
41036
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/logger.js
41065
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/logger.js
41037
41066
  function toLogTapeLevel(level) {
41038
41067
  return level === "warn" ? "warning" : level;
41039
41068
  }
@@ -42586,7 +42615,7 @@ var require_src = __commonJS((exports) => {
42586
42615
  };
42587
42616
  });
42588
42617
 
42589
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/telemetry/sdk.js
42618
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/sdk.js
42590
42619
  function getTelemetryConfig(configPartial = {}) {
42591
42620
  return {
42592
42621
  enabled: configPartial.enabled ?? CONFIG_DEFAULTS.enabled,
@@ -42622,7 +42651,7 @@ var init_sdk = __esm(() => {
42622
42651
  resolvedConfig = getTelemetryConfig();
42623
42652
  });
42624
42653
 
42625
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
42654
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
42626
42655
  function isSuppressed(tracer2) {
42627
42656
  return tracer2 === undefined && !getResolvedConfig().enabled;
42628
42657
  }
@@ -42662,7 +42691,7 @@ var init_tracing2 = __esm(() => {
42662
42691
  import_api2 = __toESM(require_src(), 1);
42663
42692
  });
42664
42693
 
42665
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
42694
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
42666
42695
  function getMeter() {
42667
42696
  return import_api3.metrics.getMeter(METER_NAME, METER_VERSION);
42668
42697
  }
@@ -42759,7 +42788,7 @@ var init_metrics = __esm(() => {
42759
42788
  instruments = {};
42760
42789
  });
42761
42790
 
42762
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/event-bus/event-bus.js
42791
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/event-bus.js
42763
42792
  function busLogger() {
42764
42793
  if (!_busLogger)
42765
42794
  _busLogger = getLogger2("event-bus");
@@ -43004,7 +43033,7 @@ var init_event_bus = __esm(() => {
43004
43033
  init_metrics();
43005
43034
  });
43006
43035
 
43007
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/event-bus/default-observers.js
43036
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/default-observers.js
43008
43037
  function obsLogger() {
43009
43038
  if (!_obsLogger)
43010
43039
  _obsLogger = getLogger2("event-bus.observers");
@@ -43068,7 +43097,7 @@ var init_default_observers = __esm(() => {
43068
43097
  init_event_bus();
43069
43098
  });
43070
43099
 
43071
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/event-bus/file-observer.js
43100
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/file-observer.js
43072
43101
  function parentDir(filePath) {
43073
43102
  const idx = filePath.lastIndexOf("/");
43074
43103
  return idx <= 0 ? "." : filePath.slice(0, idx);
@@ -43166,7 +43195,22 @@ var init_file_observer = __esm(() => {
43166
43195
  init_logger3();
43167
43196
  });
43168
43197
 
43169
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/scheduler/node.js
43198
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/internals/drain.js
43199
+ function settleWithin(promise2, deadline) {
43200
+ const remaining = deadline - Date.now();
43201
+ if (remaining <= 0)
43202
+ return Promise.resolve();
43203
+ const { promise: settled, resolve } = Promise.withResolvers();
43204
+ const timer = setTimeout(resolve, remaining);
43205
+ const done = () => {
43206
+ clearTimeout(timer);
43207
+ resolve();
43208
+ };
43209
+ promise2.then(done, done);
43210
+ return settled;
43211
+ }
43212
+
43213
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler/node.js
43170
43214
  function parseInterval(cron) {
43171
43215
  const trimmed = cron.trim();
43172
43216
  const num = Number(trimmed);
@@ -43189,8 +43233,16 @@ function parseInterval(cron) {
43189
43233
 
43190
43234
  class NodeSchedulerAdapter {
43191
43235
  entries = [];
43236
+ drainTimeoutMs;
43192
43237
  running = false;
43193
- constructor() {}
43238
+ inflight = new Set;
43239
+ constructor(config4 = {}) {
43240
+ const { drainTimeoutMs } = config4;
43241
+ if (drainTimeoutMs !== undefined && (!Number.isFinite(drainTimeoutMs) || drainTimeoutMs < 0)) {
43242
+ throw new RangeError(`NodeSchedulerAdapter drainTimeoutMs must be a non-negative finite number; received ${drainTimeoutMs}`);
43243
+ }
43244
+ this.drainTimeoutMs = drainTimeoutMs ?? 30000;
43245
+ }
43194
43246
  register(cron, action) {
43195
43247
  this.entries.push({ cron, action });
43196
43248
  if (this.running) {
@@ -43216,12 +43268,23 @@ class NodeSchedulerAdapter {
43216
43268
  entry.timer = undefined;
43217
43269
  }
43218
43270
  }
43271
+ const deadline = Date.now() + this.drainTimeoutMs;
43272
+ for (const p of [...this.inflight]) {
43273
+ await settleWithin(p, deadline);
43274
+ }
43219
43275
  }
43220
43276
  startEntry(entry) {
43221
43277
  if (entry.timer)
43222
43278
  return;
43223
43279
  const interval = parseInterval(entry.cron);
43224
- entry.timer = setInterval(this._onScheduledTick.bind(this, entry), interval);
43280
+ entry.timer = setInterval(() => {
43281
+ const tick = this._onScheduledTick(entry);
43282
+ this.inflight.add(tick);
43283
+ const cleanup = () => {
43284
+ this.inflight.delete(tick);
43285
+ };
43286
+ tick.then(cleanup, cleanup);
43287
+ }, interval);
43225
43288
  }
43226
43289
  async _onScheduledTick(entry) {
43227
43290
  const startMs = performance.now();
@@ -43240,7 +43303,7 @@ var init_node3 = __esm(() => {
43240
43303
  init_metrics();
43241
43304
  });
43242
43305
 
43243
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/scheduler-node.js
43306
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler-node.js
43244
43307
  var exports_scheduler_node = {};
43245
43308
  __export(exports_scheduler_node, {
43246
43309
  NodeSchedulerAdapter: () => NodeSchedulerAdapter
@@ -50188,8 +50251,17 @@ function parseFeature(content) {
50188
50251
  }
50189
50252
 
50190
50253
  // ../../packages/domain/src/bdd/coverage.ts
50254
+ function stripScenarioPrefixes(title) {
50255
+ let out = title.trim();
50256
+ let previous;
50257
+ do {
50258
+ previous = out;
50259
+ out = out.replace(/^\[[^\]]*\]\s*/, "").replace(/^Scenario:\s*/i, "").replace(/^R\d+\s*[:\-\u2014]?\s*/, "").trim();
50260
+ } while (out !== previous);
50261
+ return out;
50262
+ }
50191
50263
  function normalizeTitle(title) {
50192
- return title.replace(/^(R\d+)\s*[:\-\u2014]?\s*/, "").trim().toLowerCase().replace(/[\u0027\u2018\u2019\u201c\u201d]/g, "").replace(/\s+/g, " ").trim();
50264
+ return stripScenarioPrefixes(title).replace(/^(R\d+)\s*[:\-\u2014]?\s*/, "").trim().toLowerCase().replace(/[\u0027\u2018\u2019\u201c\u201d]/g, "").replace(/\s+/g, " ").trim();
50193
50265
  }
50194
50266
  function checkAcCoverage(featureAc, taskAc, taskChecklist) {
50195
50267
  const featureParsed = parseForCoverage(featureAc);
@@ -50935,7 +51007,7 @@ var init_drizzle_zod = __esm(() => {
50935
51007
  };
50936
51008
  });
50937
51009
 
50938
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
51010
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
50939
51011
  function sqlExpressionToText(value) {
50940
51012
  if (typeof value !== "object" || value === null || !("queryChunks" in value)) {
50941
51013
  return;
@@ -50958,7 +51030,7 @@ function getDrizzleTableName(table3) {
50958
51030
  return String(table3[nameSym]);
50959
51031
  }
50960
51032
 
50961
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
51033
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
50962
51034
  function quoteIdent(name) {
50963
51035
  return `"${name.replace(/"/g, '""')}"`;
50964
51036
  }
@@ -51052,7 +51124,7 @@ var init_ddl = __esm(() => {
51052
51124
  init_sqlite_core();
51053
51125
  });
51054
51126
 
51055
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
51127
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
51056
51128
  function defineTable(name, columns2) {
51057
51129
  const table3 = sqliteTable(name, columns2);
51058
51130
  let insert2;
@@ -51086,7 +51158,7 @@ var init_define_table = __esm(() => {
51086
51158
  init_ddl();
51087
51159
  });
51088
51160
 
51089
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.14+eb0d628435e6547b/node_modules/@gobing-ai/ts-db/dist/schema/index.js
51161
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/index.js
51090
51162
  var init_schema = __esm(() => {
51091
51163
  init_sqlite_core();
51092
51164
  init_define_table();
@@ -51711,7 +51783,7 @@ var init_dao = __esm(() => {
51711
51783
  init_workspace_dao();
51712
51784
  });
51713
51785
 
51714
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/errors.js
51786
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/errors.js
51715
51787
  var WorkflowValidationError, FSMError, RunCollisionError, WorkflowResumeError;
51716
51788
  var init_errors6 = __esm(() => {
51717
51789
  WorkflowValidationError = class WorkflowValidationError extends Error {
@@ -51746,12 +51818,12 @@ var init_errors6 = __esm(() => {
51746
51818
  };
51747
51819
  });
51748
51820
 
51749
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/event-bus/index.js
51821
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/index.js
51750
51822
  var init_event_bus2 = __esm(() => {
51751
51823
  init_event_bus();
51752
51824
  });
51753
51825
 
51754
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/api-client.js
51826
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/api-client.js
51755
51827
  function sanitizeUrlForObservability(url2) {
51756
51828
  try {
51757
51829
  const parsed = new URL(url2);
@@ -51981,12 +52053,12 @@ var init_api_client = __esm(() => {
51981
52053
  };
51982
52054
  });
51983
52055
 
51984
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
52056
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
51985
52057
  var init_telemetry = __esm(() => {
51986
52058
  init_tracing2();
51987
52059
  });
51988
52060
 
51989
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/index.js
52061
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/index.js
51990
52062
  var init_dist6 = __esm(() => {
51991
52063
  init_api_client();
51992
52064
  init_event_bus2();
@@ -51994,7 +52066,7 @@ var init_dist6 = __esm(() => {
51994
52066
  init_telemetry();
51995
52067
  });
51996
52068
 
51997
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/run-lifecycle.js
52069
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/run-lifecycle.js
51998
52070
  function runtimeBuiltins(workflowName, stateOrNodeId, runId, transitionsTaken, mode) {
51999
52071
  return {
52000
52072
  workflow: workflowName,
@@ -52253,7 +52325,7 @@ var init_run_lifecycle = __esm(() => {
52253
52325
  ];
52254
52326
  });
52255
52327
 
52256
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema.js
52328
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema.js
52257
52329
  var RESERVED_VAR_NAMES, IDENTIFIER, VarsSchema, EnvSchema, ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema;
52258
52330
  var init_schema2 = __esm(() => {
52259
52331
  init_zod();
@@ -52337,7 +52409,7 @@ var init_schema2 = __esm(() => {
52337
52409
  WorkflowDefSchema = exports_external.union([StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema]);
52338
52410
  });
52339
52411
 
52340
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/config.js
52412
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/config.js
52341
52413
  async function loadWorkflowDef(path9, options = {}) {
52342
52414
  return parseWorkflowDef(await loadStructuredConfig(path9, options), path9);
52343
52415
  }
@@ -52496,7 +52568,7 @@ var init_config4 = __esm(() => {
52496
52568
  RUNTIME_TEMPLATE_NAMESPACES = new Set(RUNTIME_BUILTIN_KEYS);
52497
52569
  });
52498
52570
 
52499
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/extension/capability-registry.js
52571
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/capability-registry.js
52500
52572
  class CapabilityRegistry {
52501
52573
  kind;
52502
52574
  capabilities = new Map;
@@ -52527,7 +52599,7 @@ class CapabilityRegistry {
52527
52599
  }
52528
52600
  }
52529
52601
 
52530
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-path.js
52602
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-path.js
52531
52603
  function assertRelativeExtensionPath(path9, options = {}) {
52532
52604
  const where = options.sourceName !== undefined ? ` declared by "${options.sourceName}"` : "";
52533
52605
  if (/^([/\\]|[A-Za-z]:[/\\])/.test(path9)) {
@@ -52538,20 +52610,20 @@ function assertRelativeExtensionPath(path9, options = {}) {
52538
52610
  }
52539
52611
  }
52540
52612
 
52541
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-loader.js
52613
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-loader.js
52542
52614
  var init_extension_loader = () => {};
52543
52615
 
52544
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/extension/index.js
52616
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/index.js
52545
52617
  var init_extension = __esm(() => {
52546
52618
  init_extension_loader();
52547
52619
  });
52548
52620
 
52549
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.14+1afbae169bbe5102/node_modules/@gobing-ai/ts-runtime/dist/extension.js
52621
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension.js
52550
52622
  var init_extension2 = __esm(() => {
52551
52623
  init_extension();
52552
52624
  });
52553
52625
 
52554
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/host.js
52626
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/host.js
52555
52627
  class WorkflowEngineHost {
52556
52628
  lifecycleBus;
52557
52629
  actions = new CapabilityRegistry("workflow action");
@@ -52720,7 +52792,7 @@ var init_host = __esm(() => {
52720
52792
  init_errors6();
52721
52793
  });
52722
52794
 
52723
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
52795
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
52724
52796
  var WORKFLOW_ENGINE_SCHEMA_SQL;
52725
52797
  var init_schema_sql = __esm(() => {
52726
52798
  WORKFLOW_ENGINE_SCHEMA_SQL = `
@@ -52793,7 +52865,7 @@ CREATE TABLE IF NOT EXISTS action_runs (
52793
52865
  `.trim();
52794
52866
  });
52795
52867
 
52796
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/persistence.js
52868
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/persistence.js
52797
52869
  async function applyWorkflowEngineSchema(db2) {
52798
52870
  for (const statement of WORKFLOW_ENGINE_SCHEMA_SQL.split(";")) {
52799
52871
  const sql4 = statement.trim();
@@ -53082,7 +53154,7 @@ var init_persistence = __esm(() => {
53082
53154
  init_schema_sql();
53083
53155
  });
53084
53156
 
53085
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/variables.js
53157
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/variables.js
53086
53158
  function mergeVars(workflowVars = {}, overrideVars = {}) {
53087
53159
  return { ...workflowVars, ...overrideVars };
53088
53160
  }
@@ -53142,7 +53214,7 @@ var init_variables = __esm(() => {
53142
53214
  TEMPLATE_REF = /\$\{([^}]+)\}/g;
53143
53215
  });
53144
53216
 
53145
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/action-step.js
53217
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/action-step.js
53146
53218
  async function runActionStep(action, vars, deps) {
53147
53219
  const { host, persistence, lifecycle, stateOrNodeId, runId } = deps;
53148
53220
  const resolved = resolveTemplates(action.options ?? {}, {
@@ -53200,7 +53272,7 @@ var init_action_step = __esm(() => {
53200
53272
  init_variables();
53201
53273
  });
53202
53274
 
53203
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/state-machine.js
53275
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/state-machine.js
53204
53276
  class StateMachineDriver {
53205
53277
  options;
53206
53278
  constructor(options) {
@@ -53334,7 +53406,7 @@ var init_state_machine = __esm(() => {
53334
53406
  EMPTY_OUTCOME = { outcome: "completed", result: undefined };
53335
53407
  });
53336
53408
 
53337
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/transition-flow.js
53409
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/transition-flow.js
53338
53410
  class TransitionFlowDriver {
53339
53411
  options;
53340
53412
  constructor(options) {
@@ -53452,7 +53524,7 @@ var init_transition_flow = __esm(() => {
53452
53524
  init_variables();
53453
53525
  });
53454
53526
 
53455
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/service.js
53527
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/service.js
53456
53528
  class WorkflowService {
53457
53529
  host;
53458
53530
  persistence;
@@ -53669,7 +53741,7 @@ var init_service = __esm(() => {
53669
53741
  init_variables();
53670
53742
  });
53671
53743
 
53672
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/index.js
53744
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/index.js
53673
53745
  var init_dist7 = __esm(() => {
53674
53746
  init_config4();
53675
53747
  init_host();
@@ -53678,7 +53750,7 @@ var init_dist7 = __esm(() => {
53678
53750
  init_service();
53679
53751
  });
53680
53752
 
53681
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/errors.js
53753
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/errors.js
53682
53754
  var HistoryImportError;
53683
53755
  var init_errors7 = __esm(() => {
53684
53756
  HistoryImportError = class HistoryImportError extends Error {
@@ -53691,7 +53763,7 @@ var init_errors7 = __esm(() => {
53691
53763
  };
53692
53764
  });
53693
53765
 
53694
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
53766
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
53695
53767
  import { createHash } from "crypto";
53696
53768
  function stableJson(value) {
53697
53769
  if (Array.isArray(value)) {
@@ -53708,7 +53780,7 @@ function sha256(value) {
53708
53780
  }
53709
53781
  var init_hash = () => {};
53710
53782
 
53711
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
53783
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
53712
53784
  function redactValue(value, rules = DEFAULT_REDACTION_RULES) {
53713
53785
  if (typeof value === "string") {
53714
53786
  return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
@@ -53745,7 +53817,7 @@ var init_redaction = __esm(() => {
53745
53817
  ];
53746
53818
  });
53747
53819
 
53748
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
53820
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
53749
53821
  var HISTORY_IMPORT_SCHEMA_SQL;
53750
53822
  var init_schema_sql2 = __esm(() => {
53751
53823
  HISTORY_IMPORT_SCHEMA_SQL = `
@@ -53832,7 +53904,7 @@ CREATE TABLE IF NOT EXISTS history_etl_openclaw (
53832
53904
  `.trim();
53833
53905
  });
53834
53906
 
53835
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
53907
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
53836
53908
  function firstString(...values) {
53837
53909
  for (const value of values) {
53838
53910
  if (typeof value === "string" && value.length > 0)
@@ -53897,11 +53969,59 @@ function sourceDefinition(source, displayName, defaultRoots, filePatterns) {
53897
53969
  };
53898
53970
  }
53899
53971
  function getSourceDefinition(source) {
53900
- return SOURCE_DEFINITIONS[source];
53972
+ const definition = SOURCE_DEFINITIONS[source];
53973
+ if (definition === undefined) {
53974
+ throw new HistoryImportError(`Unknown LLM JSONL source: ${source}`, { source });
53975
+ }
53976
+ return definition;
53977
+ }
53978
+ function validateSourceDefinition(definition) {
53979
+ const requiredFields = [
53980
+ "source",
53981
+ "displayName",
53982
+ "defaultRoots",
53983
+ "filePatterns",
53984
+ "targetTable",
53985
+ "splitConfig",
53986
+ "fieldMap",
53987
+ "fieldTransforms",
53988
+ "schema"
53989
+ ];
53990
+ for (const field of requiredFields) {
53991
+ if (definition[field] === undefined || definition[field] === null) {
53992
+ throw new HistoryImportError(`Source definition is missing required field: ${String(field)}`, {
53993
+ source: definition.source,
53994
+ field: String(field)
53995
+ });
53996
+ }
53997
+ }
53998
+ if (definition.filePatterns.length === 0) {
53999
+ throw new HistoryImportError("Source definition must declare at least one file pattern", {
54000
+ source: definition.source,
54001
+ field: "filePatterns"
54002
+ });
54003
+ }
54004
+ assertValidTable(definition.targetTable, definition.source);
54005
+ if (definition.splitConfig.mode !== "one-to-one" && definition.splitConfig.targetTable !== undefined) {
54006
+ assertValidTable(definition.splitConfig.targetTable, definition.source);
54007
+ }
54008
+ return definition;
53901
54009
  }
53902
- var sourceRecordSchema, SOURCE_DEFINITIONS;
54010
+ function resolveSourceDefinition(input) {
54011
+ if (typeof input === "string") {
54012
+ return getSourceDefinition(input);
54013
+ }
54014
+ return validateSourceDefinition(input);
54015
+ }
54016
+ function assertValidTable(table3, source) {
54017
+ if (!VALID_TABLE_NAME.test(table3)) {
54018
+ throw new HistoryImportError(`Invalid history ETL target table for source "${source}": ${table3}. Must match ${VALID_TABLE_NAME.source}.`, { source, table: table3 });
54019
+ }
54020
+ }
54021
+ var sourceRecordSchema, VALID_TABLE_NAME, SOURCE_DEFINITIONS;
53903
54022
  var init_sources = __esm(() => {
53904
54023
  init_zod();
54024
+ init_errors7();
53905
54025
  sourceRecordSchema = exports_external.object({
53906
54026
  source_record_id: exports_external.string().min(1),
53907
54027
  created_at: exports_external.string().min(1),
@@ -53909,6 +54029,7 @@ var init_sources = __esm(() => {
53909
54029
  role: exports_external.string().optional(),
53910
54030
  model: exports_external.string().optional()
53911
54031
  }).passthrough();
54032
+ VALID_TABLE_NAME = /^history_etl_[a-z_]+$/;
53912
54033
  SOURCE_DEFINITIONS = {
53913
54034
  pi: sourceDefinition("pi", "Pi", [".pi/history", ".pi"], ["*.jsonl", "*.json"]),
53914
54035
  claude: sourceDefinition("claude", "Claude Code", [".claude/projects", ".claude"], ["*.jsonl"]),
@@ -53920,7 +54041,7 @@ var init_sources = __esm(() => {
53920
54041
  };
53921
54042
  });
53922
54043
 
53923
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/importer.js
54044
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/importer.js
53924
54045
  async function applyHistoryImportSchema(db2) {
53925
54046
  for (const statement of HISTORY_IMPORT_SCHEMA_SQL.split(";")) {
53926
54047
  const sql4 = statement.trim();
@@ -53929,14 +54050,35 @@ async function applyHistoryImportSchema(db2) {
53929
54050
  }
53930
54051
  }
53931
54052
  }
54053
+ async function ensureTargetTables(db2, definition) {
54054
+ const tables = new Set([targetTableFor(definition.targetTable)]);
54055
+ if (definition.splitConfig.mode !== "one-to-one" && definition.splitConfig.targetTable !== undefined) {
54056
+ tables.add(targetTableFor(definition.splitConfig.targetTable));
54057
+ }
54058
+ for (const table3 of tables) {
54059
+ await db2.exec(ETL_TABLE_DDL(table3));
54060
+ }
54061
+ }
54062
+ function ETL_TABLE_DDL(table3) {
54063
+ return `CREATE TABLE IF NOT EXISTS ${table3} (
54064
+ record_hash TEXT PRIMARY KEY,
54065
+ source_file TEXT NOT NULL,
54066
+ source_line INTEGER NOT NULL,
54067
+ split_index INTEGER NOT NULL,
54068
+ payload_json TEXT NOT NULL,
54069
+ imported_at TEXT NOT NULL
54070
+ );`;
54071
+ }
53932
54072
  async function runJsonlImport(source, options) {
53933
- const definition = getSourceDefinition(source);
54073
+ const definition = resolveSourceDefinition(source);
54074
+ const resolvedSource = definition.source;
53934
54075
  const fileSystem = options.fileSystem ?? createNodeFileSystem3();
53935
54076
  await applyHistoryImportSchema(options.db);
54077
+ await ensureTargetTables(options.db, definition);
53936
54078
  const mode = options.mode ?? "incremental";
53937
- const files = await discoverFiles(definition, options.roots, options.files, fileSystem);
54079
+ const files = await discoverFiles(definition, options.roots, options.files, fileSystem, options.paths);
53938
54080
  if (mode === "full" && !options.dryRun) {
53939
- await resetCheckpoints(options.db, source, files);
54081
+ await resetCheckpoints(options.db, resolvedSource, files);
53940
54082
  }
53941
54083
  const parseErrors = [];
53942
54084
  const validationErrors = [];
@@ -53945,7 +54087,7 @@ async function runJsonlImport(source, options) {
53945
54087
  let skippedDuplicates = 0;
53946
54088
  let checkpointUpdates = 0;
53947
54089
  for (const file2 of files) {
53948
- const checkpoint = mode === "incremental" ? await readCheckpoint(options.db, source, file2) : 0;
54090
+ const checkpoint = mode === "incremental" ? await readCheckpoint(options.db, resolvedSource, file2) : 0;
53949
54091
  let lineNumber = 0;
53950
54092
  for await (const rawLine of readLines(fileSystem, file2)) {
53951
54093
  lineNumber += 1;
@@ -53963,7 +54105,7 @@ async function runJsonlImport(source, options) {
53963
54105
  if (split === undefined)
53964
54106
  continue;
53965
54107
  const normalized = normalizeRecord(definition, split.raw, {
53966
- source,
54108
+ source: resolvedSource,
53967
54109
  sourceFile: file2,
53968
54110
  sourceLine: lineNumber,
53969
54111
  splitIndex
@@ -53980,7 +54122,7 @@ async function runJsonlImport(source, options) {
53980
54122
  const redacted = redactRecord(parsed.data, options.redactionRules);
53981
54123
  lineSucceeded = true;
53982
54124
  const recordHash = sha256({
53983
- source,
54125
+ source: resolvedSource,
53984
54126
  sourceFile: file2,
53985
54127
  sourceLine: lineNumber,
53986
54128
  splitIndex,
@@ -53992,18 +54134,18 @@ async function runJsonlImport(source, options) {
53992
54134
  }
53993
54135
  if (!options.dryRun) {
53994
54136
  await insertRecord(options.db, split.targetTable, recordHash, file2, lineNumber, splitIndex, redacted, options.now);
53995
- await insertLedger(options.db, recordHash, source, file2, lineNumber, splitIndex, split.targetTable, options.now);
54137
+ await insertLedger(options.db, recordHash, resolvedSource, file2, lineNumber, splitIndex, split.targetTable, options.now);
53996
54138
  }
53997
54139
  importedRecords += 1;
53998
54140
  }
53999
54141
  if (lineSucceeded && !options.dryRun) {
54000
- await writeCheckpoint(options.db, source, file2, lineNumber, options.now);
54142
+ await writeCheckpoint(options.db, resolvedSource, file2, lineNumber, options.now);
54001
54143
  checkpointUpdates += 1;
54002
54144
  }
54003
54145
  }
54004
54146
  }
54005
54147
  return {
54006
- source,
54148
+ source: resolvedSource,
54007
54149
  mode,
54008
54150
  scannedFiles: files.length,
54009
54151
  processedLines,
@@ -54064,11 +54206,12 @@ function normalizeRecord(definition, raw, context4) {
54064
54206
  normalized.split_index = context4.splitIndex;
54065
54207
  return normalized;
54066
54208
  }
54067
- async function discoverFiles(definition, roots, files, fileSystem) {
54209
+ async function discoverFiles(definition, roots, files, fileSystem, paths) {
54068
54210
  if (files !== undefined && files.length > 0) {
54069
54211
  return files.map((file2) => resolvePath4(file2)).sort();
54070
54212
  }
54071
- const resolvedRoots = (roots ?? definition.defaultRoots).map((root) => resolvePath4(root));
54213
+ const ambient = paths ?? ambientRuntimePaths2();
54214
+ const resolvedRoots = roots !== undefined ? roots.map((root) => resolvePath4(ambient.cwd, root)) : definition.defaultRoots.map((root) => resolvePath4(ambient.home, root));
54072
54215
  const found = new Set;
54073
54216
  for (const root of resolvedRoots) {
54074
54217
  if (!await fileSystem.exists(root))
@@ -54146,7 +54289,6 @@ async function* readLines(fileSystem, file2) {
54146
54289
  yield line;
54147
54290
  }
54148
54291
  }
54149
- var VALID_TABLE_NAME;
54150
54292
  var init_importer = __esm(() => {
54151
54293
  init_dist5();
54152
54294
  init_errors7();
@@ -54154,16 +54296,15 @@ var init_importer = __esm(() => {
54154
54296
  init_redaction();
54155
54297
  init_schema_sql2();
54156
54298
  init_sources();
54157
- VALID_TABLE_NAME = /^history_etl_[a-z_]+$/;
54158
54299
  });
54159
54300
 
54160
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.14+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/index.js
54301
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/index.js
54161
54302
  var init_dist8 = __esm(() => {
54162
54303
  init_importer();
54163
54304
  init_schema_sql2();
54164
54305
  });
54165
54306
 
54166
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/extensions.js
54307
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/extensions.js
54167
54308
  function collectExtensions(sourceName, sourceDir, extensions) {
54168
54309
  if (extensions === undefined)
54169
54310
  return [];
@@ -54179,7 +54320,7 @@ var init_extensions = __esm(() => {
54179
54320
  init_dist5();
54180
54321
  });
54181
54322
 
54182
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/types.js
54323
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/types.js
54183
54324
  function createFinding(rule, message, filePath, extras = {}) {
54184
54325
  return {
54185
54326
  ruleId: rule.id,
@@ -54250,7 +54391,7 @@ var init_types3 = __esm(() => {
54250
54391
  });
54251
54392
  });
54252
54393
 
54253
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/loader.js
54394
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/loader.js
54254
54395
  async function loadPreset(name, options) {
54255
54396
  const merged = await buildMergedRoots(options.roots.map((root) => resolvePath4(root)), options.fileSystem);
54256
54397
  const presetPath = findMergedPreset(merged, name);
@@ -54465,7 +54606,7 @@ var init_loader2 = __esm(() => {
54465
54606
  FIX_MODE_AUTHORITY = { none: 0, suggest: 1, auto: 2 };
54466
54607
  });
54467
54608
 
54468
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/test-stub-fixer.js
54609
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/test-stub-fixer.js
54469
54610
  function normalizeFindingPath(filePath) {
54470
54611
  if (!filePath || isAbsolutePath2(filePath))
54471
54612
  return null;
@@ -54530,7 +54671,7 @@ var init_test_stub_fixer = __esm(() => {
54530
54671
  realFileSystem = createNodeFileSystem3();
54531
54672
  });
54532
54673
 
54533
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/fixers.js
54674
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/fixers.js
54534
54675
  function registerBuiltinFixers(host, exec) {
54535
54676
  const regexFixer = new RegexFixerProvider;
54536
54677
  const pathFixer = new PathFixerProvider;
@@ -54733,7 +54874,7 @@ var init_fixers = __esm(() => {
54733
54874
  };
54734
54875
  });
54735
54876
 
54736
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
54877
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
54737
54878
  function resolveAgentName(input) {
54738
54879
  if (isCanonicalName(input))
54739
54880
  return input;
@@ -54984,7 +55125,7 @@ var init_shims = __esm(() => {
54984
55125
  ALIAS_TO_CANONICAL = Object.fromEntries(Object.values(AGENT_SHIMS).flatMap((shim) => (shim.aliases ?? []).map((alias3) => [alias3, shim.name])));
54985
55126
  });
54986
55127
 
54987
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/identity.js
55128
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/identity.js
54988
55129
  function buildIdentityPreamble(ctx) {
54989
55130
  const sections = [
54990
55131
  `You are agent \`${ctx.agentId}\` (${ctx.agentType}) in workspace \`${ctx.workspace}\`.`
@@ -55044,7 +55185,7 @@ var init_identity = __esm(() => {
55044
55185
  init_dist5();
55045
55186
  });
55046
55187
 
55047
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/slash-command.js
55188
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/slash-command.js
55048
55189
  function isClaudeStyleSlashCommand(input) {
55049
55190
  return SLASH_COMMAND_RE.test(input);
55050
55191
  }
@@ -55072,7 +55213,15 @@ var init_slash_command = __esm(() => {
55072
55213
  SLASH_COMMAND_RE = /^\/([a-zA-Z0-9._-]+):([a-zA-Z0-9._-]+)(\s.*)?$/;
55073
55214
  });
55074
55215
 
55075
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
55216
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
55217
+ function buildCorrelationEnv(correlation) {
55218
+ return {
55219
+ [AGENT_RUN_ID_ENV]: correlation.runId,
55220
+ [AGENT_EXECUTION_ID_ENV]: correlation.executionId,
55221
+ ...correlation.actionId !== undefined ? { [AGENT_ACTION_ID_ENV]: correlation.actionId } : {}
55222
+ };
55223
+ }
55224
+
55076
55225
  class AiRunner {
55077
55226
  processExecutor;
55078
55227
  defaultCwd;
@@ -55131,6 +55280,7 @@ class AiRunner {
55131
55280
  label,
55132
55281
  ...options.correlation !== undefined ? { correlation: options.correlation } : {}
55133
55282
  });
55283
+ const correlationEnv = options.correlation === undefined ? undefined : buildCorrelationEnv(options.correlation);
55134
55284
  const result = await this.processExecutor.run({
55135
55285
  command: command.command,
55136
55286
  args: command.args,
@@ -55139,6 +55289,7 @@ class AiRunner {
55139
55289
  forceBuffered,
55140
55290
  cwd: options.cwd ?? this.defaultCwd,
55141
55291
  timeout: options.timeout ?? this.defaultTimeout,
55292
+ ...correlationEnv !== undefined ? { env: correlationEnv } : {},
55142
55293
  ...options.signal !== undefined ? { signal: options.signal } : {},
55143
55294
  ...options.onOutput !== undefined ? { onOutput: options.onOutput } : {}
55144
55295
  });
@@ -55189,6 +55340,7 @@ function applyIdentityPreamble(agent, promptOptions, context4) {
55189
55340
  ${promptOptions.input}`;
55190
55341
  return { ...promptOptions, input };
55191
55342
  }
55343
+ var AGENT_RUN_ID_ENV = "SPUR_RUN_ID", AGENT_EXECUTION_ID_ENV = "SPUR_EXECUTION_ID", AGENT_ACTION_ID_ENV = "SPUR_ACTION_ID";
55192
55344
  var init_ai_runner = __esm(() => {
55193
55345
  init_dist6();
55194
55346
  init_dist5();
@@ -55197,7 +55349,7 @@ var init_ai_runner = __esm(() => {
55197
55349
  init_slash_command();
55198
55350
  });
55199
55351
 
55200
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
55352
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
55201
55353
  class AgentDetector {
55202
55354
  runner;
55203
55355
  timeout;
@@ -55273,7 +55425,7 @@ var init_agent_detector = __esm(() => {
55273
55425
  VERSION_PATTERN = /(?<version>\d+\.\d+(?:\.\d+)?)/;
55274
55426
  });
55275
55427
 
55276
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/agent-spec.js
55428
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agent-spec.js
55277
55429
  function validateAgentId(id) {
55278
55430
  if (!/^[a-z][a-z0-9_-]{1,63}$/.test(id)) {
55279
55431
  throw new ValueError(`Invalid agent id "${id}": expected 2-64 chars, lowercase alphanumeric, "_" or "-"`);
@@ -55370,7 +55522,7 @@ var init_agent_spec = __esm(() => {
55370
55522
  };
55371
55523
  });
55372
55524
 
55373
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/agents/auth-shims.js
55525
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agents/auth-shims.js
55374
55526
  function isNonEmpty(value) {
55375
55527
  return value !== undefined && value.trim().length > 0;
55376
55528
  }
@@ -55475,7 +55627,7 @@ var init_auth_shims = __esm(() => {
55475
55627
  };
55476
55628
  });
55477
55629
 
55478
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/model-health-probe.js
55630
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/model-health-probe.js
55479
55631
  class ModelHealthProbeRegistry {
55480
55632
  probes = new Map;
55481
55633
  register(providerPrefix, probe) {
@@ -55583,7 +55735,7 @@ var init_model_health_probe = __esm(() => {
55583
55735
  };
55584
55736
  });
55585
55737
 
55586
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/doctor-runner.js
55738
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/doctor-runner.js
55587
55739
  class DoctorRunner {
55588
55740
  detector;
55589
55741
  runner;
@@ -55720,15 +55872,15 @@ var init_doctor_runner = __esm(() => {
55720
55872
  init_model_health_probe();
55721
55873
  });
55722
55874
 
55723
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/events.js
55875
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/events.js
55724
55876
  var init_events = () => {};
55725
55877
 
55726
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/messages.js
55878
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/messages.js
55727
55879
  function formatMessage(msg) {
55728
55880
  return `[task from=${msg.fromId ?? "operator"} id=${msg.id}] ${msg.body}`;
55729
55881
  }
55730
55882
 
55731
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/team-agent-process.js
55883
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/team-agent-process.js
55732
55884
  import { Buffer as Buffer5 } from "buffer";
55733
55885
 
55734
55886
  class TeamAgentProcess {
@@ -55862,7 +56014,7 @@ var init_team_agent_process = __esm(() => {
55862
56014
  init_dist5();
55863
56015
  });
55864
56016
 
55865
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/team-orchestrator.js
56017
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/team-orchestrator.js
55866
56018
  class TeamOrchestrator {
55867
56019
  configDir;
55868
56020
  inbox;
@@ -55991,7 +56143,7 @@ var init_team_orchestrator = __esm(() => {
55991
56143
  init_team_agent_process();
55992
56144
  });
55993
56145
 
55994
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.14+127e896e9a498407/node_modules/@gobing-ai/ts-ai-runner/dist/index.js
56146
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/index.js
55995
56147
  var exports_dist3 = {};
55996
56148
  __export(exports_dist3, {
55997
56149
  validateAgentId: () => validateAgentId,
@@ -56022,7 +56174,10 @@ __export(exports_dist3, {
56022
56174
  DEFAULT_PROBE_TIMEOUT_MS: () => DEFAULT_PROBE_TIMEOUT_MS,
56023
56175
  AiRunner: () => AiRunner,
56024
56176
  AgentDetector: () => AgentDetector,
56025
- AGENT_SHIMS: () => AGENT_SHIMS
56177
+ AGENT_SHIMS: () => AGENT_SHIMS,
56178
+ AGENT_RUN_ID_ENV: () => AGENT_RUN_ID_ENV,
56179
+ AGENT_EXECUTION_ID_ENV: () => AGENT_EXECUTION_ID_ENV,
56180
+ AGENT_ACTION_ID_ENV: () => AGENT_ACTION_ID_ENV
56026
56181
  });
56027
56182
  var init_dist9 = __esm(() => {
56028
56183
  init_agent_detector();
@@ -56039,7 +56194,7 @@ var init_dist9 = __esm(() => {
56039
56194
  init_team_orchestrator();
56040
56195
  });
56041
56196
 
56042
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/config-access.js
56197
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/config-access.js
56043
56198
  function stringArray(value) {
56044
56199
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : undefined;
56045
56200
  }
@@ -56077,7 +56232,7 @@ function parseInlineFlags(source) {
56077
56232
  return { flags, rest: source.slice(match[0].length) };
56078
56233
  }
56079
56234
 
56080
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/glob-match.js
56235
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/glob-match.js
56081
56236
  function matchesAny(path9, patterns) {
56082
56237
  if (patterns === undefined || patterns.length === 0)
56083
56238
  return true;
@@ -56125,7 +56280,7 @@ function escapeRegExp(value) {
56125
56280
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
56126
56281
  }
56127
56282
 
56128
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-discovery.js
56283
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-discovery.js
56129
56284
  async function discoverFiles2(options) {
56130
56285
  const fs3 = options.fs ?? createNodeFileSystem3();
56131
56286
  const allFiles = await walkDir2(options.workdir, fs3, DEFAULT_EXCLUDES);
@@ -56153,12 +56308,12 @@ var init_file_discovery = __esm(() => {
56153
56308
  DEFAULT_EXCLUDES = new Set([".git", "node_modules", "dist", ".coverage", ".astro", ".wrangler"]);
56154
56309
  });
56155
56310
 
56156
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-utils.js
56311
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-utils.js
56157
56312
  var init_file_utils = __esm(() => {
56158
56313
  init_file_discovery();
56159
56314
  });
56160
56315
 
56161
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/agent-detection-evaluator.js
56316
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/agent-detection-evaluator.js
56162
56317
  class AgentDetectionEvaluator {
56163
56318
  detector;
56164
56319
  constructor(detector = new AgentDetector) {
@@ -56186,7 +56341,7 @@ var init_agent_detection_evaluator = __esm(() => {
56186
56341
  init_file_utils();
56187
56342
  });
56188
56343
 
56189
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/coverage-gate-evaluator.js
56344
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/coverage-gate-evaluator.js
56190
56345
  class CoverageGateEvaluator {
56191
56346
  constructor() {}
56192
56347
  async evaluate(rule, context4) {
@@ -56270,7 +56425,7 @@ var init_coverage_gate_evaluator = __esm(() => {
56270
56425
  init_file_utils();
56271
56426
  });
56272
56427
 
56273
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/exit-code-evaluator.js
56428
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/exit-code-evaluator.js
56274
56429
  class ExitCodeEvaluator {
56275
56430
  executor;
56276
56431
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -56306,7 +56461,7 @@ var init_exit_code_evaluator = __esm(() => {
56306
56461
  init_file_utils();
56307
56462
  });
56308
56463
 
56309
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/forbidden-import-evaluator.js
56464
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/forbidden-import-evaluator.js
56310
56465
  class ForbiddenImportEvaluator {
56311
56466
  constructor() {}
56312
56467
  async evaluate(rule, context4) {
@@ -56387,7 +56542,7 @@ var init_forbidden_import_evaluator = __esm(() => {
56387
56542
  init_file_utils();
56388
56543
  });
56389
56544
 
56390
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/import-boundary-evaluator.js
56545
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/import-boundary-evaluator.js
56391
56546
  class ImportBoundaryEvaluator {
56392
56547
  async evaluate(rule, context4) {
56393
56548
  const config4 = rule.evaluator.config ?? {};
@@ -56480,7 +56635,7 @@ var init_import_boundary_evaluator = __esm(() => {
56480
56635
  init_file_utils();
56481
56636
  });
56482
56637
 
56483
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/path-evaluator.js
56638
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/path-evaluator.js
56484
56639
  class PathEvaluator {
56485
56640
  constructor() {}
56486
56641
  async evaluate(rule, context4) {
@@ -56541,7 +56696,7 @@ var init_path_evaluator = __esm(() => {
56541
56696
  init_file_utils();
56542
56697
  });
56543
56698
 
56544
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/regex-evaluator.js
56699
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/regex-evaluator.js
56545
56700
  class RegexEvaluator {
56546
56701
  constructor() {}
56547
56702
  async evaluate(rule, context4) {
@@ -56619,7 +56774,7 @@ var init_regex_evaluator = __esm(() => {
56619
56774
  init_file_utils();
56620
56775
  });
56621
56776
 
56622
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/ripgrep-evaluator.js
56777
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/ripgrep-evaluator.js
56623
56778
  class RipgrepEvaluator {
56624
56779
  executor;
56625
56780
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -56712,7 +56867,7 @@ var init_ripgrep_evaluator = __esm(() => {
56712
56867
  init_file_utils();
56713
56868
  });
56714
56869
 
56715
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/schema-artifact-evaluator.js
56870
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/schema-artifact-evaluator.js
56716
56871
  class SchemaArtifactEvaluator {
56717
56872
  constructor() {}
56718
56873
  async evaluate(rule, context4) {
@@ -56790,7 +56945,7 @@ var init_schema_artifact_evaluator = __esm(() => {
56790
56945
  init_file_utils();
56791
56946
  });
56792
56947
 
56793
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/secrets-scanner-evaluator.js
56948
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/secrets-scanner-evaluator.js
56794
56949
  class SecretsScannerEvaluator {
56795
56950
  constructor() {}
56796
56951
  async evaluate(rule, context4) {
@@ -56858,7 +57013,7 @@ var init_secrets_scanner_evaluator = __esm(() => {
56858
57013
  ALL_CATEGORIES = Object.keys(BUILTIN_PATTERNS);
56859
57014
  });
56860
57015
 
56861
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/sg-evaluator.js
57016
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/sg-evaluator.js
56862
57017
  class SgEvaluator {
56863
57018
  executor;
56864
57019
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -56955,7 +57110,7 @@ var init_sg_evaluator = __esm(() => {
56955
57110
  init_file_utils();
56956
57111
  });
56957
57112
 
56958
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/resolvers/test-path-resolver.js
57113
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/resolvers/test-path-resolver.js
56959
57114
  class TypeScriptTestPathResolver {
56960
57115
  name = "typescript";
56961
57116
  constructor() {}
@@ -57038,7 +57193,7 @@ function testify(rel) {
57038
57193
  return `${dir}test_${base2}`;
57039
57194
  }
57040
57195
 
57041
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/test-location-evaluator.js
57196
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/test-location-evaluator.js
57042
57197
  class TestLocationEvaluator {
57043
57198
  resolvers;
57044
57199
  constructor(resolvers) {
@@ -57113,7 +57268,7 @@ var init_test_location_evaluator = __esm(() => {
57113
57268
  TYPESCRIPT_FALLBACK = new TypeScriptTestPathResolver;
57114
57269
  });
57115
57270
 
57116
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/tsdoc-export-evaluator.js
57271
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/tsdoc-export-evaluator.js
57117
57272
  class TsdocExportEvaluator {
57118
57273
  constructor() {}
57119
57274
  async evaluate(rule, context4) {
@@ -57198,7 +57353,7 @@ var init_tsdoc_export_evaluator = __esm(() => {
57198
57353
  };
57199
57354
  });
57200
57355
 
57201
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/json.js
57356
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/json.js
57202
57357
  class JsonFormatter {
57203
57358
  constructor() {}
57204
57359
  format(result) {
@@ -57206,7 +57361,7 @@ class JsonFormatter {
57206
57361
  }
57207
57362
  }
57208
57363
 
57209
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/text.js
57364
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/text.js
57210
57365
  class TextFormatter {
57211
57366
  constructor() {}
57212
57367
  format(result) {
@@ -57220,7 +57375,7 @@ class TextFormatter {
57220
57375
  }
57221
57376
  }
57222
57377
 
57223
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/builtins.js
57378
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/builtins.js
57224
57379
  function registerBuiltins(host, executor) {
57225
57380
  const path9 = new PathEvaluator;
57226
57381
  host.evaluators.register("regex", new RegexEvaluator, "builtin");
@@ -57260,7 +57415,7 @@ var init_builtins = __esm(() => {
57260
57415
  init_tsdoc_export_evaluator();
57261
57416
  });
57262
57417
 
57263
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/rule-engine-host.js
57418
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/rule-engine-host.js
57264
57419
  class RuleEngineHost {
57265
57420
  evaluators;
57266
57421
  formatters;
@@ -57277,7 +57432,7 @@ var init_rule_engine_host = __esm(() => {
57277
57432
  init_extension2();
57278
57433
  });
57279
57434
 
57280
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/engine.js
57435
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/engine.js
57281
57436
  class RuleEngine {
57282
57437
  host;
57283
57438
  events;
@@ -57448,7 +57603,7 @@ var init_engine = __esm(() => {
57448
57603
  init_types3();
57449
57604
  });
57450
57605
 
57451
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/bundled-rules.js
57606
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/bundled-rules.js
57452
57607
  async function bundledRulesRoot() {
57453
57608
  if (cachedRoot2 !== undefined)
57454
57609
  return cachedRoot2;
@@ -57499,7 +57654,7 @@ var init_bundled_rules = __esm(() => {
57499
57654
  init_dist5();
57500
57655
  });
57501
57656
 
57502
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/db-adapter.js
57657
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/db-adapter.js
57503
57658
  class DbRulePersistenceAdapter {
57504
57659
  db;
57505
57660
  constructor(db2) {
@@ -57533,7 +57688,7 @@ class DbRulePersistenceAdapter {
57533
57688
  }
57534
57689
  }
57535
57690
 
57536
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
57691
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
57537
57692
  var RULE_ENGINE_SCHEMA_SQL = `
57538
57693
  CREATE TABLE IF NOT EXISTS rule_runs (
57539
57694
  id TEXT PRIMARY KEY,
@@ -57579,10 +57734,10 @@ CREATE TABLE IF NOT EXISTS rule_eval_runs (
57579
57734
  CREATE INDEX IF NOT EXISTS idx_rule_eval_runs_run_id ON rule_eval_runs (run_id);
57580
57735
  `;
57581
57736
 
57582
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/index.js
57737
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/index.js
57583
57738
  var init_persistence2 = () => {};
57584
57739
 
57585
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.14+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/index.js
57740
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/index.js
57586
57741
  var init_dist10 = __esm(() => {
57587
57742
  init_extensions();
57588
57743
  init_loader2();
@@ -57802,7 +57957,7 @@ ${SYSTEM_EVENTS_SCHEMA_SQL}
57802
57957
  ];
57803
57958
  });
57804
57959
 
57805
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/job-queue/db-job-queue.js
57960
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/job-queue/db-job-queue.js
57806
57961
  function queueLogger() {
57807
57962
  if (!_queueLogger)
57808
57963
  _queueLogger = getLogger2("job-queue");
@@ -57819,7 +57974,7 @@ class DBJobQueue {
57819
57974
  async enqueue(type, payload, options) {
57820
57975
  const id = await this.dao.enqueue(type, payload, options);
57821
57976
  getQueueJobEnqueuedTotal().add(1, { type });
57822
- await this.events?.emit("queue.job.enqueued", { jobId: id, type });
57977
+ await this.events?.emit("queue.job.enqueued", enqueuedDetail(id, type, options));
57823
57978
  return id;
57824
57979
  }
57825
57980
  async enqueueBatch(jobs) {
@@ -57827,7 +57982,8 @@ class DBJobQueue {
57827
57982
  getQueueJobEnqueuedTotal().add(jobs.length);
57828
57983
  if (this.events) {
57829
57984
  for (const [index2, jobId] of ids.entries()) {
57830
- await this.events.emit("queue.job.enqueued", { jobId, type: jobs[index2]?.type ?? "unknown" });
57985
+ const job = jobs[index2];
57986
+ await this.events.emit("queue.job.enqueued", enqueuedDetail(jobId, job?.type ?? "unknown", job));
57831
57987
  }
57832
57988
  }
57833
57989
  return ids;
@@ -57836,6 +57992,16 @@ class DBJobQueue {
57836
57992
  return this.dao.getStats();
57837
57993
  }
57838
57994
  }
57995
+ function enqueuedDetail(jobId, type, options) {
57996
+ const detail = { jobId, type, enqueuedAt: Date.now() };
57997
+ if (options && options.maxRetries !== undefined)
57998
+ detail.maxRetries = options.maxRetries;
57999
+ if (options && options.delay !== undefined)
58000
+ detail.delayMs = options.delay;
58001
+ if (options && options.ttlMs !== undefined)
58002
+ detail.ttlMs = options.ttlMs;
58003
+ return detail;
58004
+ }
57839
58005
 
57840
58006
  class DBQueueConsumer {
57841
58007
  dao;
@@ -57851,6 +58017,7 @@ class DBQueueConsumer {
57851
58017
  timer = null;
57852
58018
  running = false;
57853
58019
  inFlight = 0;
58020
+ pollPromise = null;
57854
58021
  constructor(dao, config4 = {}) {
57855
58022
  this.dao = dao;
57856
58023
  this.pollInterval = nonNegativeFiniteConfig("pollInterval", config4.pollInterval ?? 1000);
@@ -57870,7 +58037,13 @@ class DBQueueConsumer {
57870
58037
  return;
57871
58038
  this.running = true;
57872
58039
  this.schedule(0);
57873
- await this.events?.emit("queue.consumer.started");
58040
+ await this.events?.emit("queue.consumer.started", {
58041
+ startedAt: Date.now(),
58042
+ pollInterval: this.pollInterval,
58043
+ batchSize: this.batchSize,
58044
+ maxConcurrency: this.maxConcurrency,
58045
+ visibilityTimeout: this.visibilityTimeout
58046
+ });
57874
58047
  }
57875
58048
  async stop() {
57876
58049
  const wasRunning = this.running;
@@ -57880,11 +58053,22 @@ class DBQueueConsumer {
57880
58053
  this.timer = null;
57881
58054
  }
57882
58055
  const deadline = Date.now() + this.drainTimeoutMs;
58056
+ const pending = this.pollPromise;
58057
+ if (pending !== null) {
58058
+ await settleWithin(pending, deadline);
58059
+ }
57883
58060
  while (this.inFlight > 0 && Date.now() < deadline) {
57884
58061
  await sleep(10);
57885
58062
  }
57886
- if (wasRunning)
57887
- await this.events?.emit("queue.consumer.stopped");
58063
+ if (wasRunning) {
58064
+ const detail = {
58065
+ stoppedAt: Date.now(),
58066
+ drainTimeoutMs: this.drainTimeoutMs,
58067
+ inFlightAtStop: this.inFlight,
58068
+ drained: this.inFlight === 0
58069
+ };
58070
+ await this.events?.emit("queue.consumer.stopped", detail);
58071
+ }
57888
58072
  }
57889
58073
  async stats() {
57890
58074
  return this.dao.getStats();
@@ -57913,7 +58097,11 @@ class DBQueueConsumer {
57913
58097
  }
57914
58098
  schedule(delay) {
57915
58099
  this.timer = setTimeout(() => {
57916
- this.poll();
58100
+ const cycle = this.poll().finally(() => {
58101
+ if (this.pollPromise === cycle)
58102
+ this.pollPromise = null;
58103
+ });
58104
+ this.pollPromise = cycle;
57917
58105
  }, delay);
57918
58106
  }
57919
58107
  async poll() {
@@ -57935,7 +58123,7 @@ class DBQueueConsumer {
57935
58123
  try {
57936
58124
  job = toJob(record2);
57937
58125
  } catch (error51) {
57938
- await this.failOrRetry(record2, error51);
58126
+ await this.failOrRetry(record2, error51, 0);
57939
58127
  return;
57940
58128
  }
57941
58129
  return traceAsync("queue.job.process", async () => {
@@ -57946,45 +58134,59 @@ class DBQueueConsumer {
57946
58134
  });
57947
58135
  const handler = this.handlers.get(job.type);
57948
58136
  if (handler === undefined) {
57949
- await this.failOrRetry(job, new Error(`No handler registered for job type "${job.type}"`));
58137
+ await this.failOrRetry(job, new Error(`No handler registered for job type "${job.type}"`), 0);
57950
58138
  return;
57951
58139
  }
57952
58140
  const startMs = performance.now();
57953
58141
  try {
57954
58142
  await handler(job);
57955
58143
  await this.dao.markCompleted(job.id);
58144
+ const durationMs = performance.now() - startMs;
57956
58145
  getQueueJobCompletedTotal().add(1, { type: job.type });
57957
- getQueueJobProcessingDuration().record(performance.now() - startMs, { type: job.type });
57958
- await this.events?.emit("queue.job.completed", { jobId: job.id, type: job.type });
58146
+ getQueueJobProcessingDuration().record(durationMs, { type: job.type });
58147
+ const completed = {
58148
+ jobId: job.id,
58149
+ type: job.type,
58150
+ durationMs: Number.isFinite(durationMs) ? durationMs : 0,
58151
+ attempt: job.attempts
58152
+ };
58153
+ await this.events?.emit("queue.job.completed", completed);
57959
58154
  } catch (error51) {
57960
- getQueueJobProcessingDuration().record(performance.now() - startMs, { type: job.type });
57961
- await this.failOrRetry(job, error51);
58155
+ const durationMs = performance.now() - startMs;
58156
+ getQueueJobProcessingDuration().record(durationMs, { type: job.type });
58157
+ await this.failOrRetry(job, error51, Number.isFinite(durationMs) ? durationMs : 0);
57962
58158
  }
57963
58159
  });
57964
58160
  }
57965
- async failOrRetry(job, error51) {
58161
+ async failOrRetry(job, error51, durationMs) {
57966
58162
  const attempts = job.attempts + 1;
57967
58163
  const message = error51 instanceof Error ? error51.message : String(error51);
57968
58164
  if (attempts >= job.maxRetries) {
57969
58165
  await this.dao.markFailed(job.id, attempts, message);
57970
58166
  getQueueJobFailedTotal().add(1, { type: job.type });
57971
- await this.events?.emit("queue.job.failed", {
58167
+ const failed = {
57972
58168
  jobId: job.id,
57973
58169
  type: job.type,
57974
58170
  error: message,
57975
- attempt: attempts
57976
- });
58171
+ attempt: attempts,
58172
+ maxRetries: job.maxRetries,
58173
+ durationMs
58174
+ };
58175
+ await this.events?.emit("queue.job.failed", failed);
57977
58176
  return;
57978
58177
  }
57979
58178
  const delay = Math.min(this.maxDelay, this.baseDelay * 2 ** Math.max(0, attempts - 1));
57980
58179
  const nextRetryAt = Date.now() + delay;
57981
58180
  await this.dao.markForRetry(job.id, attempts, message, nextRetryAt);
57982
- await this.events?.emit("queue.job.retrying", {
58181
+ const retrying = {
57983
58182
  jobId: job.id,
57984
58183
  type: job.type,
57985
58184
  attempt: attempts,
57986
- nextRetryAt
57987
- });
58185
+ maxRetries: job.maxRetries,
58186
+ nextRetryAt,
58187
+ error: message
58188
+ };
58189
+ await this.events?.emit("queue.job.retrying", retrying);
57988
58190
  }
57989
58191
  }
57990
58192
  function toJob(record2) {
@@ -58003,7 +58205,9 @@ function toJob(record2) {
58003
58205
  };
58004
58206
  }
58005
58207
  function sleep(ms) {
58006
- return new Promise((resolve) => setTimeout(resolve, ms));
58208
+ const { promise: promise2, resolve } = Promise.withResolvers();
58209
+ setTimeout(resolve, ms);
58210
+ return promise2;
58007
58211
  }
58008
58212
  function positiveIntegerConfig(name, value) {
58009
58213
  if (!Number.isInteger(value) || value <= 0) {
@@ -58030,7 +58234,7 @@ var init_db_job_queue = __esm(() => {
58030
58234
  init_tracing2();
58031
58235
  });
58032
58236
 
58033
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/job-queue-db.js
58237
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/job-queue-db.js
58034
58238
  var exports_job_queue_db = {};
58035
58239
  __export(exports_job_queue_db, {
58036
58240
  DBQueueConsumer: () => DBQueueConsumer,
@@ -58100,9 +58304,6 @@ function normalizeCapabilityTier(value) {
58100
58304
  function isTierEligible(candidateTier, minTier) {
58101
58305
  return TIER_RANK[candidateTier] >= TIER_RANK[minTier];
58102
58306
  }
58103
- function pickStartingTier(policy) {
58104
- return policy.min_tier;
58105
- }
58106
58307
  function getNextFallback(policy, signal, currentTier) {
58107
58308
  const currentRank = currentTier ? TIER_RANK[currentTier] : 0;
58108
58309
  const match = policy.fallback.find((f) => f.trigger === signal && TIER_RANK[f.tier] > currentRank);
@@ -58168,12 +58369,12 @@ function parseStageRecord(raw, consumerVersion = STAGE_REGISTRY_SCHEMA_VERSION)
58168
58369
  function getCanonicalStage(idOrAlias) {
58169
58370
  return CANONICAL_STAGE_BY_KEY.get(idOrAlias);
58170
58371
  }
58171
- var STAGE_REGISTRY_SCHEMA_VERSION, stageSchemaVersionSchema, AUTHORITY_LANES, MUTATION_CLASSES, EXECUTION_KINDS, inlineExecutionSchema, subprocessExecutionSchema, deterministicExecutionSchema, hitlExecutionSchema, irreversibleExecutionSchema, executionKindSchema, ARTIFACT_DIRECTIONS, stageArtifactSchema, stageGateSchema, stageRetryPolicySchema, CAPABILITY_TIERS, LEGACY_CAPABLE_ALIAS = "capable", capabilityTierSchema, stageModelPolicySchema, TIER_RANK, CONTEXT_LAYER_NAMES, stageContextLayerSchema, stageEventSchema, STAGE_ID_PATTERN, stageRecordSchema, StageRegistryError, REGISTERED_CANONICAL_STAGES, CANONICAL_STAGE_BY_KEY;
58372
+ var STAGE_REGISTRY_SCHEMA_VERSION, stageSchemaVersionSchema, AUTHORITY_LANES, MUTATION_CLASSES, EXECUTION_KINDS, inlineExecutionSchema, subprocessExecutionSchema, deterministicExecutionSchema, hitlExecutionSchema, irreversibleExecutionSchema, executionKindSchema, ARTIFACT_DIRECTIONS, stageArtifactSchema, stageGateSchema, stageRetryPolicySchema, CAPABILITY_TIERS, LEGACY_CAPABLE_ALIAS = "capable", capabilityTierSchema, objectiveEscalationTriggerSchema, stageModelPolicySchema, TIER_RANK, CONTEXT_LAYER_NAMES, stageContextLayerSchema, stageEventSchema, STAGE_ID_PATTERN, stageRecordSchema, StageRegistryError, REGISTERED_CANONICAL_STAGES, CANONICAL_STAGE_BY_KEY;
58172
58373
  var init_schema4 = __esm(() => {
58173
58374
  init_zod();
58174
58375
  STAGE_REGISTRY_SCHEMA_VERSION = {
58175
58376
  major: 1,
58176
- minor: 0
58377
+ minor: 1
58177
58378
  };
58178
58379
  stageSchemaVersionSchema = exports_external.object({
58179
58380
  major: exports_external.number().int().nonnegative(),
@@ -58244,11 +58445,18 @@ var init_schema4 = __esm(() => {
58244
58445
  }).strict();
58245
58446
  CAPABILITY_TIERS = ["cheap", "standard", "capable-1", "capable-2", "capable-3"];
58246
58447
  capabilityTierSchema = exports_external.preprocess(normalizeCapabilityTier, exports_external.enum(CAPABILITY_TIERS));
58448
+ objectiveEscalationTriggerSchema = exports_external.enum([
58449
+ "gate-fail",
58450
+ "timeout",
58451
+ "insufficient-evidence",
58452
+ "retry-exhausted",
58453
+ "resource-exhaustion"
58454
+ ]);
58247
58455
  stageModelPolicySchema = exports_external.object({
58248
58456
  min_tier: capabilityTierSchema,
58249
58457
  fallback: exports_external.array(exports_external.object({
58250
58458
  tier: capabilityTierSchema,
58251
- trigger: exports_external.enum(["gate-fail", "timeout", "insufficient-evidence", "retry-exhausted"])
58459
+ trigger: objectiveEscalationTriggerSchema
58252
58460
  }).strict()),
58253
58461
  override_key: exports_external.string().optional()
58254
58462
  }).strict();
@@ -58319,7 +58527,10 @@ var init_schema4 = __esm(() => {
58319
58527
  retry: { max_attempts: 3, terminal_stop: "block" },
58320
58528
  model_policy: {
58321
58529
  min_tier: "standard",
58322
- fallback: [{ tier: "capable-2", trigger: "gate-fail" }]
58530
+ fallback: [
58531
+ { tier: "capable-2", trigger: "gate-fail" },
58532
+ { tier: "capable-2", trigger: "resource-exhaustion" }
58533
+ ]
58323
58534
  },
58324
58535
  context_layers: [],
58325
58536
  observability: [],
@@ -58338,7 +58549,10 @@ var init_schema4 = __esm(() => {
58338
58549
  retry: { max_attempts: 3, terminal_stop: "block" },
58339
58550
  model_policy: {
58340
58551
  min_tier: "capable-2",
58341
- fallback: [{ tier: "capable-3", trigger: "gate-fail" }]
58552
+ fallback: [
58553
+ { tier: "capable-3", trigger: "gate-fail" },
58554
+ { tier: "capable-3", trigger: "resource-exhaustion" }
58555
+ ]
58342
58556
  },
58343
58557
  context_layers: [],
58344
58558
  observability: [],
@@ -58359,7 +58573,8 @@ var init_schema4 = __esm(() => {
58359
58573
  min_tier: "standard",
58360
58574
  fallback: [
58361
58575
  { tier: "capable-1", trigger: "gate-fail" },
58362
- { tier: "capable-1", trigger: "timeout" }
58576
+ { tier: "capable-1", trigger: "timeout" },
58577
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58363
58578
  ]
58364
58579
  },
58365
58580
  context_layers: [],
@@ -58378,8 +58593,11 @@ var init_schema4 = __esm(() => {
58378
58593
  mutation_class: "tests",
58379
58594
  retry: { max_attempts: 3, terminal_stop: "block" },
58380
58595
  model_policy: {
58381
- min_tier: "standard",
58382
- fallback: [{ tier: "capable-1", trigger: "gate-fail" }]
58596
+ fallback: [
58597
+ { tier: "capable-1", trigger: "gate-fail" },
58598
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58599
+ ],
58600
+ min_tier: "standard"
58383
58601
  },
58384
58602
  context_layers: [],
58385
58603
  observability: [],
@@ -58417,7 +58635,10 @@ var init_schema4 = __esm(() => {
58417
58635
  retry: { max_attempts: 2, terminal_stop: "block" },
58418
58636
  model_policy: {
58419
58637
  min_tier: "standard",
58420
- fallback: [{ tier: "capable-1", trigger: "gate-fail" }]
58638
+ fallback: [
58639
+ { tier: "capable-1", trigger: "gate-fail" },
58640
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58641
+ ]
58421
58642
  },
58422
58643
  context_layers: [],
58423
58644
  observability: [],
@@ -58436,7 +58657,10 @@ var init_schema4 = __esm(() => {
58436
58657
  retry: { max_attempts: 2, terminal_stop: "block" },
58437
58658
  model_policy: {
58438
58659
  min_tier: "standard",
58439
- fallback: [{ tier: "capable-1", trigger: "gate-fail" }]
58660
+ fallback: [
58661
+ { tier: "capable-1", trigger: "gate-fail" },
58662
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58663
+ ]
58440
58664
  },
58441
58665
  context_layers: [],
58442
58666
  observability: [],
@@ -60079,13 +60303,13 @@ __export(exports_src, {
60079
60303
  queryEtlRecords: () => queryEtlRecords,
60080
60304
  queryAllEtlRecords: () => queryAllEtlRecords,
60081
60305
  projectSnapshotSchema: () => projectSnapshotSchema,
60082
- pickStartingTier: () => pickStartingTier,
60083
60306
  passAllResolver: () => passAllResolver,
60084
60307
  parseStageRecord: () => parseStageRecord,
60085
60308
  parseHistoryLine: () => parseHistoryLine,
60086
60309
  parseFeature: () => parseFeature,
60087
60310
  parseExistingAcTags: () => parseExistingAcTags,
60088
60311
  parseChecklist: () => parseChecklist,
60312
+ objectiveEscalationTriggerSchema: () => objectiveEscalationTriggerSchema,
60089
60313
  normalizeTitle: () => normalizeTitle,
60090
60314
  normalizeTaskStatusSafe: () => normalizeTaskStatusSafe,
60091
60315
  normalizeTaskStatus: () => normalizeTaskStatus,
@@ -60399,92 +60623,159 @@ class AgentService {
60399
60623
  if (!resolved.ok) {
60400
60624
  return { ok: false, exitCode: resolved.exitCode, message: resolved.message };
60401
60625
  }
60402
- const agent = resolved.agent;
60403
- if (!jsonOutput && TIER2_AGENTS.has(agent)) {
60404
- this.ctx.output.error(`Warning: ${agent} is a Tier-2 agent (TUI/gateway only)`);
60626
+ const runFlags = { ...flags };
60627
+ let currentAgent = resolved.agent;
60628
+ let currentModel = resolved.model;
60629
+ let currentSource = resolved.source;
60630
+ let currentStage = resolved.stage;
60631
+ const maxEscalations = currentStage?.policy.fallback.length ?? 0;
60632
+ const attemptedExecutors = new Set(currentStage ? [currentStage.executorName] : []);
60633
+ if (!jsonOutput && TIER2_AGENTS.has(currentAgent)) {
60634
+ this.ctx.output.error(`Warning: ${currentAgent} is a Tier-2 agent (TUI/gateway only)`);
60405
60635
  }
60406
- const translated = prompt !== undefined && isClaudeStyleSlashCommand(prompt) ? translateSlashCommand(agent, prompt) : undefined;
60407
- const input = translated ?? prompt;
60636
+ const explicitModel = stringFlag(flags, "model", "") || undefined;
60408
60637
  const purpose = stringFlag(flags, "purpose", "") || undefined;
60409
60638
  const tags = parseTagsFlag(flags);
60410
60639
  const systemPrompt = stringFlag(flags, "system-prompt", "") || undefined;
60411
60640
  const taskId = stringFlag(flags, "task", "") || undefined;
60412
- const explicitModel = stringFlag(flags, "model", "") || undefined;
60413
- const model = explicitModel ?? resolved.model;
60414
- const promptOptions = {
60415
- input,
60416
- continue: continueFlag || undefined,
60417
- model,
60418
- mode,
60419
- ...purpose !== undefined ? { purpose } : {},
60420
- ...tags !== undefined ? { tags } : {},
60421
- ...systemPrompt !== undefined ? { systemPrompt } : {},
60422
- ...taskId !== undefined ? { taskId } : {}
60423
- };
60424
- let shimCommand;
60425
- try {
60426
- shimCommand = typeof runner.buildPromptCommand === "function" ? runner.buildPromptCommand(agent, promptOptions, { cwd: cwd || undefined }) : getAgentShim(agent).getPromptCommand(promptOptions);
60427
- if (!jsonOutput) {
60428
- const version3 = (await detector.detectOne(agent)).version;
60429
- this.ctx.output.error(`\u2699\uFE0F ${agent}${version3 !== null ? ` v${version3}` : ""}
60430
- ${shimCommand.command} ${shimCommand.args.join(" ")}`);
60431
- }
60432
- } catch (error51) {
60433
- return { ok: false, exitCode: 2, message: error51 instanceof Error ? error51.message : String(error51) };
60434
- }
60435
- const traceInput = input === undefined ? undefined : traceSafePrompt(input);
60436
- const invocation = {
60437
- agent,
60438
- source: resolved.source,
60439
- command: shimCommand.command,
60440
- argv: sanitizeInvocationArgv(shimCommand.args, input, traceInput),
60441
- ...cwd !== "" ? { cwd } : {},
60442
- mode,
60443
- outputMode,
60444
- ...timeoutMs !== undefined ? { timeoutMs } : {},
60445
- continue: continueFlag,
60446
- stdinInteractive: false,
60447
- ...model !== undefined ? { model } : {},
60448
- ...translated !== undefined && prompt !== undefined ? { translatedFrom: traceSafePrompt(prompt) } : {}
60449
- };
60450
- let result;
60451
60641
  const controller = new AbortController;
60452
60642
  const onTerminate = () => controller.abort();
60453
60643
  const onExternalAbort = () => controller.abort();
60454
60644
  const lifecycle = new AgentExecutionLifecycle(options.execution?.observer, options.execution?.correlation, configuredSecretValues(this.ctx.env), options.execution?.heartbeatMs);
60455
- lifecycle.start({
60456
- agent,
60457
- ...model !== undefined ? { model } : {},
60458
- invocation: `${invocation.command} ${invocation.argv.join(" ")}`,
60459
- ...timeoutMs !== undefined ? { timeoutMs } : {}
60460
- });
60461
- const dispatchStartedAt = Date.now();
60645
+ process.on("SIGTERM", onTerminate);
60646
+ process.on("SIGINT", onTerminate);
60647
+ options.execution?.signal?.addEventListener("abort", onExternalAbort, { once: true });
60648
+ if (options.execution?.signal?.aborted === true)
60649
+ controller.abort();
60650
+ let result;
60651
+ let invocation;
60652
+ let dispatchStartedAt = Date.now();
60462
60653
  try {
60463
- process.on("SIGTERM", onTerminate);
60464
- process.on("SIGINT", onTerminate);
60465
- options.execution?.signal?.addEventListener("abort", onExternalAbort, { once: true });
60466
- if (options.execution?.signal?.aborted === true)
60467
- controller.abort();
60468
- result = await runner.runPromptCommand(agent, promptOptions, {
60469
- cwd: cwd || undefined,
60470
- ...timeoutMs !== undefined ? { timeout: timeoutMs } : {},
60471
- signal: controller.signal,
60472
- correlation: lifecycle.identity,
60473
- onOutput: (output2) => lifecycle.observe(output2)
60474
- });
60475
- } catch (error51) {
60476
- lifecycle.finish({
60477
- exitCode: null,
60478
- durationMs: Date.now() - dispatchStartedAt,
60479
- ...controller.signal.aborted ? { reason: "cancelled" } : {},
60480
- ...!controller.signal.aborted ? { reason: error51 instanceof Error ? error51.message : String(error51) } : {}
60481
- });
60482
- return { ok: false, exitCode: 2, message: error51 instanceof Error ? error51.message : String(error51) };
60654
+ for (let attempt = 0;; attempt++) {
60655
+ const agent = currentAgent;
60656
+ const model = explicitModel ?? currentModel;
60657
+ const translated = prompt !== undefined && isClaudeStyleSlashCommand(prompt) ? translateSlashCommand(agent, prompt) : undefined;
60658
+ const input = translated ?? prompt;
60659
+ const promptOptions = {
60660
+ input,
60661
+ continue: continueFlag || undefined,
60662
+ model,
60663
+ mode,
60664
+ ...purpose !== undefined ? { purpose } : {},
60665
+ ...tags !== undefined ? { tags } : {},
60666
+ ...systemPrompt !== undefined ? { systemPrompt } : {},
60667
+ ...taskId !== undefined ? { taskId } : {}
60668
+ };
60669
+ let shimCommand;
60670
+ try {
60671
+ shimCommand = typeof runner.buildPromptCommand === "function" ? runner.buildPromptCommand(agent, promptOptions, { cwd: cwd || undefined }) : getAgentShim(agent).getPromptCommand(promptOptions);
60672
+ if (!jsonOutput) {
60673
+ const version3 = (await detector.detectOne(agent)).version;
60674
+ this.ctx.output.error(`\u2699\uFE0F ${agent}${version3 !== null ? ` v${version3}` : ""}
60675
+ ${shimCommand.command} ${shimCommand.args.join(" ")}`);
60676
+ }
60677
+ } catch (error51) {
60678
+ if (attempt === 0) {
60679
+ return {
60680
+ ok: false,
60681
+ exitCode: 2,
60682
+ message: error51 instanceof Error ? error51.message : String(error51)
60683
+ };
60684
+ }
60685
+ if (!jsonOutput) {
60686
+ this.ctx.output.error(`Escalation aborted: ${error51 instanceof Error ? error51.message : String(error51)}`);
60687
+ }
60688
+ break;
60689
+ }
60690
+ const traceInput = input === undefined ? undefined : traceSafePrompt(input);
60691
+ const attemptInvocation = {
60692
+ agent,
60693
+ source: currentSource,
60694
+ command: shimCommand.command,
60695
+ argv: sanitizeInvocationArgv(shimCommand.args, input, traceInput),
60696
+ ...cwd !== "" ? { cwd } : {},
60697
+ mode,
60698
+ outputMode,
60699
+ ...timeoutMs !== undefined ? { timeoutMs } : {},
60700
+ continue: continueFlag,
60701
+ stdinInteractive: false,
60702
+ ...model !== undefined ? { model } : {},
60703
+ ...translated !== undefined && prompt !== undefined ? { translatedFrom: traceSafePrompt(prompt) } : {}
60704
+ };
60705
+ if (attempt === 0) {
60706
+ lifecycle.start({
60707
+ agent,
60708
+ ...model !== undefined ? { model } : {},
60709
+ invocation: `${attemptInvocation.command} ${attemptInvocation.argv.join(" ")}`,
60710
+ ...timeoutMs !== undefined ? { timeoutMs } : {}
60711
+ });
60712
+ dispatchStartedAt = Date.now();
60713
+ }
60714
+ try {
60715
+ result = await runner.runPromptCommand(agent, promptOptions, {
60716
+ cwd: cwd || undefined,
60717
+ ...timeoutMs !== undefined ? { timeout: timeoutMs } : {},
60718
+ signal: controller.signal,
60719
+ correlation: lifecycle.identity,
60720
+ onOutput: (output2) => lifecycle.observe(output2)
60721
+ });
60722
+ } catch (error51) {
60723
+ if (attempt === 0) {
60724
+ lifecycle.finish({
60725
+ exitCode: null,
60726
+ durationMs: Date.now() - dispatchStartedAt,
60727
+ ...controller.signal.aborted ? { reason: "cancelled" } : {},
60728
+ ...!controller.signal.aborted ? { reason: error51 instanceof Error ? error51.message : String(error51) } : {}
60729
+ });
60730
+ return {
60731
+ ok: false,
60732
+ exitCode: 2,
60733
+ message: error51 instanceof Error ? error51.message : String(error51)
60734
+ };
60735
+ }
60736
+ if (!jsonOutput) {
60737
+ this.ctx.output.error(`Escalation dispatch failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
60738
+ }
60739
+ break;
60740
+ }
60741
+ invocation = attemptInvocation;
60742
+ if (result.exitCode === 0)
60743
+ break;
60744
+ const escalationSignal = classifyObjectiveFailure(result);
60745
+ if (escalationSignal === undefined || currentStage === undefined || attempt >= maxEscalations) {
60746
+ break;
60747
+ }
60748
+ runFlags.signal = escalationSignal;
60749
+ runFlags["from-executor"] = currentStage.executorName;
60750
+ const nextResolved = await this.resolveAgent(prompt, runFlags, doctorRunner);
60751
+ if (!nextResolved.ok || nextResolved.stage === undefined || attemptedExecutors.has(nextResolved.stage.executorName)) {
60752
+ if (!jsonOutput) {
60753
+ this.ctx.output.error(`Escalation chain exhausted after ${attempt + 1} attempt(s); executors tried: ${[...attemptedExecutors].join(", ")}`);
60754
+ }
60755
+ break;
60756
+ }
60757
+ if (!jsonOutput) {
60758
+ this.ctx.output.error(`Escalating: ${currentStage.executorName} (tier ${currentStage.executorTier}) failed with ${escalationSignal}; retrying on ${nextResolved.stage.executorName} (tier ${nextResolved.stage.executorTier})`);
60759
+ }
60760
+ currentAgent = nextResolved.agent;
60761
+ currentModel = nextResolved.model;
60762
+ currentSource = nextResolved.source;
60763
+ currentStage = nextResolved.stage;
60764
+ attemptedExecutors.add(nextResolved.stage.executorName);
60765
+ }
60483
60766
  } finally {
60484
60767
  process.off("SIGTERM", onTerminate);
60485
60768
  process.off("SIGINT", onTerminate);
60486
60769
  options.execution?.signal?.removeEventListener("abort", onExternalAbort);
60487
60770
  }
60771
+ if (result === undefined || invocation === undefined) {
60772
+ lifecycle.finish({
60773
+ exitCode: null,
60774
+ durationMs: Date.now() - dispatchStartedAt,
60775
+ reason: "no dispatch attempted"
60776
+ });
60777
+ return { ok: false, exitCode: 2, message: "No dispatch attempted" };
60778
+ }
60488
60779
  lifecycle.finish({
60489
60780
  exitCode: result.exitCode,
60490
60781
  durationMs: result.durationMs,
@@ -60514,6 +60805,13 @@ class AgentService {
60514
60805
  const raw = stringFlag(flags, "agent", "auto");
60515
60806
  if (raw === "auto")
60516
60807
  return this.resolveAgentAuto(prompt, flags, doctorRunner);
60808
+ if (raw === "inline") {
60809
+ return {
60810
+ ok: false,
60811
+ exitCode: 2,
60812
+ message: "'inline' selects in-session execution and cannot be passed to 'spur agent run', which always starts a subprocess. Run the backing skill directly in the current session, or use '--agent auto' for subprocess dispatch with a tier-resolved executor."
60813
+ };
60814
+ }
60517
60815
  return this.resolveExecutorSelector(raw, doctorRunner, "explicit");
60518
60816
  }
60519
60817
  async resolveAgentAuto(prompt, flags, doctorRunner) {
@@ -60584,7 +60882,13 @@ class AgentService {
60584
60882
  ok: true,
60585
60883
  agent: canonical,
60586
60884
  model: executor.model,
60587
- source: "stage"
60885
+ source: "stage",
60886
+ stage: {
60887
+ stageId: stageRecord.id,
60888
+ policy,
60889
+ executorName: executor.name,
60890
+ executorTier: getExecutorTier(executor)
60891
+ }
60588
60892
  };
60589
60893
  }
60590
60894
  }
@@ -60632,8 +60936,15 @@ class AgentService {
60632
60936
  };
60633
60937
  }
60634
60938
  const canonical = resolveAgentName(selector);
60635
- if (canonical === undefined)
60636
- return { ok: false, exitCode: 2, message: `Unknown agent: ${selector}` };
60939
+ if (canonical === undefined) {
60940
+ const names = this.ctx.agentConfig?.executors?.map((e) => e.name) ?? [];
60941
+ const available = names.length > 0 ? names.join(", ") : "(no executors configured; use a canonical agent name)";
60942
+ return {
60943
+ ok: false,
60944
+ exitCode: 2,
60945
+ message: `Unknown agent: '${selector}'. Available executors: ${available}.`
60946
+ };
60947
+ }
60637
60948
  const usable = await this.checkUsable(canonical, doctorRunner);
60638
60949
  if (!usable.ok)
60639
60950
  return usable.result;
@@ -60819,6 +61130,17 @@ function getExecutorTier(executor) {
60819
61130
  return "capable-1";
60820
61131
  return "standard";
60821
61132
  }
61133
+ function classifyObjectiveFailure(result) {
61134
+ if (result.signal !== undefined)
61135
+ return "timeout";
61136
+ if (result.exitCode === 0)
61137
+ return;
61138
+ const text4 = `${result.stderr} ${result.stdout}`.toLowerCase();
61139
+ if (/\b(rate[\s-]?limit|429|too many requests|quota|token limit|token budget|context length|maximum context|context window)\b/.test(text4)) {
61140
+ return "resource-exhaustion";
61141
+ }
61142
+ return;
61143
+ }
60822
61144
  var TRACE_SAFE_SLASH_COMMAND, TRACE_SAFE_SLASH_TOKEN, SENSITIVE_FLAG, SENSITIVE_INLINE_FLAG;
60823
61145
  var init_agent_service = __esm(() => {
60824
61146
  init_src2();
@@ -61672,11 +61994,106 @@ var init_planning_check_base = __esm(() => {
61672
61994
  // ../../packages/app/src/services/feature-check.ts
61673
61995
  var exports_feature_check = {};
61674
61996
  __export(exports_feature_check, {
61997
+ findOtherP0InStatus: () => findOtherP0InStatus,
61675
61998
  defaultVerdictRunDir: () => defaultVerdictRunDir,
61676
61999
  FeatureCheckService: () => FeatureCheckService,
61677
62000
  DEFAULT_FEATURE_MATRIX: () => DEFAULT_FEATURE_MATRIX
61678
62001
  });
61679
62002
  import { dirname as dirname8, join as join8 } from "path";
62003
+ function isGroupFeature(fm) {
62004
+ const tags = fm.tags;
62005
+ return Array.isArray(tags) && tags.includes("group") ? "group" : "standard";
62006
+ }
62007
+ async function findOtherP0InStatus(fs3, featuresDir, currentId, statuses) {
62008
+ try {
62009
+ const entries = await fs3.readDir(featuresDir);
62010
+ for (const entry of entries) {
62011
+ if (!entry.endsWith(".md"))
62012
+ continue;
62013
+ const match = /^([A-Z][1-9]*)_/.exec(entry);
62014
+ if (match === null)
62015
+ continue;
62016
+ const otherId = match[1];
62017
+ if (otherId === undefined)
62018
+ continue;
62019
+ if (otherId === currentId)
62020
+ continue;
62021
+ try {
62022
+ const raw = await fs3.readFile(`${featuresDir}/${entry}`);
62023
+ const doc2 = MarkdownDocument.parse(raw, "feature");
62024
+ const otherFm = doc2.frontmatterData ?? {};
62025
+ const otherPriority = otherFm.priority;
62026
+ const otherStatus = otherFm.status ?? "backlog";
62027
+ if (otherPriority === "P0" && statuses.includes(otherStatus)) {
62028
+ return { id: otherId, status: otherStatus };
62029
+ }
62030
+ } catch {}
62031
+ }
62032
+ } catch {}
62033
+ return null;
62034
+ }
62035
+ function decodeVerdictRows(source, sectionName, required2) {
62036
+ if (source === undefined) {
62037
+ return {
62038
+ rows: [],
62039
+ rejected: 0,
62040
+ invalidFields: required2 ? [`${sectionName} (missing array)`] : [],
62041
+ state: "absent"
62042
+ };
62043
+ }
62044
+ if (!Array.isArray(source)) {
62045
+ return {
62046
+ rows: [],
62047
+ rejected: 0,
62048
+ invalidFields: [`${sectionName} (expected array)`],
62049
+ state: "invalid"
62050
+ };
62051
+ }
62052
+ const rows = [];
62053
+ const invalidFields = new Set;
62054
+ let rejected = 0;
62055
+ for (const r of source) {
62056
+ if (typeof r !== "object" || r === null) {
62057
+ rejected++;
62058
+ invalidFields.add(`${sectionName}[non-object]`);
62059
+ continue;
62060
+ }
62061
+ const row = r;
62062
+ const hasId = Object.hasOwn(row, "id");
62063
+ const hasScenario = Object.hasOwn(row, "scenario");
62064
+ const idStr = typeof row.id === "string";
62065
+ const scStr = typeof row.scenario === "string";
62066
+ const statusOk = typeof row.status === "string";
62067
+ if (!statusOk) {
62068
+ rejected++;
62069
+ invalidFields.add(`${sectionName}.status`);
62070
+ continue;
62071
+ }
62072
+ if (hasId && hasScenario) {
62073
+ if (idStr && scStr && row.id === row.scenario) {
62074
+ rows.push({ id: row.id, status: row.status });
62075
+ } else {
62076
+ rejected++;
62077
+ invalidFields.add(`${sectionName}.id/scenario conflict`);
62078
+ }
62079
+ continue;
62080
+ }
62081
+ if (hasId && idStr) {
62082
+ rows.push({ id: row.id, status: row.status });
62083
+ } else if (hasScenario && scStr) {
62084
+ rows.push({ id: row.scenario, status: row.status });
62085
+ } else {
62086
+ rejected++;
62087
+ invalidFields.add(`${sectionName}.id/scenario missing`);
62088
+ }
62089
+ }
62090
+ return {
62091
+ rows,
62092
+ rejected,
62093
+ invalidFields: [...invalidFields],
62094
+ state: source.length === 0 ? "empty" : "populated"
62095
+ };
62096
+ }
61680
62097
  function defaultVerdictRunDir(tasksDir) {
61681
62098
  const norm = tasksDir.replace(/\\/g, "/");
61682
62099
  if (/\/docs\/tasks\d*$/.test(norm) || /\/docs\/tasks$/.test(norm)) {
@@ -61685,7 +62102,7 @@ function defaultVerdictRunDir(tasksDir) {
61685
62102
  return join8(dirname8(tasksDir), ".spur", "run");
61686
62103
  }
61687
62104
  function rowMatchesScenario(id, sc) {
61688
- const stripped = id.replace(/^Scenario:\s*/i, "").trim();
62105
+ const stripped = id.replace(/^\[[^\]]*\]\s*/, "").replace(/^Scenario:\s*/i, "").replace(/^\[[^\]]*\]\s*/, "").trim();
61689
62106
  return normalizeTitle(id) === sc.normalized || normalizeTitle(stripped) === sc.normalized || id === sc.alias || stripped === sc.alias;
61690
62107
  }
61691
62108
  var DEFAULT_FEATURE_MATRIX, FeatureCheckService;
@@ -61722,6 +62139,35 @@ var init_feature_check = __esm(() => {
61722
62139
  required: ["Notes"],
61723
62140
  optional: ["Goal", "Scope", "Acceptance Criteria", "Tasks", "History"]
61724
62141
  }
62142
+ },
62143
+ group: {
62144
+ backlog: {
62145
+ required: [],
62146
+ optional: ["Goal", "Scope", "Acceptance Criteria", "Tasks", "Notes", "History"]
62147
+ },
62148
+ active: {
62149
+ required: ["Goal", "Scope"],
62150
+ optional: ["Acceptance Criteria", "Tasks", "Notes", "History"],
62151
+ gate: true
62152
+ },
62153
+ verifying: {
62154
+ required: ["Goal", "Scope"],
62155
+ optional: ["Acceptance Criteria", "Tasks", "Notes", "History"],
62156
+ gate: true
62157
+ },
62158
+ blocked: {
62159
+ required: ["Goal", "Notes"],
62160
+ optional: ["Scope", "Acceptance Criteria", "Tasks", "History"]
62161
+ },
62162
+ done: {
62163
+ required: ["Goal", "Scope", "Tasks"],
62164
+ optional: ["Acceptance Criteria", "Notes", "History"],
62165
+ gate: true
62166
+ },
62167
+ cancelled: {
62168
+ required: ["Notes"],
62169
+ optional: ["Goal", "Scope", "Acceptance Criteria", "Tasks", "History"]
62170
+ }
61725
62171
  }
61726
62172
  }
61727
62173
  };
@@ -61745,11 +62191,11 @@ var init_feature_check = __esm(() => {
61745
62191
  }
61746
62192
  const fm = doc2.frontmatterData ?? {};
61747
62193
  const status = fm.status ?? "backlog";
61748
- const entry = this.resolveMatrixEntry("standard", status);
62194
+ const entry = this.resolveMatrixEntry(isGroupFeature(fm), status);
61749
62195
  this.runL2(doc2, entry, findings);
61750
62196
  this.runL3(doc2, findings);
61751
62197
  if (options?.featuresDir) {
61752
- await this.checkOneActiveGoal(fm, featureId2, options.featuresDir, findings);
62198
+ await this.checkOneActiveGoal(fm, featureId2, options.featuresDir, findings, options.asStatus);
61753
62199
  await this.checkChildrenLimit(featureId2, options.featuresDir, findings);
61754
62200
  }
61755
62201
  const dogfoodDir = options?.dogfoodDir ?? (options?.featuresDir ? join8(dirname8(options.featuresDir), "dogfood") : undefined);
@@ -61822,44 +62268,24 @@ var init_feature_check = __esm(() => {
61822
62268
  }
61823
62269
  }
61824
62270
  }
61825
- async checkOneActiveGoal(fm, currentId, featuresDir, findings) {
62271
+ async checkOneActiveGoal(fm, currentId, featuresDir, findings, asStatus) {
61826
62272
  const priority = fm.priority;
61827
- const status = fm.status;
62273
+ const status = fm.status ?? "backlog";
62274
+ const effectiveStatus = asStatus ?? status;
61828
62275
  if (priority !== "P0")
61829
62276
  return;
61830
- if (status !== "active" && status !== "verifying")
62277
+ if (effectiveStatus !== "active")
61831
62278
  return;
61832
- try {
61833
- const entries = await this.fs.readDir(featuresDir);
61834
- for (const entry of entries) {
61835
- if (!entry.endsWith(".md"))
61836
- continue;
61837
- const otherPath = `${featuresDir}/${entry}`;
61838
- const match = /^([A-Z][1-9]*)_/.exec(entry);
61839
- if (!match)
61840
- continue;
61841
- const otherId = match[1];
61842
- if (otherId === currentId)
61843
- continue;
61844
- try {
61845
- const raw = await this.fs.readFile(otherPath);
61846
- const doc2 = MarkdownDocument.parse(raw, "feature");
61847
- const otherFm = doc2.frontmatterData ?? {};
61848
- const otherPriority = otherFm.priority;
61849
- const otherStatus = otherFm.status;
61850
- if (otherPriority === "P0" && (otherStatus === "active" || otherStatus === "verifying")) {
61851
- findings.push({
61852
- layer: "L3",
61853
- code: FINDING_CODES.L3_ONE_ACTIVE_GOAL,
61854
- severity: "error",
61855
- section: "",
61856
- message: `One-active-goal violated: P0 feature "${otherId}" is already ${otherStatus}`
61857
- });
61858
- return;
61859
- }
61860
- } catch {}
61861
- }
61862
- } catch {}
62279
+ const conflict = await findOtherP0InStatus(this.fs, featuresDir, currentId, ["active"]);
62280
+ if (conflict !== null) {
62281
+ findings.push({
62282
+ layer: "L3",
62283
+ code: FINDING_CODES.L3_ONE_ACTIVE_GOAL,
62284
+ severity: "error",
62285
+ section: "",
62286
+ message: `One-active-goal violated: P0 feature "${conflict.id}" is already ${conflict.status}`
62287
+ });
62288
+ }
61863
62289
  }
61864
62290
  async checkChildrenLimit(featureId2, featuresDir, findings) {
61865
62291
  let children = 0;
@@ -62020,11 +62446,42 @@ var init_feature_check = __esm(() => {
62020
62446
  }
62021
62447
  covers[sc.title] = linked;
62022
62448
  }
62449
+ const doneWbs = new Set;
62450
+ for (const sc of scenarioAliases) {
62451
+ for (const task of covers[sc.title] ?? []) {
62452
+ if (task.status === "done")
62453
+ doneWbs.add(task.wbs);
62454
+ }
62455
+ }
62456
+ const artifacts2 = new Map;
62457
+ for (const wbs of doneWbs) {
62458
+ const artifact = await this.readVerdictArtifact(runDir, wbs);
62459
+ artifacts2.set(wbs, artifact);
62460
+ const diagnosticParts = [];
62461
+ if (artifact.diagnostics.artifactError !== undefined) {
62462
+ diagnosticParts.push(artifact.diagnostics.artifactError);
62463
+ }
62464
+ if (artifact.diagnostics.rejectedRowCount > 0) {
62465
+ diagnosticParts.push(`${artifact.diagnostics.rejectedRowCount} rejected coverage row(s)`);
62466
+ }
62467
+ if (artifact.diagnostics.invalidFields.length > 0) {
62468
+ diagnosticParts.push(`invalid fields: ${artifact.diagnostics.invalidFields.join(", ")}`);
62469
+ }
62470
+ if (diagnosticParts.length > 0) {
62471
+ findings.push({
62472
+ layer: "L4",
62473
+ code: FINDING_CODES.L4_MALFORMED_VERDICT_ARTIFACT,
62474
+ severity: "warning",
62475
+ section: "Acceptance Criteria",
62476
+ message: `Task ${wbs} verdict artifact (${artifact.path}) is invalid: ${diagnosticParts.join("; ")}. ` + "Rows were not silently dropped \u2014 verify the artifact uses canonical `id` " + "(or `scenario` alias) and `status` fields."
62477
+ });
62478
+ }
62479
+ }
62023
62480
  for (const sc of scenarioAliases) {
62024
62481
  const linked = covers[sc.title] ?? [];
62025
62482
  if (linked.length === 0)
62026
62483
  continue;
62027
- const verified = await this.isScenarioVerified(sc, linked, runDir);
62484
+ const verified = this.isScenarioVerified(sc, linked, artifacts2);
62028
62485
  if (!verified) {
62029
62486
  findings.push({
62030
62487
  layer: "L4",
@@ -62036,12 +62493,12 @@ var init_feature_check = __esm(() => {
62036
62493
  }
62037
62494
  }
62038
62495
  }
62039
- async isScenarioVerified(sc, linked, runDir) {
62496
+ isScenarioVerified(sc, linked, artifacts2) {
62040
62497
  for (const task of linked) {
62041
62498
  if (task.status !== "done")
62042
62499
  continue;
62043
- const artifact = await this.readVerdictArtifact(runDir, task.wbs);
62044
- if (artifact === null)
62500
+ const artifact = artifacts2.get(task.wbs);
62501
+ if (artifact === undefined)
62045
62502
  continue;
62046
62503
  if (artifact.verdict !== "PASS")
62047
62504
  continue;
@@ -62053,20 +62510,35 @@ var init_feature_check = __esm(() => {
62053
62510
  return false;
62054
62511
  }
62055
62512
  async readVerdictArtifact(runDir, wbs) {
62056
- try {
62057
- const raw = await this.fs.readFile(join8(runDir, `${wbs}-verdict.json`));
62058
- const parsed = JSON.parse(raw);
62059
- if (typeof parsed.verdict !== "string")
62060
- return null;
62061
- const pickRows = (arr) => (arr ?? []).filter((r) => typeof r?.id === "string" && typeof r?.status === "string").map((r) => ({ id: r.id, status: r.status }));
62062
- const requirements = pickRows(parsed.requirements);
62063
- const acceptanceCriteria = pickRows(parsed.acceptanceCriteria);
62064
- if (requirements.length === 0 && acceptanceCriteria.length === 0)
62065
- return null;
62066
- return { verdict: parsed.verdict, requirements, acceptanceCriteria };
62067
- } catch {
62068
- return null;
62513
+ const loaded = await readVerdictArtifact(this.fs, runDir, wbs);
62514
+ if (loaded.artifact === undefined) {
62515
+ return {
62516
+ path: loaded.path,
62517
+ requirements: [],
62518
+ acceptanceCriteria: [],
62519
+ diagnostics: {
62520
+ artifactError: loaded.readError ?? "artifact is missing",
62521
+ rejectedRowCount: 0,
62522
+ invalidFields: [],
62523
+ arrayStates: { requirements: "unavailable", acceptanceCriteria: "unavailable" }
62524
+ }
62525
+ };
62069
62526
  }
62527
+ const parsed = loaded.artifact;
62528
+ const req = decodeVerdictRows(parsed.requirements, "requirements", true);
62529
+ const ac = decodeVerdictRows(parsed.acceptanceCriteria, "acceptanceCriteria", false);
62530
+ return {
62531
+ path: loaded.path,
62532
+ verdict: typeof parsed.verdict === "string" ? parsed.verdict : undefined,
62533
+ requirements: req.rows,
62534
+ acceptanceCriteria: ac.rows,
62535
+ diagnostics: {
62536
+ artifactError: typeof parsed.verdict === "string" ? undefined : "invalid `verdict` field",
62537
+ rejectedRowCount: req.rejected + ac.rejected,
62538
+ invalidFields: [...new Set([...req.invalidFields, ...ac.invalidFields])],
62539
+ arrayStates: { requirements: req.state, acceptanceCriteria: ac.state }
62540
+ }
62541
+ };
62070
62542
  }
62071
62543
  };
62072
62544
  });
@@ -62134,6 +62606,25 @@ class TaskLocator {
62134
62606
  }
62135
62607
  return null;
62136
62608
  }
62609
+ async findDuplicateWbs() {
62610
+ const wbsMap = new Map;
62611
+ for (const dir of this.folderDirs()) {
62612
+ for (const name of await readDirIfPresent(this.fs, dir)) {
62613
+ const captured = TASK_FILENAME_RE.exec(name);
62614
+ if (captured === null)
62615
+ continue;
62616
+ const wbs = captured[1];
62617
+ const hit = { wbs, name, filePath: `${dir}/${name}` };
62618
+ const existing = wbsMap.get(wbs);
62619
+ if (existing) {
62620
+ existing.push(hit);
62621
+ } else {
62622
+ wbsMap.set(wbs, [hit]);
62623
+ }
62624
+ }
62625
+ }
62626
+ return [...wbsMap.values()].filter((hits) => hits.length > 1);
62627
+ }
62137
62628
  }
62138
62629
  var TASK_FILENAME_RE;
62139
62630
  var init_task_locator = __esm(() => {
@@ -62420,11 +62911,32 @@ class FeatureService {
62420
62911
  }
62421
62912
  const appliedHops = [];
62422
62913
  for (const hop of hops) {
62914
+ if (hop === "active") {
62915
+ const conflict = await this.findOneActiveGoalConflict(featureId2);
62916
+ if (conflict !== null) {
62917
+ return {
62918
+ proposal: {
62919
+ ...proposal,
62920
+ reason: `Activation blocked by one-active-goal: P0 feature "${conflict.featureId}" is already ${conflict.status}`
62921
+ },
62922
+ applied: false,
62923
+ appliedHops,
62924
+ goalConflict: conflict
62925
+ };
62926
+ }
62927
+ }
62423
62928
  await this.transition(featureId2, hop);
62424
62929
  appliedHops.push(hop);
62425
62930
  }
62426
62931
  return { proposal, applied: true, appliedHops };
62427
62932
  }
62933
+ async findOneActiveGoalConflict(featureId2) {
62934
+ const feature = await this.show(featureId2);
62935
+ if (feature === null || feature.frontmatter.priority !== "P0")
62936
+ return null;
62937
+ const conflict = await findOtherP0InStatus(this.ctx.fs, this.ctx.featuresDir, featureId2, ["active"]);
62938
+ return conflict === null ? null : { featureId: conflict.id, status: conflict.status };
62939
+ }
62428
62940
  async syncAllFeatures(options) {
62429
62941
  const allFeatures = await this.list();
62430
62942
  const tasksByFeature = await this.collectTasksByFeature();
@@ -65158,6 +65670,21 @@ var init_task_check = __esm(() => {
65158
65670
  });
65159
65671
  }
65160
65672
  }
65673
+ const requiredSections = new Set(entry?.required ?? []);
65674
+ for (const sectionName of ["Testing", "Solution"]) {
65675
+ if (!requiredSections.has(sectionName))
65676
+ continue;
65677
+ const body = doc2.getSection(sectionName);
65678
+ if (body === null || !isPlaceholderBody(body))
65679
+ continue;
65680
+ findings.push({
65681
+ layer: "L3",
65682
+ code: FINDING_CODES.L3_REQUIRED_SECTION_PLACEHOLDER,
65683
+ severity: "error",
65684
+ section: sectionName,
65685
+ message: `${sectionName} is required at status '${status}' but is still placeholder-only \u2014 run \`spur task record <wbs>\` to fill it from the verdict artifact, or author it directly`
65686
+ });
65687
+ }
65161
65688
  const testBody = doc2.getSection("Testing");
65162
65689
  if (testBody !== null && !isPlaceholderBody(testBody)) {
65163
65690
  const hasCoverage = /coverage|\u2265\d+%|\d+\.\d+%|N\/A/i.test(testBody);
@@ -66030,15 +66557,15 @@ class TaskService {
66030
66557
  const variant = params.template ?? (params.featureId !== undefined ? "feature-impl" : DEFAULT_TASK_VARIANT);
66031
66558
  const status = params.status ?? (params.featureId !== undefined ? "todo" : "backlog");
66032
66559
  return this.writeService.createAllocated(folder, async () => {
66033
- if (params.dedupeWithinSec !== undefined && params.featureId !== undefined) {
66034
- const collision = await this.findDuplicateFollowUp(params.featureId, params.title, params.dedupeWithinSec);
66560
+ const dedupeWithinSec = params.dedupeWithinSec === null ? undefined : params.dedupeWithinSec ?? 300;
66561
+ if (dedupeWithinSec !== undefined && params.featureId !== undefined) {
66562
+ const collision = await this.findDuplicateFollowUp(params.featureId, params.title, dedupeWithinSec);
66035
66563
  if (collision !== null) {
66036
66564
  throw new DuplicateFollowUpError(collision.wbs, collision.name, params.title);
66037
66565
  }
66038
66566
  }
66039
- const wbs = await this.allocateWbs();
66040
66567
  const slug = this.slugify(params.title);
66041
- const filePath = this.resolveTaskPath(wbs, slug);
66568
+ const { wbs, filePath } = await this.allocateWbsChecked(slug);
66042
66569
  const now = new Date().toISOString();
66043
66570
  const rawTemplate = this.ctx.resolveTemplate?.(variant);
66044
66571
  if (rawTemplate !== undefined) {
@@ -66441,9 +66968,8 @@ ${issues}`);
66441
66968
  const status = hasSpec ? "todo" : "backlog";
66442
66969
  const variant = item.template ?? (item.feature_id !== undefined && item.feature_id !== null ? "feature-impl" : DEFAULT_TASK_VARIANT);
66443
66970
  return this.writeService.createAllocated(folder, async () => {
66444
- const wbs = await this.allocateWbs();
66445
66971
  const slug = this.slugify(item.name);
66446
- const filePath = this.resolveTaskPath(wbs, slug);
66972
+ const { wbs, filePath } = await this.allocateWbsChecked(slug);
66447
66973
  const now = new Date().toISOString();
66448
66974
  const rawTemplate = this.ctx.resolveTemplate?.(variant);
66449
66975
  if (rawTemplate !== undefined) {
@@ -66596,9 +67122,15 @@ ${block}` : block);
66596
67122
  }
66597
67123
  async allocateWbs() {
66598
67124
  let max = 0;
66599
- const dirs = this.ctx.foldersConfig ? [...new Set([this.ctx.tasksDir, ...Object.keys(this.ctx.foldersConfig.folders)])] : [this.ctx.tasksDir];
67125
+ const dirs = this.allFolderDirs();
67126
+ const folderFloors = new Map;
67127
+ if (this.ctx.foldersConfig) {
67128
+ for (const [key, entry] of Object.entries(this.ctx.foldersConfig.folders)) {
67129
+ folderFloors.set(this.ctx.fs.resolve(key), entry.baseCounter);
67130
+ }
67131
+ }
66600
67132
  for (const dir of dirs) {
66601
- const baseCounter = this.ctx.foldersConfig?.folders[dir]?.base_counter ?? 0;
67133
+ const baseCounter = folderFloors.get(dir) ?? 0;
66602
67134
  if (baseCounter > max)
66603
67135
  max = baseCounter;
66604
67136
  try {
@@ -66615,6 +67147,14 @@ ${block}` : block);
66615
67147
  }
66616
67148
  return String(max + 1).padStart(4, "0");
66617
67149
  }
67150
+ async allocateWbsChecked(slug) {
67151
+ const wbs = await this.allocateWbs();
67152
+ const existing = await this.locator.findByWbs(wbs);
67153
+ if (existing !== null) {
67154
+ throw new WbsCollisionError(wbs, existing.filePath, this.resolveTaskPath(wbs, slug));
67155
+ }
67156
+ return { wbs, filePath: this.resolveTaskPath(wbs, slug) };
67157
+ }
66618
67158
  async getFilePath(wbs) {
66619
67159
  const result = await this.findTaskFileName(wbs);
66620
67160
  if (!result)
@@ -66676,7 +67216,7 @@ ${block}` : block);
66676
67216
  return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
66677
67217
  }
66678
67218
  }
66679
- var DependencyMutationError, SectionMutationError, DuplicateFollowUpError, ROSTER_START = "<!-- AUTO-GENERATED by spur task refresh-roster -->", ROSTER_END = "<!-- END AUTO-GENERATED -->", ROSTER_REGION_RE, TASK_ACTION_COMMANDS, DEFAULT_CREATION_SECTIONS;
67219
+ var DependencyMutationError, SectionMutationError, DuplicateFollowUpError, WbsCollisionError, ROSTER_START = "<!-- AUTO-GENERATED by spur task refresh-roster -->", ROSTER_END = "<!-- END AUTO-GENERATED -->", ROSTER_REGION_RE, TASK_ACTION_COMMANDS, DEFAULT_CREATION_SECTIONS;
66680
67220
  var init_task_service = __esm(() => {
66681
67221
  init_src2();
66682
67222
  init_task_locator();
@@ -66709,6 +67249,18 @@ var init_task_service = __esm(() => {
66709
67249
  this.attemptedName = attemptedName;
66710
67250
  }
66711
67251
  };
67252
+ WbsCollisionError = class WbsCollisionError extends Error {
67253
+ wbs;
67254
+ existingPath;
67255
+ attemptedPath;
67256
+ constructor(wbs, existingPath, attemptedPath) {
67257
+ super(`wbs-collision: WBS ${wbs} already exists at "${existingPath}". ` + `Refusing to overwrite with "${attemptedPath}". ` + `Re-run create; if the collision persists, inspect the corpus with: spur task check.`);
67258
+ this.name = "WbsCollisionError";
67259
+ this.wbs = wbs;
67260
+ this.existingPath = existingPath;
67261
+ this.attemptedPath = attemptedPath;
67262
+ }
67263
+ };
66712
67264
  ROSTER_REGION_RE = /<!--[ \t]*AUTO-GENERATED[^>]*-->[\s\S]*?<!--[ \t]*END[ \t]*AUTO-GENERATED[^>]*-->/g;
66713
67265
  TASK_ACTION_COMMANDS = {
66714
67266
  refine: (wbs) => `/sp:dev-refine ${wbs} --auto`,
@@ -66727,8 +67279,9 @@ var init_task_service = __esm(() => {
66727
67279
  // ../../packages/app/src/services/task-verdict.ts
66728
67280
  function deriveVerdict(answerText, taskCheckPassed) {
66729
67281
  const requirements = extractRequirements(answerText);
66730
- const acceptanceCriteria = applyAcceptanceCriteriaEvidenceRule(extractAcceptanceCriteria(answerText));
66731
- const checks4 = extractChecks(answerText, taskCheckPassed, acceptanceCriteria);
67282
+ const parsedAc = extractAcceptanceCriteria(answerText);
67283
+ const acceptanceCriteria = applyAcceptanceCriteriaEvidenceRule(parsedAc.rows);
67284
+ const checks4 = extractChecks(answerText, taskCheckPassed, acceptanceCriteria, parsedAc.dropped);
66732
67285
  if (requirements.length === 0) {
66733
67286
  return { verdict: "UNKNOWN", requirements, acceptanceCriteria, checks: checks4 };
66734
67287
  }
@@ -66796,6 +67349,7 @@ function normalizeStatus(raw) {
66796
67349
  }
66797
67350
  function extractAcceptanceCriteria(text4) {
66798
67351
  const rows = [];
67352
+ const dropped = [];
66799
67353
  const lines = text4.split(`
66800
67354
  `);
66801
67355
  let inTable = false;
@@ -66817,15 +67371,19 @@ function extractAcceptanceCriteria(text4) {
66817
67371
  continue;
66818
67372
  if (inTable && cells.length >= 4) {
66819
67373
  const id = cells[0] ?? "";
66820
- const status = normalizeAcceptanceCriteriaStatus(cells[1] ?? "");
66821
- const evidenceType = normalizeEvidenceType(cells[2] ?? "");
67374
+ const statusRaw = cells[1] ?? "";
67375
+ const evidenceTypeRaw = cells[2] ?? "";
67376
+ const status = normalizeAcceptanceCriteriaStatus(statusRaw);
67377
+ const evidenceType = normalizeEvidenceType(evidenceTypeRaw);
66822
67378
  const evidence = cells[3] ?? "";
66823
67379
  if (status !== null && evidenceType !== null && id.length > 0) {
66824
67380
  rows.push({ id, status, evidenceType, evidence });
67381
+ } else if (id.length > 0) {
67382
+ dropped.push(evidenceType === null && status !== null ? `${id} (unrecognised evidence type "${evidenceTypeRaw}")` : `${id} (unrecognised status "${statusRaw}")`);
66825
67383
  }
66826
67384
  }
66827
67385
  }
66828
- return rows;
67386
+ return { rows, dropped };
66829
67387
  }
66830
67388
  function normalizeAcceptanceCriteriaStatus(raw) {
66831
67389
  const upper = raw.toUpperCase();
@@ -66845,8 +67403,9 @@ function normalizeEvidenceType(raw) {
66845
67403
  return "test";
66846
67404
  if (normalized === "command")
66847
67405
  return "command";
66848
- if (normalized === "static-ref" || normalized === "static")
67406
+ if (normalized === "static-ref" || normalized === "static" || normalized === "doc" || normalized === "docs" || normalized === "documentation") {
66849
67407
  return "static-ref";
67408
+ }
66850
67409
  if (normalized === "manual-review" || normalized === "manual")
66851
67410
  return "manual-review";
66852
67411
  if (normalized === "llm-judge" || normalized === "judge")
@@ -66869,7 +67428,7 @@ function requiresExecutableEvidence(id) {
66869
67428
  const nonBehavior = normalized.includes("[non-behavior]") || normalized.includes("[docs-only]") || normalized.includes("[doc-only]");
66870
67429
  return !nonCore && !nonBehavior;
66871
67430
  }
66872
- function extractChecks(_text, taskCheckPassed, acceptanceCriteria) {
67431
+ function extractChecks(_text, taskCheckPassed, acceptanceCriteria, droppedAcRows = []) {
66873
67432
  const checks4 = [
66874
67433
  {
66875
67434
  name: "spur task check",
@@ -66901,6 +67460,13 @@ function extractChecks(_text, taskCheckPassed, acceptanceCriteria) {
66901
67460
  }
66902
67461
  }
66903
67462
  }
67463
+ if (droppedAcRows.length > 0) {
67464
+ checks4.push({
67465
+ name: "ac-row-dropped",
67466
+ status: "fail",
67467
+ evidence: `${droppedAcRows.length} AC row(s) could not be parsed and were omitted from the verdict: ` + `${droppedAcRows.join("; ")}. Accepted evidence types: test, command, static-ref (aliases: ` + "static, doc, docs, documentation), manual-review, llm-judge, n/a. Accepted statuses: " + "MET, PARTIAL, UNMET, N/A."
67468
+ });
67469
+ }
66904
67470
  if (acceptanceCriteria.length > 0) {
66905
67471
  const downgraded = acceptanceCriteria.filter((row) => row.status === "PARTIAL" && requiresExecutableEvidence(row.id) && row.evidenceType !== "test" && row.evidenceType !== "command");
66906
67472
  checks4.push({
@@ -67681,6 +68247,110 @@ var init_token_ledger_watcher = __esm(() => {
67681
68247
  init_token_ledger_service();
67682
68248
  });
67683
68249
 
68250
+ // ../../packages/app/src/observability/run-output-sink.ts
68251
+ import { closeSync as closeSync4, mkdirSync as mkdirSync6, openSync as openSync4, writeSync as writeSync2 } from "fs";
68252
+ import { join as join14 } from "path";
68253
+
68254
+ class RunOutputSink {
68255
+ filePath;
68256
+ maxBytes;
68257
+ maxLines;
68258
+ fd;
68259
+ bytes = 0;
68260
+ lines = 0;
68261
+ truncated = false;
68262
+ closed = false;
68263
+ constructor(options) {
68264
+ this.filePath = join14(options.dir, `${options.runId}-output.log`);
68265
+ this.maxBytes = options.maxBytes ?? DEFAULT_OUTPUT_MAX_BYTES;
68266
+ this.maxLines = options.maxLines;
68267
+ try {
68268
+ mkdirSync6(options.dir, { recursive: true });
68269
+ this.fd = openSync4(this.filePath, "a");
68270
+ } catch {
68271
+ this.fd = undefined;
68272
+ }
68273
+ }
68274
+ get isTruncated() {
68275
+ return this.truncated;
68276
+ }
68277
+ observe(event2) {
68278
+ if (this.fd === undefined || this.closed)
68279
+ return;
68280
+ switch (event2.kind) {
68281
+ case "output":
68282
+ this.appendChunk(event2.at, event2.stream, event2.chunk);
68283
+ break;
68284
+ case "started":
68285
+ this.append(`# agent output \u2014 run ${event2.runId} \u2014 ${event2.agent} \u2014 ${event2.at}
68286
+ `);
68287
+ this.append(`# invocation: ${event2.invocation}
68288
+ `);
68289
+ break;
68290
+ case "dropped":
68291
+ this.append(`
68292
+ === [dropped] ${event2.chunks} chunk(s) discarded by the lifecycle relay under backpressure ===
68293
+ `);
68294
+ break;
68295
+ case "finished":
68296
+ this.append(`
68297
+ === run ${event2.outcome} (exit ${event2.exitCode}) after ${event2.durationMs}ms ===
68298
+ `);
68299
+ break;
68300
+ default:
68301
+ break;
68302
+ }
68303
+ }
68304
+ close() {
68305
+ if (this.closed)
68306
+ return;
68307
+ this.closed = true;
68308
+ if (this.fd !== undefined) {
68309
+ try {
68310
+ closeSync4(this.fd);
68311
+ } catch {}
68312
+ this.fd = undefined;
68313
+ }
68314
+ }
68315
+ appendChunk(at, stream, chunk) {
68316
+ if (this.truncated)
68317
+ return;
68318
+ const text4 = `[${at}] ${stream}: ${chunk}
68319
+ `;
68320
+ const chunkBytes = Buffer.byteLength(text4);
68321
+ const chunkLines = countNewlines(text4);
68322
+ if (this.bytes + chunkBytes > this.maxBytes || this.maxLines !== undefined && this.lines + chunkLines > this.maxLines) {
68323
+ this.truncated = true;
68324
+ this.append(TRUNCATION_MARKER);
68325
+ return;
68326
+ }
68327
+ this.append(text4);
68328
+ }
68329
+ append(text4) {
68330
+ if (this.fd === undefined || this.closed)
68331
+ return;
68332
+ try {
68333
+ writeSync2(this.fd, text4);
68334
+ this.bytes += Buffer.byteLength(text4);
68335
+ this.lines += countNewlines(text4);
68336
+ } catch {}
68337
+ }
68338
+ }
68339
+ function countNewlines(text4) {
68340
+ let count3 = 0;
68341
+ for (let i2 = 0;i2 < text4.length; i2 += 1) {
68342
+ if (text4.charCodeAt(i2) === 10)
68343
+ count3 += 1;
68344
+ }
68345
+ return count3;
68346
+ }
68347
+ var DEFAULT_OUTPUT_MAX_BYTES, TRUNCATION_MARKER = `
68348
+ === [truncated] agent output capture reached its configured bound; further chunks were not written ===
68349
+ `;
68350
+ var init_run_output_sink = __esm(() => {
68351
+ DEFAULT_OUTPUT_MAX_BYTES = 1024 * 1024;
68352
+ });
68353
+
67684
68354
  // ../../packages/app/src/workflow/steering.ts
67685
68355
  class WorkflowSteeringController {
67686
68356
  onAck;
@@ -67923,16 +68593,18 @@ var init_steering = __esm(() => {
67923
68593
  });
67924
68594
 
67925
68595
  // ../../packages/app/src/workflow/actions/agent-run.ts
67926
- import { dirname as dirname12, isAbsolute as isAbsolute2, join as join14 } from "path";
68596
+ import { dirname as dirname12, isAbsolute as isAbsolute2, join as join15 } from "path";
67927
68597
 
67928
68598
  class AgentRunActionRunner {
67929
68599
  observabilityBus;
67930
68600
  steeringController;
68601
+ outputLog;
67931
68602
  kind = KIND;
67932
68603
  agentService;
67933
- constructor(agentService, observabilityBus, steeringController) {
68604
+ constructor(agentService, observabilityBus, steeringController, outputLog) {
67934
68605
  this.observabilityBus = observabilityBus;
67935
68606
  this.steeringController = steeringController;
68607
+ this.outputLog = outputLog;
67936
68608
  this.agentService = agentService;
67937
68609
  }
67938
68610
  async execute(options, context4) {
@@ -67943,7 +68615,8 @@ class AgentRunActionRunner {
67943
68615
  const cwd = asOptionalString(options.cwd) ?? context4.workdir ?? ".";
67944
68616
  let continueFlag = asOptionalBoolean(options.continue);
67945
68617
  const latch = context4.vars.__agentSession;
67946
- if (continueFlag === undefined && latch === "open") {
68618
+ const latchAutoContinued = continueFlag === undefined && latch === "open";
68619
+ if (latchAutoContinued) {
67947
68620
  continueFlag = true;
67948
68621
  }
67949
68622
  if (input === undefined && !continueFlag) {
@@ -67975,78 +68648,100 @@ class AgentRunActionRunner {
67975
68648
  const expectFile = asOptionalString(options.expectFile);
67976
68649
  const capture = asOptionalBoolean(options.capture) || answerFile !== undefined;
67977
68650
  const agentLabel = agent ?? "<default>";
67978
- const observer = this.observabilityBus === undefined ? undefined : (event2) => {
68651
+ const outputLog = this.outputLog;
68652
+ const sink = outputLog === undefined ? undefined : new RunOutputSink({
68653
+ dir: join15(cwd, ".spur", "run"),
68654
+ runId: context4.runId,
68655
+ ...outputLog.maxBytes !== undefined ? { maxBytes: outputLog.maxBytes } : {},
68656
+ ...outputLog.maxLines !== undefined ? { maxLines: outputLog.maxLines } : {}
68657
+ });
68658
+ const observer = this.observabilityBus === undefined && sink === undefined ? undefined : (event2) => {
68659
+ sink?.observe(event2);
67979
68660
  this.observabilityBus?.emit("workflow.agent", event2);
67980
68661
  };
67981
68662
  const actionId = context4.actionId ?? `${context4.runId}:${context4.stateOrNodeId}`;
67982
68663
  const steeringPolicy = parseSteeringPolicy(options);
67983
- let steeringSignal = this.steeringController?.begin(context4.runId, actionId, steeringPolicy);
68664
+ let resumeRetried = false;
67984
68665
  let steeringNote;
67985
68666
  let traced;
67986
- while (true) {
67987
- traced = await this.agentService.runTraced(input, flags, undefined, {
67988
- correlation: {
67989
- runId: context4.runId,
67990
- executionId: crypto.randomUUID(),
67991
- actionId
67992
- },
67993
- ...observer !== undefined ? { observer } : {},
67994
- ...steeringSignal !== undefined ? { signal: steeringSignal } : {}
67995
- });
67996
- if (this.steeringController === undefined)
68667
+ try {
68668
+ for (;; ) {
68669
+ steeringNote = undefined;
68670
+ let steeringSignal = this.steeringController?.begin(context4.runId, actionId, steeringPolicy);
68671
+ while (true) {
68672
+ traced = await this.agentService.runTraced(input, flags, undefined, {
68673
+ correlation: {
68674
+ runId: context4.runId,
68675
+ executionId: crypto.randomUUID(),
68676
+ actionId
68677
+ },
68678
+ ...observer !== undefined ? { observer } : {},
68679
+ ...steeringSignal !== undefined ? { signal: steeringSignal } : {}
68680
+ });
68681
+ if (this.steeringController === undefined)
68682
+ break;
68683
+ const decision = await this.steeringController.boundary(traced.exitCode === 0);
68684
+ if (decision.operation === "retry") {
68685
+ steeringSignal = this.steeringController.nextAttempt();
68686
+ continue;
68687
+ }
68688
+ if (decision.operation === "note")
68689
+ steeringNote = decision.note;
68690
+ if (decision.operation === "abort" && traced.exitCode === 0) {
68691
+ traced = {
68692
+ ...traced,
68693
+ exitCode: 3,
68694
+ signal: "STEERING_ABORT",
68695
+ message: "aborted at steering boundary"
68696
+ };
68697
+ }
68698
+ break;
68699
+ }
68700
+ this.steeringController?.complete();
68701
+ if (!resumeRetried && latchAutoContinued && traced.exitCode === 2) {
68702
+ resumeRetried = true;
68703
+ delete flags.continue;
68704
+ continue;
68705
+ }
67997
68706
  break;
67998
- const decision = await this.steeringController.boundary(traced.exitCode === 0);
67999
- if (decision.operation === "retry") {
68000
- steeringSignal = this.steeringController.nextAttempt();
68001
- continue;
68002
68707
  }
68003
- if (decision.operation === "note")
68004
- steeringNote = decision.note;
68005
- if (decision.operation === "abort" && traced.exitCode === 0) {
68006
- traced = {
68007
- ...traced,
68008
- exitCode: 3,
68009
- signal: "STEERING_ABORT",
68010
- message: "aborted at steering boundary"
68011
- };
68708
+ const { exitCode, stdout: answer } = traced;
68709
+ const ok = exitCode === 0;
68710
+ const invocation = traced.invocation;
68711
+ if (capture && answerFile !== undefined) {
68712
+ const target = isAbsolute2(answerFile) ? answerFile : join15(cwd, answerFile);
68713
+ const fs3 = createNodeFileSystem3(cwd);
68714
+ await fs3.ensureDir(dirname12(target));
68715
+ await fs3.writeFile(target, answer);
68716
+ }
68717
+ if (ok && expectFile !== undefined) {
68718
+ const target = isAbsolute2(expectFile) ? expectFile : join15(cwd, expectFile);
68719
+ const fs3 = createNodeFileSystem3(cwd);
68720
+ if (!await fs3.exists(target)) {
68721
+ return {
68722
+ ok: false,
68723
+ data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68724
+ error: `agent.run (${agentLabel}) exited 0 but expected file is absent: ${expectFile}`
68725
+ };
68726
+ }
68012
68727
  }
68013
- break;
68014
- }
68015
- this.steeringController?.complete();
68016
- const { exitCode, stdout: answer } = traced;
68017
- const ok = exitCode === 0;
68018
- const invocation = traced.invocation;
68019
- if (capture && answerFile !== undefined) {
68020
- const target = isAbsolute2(answerFile) ? answerFile : join14(cwd, answerFile);
68021
- const fs3 = createNodeFileSystem3(cwd);
68022
- await fs3.ensureDir(dirname12(target));
68023
- await fs3.writeFile(target, answer);
68024
- }
68025
- if (ok && expectFile !== undefined) {
68026
- const target = isAbsolute2(expectFile) ? expectFile : join14(cwd, expectFile);
68027
- const fs3 = createNodeFileSystem3(cwd);
68028
- if (!await fs3.exists(target)) {
68029
- return {
68030
- ok: false,
68031
- data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68032
- error: `agent.run (${agentLabel}) exited 0 but expected file is absent: ${expectFile}`
68033
- };
68728
+ if (!ok) {
68729
+ await writePartialWorkArtifact(context4, agentLabel, model, traced, cwd);
68034
68730
  }
68731
+ const stepLabel = context4.stateOrNodeId;
68732
+ const error51 = ok ? undefined : traced.signal !== undefined ? timeoutMs !== undefined ? `agent.run '${stepLabel}' (${agentLabel}) terminated by signal ${traced.signal} (configured timeout: ${timeoutMs}ms; timeout or cancellation); see partial-work artifact` : `agent.run '${stepLabel}' (${agentLabel}) was cancelled by signal ${traced.signal}; see partial-work artifact` : traced.message !== undefined ? `agent.run '${stepLabel}' (${agentLabel}) dispatch failed: ${traced.message}` : `agent.run '${stepLabel}' (${agentLabel}) exited with code ${exitCode}`;
68733
+ return {
68734
+ ok,
68735
+ data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68736
+ error: error51,
68737
+ setVars: ok ? {
68738
+ __agentSession: resumeRetried ? "no-resume" : "open",
68739
+ ...steeringNote !== undefined ? { __steeringNote: steeringNote } : {}
68740
+ } : undefined
68741
+ };
68742
+ } finally {
68743
+ sink?.close();
68035
68744
  }
68036
- if (!ok) {
68037
- await writePartialWorkArtifact(context4, agentLabel, model, traced, cwd);
68038
- }
68039
- const stepLabel = context4.stateOrNodeId;
68040
- const error51 = ok ? undefined : traced.signal !== undefined ? timeoutMs !== undefined ? `agent.run '${stepLabel}' (${agentLabel}) terminated by signal ${traced.signal} (configured timeout: ${timeoutMs}ms; timeout or cancellation); see partial-work artifact` : `agent.run '${stepLabel}' (${agentLabel}) was cancelled by signal ${traced.signal}; see partial-work artifact` : traced.message !== undefined ? `agent.run '${stepLabel}' (${agentLabel}) dispatch failed: ${traced.message}` : `agent.run '${stepLabel}' (${agentLabel}) exited with code ${exitCode}`;
68041
- return {
68042
- ok,
68043
- data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68044
- error: error51,
68045
- setVars: ok ? {
68046
- __agentSession: "open",
68047
- ...steeringNote !== undefined ? { __steeringNote: steeringNote } : {}
68048
- } : undefined
68049
- };
68050
68745
  }
68051
68746
  }
68052
68747
  function buildResultData(exitCode, agentLabel, capture, answer, invocation) {
@@ -68132,7 +68827,7 @@ async function writePartialWorkArtifact(context4, agentLabel, model, traced, cwd
68132
68827
  ""
68133
68828
  ].join(`
68134
68829
  `);
68135
- const target = join14(cwd, ".spur", "run", `${context4.runId}-${context4.stateOrNodeId}-partial.md`);
68830
+ const target = join15(cwd, ".spur", "run", `${context4.runId}-${context4.stateOrNodeId}-partial.md`);
68136
68831
  const fs3 = createNodeFileSystem3(cwd);
68137
68832
  await fs3.ensureDir(dirname12(target));
68138
68833
  await fs3.writeFile(target, body);
@@ -68162,6 +68857,7 @@ ${text4.slice(text4.length - maxChars)}`;
68162
68857
  var PARTIAL_ARTIFACT_TAIL_CHARS = 4000, KIND = "agent.run";
68163
68858
  var init_agent_run = __esm(() => {
68164
68859
  init_dist5();
68860
+ init_run_output_sink();
68165
68861
  init_steering();
68166
68862
  });
68167
68863
 
@@ -68690,7 +69386,7 @@ var init_rule_check = __esm(() => {
68690
69386
  // ../../packages/app/src/workflow/builtins.ts
68691
69387
  function registerSpurBuiltins(host, options) {
68692
69388
  const fileSystem = options.fileSystem ?? createNodeFileSystem3();
68693
- host.registerAction(new AgentRunActionRunner(options.agentService, options.observabilityBus, options.steeringController), "builtin");
69389
+ host.registerAction(new AgentRunActionRunner(options.agentService, options.observabilityBus, options.steeringController, options.outputLog), "builtin");
68694
69390
  host.registerAction(new RuleCheckActionRunner(options.ruleService), "builtin");
68695
69391
  host.registerAction(new FileExistsActionRunner(fileSystem), "builtin");
68696
69392
  host.registerAction(new FileReadActionRunner(fileSystem), "builtin");
@@ -68870,7 +69566,7 @@ var init_observability = __esm(() => {
68870
69566
 
68871
69567
  // ../../packages/app/src/services/workflow-service.ts
68872
69568
  import { homedir as homedir5 } from "os";
68873
- import { join as join15, resolve as resolve4 } from "path";
69569
+ import { join as join16, resolve as resolve4 } from "path";
68874
69570
  function signalSubprocess(pid) {
68875
69571
  if (!Number.isInteger(pid) || pid <= 1)
68876
69572
  return false;
@@ -69093,7 +69789,7 @@ class WorkflowAppService {
69093
69789
  }
69094
69790
  async list(workflowPaths = [".spur/workflows/"]) {
69095
69791
  const projectRoot = this.ctx.cwd;
69096
- const globalRoot = join15(homedir5(), ".config", "spur");
69792
+ const globalRoot = join16(homedir5(), ".config", "spur");
69097
69793
  const layers = [];
69098
69794
  const entries = [];
69099
69795
  const scannedPaths = new Set;
@@ -69197,7 +69893,12 @@ class WorkflowAppService {
69197
69893
  });
69198
69894
  }
69199
69895
  }
69200
- return { run, events: events2 };
69896
+ const outputArtifact = await outputArtifactForRun(this.ctx.cwd, runId);
69897
+ return {
69898
+ run,
69899
+ events: events2,
69900
+ ...outputArtifact !== undefined ? { outputArtifact } : {}
69901
+ };
69201
69902
  }
69202
69903
  async createEngineService(opts = {}) {
69203
69904
  const processExec = this.ctx.processExecutor?.();
@@ -69210,7 +69911,8 @@ class WorkflowAppService {
69210
69911
  httpRequester: this.ctx.httpRequester?.(),
69211
69912
  hostAllowlist: this.ctx.hostAllowlist?.(),
69212
69913
  ...bus !== undefined ? { observabilityBus: bus } : {},
69213
- ...opts.steeringController !== undefined ? { steeringController: opts.steeringController } : {}
69914
+ ...opts.steeringController !== undefined ? { steeringController: opts.steeringController } : {},
69915
+ outputLog: await resolveOutputLogConfig(this.ctx.cwd)
69214
69916
  });
69215
69917
  const db2 = await this.ctx.getDb();
69216
69918
  let persistence2 = new DbWorkflowPersistenceAdapter(db2);
@@ -69225,6 +69927,23 @@ async function fileExists(path9) {
69225
69927
  const fs3 = createNodeFileSystem3();
69226
69928
  return await fs3.exists(path9);
69227
69929
  }
69930
+ async function resolveOutputLogConfig(cwd) {
69931
+ try {
69932
+ const output2 = (await loadSpurConfig(cwd)).agent?.output;
69933
+ if (output2 === undefined)
69934
+ return {};
69935
+ return {
69936
+ ...output2["max-bytes"] !== undefined ? { maxBytes: output2["max-bytes"] } : {},
69937
+ ...output2["max-lines"] !== undefined ? { maxLines: output2["max-lines"] } : {}
69938
+ };
69939
+ } catch {
69940
+ return {};
69941
+ }
69942
+ }
69943
+ async function outputArtifactForRun(cwd, runId) {
69944
+ const relative4 = join16(".spur", "run", `${runId}-output.log`);
69945
+ return await fileExists(join16(cwd, relative4)) ? relative4 : undefined;
69946
+ }
69228
69947
  async function scanWorkflowFiles(rootPath, source) {
69229
69948
  const entries = [];
69230
69949
  const fs3 = createNodeFileSystem3();
@@ -69304,6 +70023,7 @@ function rowToTraceEntry(row) {
69304
70023
  }
69305
70024
  var TASK_PIPELINE_WORKFLOW = "task-pipeline", EMBEDDED_SCHEMA_PREFIX = "\x00embedded-spur", SPUR_SCHEMA_MANIFEST = "@gobing-ai/spur/package.json", PIPELINE_LINK_KIND = "pipeline";
69306
70025
  var init_workflow_service = __esm(() => {
70026
+ init_loader();
69307
70027
  init_src2();
69308
70028
  init_dist7();
69309
70029
  init_dist5();
@@ -69537,7 +70257,7 @@ function formatDuration(ms) {
69537
70257
  var isAgentExecution = (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);
69538
70258
 
69539
70259
  // ../../packages/app/src/workflow/trace-writer.ts
69540
- import { dirname as dirname13, join as join16 } from "path";
70260
+ import { dirname as dirname13, join as join17 } from "path";
69541
70261
 
69542
70262
  class WorkflowTraceWriter {
69543
70263
  path;
@@ -69545,7 +70265,7 @@ class WorkflowTraceWriter {
69545
70265
  pending = Promise.resolve();
69546
70266
  constructor(cwd, runId) {
69547
70267
  const safeRunId = runId.replace(/[^A-Za-z0-9._-]/g, "_");
69548
- this.path = join16(cwd, ".spur", "runs", "workflow", `${safeRunId}.jsonl`);
70268
+ this.path = join17(cwd, ".spur", "runs", "workflow", `${safeRunId}.jsonl`);
69549
70269
  }
69550
70270
  attach(bus) {
69551
70271
  bus.on("workflow.run.started", (event2) => this.enqueue("workflow.run.started", event2));
@@ -69637,6 +70357,7 @@ __export(exports_src2, {
69637
70357
  WorkflowTraceWriter: () => WorkflowTraceWriter,
69638
70358
  WorkflowSteeringController: () => WorkflowSteeringController,
69639
70359
  WorkflowAppService: () => WorkflowAppService,
70360
+ WbsCollisionError: () => WbsCollisionError,
69640
70361
  UnsupportedProcessPlatformError: () => UnsupportedProcessPlatformError,
69641
70362
  TokenLedgerWatcher: () => TokenLedgerWatcher,
69642
70363
  TokenLedgerService: () => TokenLedgerService,
@@ -69827,19 +70548,19 @@ var {
69827
70548
  init_src();
69828
70549
  init_loader();
69829
70550
 
69830
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70551
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application-node.js
69831
70552
  init_dist4();
69832
70553
  init_dist5();
69833
70554
  import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
69834
70555
  import { dirname as dirname5 } from "path";
69835
70556
 
69836
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70557
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/index.js
69837
70558
  init_default_observers();
69838
70559
  init_event_bus();
69839
70560
  init_file_observer();
69840
70561
  init_logger3();
69841
70562
 
69842
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/scheduler/noop.js
70563
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler/noop.js
69843
70564
  class NoopSchedulerAdapter {
69844
70565
  constructor() {}
69845
70566
  register(_cron, _action) {}
@@ -69847,7 +70568,7 @@ class NoopSchedulerAdapter {
69847
70568
  async stop() {}
69848
70569
  }
69849
70570
 
69850
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/scheduler/factory.js
70571
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler/factory.js
69851
70572
  function initScheduler(adapter, cronEntries) {
69852
70573
  const resolved = adapter ?? new NoopSchedulerAdapter;
69853
70574
  if (cronEntries) {
@@ -69858,7 +70579,7 @@ function initScheduler(adapter, cronEntries) {
69858
70579
  return resolved;
69859
70580
  }
69860
70581
 
69861
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application/plugins/builtins.js
70582
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/plugins/builtins.js
69862
70583
  init_logger3();
69863
70584
  init_metrics();
69864
70585
  init_sdk();
@@ -69951,7 +70672,7 @@ function dbPlugin(db2) {
69951
70672
  };
69952
70673
  }
69953
70674
 
69954
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application/plugins/host.js
70675
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/plugins/host.js
69955
70676
  init_logger3();
69956
70677
 
69957
70678
  class PluginHost {
@@ -70039,7 +70760,7 @@ class PluginHost {
70039
70760
  }
70040
70761
  }
70041
70762
 
70042
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70763
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70043
70764
  async function performShutdown(state, reason) {
70044
70765
  if (state.stopped)
70045
70766
  return;
@@ -70150,10 +70871,10 @@ async function runApplication(options) {
70150
70871
  }
70151
70872
  }
70152
70873
 
70153
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70874
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70154
70875
  init_scheduler_node();
70155
70876
 
70156
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
70877
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
70157
70878
  var import_api14 = __toESM(require_src(), 1);
70158
70879
 
70159
70880
  // ../../node_modules/.bun/@opentelemetry+exporter-metrics-otlp-http@0.218.0+e40b0dfdd726a224/node_modules/@opentelemetry/exporter-metrics-otlp-http/build/esm/OTLPMetricExporterBase.js
@@ -73169,7 +73890,7 @@ class OTLPTraceExporter extends import_otlp_exporter_base2.OTLPExporterBase {
73169
73890
  }), JsonTraceSerializer));
73170
73891
  }
73171
73892
  }
73172
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
73893
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
73173
73894
  var import_resources2 = __toESM(require_src4(), 1);
73174
73895
  var import_sdk_trace_node = __toESM(require_src8(), 1);
73175
73896
  var import_semantic_conventions = __toESM(require_src2(), 1);
@@ -73220,7 +73941,7 @@ async function shutdownNodeTelemetry() {
73220
73941
  await Promise.all(pending);
73221
73942
  }
73222
73943
 
73223
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.14+a32276a722fab3c8/node_modules/@gobing-ai/ts-infra/dist/application-node.js
73944
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application-node.js
73224
73945
  class ConfigValidationError extends Error {
73225
73946
  constructor(message) {
73226
73947
  super(message);
@@ -73309,11 +74030,13 @@ async function runNodeApplication(options) {
73309
74030
  const logFilePath = yamlBootstrap.logging?.filePath;
73310
74031
  const loggingConfig = typeof logFilePath === "string" ? { ...loggingOpts, fileSink: createFileSink(logFilePath) } : loggingOpts;
73311
74032
  const schedulerConfig = {};
73312
- const rawSched = { ...schedulerOpts };
73313
- if (rawSched.enabled === true) {
74033
+ if (schedulerOpts.enabled === true) {
73314
74034
  schedulerConfig.enabled = true;
73315
74035
  schedulerConfig.autoStart = schedulerOpts.autoStart;
73316
- schedulerConfig.adapter = new NodeSchedulerAdapter;
74036
+ schedulerConfig.adapter = schedulerOpts.adapter ?? new NodeSchedulerAdapter;
74037
+ if (schedulerOpts.entries) {
74038
+ schedulerConfig.entries = schedulerOpts.entries;
74039
+ }
73317
74040
  }
73318
74041
  const plugins = [];
73319
74042
  let dbAdapter = options.services?.db;
@@ -77366,7 +78089,7 @@ init_loader();
77366
78089
  init_src2();
77367
78090
  import { existsSync as existsSync9 } from "fs";
77368
78091
  import { homedir as homedir6 } from "os";
77369
- import { join as join17, resolve as resolve5 } from "path";
78092
+ import { join as join18, resolve as resolve5 } from "path";
77370
78093
 
77371
78094
  // src/workflow/resolve-spur-bin.ts
77372
78095
  import { basename as basename3 } from "path";
@@ -77384,22 +78107,22 @@ function resolveSpurBin() {
77384
78107
  }
77385
78108
 
77386
78109
  // src/workflow/make-lifecycle-adapter.ts
77387
- var GLOBAL_CONFIG_DIR = join17(".config", "spur");
78110
+ var GLOBAL_CONFIG_DIR = join18(".config", "spur");
77388
78111
  function globalConfigRoot(context4) {
77389
78112
  const override = context4.env.SPUR_GLOBAL_RULES_DIR;
77390
- return override !== undefined && override.length > 0 ? resolve5(context4.cwd, override) : join17(homedir6(), GLOBAL_CONFIG_DIR);
78113
+ return override !== undefined && override.length > 0 ? resolve5(context4.cwd, override) : join18(homedir6(), GLOBAL_CONFIG_DIR);
77391
78114
  }
77392
78115
  function resolveWorkflowPath(context4, profile) {
77393
78116
  const bundledRoot = bundledConfigRoot();
77394
78117
  if (bundledRoot !== null) {
77395
- const bundledPath = join17(bundledRoot, "workflows", `${profile.workflowName}.yaml`);
78118
+ const bundledPath = join18(bundledRoot, "workflows", `${profile.workflowName}.yaml`);
77396
78119
  if (existsSync9(bundledPath))
77397
78120
  return bundledPath;
77398
78121
  }
77399
- const projectPath = join17(context4.cwd, ".spur", "workflows", `${profile.workflowName}.yaml`);
78122
+ const projectPath = join18(context4.cwd, ".spur", "workflows", `${profile.workflowName}.yaml`);
77400
78123
  if (existsSync9(projectPath))
77401
78124
  return projectPath;
77402
- const globalPath = join17(globalConfigRoot(context4), "workflows", `${profile.workflowName}.yaml`);
78125
+ const globalPath = join18(globalConfigRoot(context4), "workflows", `${profile.workflowName}.yaml`);
77403
78126
  if (existsSync9(globalPath))
77404
78127
  return globalPath;
77405
78128
  return null;
@@ -77540,9 +78263,9 @@ function registerFeatureCommand(program2, context4) {
77540
78263
  let next = forwardPath[current];
77541
78264
  while (next !== undefined) {
77542
78265
  if (current === "active") {
77543
- await assertFeatureCheckPass(context4, id, options.folder, false);
78266
+ await assertFeatureCheckPass(context4, id, options.folder, false, "verifying");
77544
78267
  } else if (current === "verifying") {
77545
- await assertFeatureCheckPass(context4, id, options.folder, true);
78268
+ await assertFeatureCheckPass(context4, id, options.folder, true, "done");
77546
78269
  }
77547
78270
  const result = await svc.transition(id, next);
77548
78271
  history.push({ from: result.fromStatus ?? current, to: result.toStatus ?? next });
@@ -77632,7 +78355,7 @@ function registerFeatureCommand(program2, context4) {
77632
78355
  context4.setExitCode(1);
77633
78356
  }
77634
78357
  });
77635
- feature.command("check").summary("Validate feature file(s) through the four-layer check (design \xA73).").argument("[id]", "Feature ID (validates all features in the folder when omitted)").option("--strict", "Elevate warnings to failures").option("--folder <path>", "Custom features folder").option("--json", "Output machine-readable JSON").action(async (id, options) => {
78358
+ feature.command("check").summary("Validate feature file(s) through the four-layer check (design \xA73).").argument("[id]", "Feature ID (validates all features in the folder when omitted)").option("--strict", "Elevate warnings to failures").option("--as <status>", "Evaluate the one-active-goal rule as if the feature were in <status> (0418: lifecycle FSM guards pass the transition target)").option("--folder <path>", "Custom features folder").option("--json", "Output machine-readable JSON").action(async (id, options) => {
77636
78359
  const resolved = await resolvePlanningFolders(context4.fs);
77637
78360
  const featuresDir = options.folder ?? context4.fs.resolve(resolved.featuresDir);
77638
78361
  const tasksDir = context4.fs.resolve(resolved.tasksDir);
@@ -77655,7 +78378,8 @@ function registerFeatureCommand(program2, context4) {
77655
78378
  featuresDir,
77656
78379
  tasksDir,
77657
78380
  runDir: context4.fs.resolve(".spur/run"),
77658
- severityOverrides: resolved.severityOverrides
78381
+ severityOverrides: resolved.severityOverrides,
78382
+ asStatus: options.as
77659
78383
  });
77660
78384
  results.push(result);
77661
78385
  if (!json3) {
@@ -77695,7 +78419,7 @@ ${result.id} (${result.status}): ${result.pass ? "PASS" : "FAIL"}`);
77695
78419
  } else {
77696
78420
  context4.output.write(`Evaluated ${result.evaluated}/${result.totalFeatures} features; updated ${result.updatedCount} feature(s).`);
77697
78421
  for (const res of result.results) {
77698
- const tag = res.applied ? "UPDATED" : res.proposal.from === res.proposal.to ? "NOOP" : "SKIPPED";
78422
+ const tag = res.applied ? "UPDATED" : res.goalConflict !== undefined ? "GOAL-CONFLICT" : res.proposal.from === res.proposal.to ? "NOOP" : "SKIPPED";
77699
78423
  context4.output.write(` [${tag}] ${res.proposal.featureId}: ${res.proposal.from} -> ${res.proposal.to} (${res.proposal.reason})`);
77700
78424
  }
77701
78425
  }
@@ -77707,7 +78431,7 @@ ${result.id} (${result.status}): ${result.pass ? "PASS" : "FAIL"}`);
77707
78431
  if (options.json) {
77708
78432
  context4.output.write(toJson2(result));
77709
78433
  } else {
77710
- const tag = result.applied ? "UPDATED" : result.proposal.from === result.proposal.to ? "NOOP" : "SKIPPED";
78434
+ const tag = result.applied ? "UPDATED" : result.goalConflict !== undefined ? "GOAL-CONFLICT" : result.proposal.from === result.proposal.to ? "NOOP" : "SKIPPED";
77711
78435
  context4.output.write(`Feature ${id}: [${tag}] ${result.proposal.from} -> ${result.proposal.to} (${result.proposal.reason})`);
77712
78436
  }
77713
78437
  }
@@ -77735,7 +78459,7 @@ async function makeService(context4, folderOverride) {
77735
78459
  foldersConfig: resolved.foldersConfig
77736
78460
  });
77737
78461
  }
77738
- async function assertFeatureCheckPass(context4, id, folderOverride, strict) {
78462
+ async function assertFeatureCheckPass(context4, id, folderOverride, strict, asStatus) {
77739
78463
  const resolved = await resolvePlanningFolders(context4.fs);
77740
78464
  const featuresDir = folderOverride ?? context4.fs.resolve(resolved.featuresDir);
77741
78465
  const tasksDir = context4.fs.resolve(resolved.tasksDir);
@@ -77747,7 +78471,8 @@ async function assertFeatureCheckPass(context4, id, folderOverride, strict) {
77747
78471
  const result = await new FeatureCheckService(context4.fs).check(`${featuresDir}/${fileName}`, id, {
77748
78472
  strict,
77749
78473
  featuresDir,
77750
- tasksDir
78474
+ tasksDir,
78475
+ asStatus
77751
78476
  });
77752
78477
  if (!result.pass) {
77753
78478
  const details = result.findings.map((f) => `${f.layer} ${f.section}: ${f.message}`).join("; ");
@@ -77801,13 +78526,13 @@ init_loader();
77801
78526
  init_src2();
77802
78527
  init_dist10();
77803
78528
  import { homedir as homedir7 } from "os";
77804
- import { join as join18, resolve as resolve6 } from "path";
78529
+ import { join as join19, resolve as resolve6 } from "path";
77805
78530
 
77806
78531
  // src/config.ts
77807
78532
  var CLI_CONFIG = {
77808
78533
  binaryName: "spur",
77809
78534
  binaryLabel: "spur",
77810
- binaryVersion: "0.3.27",
78535
+ binaryVersion: "0.3.29",
77811
78536
  configDir: ".spur",
77812
78537
  configFile: ".spur/config.yaml",
77813
78538
  databaseFile: ".spur/spur.db"
@@ -77858,8 +78583,8 @@ var SCAFFOLD_MANIFEST = [
77858
78583
  ];
77859
78584
 
77860
78585
  // src/commands/init.ts
77861
- var GLOBAL_CONFIG_DIR2 = join18(".config", "spur");
77862
- var GLOBAL_RULES_DIR2 = join18(GLOBAL_CONFIG_DIR2, "rules");
78586
+ var GLOBAL_CONFIG_DIR2 = join19(".config", "spur");
78587
+ var GLOBAL_RULES_DIR2 = join19(GLOBAL_CONFIG_DIR2, "rules");
77863
78588
  var GLOBAL_CONFIG_EXAMPLE = "config.example.yaml";
77864
78589
  var GLOBAL_CONFIG_FILE2 = "config.yaml";
77865
78590
  var INDEXED_CONTEXT_MARKER = "## Indexed context";
@@ -77890,7 +78615,7 @@ If \`.spur/context/\` is absent, proceed normally. Never block work on its absen
77890
78615
  `;
77891
78616
  function globalRulesRoot(context4) {
77892
78617
  const override = context4.env.SPUR_GLOBAL_RULES_DIR;
77893
- return override !== undefined && override.length > 0 ? resolve6(context4.cwd, override) : join18(homedir7(), GLOBAL_RULES_DIR2);
78618
+ return override !== undefined && override.length > 0 ? resolve6(context4.cwd, override) : join19(homedir7(), GLOBAL_RULES_DIR2);
77894
78619
  }
77895
78620
  async function writeIfNew(context4, path9, content, force, result) {
77896
78621
  if (!force && await context4.fs.exists(path9)) {
@@ -77907,11 +78632,11 @@ async function seedGlobalRules(context4) {
77907
78632
  const target = globalRulesRoot(context4);
77908
78633
  let written = 0;
77909
78634
  for (const relPath of await listBundledRuleFiles()) {
77910
- const destination = join18(target, relPath);
78635
+ const destination = join19(target, relPath);
77911
78636
  if (await context4.fs.exists(destination))
77912
78637
  continue;
77913
- await context4.fs.ensureDir(join18(target, ...relPath.split("/").slice(0, -1)));
77914
- await context4.fs.writeFile(destination, await context4.fs.readFile(join18(source, relPath)));
78638
+ await context4.fs.ensureDir(join19(target, ...relPath.split("/").slice(0, -1)));
78639
+ await context4.fs.writeFile(destination, await context4.fs.readFile(join19(source, relPath)));
77915
78640
  written += 1;
77916
78641
  }
77917
78642
  return written;
@@ -77921,20 +78646,20 @@ async function seedGlobalConfig(context4) {
77921
78646
  if (source === null)
77922
78647
  return 0;
77923
78648
  const globalOverride = context4.env.SPUR_GLOBAL_RULES_DIR;
77924
- const target = globalOverride !== undefined && globalOverride.length > 0 ? resolve6(context4.cwd, globalOverride) : join18(homedir7(), GLOBAL_CONFIG_DIR2);
78649
+ const target = globalOverride !== undefined && globalOverride.length > 0 ? resolve6(context4.cwd, globalOverride) : join19(homedir7(), GLOBAL_CONFIG_DIR2);
77925
78650
  let written = 0;
77926
78651
  for (const relPath of listBundledConfigFiles()) {
77927
78652
  if (relPath === GLOBAL_CONFIG_EXAMPLE)
77928
78653
  continue;
77929
- const destination = join18(target, relPath);
78654
+ const destination = join19(target, relPath);
77930
78655
  if (await context4.fs.exists(destination))
77931
78656
  continue;
77932
- await context4.fs.ensureDir(join18(target, ...relPath.split("/").slice(0, -1)));
77933
- await context4.fs.writeFile(destination, await context4.fs.readFile(join18(source, relPath)));
78657
+ await context4.fs.ensureDir(join19(target, ...relPath.split("/").slice(0, -1)));
78658
+ await context4.fs.writeFile(destination, await context4.fs.readFile(join19(source, relPath)));
77934
78659
  written += 1;
77935
78660
  }
77936
- const examplePath = join18(source, GLOBAL_CONFIG_EXAMPLE);
77937
- const globalConfigPath = join18(target, GLOBAL_CONFIG_FILE2);
78661
+ const examplePath = join19(source, GLOBAL_CONFIG_EXAMPLE);
78662
+ const globalConfigPath = join19(target, GLOBAL_CONFIG_FILE2);
77938
78663
  if (await context4.fs.exists(examplePath) && !await context4.fs.exists(globalConfigPath)) {
77939
78664
  await context4.fs.ensureDir(target);
77940
78665
  await context4.fs.writeFile(globalConfigPath, await context4.fs.readFile(examplePath));
@@ -77948,7 +78673,7 @@ function registerInitCommand(program2, context4) {
77948
78673
  const force = options.force === true;
77949
78674
  const minimal = options.minimal === true;
77950
78675
  const projectName = options.name ?? "default";
77951
- const configPath = join18(context4.cwd, CLI_CONFIG.configFile);
78676
+ const configPath = join19(context4.cwd, CLI_CONFIG.configFile);
77952
78677
  if (!force && await context4.fs.exists(configPath)) {
77953
78678
  const message = `Already initialized: ${CLI_CONFIG.configFile}. Use --force to overwrite.`;
77954
78679
  context4.output.write(json3 ? toJson2({ ok: false, reason: "already-initialized", config: CLI_CONFIG.configFile }) : message);
@@ -77983,13 +78708,13 @@ function registerInitCommand(program2, context4) {
77983
78708
  ].join(`
77984
78709
  `)}
77985
78710
  `;
77986
- await context4.fs.ensureDir(join18(context4.cwd, CLI_CONFIG.configDir));
78711
+ await context4.fs.ensureDir(join19(context4.cwd, CLI_CONFIG.configDir));
77987
78712
  await context4.fs.writeFile(configPath, configYaml);
77988
78713
  result.created.push(configPath);
77989
- const agentsDir = join18(context4.cwd, CLI_CONFIG.configDir, "agents");
78714
+ const agentsDir = join19(context4.cwd, CLI_CONFIG.configDir, "agents");
77990
78715
  await context4.fs.ensureDir(agentsDir);
77991
- await writeIfNew(context4, join18(agentsDir, ".gitkeep"), "", force, result);
77992
- const gitignorePath = join18(context4.cwd, ".gitignore");
78716
+ await writeIfNew(context4, join19(agentsDir, ".gitkeep"), "", force, result);
78717
+ const gitignorePath = join19(context4.cwd, ".gitignore");
77993
78718
  const contextEntry = ".spur/context/";
77994
78719
  if (await context4.fs.exists(gitignorePath)) {
77995
78720
  const existing = await context4.fs.readFile(gitignorePath);
@@ -78011,20 +78736,20 @@ ${contextEntry}
78011
78736
  for (const relPath of listBundledProjectSeedFiles()) {
78012
78737
  if (relPath.startsWith("templates/docs/"))
78013
78738
  continue;
78014
- const sourcePath = join18(configRoot, relPath);
78739
+ const sourcePath = join19(configRoot, relPath);
78015
78740
  if (!await context4.fs.exists(sourcePath))
78016
78741
  continue;
78017
- const targetPath = join18(context4.cwd, CLI_CONFIG.configDir, relPath);
78018
- await context4.fs.ensureDir(join18(targetPath, ".."));
78742
+ const targetPath = join19(context4.cwd, CLI_CONFIG.configDir, relPath);
78743
+ await context4.fs.ensureDir(join19(targetPath, ".."));
78019
78744
  await writeIfNew(context4, targetPath, await context4.fs.readFile(sourcePath), force, result);
78020
78745
  }
78021
78746
  for (const entry of SCAFFOLD_MANIFEST) {
78022
- const sourcePath = join18(configRoot, entry.source);
78747
+ const sourcePath = join19(configRoot, entry.source);
78023
78748
  if (!await context4.fs.exists(sourcePath))
78024
78749
  continue;
78025
- const baseDir = entry.root === true ? context4.cwd : join18(context4.cwd, CLI_CONFIG.configDir);
78026
- const targetPath = join18(baseDir, entry.target);
78027
- await context4.fs.ensureDir(join18(targetPath, ".."));
78750
+ const baseDir = entry.root === true ? context4.cwd : join19(context4.cwd, CLI_CONFIG.configDir);
78751
+ const targetPath = join19(baseDir, entry.target);
78752
+ await context4.fs.ensureDir(join19(targetPath, ".."));
78028
78753
  const entryForce = entry.preserve === true ? false : force;
78029
78754
  let body = await context4.fs.readFile(sourcePath);
78030
78755
  if (entry.target === "AGENTS.md") {
@@ -78037,7 +78762,7 @@ ${contextEntry}
78037
78762
  }
78038
78763
  }
78039
78764
  }
78040
- const agentsMdPath = join18(context4.cwd, "AGENTS.md");
78765
+ const agentsMdPath = join19(context4.cwd, "AGENTS.md");
78041
78766
  if (await context4.fs.exists(agentsMdPath)) {
78042
78767
  const existing = await context4.fs.readFile(agentsMdPath);
78043
78768
  if (!existing.includes(INDEXED_CONTEXT_MARKER)) {
@@ -78215,10 +78940,10 @@ function parseInterval2(raw) {
78215
78940
 
78216
78941
  // src/commands/migrate.ts
78217
78942
  init_src2();
78218
- import { join as join19 } from "path";
78943
+ import { join as join20 } from "path";
78219
78944
  function registerMigrateCommand(program2, context4) {
78220
78945
  program2.command("migrate").summary("apply CLI-owned schema migrations").option("--json", "Output machine-readable JSON").action(async (options) => {
78221
- const migrations = await loadSqlMigrations(join19(context4.cwd, "drizzle")).catch(() => {
78946
+ const migrations = await loadSqlMigrations(join20(context4.cwd, "drizzle")).catch(() => {
78222
78947
  return;
78223
78948
  });
78224
78949
  const applied = await applyCliMigrations(await context4.getDb(), migrations);
@@ -78634,7 +79359,7 @@ function formatTraceDetail(detail) {
78634
79359
 
78635
79360
  // src/commands/serve.ts
78636
79361
  init_src();
78637
- import { join as join23 } from "path";
79362
+ import { join as join24 } from "path";
78638
79363
 
78639
79364
  // ../server/src/index.ts
78640
79365
  init_src();
@@ -78644,11 +79369,11 @@ init_src3();
78644
79369
  init_src();
78645
79370
  init_loader();
78646
79371
  init_src2();
78647
- import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute3, join as join22 } from "path";
79372
+ import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute3, join as join23 } from "path";
78648
79373
  init_dist5();
78649
79374
 
78650
79375
  // ../server/src/bootstrap.ts
78651
- import { join as join20 } from "path";
79376
+ import { join as join21 } from "path";
78652
79377
 
78653
79378
  // ../../node_modules/.bun/radash@12.1.1/node_modules/radash/dist/esm/async.mjs
78654
79379
  var guard = (func, shouldGuard) => {
@@ -83883,6 +84608,9 @@ var contextInjector = (appRt) => async function contextInjectorMiddleware(c3, ne
83883
84608
  await next();
83884
84609
  };
83885
84610
 
84611
+ // ../server/src/middleware/error-handler.ts
84612
+ init_src3();
84613
+
83886
84614
  // ../server/src/errors.ts
83887
84615
  init_errors5();
83888
84616
 
@@ -83945,6 +84673,14 @@ function resolveError(err, requestId, isProd) {
83945
84673
  details: { requestId }
83946
84674
  };
83947
84675
  }
84676
+ if (err instanceof WbsCollisionError) {
84677
+ return {
84678
+ status: 409,
84679
+ apiCode: "WBS_COLLISION",
84680
+ message: isProd ? "WBS collision - task already exists" : message,
84681
+ details: { requestId, wbs: err.wbs, existingPath: err.existingPath, attemptedPath: err.attemptedPath }
84682
+ };
84683
+ }
83948
84684
  if (err instanceof LockTimeoutError) {
83949
84685
  return {
83950
84686
  status: 503,
@@ -87532,7 +88268,7 @@ function createApp(appRt, opts) {
87532
88268
  app.use("*", async (c3, next) => {
87533
88269
  const pathname = c3.req.path === "/" ? "/index.html" : c3.req.path;
87534
88270
  try {
87535
- const file2 = Bun.file(join20(webDistPath, pathname));
88271
+ const file2 = Bun.file(join21(webDistPath, pathname));
87536
88272
  if (await file2.exists()) {
87537
88273
  const headers = new Headers({ "content-type": file2.type });
87538
88274
  return new Response(file2.stream(), { headers });
@@ -87545,7 +88281,7 @@ function createApp(appRt, opts) {
87545
88281
  return c3.json({ error: "Not Found" }, 404);
87546
88282
  }
87547
88283
  try {
87548
- const indexFile = Bun.file(join20(webDistPath, "index.html"));
88284
+ const indexFile = Bun.file(join21(webDistPath, "index.html"));
87549
88285
  if (await indexFile.exists()) {
87550
88286
  return new Response(indexFile.stream(), {
87551
88287
  headers: { "content-type": "text/html; charset=utf-8" }
@@ -87566,7 +88302,7 @@ init_src3();
87566
88302
  init_src();
87567
88303
  init_src2();
87568
88304
  init_dist5();
87569
- import { dirname as dirname14, join as join21 } from "path";
88305
+ import { dirname as dirname14, join as join22 } from "path";
87570
88306
  var NOOP_OUTPUT = { write: (_s) => {}, error: (_s) => {} };
87571
88307
 
87572
88308
  class LazyPlanningEventEmitter {
@@ -87589,7 +88325,7 @@ class LazyPlanningEventEmitter {
87589
88325
  var DEFAULT_PLANNING_FOLDERS = {
87590
88326
  tasksDir: DEFAULT_TASKS_DIR,
87591
88327
  featuresDir: DEFAULT_FEATURES_DIR,
87592
- foldersConfig: { active_folder: DEFAULT_TASKS_DIR, folders: { [DEFAULT_TASKS_DIR]: { base_counter: 0 } } }
88328
+ foldersConfig: { active_folder: DEFAULT_TASKS_DIR, folders: { [DEFAULT_TASKS_DIR]: { baseCounter: 0 } } }
87593
88329
  };
87594
88330
 
87595
88331
  class NotConfiguredError extends Error {
@@ -87601,7 +88337,7 @@ class NotConfiguredError extends Error {
87601
88337
  function createServerContext(appRt, options) {
87602
88338
  const cwd = options.cwd;
87603
88339
  const fs3 = options.fs;
87604
- const dbUrl = options.dbUrl ?? join21(cwd, DEFAULT_DATABASE_URL);
88340
+ const dbUrl = options.dbUrl ?? join22(cwd, DEFAULT_DATABASE_URL);
87605
88341
  const eventsBus = options.eventsBus ?? appRt.events;
87606
88342
  const jobQueueEnabled = options.jobQueueEnabled ?? false;
87607
88343
  const folders = options.folders ?? DEFAULT_PLANNING_FOLDERS;
@@ -87961,15 +88697,15 @@ async function handleFeatureActionJob(ctx, env, payload) {
87961
88697
  await runFeatureActionJob(ctx, env, payload);
87962
88698
  }
87963
88699
  async function resolveWebDistPath(configuredPath) {
87964
- const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute3(configuredPath) ? configuredPath : join22(process.cwd(), configuredPath)] : [
87965
- join22(process.cwd(), "dist/web"),
87966
- join22(import.meta.dir, "web"),
87967
- join22(dirname15(process.execPath), "web"),
87968
- join22(dirname15(process.execPath), "../web"),
87969
- join22(import.meta.dir, "../../../dist/web")
88700
+ const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute3(configuredPath) ? configuredPath : join23(process.cwd(), configuredPath)] : [
88701
+ join23(process.cwd(), "dist/web"),
88702
+ join23(import.meta.dir, "web"),
88703
+ join23(dirname15(process.execPath), "web"),
88704
+ join23(dirname15(process.execPath), "../web"),
88705
+ join23(import.meta.dir, "../../../dist/web")
87970
88706
  ];
87971
88707
  for (const candidate of candidates) {
87972
- if (await Bun.file(join22(candidate, "index.html")).exists()) {
88708
+ if (await Bun.file(join23(candidate, "index.html")).exists()) {
87973
88709
  return candidate;
87974
88710
  }
87975
88711
  }
@@ -88128,7 +88864,7 @@ if (false) {}
88128
88864
 
88129
88865
  // src/commands/serve.ts
88130
88866
  function resolveServeDbUrl(cwd, env, configuredUrl) {
88131
- return env.DATABASE_URL === undefined ? join23(cwd, DEFAULT_DATABASE_URL) : configuredUrl;
88867
+ return env.DATABASE_URL === undefined ? join24(cwd, DEFAULT_DATABASE_URL) : configuredUrl;
88132
88868
  }
88133
88869
  function registerServeCommand(program2, context4) {
88134
88870
  program2.command("serve").summary("start the Spur web server (local fallback)").option("--port <n>", "Server port (env: PORT, default: 3000)", parseInt).option("--host <addr>", "Bind address (env: HOST, default: localhost)").option("--no-open", "Skip opening the browser").option("--cwd <path>", "Working directory", context4.cwd).option("--json", "Output { port, url, pid } and exit").action(async (options) => {
@@ -88167,7 +88903,7 @@ function registerServeCommand(program2, context4) {
88167
88903
  }
88168
88904
 
88169
88905
  // src/commands/status.ts
88170
- import { join as join24 } from "path";
88906
+ import { join as join25 } from "path";
88171
88907
 
88172
88908
  // src/errors.ts
88173
88909
  class CommandError extends Error {
@@ -88238,8 +88974,8 @@ function registerStatusCommand(program2, context4) {
88238
88974
  }
88239
88975
  async function runStatusCore(path9, options, context4) {
88240
88976
  const [packageJsonExists, spurConfigExists, git, agentSpecs] = await Promise.all([
88241
- context4.fs.exists(join24(context4.cwd, "package.json")),
88242
- context4.fs.exists(join24(context4.cwd, ".spur", "config.yaml")),
88977
+ context4.fs.exists(join25(context4.cwd, "package.json")),
88978
+ context4.fs.exists(join25(context4.cwd, ".spur", "config.yaml")),
88243
88979
  gitContext(context4.cwd),
88244
88980
  listAgentSpecIds(context4)
88245
88981
  ]);
@@ -88267,14 +89003,14 @@ async function runStatusCore(path9, options, context4) {
88267
89003
  return status.ok ? 0 : 1;
88268
89004
  }
88269
89005
  async function listAgentSpecIds(context4) {
88270
- const dir = join24(context4.cwd, ".spur", "agents");
89006
+ const dir = join25(context4.cwd, ".spur", "agents");
88271
89007
  if (!await context4.fs.exists(dir))
88272
89008
  return [];
88273
89009
  const entries = await context4.fs.readDir(dir);
88274
89010
  return entries.filter((entry) => entry.endsWith(".yaml") || entry.endsWith(".yml")).map((entry) => entry.replace(/\.ya?ml$/, "")).sort();
88275
89011
  }
88276
89012
  async function readTargetStatus(context4, targetPath) {
88277
- const resolved = join24(context4.cwd, targetPath);
89013
+ const resolved = join25(context4.cwd, targetPath);
88278
89014
  const stat = await context4.fs.stat(resolved);
88279
89015
  if (stat === null)
88280
89016
  throw new CommandError(`status failed: path does not exist at ${resolved}`);
@@ -88287,7 +89023,7 @@ init_loader();
88287
89023
  init_src2();
88288
89024
  init_dist5();
88289
89025
  import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
88290
- import { join as join25 } from "path";
89026
+ import { join as join26 } from "path";
88291
89027
  // schemas/section-matrix.schema.json
88292
89028
  var section_matrix_schema_default = {
88293
89029
  $schema: "http://json-schema.org/draft-07/schema#",
@@ -88599,7 +89335,7 @@ var spur_config_schema_default = {
88599
89335
  },
88600
89336
  tasks: {
88601
89337
  type: "object",
88602
- description: "Task-folder registration (design \xA79). Absorbs the legacy docs/.tasks/config.json folders + base_counter concepts. Mirrors @gobing-ai/spur-config tasksConfigSchema (Zod is SSOT).",
89338
+ description: "Task-folder registration (design \xA79). Absorbs the legacy docs/.tasks/config.json folders + baseCounter concepts. Mirrors @gobing-ai/spur-config tasksConfigSchema (Zod is SSOT).",
88603
89339
  properties: {
88604
89340
  folders: {
88605
89341
  type: "object",
@@ -88878,12 +89614,17 @@ function renderMigrationReport(report, dryRun, corpusDir) {
88878
89614
  }
88879
89615
  function registerTaskCommand(program2, context4) {
88880
89616
  const task = program2.command("task").summary("manage tasks");
88881
- task.command("create").summary("Create a new task with race-safe WBS allocation.").argument("<title>", "Task title").option("--feature <id>", "Feature ID for traceability and Goal\u2192Background derivation").option("--parent <wbs>", "Parent WBS for sub-task grouping").option("--template <variant>", `Template variant (${TASK_VARIANTS.join("|")})`).option("--folder <path>", "Custom tasks folder").option("--dedupe-within <seconds>", "Refuse creation if an existing task under the same feature has an identical name created within the last N seconds (task 0341 R4)", (v) => Number.parseInt(v, 10)).option("--allow-duplicate-name", "Override the --dedupe-within guard (creates anyway)").option("--json", "Output machine-readable JSON").action(async (title2, options) => {
89617
+ task.command("create").summary("Create a new task with race-safe WBS allocation.").argument("<title>", "Task title").option("--feature <id>", "Feature ID for traceability and Goal\u2192Background derivation").option("--parent <wbs>", "Parent WBS for sub-task grouping").option("--template <variant>", `Template variant (${TASK_VARIANTS.join("|")})`).option("--folder <path>", "Custom tasks folder").option("--dedupe-within <seconds>", "Override the default dedup window (seconds). Guard is on (300s) by default when --feature is set.", Number).option("--allow-duplicate-name", "Disable the dedup guard entirely (creates anyway)").option("--json", "Output machine-readable JSON").action(async (title2, options) => {
88882
89618
  if (options.template !== undefined && !TASK_VARIANTS.includes(options.template)) {
88883
89619
  context4.output.error(`Unknown template variant "${options.template}". Valid: ${TASK_VARIANTS.join(", ")}`);
88884
89620
  context4.setExitCode(2);
88885
89621
  return;
88886
89622
  }
89623
+ if (options.dedupeWithin !== undefined && (!Number.isInteger(options.dedupeWithin) || options.dedupeWithin <= 0)) {
89624
+ context4.output.error("--dedupe-within must be a positive integer");
89625
+ context4.setExitCode(2);
89626
+ return;
89627
+ }
88887
89628
  const svc = await makeService2(context4, options.folder);
88888
89629
  try {
88889
89630
  const result = await svc.create({
@@ -88891,7 +89632,7 @@ function registerTaskCommand(program2, context4) {
88891
89632
  featureId: options.feature,
88892
89633
  parentWbs: options.parent,
88893
89634
  template: options.template,
88894
- dedupeWithinSec: options.allowDuplicateName ? undefined : options.dedupeWithin
89635
+ dedupeWithinSec: options.allowDuplicateName ? null : options.dedupeWithin
88895
89636
  });
88896
89637
  if (options.json) {
88897
89638
  context4.output.write(toJson2(result));
@@ -88899,8 +89640,37 @@ function registerTaskCommand(program2, context4) {
88899
89640
  context4.output.write(`Created task ${result.ref.id}: ${result.ref.filePath}`);
88900
89641
  }
88901
89642
  } catch (err) {
88902
- if (err instanceof DuplicateFollowUpError) {
88903
- context4.output.error(err.message);
89643
+ if (err instanceof WbsCollisionError) {
89644
+ if (options.json) {
89645
+ context4.output.write(toJson2({
89646
+ ok: false,
89647
+ error: {
89648
+ code: "wbs-collision",
89649
+ message: err.message,
89650
+ wbs: err.wbs,
89651
+ existingPath: err.existingPath,
89652
+ attemptedPath: err.attemptedPath
89653
+ }
89654
+ }));
89655
+ } else {
89656
+ context4.output.error(err.message);
89657
+ }
89658
+ context4.setExitCode(3);
89659
+ } else if (err instanceof DuplicateFollowUpError) {
89660
+ if (options.json) {
89661
+ context4.output.write(toJson2({
89662
+ ok: false,
89663
+ error: {
89664
+ code: "duplicate-follow-up",
89665
+ message: err.message,
89666
+ existingWbs: err.existingWbs,
89667
+ existingName: err.existingName,
89668
+ attemptedName: err.attemptedName
89669
+ }
89670
+ }));
89671
+ } else {
89672
+ context4.output.error(err.message);
89673
+ }
88904
89674
  context4.setExitCode(3);
88905
89675
  } else {
88906
89676
  context4.output.error(String(err));
@@ -88971,7 +89741,7 @@ ${result.content}`);
88971
89741
  let forcedDoneVerdict;
88972
89742
  if (status === "done") {
88973
89743
  const current = await svc.show(wbs);
88974
- const verdictDir = options.verdictDir ?? join25(context4.cwd, ".spur", "run");
89744
+ const verdictDir = options.verdictDir ?? join26(context4.cwd, ".spur", "run");
88975
89745
  const loaded = await readVerdictArtifact(context4.fs, verdictDir, wbs);
88976
89746
  const guardOutcome = evaluateDoneTransition({
88977
89747
  wbs,
@@ -89230,8 +90000,26 @@ ${result.content}`);
89230
90000
  }
89231
90001
  }
89232
90002
  } catch (err) {
89233
- context4.output.error(String(err));
89234
- context4.setExitCode(1);
90003
+ if (err instanceof WbsCollisionError) {
90004
+ if (options.json) {
90005
+ context4.output.write(toJson2({
90006
+ ok: false,
90007
+ error: {
90008
+ code: "wbs-collision",
90009
+ message: err.message,
90010
+ wbs: err.wbs,
90011
+ existingPath: err.existingPath,
90012
+ attemptedPath: err.attemptedPath
90013
+ }
90014
+ }));
90015
+ } else {
90016
+ context4.output.error(err.message);
90017
+ }
90018
+ context4.setExitCode(3);
90019
+ } else {
90020
+ context4.output.error(String(err));
90021
+ context4.setExitCode(1);
90022
+ }
89235
90023
  }
89236
90024
  });
89237
90025
  task.command("record").summary("Record pipeline results into the task file \u2014 Testing, Review, and optional Solution backfill.").argument("<wbs>", "Task WBS number").option("--verdict-file <path>", "Path to verdict JSON (default: .spur/run/<wbs>-verdict.json)").option("--solution-from-diff", "Backfill Solution from git diff when bare").option("--transition <status>", "Optional lifecycle transition (e.g. testing)").option("--folder <path>", "Custom tasks folder").option("--json", "Output machine-readable JSON").action(async (wbs, options) => {
@@ -89369,6 +90157,23 @@ ${result.wbs} (${result.status}): ${result.pass ? "PASS" : "FAIL"}`);
89369
90157
  }
89370
90158
  }
89371
90159
  }
90160
+ if (!wbs) {
90161
+ const locator = await makeTaskLocator(context4);
90162
+ const duplicates2 = await locator.findDuplicateWbs();
90163
+ for (const dup of duplicates2) {
90164
+ const [first] = dup;
90165
+ if (first === undefined)
90166
+ continue;
90167
+ const msg = `Duplicate WBS ${first.wbs} found in ${dup.length} files:
90168
+ ` + dup.map((h2) => ` ${h2.filePath}`).join(`
90169
+ `);
90170
+ if (json3) {
90171
+ results.push({ wbs: first.wbs, pass: false, status: "duplicate", findings: [msg] });
90172
+ } else {
90173
+ context4.output.error(msg);
90174
+ }
90175
+ }
90176
+ }
89372
90177
  if (json3) {
89373
90178
  context4.output.write(toJson2(results));
89374
90179
  }
@@ -89511,7 +90316,7 @@ function loadTemplateContent(projectRoot, variant) {
89511
90316
  return templateContentCache.get(variant);
89512
90317
  if (templateMissSet.has(variant))
89513
90318
  return;
89514
- const localPath = join25(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
90319
+ const localPath = join26(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
89515
90320
  if (existsSync10(localPath)) {
89516
90321
  const content = readFileSync9(localPath, "utf8");
89517
90322
  templateContentCache.set(variant, content);
@@ -89519,7 +90324,7 @@ function loadTemplateContent(projectRoot, variant) {
89519
90324
  }
89520
90325
  const root = bundledConfigRoot();
89521
90326
  if (root !== null) {
89522
- const templatePath = join25(root, "templates", "task", `${variant}.md`);
90327
+ const templatePath = join26(root, "templates", "task", `${variant}.md`);
89523
90328
  if (existsSync10(templatePath)) {
89524
90329
  const content = readFileSync9(templatePath, "utf8");
89525
90330
  templateContentCache.set(variant, content);
@@ -89535,13 +90340,13 @@ function loadTemplateBodies(projectRoot, variant) {
89535
90340
  if (cached2 !== undefined)
89536
90341
  return cached2;
89537
90342
  let bodies = {};
89538
- const localPath = join25(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
90343
+ const localPath = join26(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
89539
90344
  if (existsSync10(localPath)) {
89540
90345
  bodies = extractTemplateBodies(readFileSync9(localPath, "utf8"));
89541
90346
  } else {
89542
90347
  const root = bundledConfigRoot();
89543
90348
  if (root !== null) {
89544
- const templatePath = join25(root, "templates", "task", `${variant}.md`);
90349
+ const templatePath = join26(root, "templates", "task", `${variant}.md`);
89545
90350
  if (existsSync10(templatePath)) {
89546
90351
  bodies = extractTemplateBodies(readFileSync9(templatePath, "utf8"));
89547
90352
  }
@@ -89594,7 +90399,7 @@ async function loadSectionMatrixUncached(projectRoot) {
89594
90399
  }
89595
90400
  const root = bundledConfigRoot();
89596
90401
  if (root !== null) {
89597
- const matrixPath = join25(root, "tasks", "section-matrix.yaml");
90402
+ const matrixPath = join26(root, "tasks", "section-matrix.yaml");
89598
90403
  if (await fs3.exists(matrixPath)) {
89599
90404
  const data = await loadStructuredSpurConfig(matrixPath, {
89600
90405
  validateJsonSchema: true,
@@ -90313,6 +91118,10 @@ function formatTraceTimeline(result) {
90313
91118
  `Started: ${run.startedAt} Completed: ${run.completedAt ?? "-"} Events: ${events2.length}`,
90314
91119
  ""
90315
91120
  ];
91121
+ if (result.outputArtifact !== undefined) {
91122
+ lines.push(`Agent output: ${result.outputArtifact} (tail -f for live view)`);
91123
+ lines.push("");
91124
+ }
90316
91125
  for (const event2 of events2) {
90317
91126
  lines.push(formatTimelineEvent(event2));
90318
91127
  }
@@ -90393,7 +91202,7 @@ init_src3();
90393
91202
  init_src();
90394
91203
  init_src2();
90395
91204
  init_dist5();
90396
- import { dirname as dirname16, join as join26, resolve as resolve9 } from "path";
91205
+ import { dirname as dirname16, join as join27, resolve as resolve9 } from "path";
90397
91206
  import { isatty as isatty4 } from "tty";
90398
91207
 
90399
91208
  // ../../node_modules/.bun/@clack+core@1.4.1/node_modules/@clack/core/dist/index.mjs
@@ -91815,7 +92624,7 @@ function createCliContext(options) {
91815
92624
  function noopSetExitCode(_code) {}
91816
92625
  async function createMigratedDbAdapter(cwd = process.cwd(), env = process.env, dbUrl) {
91817
92626
  const config4 = buildConfigFromEnv(env);
91818
- const configuredUrl = env.DATABASE_URL === undefined ? join26(cwd, DEFAULT_DATABASE_URL) : config4.database.url;
92627
+ const configuredUrl = env.DATABASE_URL === undefined ? join27(cwd, DEFAULT_DATABASE_URL) : config4.database.url;
91819
92628
  const url2 = dbUrl ?? configuredUrl;
91820
92629
  if (url2 !== IN_MEMORY_DATABASE_URL) {
91821
92630
  await createNodeFileSystem3().ensureDir(dirname16(url2));