@gobing-ai/spur 0.3.28 → 0.3.30

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.15/node_modules/@gobing-ai/ts-utils/dist/errors.js
50
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.16/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.15/node_modules/@gobing-ai/ts-utils/dist/api-response.js
61
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.16/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,10 +81,10 @@ 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.15/node_modules/@gobing-ai/ts-utils/dist/cursor.js
84
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.16/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.15/node_modules/@gobing-ai/ts-utils/dist/object.js
87
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.16/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
  }
@@ -102,7 +102,7 @@ function deepMerge(target, source) {
102
102
  return result;
103
103
  }
104
104
 
105
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/output.js
105
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.16/node_modules/@gobing-ai/ts-utils/dist/output.js
106
106
  function processStream(name) {
107
107
  const proc = globalThis.process;
108
108
  const stream = proc?.[name];
@@ -123,7 +123,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
123
123
  }
124
124
  var defaultStdoutTarget, defaultStderrTarget;
125
125
 
126
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.15/node_modules/@gobing-ai/ts-utils/dist/index.js
126
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.16/node_modules/@gobing-ai/ts-utils/dist/index.js
127
127
  var init_dist = __esm(() => {
128
128
  init_api_response();
129
129
  init_cursor();
@@ -21745,7 +21745,7 @@ var init_zod = __esm(() => {
21745
21745
  init_external();
21746
21746
  });
21747
21747
 
21748
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/config.js
21748
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/config.js
21749
21749
  function getProcessEnv() {
21750
21750
  return process.env;
21751
21751
  }
@@ -21823,7 +21823,7 @@ var init_config = __esm(() => {
21823
21823
  };
21824
21824
  });
21825
21825
 
21826
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21826
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21827
21827
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
21828
21828
  import { dirname, resolve as resolvePath } from "path";
21829
21829
  function createNodeFileSystem(root, paths) {
@@ -21910,7 +21910,7 @@ function findProjectRoot(startDir) {
21910
21910
  }
21911
21911
  var init_file_system_node = () => {};
21912
21912
 
21913
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
21913
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
21914
21914
  var DbModuleNotInstalledError;
21915
21915
  var init_db_errors = __esm(() => {
21916
21916
  DbModuleNotInstalledError = class DbModuleNotInstalledError extends Error {
@@ -29101,7 +29101,7 @@ var init_execa = __esm(() => {
29101
29101
  } = getIpcExport());
29102
29102
  });
29103
29103
 
29104
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
29104
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
29105
29105
  import { isatty } from "tty";
29106
29106
 
29107
29107
  class NodeProcessExecutor {
@@ -29431,7 +29431,7 @@ var init_process_executor = __esm(() => {
29431
29431
  init_execa();
29432
29432
  });
29433
29433
 
29434
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
29434
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
29435
29435
  function getNodeFileSystem() {
29436
29436
  if (!_nodeFileSystem)
29437
29437
  _nodeFileSystem = createNodeFileSystem();
@@ -29491,7 +29491,7 @@ var init_runtime_node_bun = __esm(() => {
29491
29491
  };
29492
29492
  });
29493
29493
 
29494
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/context.js
29494
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/context.js
29495
29495
  class RuntimeContext {
29496
29496
  scope;
29497
29497
  runtimeName;
@@ -29561,7 +29561,7 @@ var init_context = __esm(() => {
29561
29561
  init_runtime_node_bun();
29562
29562
  });
29563
29563
 
29564
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/path.js
29564
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/path.js
29565
29565
  function normalizeSeparators(path6) {
29566
29566
  return path6.replaceAll("\\", "/");
29567
29567
  }
@@ -29622,17 +29622,17 @@ var init_path = __esm(() => {
29622
29622
  SEP = globalThis.process?.platform === "win32" ? "\\" : "/";
29623
29623
  });
29624
29624
 
29625
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
29625
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
29626
29626
  var REMOTE_SCHEMA_MAX_BYTES;
29627
29627
  var init_schema_validation = __esm(() => {
29628
29628
  init_dist2();
29629
29629
  REMOTE_SCHEMA_MAX_BYTES = 5 * 1024 * 1024;
29630
29630
  });
29631
29631
 
29632
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/types.js
29632
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/types.js
29633
29633
  var init_types = () => {};
29634
29634
 
29635
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/index.js
29635
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/index.js
29636
29636
  var init_dist3 = __esm(() => {
29637
29637
  init_config();
29638
29638
  init_context();
@@ -29641,7 +29641,7 @@ var init_dist3 = __esm(() => {
29641
29641
  init_types();
29642
29642
  });
29643
29643
 
29644
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+3805a7059a817025/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
29644
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+a1f7d493e005a6ca/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
29645
29645
  import { Database } from "bun:sqlite";
29646
29646
  var init_bun_sqlite = () => {};
29647
29647
 
@@ -33833,7 +33833,7 @@ var init_bun_sqlite2 = __esm(() => {
33833
33833
  init_session2();
33834
33834
  });
33835
33835
 
33836
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
33836
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
33837
33837
  var inboxMessages;
33838
33838
  var init_inbox_messages = __esm(() => {
33839
33839
  init_sqlite_core();
@@ -33852,7 +33852,7 @@ var init_inbox_messages = __esm(() => {
33852
33852
  }, (table2) => [index("idx_inbox_messages_to_status").on(table2.toId, table2.status)]);
33853
33853
  });
33854
33854
 
33855
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/common.js
33855
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/common.js
33856
33856
  function nowTimestamp() {
33857
33857
  return Date.now();
33858
33858
  }
@@ -33881,7 +33881,7 @@ var init_common3 = __esm(() => {
33881
33881
  appendOnlyColumns = buildAppendOnlyColumns();
33882
33882
  });
33883
33883
 
33884
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
33884
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
33885
33885
  var queueJobs;
33886
33886
  var init_queue_jobs = __esm(() => {
33887
33887
  init_sqlite_core();
@@ -33901,7 +33901,7 @@ var init_queue_jobs = __esm(() => {
33901
33901
  }, (table2) => [index("queue_jobs_ready_idx").on(table2.status, table2.nextRetryAt, table2.createdAt)]);
33902
33902
  });
33903
33903
 
33904
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
33904
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
33905
33905
  var exports_runtime = {};
33906
33906
  __export(exports_runtime, {
33907
33907
  queueJobs: () => queueJobs,
@@ -33912,7 +33912,7 @@ var init_runtime = __esm(() => {
33912
33912
  init_queue_jobs();
33913
33913
  });
33914
33914
 
33915
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
33915
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
33916
33916
  var exports_bun_sqlite = {};
33917
33917
  __export(exports_bun_sqlite, {
33918
33918
  BunSqliteAdapter: () => BunSqliteAdapter
@@ -33941,6 +33941,7 @@ class BunSqliteAdapter {
33941
33941
  this.sqlite.run(pragmas.journalMode);
33942
33942
  this.sqlite.run(pragmas.synchronous);
33943
33943
  this.sqlite.run(pragmas.foreignKeys);
33944
+ this.sqlite.run(pragmas.busyTimeout);
33944
33945
  this.drizzleDb = drizzle({ client: this.sqlite, schema: exports_runtime });
33945
33946
  }
33946
33947
  get db() {
@@ -33987,7 +33988,8 @@ var init_bun_sqlite3 = __esm(() => {
33987
33988
  DEFAULT_PRAGMAS = {
33988
33989
  journalMode: "PRAGMA journal_mode = WAL",
33989
33990
  synchronous: "PRAGMA synchronous = NORMAL",
33990
- foreignKeys: "PRAGMA foreign_keys = ON"
33991
+ foreignKeys: "PRAGMA foreign_keys = ON",
33992
+ busyTimeout: "PRAGMA busy_timeout = 5000"
33991
33993
  };
33992
33994
  });
33993
33995
 
@@ -34201,7 +34203,7 @@ var init_d1 = __esm(() => {
34201
34203
  init_session3();
34202
34204
  });
34203
34205
 
34204
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
34206
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
34205
34207
  var exports_d1 = {};
34206
34208
  __export(exports_d1, {
34207
34209
  D1Adapter: () => D1Adapter
@@ -34265,7 +34267,7 @@ var init_d12 = __esm(() => {
34265
34267
  init_runtime();
34266
34268
  });
34267
34269
 
34268
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/adapter.js
34270
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/adapter.js
34269
34271
  async function createDbAdapter(config3) {
34270
34272
  switch (config3.driver) {
34271
34273
  case "bun-sqlite": {
@@ -34305,7 +34307,7 @@ var init_drizzle_orm = __esm(() => {
34305
34307
  init_view_common();
34306
34308
  });
34307
34309
 
34308
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/query-spec.js
34310
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/query-spec.js
34309
34311
  function compilePredicate(predicate) {
34310
34312
  if ("and" in predicate) {
34311
34313
  const parts = predicate.and.map(compilePredicate).filter((p) => p !== undefined);
@@ -34343,7 +34345,7 @@ var init_query_spec = __esm(() => {
34343
34345
  };
34344
34346
  });
34345
34347
 
34346
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/base-dao.js
34348
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/base-dao.js
34347
34349
  function asSelectQuery(query) {
34348
34350
  return query;
34349
34351
  }
@@ -34385,7 +34387,7 @@ var init_base_dao = __esm(() => {
34385
34387
  init_query_spec();
34386
34388
  });
34387
34389
 
34388
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/embedded-migrations.js
34390
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/embedded-migrations.js
34389
34391
  var embeddedMigrations;
34390
34392
  var init_embedded_migrations = __esm(() => {
34391
34393
  embeddedMigrations = [
@@ -34417,7 +34419,7 @@ var init_embedded_migrations = __esm(() => {
34417
34419
  ];
34418
34420
  });
34419
34421
 
34420
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
34422
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
34421
34423
  var EntityDao;
34422
34424
  var init_entity_dao = __esm(() => {
34423
34425
  init_drizzle_orm();
@@ -34579,7 +34581,7 @@ var init_entity_dao = __esm(() => {
34579
34581
  };
34580
34582
  });
34581
34583
 
34582
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/inbox-message-dao.js
34584
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/inbox-message-dao.js
34583
34585
  function isPromiseLike(value) {
34584
34586
  return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
34585
34587
  }
@@ -34752,7 +34754,7 @@ var init_migrator2 = __esm(() => {
34752
34754
  init_migrator();
34753
34755
  });
34754
34756
 
34755
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/migrate.js
34757
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/migrate.js
34756
34758
  async function ensureJournalTable(adapter, table3) {
34757
34759
  await adapter.exec(`CREATE TABLE IF NOT EXISTS "${table3}" (` + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "hash text NOT NULL, " + "created_at numeric" + ")");
34758
34760
  }
@@ -34827,7 +34829,7 @@ var init_migrate = __esm(() => {
34827
34829
  init_embedded_migrations();
34828
34830
  });
34829
34831
 
34830
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/queue-job-dao.js
34832
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/queue-job-dao.js
34831
34833
  var QueueJobDao;
34832
34834
  var init_queue_job_dao = __esm(() => {
34833
34835
  init_drizzle_orm();
@@ -34968,7 +34970,7 @@ var init_queue_job_dao = __esm(() => {
34968
34970
  };
34969
34971
  });
34970
34972
 
34971
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/index.js
34973
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/index.js
34972
34974
  var exports_dist = {};
34973
34975
  __export(exports_dist, {
34974
34976
  embeddedMigrations: () => embeddedMigrations,
@@ -37121,6 +37123,7 @@ var init_finding_codes = __esm(() => {
37121
37123
  "L3.solution-file-line",
37122
37124
  "L3.review-priority-table",
37123
37125
  "L3.testing-coverage",
37126
+ "L3.required-section-placeholder",
37124
37127
  "L3.plan-format",
37125
37128
  "L3.unchecked-checklist",
37126
37129
  "L3.ac-checklist-text",
@@ -37150,8 +37153,9 @@ var init_finding_codes = __esm(() => {
37150
37153
  "L4.uncovered-feature-scenario",
37151
37154
  "L4.verifying-incomplete-tasks",
37152
37155
  "L4.dogfood-missing",
37153
- "L4.scenario-unverified",
37154
- "L4.stale-line-anchor"
37156
+ "L4.stale-line-anchor",
37157
+ "L4.malformed-verdict-artifact",
37158
+ "L4.scenario-unverified"
37155
37159
  ];
37156
37160
  FINDING_CODES = {
37157
37161
  L1_MARKDOWN_PARSE: "L1.markdown-parse",
@@ -37165,6 +37169,7 @@ var init_finding_codes = __esm(() => {
37165
37169
  L3_SOLUTION_FILE_LINE: "L3.solution-file-line",
37166
37170
  L3_REVIEW_PRIORITY_TABLE: "L3.review-priority-table",
37167
37171
  L3_TESTING_COVERAGE: "L3.testing-coverage",
37172
+ L3_REQUIRED_SECTION_PLACEHOLDER: "L3.required-section-placeholder",
37168
37173
  L3_PLAN_FORMAT: "L3.plan-format",
37169
37174
  L3_UNCHECKED_CHECKLIST: "L3.unchecked-checklist",
37170
37175
  L3_AC_CHECKLIST_TEXT: "L3.ac-checklist-text",
@@ -37192,10 +37197,11 @@ var init_finding_codes = __esm(() => {
37192
37197
  L4_ORPHAN_SCENARIOS: "L4.orphan-scenarios",
37193
37198
  L4_UNCOVERED_TASK_SCENARIO: "L4.uncovered-task-scenario",
37194
37199
  L4_UNCOVERED_FEATURE_SCENARIO: "L4.uncovered-feature-scenario",
37195
- L4_VERIFYING_INCOMPLETE_TASKS: "L4.verifying-incomplete-tasks",
37196
37200
  L4_DOGFOOD_MISSING: "L4.dogfood-missing",
37197
- L4_SCENARIO_UNVERIFIED: "L4.scenario-unverified",
37198
- L4_STALE_LINE_ANCHOR: "L4.stale-line-anchor"
37201
+ L4_VERIFYING_INCOMPLETE_TASKS: "L4.verifying-incomplete-tasks",
37202
+ L4_STALE_LINE_ANCHOR: "L4.stale-line-anchor",
37203
+ L4_MALFORMED_VERDICT_ARTIFACT: "L4.malformed-verdict-artifact",
37204
+ L4_SCENARIO_UNVERIFIED: "L4.scenario-unverified"
37199
37205
  };
37200
37206
  });
37201
37207
 
@@ -37269,7 +37275,7 @@ function buildConfigFromEnv(env = process.env) {
37269
37275
  }
37270
37276
  });
37271
37277
  }
37272
- 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;
37278
+ 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;
37273
37279
  var init_src = __esm(() => {
37274
37280
  init_zod();
37275
37281
  init_finding_codes();
@@ -37339,11 +37345,16 @@ var init_src = __esm(() => {
37339
37345
  autostart: exports_external.boolean().optional(),
37340
37346
  members: exports_external.array(TeamMemberConfigSchema).min(1)
37341
37347
  });
37348
+ AgentOutputConfigSchema = exports_external.object({
37349
+ "max-bytes": exports_external.number().int().positive().optional(),
37350
+ "max-lines": exports_external.number().int().positive().optional()
37351
+ });
37342
37352
  AgentConfigSchema = exports_external.object({
37343
37353
  default: exports_external.string().optional(),
37344
37354
  executors: exports_external.array(AgentExecutorConfigSchema).optional(),
37345
37355
  "default-by-phase": exports_external.record(exports_external.string(), exports_external.string()).optional(),
37346
- team: exports_external.record(exports_external.string(), TeamConfigSchema).optional()
37356
+ team: exports_external.record(exports_external.string(), TeamConfigSchema).optional(),
37357
+ output: AgentOutputConfigSchema.optional()
37347
37358
  }).superRefine((value, ctx) => {
37348
37359
  const executors = value.executors;
37349
37360
  if (executors !== undefined) {
@@ -37356,6 +37367,13 @@ var init_src = __esm(() => {
37356
37367
  path: ["executors", index2, "name"]
37357
37368
  });
37358
37369
  }
37370
+ if (executor.name === "inline" || executor.name === "auto") {
37371
+ ctx.addIssue({
37372
+ code: exports_external.ZodIssueCode.custom,
37373
+ message: `Executor name "${executor.name}" is reserved (the --agent selector value '${executor.name}' has fixed semantics); rename executor at index ${index2}.`,
37374
+ path: ["executors", index2, "name"]
37375
+ });
37376
+ }
37359
37377
  seen.add(executor.name);
37360
37378
  }
37361
37379
  }
@@ -37434,7 +37452,7 @@ var init_src = __esm(() => {
37434
37452
  });
37435
37453
  });
37436
37454
 
37437
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/config.js
37455
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/config.js
37438
37456
  function parseYamlObject(text3) {
37439
37457
  let parsed;
37440
37458
  try {
@@ -37561,7 +37579,7 @@ var init_config2 = __esm(() => {
37561
37579
  };
37562
37580
  });
37563
37581
 
37564
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
37582
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
37565
37583
  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";
37566
37584
  import { dirname as dirname2, resolve as resolvePath3 } from "path";
37567
37585
  function createNodeFileSystem3(root, paths) {
@@ -37648,7 +37666,7 @@ function findProjectRoot3(startDir) {
37648
37666
  }
37649
37667
  var init_file_system_node2 = () => {};
37650
37668
 
37651
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
37669
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
37652
37670
  var D1NotConfiguredError2, DbModuleNotInstalledError3;
37653
37671
  var init_db_errors2 = __esm(() => {
37654
37672
  D1NotConfiguredError2 = class D1NotConfiguredError2 extends Error {
@@ -37665,7 +37683,7 @@ var init_db_errors2 = __esm(() => {
37665
37683
  };
37666
37684
  });
37667
37685
 
37668
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/file-system-cf.js
37686
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/file-system-cf.js
37669
37687
  function createCfFileSystem2() {
37670
37688
  return {
37671
37689
  getProjectRoot: () => "/bundle",
@@ -37704,7 +37722,7 @@ function createCfFileSystem2() {
37704
37722
  }
37705
37723
  var UNSUPPORTED = "FileSystem is not available on Cloudflare Workers. Use D1, KV, or R2 for persistent storage.";
37706
37724
 
37707
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/runtime-cf.js
37725
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/runtime-cf.js
37708
37726
  var exports_runtime_cf = {};
37709
37727
  __export(exports_runtime_cf, {
37710
37728
  cloudflareWorkersFactory: () => cloudflareWorkersFactory2
@@ -37742,7 +37760,7 @@ var init_runtime_cf = __esm(() => {
37742
37760
  };
37743
37761
  });
37744
37762
 
37745
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
37763
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
37746
37764
  import { isatty as isatty2 } from "tty";
37747
37765
 
37748
37766
  class NodeProcessExecutor3 {
@@ -38119,7 +38137,7 @@ var init_process_executor2 = __esm(() => {
38119
38137
  ProcessExecutor2 = NodeProcessExecutor3;
38120
38138
  });
38121
38139
 
38122
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
38140
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
38123
38141
  var exports_runtime_node_bun = {};
38124
38142
  __export(exports_runtime_node_bun, {
38125
38143
  nodeBunFactory: () => nodeBunFactory3,
@@ -38187,7 +38205,7 @@ var init_runtime_node_bun2 = __esm(() => {
38187
38205
  };
38188
38206
  });
38189
38207
 
38190
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/platform.js
38208
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/platform.js
38191
38209
  function isCloudflareWorkerRuntime2() {
38192
38210
  return globalThis.navigator?.userAgent?.startsWith("Cloudflare-Workers") ?? false;
38193
38211
  }
@@ -38217,7 +38235,7 @@ function _resetRuntimeFactory2() {
38217
38235
  }
38218
38236
  var _factory, _runtimeName;
38219
38237
 
38220
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/context.js
38238
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/context.js
38221
38239
  class RuntimeContext2 {
38222
38240
  scope;
38223
38241
  runtimeName;
@@ -38307,7 +38325,7 @@ var init_context2 = __esm(() => {
38307
38325
  init_runtime_node_bun2();
38308
38326
  });
38309
38327
 
38310
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/path.js
38328
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/path.js
38311
38329
  function normalizeSeparators2(path7) {
38312
38330
  return path7.replaceAll("\\", "/");
38313
38331
  }
@@ -38430,7 +38448,7 @@ var init_path2 = __esm(() => {
38430
38448
  SEP2 = globalThis.process?.platform === "win32" ? "\\" : "/";
38431
38449
  });
38432
38450
 
38433
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/fs.js
38451
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/fs.js
38434
38452
  async function ensureDirForFile2(path7, fs2 = createNodeFileSystem3()) {
38435
38453
  await fs2.ensureDir(dirnamePath(path7));
38436
38454
  }
@@ -38481,7 +38499,7 @@ var init_fs = __esm(() => {
38481
38499
  init_path2();
38482
38500
  });
38483
38501
 
38484
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/process-registry.js
38502
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/process-registry.js
38485
38503
  function allocateId() {
38486
38504
  nextIdSeq += 1;
38487
38505
  return `pe_${Date.now().toString(36)}_${nextIdSeq.toString(36)}`;
@@ -38605,7 +38623,7 @@ function createInMemoryProcessRegistry2(options) {
38605
38623
  }
38606
38624
  var nextIdSeq = 0;
38607
38625
 
38608
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/runtime-paths.js
38626
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/runtime-paths.js
38609
38627
  function ambientRuntimePaths2() {
38610
38628
  const cwd = getProcessCwd2();
38611
38629
  return { cwd, home: getHomeDir() ?? cwd };
@@ -38615,7 +38633,7 @@ var init_runtime_paths = __esm(() => {
38615
38633
  init_path2();
38616
38634
  });
38617
38635
 
38618
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
38636
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
38619
38637
  async function loadStructuredConfig(path7, options = {}) {
38620
38638
  const content = await (options.fileSystem ?? createNodeFileSystem3()).readFile(path7);
38621
38639
  return await parseStructuredConfig(content, path7, options);
@@ -38892,10 +38910,10 @@ var init_schema_validation2 = __esm(() => {
38892
38910
  defaultResolve = typeof Bun !== "undefined" ? (specifier, from) => Bun.resolveSync(specifier, from) : undefined;
38893
38911
  });
38894
38912
 
38895
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/types.js
38913
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/types.js
38896
38914
  var init_types2 = () => {};
38897
38915
 
38898
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/index.js
38916
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/index.js
38899
38917
  var exports_dist2 = {};
38900
38918
  __export(exports_dist2, {
38901
38919
  writeJsonFile: () => writeJsonFile2,
@@ -39182,7 +39200,7 @@ async function loadStructuredSpurConfig(configPath, opts) {
39182
39200
  function defaultFoldersConfig() {
39183
39201
  return {
39184
39202
  active_folder: DEFAULT_TASKS_DIR,
39185
- folders: { [DEFAULT_TASKS_DIR]: { base_counter: 0 } }
39203
+ folders: { [DEFAULT_TASKS_DIR]: { baseCounter: 0 } }
39186
39204
  };
39187
39205
  }
39188
39206
  function defaultPlanningFolders() {
@@ -39219,8 +39237,7 @@ async function resolvePlanningFoldersUncached(fs2) {
39219
39237
  const tasks = tasksConfigSchema.parse(parsed.tasks);
39220
39238
  const folders = {};
39221
39239
  for (const [path8, fc] of Object.entries(tasks.folders)) {
39222
- const validated = folderConfigSchema.parse(fc);
39223
- folders[path8] = { base_counter: validated.baseCounter, label: validated.label };
39240
+ folders[path8] = folderConfigSchema.parse(fc);
39224
39241
  }
39225
39242
  const foldersConfig = {
39226
39243
  active_folder: tasks.active,
@@ -41047,7 +41064,7 @@ var init_mod = __esm(() => {
41047
41064
  init_config3();
41048
41065
  });
41049
41066
 
41050
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/logger.js
41067
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/logger.js
41051
41068
  function toLogTapeLevel(level) {
41052
41069
  return level === "warn" ? "warning" : level;
41053
41070
  }
@@ -42600,7 +42617,7 @@ var require_src = __commonJS((exports) => {
42600
42617
  };
42601
42618
  });
42602
42619
 
42603
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/sdk.js
42620
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/telemetry/sdk.js
42604
42621
  function getTelemetryConfig(configPartial = {}) {
42605
42622
  return {
42606
42623
  enabled: configPartial.enabled ?? CONFIG_DEFAULTS.enabled,
@@ -42636,7 +42653,7 @@ var init_sdk = __esm(() => {
42636
42653
  resolvedConfig = getTelemetryConfig();
42637
42654
  });
42638
42655
 
42639
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
42656
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
42640
42657
  function isSuppressed(tracer2) {
42641
42658
  return tracer2 === undefined && !getResolvedConfig().enabled;
42642
42659
  }
@@ -42676,7 +42693,7 @@ var init_tracing2 = __esm(() => {
42676
42693
  import_api2 = __toESM(require_src(), 1);
42677
42694
  });
42678
42695
 
42679
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
42696
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
42680
42697
  function getMeter() {
42681
42698
  return import_api3.metrics.getMeter(METER_NAME, METER_VERSION);
42682
42699
  }
@@ -42773,7 +42790,7 @@ var init_metrics = __esm(() => {
42773
42790
  instruments = {};
42774
42791
  });
42775
42792
 
42776
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/event-bus.js
42793
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/event-bus/event-bus.js
42777
42794
  function busLogger() {
42778
42795
  if (!_busLogger)
42779
42796
  _busLogger = getLogger2("event-bus");
@@ -43018,7 +43035,7 @@ var init_event_bus = __esm(() => {
43018
43035
  init_metrics();
43019
43036
  });
43020
43037
 
43021
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/default-observers.js
43038
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/event-bus/default-observers.js
43022
43039
  function obsLogger() {
43023
43040
  if (!_obsLogger)
43024
43041
  _obsLogger = getLogger2("event-bus.observers");
@@ -43082,7 +43099,7 @@ var init_default_observers = __esm(() => {
43082
43099
  init_event_bus();
43083
43100
  });
43084
43101
 
43085
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/file-observer.js
43102
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/event-bus/file-observer.js
43086
43103
  function parentDir(filePath) {
43087
43104
  const idx = filePath.lastIndexOf("/");
43088
43105
  return idx <= 0 ? "." : filePath.slice(0, idx);
@@ -43180,7 +43197,7 @@ var init_file_observer = __esm(() => {
43180
43197
  init_logger3();
43181
43198
  });
43182
43199
 
43183
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/internals/drain.js
43200
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/internals/drain.js
43184
43201
  function settleWithin(promise2, deadline) {
43185
43202
  const remaining = deadline - Date.now();
43186
43203
  if (remaining <= 0)
@@ -43195,7 +43212,7 @@ function settleWithin(promise2, deadline) {
43195
43212
  return settled;
43196
43213
  }
43197
43214
 
43198
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler/node.js
43215
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/scheduler/node.js
43199
43216
  function parseInterval(cron) {
43200
43217
  const trimmed = cron.trim();
43201
43218
  const num = Number(trimmed);
@@ -43288,7 +43305,7 @@ var init_node3 = __esm(() => {
43288
43305
  init_metrics();
43289
43306
  });
43290
43307
 
43291
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler-node.js
43308
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/scheduler-node.js
43292
43309
  var exports_scheduler_node = {};
43293
43310
  __export(exports_scheduler_node, {
43294
43311
  NodeSchedulerAdapter: () => NodeSchedulerAdapter
@@ -50992,7 +51009,7 @@ var init_drizzle_zod = __esm(() => {
50992
51009
  };
50993
51010
  });
50994
51011
 
50995
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
51012
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
50996
51013
  function sqlExpressionToText(value) {
50997
51014
  if (typeof value !== "object" || value === null || !("queryChunks" in value)) {
50998
51015
  return;
@@ -51015,7 +51032,7 @@ function getDrizzleTableName(table3) {
51015
51032
  return String(table3[nameSym]);
51016
51033
  }
51017
51034
 
51018
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
51035
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
51019
51036
  function quoteIdent(name) {
51020
51037
  return `"${name.replace(/"/g, '""')}"`;
51021
51038
  }
@@ -51109,7 +51126,7 @@ var init_ddl = __esm(() => {
51109
51126
  init_sqlite_core();
51110
51127
  });
51111
51128
 
51112
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
51129
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
51113
51130
  function defineTable(name, columns2) {
51114
51131
  const table3 = sqliteTable(name, columns2);
51115
51132
  let insert2;
@@ -51143,7 +51160,7 @@ var init_define_table = __esm(() => {
51143
51160
  init_ddl();
51144
51161
  });
51145
51162
 
51146
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.15+7b9696e001f6f9db/node_modules/@gobing-ai/ts-db/dist/schema/index.js
51163
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.4.16+fec36642bac873ee/node_modules/@gobing-ai/ts-db/dist/schema/index.js
51147
51164
  var init_schema = __esm(() => {
51148
51165
  init_sqlite_core();
51149
51166
  init_define_table();
@@ -51768,7 +51785,7 @@ var init_dao = __esm(() => {
51768
51785
  init_workspace_dao();
51769
51786
  });
51770
51787
 
51771
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/errors.js
51788
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/errors.js
51772
51789
  var WorkflowValidationError, FSMError, RunCollisionError, WorkflowResumeError;
51773
51790
  var init_errors6 = __esm(() => {
51774
51791
  WorkflowValidationError = class WorkflowValidationError extends Error {
@@ -51803,12 +51820,12 @@ var init_errors6 = __esm(() => {
51803
51820
  };
51804
51821
  });
51805
51822
 
51806
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/event-bus/index.js
51823
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/event-bus/index.js
51807
51824
  var init_event_bus2 = __esm(() => {
51808
51825
  init_event_bus();
51809
51826
  });
51810
51827
 
51811
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/api-client.js
51828
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/api-client.js
51812
51829
  function sanitizeUrlForObservability(url2) {
51813
51830
  try {
51814
51831
  const parsed = new URL(url2);
@@ -52038,12 +52055,12 @@ var init_api_client = __esm(() => {
52038
52055
  };
52039
52056
  });
52040
52057
 
52041
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
52058
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
52042
52059
  var init_telemetry = __esm(() => {
52043
52060
  init_tracing2();
52044
52061
  });
52045
52062
 
52046
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/index.js
52063
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/index.js
52047
52064
  var init_dist6 = __esm(() => {
52048
52065
  init_api_client();
52049
52066
  init_event_bus2();
@@ -52051,7 +52068,7 @@ var init_dist6 = __esm(() => {
52051
52068
  init_telemetry();
52052
52069
  });
52053
52070
 
52054
- // ../../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
52071
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/run-lifecycle.js
52055
52072
  function runtimeBuiltins(workflowName, stateOrNodeId, runId, transitionsTaken, mode) {
52056
52073
  return {
52057
52074
  workflow: workflowName,
@@ -52310,7 +52327,7 @@ var init_run_lifecycle = __esm(() => {
52310
52327
  ];
52311
52328
  });
52312
52329
 
52313
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema.js
52330
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema.js
52314
52331
  var RESERVED_VAR_NAMES, IDENTIFIER, VarsSchema, EnvSchema, ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema;
52315
52332
  var init_schema2 = __esm(() => {
52316
52333
  init_zod();
@@ -52394,7 +52411,7 @@ var init_schema2 = __esm(() => {
52394
52411
  WorkflowDefSchema = exports_external.union([StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema]);
52395
52412
  });
52396
52413
 
52397
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/config.js
52414
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/config.js
52398
52415
  async function loadWorkflowDef(path9, options = {}) {
52399
52416
  return parseWorkflowDef(await loadStructuredConfig(path9, options), path9);
52400
52417
  }
@@ -52553,7 +52570,7 @@ var init_config4 = __esm(() => {
52553
52570
  RUNTIME_TEMPLATE_NAMESPACES = new Set(RUNTIME_BUILTIN_KEYS);
52554
52571
  });
52555
52572
 
52556
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/capability-registry.js
52573
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/extension/capability-registry.js
52557
52574
  class CapabilityRegistry {
52558
52575
  kind;
52559
52576
  capabilities = new Map;
@@ -52584,7 +52601,7 @@ class CapabilityRegistry {
52584
52601
  }
52585
52602
  }
52586
52603
 
52587
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-path.js
52604
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-path.js
52588
52605
  function assertRelativeExtensionPath(path9, options = {}) {
52589
52606
  const where = options.sourceName !== undefined ? ` declared by "${options.sourceName}"` : "";
52590
52607
  if (/^([/\\]|[A-Za-z]:[/\\])/.test(path9)) {
@@ -52595,20 +52612,20 @@ function assertRelativeExtensionPath(path9, options = {}) {
52595
52612
  }
52596
52613
  }
52597
52614
 
52598
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-loader.js
52615
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/extension/extension-loader.js
52599
52616
  var init_extension_loader = () => {};
52600
52617
 
52601
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension/index.js
52618
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/extension/index.js
52602
52619
  var init_extension = __esm(() => {
52603
52620
  init_extension_loader();
52604
52621
  });
52605
52622
 
52606
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.15+df0d32ac93e36a8d/node_modules/@gobing-ai/ts-runtime/dist/extension.js
52623
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.16+d8250d61be64a872/node_modules/@gobing-ai/ts-runtime/dist/extension.js
52607
52624
  var init_extension2 = __esm(() => {
52608
52625
  init_extension();
52609
52626
  });
52610
52627
 
52611
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/host.js
52628
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/host.js
52612
52629
  class WorkflowEngineHost {
52613
52630
  lifecycleBus;
52614
52631
  actions = new CapabilityRegistry("workflow action");
@@ -52777,7 +52794,7 @@ var init_host = __esm(() => {
52777
52794
  init_errors6();
52778
52795
  });
52779
52796
 
52780
- // ../../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
52797
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
52781
52798
  var WORKFLOW_ENGINE_SCHEMA_SQL;
52782
52799
  var init_schema_sql = __esm(() => {
52783
52800
  WORKFLOW_ENGINE_SCHEMA_SQL = `
@@ -52850,7 +52867,7 @@ CREATE TABLE IF NOT EXISTS action_runs (
52850
52867
  `.trim();
52851
52868
  });
52852
52869
 
52853
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/persistence.js
52870
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/persistence.js
52854
52871
  async function applyWorkflowEngineSchema(db2) {
52855
52872
  for (const statement of WORKFLOW_ENGINE_SCHEMA_SQL.split(";")) {
52856
52873
  const sql4 = statement.trim();
@@ -53139,7 +53156,7 @@ var init_persistence = __esm(() => {
53139
53156
  init_schema_sql();
53140
53157
  });
53141
53158
 
53142
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/variables.js
53159
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/variables.js
53143
53160
  function mergeVars(workflowVars = {}, overrideVars = {}) {
53144
53161
  return { ...workflowVars, ...overrideVars };
53145
53162
  }
@@ -53199,7 +53216,7 @@ var init_variables = __esm(() => {
53199
53216
  TEMPLATE_REF = /\$\{([^}]+)\}/g;
53200
53217
  });
53201
53218
 
53202
- // ../../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
53219
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/action-step.js
53203
53220
  async function runActionStep(action, vars, deps) {
53204
53221
  const { host, persistence, lifecycle, stateOrNodeId, runId } = deps;
53205
53222
  const resolved = resolveTemplates(action.options ?? {}, {
@@ -53257,7 +53274,7 @@ var init_action_step = __esm(() => {
53257
53274
  init_variables();
53258
53275
  });
53259
53276
 
53260
- // ../../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
53277
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/state-machine.js
53261
53278
  class StateMachineDriver {
53262
53279
  options;
53263
53280
  constructor(options) {
@@ -53391,7 +53408,7 @@ var init_state_machine = __esm(() => {
53391
53408
  EMPTY_OUTCOME = { outcome: "completed", result: undefined };
53392
53409
  });
53393
53410
 
53394
- // ../../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
53411
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/transition-flow.js
53395
53412
  class TransitionFlowDriver {
53396
53413
  options;
53397
53414
  constructor(options) {
@@ -53509,7 +53526,7 @@ var init_transition_flow = __esm(() => {
53509
53526
  init_variables();
53510
53527
  });
53511
53528
 
53512
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/service.js
53529
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/service.js
53513
53530
  class WorkflowService {
53514
53531
  host;
53515
53532
  persistence;
@@ -53726,7 +53743,7 @@ var init_service = __esm(() => {
53726
53743
  init_variables();
53727
53744
  });
53728
53745
 
53729
- // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/index.js
53746
+ // ../../node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/index.js
53730
53747
  var init_dist7 = __esm(() => {
53731
53748
  init_config4();
53732
53749
  init_host();
@@ -53735,20 +53752,7 @@ var init_dist7 = __esm(() => {
53735
53752
  init_service();
53736
53753
  });
53737
53754
 
53738
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/errors.js
53739
- var HistoryImportError;
53740
- var init_errors7 = __esm(() => {
53741
- HistoryImportError = class HistoryImportError extends Error {
53742
- details;
53743
- constructor(message, details) {
53744
- super(message);
53745
- this.details = details;
53746
- this.name = "HistoryImportError";
53747
- }
53748
- };
53749
- });
53750
-
53751
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
53755
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
53752
53756
  import { createHash } from "crypto";
53753
53757
  function stableJson(value) {
53754
53758
  if (Array.isArray(value)) {
@@ -53765,44 +53769,20 @@ function sha256(value) {
53765
53769
  }
53766
53770
  var init_hash = () => {};
53767
53771
 
53768
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
53769
- function redactValue(value, rules = DEFAULT_REDACTION_RULES) {
53770
- if (typeof value === "string") {
53771
- return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
53772
- }
53773
- if (Array.isArray(value)) {
53774
- return value.map((entry) => redactValue(entry, rules));
53775
- }
53776
- if (value !== null && typeof value === "object") {
53777
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, redactValue(entry, rules)]));
53778
- }
53779
- return value;
53780
- }
53781
- function redactRecord(record2, rules = DEFAULT_REDACTION_RULES) {
53782
- return redactValue(record2, rules);
53783
- }
53784
- var DEFAULT_REDACTION_RULES;
53785
- var init_redaction = __esm(() => {
53786
- DEFAULT_REDACTION_RULES = [
53787
- {
53788
- name: "api-key",
53789
- pattern: /\b(?:sk|pk|ghp|github_pat|xox[baprs])-[-_a-zA-Z0-9]{12,}\b/g,
53790
- replacement: "[REDACTED:token]"
53791
- },
53792
- {
53793
- name: "assignment-secret",
53794
- pattern: /\b(?:api[_-]?key|token|secret|password)\s*[:=]\s*["']?[^"',\s}]+/gi,
53795
- replacement: "[REDACTED:secret]"
53796
- },
53797
- {
53798
- name: "email",
53799
- pattern: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi,
53800
- replacement: "[REDACTED:email]"
53772
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/errors.js
53773
+ var HistoryImportError;
53774
+ var init_errors7 = __esm(() => {
53775
+ HistoryImportError = class HistoryImportError extends Error {
53776
+ details;
53777
+ constructor(message, details) {
53778
+ super(message);
53779
+ this.details = details;
53780
+ this.name = "HistoryImportError";
53801
53781
  }
53802
- ];
53782
+ };
53803
53783
  });
53804
53784
 
53805
- // ../../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
53785
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
53806
53786
  var HISTORY_IMPORT_SCHEMA_SQL;
53807
53787
  var init_schema_sql2 = __esm(() => {
53808
53788
  HISTORY_IMPORT_SCHEMA_SQL = `
@@ -53889,7 +53869,7 @@ CREATE TABLE IF NOT EXISTS history_etl_openclaw (
53889
53869
  `.trim();
53890
53870
  });
53891
53871
 
53892
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
53872
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
53893
53873
  function firstString(...values) {
53894
53874
  for (const value of values) {
53895
53875
  if (typeof value === "string" && value.length > 0)
@@ -54026,23 +54006,15 @@ var init_sources = __esm(() => {
54026
54006
  };
54027
54007
  });
54028
54008
 
54029
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/importer.js
54030
- async function applyHistoryImportSchema(db2) {
54031
- for (const statement of HISTORY_IMPORT_SCHEMA_SQL.split(";")) {
54032
- const sql4 = statement.trim();
54033
- if (sql4.length > 0) {
54034
- await db2.exec(sql4);
54035
- }
54009
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/jsonl-importer-dao.js
54010
+ function targetTableFor(table3) {
54011
+ if (!VALID_TABLE_NAME.test(table3)) {
54012
+ throw new HistoryImportError(`Invalid history ETL target table: ${table3}`, { table: table3 });
54036
54013
  }
54014
+ return table3;
54037
54015
  }
54038
- async function ensureTargetTables(db2, definition) {
54039
- const tables = new Set([targetTableFor(definition.targetTable)]);
54040
- if (definition.splitConfig.mode !== "one-to-one" && definition.splitConfig.targetTable !== undefined) {
54041
- tables.add(targetTableFor(definition.splitConfig.targetTable));
54042
- }
54043
- for (const table3 of tables) {
54044
- await db2.exec(ETL_TABLE_DDL(table3));
54045
- }
54016
+ function timestamp(now) {
54017
+ return (now?.() ?? new Date).toISOString();
54046
54018
  }
54047
54019
  function ETL_TABLE_DDL(table3) {
54048
54020
  return `CREATE TABLE IF NOT EXISTS ${table3} (
@@ -54054,176 +54026,22 @@ function ETL_TABLE_DDL(table3) {
54054
54026
  imported_at TEXT NOT NULL
54055
54027
  );`;
54056
54028
  }
54057
- async function runJsonlImport(source, options) {
54058
- const definition = resolveSourceDefinition(source);
54059
- const resolvedSource = definition.source;
54060
- const fileSystem = options.fileSystem ?? createNodeFileSystem3();
54061
- await applyHistoryImportSchema(options.db);
54062
- await ensureTargetTables(options.db, definition);
54063
- const mode = options.mode ?? "incremental";
54064
- const files = await discoverFiles(definition, options.roots, options.files, fileSystem, options.paths);
54065
- if (mode === "full" && !options.dryRun) {
54066
- await resetCheckpoints(options.db, resolvedSource, files);
54067
- }
54068
- const parseErrors = [];
54069
- const validationErrors = [];
54070
- let processedLines = 0;
54071
- let importedRecords = 0;
54072
- let skippedDuplicates = 0;
54073
- let checkpointUpdates = 0;
54074
- for (const file2 of files) {
54075
- const checkpoint = mode === "incremental" ? await readCheckpoint(options.db, resolvedSource, file2) : 0;
54076
- let lineNumber = 0;
54077
- for await (const rawLine of readLines(fileSystem, file2)) {
54078
- lineNumber += 1;
54079
- const line = rawLine.trim();
54080
- if (line.length === 0 || lineNumber <= checkpoint)
54081
- continue;
54082
- processedLines += 1;
54083
- const raw = parseJsonLine(line, file2, lineNumber, parseErrors);
54084
- if (raw === undefined)
54085
- continue;
54086
- const splitRecords = splitRawRecord(definition, raw);
54087
- let lineSucceeded = false;
54088
- for (let splitIndex = 0;splitIndex < splitRecords.length; splitIndex += 1) {
54089
- const split = splitRecords[splitIndex];
54090
- if (split === undefined)
54091
- continue;
54092
- const normalized = normalizeRecord(definition, split.raw, {
54093
- source: resolvedSource,
54094
- sourceFile: file2,
54095
- sourceLine: lineNumber,
54096
- splitIndex
54097
- });
54098
- const parsed = definition.schema.safeParse(normalized);
54099
- if (!parsed.success) {
54100
- validationErrors.push({
54101
- sourceFile: file2,
54102
- sourceLine: lineNumber,
54103
- reason: parsed.error.issues.map((issue2) => issue2.message).join("; ")
54104
- });
54105
- continue;
54106
- }
54107
- const redacted = redactRecord(parsed.data, options.redactionRules);
54108
- lineSucceeded = true;
54109
- const recordHash = sha256({
54110
- source: resolvedSource,
54111
- sourceFile: file2,
54112
- sourceLine: lineNumber,
54113
- splitIndex,
54114
- record: redacted
54115
- });
54116
- if (await ledgerExists(options.db, recordHash)) {
54117
- skippedDuplicates += 1;
54118
- continue;
54119
- }
54120
- if (!options.dryRun) {
54121
- await insertRecord(options.db, split.targetTable, recordHash, file2, lineNumber, splitIndex, redacted, options.now);
54122
- await insertLedger(options.db, recordHash, resolvedSource, file2, lineNumber, splitIndex, split.targetTable, options.now);
54123
- }
54124
- importedRecords += 1;
54125
- }
54126
- if (lineSucceeded && !options.dryRun) {
54127
- await writeCheckpoint(options.db, resolvedSource, file2, lineNumber, options.now);
54128
- checkpointUpdates += 1;
54129
- }
54130
- }
54131
- }
54132
- return {
54133
- source: resolvedSource,
54134
- mode,
54135
- scannedFiles: files.length,
54136
- processedLines,
54137
- importedRecords,
54138
- skippedDuplicates,
54139
- parseErrors,
54140
- validationErrors,
54141
- checkpointUpdates
54142
- };
54143
- }
54144
- function parseJsonLine(line, sourceFile, sourceLine, parseErrors) {
54145
- try {
54146
- const value = JSON.parse(line);
54147
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
54148
- parseErrors.push({ sourceFile, sourceLine, reason: "JSONL row must be an object" });
54149
- return;
54029
+ async function applyHistoryImportSchema(db2) {
54030
+ for (const statement of HISTORY_IMPORT_SCHEMA_SQL.split(";")) {
54031
+ const sql4 = statement.trim();
54032
+ if (sql4.length > 0) {
54033
+ await db2.exec(sql4);
54150
54034
  }
54151
- return value;
54152
- } catch (error51) {
54153
- parseErrors.push({ sourceFile, sourceLine, reason: error51 instanceof Error ? error51.message : "Invalid JSON" });
54154
- return;
54155
54035
  }
54156
54036
  }
54157
- function splitRawRecord(definition, raw) {
54158
- const targetTable = targetTableFor(definition.targetTable);
54159
- if (definition.splitConfig.mode === "one-to-one") {
54160
- return [{ targetTable, raw }];
54161
- }
54162
- if (definition.splitConfig.mode === "custom") {
54163
- const config5 = definition.splitConfig;
54164
- return config5.split(raw).map((entry) => ({
54165
- targetTable: targetTableFor(config5.targetTable ?? definition.targetTable),
54166
- raw: entry
54167
- }));
54168
- }
54169
- const config4 = definition.splitConfig;
54170
- const nested = raw[config4.field];
54171
- if (!Array.isArray(nested)) {
54172
- return [{ targetTable, raw }];
54173
- }
54174
- return nested.filter((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry)).map((entry) => ({
54175
- targetTable: targetTableFor(config4.targetTable ?? definition.targetTable),
54176
- raw: { ...raw, ...entry }
54177
- }));
54178
- }
54179
- function normalizeRecord(definition, raw, context4) {
54180
- const normalized = {};
54181
- for (const [rawKey, targetKey] of Object.entries(definition.fieldMap)) {
54182
- if (rawKey in raw)
54183
- normalized[targetKey] = raw[rawKey];
54184
- }
54185
- for (const [targetKey, transform2] of Object.entries(definition.fieldTransforms)) {
54186
- normalized[targetKey] = transform2(normalized[targetKey], raw, context4);
54187
- }
54188
- normalized.source = context4.source;
54189
- normalized.source_file = context4.sourceFile;
54190
- normalized.source_line = context4.sourceLine;
54191
- normalized.split_index = context4.splitIndex;
54192
- return normalized;
54193
- }
54194
- async function discoverFiles(definition, roots, files, fileSystem, paths) {
54195
- if (files !== undefined && files.length > 0) {
54196
- return files.map((file2) => resolvePath4(file2)).sort();
54037
+ async function ensureTargetTables(db2, definition) {
54038
+ const tables = new Set([targetTableFor(definition.targetTable)]);
54039
+ if (definition.splitConfig.mode !== "one-to-one" && definition.splitConfig.targetTable !== undefined) {
54040
+ tables.add(targetTableFor(definition.splitConfig.targetTable));
54197
54041
  }
54198
- const ambient = paths ?? ambientRuntimePaths2();
54199
- const resolvedRoots = roots !== undefined ? roots.map((root) => resolvePath4(ambient.cwd, root)) : definition.defaultRoots.map((root) => resolvePath4(ambient.home, root));
54200
- const found = new Set;
54201
- for (const root of resolvedRoots) {
54202
- if (!await fileSystem.exists(root))
54203
- continue;
54204
- const stat = await fileSystem.stat(root);
54205
- if (stat === null)
54206
- continue;
54207
- if (stat.isFile()) {
54208
- if (matchesPattern(root, definition.filePatterns))
54209
- found.add(root);
54210
- continue;
54211
- }
54212
- for (const file2 of await walkDir2(root, fileSystem)) {
54213
- if (matchesPattern(file2, definition.filePatterns))
54214
- found.add(file2);
54215
- }
54042
+ for (const table3 of tables) {
54043
+ await db2.exec(ETL_TABLE_DDL(table3));
54216
54044
  }
54217
- return [...found].sort();
54218
- }
54219
- function matchesPattern(path9, patterns) {
54220
- return patterns.some((pattern) => {
54221
- if (pattern === "*.jsonl")
54222
- return path9.endsWith(".jsonl");
54223
- if (pattern === "*.json")
54224
- return path9.endsWith(".json");
54225
- return path9.endsWith(pattern.replace(/^\*/, ""));
54226
- });
54227
54045
  }
54228
54046
  async function readCheckpoint(db2, source, sourceFile) {
54229
54047
  const row = await db2.queryFirst("SELECT last_imported_line FROM history_import_checkpoint WHERE source = ? AND source_file = ?", source, sourceFile);
@@ -54255,14 +54073,220 @@ async function insertLedger(db2, recordHash, source, sourceFile, sourceLine, spl
54255
54073
  await db2.run(`INSERT INTO history_import_ledger (record_hash, source, source_file, source_line, split_index, target_table, imported_at)
54256
54074
  VALUES (?, ?, ?, ?, ?, ?, ?)`, recordHash, source, sourceFile, sourceLine, splitIndex, targetTable, timestamp(now));
54257
54075
  }
54258
- function targetTableFor(table3) {
54259
- if (!VALID_TABLE_NAME.test(table3)) {
54260
- throw new HistoryImportError(`Invalid history ETL target table: ${table3}`, { table: table3 });
54076
+ var init_jsonl_importer_dao = __esm(() => {
54077
+ init_errors7();
54078
+ init_schema_sql2();
54079
+ init_sources();
54080
+ });
54081
+
54082
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
54083
+ function redactValue(value, rules = DEFAULT_REDACTION_RULES) {
54084
+ if (typeof value === "string") {
54085
+ return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
54261
54086
  }
54262
- return table3;
54087
+ if (Array.isArray(value)) {
54088
+ return value.map((entry) => redactValue(entry, rules));
54089
+ }
54090
+ if (value !== null && typeof value === "object") {
54091
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, redactValue(entry, rules)]));
54092
+ }
54093
+ return value;
54263
54094
  }
54264
- function timestamp(now) {
54265
- return (now?.() ?? new Date).toISOString();
54095
+ function redactRecord(record2, rules = DEFAULT_REDACTION_RULES) {
54096
+ return redactValue(record2, rules);
54097
+ }
54098
+ var DEFAULT_REDACTION_RULES;
54099
+ var init_redaction = __esm(() => {
54100
+ DEFAULT_REDACTION_RULES = [
54101
+ {
54102
+ name: "api-key",
54103
+ pattern: /\b(?:sk|pk|ghp|github_pat|xox[baprs])-[-_a-zA-Z0-9]{12,}\b/g,
54104
+ replacement: "[REDACTED:token]"
54105
+ },
54106
+ {
54107
+ name: "assignment-secret",
54108
+ pattern: /\b(?:api[_-]?key|token|secret|password)\s*[:=]\s*["']?[^"',\s}]+/gi,
54109
+ replacement: "[REDACTED:secret]"
54110
+ },
54111
+ {
54112
+ name: "email",
54113
+ pattern: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi,
54114
+ replacement: "[REDACTED:email]"
54115
+ }
54116
+ ];
54117
+ });
54118
+
54119
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/importer.js
54120
+ async function runJsonlImport(source, options) {
54121
+ const definition = resolveSourceDefinition(source);
54122
+ const resolvedSource = definition.source;
54123
+ const fileSystem = options.fileSystem ?? createNodeFileSystem3();
54124
+ await applyHistoryImportSchema(options.db);
54125
+ await ensureTargetTables(options.db, definition);
54126
+ const mode = options.mode ?? "incremental";
54127
+ const files = await discoverFiles(definition, options.roots, options.files, fileSystem, options.paths);
54128
+ if (mode === "full" && !options.dryRun) {
54129
+ await resetCheckpoints(options.db, resolvedSource, files);
54130
+ }
54131
+ const parseErrors = [];
54132
+ const validationErrors = [];
54133
+ let processedLines = 0;
54134
+ let importedRecords = 0;
54135
+ let skippedDuplicates = 0;
54136
+ let checkpointUpdates = 0;
54137
+ for (const file2 of files) {
54138
+ const checkpoint = mode === "incremental" ? await readCheckpoint(options.db, resolvedSource, file2) : 0;
54139
+ let lineNumber = 0;
54140
+ for await (const rawLine of readLines(fileSystem, file2)) {
54141
+ lineNumber += 1;
54142
+ const line = rawLine.trim();
54143
+ if (line.length === 0 || lineNumber <= checkpoint)
54144
+ continue;
54145
+ processedLines += 1;
54146
+ const raw = parseJsonLine(line, file2, lineNumber, parseErrors);
54147
+ if (raw === undefined)
54148
+ continue;
54149
+ const splitRecords = splitRawRecord(definition, raw);
54150
+ let lineSucceeded = false;
54151
+ for (let splitIndex = 0;splitIndex < splitRecords.length; splitIndex += 1) {
54152
+ const split = splitRecords[splitIndex];
54153
+ if (split === undefined)
54154
+ continue;
54155
+ const normalized = normalizeRecord(definition, split.raw, {
54156
+ source: resolvedSource,
54157
+ sourceFile: file2,
54158
+ sourceLine: lineNumber,
54159
+ splitIndex
54160
+ });
54161
+ const parsed = definition.schema.safeParse(normalized);
54162
+ if (!parsed.success) {
54163
+ validationErrors.push({
54164
+ sourceFile: file2,
54165
+ sourceLine: lineNumber,
54166
+ reason: parsed.error.issues.map((issue2) => issue2.message).join("; ")
54167
+ });
54168
+ continue;
54169
+ }
54170
+ const redacted = redactRecord(parsed.data, options.redactionRules);
54171
+ lineSucceeded = true;
54172
+ const recordHash = sha256({
54173
+ source: resolvedSource,
54174
+ sourceFile: file2,
54175
+ sourceLine: lineNumber,
54176
+ splitIndex,
54177
+ record: redacted
54178
+ });
54179
+ if (await ledgerExists(options.db, recordHash)) {
54180
+ skippedDuplicates += 1;
54181
+ continue;
54182
+ }
54183
+ if (!options.dryRun) {
54184
+ await insertRecord(options.db, split.targetTable, recordHash, file2, lineNumber, splitIndex, redacted, options.now);
54185
+ await insertLedger(options.db, recordHash, resolvedSource, file2, lineNumber, splitIndex, split.targetTable, options.now);
54186
+ }
54187
+ importedRecords += 1;
54188
+ }
54189
+ if (lineSucceeded && !options.dryRun) {
54190
+ await writeCheckpoint(options.db, resolvedSource, file2, lineNumber, options.now);
54191
+ checkpointUpdates += 1;
54192
+ }
54193
+ }
54194
+ }
54195
+ return {
54196
+ source: resolvedSource,
54197
+ mode,
54198
+ scannedFiles: files.length,
54199
+ processedLines,
54200
+ importedRecords,
54201
+ skippedDuplicates,
54202
+ parseErrors,
54203
+ validationErrors,
54204
+ checkpointUpdates
54205
+ };
54206
+ }
54207
+ function parseJsonLine(line, sourceFile, sourceLine, parseErrors) {
54208
+ try {
54209
+ const value = JSON.parse(line);
54210
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
54211
+ parseErrors.push({ sourceFile, sourceLine, reason: "JSONL row must be an object" });
54212
+ return;
54213
+ }
54214
+ return value;
54215
+ } catch (error51) {
54216
+ parseErrors.push({ sourceFile, sourceLine, reason: error51 instanceof Error ? error51.message : "Invalid JSON" });
54217
+ return;
54218
+ }
54219
+ }
54220
+ function splitRawRecord(definition, raw) {
54221
+ const targetTable = targetTableFor(definition.targetTable);
54222
+ if (definition.splitConfig.mode === "one-to-one") {
54223
+ return [{ targetTable, raw }];
54224
+ }
54225
+ if (definition.splitConfig.mode === "custom") {
54226
+ const config5 = definition.splitConfig;
54227
+ return config5.split(raw).map((entry) => ({
54228
+ targetTable: targetTableFor(config5.targetTable ?? definition.targetTable),
54229
+ raw: entry
54230
+ }));
54231
+ }
54232
+ const config4 = definition.splitConfig;
54233
+ const nested = raw[config4.field];
54234
+ if (!Array.isArray(nested)) {
54235
+ return [{ targetTable, raw }];
54236
+ }
54237
+ return nested.filter((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry)).map((entry) => ({
54238
+ targetTable: targetTableFor(config4.targetTable ?? definition.targetTable),
54239
+ raw: { ...raw, ...entry }
54240
+ }));
54241
+ }
54242
+ function normalizeRecord(definition, raw, context4) {
54243
+ const normalized = {};
54244
+ for (const [rawKey, targetKey] of Object.entries(definition.fieldMap)) {
54245
+ if (rawKey in raw)
54246
+ normalized[targetKey] = raw[rawKey];
54247
+ }
54248
+ for (const [targetKey, transform2] of Object.entries(definition.fieldTransforms)) {
54249
+ normalized[targetKey] = transform2(normalized[targetKey], raw, context4);
54250
+ }
54251
+ normalized.source = context4.source;
54252
+ normalized.source_file = context4.sourceFile;
54253
+ normalized.source_line = context4.sourceLine;
54254
+ normalized.split_index = context4.splitIndex;
54255
+ return normalized;
54256
+ }
54257
+ async function discoverFiles(definition, roots, files, fileSystem, paths) {
54258
+ if (files !== undefined && files.length > 0) {
54259
+ return files.map((file2) => resolvePath4(file2)).sort();
54260
+ }
54261
+ const ambient = paths ?? ambientRuntimePaths2();
54262
+ const resolvedRoots = roots !== undefined ? roots.map((root) => resolvePath4(ambient.cwd, root)) : definition.defaultRoots.map((root) => resolvePath4(ambient.home, root));
54263
+ const found = new Set;
54264
+ for (const root of resolvedRoots) {
54265
+ if (!await fileSystem.exists(root))
54266
+ continue;
54267
+ const stat = await fileSystem.stat(root);
54268
+ if (stat === null)
54269
+ continue;
54270
+ if (stat.isFile()) {
54271
+ if (matchesPattern(root, definition.filePatterns))
54272
+ found.add(root);
54273
+ continue;
54274
+ }
54275
+ for (const file2 of await walkDir2(root, fileSystem)) {
54276
+ if (matchesPattern(file2, definition.filePatterns))
54277
+ found.add(file2);
54278
+ }
54279
+ }
54280
+ return [...found].sort();
54281
+ }
54282
+ function matchesPattern(path9, patterns) {
54283
+ return patterns.some((pattern) => {
54284
+ if (pattern === "*.jsonl")
54285
+ return path9.endsWith(".jsonl");
54286
+ if (pattern === "*.json")
54287
+ return path9.endsWith(".json");
54288
+ return path9.endsWith(pattern.replace(/^\*/, ""));
54289
+ });
54266
54290
  }
54267
54291
  async function* readLines(fileSystem, file2) {
54268
54292
  if (fileSystem.readFileStream) {
@@ -54276,20 +54300,19 @@ async function* readLines(fileSystem, file2) {
54276
54300
  }
54277
54301
  var init_importer = __esm(() => {
54278
54302
  init_dist5();
54279
- init_errors7();
54280
54303
  init_hash();
54304
+ init_jsonl_importer_dao();
54281
54305
  init_redaction();
54282
- init_schema_sql2();
54283
54306
  init_sources();
54284
54307
  });
54285
54308
 
54286
- // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.15+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/index.js
54309
+ // ../../node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.4.16+d5c29f764bf0e6e0/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/index.js
54287
54310
  var init_dist8 = __esm(() => {
54288
54311
  init_importer();
54289
54312
  init_schema_sql2();
54290
54313
  });
54291
54314
 
54292
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/extensions.js
54315
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/extensions.js
54293
54316
  function collectExtensions(sourceName, sourceDir, extensions) {
54294
54317
  if (extensions === undefined)
54295
54318
  return [];
@@ -54305,7 +54328,7 @@ var init_extensions = __esm(() => {
54305
54328
  init_dist5();
54306
54329
  });
54307
54330
 
54308
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/types.js
54331
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/types.js
54309
54332
  function createFinding(rule, message, filePath, extras = {}) {
54310
54333
  return {
54311
54334
  ruleId: rule.id,
@@ -54376,7 +54399,7 @@ var init_types3 = __esm(() => {
54376
54399
  });
54377
54400
  });
54378
54401
 
54379
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/loader.js
54402
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/config/loader.js
54380
54403
  async function loadPreset(name, options) {
54381
54404
  const merged = await buildMergedRoots(options.roots.map((root) => resolvePath4(root)), options.fileSystem);
54382
54405
  const presetPath = findMergedPreset(merged, name);
@@ -54591,7 +54614,7 @@ var init_loader2 = __esm(() => {
54591
54614
  FIX_MODE_AUTHORITY = { none: 0, suggest: 1, auto: 2 };
54592
54615
  });
54593
54616
 
54594
- // ../../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
54617
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/test-stub-fixer.js
54595
54618
  function normalizeFindingPath(filePath) {
54596
54619
  if (!filePath || isAbsolutePath2(filePath))
54597
54620
  return null;
@@ -54656,7 +54679,7 @@ var init_test_stub_fixer = __esm(() => {
54656
54679
  realFileSystem = createNodeFileSystem3();
54657
54680
  });
54658
54681
 
54659
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/fixers.js
54682
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/fixers/fixers.js
54660
54683
  function registerBuiltinFixers(host, exec) {
54661
54684
  const regexFixer = new RegexFixerProvider;
54662
54685
  const pathFixer = new PathFixerProvider;
@@ -54859,7 +54882,7 @@ var init_fixers = __esm(() => {
54859
54882
  };
54860
54883
  });
54861
54884
 
54862
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
54885
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
54863
54886
  function resolveAgentName(input) {
54864
54887
  if (isCanonicalName(input))
54865
54888
  return input;
@@ -55110,7 +55133,7 @@ var init_shims = __esm(() => {
55110
55133
  ALIAS_TO_CANONICAL = Object.fromEntries(Object.values(AGENT_SHIMS).flatMap((shim) => (shim.aliases ?? []).map((alias3) => [alias3, shim.name])));
55111
55134
  });
55112
55135
 
55113
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/identity.js
55136
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/identity.js
55114
55137
  function buildIdentityPreamble(ctx) {
55115
55138
  const sections = [
55116
55139
  `You are agent \`${ctx.agentId}\` (${ctx.agentType}) in workspace \`${ctx.workspace}\`.`
@@ -55170,7 +55193,7 @@ var init_identity = __esm(() => {
55170
55193
  init_dist5();
55171
55194
  });
55172
55195
 
55173
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/slash-command.js
55196
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/slash-command.js
55174
55197
  function isClaudeStyleSlashCommand(input) {
55175
55198
  return SLASH_COMMAND_RE.test(input);
55176
55199
  }
@@ -55198,7 +55221,7 @@ var init_slash_command = __esm(() => {
55198
55221
  SLASH_COMMAND_RE = /^\/([a-zA-Z0-9._-]+):([a-zA-Z0-9._-]+)(\s.*)?$/;
55199
55222
  });
55200
55223
 
55201
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
55224
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
55202
55225
  function buildCorrelationEnv(correlation) {
55203
55226
  return {
55204
55227
  [AGENT_RUN_ID_ENV]: correlation.runId,
@@ -55334,7 +55357,7 @@ var init_ai_runner = __esm(() => {
55334
55357
  init_slash_command();
55335
55358
  });
55336
55359
 
55337
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
55360
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
55338
55361
  class AgentDetector {
55339
55362
  runner;
55340
55363
  timeout;
@@ -55410,7 +55433,7 @@ var init_agent_detector = __esm(() => {
55410
55433
  VERSION_PATTERN = /(?<version>\d+\.\d+(?:\.\d+)?)/;
55411
55434
  });
55412
55435
 
55413
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agent-spec.js
55436
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/agent-spec.js
55414
55437
  function validateAgentId(id) {
55415
55438
  if (!/^[a-z][a-z0-9_-]{1,63}$/.test(id)) {
55416
55439
  throw new ValueError(`Invalid agent id "${id}": expected 2-64 chars, lowercase alphanumeric, "_" or "-"`);
@@ -55507,7 +55530,7 @@ var init_agent_spec = __esm(() => {
55507
55530
  };
55508
55531
  });
55509
55532
 
55510
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/agents/auth-shims.js
55533
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/agents/auth-shims.js
55511
55534
  function isNonEmpty(value) {
55512
55535
  return value !== undefined && value.trim().length > 0;
55513
55536
  }
@@ -55612,7 +55635,7 @@ var init_auth_shims = __esm(() => {
55612
55635
  };
55613
55636
  });
55614
55637
 
55615
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/model-health-probe.js
55638
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/model-health-probe.js
55616
55639
  class ModelHealthProbeRegistry {
55617
55640
  probes = new Map;
55618
55641
  register(providerPrefix, probe) {
@@ -55720,7 +55743,7 @@ var init_model_health_probe = __esm(() => {
55720
55743
  };
55721
55744
  });
55722
55745
 
55723
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/doctor-runner.js
55746
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/doctor-runner.js
55724
55747
  class DoctorRunner {
55725
55748
  detector;
55726
55749
  runner;
@@ -55857,15 +55880,15 @@ var init_doctor_runner = __esm(() => {
55857
55880
  init_model_health_probe();
55858
55881
  });
55859
55882
 
55860
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/events.js
55883
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/events.js
55861
55884
  var init_events = () => {};
55862
55885
 
55863
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/messages.js
55886
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/messages.js
55864
55887
  function formatMessage(msg) {
55865
55888
  return `[task from=${msg.fromId ?? "operator"} id=${msg.id}] ${msg.body}`;
55866
55889
  }
55867
55890
 
55868
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/team-agent-process.js
55891
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/team-agent-process.js
55869
55892
  import { Buffer as Buffer5 } from "buffer";
55870
55893
 
55871
55894
  class TeamAgentProcess {
@@ -55999,7 +56022,7 @@ var init_team_agent_process = __esm(() => {
55999
56022
  init_dist5();
56000
56023
  });
56001
56024
 
56002
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/team-orchestrator.js
56025
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/team-orchestrator.js
56003
56026
  class TeamOrchestrator {
56004
56027
  configDir;
56005
56028
  inbox;
@@ -56128,7 +56151,7 @@ var init_team_orchestrator = __esm(() => {
56128
56151
  init_team_agent_process();
56129
56152
  });
56130
56153
 
56131
- // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.15+1d3d52e40c4aad1a/node_modules/@gobing-ai/ts-ai-runner/dist/index.js
56154
+ // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.4.16+ae22402965cb65aa/node_modules/@gobing-ai/ts-ai-runner/dist/index.js
56132
56155
  var exports_dist3 = {};
56133
56156
  __export(exports_dist3, {
56134
56157
  validateAgentId: () => validateAgentId,
@@ -56179,7 +56202,7 @@ var init_dist9 = __esm(() => {
56179
56202
  init_team_orchestrator();
56180
56203
  });
56181
56204
 
56182
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/config-access.js
56205
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/config-access.js
56183
56206
  function stringArray(value) {
56184
56207
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : undefined;
56185
56208
  }
@@ -56217,7 +56240,7 @@ function parseInlineFlags(source) {
56217
56240
  return { flags, rest: source.slice(match[0].length) };
56218
56241
  }
56219
56242
 
56220
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/glob-match.js
56243
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/glob-match.js
56221
56244
  function matchesAny(path9, patterns) {
56222
56245
  if (patterns === undefined || patterns.length === 0)
56223
56246
  return true;
@@ -56265,7 +56288,7 @@ function escapeRegExp(value) {
56265
56288
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
56266
56289
  }
56267
56290
 
56268
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-discovery.js
56291
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-discovery.js
56269
56292
  async function discoverFiles2(options) {
56270
56293
  const fs3 = options.fs ?? createNodeFileSystem3();
56271
56294
  const allFiles = await walkDir2(options.workdir, fs3, DEFAULT_EXCLUDES);
@@ -56293,12 +56316,12 @@ var init_file_discovery = __esm(() => {
56293
56316
  DEFAULT_EXCLUDES = new Set([".git", "node_modules", "dist", ".coverage", ".astro", ".wrangler"]);
56294
56317
  });
56295
56318
 
56296
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-utils.js
56319
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/file-utils.js
56297
56320
  var init_file_utils = __esm(() => {
56298
56321
  init_file_discovery();
56299
56322
  });
56300
56323
 
56301
- // ../../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
56324
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/agent-detection-evaluator.js
56302
56325
  class AgentDetectionEvaluator {
56303
56326
  detector;
56304
56327
  constructor(detector = new AgentDetector) {
@@ -56326,7 +56349,7 @@ var init_agent_detection_evaluator = __esm(() => {
56326
56349
  init_file_utils();
56327
56350
  });
56328
56351
 
56329
- // ../../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
56352
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/coverage-gate-evaluator.js
56330
56353
  class CoverageGateEvaluator {
56331
56354
  constructor() {}
56332
56355
  async evaluate(rule, context4) {
@@ -56410,7 +56433,7 @@ var init_coverage_gate_evaluator = __esm(() => {
56410
56433
  init_file_utils();
56411
56434
  });
56412
56435
 
56413
- // ../../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
56436
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/exit-code-evaluator.js
56414
56437
  class ExitCodeEvaluator {
56415
56438
  executor;
56416
56439
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -56446,7 +56469,7 @@ var init_exit_code_evaluator = __esm(() => {
56446
56469
  init_file_utils();
56447
56470
  });
56448
56471
 
56449
- // ../../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
56472
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/forbidden-import-evaluator.js
56450
56473
  class ForbiddenImportEvaluator {
56451
56474
  constructor() {}
56452
56475
  async evaluate(rule, context4) {
@@ -56527,7 +56550,7 @@ var init_forbidden_import_evaluator = __esm(() => {
56527
56550
  init_file_utils();
56528
56551
  });
56529
56552
 
56530
- // ../../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
56553
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/import-boundary-evaluator.js
56531
56554
  class ImportBoundaryEvaluator {
56532
56555
  async evaluate(rule, context4) {
56533
56556
  const config4 = rule.evaluator.config ?? {};
@@ -56620,7 +56643,7 @@ var init_import_boundary_evaluator = __esm(() => {
56620
56643
  init_file_utils();
56621
56644
  });
56622
56645
 
56623
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/path-evaluator.js
56646
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/path-evaluator.js
56624
56647
  class PathEvaluator {
56625
56648
  constructor() {}
56626
56649
  async evaluate(rule, context4) {
@@ -56681,7 +56704,7 @@ var init_path_evaluator = __esm(() => {
56681
56704
  init_file_utils();
56682
56705
  });
56683
56706
 
56684
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/regex-evaluator.js
56707
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/regex-evaluator.js
56685
56708
  class RegexEvaluator {
56686
56709
  constructor() {}
56687
56710
  async evaluate(rule, context4) {
@@ -56759,7 +56782,7 @@ var init_regex_evaluator = __esm(() => {
56759
56782
  init_file_utils();
56760
56783
  });
56761
56784
 
56762
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/ripgrep-evaluator.js
56785
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/ripgrep-evaluator.js
56763
56786
  class RipgrepEvaluator {
56764
56787
  executor;
56765
56788
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -56852,7 +56875,7 @@ var init_ripgrep_evaluator = __esm(() => {
56852
56875
  init_file_utils();
56853
56876
  });
56854
56877
 
56855
- // ../../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
56878
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/schema-artifact-evaluator.js
56856
56879
  class SchemaArtifactEvaluator {
56857
56880
  constructor() {}
56858
56881
  async evaluate(rule, context4) {
@@ -56930,7 +56953,7 @@ var init_schema_artifact_evaluator = __esm(() => {
56930
56953
  init_file_utils();
56931
56954
  });
56932
56955
 
56933
- // ../../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
56956
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/secrets-scanner-evaluator.js
56934
56957
  class SecretsScannerEvaluator {
56935
56958
  constructor() {}
56936
56959
  async evaluate(rule, context4) {
@@ -56998,7 +57021,7 @@ var init_secrets_scanner_evaluator = __esm(() => {
56998
57021
  ALL_CATEGORIES = Object.keys(BUILTIN_PATTERNS);
56999
57022
  });
57000
57023
 
57001
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/sg-evaluator.js
57024
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/sg-evaluator.js
57002
57025
  class SgEvaluator {
57003
57026
  executor;
57004
57027
  constructor(executor = nodeBunFactory3.createProcessExecutor()) {
@@ -57095,7 +57118,7 @@ var init_sg_evaluator = __esm(() => {
57095
57118
  init_file_utils();
57096
57119
  });
57097
57120
 
57098
- // ../../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
57121
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/resolvers/test-path-resolver.js
57099
57122
  class TypeScriptTestPathResolver {
57100
57123
  name = "typescript";
57101
57124
  constructor() {}
@@ -57178,7 +57201,7 @@ function testify(rel) {
57178
57201
  return `${dir}test_${base2}`;
57179
57202
  }
57180
57203
 
57181
- // ../../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
57204
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/test-location-evaluator.js
57182
57205
  class TestLocationEvaluator {
57183
57206
  resolvers;
57184
57207
  constructor(resolvers) {
@@ -57253,7 +57276,7 @@ var init_test_location_evaluator = __esm(() => {
57253
57276
  TYPESCRIPT_FALLBACK = new TypeScriptTestPathResolver;
57254
57277
  });
57255
57278
 
57256
- // ../../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
57279
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/evaluators/tsdoc-export-evaluator.js
57257
57280
  class TsdocExportEvaluator {
57258
57281
  constructor() {}
57259
57282
  async evaluate(rule, context4) {
@@ -57338,7 +57361,7 @@ var init_tsdoc_export_evaluator = __esm(() => {
57338
57361
  };
57339
57362
  });
57340
57363
 
57341
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/json.js
57364
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/json.js
57342
57365
  class JsonFormatter {
57343
57366
  constructor() {}
57344
57367
  format(result) {
@@ -57346,7 +57369,7 @@ class JsonFormatter {
57346
57369
  }
57347
57370
  }
57348
57371
 
57349
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/text.js
57372
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/formatters/text.js
57350
57373
  class TextFormatter {
57351
57374
  constructor() {}
57352
57375
  format(result) {
@@ -57360,7 +57383,7 @@ class TextFormatter {
57360
57383
  }
57361
57384
  }
57362
57385
 
57363
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/builtins.js
57386
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/builtins.js
57364
57387
  function registerBuiltins(host, executor) {
57365
57388
  const path9 = new PathEvaluator;
57366
57389
  host.evaluators.register("regex", new RegexEvaluator, "builtin");
@@ -57400,7 +57423,7 @@ var init_builtins = __esm(() => {
57400
57423
  init_tsdoc_export_evaluator();
57401
57424
  });
57402
57425
 
57403
- // ../../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
57426
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/rule-engine-host.js
57404
57427
  class RuleEngineHost {
57405
57428
  evaluators;
57406
57429
  formatters;
@@ -57417,7 +57440,7 @@ var init_rule_engine_host = __esm(() => {
57417
57440
  init_extension2();
57418
57441
  });
57419
57442
 
57420
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/engine.js
57443
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/engine.js
57421
57444
  class RuleEngine {
57422
57445
  host;
57423
57446
  events;
@@ -57588,7 +57611,7 @@ var init_engine = __esm(() => {
57588
57611
  init_types3();
57589
57612
  });
57590
57613
 
57591
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/bundled-rules.js
57614
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/host/bundled-rules.js
57592
57615
  async function bundledRulesRoot() {
57593
57616
  if (cachedRoot2 !== undefined)
57594
57617
  return cachedRoot2;
@@ -57639,7 +57662,7 @@ var init_bundled_rules = __esm(() => {
57639
57662
  init_dist5();
57640
57663
  });
57641
57664
 
57642
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/db-adapter.js
57665
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/db-adapter.js
57643
57666
  class DbRulePersistenceAdapter {
57644
57667
  db;
57645
57668
  constructor(db2) {
@@ -57673,7 +57696,7 @@ class DbRulePersistenceAdapter {
57673
57696
  }
57674
57697
  }
57675
57698
 
57676
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
57699
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
57677
57700
  var RULE_ENGINE_SCHEMA_SQL = `
57678
57701
  CREATE TABLE IF NOT EXISTS rule_runs (
57679
57702
  id TEXT PRIMARY KEY,
@@ -57719,10 +57742,10 @@ CREATE TABLE IF NOT EXISTS rule_eval_runs (
57719
57742
  CREATE INDEX IF NOT EXISTS idx_rule_eval_runs_run_id ON rule_eval_runs (run_id);
57720
57743
  `;
57721
57744
 
57722
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/index.js
57745
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/index.js
57723
57746
  var init_persistence2 = () => {};
57724
57747
 
57725
- // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.15+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/index.js
57748
+ // ../../node_modules/.bun/@gobing-ai+ts-rule-engine@0.4.16+eb8900f44f4776f9/node_modules/@gobing-ai/ts-rule-engine/dist/index.js
57726
57749
  var init_dist10 = __esm(() => {
57727
57750
  init_extensions();
57728
57751
  init_loader2();
@@ -57942,7 +57965,7 @@ ${SYSTEM_EVENTS_SCHEMA_SQL}
57942
57965
  ];
57943
57966
  });
57944
57967
 
57945
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/job-queue/db-job-queue.js
57968
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/job-queue/db-job-queue.js
57946
57969
  function queueLogger() {
57947
57970
  if (!_queueLogger)
57948
57971
  _queueLogger = getLogger2("job-queue");
@@ -58219,7 +58242,7 @@ var init_db_job_queue = __esm(() => {
58219
58242
  init_tracing2();
58220
58243
  });
58221
58244
 
58222
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/job-queue-db.js
58245
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/job-queue-db.js
58223
58246
  var exports_job_queue_db = {};
58224
58247
  __export(exports_job_queue_db, {
58225
58248
  DBQueueConsumer: () => DBQueueConsumer,
@@ -58241,6 +58264,7 @@ async function createMigratedDbViaRuntime(config4) {
58241
58264
  const { loadRuntimeFactory: loadRuntimeFactory3 } = await Promise.resolve().then(() => (init_dist5(), exports_dist2));
58242
58265
  const factory = await loadRuntimeFactory3();
58243
58266
  const runtimeAdapter = await factory.createDbAdapter(config4);
58267
+ await runtimeAdapter.exec("PRAGMA busy_timeout = 5000");
58244
58268
  await applyCliMigrations(runtimeAdapter);
58245
58269
  return runtimeAdapter;
58246
58270
  }
@@ -58289,9 +58313,6 @@ function normalizeCapabilityTier(value) {
58289
58313
  function isTierEligible(candidateTier, minTier) {
58290
58314
  return TIER_RANK[candidateTier] >= TIER_RANK[minTier];
58291
58315
  }
58292
- function pickStartingTier(policy) {
58293
- return policy.min_tier;
58294
- }
58295
58316
  function getNextFallback(policy, signal, currentTier) {
58296
58317
  const currentRank = currentTier ? TIER_RANK[currentTier] : 0;
58297
58318
  const match = policy.fallback.find((f) => f.trigger === signal && TIER_RANK[f.tier] > currentRank);
@@ -58357,12 +58378,12 @@ function parseStageRecord(raw, consumerVersion = STAGE_REGISTRY_SCHEMA_VERSION)
58357
58378
  function getCanonicalStage(idOrAlias) {
58358
58379
  return CANONICAL_STAGE_BY_KEY.get(idOrAlias);
58359
58380
  }
58360
- 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;
58381
+ 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;
58361
58382
  var init_schema4 = __esm(() => {
58362
58383
  init_zod();
58363
58384
  STAGE_REGISTRY_SCHEMA_VERSION = {
58364
58385
  major: 1,
58365
- minor: 0
58386
+ minor: 1
58366
58387
  };
58367
58388
  stageSchemaVersionSchema = exports_external.object({
58368
58389
  major: exports_external.number().int().nonnegative(),
@@ -58433,11 +58454,18 @@ var init_schema4 = __esm(() => {
58433
58454
  }).strict();
58434
58455
  CAPABILITY_TIERS = ["cheap", "standard", "capable-1", "capable-2", "capable-3"];
58435
58456
  capabilityTierSchema = exports_external.preprocess(normalizeCapabilityTier, exports_external.enum(CAPABILITY_TIERS));
58457
+ objectiveEscalationTriggerSchema = exports_external.enum([
58458
+ "gate-fail",
58459
+ "timeout",
58460
+ "insufficient-evidence",
58461
+ "retry-exhausted",
58462
+ "resource-exhaustion"
58463
+ ]);
58436
58464
  stageModelPolicySchema = exports_external.object({
58437
58465
  min_tier: capabilityTierSchema,
58438
58466
  fallback: exports_external.array(exports_external.object({
58439
58467
  tier: capabilityTierSchema,
58440
- trigger: exports_external.enum(["gate-fail", "timeout", "insufficient-evidence", "retry-exhausted"])
58468
+ trigger: objectiveEscalationTriggerSchema
58441
58469
  }).strict()),
58442
58470
  override_key: exports_external.string().optional()
58443
58471
  }).strict();
@@ -58508,7 +58536,10 @@ var init_schema4 = __esm(() => {
58508
58536
  retry: { max_attempts: 3, terminal_stop: "block" },
58509
58537
  model_policy: {
58510
58538
  min_tier: "standard",
58511
- fallback: [{ tier: "capable-2", trigger: "gate-fail" }]
58539
+ fallback: [
58540
+ { tier: "capable-2", trigger: "gate-fail" },
58541
+ { tier: "capable-2", trigger: "resource-exhaustion" }
58542
+ ]
58512
58543
  },
58513
58544
  context_layers: [],
58514
58545
  observability: [],
@@ -58527,7 +58558,10 @@ var init_schema4 = __esm(() => {
58527
58558
  retry: { max_attempts: 3, terminal_stop: "block" },
58528
58559
  model_policy: {
58529
58560
  min_tier: "capable-2",
58530
- fallback: [{ tier: "capable-3", trigger: "gate-fail" }]
58561
+ fallback: [
58562
+ { tier: "capable-3", trigger: "gate-fail" },
58563
+ { tier: "capable-3", trigger: "resource-exhaustion" }
58564
+ ]
58531
58565
  },
58532
58566
  context_layers: [],
58533
58567
  observability: [],
@@ -58548,7 +58582,8 @@ var init_schema4 = __esm(() => {
58548
58582
  min_tier: "standard",
58549
58583
  fallback: [
58550
58584
  { tier: "capable-1", trigger: "gate-fail" },
58551
- { tier: "capable-1", trigger: "timeout" }
58585
+ { tier: "capable-1", trigger: "timeout" },
58586
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58552
58587
  ]
58553
58588
  },
58554
58589
  context_layers: [],
@@ -58567,8 +58602,11 @@ var init_schema4 = __esm(() => {
58567
58602
  mutation_class: "tests",
58568
58603
  retry: { max_attempts: 3, terminal_stop: "block" },
58569
58604
  model_policy: {
58570
- min_tier: "standard",
58571
- fallback: [{ tier: "capable-1", trigger: "gate-fail" }]
58605
+ fallback: [
58606
+ { tier: "capable-1", trigger: "gate-fail" },
58607
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58608
+ ],
58609
+ min_tier: "standard"
58572
58610
  },
58573
58611
  context_layers: [],
58574
58612
  observability: [],
@@ -58606,7 +58644,10 @@ var init_schema4 = __esm(() => {
58606
58644
  retry: { max_attempts: 2, terminal_stop: "block" },
58607
58645
  model_policy: {
58608
58646
  min_tier: "standard",
58609
- fallback: [{ tier: "capable-1", trigger: "gate-fail" }]
58647
+ fallback: [
58648
+ { tier: "capable-1", trigger: "gate-fail" },
58649
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58650
+ ]
58610
58651
  },
58611
58652
  context_layers: [],
58612
58653
  observability: [],
@@ -58625,7 +58666,10 @@ var init_schema4 = __esm(() => {
58625
58666
  retry: { max_attempts: 2, terminal_stop: "block" },
58626
58667
  model_policy: {
58627
58668
  min_tier: "standard",
58628
- fallback: [{ tier: "capable-1", trigger: "gate-fail" }]
58669
+ fallback: [
58670
+ { tier: "capable-1", trigger: "gate-fail" },
58671
+ { tier: "capable-1", trigger: "resource-exhaustion" }
58672
+ ]
58629
58673
  },
58630
58674
  context_layers: [],
58631
58675
  observability: [],
@@ -60268,13 +60312,13 @@ __export(exports_src, {
60268
60312
  queryEtlRecords: () => queryEtlRecords,
60269
60313
  queryAllEtlRecords: () => queryAllEtlRecords,
60270
60314
  projectSnapshotSchema: () => projectSnapshotSchema,
60271
- pickStartingTier: () => pickStartingTier,
60272
60315
  passAllResolver: () => passAllResolver,
60273
60316
  parseStageRecord: () => parseStageRecord,
60274
60317
  parseHistoryLine: () => parseHistoryLine,
60275
60318
  parseFeature: () => parseFeature,
60276
60319
  parseExistingAcTags: () => parseExistingAcTags,
60277
60320
  parseChecklist: () => parseChecklist,
60321
+ objectiveEscalationTriggerSchema: () => objectiveEscalationTriggerSchema,
60278
60322
  normalizeTitle: () => normalizeTitle,
60279
60323
  normalizeTaskStatusSafe: () => normalizeTaskStatusSafe,
60280
60324
  normalizeTaskStatus: () => normalizeTaskStatus,
@@ -60588,92 +60632,159 @@ class AgentService {
60588
60632
  if (!resolved.ok) {
60589
60633
  return { ok: false, exitCode: resolved.exitCode, message: resolved.message };
60590
60634
  }
60591
- const agent = resolved.agent;
60592
- if (!jsonOutput && TIER2_AGENTS.has(agent)) {
60593
- this.ctx.output.error(`Warning: ${agent} is a Tier-2 agent (TUI/gateway only)`);
60635
+ const runFlags = { ...flags };
60636
+ let currentAgent = resolved.agent;
60637
+ let currentModel = resolved.model;
60638
+ let currentSource = resolved.source;
60639
+ let currentStage = resolved.stage;
60640
+ const maxEscalations = currentStage?.policy.fallback.length ?? 0;
60641
+ const attemptedExecutors = new Set(currentStage ? [currentStage.executorName] : []);
60642
+ if (!jsonOutput && TIER2_AGENTS.has(currentAgent)) {
60643
+ this.ctx.output.error(`Warning: ${currentAgent} is a Tier-2 agent (TUI/gateway only)`);
60594
60644
  }
60595
- const translated = prompt !== undefined && isClaudeStyleSlashCommand(prompt) ? translateSlashCommand(agent, prompt) : undefined;
60596
- const input = translated ?? prompt;
60645
+ const explicitModel = stringFlag(flags, "model", "") || undefined;
60597
60646
  const purpose = stringFlag(flags, "purpose", "") || undefined;
60598
60647
  const tags = parseTagsFlag(flags);
60599
60648
  const systemPrompt = stringFlag(flags, "system-prompt", "") || undefined;
60600
60649
  const taskId = stringFlag(flags, "task", "") || undefined;
60601
- const explicitModel = stringFlag(flags, "model", "") || undefined;
60602
- const model = explicitModel ?? resolved.model;
60603
- const promptOptions = {
60604
- input,
60605
- continue: continueFlag || undefined,
60606
- model,
60607
- mode,
60608
- ...purpose !== undefined ? { purpose } : {},
60609
- ...tags !== undefined ? { tags } : {},
60610
- ...systemPrompt !== undefined ? { systemPrompt } : {},
60611
- ...taskId !== undefined ? { taskId } : {}
60612
- };
60613
- let shimCommand;
60614
- try {
60615
- shimCommand = typeof runner.buildPromptCommand === "function" ? runner.buildPromptCommand(agent, promptOptions, { cwd: cwd || undefined }) : getAgentShim(agent).getPromptCommand(promptOptions);
60616
- if (!jsonOutput) {
60617
- const version3 = (await detector.detectOne(agent)).version;
60618
- this.ctx.output.error(`\u2699\uFE0F ${agent}${version3 !== null ? ` v${version3}` : ""}
60619
- ${shimCommand.command} ${shimCommand.args.join(" ")}`);
60620
- }
60621
- } catch (error51) {
60622
- return { ok: false, exitCode: 2, message: error51 instanceof Error ? error51.message : String(error51) };
60623
- }
60624
- const traceInput = input === undefined ? undefined : traceSafePrompt(input);
60625
- const invocation = {
60626
- agent,
60627
- source: resolved.source,
60628
- command: shimCommand.command,
60629
- argv: sanitizeInvocationArgv(shimCommand.args, input, traceInput),
60630
- ...cwd !== "" ? { cwd } : {},
60631
- mode,
60632
- outputMode,
60633
- ...timeoutMs !== undefined ? { timeoutMs } : {},
60634
- continue: continueFlag,
60635
- stdinInteractive: false,
60636
- ...model !== undefined ? { model } : {},
60637
- ...translated !== undefined && prompt !== undefined ? { translatedFrom: traceSafePrompt(prompt) } : {}
60638
- };
60639
- let result;
60640
60650
  const controller = new AbortController;
60641
60651
  const onTerminate = () => controller.abort();
60642
60652
  const onExternalAbort = () => controller.abort();
60643
60653
  const lifecycle = new AgentExecutionLifecycle(options.execution?.observer, options.execution?.correlation, configuredSecretValues(this.ctx.env), options.execution?.heartbeatMs);
60644
- lifecycle.start({
60645
- agent,
60646
- ...model !== undefined ? { model } : {},
60647
- invocation: `${invocation.command} ${invocation.argv.join(" ")}`,
60648
- ...timeoutMs !== undefined ? { timeoutMs } : {}
60649
- });
60650
- const dispatchStartedAt = Date.now();
60654
+ process.on("SIGTERM", onTerminate);
60655
+ process.on("SIGINT", onTerminate);
60656
+ options.execution?.signal?.addEventListener("abort", onExternalAbort, { once: true });
60657
+ if (options.execution?.signal?.aborted === true)
60658
+ controller.abort();
60659
+ let result;
60660
+ let invocation;
60661
+ let dispatchStartedAt = Date.now();
60651
60662
  try {
60652
- process.on("SIGTERM", onTerminate);
60653
- process.on("SIGINT", onTerminate);
60654
- options.execution?.signal?.addEventListener("abort", onExternalAbort, { once: true });
60655
- if (options.execution?.signal?.aborted === true)
60656
- controller.abort();
60657
- result = await runner.runPromptCommand(agent, promptOptions, {
60658
- cwd: cwd || undefined,
60659
- ...timeoutMs !== undefined ? { timeout: timeoutMs } : {},
60660
- signal: controller.signal,
60661
- correlation: lifecycle.identity,
60662
- onOutput: (output2) => lifecycle.observe(output2)
60663
- });
60664
- } catch (error51) {
60665
- lifecycle.finish({
60666
- exitCode: null,
60667
- durationMs: Date.now() - dispatchStartedAt,
60668
- ...controller.signal.aborted ? { reason: "cancelled" } : {},
60669
- ...!controller.signal.aborted ? { reason: error51 instanceof Error ? error51.message : String(error51) } : {}
60670
- });
60671
- return { ok: false, exitCode: 2, message: error51 instanceof Error ? error51.message : String(error51) };
60663
+ for (let attempt = 0;; attempt++) {
60664
+ const agent = currentAgent;
60665
+ const model = explicitModel ?? currentModel;
60666
+ const translated = prompt !== undefined && isClaudeStyleSlashCommand(prompt) ? translateSlashCommand(agent, prompt) : undefined;
60667
+ const input = translated ?? prompt;
60668
+ const promptOptions = {
60669
+ input,
60670
+ continue: continueFlag || undefined,
60671
+ model,
60672
+ mode,
60673
+ ...purpose !== undefined ? { purpose } : {},
60674
+ ...tags !== undefined ? { tags } : {},
60675
+ ...systemPrompt !== undefined ? { systemPrompt } : {},
60676
+ ...taskId !== undefined ? { taskId } : {}
60677
+ };
60678
+ let shimCommand;
60679
+ try {
60680
+ shimCommand = typeof runner.buildPromptCommand === "function" ? runner.buildPromptCommand(agent, promptOptions, { cwd: cwd || undefined }) : getAgentShim(agent).getPromptCommand(promptOptions);
60681
+ if (!jsonOutput) {
60682
+ const version3 = (await detector.detectOne(agent)).version;
60683
+ this.ctx.output.error(`\u2699\uFE0F ${agent}${version3 !== null ? ` v${version3}` : ""}
60684
+ ${shimCommand.command} ${shimCommand.args.join(" ")}`);
60685
+ }
60686
+ } catch (error51) {
60687
+ if (attempt === 0) {
60688
+ return {
60689
+ ok: false,
60690
+ exitCode: 2,
60691
+ message: error51 instanceof Error ? error51.message : String(error51)
60692
+ };
60693
+ }
60694
+ if (!jsonOutput) {
60695
+ this.ctx.output.error(`Escalation aborted: ${error51 instanceof Error ? error51.message : String(error51)}`);
60696
+ }
60697
+ break;
60698
+ }
60699
+ const traceInput = input === undefined ? undefined : traceSafePrompt(input);
60700
+ const attemptInvocation = {
60701
+ agent,
60702
+ source: currentSource,
60703
+ command: shimCommand.command,
60704
+ argv: sanitizeInvocationArgv(shimCommand.args, input, traceInput),
60705
+ ...cwd !== "" ? { cwd } : {},
60706
+ mode,
60707
+ outputMode,
60708
+ ...timeoutMs !== undefined ? { timeoutMs } : {},
60709
+ continue: continueFlag,
60710
+ stdinInteractive: false,
60711
+ ...model !== undefined ? { model } : {},
60712
+ ...translated !== undefined && prompt !== undefined ? { translatedFrom: traceSafePrompt(prompt) } : {}
60713
+ };
60714
+ if (attempt === 0) {
60715
+ lifecycle.start({
60716
+ agent,
60717
+ ...model !== undefined ? { model } : {},
60718
+ invocation: `${attemptInvocation.command} ${attemptInvocation.argv.join(" ")}`,
60719
+ ...timeoutMs !== undefined ? { timeoutMs } : {}
60720
+ });
60721
+ dispatchStartedAt = Date.now();
60722
+ }
60723
+ try {
60724
+ result = await runner.runPromptCommand(agent, promptOptions, {
60725
+ cwd: cwd || undefined,
60726
+ ...timeoutMs !== undefined ? { timeout: timeoutMs } : {},
60727
+ signal: controller.signal,
60728
+ correlation: lifecycle.identity,
60729
+ onOutput: (output2) => lifecycle.observe(output2)
60730
+ });
60731
+ } catch (error51) {
60732
+ if (attempt === 0) {
60733
+ lifecycle.finish({
60734
+ exitCode: null,
60735
+ durationMs: Date.now() - dispatchStartedAt,
60736
+ ...controller.signal.aborted ? { reason: "cancelled" } : {},
60737
+ ...!controller.signal.aborted ? { reason: error51 instanceof Error ? error51.message : String(error51) } : {}
60738
+ });
60739
+ return {
60740
+ ok: false,
60741
+ exitCode: 2,
60742
+ message: error51 instanceof Error ? error51.message : String(error51)
60743
+ };
60744
+ }
60745
+ if (!jsonOutput) {
60746
+ this.ctx.output.error(`Escalation dispatch failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
60747
+ }
60748
+ break;
60749
+ }
60750
+ invocation = attemptInvocation;
60751
+ if (result.exitCode === 0)
60752
+ break;
60753
+ const escalationSignal = classifyObjectiveFailure(result);
60754
+ if (escalationSignal === undefined || currentStage === undefined || attempt >= maxEscalations) {
60755
+ break;
60756
+ }
60757
+ runFlags.signal = escalationSignal;
60758
+ runFlags["from-executor"] = currentStage.executorName;
60759
+ const nextResolved = await this.resolveAgent(prompt, runFlags, doctorRunner);
60760
+ if (!nextResolved.ok || nextResolved.stage === undefined || attemptedExecutors.has(nextResolved.stage.executorName)) {
60761
+ if (!jsonOutput) {
60762
+ this.ctx.output.error(`Escalation chain exhausted after ${attempt + 1} attempt(s); executors tried: ${[...attemptedExecutors].join(", ")}`);
60763
+ }
60764
+ break;
60765
+ }
60766
+ if (!jsonOutput) {
60767
+ this.ctx.output.error(`Escalating: ${currentStage.executorName} (tier ${currentStage.executorTier}) failed with ${escalationSignal}; retrying on ${nextResolved.stage.executorName} (tier ${nextResolved.stage.executorTier})`);
60768
+ }
60769
+ currentAgent = nextResolved.agent;
60770
+ currentModel = nextResolved.model;
60771
+ currentSource = nextResolved.source;
60772
+ currentStage = nextResolved.stage;
60773
+ attemptedExecutors.add(nextResolved.stage.executorName);
60774
+ }
60672
60775
  } finally {
60673
60776
  process.off("SIGTERM", onTerminate);
60674
60777
  process.off("SIGINT", onTerminate);
60675
60778
  options.execution?.signal?.removeEventListener("abort", onExternalAbort);
60676
60779
  }
60780
+ if (result === undefined || invocation === undefined) {
60781
+ lifecycle.finish({
60782
+ exitCode: null,
60783
+ durationMs: Date.now() - dispatchStartedAt,
60784
+ reason: "no dispatch attempted"
60785
+ });
60786
+ return { ok: false, exitCode: 2, message: "No dispatch attempted" };
60787
+ }
60677
60788
  lifecycle.finish({
60678
60789
  exitCode: result.exitCode,
60679
60790
  durationMs: result.durationMs,
@@ -60703,6 +60814,13 @@ class AgentService {
60703
60814
  const raw = stringFlag(flags, "agent", "auto");
60704
60815
  if (raw === "auto")
60705
60816
  return this.resolveAgentAuto(prompt, flags, doctorRunner);
60817
+ if (raw === "inline") {
60818
+ return {
60819
+ ok: false,
60820
+ exitCode: 2,
60821
+ 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."
60822
+ };
60823
+ }
60706
60824
  return this.resolveExecutorSelector(raw, doctorRunner, "explicit");
60707
60825
  }
60708
60826
  async resolveAgentAuto(prompt, flags, doctorRunner) {
@@ -60773,7 +60891,13 @@ class AgentService {
60773
60891
  ok: true,
60774
60892
  agent: canonical,
60775
60893
  model: executor.model,
60776
- source: "stage"
60894
+ source: "stage",
60895
+ stage: {
60896
+ stageId: stageRecord.id,
60897
+ policy,
60898
+ executorName: executor.name,
60899
+ executorTier: getExecutorTier(executor)
60900
+ }
60777
60901
  };
60778
60902
  }
60779
60903
  }
@@ -60821,8 +60945,15 @@ class AgentService {
60821
60945
  };
60822
60946
  }
60823
60947
  const canonical = resolveAgentName(selector);
60824
- if (canonical === undefined)
60825
- return { ok: false, exitCode: 2, message: `Unknown agent: ${selector}` };
60948
+ if (canonical === undefined) {
60949
+ const names = this.ctx.agentConfig?.executors?.map((e) => e.name) ?? [];
60950
+ const available = names.length > 0 ? names.join(", ") : "(no executors configured; use a canonical agent name)";
60951
+ return {
60952
+ ok: false,
60953
+ exitCode: 2,
60954
+ message: `Unknown agent: '${selector}'. Available executors: ${available}.`
60955
+ };
60956
+ }
60826
60957
  const usable = await this.checkUsable(canonical, doctorRunner);
60827
60958
  if (!usable.ok)
60828
60959
  return usable.result;
@@ -61008,6 +61139,17 @@ function getExecutorTier(executor) {
61008
61139
  return "capable-1";
61009
61140
  return "standard";
61010
61141
  }
61142
+ function classifyObjectiveFailure(result) {
61143
+ if (result.signal !== undefined)
61144
+ return "timeout";
61145
+ if (result.exitCode === 0)
61146
+ return;
61147
+ const text4 = `${result.stderr} ${result.stdout}`.toLowerCase();
61148
+ if (/\b(rate[\s-]?limit|429|too many requests|quota|token limit|token budget|context length|maximum context|context window)\b/.test(text4)) {
61149
+ return "resource-exhaustion";
61150
+ }
61151
+ return;
61152
+ }
61011
61153
  var TRACE_SAFE_SLASH_COMMAND, TRACE_SAFE_SLASH_TOKEN, SENSITIVE_FLAG, SENSITIVE_INLINE_FLAG;
61012
61154
  var init_agent_service = __esm(() => {
61013
61155
  init_src2();
@@ -61861,11 +62003,106 @@ var init_planning_check_base = __esm(() => {
61861
62003
  // ../../packages/app/src/services/feature-check.ts
61862
62004
  var exports_feature_check = {};
61863
62005
  __export(exports_feature_check, {
62006
+ findOtherP0InStatus: () => findOtherP0InStatus,
61864
62007
  defaultVerdictRunDir: () => defaultVerdictRunDir,
61865
62008
  FeatureCheckService: () => FeatureCheckService,
61866
62009
  DEFAULT_FEATURE_MATRIX: () => DEFAULT_FEATURE_MATRIX
61867
62010
  });
61868
62011
  import { dirname as dirname8, join as join8 } from "path";
62012
+ function isGroupFeature(fm) {
62013
+ const tags = fm.tags;
62014
+ return Array.isArray(tags) && tags.includes("group") ? "group" : "standard";
62015
+ }
62016
+ async function findOtherP0InStatus(fs3, featuresDir, currentId, statuses) {
62017
+ try {
62018
+ const entries = await fs3.readDir(featuresDir);
62019
+ for (const entry of entries) {
62020
+ if (!entry.endsWith(".md"))
62021
+ continue;
62022
+ const match = /^([A-Z][1-9]*)_/.exec(entry);
62023
+ if (match === null)
62024
+ continue;
62025
+ const otherId = match[1];
62026
+ if (otherId === undefined)
62027
+ continue;
62028
+ if (otherId === currentId)
62029
+ continue;
62030
+ try {
62031
+ const raw = await fs3.readFile(`${featuresDir}/${entry}`);
62032
+ const doc2 = MarkdownDocument.parse(raw, "feature");
62033
+ const otherFm = doc2.frontmatterData ?? {};
62034
+ const otherPriority = otherFm.priority;
62035
+ const otherStatus = otherFm.status ?? "backlog";
62036
+ if (otherPriority === "P0" && statuses.includes(otherStatus)) {
62037
+ return { id: otherId, status: otherStatus };
62038
+ }
62039
+ } catch {}
62040
+ }
62041
+ } catch {}
62042
+ return null;
62043
+ }
62044
+ function decodeVerdictRows(source, sectionName, required2) {
62045
+ if (source === undefined) {
62046
+ return {
62047
+ rows: [],
62048
+ rejected: 0,
62049
+ invalidFields: required2 ? [`${sectionName} (missing array)`] : [],
62050
+ state: "absent"
62051
+ };
62052
+ }
62053
+ if (!Array.isArray(source)) {
62054
+ return {
62055
+ rows: [],
62056
+ rejected: 0,
62057
+ invalidFields: [`${sectionName} (expected array)`],
62058
+ state: "invalid"
62059
+ };
62060
+ }
62061
+ const rows = [];
62062
+ const invalidFields = new Set;
62063
+ let rejected = 0;
62064
+ for (const r of source) {
62065
+ if (typeof r !== "object" || r === null) {
62066
+ rejected++;
62067
+ invalidFields.add(`${sectionName}[non-object]`);
62068
+ continue;
62069
+ }
62070
+ const row = r;
62071
+ const hasId = Object.hasOwn(row, "id");
62072
+ const hasScenario = Object.hasOwn(row, "scenario");
62073
+ const idStr = typeof row.id === "string";
62074
+ const scStr = typeof row.scenario === "string";
62075
+ const statusOk = typeof row.status === "string";
62076
+ if (!statusOk) {
62077
+ rejected++;
62078
+ invalidFields.add(`${sectionName}.status`);
62079
+ continue;
62080
+ }
62081
+ if (hasId && hasScenario) {
62082
+ if (idStr && scStr && row.id === row.scenario) {
62083
+ rows.push({ id: row.id, status: row.status });
62084
+ } else {
62085
+ rejected++;
62086
+ invalidFields.add(`${sectionName}.id/scenario conflict`);
62087
+ }
62088
+ continue;
62089
+ }
62090
+ if (hasId && idStr) {
62091
+ rows.push({ id: row.id, status: row.status });
62092
+ } else if (hasScenario && scStr) {
62093
+ rows.push({ id: row.scenario, status: row.status });
62094
+ } else {
62095
+ rejected++;
62096
+ invalidFields.add(`${sectionName}.id/scenario missing`);
62097
+ }
62098
+ }
62099
+ return {
62100
+ rows,
62101
+ rejected,
62102
+ invalidFields: [...invalidFields],
62103
+ state: source.length === 0 ? "empty" : "populated"
62104
+ };
62105
+ }
61869
62106
  function defaultVerdictRunDir(tasksDir) {
61870
62107
  const norm = tasksDir.replace(/\\/g, "/");
61871
62108
  if (/\/docs\/tasks\d*$/.test(norm) || /\/docs\/tasks$/.test(norm)) {
@@ -61911,6 +62148,35 @@ var init_feature_check = __esm(() => {
61911
62148
  required: ["Notes"],
61912
62149
  optional: ["Goal", "Scope", "Acceptance Criteria", "Tasks", "History"]
61913
62150
  }
62151
+ },
62152
+ group: {
62153
+ backlog: {
62154
+ required: [],
62155
+ optional: ["Goal", "Scope", "Acceptance Criteria", "Tasks", "Notes", "History"]
62156
+ },
62157
+ active: {
62158
+ required: ["Goal", "Scope"],
62159
+ optional: ["Acceptance Criteria", "Tasks", "Notes", "History"],
62160
+ gate: true
62161
+ },
62162
+ verifying: {
62163
+ required: ["Goal", "Scope"],
62164
+ optional: ["Acceptance Criteria", "Tasks", "Notes", "History"],
62165
+ gate: true
62166
+ },
62167
+ blocked: {
62168
+ required: ["Goal", "Notes"],
62169
+ optional: ["Scope", "Acceptance Criteria", "Tasks", "History"]
62170
+ },
62171
+ done: {
62172
+ required: ["Goal", "Scope", "Tasks"],
62173
+ optional: ["Acceptance Criteria", "Notes", "History"],
62174
+ gate: true
62175
+ },
62176
+ cancelled: {
62177
+ required: ["Notes"],
62178
+ optional: ["Goal", "Scope", "Acceptance Criteria", "Tasks", "History"]
62179
+ }
61914
62180
  }
61915
62181
  }
61916
62182
  };
@@ -61934,11 +62200,11 @@ var init_feature_check = __esm(() => {
61934
62200
  }
61935
62201
  const fm = doc2.frontmatterData ?? {};
61936
62202
  const status = fm.status ?? "backlog";
61937
- const entry = this.resolveMatrixEntry("standard", status);
62203
+ const entry = this.resolveMatrixEntry(isGroupFeature(fm), status);
61938
62204
  this.runL2(doc2, entry, findings);
61939
62205
  this.runL3(doc2, findings);
61940
62206
  if (options?.featuresDir) {
61941
- await this.checkOneActiveGoal(fm, featureId2, options.featuresDir, findings);
62207
+ await this.checkOneActiveGoal(fm, featureId2, options.featuresDir, findings, options.asStatus);
61942
62208
  await this.checkChildrenLimit(featureId2, options.featuresDir, findings);
61943
62209
  }
61944
62210
  const dogfoodDir = options?.dogfoodDir ?? (options?.featuresDir ? join8(dirname8(options.featuresDir), "dogfood") : undefined);
@@ -62011,44 +62277,24 @@ var init_feature_check = __esm(() => {
62011
62277
  }
62012
62278
  }
62013
62279
  }
62014
- async checkOneActiveGoal(fm, currentId, featuresDir, findings) {
62280
+ async checkOneActiveGoal(fm, currentId, featuresDir, findings, asStatus) {
62015
62281
  const priority = fm.priority;
62016
- const status = fm.status;
62282
+ const status = fm.status ?? "backlog";
62283
+ const effectiveStatus = asStatus ?? status;
62017
62284
  if (priority !== "P0")
62018
62285
  return;
62019
- if (status !== "active" && status !== "verifying")
62286
+ if (effectiveStatus !== "active")
62020
62287
  return;
62021
- try {
62022
- const entries = await this.fs.readDir(featuresDir);
62023
- for (const entry of entries) {
62024
- if (!entry.endsWith(".md"))
62025
- continue;
62026
- const otherPath = `${featuresDir}/${entry}`;
62027
- const match = /^([A-Z][1-9]*)_/.exec(entry);
62028
- if (!match)
62029
- continue;
62030
- const otherId = match[1];
62031
- if (otherId === currentId)
62032
- continue;
62033
- try {
62034
- const raw = await this.fs.readFile(otherPath);
62035
- const doc2 = MarkdownDocument.parse(raw, "feature");
62036
- const otherFm = doc2.frontmatterData ?? {};
62037
- const otherPriority = otherFm.priority;
62038
- const otherStatus = otherFm.status;
62039
- if (otherPriority === "P0" && (otherStatus === "active" || otherStatus === "verifying")) {
62040
- findings.push({
62041
- layer: "L3",
62042
- code: FINDING_CODES.L3_ONE_ACTIVE_GOAL,
62043
- severity: "error",
62044
- section: "",
62045
- message: `One-active-goal violated: P0 feature "${otherId}" is already ${otherStatus}`
62046
- });
62047
- return;
62048
- }
62049
- } catch {}
62050
- }
62051
- } catch {}
62288
+ const conflict = await findOtherP0InStatus(this.fs, featuresDir, currentId, ["active"]);
62289
+ if (conflict !== null) {
62290
+ findings.push({
62291
+ layer: "L3",
62292
+ code: FINDING_CODES.L3_ONE_ACTIVE_GOAL,
62293
+ severity: "error",
62294
+ section: "",
62295
+ message: `One-active-goal violated: P0 feature "${conflict.id}" is already ${conflict.status}`
62296
+ });
62297
+ }
62052
62298
  }
62053
62299
  async checkChildrenLimit(featureId2, featuresDir, findings) {
62054
62300
  let children = 0;
@@ -62209,11 +62455,42 @@ var init_feature_check = __esm(() => {
62209
62455
  }
62210
62456
  covers[sc.title] = linked;
62211
62457
  }
62458
+ const doneWbs = new Set;
62459
+ for (const sc of scenarioAliases) {
62460
+ for (const task of covers[sc.title] ?? []) {
62461
+ if (task.status === "done")
62462
+ doneWbs.add(task.wbs);
62463
+ }
62464
+ }
62465
+ const artifacts2 = new Map;
62466
+ for (const wbs of doneWbs) {
62467
+ const artifact = await this.readVerdictArtifact(runDir, wbs);
62468
+ artifacts2.set(wbs, artifact);
62469
+ const diagnosticParts = [];
62470
+ if (artifact.diagnostics.artifactError !== undefined) {
62471
+ diagnosticParts.push(artifact.diagnostics.artifactError);
62472
+ }
62473
+ if (artifact.diagnostics.rejectedRowCount > 0) {
62474
+ diagnosticParts.push(`${artifact.diagnostics.rejectedRowCount} rejected coverage row(s)`);
62475
+ }
62476
+ if (artifact.diagnostics.invalidFields.length > 0) {
62477
+ diagnosticParts.push(`invalid fields: ${artifact.diagnostics.invalidFields.join(", ")}`);
62478
+ }
62479
+ if (diagnosticParts.length > 0) {
62480
+ findings.push({
62481
+ layer: "L4",
62482
+ code: FINDING_CODES.L4_MALFORMED_VERDICT_ARTIFACT,
62483
+ severity: "warning",
62484
+ section: "Acceptance Criteria",
62485
+ 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."
62486
+ });
62487
+ }
62488
+ }
62212
62489
  for (const sc of scenarioAliases) {
62213
62490
  const linked = covers[sc.title] ?? [];
62214
62491
  if (linked.length === 0)
62215
62492
  continue;
62216
- const verified = await this.isScenarioVerified(sc, linked, runDir);
62493
+ const verified = this.isScenarioVerified(sc, linked, artifacts2);
62217
62494
  if (!verified) {
62218
62495
  findings.push({
62219
62496
  layer: "L4",
@@ -62225,12 +62502,12 @@ var init_feature_check = __esm(() => {
62225
62502
  }
62226
62503
  }
62227
62504
  }
62228
- async isScenarioVerified(sc, linked, runDir) {
62505
+ isScenarioVerified(sc, linked, artifacts2) {
62229
62506
  for (const task of linked) {
62230
62507
  if (task.status !== "done")
62231
62508
  continue;
62232
- const artifact = await this.readVerdictArtifact(runDir, task.wbs);
62233
- if (artifact === null)
62509
+ const artifact = artifacts2.get(task.wbs);
62510
+ if (artifact === undefined)
62234
62511
  continue;
62235
62512
  if (artifact.verdict !== "PASS")
62236
62513
  continue;
@@ -62242,20 +62519,35 @@ var init_feature_check = __esm(() => {
62242
62519
  return false;
62243
62520
  }
62244
62521
  async readVerdictArtifact(runDir, wbs) {
62245
- try {
62246
- const raw = await this.fs.readFile(join8(runDir, `${wbs}-verdict.json`));
62247
- const parsed = JSON.parse(raw);
62248
- if (typeof parsed.verdict !== "string")
62249
- return null;
62250
- const pickRows = (arr) => (arr ?? []).filter((r) => typeof r?.id === "string" && typeof r?.status === "string").map((r) => ({ id: r.id, status: r.status }));
62251
- const requirements = pickRows(parsed.requirements);
62252
- const acceptanceCriteria = pickRows(parsed.acceptanceCriteria);
62253
- if (requirements.length === 0 && acceptanceCriteria.length === 0)
62254
- return null;
62255
- return { verdict: parsed.verdict, requirements, acceptanceCriteria };
62256
- } catch {
62257
- return null;
62522
+ const loaded = await readVerdictArtifact(this.fs, runDir, wbs);
62523
+ if (loaded.artifact === undefined) {
62524
+ return {
62525
+ path: loaded.path,
62526
+ requirements: [],
62527
+ acceptanceCriteria: [],
62528
+ diagnostics: {
62529
+ artifactError: loaded.readError ?? "artifact is missing",
62530
+ rejectedRowCount: 0,
62531
+ invalidFields: [],
62532
+ arrayStates: { requirements: "unavailable", acceptanceCriteria: "unavailable" }
62533
+ }
62534
+ };
62258
62535
  }
62536
+ const parsed = loaded.artifact;
62537
+ const req = decodeVerdictRows(parsed.requirements, "requirements", true);
62538
+ const ac = decodeVerdictRows(parsed.acceptanceCriteria, "acceptanceCriteria", false);
62539
+ return {
62540
+ path: loaded.path,
62541
+ verdict: typeof parsed.verdict === "string" ? parsed.verdict : undefined,
62542
+ requirements: req.rows,
62543
+ acceptanceCriteria: ac.rows,
62544
+ diagnostics: {
62545
+ artifactError: typeof parsed.verdict === "string" ? undefined : "invalid `verdict` field",
62546
+ rejectedRowCount: req.rejected + ac.rejected,
62547
+ invalidFields: [...new Set([...req.invalidFields, ...ac.invalidFields])],
62548
+ arrayStates: { requirements: req.state, acceptanceCriteria: ac.state }
62549
+ }
62550
+ };
62259
62551
  }
62260
62552
  };
62261
62553
  });
@@ -62323,6 +62615,25 @@ class TaskLocator {
62323
62615
  }
62324
62616
  return null;
62325
62617
  }
62618
+ async findDuplicateWbs() {
62619
+ const wbsMap = new Map;
62620
+ for (const dir of this.folderDirs()) {
62621
+ for (const name of await readDirIfPresent(this.fs, dir)) {
62622
+ const captured = TASK_FILENAME_RE.exec(name);
62623
+ if (captured === null)
62624
+ continue;
62625
+ const wbs = captured[1];
62626
+ const hit = { wbs, name, filePath: `${dir}/${name}` };
62627
+ const existing = wbsMap.get(wbs);
62628
+ if (existing) {
62629
+ existing.push(hit);
62630
+ } else {
62631
+ wbsMap.set(wbs, [hit]);
62632
+ }
62633
+ }
62634
+ }
62635
+ return [...wbsMap.values()].filter((hits) => hits.length > 1);
62636
+ }
62326
62637
  }
62327
62638
  var TASK_FILENAME_RE;
62328
62639
  var init_task_locator = __esm(() => {
@@ -62609,11 +62920,32 @@ class FeatureService {
62609
62920
  }
62610
62921
  const appliedHops = [];
62611
62922
  for (const hop of hops) {
62923
+ if (hop === "active") {
62924
+ const conflict = await this.findOneActiveGoalConflict(featureId2);
62925
+ if (conflict !== null) {
62926
+ return {
62927
+ proposal: {
62928
+ ...proposal,
62929
+ reason: `Activation blocked by one-active-goal: P0 feature "${conflict.featureId}" is already ${conflict.status}`
62930
+ },
62931
+ applied: false,
62932
+ appliedHops,
62933
+ goalConflict: conflict
62934
+ };
62935
+ }
62936
+ }
62612
62937
  await this.transition(featureId2, hop);
62613
62938
  appliedHops.push(hop);
62614
62939
  }
62615
62940
  return { proposal, applied: true, appliedHops };
62616
62941
  }
62942
+ async findOneActiveGoalConflict(featureId2) {
62943
+ const feature = await this.show(featureId2);
62944
+ if (feature === null || feature.frontmatter.priority !== "P0")
62945
+ return null;
62946
+ const conflict = await findOtherP0InStatus(this.ctx.fs, this.ctx.featuresDir, featureId2, ["active"]);
62947
+ return conflict === null ? null : { featureId: conflict.id, status: conflict.status };
62948
+ }
62617
62949
  async syncAllFeatures(options) {
62618
62950
  const allFeatures = await this.list();
62619
62951
  const tasksByFeature = await this.collectTasksByFeature();
@@ -65347,6 +65679,21 @@ var init_task_check = __esm(() => {
65347
65679
  });
65348
65680
  }
65349
65681
  }
65682
+ const requiredSections = new Set(entry?.required ?? []);
65683
+ for (const sectionName of ["Testing", "Solution"]) {
65684
+ if (!requiredSections.has(sectionName))
65685
+ continue;
65686
+ const body = doc2.getSection(sectionName);
65687
+ if (body === null || !isPlaceholderBody(body))
65688
+ continue;
65689
+ findings.push({
65690
+ layer: "L3",
65691
+ code: FINDING_CODES.L3_REQUIRED_SECTION_PLACEHOLDER,
65692
+ severity: "error",
65693
+ section: sectionName,
65694
+ 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`
65695
+ });
65696
+ }
65350
65697
  const testBody = doc2.getSection("Testing");
65351
65698
  if (testBody !== null && !isPlaceholderBody(testBody)) {
65352
65699
  const hasCoverage = /coverage|\u2265\d+%|\d+\.\d+%|N\/A/i.test(testBody);
@@ -66219,15 +66566,15 @@ class TaskService {
66219
66566
  const variant = params.template ?? (params.featureId !== undefined ? "feature-impl" : DEFAULT_TASK_VARIANT);
66220
66567
  const status = params.status ?? (params.featureId !== undefined ? "todo" : "backlog");
66221
66568
  return this.writeService.createAllocated(folder, async () => {
66222
- if (params.dedupeWithinSec !== undefined && params.featureId !== undefined) {
66223
- const collision = await this.findDuplicateFollowUp(params.featureId, params.title, params.dedupeWithinSec);
66569
+ const dedupeWithinSec = params.dedupeWithinSec === null ? undefined : params.dedupeWithinSec ?? 300;
66570
+ if (dedupeWithinSec !== undefined && params.featureId !== undefined) {
66571
+ const collision = await this.findDuplicateFollowUp(params.featureId, params.title, dedupeWithinSec);
66224
66572
  if (collision !== null) {
66225
66573
  throw new DuplicateFollowUpError(collision.wbs, collision.name, params.title);
66226
66574
  }
66227
66575
  }
66228
- const wbs = await this.allocateWbs();
66229
66576
  const slug = this.slugify(params.title);
66230
- const filePath = this.resolveTaskPath(wbs, slug);
66577
+ const { wbs, filePath } = await this.allocateWbsChecked(slug);
66231
66578
  const now = new Date().toISOString();
66232
66579
  const rawTemplate = this.ctx.resolveTemplate?.(variant);
66233
66580
  if (rawTemplate !== undefined) {
@@ -66630,9 +66977,8 @@ ${issues}`);
66630
66977
  const status = hasSpec ? "todo" : "backlog";
66631
66978
  const variant = item.template ?? (item.feature_id !== undefined && item.feature_id !== null ? "feature-impl" : DEFAULT_TASK_VARIANT);
66632
66979
  return this.writeService.createAllocated(folder, async () => {
66633
- const wbs = await this.allocateWbs();
66634
66980
  const slug = this.slugify(item.name);
66635
- const filePath = this.resolveTaskPath(wbs, slug);
66981
+ const { wbs, filePath } = await this.allocateWbsChecked(slug);
66636
66982
  const now = new Date().toISOString();
66637
66983
  const rawTemplate = this.ctx.resolveTemplate?.(variant);
66638
66984
  if (rawTemplate !== undefined) {
@@ -66785,9 +67131,15 @@ ${block}` : block);
66785
67131
  }
66786
67132
  async allocateWbs() {
66787
67133
  let max = 0;
66788
- const dirs = this.ctx.foldersConfig ? [...new Set([this.ctx.tasksDir, ...Object.keys(this.ctx.foldersConfig.folders)])] : [this.ctx.tasksDir];
67134
+ const dirs = this.allFolderDirs();
67135
+ const folderFloors = new Map;
67136
+ if (this.ctx.foldersConfig) {
67137
+ for (const [key, entry] of Object.entries(this.ctx.foldersConfig.folders)) {
67138
+ folderFloors.set(this.ctx.fs.resolve(key), entry.baseCounter);
67139
+ }
67140
+ }
66789
67141
  for (const dir of dirs) {
66790
- const baseCounter = this.ctx.foldersConfig?.folders[dir]?.base_counter ?? 0;
67142
+ const baseCounter = folderFloors.get(dir) ?? 0;
66791
67143
  if (baseCounter > max)
66792
67144
  max = baseCounter;
66793
67145
  try {
@@ -66804,6 +67156,14 @@ ${block}` : block);
66804
67156
  }
66805
67157
  return String(max + 1).padStart(4, "0");
66806
67158
  }
67159
+ async allocateWbsChecked(slug) {
67160
+ const wbs = await this.allocateWbs();
67161
+ const existing = await this.locator.findByWbs(wbs);
67162
+ if (existing !== null) {
67163
+ throw new WbsCollisionError(wbs, existing.filePath, this.resolveTaskPath(wbs, slug));
67164
+ }
67165
+ return { wbs, filePath: this.resolveTaskPath(wbs, slug) };
67166
+ }
66807
67167
  async getFilePath(wbs) {
66808
67168
  const result = await this.findTaskFileName(wbs);
66809
67169
  if (!result)
@@ -66865,7 +67225,7 @@ ${block}` : block);
66865
67225
  return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
66866
67226
  }
66867
67227
  }
66868
- 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;
67228
+ 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;
66869
67229
  var init_task_service = __esm(() => {
66870
67230
  init_src2();
66871
67231
  init_task_locator();
@@ -66898,6 +67258,18 @@ var init_task_service = __esm(() => {
66898
67258
  this.attemptedName = attemptedName;
66899
67259
  }
66900
67260
  };
67261
+ WbsCollisionError = class WbsCollisionError extends Error {
67262
+ wbs;
67263
+ existingPath;
67264
+ attemptedPath;
67265
+ constructor(wbs, existingPath, attemptedPath) {
67266
+ 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.`);
67267
+ this.name = "WbsCollisionError";
67268
+ this.wbs = wbs;
67269
+ this.existingPath = existingPath;
67270
+ this.attemptedPath = attemptedPath;
67271
+ }
67272
+ };
66901
67273
  ROSTER_REGION_RE = /<!--[ \t]*AUTO-GENERATED[^>]*-->[\s\S]*?<!--[ \t]*END[ \t]*AUTO-GENERATED[^>]*-->/g;
66902
67274
  TASK_ACTION_COMMANDS = {
66903
67275
  refine: (wbs) => `/sp:dev-refine ${wbs} --auto`,
@@ -67884,6 +68256,110 @@ var init_token_ledger_watcher = __esm(() => {
67884
68256
  init_token_ledger_service();
67885
68257
  });
67886
68258
 
68259
+ // ../../packages/app/src/observability/run-output-sink.ts
68260
+ import { closeSync as closeSync4, mkdirSync as mkdirSync6, openSync as openSync4, writeSync as writeSync2 } from "fs";
68261
+ import { join as join14 } from "path";
68262
+
68263
+ class RunOutputSink {
68264
+ filePath;
68265
+ maxBytes;
68266
+ maxLines;
68267
+ fd;
68268
+ bytes = 0;
68269
+ lines = 0;
68270
+ truncated = false;
68271
+ closed = false;
68272
+ constructor(options) {
68273
+ this.filePath = join14(options.dir, `${options.runId}-output.log`);
68274
+ this.maxBytes = options.maxBytes ?? DEFAULT_OUTPUT_MAX_BYTES;
68275
+ this.maxLines = options.maxLines;
68276
+ try {
68277
+ mkdirSync6(options.dir, { recursive: true });
68278
+ this.fd = openSync4(this.filePath, "a");
68279
+ } catch {
68280
+ this.fd = undefined;
68281
+ }
68282
+ }
68283
+ get isTruncated() {
68284
+ return this.truncated;
68285
+ }
68286
+ observe(event2) {
68287
+ if (this.fd === undefined || this.closed)
68288
+ return;
68289
+ switch (event2.kind) {
68290
+ case "output":
68291
+ this.appendChunk(event2.at, event2.stream, event2.chunk);
68292
+ break;
68293
+ case "started":
68294
+ this.append(`# agent output \u2014 run ${event2.runId} \u2014 ${event2.agent} \u2014 ${event2.at}
68295
+ `);
68296
+ this.append(`# invocation: ${event2.invocation}
68297
+ `);
68298
+ break;
68299
+ case "dropped":
68300
+ this.append(`
68301
+ === [dropped] ${event2.chunks} chunk(s) discarded by the lifecycle relay under backpressure ===
68302
+ `);
68303
+ break;
68304
+ case "finished":
68305
+ this.append(`
68306
+ === run ${event2.outcome} (exit ${event2.exitCode}) after ${event2.durationMs}ms ===
68307
+ `);
68308
+ break;
68309
+ default:
68310
+ break;
68311
+ }
68312
+ }
68313
+ close() {
68314
+ if (this.closed)
68315
+ return;
68316
+ this.closed = true;
68317
+ if (this.fd !== undefined) {
68318
+ try {
68319
+ closeSync4(this.fd);
68320
+ } catch {}
68321
+ this.fd = undefined;
68322
+ }
68323
+ }
68324
+ appendChunk(at, stream, chunk) {
68325
+ if (this.truncated)
68326
+ return;
68327
+ const text4 = `[${at}] ${stream}: ${chunk}
68328
+ `;
68329
+ const chunkBytes = Buffer.byteLength(text4);
68330
+ const chunkLines = countNewlines(text4);
68331
+ if (this.bytes + chunkBytes > this.maxBytes || this.maxLines !== undefined && this.lines + chunkLines > this.maxLines) {
68332
+ this.truncated = true;
68333
+ this.append(TRUNCATION_MARKER);
68334
+ return;
68335
+ }
68336
+ this.append(text4);
68337
+ }
68338
+ append(text4) {
68339
+ if (this.fd === undefined || this.closed)
68340
+ return;
68341
+ try {
68342
+ writeSync2(this.fd, text4);
68343
+ this.bytes += Buffer.byteLength(text4);
68344
+ this.lines += countNewlines(text4);
68345
+ } catch {}
68346
+ }
68347
+ }
68348
+ function countNewlines(text4) {
68349
+ let count3 = 0;
68350
+ for (let i2 = 0;i2 < text4.length; i2 += 1) {
68351
+ if (text4.charCodeAt(i2) === 10)
68352
+ count3 += 1;
68353
+ }
68354
+ return count3;
68355
+ }
68356
+ var DEFAULT_OUTPUT_MAX_BYTES, TRUNCATION_MARKER = `
68357
+ === [truncated] agent output capture reached its configured bound; further chunks were not written ===
68358
+ `;
68359
+ var init_run_output_sink = __esm(() => {
68360
+ DEFAULT_OUTPUT_MAX_BYTES = 1024 * 1024;
68361
+ });
68362
+
67887
68363
  // ../../packages/app/src/workflow/steering.ts
67888
68364
  class WorkflowSteeringController {
67889
68365
  onAck;
@@ -68126,16 +68602,18 @@ var init_steering = __esm(() => {
68126
68602
  });
68127
68603
 
68128
68604
  // ../../packages/app/src/workflow/actions/agent-run.ts
68129
- import { dirname as dirname12, isAbsolute as isAbsolute2, join as join14 } from "path";
68605
+ import { dirname as dirname12, isAbsolute as isAbsolute2, join as join15 } from "path";
68130
68606
 
68131
68607
  class AgentRunActionRunner {
68132
68608
  observabilityBus;
68133
68609
  steeringController;
68610
+ outputLog;
68134
68611
  kind = KIND;
68135
68612
  agentService;
68136
- constructor(agentService, observabilityBus, steeringController) {
68613
+ constructor(agentService, observabilityBus, steeringController, outputLog) {
68137
68614
  this.observabilityBus = observabilityBus;
68138
68615
  this.steeringController = steeringController;
68616
+ this.outputLog = outputLog;
68139
68617
  this.agentService = agentService;
68140
68618
  }
68141
68619
  async execute(options, context4) {
@@ -68146,7 +68624,8 @@ class AgentRunActionRunner {
68146
68624
  const cwd = asOptionalString(options.cwd) ?? context4.workdir ?? ".";
68147
68625
  let continueFlag = asOptionalBoolean(options.continue);
68148
68626
  const latch = context4.vars.__agentSession;
68149
- if (continueFlag === undefined && latch === "open") {
68627
+ const latchAutoContinued = continueFlag === undefined && latch === "open";
68628
+ if (latchAutoContinued) {
68150
68629
  continueFlag = true;
68151
68630
  }
68152
68631
  if (input === undefined && !continueFlag) {
@@ -68178,78 +68657,100 @@ class AgentRunActionRunner {
68178
68657
  const expectFile = asOptionalString(options.expectFile);
68179
68658
  const capture = asOptionalBoolean(options.capture) || answerFile !== undefined;
68180
68659
  const agentLabel = agent ?? "<default>";
68181
- const observer = this.observabilityBus === undefined ? undefined : (event2) => {
68660
+ const outputLog = this.outputLog;
68661
+ const sink = outputLog === undefined ? undefined : new RunOutputSink({
68662
+ dir: join15(cwd, ".spur", "run"),
68663
+ runId: context4.runId,
68664
+ ...outputLog.maxBytes !== undefined ? { maxBytes: outputLog.maxBytes } : {},
68665
+ ...outputLog.maxLines !== undefined ? { maxLines: outputLog.maxLines } : {}
68666
+ });
68667
+ const observer = this.observabilityBus === undefined && sink === undefined ? undefined : (event2) => {
68668
+ sink?.observe(event2);
68182
68669
  this.observabilityBus?.emit("workflow.agent", event2);
68183
68670
  };
68184
68671
  const actionId = context4.actionId ?? `${context4.runId}:${context4.stateOrNodeId}`;
68185
68672
  const steeringPolicy = parseSteeringPolicy(options);
68186
- let steeringSignal = this.steeringController?.begin(context4.runId, actionId, steeringPolicy);
68673
+ let resumeRetried = false;
68187
68674
  let steeringNote;
68188
68675
  let traced;
68189
- while (true) {
68190
- traced = await this.agentService.runTraced(input, flags, undefined, {
68191
- correlation: {
68192
- runId: context4.runId,
68193
- executionId: crypto.randomUUID(),
68194
- actionId
68195
- },
68196
- ...observer !== undefined ? { observer } : {},
68197
- ...steeringSignal !== undefined ? { signal: steeringSignal } : {}
68198
- });
68199
- if (this.steeringController === undefined)
68676
+ try {
68677
+ for (;; ) {
68678
+ steeringNote = undefined;
68679
+ let steeringSignal = this.steeringController?.begin(context4.runId, actionId, steeringPolicy);
68680
+ while (true) {
68681
+ traced = await this.agentService.runTraced(input, flags, undefined, {
68682
+ correlation: {
68683
+ runId: context4.runId,
68684
+ executionId: crypto.randomUUID(),
68685
+ actionId
68686
+ },
68687
+ ...observer !== undefined ? { observer } : {},
68688
+ ...steeringSignal !== undefined ? { signal: steeringSignal } : {}
68689
+ });
68690
+ if (this.steeringController === undefined)
68691
+ break;
68692
+ const decision = await this.steeringController.boundary(traced.exitCode === 0);
68693
+ if (decision.operation === "retry") {
68694
+ steeringSignal = this.steeringController.nextAttempt();
68695
+ continue;
68696
+ }
68697
+ if (decision.operation === "note")
68698
+ steeringNote = decision.note;
68699
+ if (decision.operation === "abort" && traced.exitCode === 0) {
68700
+ traced = {
68701
+ ...traced,
68702
+ exitCode: 3,
68703
+ signal: "STEERING_ABORT",
68704
+ message: "aborted at steering boundary"
68705
+ };
68706
+ }
68707
+ break;
68708
+ }
68709
+ this.steeringController?.complete();
68710
+ if (!resumeRetried && latchAutoContinued && traced.exitCode === 2) {
68711
+ resumeRetried = true;
68712
+ delete flags.continue;
68713
+ continue;
68714
+ }
68200
68715
  break;
68201
- const decision = await this.steeringController.boundary(traced.exitCode === 0);
68202
- if (decision.operation === "retry") {
68203
- steeringSignal = this.steeringController.nextAttempt();
68204
- continue;
68205
68716
  }
68206
- if (decision.operation === "note")
68207
- steeringNote = decision.note;
68208
- if (decision.operation === "abort" && traced.exitCode === 0) {
68209
- traced = {
68210
- ...traced,
68211
- exitCode: 3,
68212
- signal: "STEERING_ABORT",
68213
- message: "aborted at steering boundary"
68214
- };
68717
+ const { exitCode, stdout: answer } = traced;
68718
+ const ok = exitCode === 0;
68719
+ const invocation = traced.invocation;
68720
+ if (capture && answerFile !== undefined) {
68721
+ const target = isAbsolute2(answerFile) ? answerFile : join15(cwd, answerFile);
68722
+ const fs3 = createNodeFileSystem3(cwd);
68723
+ await fs3.ensureDir(dirname12(target));
68724
+ await fs3.writeFile(target, answer);
68725
+ }
68726
+ if (ok && expectFile !== undefined) {
68727
+ const target = isAbsolute2(expectFile) ? expectFile : join15(cwd, expectFile);
68728
+ const fs3 = createNodeFileSystem3(cwd);
68729
+ if (!await fs3.exists(target)) {
68730
+ return {
68731
+ ok: false,
68732
+ data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68733
+ error: `agent.run (${agentLabel}) exited 0 but expected file is absent: ${expectFile}`
68734
+ };
68735
+ }
68215
68736
  }
68216
- break;
68217
- }
68218
- this.steeringController?.complete();
68219
- const { exitCode, stdout: answer } = traced;
68220
- const ok = exitCode === 0;
68221
- const invocation = traced.invocation;
68222
- if (capture && answerFile !== undefined) {
68223
- const target = isAbsolute2(answerFile) ? answerFile : join14(cwd, answerFile);
68224
- const fs3 = createNodeFileSystem3(cwd);
68225
- await fs3.ensureDir(dirname12(target));
68226
- await fs3.writeFile(target, answer);
68227
- }
68228
- if (ok && expectFile !== undefined) {
68229
- const target = isAbsolute2(expectFile) ? expectFile : join14(cwd, expectFile);
68230
- const fs3 = createNodeFileSystem3(cwd);
68231
- if (!await fs3.exists(target)) {
68232
- return {
68233
- ok: false,
68234
- data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68235
- error: `agent.run (${agentLabel}) exited 0 but expected file is absent: ${expectFile}`
68236
- };
68737
+ if (!ok) {
68738
+ await writePartialWorkArtifact(context4, agentLabel, model, traced, cwd);
68237
68739
  }
68740
+ const stepLabel = context4.stateOrNodeId;
68741
+ 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}`;
68742
+ return {
68743
+ ok,
68744
+ data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68745
+ error: error51,
68746
+ setVars: ok ? {
68747
+ __agentSession: resumeRetried ? "no-resume" : "open",
68748
+ ...steeringNote !== undefined ? { __steeringNote: steeringNote } : {}
68749
+ } : undefined
68750
+ };
68751
+ } finally {
68752
+ sink?.close();
68238
68753
  }
68239
- if (!ok) {
68240
- await writePartialWorkArtifact(context4, agentLabel, model, traced, cwd);
68241
- }
68242
- const stepLabel = context4.stateOrNodeId;
68243
- 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}`;
68244
- return {
68245
- ok,
68246
- data: buildResultData(exitCode, agentLabel, capture, answer, invocation),
68247
- error: error51,
68248
- setVars: ok ? {
68249
- __agentSession: "open",
68250
- ...steeringNote !== undefined ? { __steeringNote: steeringNote } : {}
68251
- } : undefined
68252
- };
68253
68754
  }
68254
68755
  }
68255
68756
  function buildResultData(exitCode, agentLabel, capture, answer, invocation) {
@@ -68335,7 +68836,7 @@ async function writePartialWorkArtifact(context4, agentLabel, model, traced, cwd
68335
68836
  ""
68336
68837
  ].join(`
68337
68838
  `);
68338
- const target = join14(cwd, ".spur", "run", `${context4.runId}-${context4.stateOrNodeId}-partial.md`);
68839
+ const target = join15(cwd, ".spur", "run", `${context4.runId}-${context4.stateOrNodeId}-partial.md`);
68339
68840
  const fs3 = createNodeFileSystem3(cwd);
68340
68841
  await fs3.ensureDir(dirname12(target));
68341
68842
  await fs3.writeFile(target, body);
@@ -68365,6 +68866,7 @@ ${text4.slice(text4.length - maxChars)}`;
68365
68866
  var PARTIAL_ARTIFACT_TAIL_CHARS = 4000, KIND = "agent.run";
68366
68867
  var init_agent_run = __esm(() => {
68367
68868
  init_dist5();
68869
+ init_run_output_sink();
68368
68870
  init_steering();
68369
68871
  });
68370
68872
 
@@ -68893,7 +69395,7 @@ var init_rule_check = __esm(() => {
68893
69395
  // ../../packages/app/src/workflow/builtins.ts
68894
69396
  function registerSpurBuiltins(host, options) {
68895
69397
  const fileSystem = options.fileSystem ?? createNodeFileSystem3();
68896
- host.registerAction(new AgentRunActionRunner(options.agentService, options.observabilityBus, options.steeringController), "builtin");
69398
+ host.registerAction(new AgentRunActionRunner(options.agentService, options.observabilityBus, options.steeringController, options.outputLog), "builtin");
68897
69399
  host.registerAction(new RuleCheckActionRunner(options.ruleService), "builtin");
68898
69400
  host.registerAction(new FileExistsActionRunner(fileSystem), "builtin");
68899
69401
  host.registerAction(new FileReadActionRunner(fileSystem), "builtin");
@@ -69073,7 +69575,7 @@ var init_observability = __esm(() => {
69073
69575
 
69074
69576
  // ../../packages/app/src/services/workflow-service.ts
69075
69577
  import { homedir as homedir5 } from "os";
69076
- import { join as join15, resolve as resolve4 } from "path";
69578
+ import { join as join16, resolve as resolve4 } from "path";
69077
69579
  function signalSubprocess(pid) {
69078
69580
  if (!Number.isInteger(pid) || pid <= 1)
69079
69581
  return false;
@@ -69296,7 +69798,7 @@ class WorkflowAppService {
69296
69798
  }
69297
69799
  async list(workflowPaths = [".spur/workflows/"]) {
69298
69800
  const projectRoot = this.ctx.cwd;
69299
- const globalRoot = join15(homedir5(), ".config", "spur");
69801
+ const globalRoot = join16(homedir5(), ".config", "spur");
69300
69802
  const layers = [];
69301
69803
  const entries = [];
69302
69804
  const scannedPaths = new Set;
@@ -69400,7 +69902,12 @@ class WorkflowAppService {
69400
69902
  });
69401
69903
  }
69402
69904
  }
69403
- return { run, events: events2 };
69905
+ const outputArtifact = await outputArtifactForRun(this.ctx.cwd, runId);
69906
+ return {
69907
+ run,
69908
+ events: events2,
69909
+ ...outputArtifact !== undefined ? { outputArtifact } : {}
69910
+ };
69404
69911
  }
69405
69912
  async createEngineService(opts = {}) {
69406
69913
  const processExec = this.ctx.processExecutor?.();
@@ -69413,7 +69920,8 @@ class WorkflowAppService {
69413
69920
  httpRequester: this.ctx.httpRequester?.(),
69414
69921
  hostAllowlist: this.ctx.hostAllowlist?.(),
69415
69922
  ...bus !== undefined ? { observabilityBus: bus } : {},
69416
- ...opts.steeringController !== undefined ? { steeringController: opts.steeringController } : {}
69923
+ ...opts.steeringController !== undefined ? { steeringController: opts.steeringController } : {},
69924
+ outputLog: await resolveOutputLogConfig(this.ctx.cwd)
69417
69925
  });
69418
69926
  const db2 = await this.ctx.getDb();
69419
69927
  let persistence2 = new DbWorkflowPersistenceAdapter(db2);
@@ -69428,6 +69936,23 @@ async function fileExists(path9) {
69428
69936
  const fs3 = createNodeFileSystem3();
69429
69937
  return await fs3.exists(path9);
69430
69938
  }
69939
+ async function resolveOutputLogConfig(cwd) {
69940
+ try {
69941
+ const output2 = (await loadSpurConfig(cwd)).agent?.output;
69942
+ if (output2 === undefined)
69943
+ return {};
69944
+ return {
69945
+ ...output2["max-bytes"] !== undefined ? { maxBytes: output2["max-bytes"] } : {},
69946
+ ...output2["max-lines"] !== undefined ? { maxLines: output2["max-lines"] } : {}
69947
+ };
69948
+ } catch {
69949
+ return {};
69950
+ }
69951
+ }
69952
+ async function outputArtifactForRun(cwd, runId) {
69953
+ const relative4 = join16(".spur", "run", `${runId}-output.log`);
69954
+ return await fileExists(join16(cwd, relative4)) ? relative4 : undefined;
69955
+ }
69431
69956
  async function scanWorkflowFiles(rootPath, source) {
69432
69957
  const entries = [];
69433
69958
  const fs3 = createNodeFileSystem3();
@@ -69507,6 +70032,7 @@ function rowToTraceEntry(row) {
69507
70032
  }
69508
70033
  var TASK_PIPELINE_WORKFLOW = "task-pipeline", EMBEDDED_SCHEMA_PREFIX = "\x00embedded-spur", SPUR_SCHEMA_MANIFEST = "@gobing-ai/spur/package.json", PIPELINE_LINK_KIND = "pipeline";
69509
70034
  var init_workflow_service = __esm(() => {
70035
+ init_loader();
69510
70036
  init_src2();
69511
70037
  init_dist7();
69512
70038
  init_dist5();
@@ -69740,7 +70266,7 @@ function formatDuration(ms) {
69740
70266
  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);
69741
70267
 
69742
70268
  // ../../packages/app/src/workflow/trace-writer.ts
69743
- import { dirname as dirname13, join as join16 } from "path";
70269
+ import { dirname as dirname13, join as join17 } from "path";
69744
70270
 
69745
70271
  class WorkflowTraceWriter {
69746
70272
  path;
@@ -69748,7 +70274,7 @@ class WorkflowTraceWriter {
69748
70274
  pending = Promise.resolve();
69749
70275
  constructor(cwd, runId) {
69750
70276
  const safeRunId = runId.replace(/[^A-Za-z0-9._-]/g, "_");
69751
- this.path = join16(cwd, ".spur", "runs", "workflow", `${safeRunId}.jsonl`);
70277
+ this.path = join17(cwd, ".spur", "runs", "workflow", `${safeRunId}.jsonl`);
69752
70278
  }
69753
70279
  attach(bus) {
69754
70280
  bus.on("workflow.run.started", (event2) => this.enqueue("workflow.run.started", event2));
@@ -69840,6 +70366,7 @@ __export(exports_src2, {
69840
70366
  WorkflowTraceWriter: () => WorkflowTraceWriter,
69841
70367
  WorkflowSteeringController: () => WorkflowSteeringController,
69842
70368
  WorkflowAppService: () => WorkflowAppService,
70369
+ WbsCollisionError: () => WbsCollisionError,
69843
70370
  UnsupportedProcessPlatformError: () => UnsupportedProcessPlatformError,
69844
70371
  TokenLedgerWatcher: () => TokenLedgerWatcher,
69845
70372
  TokenLedgerService: () => TokenLedgerService,
@@ -70030,19 +70557,19 @@ var {
70030
70557
  init_src();
70031
70558
  init_loader();
70032
70559
 
70033
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70560
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70034
70561
  init_dist4();
70035
70562
  init_dist5();
70036
70563
  import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
70037
70564
  import { dirname as dirname5 } from "path";
70038
70565
 
70039
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70566
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70040
70567
  init_default_observers();
70041
70568
  init_event_bus();
70042
70569
  init_file_observer();
70043
70570
  init_logger3();
70044
70571
 
70045
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler/noop.js
70572
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/scheduler/noop.js
70046
70573
  class NoopSchedulerAdapter {
70047
70574
  constructor() {}
70048
70575
  register(_cron, _action) {}
@@ -70050,7 +70577,7 @@ class NoopSchedulerAdapter {
70050
70577
  async stop() {}
70051
70578
  }
70052
70579
 
70053
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/scheduler/factory.js
70580
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/scheduler/factory.js
70054
70581
  function initScheduler(adapter, cronEntries) {
70055
70582
  const resolved = adapter ?? new NoopSchedulerAdapter;
70056
70583
  if (cronEntries) {
@@ -70061,7 +70588,7 @@ function initScheduler(adapter, cronEntries) {
70061
70588
  return resolved;
70062
70589
  }
70063
70590
 
70064
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/plugins/builtins.js
70591
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application/plugins/builtins.js
70065
70592
  init_logger3();
70066
70593
  init_metrics();
70067
70594
  init_sdk();
@@ -70154,7 +70681,7 @@ function dbPlugin(db2) {
70154
70681
  };
70155
70682
  }
70156
70683
 
70157
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/plugins/host.js
70684
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application/plugins/host.js
70158
70685
  init_logger3();
70159
70686
 
70160
70687
  class PluginHost {
@@ -70242,7 +70769,7 @@ class PluginHost {
70242
70769
  }
70243
70770
  }
70244
70771
 
70245
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70772
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application/index.js
70246
70773
  async function performShutdown(state, reason) {
70247
70774
  if (state.stopped)
70248
70775
  return;
@@ -70353,10 +70880,10 @@ async function runApplication(options) {
70353
70880
  }
70354
70881
  }
70355
70882
 
70356
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70883
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application-node.js
70357
70884
  init_scheduler_node();
70358
70885
 
70359
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
70886
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
70360
70887
  var import_api14 = __toESM(require_src(), 1);
70361
70888
 
70362
70889
  // ../../node_modules/.bun/@opentelemetry+exporter-metrics-otlp-http@0.218.0+e40b0dfdd726a224/node_modules/@opentelemetry/exporter-metrics-otlp-http/build/esm/OTLPMetricExporterBase.js
@@ -73372,7 +73899,7 @@ class OTLPTraceExporter extends import_otlp_exporter_base2.OTLPExporterBase {
73372
73899
  }), JsonTraceSerializer));
73373
73900
  }
73374
73901
  }
73375
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
73902
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/telemetry/otel-node.js
73376
73903
  var import_resources2 = __toESM(require_src4(), 1);
73377
73904
  var import_sdk_trace_node = __toESM(require_src8(), 1);
73378
73905
  var import_semantic_conventions = __toESM(require_src2(), 1);
@@ -73423,7 +73950,7 @@ async function shutdownNodeTelemetry() {
73423
73950
  await Promise.all(pending);
73424
73951
  }
73425
73952
 
73426
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.15+60cc1f0410bb6d88/node_modules/@gobing-ai/ts-infra/dist/application-node.js
73953
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.4.16+4e212f5ced9864ce/node_modules/@gobing-ai/ts-infra/dist/application-node.js
73427
73954
  class ConfigValidationError extends Error {
73428
73955
  constructor(message) {
73429
73956
  super(message);
@@ -77571,7 +78098,7 @@ init_loader();
77571
78098
  init_src2();
77572
78099
  import { existsSync as existsSync9 } from "fs";
77573
78100
  import { homedir as homedir6 } from "os";
77574
- import { join as join17, resolve as resolve5 } from "path";
78101
+ import { join as join18, resolve as resolve5 } from "path";
77575
78102
 
77576
78103
  // src/workflow/resolve-spur-bin.ts
77577
78104
  import { basename as basename3 } from "path";
@@ -77589,22 +78116,22 @@ function resolveSpurBin() {
77589
78116
  }
77590
78117
 
77591
78118
  // src/workflow/make-lifecycle-adapter.ts
77592
- var GLOBAL_CONFIG_DIR = join17(".config", "spur");
78119
+ var GLOBAL_CONFIG_DIR = join18(".config", "spur");
77593
78120
  function globalConfigRoot(context4) {
77594
78121
  const override = context4.env.SPUR_GLOBAL_RULES_DIR;
77595
- return override !== undefined && override.length > 0 ? resolve5(context4.cwd, override) : join17(homedir6(), GLOBAL_CONFIG_DIR);
78122
+ return override !== undefined && override.length > 0 ? resolve5(context4.cwd, override) : join18(homedir6(), GLOBAL_CONFIG_DIR);
77596
78123
  }
77597
78124
  function resolveWorkflowPath(context4, profile) {
77598
78125
  const bundledRoot = bundledConfigRoot();
77599
78126
  if (bundledRoot !== null) {
77600
- const bundledPath = join17(bundledRoot, "workflows", `${profile.workflowName}.yaml`);
78127
+ const bundledPath = join18(bundledRoot, "workflows", `${profile.workflowName}.yaml`);
77601
78128
  if (existsSync9(bundledPath))
77602
78129
  return bundledPath;
77603
78130
  }
77604
- const projectPath = join17(context4.cwd, ".spur", "workflows", `${profile.workflowName}.yaml`);
78131
+ const projectPath = join18(context4.cwd, ".spur", "workflows", `${profile.workflowName}.yaml`);
77605
78132
  if (existsSync9(projectPath))
77606
78133
  return projectPath;
77607
- const globalPath = join17(globalConfigRoot(context4), "workflows", `${profile.workflowName}.yaml`);
78134
+ const globalPath = join18(globalConfigRoot(context4), "workflows", `${profile.workflowName}.yaml`);
77608
78135
  if (existsSync9(globalPath))
77609
78136
  return globalPath;
77610
78137
  return null;
@@ -77745,9 +78272,9 @@ function registerFeatureCommand(program2, context4) {
77745
78272
  let next = forwardPath[current];
77746
78273
  while (next !== undefined) {
77747
78274
  if (current === "active") {
77748
- await assertFeatureCheckPass(context4, id, options.folder, false);
78275
+ await assertFeatureCheckPass(context4, id, options.folder, false, "verifying");
77749
78276
  } else if (current === "verifying") {
77750
- await assertFeatureCheckPass(context4, id, options.folder, true);
78277
+ await assertFeatureCheckPass(context4, id, options.folder, true, "done");
77751
78278
  }
77752
78279
  const result = await svc.transition(id, next);
77753
78280
  history.push({ from: result.fromStatus ?? current, to: result.toStatus ?? next });
@@ -77837,7 +78364,7 @@ function registerFeatureCommand(program2, context4) {
77837
78364
  context4.setExitCode(1);
77838
78365
  }
77839
78366
  });
77840
- 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) => {
78367
+ 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) => {
77841
78368
  const resolved = await resolvePlanningFolders(context4.fs);
77842
78369
  const featuresDir = options.folder ?? context4.fs.resolve(resolved.featuresDir);
77843
78370
  const tasksDir = context4.fs.resolve(resolved.tasksDir);
@@ -77860,7 +78387,8 @@ function registerFeatureCommand(program2, context4) {
77860
78387
  featuresDir,
77861
78388
  tasksDir,
77862
78389
  runDir: context4.fs.resolve(".spur/run"),
77863
- severityOverrides: resolved.severityOverrides
78390
+ severityOverrides: resolved.severityOverrides,
78391
+ asStatus: options.as
77864
78392
  });
77865
78393
  results.push(result);
77866
78394
  if (!json3) {
@@ -77900,7 +78428,7 @@ ${result.id} (${result.status}): ${result.pass ? "PASS" : "FAIL"}`);
77900
78428
  } else {
77901
78429
  context4.output.write(`Evaluated ${result.evaluated}/${result.totalFeatures} features; updated ${result.updatedCount} feature(s).`);
77902
78430
  for (const res of result.results) {
77903
- const tag = res.applied ? "UPDATED" : res.proposal.from === res.proposal.to ? "NOOP" : "SKIPPED";
78431
+ const tag = res.applied ? "UPDATED" : res.goalConflict !== undefined ? "GOAL-CONFLICT" : res.proposal.from === res.proposal.to ? "NOOP" : "SKIPPED";
77904
78432
  context4.output.write(` [${tag}] ${res.proposal.featureId}: ${res.proposal.from} -> ${res.proposal.to} (${res.proposal.reason})`);
77905
78433
  }
77906
78434
  }
@@ -77912,7 +78440,7 @@ ${result.id} (${result.status}): ${result.pass ? "PASS" : "FAIL"}`);
77912
78440
  if (options.json) {
77913
78441
  context4.output.write(toJson2(result));
77914
78442
  } else {
77915
- const tag = result.applied ? "UPDATED" : result.proposal.from === result.proposal.to ? "NOOP" : "SKIPPED";
78443
+ const tag = result.applied ? "UPDATED" : result.goalConflict !== undefined ? "GOAL-CONFLICT" : result.proposal.from === result.proposal.to ? "NOOP" : "SKIPPED";
77916
78444
  context4.output.write(`Feature ${id}: [${tag}] ${result.proposal.from} -> ${result.proposal.to} (${result.proposal.reason})`);
77917
78445
  }
77918
78446
  }
@@ -77940,7 +78468,7 @@ async function makeService(context4, folderOverride) {
77940
78468
  foldersConfig: resolved.foldersConfig
77941
78469
  });
77942
78470
  }
77943
- async function assertFeatureCheckPass(context4, id, folderOverride, strict) {
78471
+ async function assertFeatureCheckPass(context4, id, folderOverride, strict, asStatus) {
77944
78472
  const resolved = await resolvePlanningFolders(context4.fs);
77945
78473
  const featuresDir = folderOverride ?? context4.fs.resolve(resolved.featuresDir);
77946
78474
  const tasksDir = context4.fs.resolve(resolved.tasksDir);
@@ -77952,7 +78480,8 @@ async function assertFeatureCheckPass(context4, id, folderOverride, strict) {
77952
78480
  const result = await new FeatureCheckService(context4.fs).check(`${featuresDir}/${fileName}`, id, {
77953
78481
  strict,
77954
78482
  featuresDir,
77955
- tasksDir
78483
+ tasksDir,
78484
+ asStatus
77956
78485
  });
77957
78486
  if (!result.pass) {
77958
78487
  const details = result.findings.map((f) => `${f.layer} ${f.section}: ${f.message}`).join("; ");
@@ -78006,13 +78535,13 @@ init_loader();
78006
78535
  init_src2();
78007
78536
  init_dist10();
78008
78537
  import { homedir as homedir7 } from "os";
78009
- import { join as join18, resolve as resolve6 } from "path";
78538
+ import { join as join19, resolve as resolve6 } from "path";
78010
78539
 
78011
78540
  // src/config.ts
78012
78541
  var CLI_CONFIG = {
78013
78542
  binaryName: "spur",
78014
78543
  binaryLabel: "spur",
78015
- binaryVersion: "0.3.28",
78544
+ binaryVersion: "0.3.30",
78016
78545
  configDir: ".spur",
78017
78546
  configFile: ".spur/config.yaml",
78018
78547
  databaseFile: ".spur/spur.db"
@@ -78063,8 +78592,8 @@ var SCAFFOLD_MANIFEST = [
78063
78592
  ];
78064
78593
 
78065
78594
  // src/commands/init.ts
78066
- var GLOBAL_CONFIG_DIR2 = join18(".config", "spur");
78067
- var GLOBAL_RULES_DIR2 = join18(GLOBAL_CONFIG_DIR2, "rules");
78595
+ var GLOBAL_CONFIG_DIR2 = join19(".config", "spur");
78596
+ var GLOBAL_RULES_DIR2 = join19(GLOBAL_CONFIG_DIR2, "rules");
78068
78597
  var GLOBAL_CONFIG_EXAMPLE = "config.example.yaml";
78069
78598
  var GLOBAL_CONFIG_FILE2 = "config.yaml";
78070
78599
  var INDEXED_CONTEXT_MARKER = "## Indexed context";
@@ -78095,7 +78624,7 @@ If \`.spur/context/\` is absent, proceed normally. Never block work on its absen
78095
78624
  `;
78096
78625
  function globalRulesRoot(context4) {
78097
78626
  const override = context4.env.SPUR_GLOBAL_RULES_DIR;
78098
- return override !== undefined && override.length > 0 ? resolve6(context4.cwd, override) : join18(homedir7(), GLOBAL_RULES_DIR2);
78627
+ return override !== undefined && override.length > 0 ? resolve6(context4.cwd, override) : join19(homedir7(), GLOBAL_RULES_DIR2);
78099
78628
  }
78100
78629
  async function writeIfNew(context4, path9, content, force, result) {
78101
78630
  if (!force && await context4.fs.exists(path9)) {
@@ -78112,11 +78641,11 @@ async function seedGlobalRules(context4) {
78112
78641
  const target = globalRulesRoot(context4);
78113
78642
  let written = 0;
78114
78643
  for (const relPath of await listBundledRuleFiles()) {
78115
- const destination = join18(target, relPath);
78644
+ const destination = join19(target, relPath);
78116
78645
  if (await context4.fs.exists(destination))
78117
78646
  continue;
78118
- await context4.fs.ensureDir(join18(target, ...relPath.split("/").slice(0, -1)));
78119
- await context4.fs.writeFile(destination, await context4.fs.readFile(join18(source, relPath)));
78647
+ await context4.fs.ensureDir(join19(target, ...relPath.split("/").slice(0, -1)));
78648
+ await context4.fs.writeFile(destination, await context4.fs.readFile(join19(source, relPath)));
78120
78649
  written += 1;
78121
78650
  }
78122
78651
  return written;
@@ -78126,20 +78655,20 @@ async function seedGlobalConfig(context4) {
78126
78655
  if (source === null)
78127
78656
  return 0;
78128
78657
  const globalOverride = context4.env.SPUR_GLOBAL_RULES_DIR;
78129
- const target = globalOverride !== undefined && globalOverride.length > 0 ? resolve6(context4.cwd, globalOverride) : join18(homedir7(), GLOBAL_CONFIG_DIR2);
78658
+ const target = globalOverride !== undefined && globalOverride.length > 0 ? resolve6(context4.cwd, globalOverride) : join19(homedir7(), GLOBAL_CONFIG_DIR2);
78130
78659
  let written = 0;
78131
78660
  for (const relPath of listBundledConfigFiles()) {
78132
78661
  if (relPath === GLOBAL_CONFIG_EXAMPLE)
78133
78662
  continue;
78134
- const destination = join18(target, relPath);
78663
+ const destination = join19(target, relPath);
78135
78664
  if (await context4.fs.exists(destination))
78136
78665
  continue;
78137
- await context4.fs.ensureDir(join18(target, ...relPath.split("/").slice(0, -1)));
78138
- await context4.fs.writeFile(destination, await context4.fs.readFile(join18(source, relPath)));
78666
+ await context4.fs.ensureDir(join19(target, ...relPath.split("/").slice(0, -1)));
78667
+ await context4.fs.writeFile(destination, await context4.fs.readFile(join19(source, relPath)));
78139
78668
  written += 1;
78140
78669
  }
78141
- const examplePath = join18(source, GLOBAL_CONFIG_EXAMPLE);
78142
- const globalConfigPath = join18(target, GLOBAL_CONFIG_FILE2);
78670
+ const examplePath = join19(source, GLOBAL_CONFIG_EXAMPLE);
78671
+ const globalConfigPath = join19(target, GLOBAL_CONFIG_FILE2);
78143
78672
  if (await context4.fs.exists(examplePath) && !await context4.fs.exists(globalConfigPath)) {
78144
78673
  await context4.fs.ensureDir(target);
78145
78674
  await context4.fs.writeFile(globalConfigPath, await context4.fs.readFile(examplePath));
@@ -78153,7 +78682,7 @@ function registerInitCommand(program2, context4) {
78153
78682
  const force = options.force === true;
78154
78683
  const minimal = options.minimal === true;
78155
78684
  const projectName = options.name ?? "default";
78156
- const configPath = join18(context4.cwd, CLI_CONFIG.configFile);
78685
+ const configPath = join19(context4.cwd, CLI_CONFIG.configFile);
78157
78686
  if (!force && await context4.fs.exists(configPath)) {
78158
78687
  const message = `Already initialized: ${CLI_CONFIG.configFile}. Use --force to overwrite.`;
78159
78688
  context4.output.write(json3 ? toJson2({ ok: false, reason: "already-initialized", config: CLI_CONFIG.configFile }) : message);
@@ -78188,13 +78717,13 @@ function registerInitCommand(program2, context4) {
78188
78717
  ].join(`
78189
78718
  `)}
78190
78719
  `;
78191
- await context4.fs.ensureDir(join18(context4.cwd, CLI_CONFIG.configDir));
78720
+ await context4.fs.ensureDir(join19(context4.cwd, CLI_CONFIG.configDir));
78192
78721
  await context4.fs.writeFile(configPath, configYaml);
78193
78722
  result.created.push(configPath);
78194
- const agentsDir = join18(context4.cwd, CLI_CONFIG.configDir, "agents");
78723
+ const agentsDir = join19(context4.cwd, CLI_CONFIG.configDir, "agents");
78195
78724
  await context4.fs.ensureDir(agentsDir);
78196
- await writeIfNew(context4, join18(agentsDir, ".gitkeep"), "", force, result);
78197
- const gitignorePath = join18(context4.cwd, ".gitignore");
78725
+ await writeIfNew(context4, join19(agentsDir, ".gitkeep"), "", force, result);
78726
+ const gitignorePath = join19(context4.cwd, ".gitignore");
78198
78727
  const contextEntry = ".spur/context/";
78199
78728
  if (await context4.fs.exists(gitignorePath)) {
78200
78729
  const existing = await context4.fs.readFile(gitignorePath);
@@ -78216,20 +78745,20 @@ ${contextEntry}
78216
78745
  for (const relPath of listBundledProjectSeedFiles()) {
78217
78746
  if (relPath.startsWith("templates/docs/"))
78218
78747
  continue;
78219
- const sourcePath = join18(configRoot, relPath);
78748
+ const sourcePath = join19(configRoot, relPath);
78220
78749
  if (!await context4.fs.exists(sourcePath))
78221
78750
  continue;
78222
- const targetPath = join18(context4.cwd, CLI_CONFIG.configDir, relPath);
78223
- await context4.fs.ensureDir(join18(targetPath, ".."));
78751
+ const targetPath = join19(context4.cwd, CLI_CONFIG.configDir, relPath);
78752
+ await context4.fs.ensureDir(join19(targetPath, ".."));
78224
78753
  await writeIfNew(context4, targetPath, await context4.fs.readFile(sourcePath), force, result);
78225
78754
  }
78226
78755
  for (const entry of SCAFFOLD_MANIFEST) {
78227
- const sourcePath = join18(configRoot, entry.source);
78756
+ const sourcePath = join19(configRoot, entry.source);
78228
78757
  if (!await context4.fs.exists(sourcePath))
78229
78758
  continue;
78230
- const baseDir = entry.root === true ? context4.cwd : join18(context4.cwd, CLI_CONFIG.configDir);
78231
- const targetPath = join18(baseDir, entry.target);
78232
- await context4.fs.ensureDir(join18(targetPath, ".."));
78759
+ const baseDir = entry.root === true ? context4.cwd : join19(context4.cwd, CLI_CONFIG.configDir);
78760
+ const targetPath = join19(baseDir, entry.target);
78761
+ await context4.fs.ensureDir(join19(targetPath, ".."));
78233
78762
  const entryForce = entry.preserve === true ? false : force;
78234
78763
  let body = await context4.fs.readFile(sourcePath);
78235
78764
  if (entry.target === "AGENTS.md") {
@@ -78242,7 +78771,7 @@ ${contextEntry}
78242
78771
  }
78243
78772
  }
78244
78773
  }
78245
- const agentsMdPath = join18(context4.cwd, "AGENTS.md");
78774
+ const agentsMdPath = join19(context4.cwd, "AGENTS.md");
78246
78775
  if (await context4.fs.exists(agentsMdPath)) {
78247
78776
  const existing = await context4.fs.readFile(agentsMdPath);
78248
78777
  if (!existing.includes(INDEXED_CONTEXT_MARKER)) {
@@ -78420,10 +78949,10 @@ function parseInterval2(raw) {
78420
78949
 
78421
78950
  // src/commands/migrate.ts
78422
78951
  init_src2();
78423
- import { join as join19 } from "path";
78952
+ import { join as join20 } from "path";
78424
78953
  function registerMigrateCommand(program2, context4) {
78425
78954
  program2.command("migrate").summary("apply CLI-owned schema migrations").option("--json", "Output machine-readable JSON").action(async (options) => {
78426
- const migrations = await loadSqlMigrations(join19(context4.cwd, "drizzle")).catch(() => {
78955
+ const migrations = await loadSqlMigrations(join20(context4.cwd, "drizzle")).catch(() => {
78427
78956
  return;
78428
78957
  });
78429
78958
  const applied = await applyCliMigrations(await context4.getDb(), migrations);
@@ -78839,7 +79368,7 @@ function formatTraceDetail(detail) {
78839
79368
 
78840
79369
  // src/commands/serve.ts
78841
79370
  init_src();
78842
- import { join as join23 } from "path";
79371
+ import { join as join24 } from "path";
78843
79372
 
78844
79373
  // ../server/src/index.ts
78845
79374
  init_src();
@@ -78849,11 +79378,11 @@ init_src3();
78849
79378
  init_src();
78850
79379
  init_loader();
78851
79380
  init_src2();
78852
- import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute3, join as join22 } from "path";
79381
+ import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute3, join as join23 } from "path";
78853
79382
  init_dist5();
78854
79383
 
78855
79384
  // ../server/src/bootstrap.ts
78856
- import { join as join20 } from "path";
79385
+ import { join as join21 } from "path";
78857
79386
 
78858
79387
  // ../../node_modules/.bun/radash@12.1.1/node_modules/radash/dist/esm/async.mjs
78859
79388
  var guard = (func, shouldGuard) => {
@@ -84088,6 +84617,9 @@ var contextInjector = (appRt) => async function contextInjectorMiddleware(c3, ne
84088
84617
  await next();
84089
84618
  };
84090
84619
 
84620
+ // ../server/src/middleware/error-handler.ts
84621
+ init_src3();
84622
+
84091
84623
  // ../server/src/errors.ts
84092
84624
  init_errors5();
84093
84625
 
@@ -84150,6 +84682,14 @@ function resolveError(err, requestId, isProd) {
84150
84682
  details: { requestId }
84151
84683
  };
84152
84684
  }
84685
+ if (err instanceof WbsCollisionError) {
84686
+ return {
84687
+ status: 409,
84688
+ apiCode: "WBS_COLLISION",
84689
+ message: isProd ? "WBS collision - task already exists" : message,
84690
+ details: { requestId, wbs: err.wbs, existingPath: err.existingPath, attemptedPath: err.attemptedPath }
84691
+ };
84692
+ }
84153
84693
  if (err instanceof LockTimeoutError) {
84154
84694
  return {
84155
84695
  status: 503,
@@ -87737,7 +88277,7 @@ function createApp(appRt, opts) {
87737
88277
  app.use("*", async (c3, next) => {
87738
88278
  const pathname = c3.req.path === "/" ? "/index.html" : c3.req.path;
87739
88279
  try {
87740
- const file2 = Bun.file(join20(webDistPath, pathname));
88280
+ const file2 = Bun.file(join21(webDistPath, pathname));
87741
88281
  if (await file2.exists()) {
87742
88282
  const headers = new Headers({ "content-type": file2.type });
87743
88283
  return new Response(file2.stream(), { headers });
@@ -87750,7 +88290,7 @@ function createApp(appRt, opts) {
87750
88290
  return c3.json({ error: "Not Found" }, 404);
87751
88291
  }
87752
88292
  try {
87753
- const indexFile = Bun.file(join20(webDistPath, "index.html"));
88293
+ const indexFile = Bun.file(join21(webDistPath, "index.html"));
87754
88294
  if (await indexFile.exists()) {
87755
88295
  return new Response(indexFile.stream(), {
87756
88296
  headers: { "content-type": "text/html; charset=utf-8" }
@@ -87771,7 +88311,7 @@ init_src3();
87771
88311
  init_src();
87772
88312
  init_src2();
87773
88313
  init_dist5();
87774
- import { dirname as dirname14, join as join21 } from "path";
88314
+ import { dirname as dirname14, join as join22 } from "path";
87775
88315
  var NOOP_OUTPUT = { write: (_s) => {}, error: (_s) => {} };
87776
88316
 
87777
88317
  class LazyPlanningEventEmitter {
@@ -87794,7 +88334,7 @@ class LazyPlanningEventEmitter {
87794
88334
  var DEFAULT_PLANNING_FOLDERS = {
87795
88335
  tasksDir: DEFAULT_TASKS_DIR,
87796
88336
  featuresDir: DEFAULT_FEATURES_DIR,
87797
- foldersConfig: { active_folder: DEFAULT_TASKS_DIR, folders: { [DEFAULT_TASKS_DIR]: { base_counter: 0 } } }
88337
+ foldersConfig: { active_folder: DEFAULT_TASKS_DIR, folders: { [DEFAULT_TASKS_DIR]: { baseCounter: 0 } } }
87798
88338
  };
87799
88339
 
87800
88340
  class NotConfiguredError extends Error {
@@ -87806,7 +88346,7 @@ class NotConfiguredError extends Error {
87806
88346
  function createServerContext(appRt, options) {
87807
88347
  const cwd = options.cwd;
87808
88348
  const fs3 = options.fs;
87809
- const dbUrl = options.dbUrl ?? join21(cwd, DEFAULT_DATABASE_URL);
88349
+ const dbUrl = options.dbUrl ?? join22(cwd, DEFAULT_DATABASE_URL);
87810
88350
  const eventsBus = options.eventsBus ?? appRt.events;
87811
88351
  const jobQueueEnabled = options.jobQueueEnabled ?? false;
87812
88352
  const folders = options.folders ?? DEFAULT_PLANNING_FOLDERS;
@@ -88166,15 +88706,15 @@ async function handleFeatureActionJob(ctx, env, payload) {
88166
88706
  await runFeatureActionJob(ctx, env, payload);
88167
88707
  }
88168
88708
  async function resolveWebDistPath(configuredPath) {
88169
- const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute3(configuredPath) ? configuredPath : join22(process.cwd(), configuredPath)] : [
88170
- join22(process.cwd(), "dist/web"),
88171
- join22(import.meta.dir, "web"),
88172
- join22(dirname15(process.execPath), "web"),
88173
- join22(dirname15(process.execPath), "../web"),
88174
- join22(import.meta.dir, "../../../dist/web")
88709
+ const candidates = configuredPath && configuredPath.trim() !== "" ? [isAbsolute3(configuredPath) ? configuredPath : join23(process.cwd(), configuredPath)] : [
88710
+ join23(process.cwd(), "dist/web"),
88711
+ join23(import.meta.dir, "web"),
88712
+ join23(dirname15(process.execPath), "web"),
88713
+ join23(dirname15(process.execPath), "../web"),
88714
+ join23(import.meta.dir, "../../../dist/web")
88175
88715
  ];
88176
88716
  for (const candidate of candidates) {
88177
- if (await Bun.file(join22(candidate, "index.html")).exists()) {
88717
+ if (await Bun.file(join23(candidate, "index.html")).exists()) {
88178
88718
  return candidate;
88179
88719
  }
88180
88720
  }
@@ -88333,7 +88873,7 @@ if (false) {}
88333
88873
 
88334
88874
  // src/commands/serve.ts
88335
88875
  function resolveServeDbUrl(cwd, env, configuredUrl) {
88336
- return env.DATABASE_URL === undefined ? join23(cwd, DEFAULT_DATABASE_URL) : configuredUrl;
88876
+ return env.DATABASE_URL === undefined ? join24(cwd, DEFAULT_DATABASE_URL) : configuredUrl;
88337
88877
  }
88338
88878
  function registerServeCommand(program2, context4) {
88339
88879
  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) => {
@@ -88372,7 +88912,7 @@ function registerServeCommand(program2, context4) {
88372
88912
  }
88373
88913
 
88374
88914
  // src/commands/status.ts
88375
- import { join as join24 } from "path";
88915
+ import { join as join25 } from "path";
88376
88916
 
88377
88917
  // src/errors.ts
88378
88918
  class CommandError extends Error {
@@ -88443,8 +88983,8 @@ function registerStatusCommand(program2, context4) {
88443
88983
  }
88444
88984
  async function runStatusCore(path9, options, context4) {
88445
88985
  const [packageJsonExists, spurConfigExists, git, agentSpecs] = await Promise.all([
88446
- context4.fs.exists(join24(context4.cwd, "package.json")),
88447
- context4.fs.exists(join24(context4.cwd, ".spur", "config.yaml")),
88986
+ context4.fs.exists(join25(context4.cwd, "package.json")),
88987
+ context4.fs.exists(join25(context4.cwd, ".spur", "config.yaml")),
88448
88988
  gitContext(context4.cwd),
88449
88989
  listAgentSpecIds(context4)
88450
88990
  ]);
@@ -88472,14 +89012,14 @@ async function runStatusCore(path9, options, context4) {
88472
89012
  return status.ok ? 0 : 1;
88473
89013
  }
88474
89014
  async function listAgentSpecIds(context4) {
88475
- const dir = join24(context4.cwd, ".spur", "agents");
89015
+ const dir = join25(context4.cwd, ".spur", "agents");
88476
89016
  if (!await context4.fs.exists(dir))
88477
89017
  return [];
88478
89018
  const entries = await context4.fs.readDir(dir);
88479
89019
  return entries.filter((entry) => entry.endsWith(".yaml") || entry.endsWith(".yml")).map((entry) => entry.replace(/\.ya?ml$/, "")).sort();
88480
89020
  }
88481
89021
  async function readTargetStatus(context4, targetPath) {
88482
- const resolved = join24(context4.cwd, targetPath);
89022
+ const resolved = join25(context4.cwd, targetPath);
88483
89023
  const stat = await context4.fs.stat(resolved);
88484
89024
  if (stat === null)
88485
89025
  throw new CommandError(`status failed: path does not exist at ${resolved}`);
@@ -88492,7 +89032,7 @@ init_loader();
88492
89032
  init_src2();
88493
89033
  init_dist5();
88494
89034
  import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
88495
- import { join as join25 } from "path";
89035
+ import { join as join26 } from "path";
88496
89036
  // schemas/section-matrix.schema.json
88497
89037
  var section_matrix_schema_default = {
88498
89038
  $schema: "http://json-schema.org/draft-07/schema#",
@@ -88804,7 +89344,7 @@ var spur_config_schema_default = {
88804
89344
  },
88805
89345
  tasks: {
88806
89346
  type: "object",
88807
- 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).",
89347
+ 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).",
88808
89348
  properties: {
88809
89349
  folders: {
88810
89350
  type: "object",
@@ -89083,12 +89623,17 @@ function renderMigrationReport(report, dryRun, corpusDir) {
89083
89623
  }
89084
89624
  function registerTaskCommand(program2, context4) {
89085
89625
  const task = program2.command("task").summary("manage tasks");
89086
- 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) => {
89626
+ 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) => {
89087
89627
  if (options.template !== undefined && !TASK_VARIANTS.includes(options.template)) {
89088
89628
  context4.output.error(`Unknown template variant "${options.template}". Valid: ${TASK_VARIANTS.join(", ")}`);
89089
89629
  context4.setExitCode(2);
89090
89630
  return;
89091
89631
  }
89632
+ if (options.dedupeWithin !== undefined && (!Number.isInteger(options.dedupeWithin) || options.dedupeWithin <= 0)) {
89633
+ context4.output.error("--dedupe-within must be a positive integer");
89634
+ context4.setExitCode(2);
89635
+ return;
89636
+ }
89092
89637
  const svc = await makeService2(context4, options.folder);
89093
89638
  try {
89094
89639
  const result = await svc.create({
@@ -89096,7 +89641,7 @@ function registerTaskCommand(program2, context4) {
89096
89641
  featureId: options.feature,
89097
89642
  parentWbs: options.parent,
89098
89643
  template: options.template,
89099
- dedupeWithinSec: options.allowDuplicateName ? undefined : options.dedupeWithin
89644
+ dedupeWithinSec: options.allowDuplicateName ? null : options.dedupeWithin
89100
89645
  });
89101
89646
  if (options.json) {
89102
89647
  context4.output.write(toJson2(result));
@@ -89104,8 +89649,37 @@ function registerTaskCommand(program2, context4) {
89104
89649
  context4.output.write(`Created task ${result.ref.id}: ${result.ref.filePath}`);
89105
89650
  }
89106
89651
  } catch (err) {
89107
- if (err instanceof DuplicateFollowUpError) {
89108
- context4.output.error(err.message);
89652
+ if (err instanceof WbsCollisionError) {
89653
+ if (options.json) {
89654
+ context4.output.write(toJson2({
89655
+ ok: false,
89656
+ error: {
89657
+ code: "wbs-collision",
89658
+ message: err.message,
89659
+ wbs: err.wbs,
89660
+ existingPath: err.existingPath,
89661
+ attemptedPath: err.attemptedPath
89662
+ }
89663
+ }));
89664
+ } else {
89665
+ context4.output.error(err.message);
89666
+ }
89667
+ context4.setExitCode(3);
89668
+ } else if (err instanceof DuplicateFollowUpError) {
89669
+ if (options.json) {
89670
+ context4.output.write(toJson2({
89671
+ ok: false,
89672
+ error: {
89673
+ code: "duplicate-follow-up",
89674
+ message: err.message,
89675
+ existingWbs: err.existingWbs,
89676
+ existingName: err.existingName,
89677
+ attemptedName: err.attemptedName
89678
+ }
89679
+ }));
89680
+ } else {
89681
+ context4.output.error(err.message);
89682
+ }
89109
89683
  context4.setExitCode(3);
89110
89684
  } else {
89111
89685
  context4.output.error(String(err));
@@ -89176,7 +89750,7 @@ ${result.content}`);
89176
89750
  let forcedDoneVerdict;
89177
89751
  if (status === "done") {
89178
89752
  const current = await svc.show(wbs);
89179
- const verdictDir = options.verdictDir ?? join25(context4.cwd, ".spur", "run");
89753
+ const verdictDir = options.verdictDir ?? join26(context4.cwd, ".spur", "run");
89180
89754
  const loaded = await readVerdictArtifact(context4.fs, verdictDir, wbs);
89181
89755
  const guardOutcome = evaluateDoneTransition({
89182
89756
  wbs,
@@ -89435,8 +90009,26 @@ ${result.content}`);
89435
90009
  }
89436
90010
  }
89437
90011
  } catch (err) {
89438
- context4.output.error(String(err));
89439
- context4.setExitCode(1);
90012
+ if (err instanceof WbsCollisionError) {
90013
+ if (options.json) {
90014
+ context4.output.write(toJson2({
90015
+ ok: false,
90016
+ error: {
90017
+ code: "wbs-collision",
90018
+ message: err.message,
90019
+ wbs: err.wbs,
90020
+ existingPath: err.existingPath,
90021
+ attemptedPath: err.attemptedPath
90022
+ }
90023
+ }));
90024
+ } else {
90025
+ context4.output.error(err.message);
90026
+ }
90027
+ context4.setExitCode(3);
90028
+ } else {
90029
+ context4.output.error(String(err));
90030
+ context4.setExitCode(1);
90031
+ }
89440
90032
  }
89441
90033
  });
89442
90034
  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) => {
@@ -89574,6 +90166,23 @@ ${result.wbs} (${result.status}): ${result.pass ? "PASS" : "FAIL"}`);
89574
90166
  }
89575
90167
  }
89576
90168
  }
90169
+ if (!wbs) {
90170
+ const locator = await makeTaskLocator(context4);
90171
+ const duplicates2 = await locator.findDuplicateWbs();
90172
+ for (const dup of duplicates2) {
90173
+ const [first] = dup;
90174
+ if (first === undefined)
90175
+ continue;
90176
+ const msg = `Duplicate WBS ${first.wbs} found in ${dup.length} files:
90177
+ ` + dup.map((h2) => ` ${h2.filePath}`).join(`
90178
+ `);
90179
+ if (json3) {
90180
+ results.push({ wbs: first.wbs, pass: false, status: "duplicate", findings: [msg] });
90181
+ } else {
90182
+ context4.output.error(msg);
90183
+ }
90184
+ }
90185
+ }
89577
90186
  if (json3) {
89578
90187
  context4.output.write(toJson2(results));
89579
90188
  }
@@ -89716,7 +90325,7 @@ function loadTemplateContent(projectRoot, variant) {
89716
90325
  return templateContentCache.get(variant);
89717
90326
  if (templateMissSet.has(variant))
89718
90327
  return;
89719
- const localPath = join25(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
90328
+ const localPath = join26(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
89720
90329
  if (existsSync10(localPath)) {
89721
90330
  const content = readFileSync9(localPath, "utf8");
89722
90331
  templateContentCache.set(variant, content);
@@ -89724,7 +90333,7 @@ function loadTemplateContent(projectRoot, variant) {
89724
90333
  }
89725
90334
  const root = bundledConfigRoot();
89726
90335
  if (root !== null) {
89727
- const templatePath = join25(root, "templates", "task", `${variant}.md`);
90336
+ const templatePath = join26(root, "templates", "task", `${variant}.md`);
89728
90337
  if (existsSync10(templatePath)) {
89729
90338
  const content = readFileSync9(templatePath, "utf8");
89730
90339
  templateContentCache.set(variant, content);
@@ -89740,13 +90349,13 @@ function loadTemplateBodies(projectRoot, variant) {
89740
90349
  if (cached2 !== undefined)
89741
90350
  return cached2;
89742
90351
  let bodies = {};
89743
- const localPath = join25(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
90352
+ const localPath = join26(projectRoot, ".spur", "tasks", "templates", `${variant}.md`);
89744
90353
  if (existsSync10(localPath)) {
89745
90354
  bodies = extractTemplateBodies(readFileSync9(localPath, "utf8"));
89746
90355
  } else {
89747
90356
  const root = bundledConfigRoot();
89748
90357
  if (root !== null) {
89749
- const templatePath = join25(root, "templates", "task", `${variant}.md`);
90358
+ const templatePath = join26(root, "templates", "task", `${variant}.md`);
89750
90359
  if (existsSync10(templatePath)) {
89751
90360
  bodies = extractTemplateBodies(readFileSync9(templatePath, "utf8"));
89752
90361
  }
@@ -89799,7 +90408,7 @@ async function loadSectionMatrixUncached(projectRoot) {
89799
90408
  }
89800
90409
  const root = bundledConfigRoot();
89801
90410
  if (root !== null) {
89802
- const matrixPath = join25(root, "tasks", "section-matrix.yaml");
90411
+ const matrixPath = join26(root, "tasks", "section-matrix.yaml");
89803
90412
  if (await fs3.exists(matrixPath)) {
89804
90413
  const data = await loadStructuredSpurConfig(matrixPath, {
89805
90414
  validateJsonSchema: true,
@@ -90518,6 +91127,10 @@ function formatTraceTimeline(result) {
90518
91127
  `Started: ${run.startedAt} Completed: ${run.completedAt ?? "-"} Events: ${events2.length}`,
90519
91128
  ""
90520
91129
  ];
91130
+ if (result.outputArtifact !== undefined) {
91131
+ lines.push(`Agent output: ${result.outputArtifact} (tail -f for live view)`);
91132
+ lines.push("");
91133
+ }
90521
91134
  for (const event2 of events2) {
90522
91135
  lines.push(formatTimelineEvent(event2));
90523
91136
  }
@@ -90598,7 +91211,7 @@ init_src3();
90598
91211
  init_src();
90599
91212
  init_src2();
90600
91213
  init_dist5();
90601
- import { dirname as dirname16, join as join26, resolve as resolve9 } from "path";
91214
+ import { dirname as dirname16, join as join27, resolve as resolve9 } from "path";
90602
91215
  import { isatty as isatty4 } from "tty";
90603
91216
 
90604
91217
  // ../../node_modules/.bun/@clack+core@1.4.1/node_modules/@clack/core/dist/index.mjs
@@ -92020,7 +92633,7 @@ function createCliContext(options) {
92020
92633
  function noopSetExitCode(_code) {}
92021
92634
  async function createMigratedDbAdapter(cwd = process.cwd(), env = process.env, dbUrl) {
92022
92635
  const config4 = buildConfigFromEnv(env);
92023
- const configuredUrl = env.DATABASE_URL === undefined ? join26(cwd, DEFAULT_DATABASE_URL) : config4.database.url;
92636
+ const configuredUrl = env.DATABASE_URL === undefined ? join27(cwd, DEFAULT_DATABASE_URL) : config4.database.url;
92024
92637
  const url2 = dbUrl ?? configuredUrl;
92025
92638
  if (url2 !== IN_MEMORY_DATABASE_URL) {
92026
92639
  await createNodeFileSystem3().ensureDir(dirname16(url2));