substrate-ai 0.2.16 → 0.2.17

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.
@@ -1,12 +1,13 @@
1
- import { createLogger } from "./logger-C6n1g8uP.js";
2
- import { AdapterRegistry, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning } from "./event-bus-J-bw-pkp.js";
3
- import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByPhase, getDecisionsByPhaseForRun, getPipelineRunById, getTokenUsageSummary, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./decisions-SyswIRKz.js";
1
+ import { createLogger } from "./logger-D2fS2ccL.js";
2
+ import { AdapterRegistry, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning } from "./event-bus-BMxhfxfT.js";
3
+ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./decisions-Dq4cAA2L.js";
4
4
  import { STORY_METRICS, aggregateTokenUsageForRun, aggregateTokenUsageForStory, getStoryMetricsForRun, writeRunMetrics, writeStoryMetrics } from "./operational-CobuCGbM.js";
5
+ import { createRequire } from "module";
5
6
  import { dirname, join } from "path";
6
7
  import { access, readFile, readdir, stat } from "fs/promises";
7
8
  import { existsSync, mkdirSync, readFileSync } from "fs";
8
9
  import yaml from "js-yaml";
9
- import { createRequire } from "node:module";
10
+ import { createRequire as createRequire$1 } from "node:module";
10
11
  import { z } from "zod";
11
12
  import { execSync, spawn } from "node:child_process";
12
13
  import { dirname as dirname$1, join as join$1, resolve as resolve$1 } from "node:path";
@@ -17,6 +18,10 @@ import { freemem, platform } from "node:os";
17
18
  import { randomUUID } from "node:crypto";
18
19
  import { readFile as readFile$1, stat as stat$1 } from "node:fs/promises";
19
20
 
21
+ //#region rolldown:runtime
22
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
23
+
24
+ //#endregion
20
25
  //#region src/utils/git-root.ts
21
26
  /**
22
27
  * Resolve the main git repository root, even from a linked worktree.
@@ -534,7 +539,7 @@ const migration010RunMetrics = {
534
539
 
535
540
  //#endregion
536
541
  //#region src/persistence/migrations/index.ts
537
- const logger$15 = createLogger("persistence:migrations");
542
+ const logger$16 = createLogger("persistence:migrations");
538
543
  const MIGRATIONS = [
539
544
  initialSchemaMigration,
540
545
  costTrackerSchemaMigration,
@@ -552,7 +557,7 @@ const MIGRATIONS = [
552
557
  * Safe to call multiple times — already-applied migrations are skipped.
553
558
  */
554
559
  function runMigrations(db) {
555
- logger$15.info("Starting migration runner");
560
+ logger$16.info("Starting migration runner");
556
561
  db.exec(`
557
562
  CREATE TABLE IF NOT EXISTS schema_migrations (
558
563
  version INTEGER PRIMARY KEY,
@@ -563,12 +568,12 @@ function runMigrations(db) {
563
568
  const appliedVersions = new Set(db.prepare("SELECT version FROM schema_migrations").all().map((row) => row.version));
564
569
  const pending = MIGRATIONS.filter((m) => !appliedVersions.has(m.version)).sort((a, b) => a.version - b.version);
565
570
  if (pending.length === 0) {
566
- logger$15.info("No pending migrations");
571
+ logger$16.info("No pending migrations");
567
572
  return;
568
573
  }
569
574
  const insertMigration = db.prepare("INSERT INTO schema_migrations (version, name) VALUES (?, ?)");
570
575
  for (const migration of pending) {
571
- logger$15.info({
576
+ logger$16.info({
572
577
  version: migration.version,
573
578
  name: migration.name
574
579
  }, "Applying migration");
@@ -582,14 +587,14 @@ function runMigrations(db) {
582
587
  });
583
588
  applyMigration();
584
589
  }
585
- logger$15.info({ version: migration.version }, "Migration applied successfully");
590
+ logger$16.info({ version: migration.version }, "Migration applied successfully");
586
591
  }
587
- logger$15.info({ count: pending.length }, "All pending migrations applied");
592
+ logger$16.info({ count: pending.length }, "All pending migrations applied");
588
593
  }
589
594
 
590
595
  //#endregion
591
596
  //#region src/persistence/database.ts
592
- const logger$14 = createLogger("persistence:database");
597
+ const logger$15 = createLogger("persistence:database");
593
598
  /**
594
599
  * Thin wrapper that opens a SQLite database, applies required PRAGMAs,
595
600
  * and exposes the raw BetterSqlite3 instance.
@@ -606,14 +611,14 @@ var DatabaseWrapper = class {
606
611
  */
607
612
  open() {
608
613
  if (this._db !== null) return;
609
- logger$14.info({ path: this._path }, "Opening SQLite database");
614
+ logger$15.info({ path: this._path }, "Opening SQLite database");
610
615
  this._db = new BetterSqlite3(this._path);
611
616
  const walResult = this._db.pragma("journal_mode = WAL");
612
- if (walResult?.[0]?.journal_mode !== "wal") logger$14.warn({ result: walResult?.[0]?.journal_mode }, "WAL pragma did not return expected \"wal\" — journal_mode may be \"memory\" or unsupported");
617
+ if (walResult?.[0]?.journal_mode !== "wal") logger$15.warn({ result: walResult?.[0]?.journal_mode }, "WAL pragma did not return expected \"wal\" — journal_mode may be \"memory\" or unsupported");
613
618
  this._db.pragma("busy_timeout = 5000");
614
619
  this._db.pragma("synchronous = NORMAL");
615
620
  this._db.pragma("foreign_keys = ON");
616
- logger$14.info({ path: this._path }, "SQLite database opened with WAL mode");
621
+ logger$15.info({ path: this._path }, "SQLite database opened with WAL mode");
617
622
  }
618
623
  /**
619
624
  * Close the database. Idempotent — calling close() when already closed is a no-op.
@@ -622,7 +627,7 @@ var DatabaseWrapper = class {
622
627
  if (this._db === null) return;
623
628
  this._db.close();
624
629
  this._db = null;
625
- logger$14.info({ path: this._path }, "SQLite database closed");
630
+ logger$15.info({ path: this._path }, "SQLite database closed");
626
631
  }
627
632
  /**
628
633
  * Return the raw BetterSqlite3 instance.
@@ -1064,8 +1069,8 @@ const PACKAGE_ROOT = join(__dirname, "..", "..", "..");
1064
1069
  */
1065
1070
  function resolveBmadMethodSrcPath(fromDir = __dirname) {
1066
1071
  try {
1067
- const require = createRequire(join(fromDir, "synthetic.js"));
1068
- const pkgJsonPath = require.resolve("bmad-method/package.json");
1072
+ const require$1 = createRequire$1(join(fromDir, "synthetic.js"));
1073
+ const pkgJsonPath = require$1.resolve("bmad-method/package.json");
1069
1074
  return join(dirname(pkgJsonPath), "src");
1070
1075
  } catch {
1071
1076
  return null;
@@ -1077,9 +1082,9 @@ function resolveBmadMethodSrcPath(fromDir = __dirname) {
1077
1082
  */
1078
1083
  function resolveBmadMethodVersion(fromDir = __dirname) {
1079
1084
  try {
1080
- const require = createRequire(join(fromDir, "synthetic.js"));
1081
- const pkgJsonPath = require.resolve("bmad-method/package.json");
1082
- const pkg = require(pkgJsonPath);
1085
+ const require$1 = createRequire$1(join(fromDir, "synthetic.js"));
1086
+ const pkgJsonPath = require$1.resolve("bmad-method/package.json");
1087
+ const pkg = require$1(pkgJsonPath);
1083
1088
  return pkg.version ?? "unknown";
1084
1089
  } catch {
1085
1090
  return "unknown";
@@ -2491,7 +2496,7 @@ function truncateToTokens(text, maxTokens) {
2491
2496
 
2492
2497
  //#endregion
2493
2498
  //#region src/modules/context-compiler/context-compiler-impl.ts
2494
- const logger$13 = createLogger("context-compiler");
2499
+ const logger$14 = createLogger("context-compiler");
2495
2500
  /**
2496
2501
  * Fraction of the original token budget that must remain (after required +
2497
2502
  * important sections) before an optional section is included.
@@ -2583,7 +2588,7 @@ var ContextCompilerImpl = class {
2583
2588
  includedParts.push(truncated);
2584
2589
  remainingBudget -= truncatedTokens;
2585
2590
  anyTruncated = true;
2586
- logger$13.warn({
2591
+ logger$14.warn({
2587
2592
  section: section.name,
2588
2593
  originalTokens: tokens,
2589
2594
  budgetTokens: truncatedTokens
@@ -2597,7 +2602,7 @@ var ContextCompilerImpl = class {
2597
2602
  });
2598
2603
  } else {
2599
2604
  anyTruncated = true;
2600
- logger$13.warn({
2605
+ logger$14.warn({
2601
2606
  section: section.name,
2602
2607
  tokens
2603
2608
  }, "Context compiler: omitted \"important\" section — no budget remaining");
@@ -2624,7 +2629,7 @@ var ContextCompilerImpl = class {
2624
2629
  } else {
2625
2630
  if (tokens > 0) {
2626
2631
  anyTruncated = true;
2627
- logger$13.warn({
2632
+ logger$14.warn({
2628
2633
  section: section.name,
2629
2634
  tokens,
2630
2635
  budgetFractionRemaining: budgetFractionRemaining.toFixed(2)
@@ -2892,7 +2897,7 @@ function parseYamlResult(yamlText, schema) {
2892
2897
 
2893
2898
  //#endregion
2894
2899
  //#region src/modules/agent-dispatch/dispatcher-impl.ts
2895
- const logger$12 = createLogger("agent-dispatch");
2900
+ const logger$13 = createLogger("agent-dispatch");
2896
2901
  const SHUTDOWN_GRACE_MS = 1e4;
2897
2902
  const SHUTDOWN_MAX_WAIT_MS = 3e4;
2898
2903
  const CHARS_PER_TOKEN = 4;
@@ -2929,7 +2934,7 @@ function getAvailableMemory() {
2929
2934
  encoding: "utf-8"
2930
2935
  }).trim(), 10);
2931
2936
  if (pressureLevel >= 2) {
2932
- logger$12.warn({ pressureLevel }, "macOS kernel reports memory pressure");
2937
+ logger$13.warn({ pressureLevel }, "macOS kernel reports memory pressure");
2933
2938
  return 0;
2934
2939
  }
2935
2940
  } catch {}
@@ -3015,7 +3020,7 @@ var DispatcherImpl = class {
3015
3020
  resolve: typedResolve,
3016
3021
  reject
3017
3022
  });
3018
- logger$12.debug({
3023
+ logger$13.debug({
3019
3024
  id,
3020
3025
  queueLength: this._queue.length
3021
3026
  }, "Dispatch queued");
@@ -3046,7 +3051,7 @@ var DispatcherImpl = class {
3046
3051
  async shutdown() {
3047
3052
  this._shuttingDown = true;
3048
3053
  this._stopMemoryPressureTimer();
3049
- logger$12.info({
3054
+ logger$13.info({
3050
3055
  running: this._running.size,
3051
3056
  queued: this._queue.length
3052
3057
  }, "Dispatcher shutting down");
@@ -3079,13 +3084,13 @@ var DispatcherImpl = class {
3079
3084
  }
3080
3085
  }, 50);
3081
3086
  });
3082
- logger$12.info("Dispatcher shutdown complete");
3087
+ logger$13.info("Dispatcher shutdown complete");
3083
3088
  }
3084
3089
  async _startDispatch(id, request, resolve$2) {
3085
3090
  const { prompt, agent, taskType, timeout, outputSchema, workingDirectory, model, maxTurns } = request;
3086
3091
  const adapter = this._adapterRegistry.get(agent);
3087
3092
  if (adapter === void 0) {
3088
- logger$12.warn({
3093
+ logger$13.warn({
3089
3094
  id,
3090
3095
  agent
3091
3096
  }, "No adapter found for agent");
@@ -3131,7 +3136,7 @@ var DispatcherImpl = class {
3131
3136
  });
3132
3137
  const startedAt = Date.now();
3133
3138
  proc.on("error", (err) => {
3134
- logger$12.error({
3139
+ logger$13.error({
3135
3140
  id,
3136
3141
  binary: cmd.binary,
3137
3142
  error: err.message
@@ -3139,7 +3144,7 @@ var DispatcherImpl = class {
3139
3144
  });
3140
3145
  if (proc.stdin !== null) {
3141
3146
  proc.stdin.on("error", (err) => {
3142
- if (err.code !== "EPIPE") logger$12.warn({
3147
+ if (err.code !== "EPIPE") logger$13.warn({
3143
3148
  id,
3144
3149
  error: err.message
3145
3150
  }, "stdin write error");
@@ -3181,7 +3186,7 @@ var DispatcherImpl = class {
3181
3186
  agent,
3182
3187
  taskType
3183
3188
  });
3184
- logger$12.debug({
3189
+ logger$13.debug({
3185
3190
  id,
3186
3191
  agent,
3187
3192
  taskType,
@@ -3198,7 +3203,7 @@ var DispatcherImpl = class {
3198
3203
  dispatchId: id,
3199
3204
  timeoutMs
3200
3205
  });
3201
- logger$12.warn({
3206
+ logger$13.warn({
3202
3207
  id,
3203
3208
  agent,
3204
3209
  taskType,
@@ -3252,7 +3257,7 @@ var DispatcherImpl = class {
3252
3257
  exitCode: code,
3253
3258
  output: stdout
3254
3259
  });
3255
- logger$12.debug({
3260
+ logger$13.debug({
3256
3261
  id,
3257
3262
  agent,
3258
3263
  taskType,
@@ -3278,7 +3283,7 @@ var DispatcherImpl = class {
3278
3283
  error: stderr || `Process exited with code ${String(code)}`,
3279
3284
  exitCode: code
3280
3285
  });
3281
- logger$12.debug({
3286
+ logger$13.debug({
3282
3287
  id,
3283
3288
  agent,
3284
3289
  taskType,
@@ -3337,7 +3342,7 @@ var DispatcherImpl = class {
3337
3342
  const next = this._queue.shift();
3338
3343
  if (next === void 0) return;
3339
3344
  next.handle.status = "running";
3340
- logger$12.debug({
3345
+ logger$13.debug({
3341
3346
  id: next.id,
3342
3347
  queueLength: this._queue.length
3343
3348
  }, "Dequeued dispatch");
@@ -3350,7 +3355,7 @@ var DispatcherImpl = class {
3350
3355
  _isMemoryPressured() {
3351
3356
  const free = getAvailableMemory();
3352
3357
  if (free < MIN_FREE_MEMORY_BYTES) {
3353
- logger$12.warn({
3358
+ logger$13.warn({
3354
3359
  freeMB: Math.round(free / 1024 / 1024),
3355
3360
  thresholdMB: Math.round(MIN_FREE_MEMORY_BYTES / 1024 / 1024)
3356
3361
  }, "Memory pressure detected — holding dispatch queue");
@@ -3390,7 +3395,7 @@ function createDispatcher(options) {
3390
3395
 
3391
3396
  //#endregion
3392
3397
  //#region src/modules/compiled-workflows/prompt-assembler.ts
3393
- const logger$11 = createLogger("compiled-workflows:prompt-assembler");
3398
+ const logger$12 = createLogger("compiled-workflows:prompt-assembler");
3394
3399
  /**
3395
3400
  * Assemble a final prompt from a template and sections map.
3396
3401
  *
@@ -3415,7 +3420,7 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
3415
3420
  tokenCount,
3416
3421
  truncated: false
3417
3422
  };
3418
- logger$11.warn({
3423
+ logger$12.warn({
3419
3424
  tokenCount,
3420
3425
  ceiling: tokenCeiling
3421
3426
  }, "Prompt exceeds token ceiling — truncating optional sections");
@@ -3431,10 +3436,10 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
3431
3436
  const targetSectionTokens = Math.max(0, currentSectionTokens - overBy);
3432
3437
  if (targetSectionTokens === 0) {
3433
3438
  contentMap[section.name] = "";
3434
- logger$11.warn({ sectionName: section.name }, "Section eliminated to fit token budget");
3439
+ logger$12.warn({ sectionName: section.name }, "Section eliminated to fit token budget");
3435
3440
  } else {
3436
3441
  contentMap[section.name] = truncateToTokens(section.content, targetSectionTokens);
3437
- logger$11.warn({
3442
+ logger$12.warn({
3438
3443
  sectionName: section.name,
3439
3444
  targetSectionTokens
3440
3445
  }, "Section truncated to fit token budget");
@@ -3445,7 +3450,7 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
3445
3450
  }
3446
3451
  if (tokenCount <= tokenCeiling) break;
3447
3452
  }
3448
- if (tokenCount > tokenCeiling) logger$11.warn({
3453
+ if (tokenCount > tokenCeiling) logger$12.warn({
3449
3454
  tokenCount,
3450
3455
  ceiling: tokenCeiling
3451
3456
  }, "Required sections alone exceed token ceiling — returning over-budget prompt");
@@ -3586,7 +3591,7 @@ const CodeReviewResultSchema = z.object({
3586
3591
 
3587
3592
  //#endregion
3588
3593
  //#region src/modules/compiled-workflows/create-story.ts
3589
- const logger$10 = createLogger("compiled-workflows:create-story");
3594
+ const logger$11 = createLogger("compiled-workflows:create-story");
3590
3595
  /**
3591
3596
  * Hard ceiling for the assembled create-story prompt.
3592
3597
  */
@@ -3610,7 +3615,7 @@ const TOKEN_CEILING$2 = 3e3;
3610
3615
  */
3611
3616
  async function runCreateStory(deps, params) {
3612
3617
  const { epicId, storyKey, pipelineRunId } = params;
3613
- logger$10.debug({
3618
+ logger$11.debug({
3614
3619
  epicId,
3615
3620
  storyKey,
3616
3621
  pipelineRunId
@@ -3620,7 +3625,7 @@ async function runCreateStory(deps, params) {
3620
3625
  template = await deps.pack.getPrompt("create-story");
3621
3626
  } catch (err) {
3622
3627
  const error = err instanceof Error ? err.message : String(err);
3623
- logger$10.error({ error }, "Failed to retrieve create-story prompt template");
3628
+ logger$11.error({ error }, "Failed to retrieve create-story prompt template");
3624
3629
  return {
3625
3630
  result: "failed",
3626
3631
  error: `Failed to retrieve prompt template: ${error}`,
@@ -3662,7 +3667,7 @@ async function runCreateStory(deps, params) {
3662
3667
  priority: "important"
3663
3668
  }
3664
3669
  ], TOKEN_CEILING$2);
3665
- logger$10.debug({
3670
+ logger$11.debug({
3666
3671
  tokenCount,
3667
3672
  truncated,
3668
3673
  tokenCeiling: TOKEN_CEILING$2
@@ -3679,7 +3684,7 @@ async function runCreateStory(deps, params) {
3679
3684
  dispatchResult = await handle.result;
3680
3685
  } catch (err) {
3681
3686
  const error = err instanceof Error ? err.message : String(err);
3682
- logger$10.error({
3687
+ logger$11.error({
3683
3688
  epicId,
3684
3689
  storyKey,
3685
3690
  error
@@ -3700,7 +3705,7 @@ async function runCreateStory(deps, params) {
3700
3705
  if (dispatchResult.status === "failed") {
3701
3706
  const errorMsg = dispatchResult.parseError ?? `Dispatch failed with exit code ${dispatchResult.exitCode}`;
3702
3707
  const stderrDetail = dispatchResult.output ? ` Output: ${dispatchResult.output}` : "";
3703
- logger$10.warn({
3708
+ logger$11.warn({
3704
3709
  epicId,
3705
3710
  storyKey,
3706
3711
  exitCode: dispatchResult.exitCode
@@ -3712,7 +3717,7 @@ async function runCreateStory(deps, params) {
3712
3717
  };
3713
3718
  }
3714
3719
  if (dispatchResult.status === "timeout") {
3715
- logger$10.warn({
3720
+ logger$11.warn({
3716
3721
  epicId,
3717
3722
  storyKey
3718
3723
  }, "Create-story dispatch timed out");
@@ -3725,7 +3730,7 @@ async function runCreateStory(deps, params) {
3725
3730
  if (dispatchResult.parsed === null) {
3726
3731
  const details = dispatchResult.parseError ?? "No YAML block found in output";
3727
3732
  const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
3728
- logger$10.warn({
3733
+ logger$11.warn({
3729
3734
  epicId,
3730
3735
  storyKey,
3731
3736
  details,
@@ -3741,7 +3746,7 @@ async function runCreateStory(deps, params) {
3741
3746
  const parseResult = CreateStoryResultSchema.safeParse(dispatchResult.parsed);
3742
3747
  if (!parseResult.success) {
3743
3748
  const details = parseResult.error.message;
3744
- logger$10.warn({
3749
+ logger$11.warn({
3745
3750
  epicId,
3746
3751
  storyKey,
3747
3752
  details
@@ -3754,7 +3759,7 @@ async function runCreateStory(deps, params) {
3754
3759
  };
3755
3760
  }
3756
3761
  const parsed = parseResult.data;
3757
- logger$10.info({
3762
+ logger$11.info({
3758
3763
  epicId,
3759
3764
  storyKey,
3760
3765
  storyFile: parsed.story_file,
@@ -3776,7 +3781,7 @@ function getImplementationDecisions(deps) {
3776
3781
  try {
3777
3782
  return getDecisionsByPhase(deps.db, "implementation");
3778
3783
  } catch (err) {
3779
- logger$10.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve implementation decisions");
3784
+ logger$11.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve implementation decisions");
3780
3785
  return [];
3781
3786
  }
3782
3787
  }
@@ -3792,13 +3797,13 @@ function getEpicShard(decisions, epicId, projectRoot) {
3792
3797
  if (projectRoot) {
3793
3798
  const fallback = readEpicShardFromFile(projectRoot, epicId);
3794
3799
  if (fallback) {
3795
- logger$10.info({ epicId }, "Using file-based fallback for epic shard (decisions table empty)");
3800
+ logger$11.info({ epicId }, "Using file-based fallback for epic shard (decisions table empty)");
3796
3801
  return fallback;
3797
3802
  }
3798
3803
  }
3799
3804
  return "";
3800
3805
  } catch (err) {
3801
- logger$10.warn({
3806
+ logger$11.warn({
3802
3807
  epicId,
3803
3808
  error: err instanceof Error ? err.message : String(err)
3804
3809
  }, "Failed to retrieve epic shard");
@@ -3815,7 +3820,7 @@ function getPrevDevNotes(decisions, epicId) {
3815
3820
  if (devNotes.length === 0) return "";
3816
3821
  return devNotes[devNotes.length - 1].value;
3817
3822
  } catch (err) {
3818
- logger$10.warn({
3823
+ logger$11.warn({
3819
3824
  epicId,
3820
3825
  error: err instanceof Error ? err.message : String(err)
3821
3826
  }, "Failed to retrieve prev dev notes");
@@ -3835,13 +3840,13 @@ function getArchConstraints$1(deps) {
3835
3840
  if (deps.projectRoot) {
3836
3841
  const fallback = readArchConstraintsFromFile(deps.projectRoot);
3837
3842
  if (fallback) {
3838
- logger$10.info("Using file-based fallback for architecture constraints (decisions table empty)");
3843
+ logger$11.info("Using file-based fallback for architecture constraints (decisions table empty)");
3839
3844
  return fallback;
3840
3845
  }
3841
3846
  }
3842
3847
  return "";
3843
3848
  } catch (err) {
3844
- logger$10.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
3849
+ logger$11.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
3845
3850
  return "";
3846
3851
  }
3847
3852
  }
@@ -3861,7 +3866,7 @@ function readEpicShardFromFile(projectRoot, epicId) {
3861
3866
  const match = pattern.exec(content);
3862
3867
  return match ? match[0].trim() : "";
3863
3868
  } catch (err) {
3864
- logger$10.warn({
3869
+ logger$11.warn({
3865
3870
  epicId,
3866
3871
  error: err instanceof Error ? err.message : String(err)
3867
3872
  }, "File-based epic shard fallback failed");
@@ -3884,7 +3889,7 @@ function readArchConstraintsFromFile(projectRoot) {
3884
3889
  const content = readFileSync$1(archPath, "utf-8");
3885
3890
  return content.slice(0, 1500);
3886
3891
  } catch (err) {
3887
- logger$10.warn({ error: err instanceof Error ? err.message : String(err) }, "File-based architecture fallback failed");
3892
+ logger$11.warn({ error: err instanceof Error ? err.message : String(err) }, "File-based architecture fallback failed");
3888
3893
  return "";
3889
3894
  }
3890
3895
  }
@@ -3897,14 +3902,14 @@ async function getStoryTemplate(deps) {
3897
3902
  try {
3898
3903
  return await deps.pack.getTemplate("story");
3899
3904
  } catch (err) {
3900
- logger$10.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve story template from pack");
3905
+ logger$11.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve story template from pack");
3901
3906
  return "";
3902
3907
  }
3903
3908
  }
3904
3909
 
3905
3910
  //#endregion
3906
3911
  //#region src/modules/compiled-workflows/git-helpers.ts
3907
- const logger$9 = createLogger("compiled-workflows:git-helpers");
3912
+ const logger$10 = createLogger("compiled-workflows:git-helpers");
3908
3913
  /**
3909
3914
  * Capture the full git diff for HEAD (working tree vs current commit).
3910
3915
  *
@@ -4028,7 +4033,7 @@ async function runGitCommand(args, cwd, logLabel) {
4028
4033
  stderr += chunk.toString("utf-8");
4029
4034
  });
4030
4035
  proc.on("error", (err) => {
4031
- logger$9.warn({
4036
+ logger$10.warn({
4032
4037
  label: logLabel,
4033
4038
  cwd,
4034
4039
  error: err.message
@@ -4037,7 +4042,7 @@ async function runGitCommand(args, cwd, logLabel) {
4037
4042
  });
4038
4043
  proc.on("close", (code) => {
4039
4044
  if (code !== 0) {
4040
- logger$9.warn({
4045
+ logger$10.warn({
4041
4046
  label: logLabel,
4042
4047
  cwd,
4043
4048
  code,
@@ -4053,7 +4058,7 @@ async function runGitCommand(args, cwd, logLabel) {
4053
4058
 
4054
4059
  //#endregion
4055
4060
  //#region src/modules/compiled-workflows/dev-story.ts
4056
- const logger$8 = createLogger("compiled-workflows:dev-story");
4061
+ const logger$9 = createLogger("compiled-workflows:dev-story");
4057
4062
  /** Hard token ceiling for the assembled dev-story prompt */
4058
4063
  const TOKEN_CEILING$1 = 24e3;
4059
4064
  /** Default timeout for dev-story dispatches in milliseconds (30 min) */
@@ -4078,7 +4083,7 @@ const DEFAULT_VITEST_PATTERNS = `## Test Patterns (defaults)
4078
4083
  */
4079
4084
  async function runDevStory(deps, params) {
4080
4085
  const { storyKey, storyFilePath, taskScope, priorFiles } = params;
4081
- logger$8.info({
4086
+ logger$9.info({
4082
4087
  storyKey,
4083
4088
  storyFilePath
4084
4089
  }, "Starting compiled dev-story workflow");
@@ -4120,10 +4125,10 @@ async function runDevStory(deps, params) {
4120
4125
  let template;
4121
4126
  try {
4122
4127
  template = await deps.pack.getPrompt("dev-story");
4123
- logger$8.debug({ storyKey }, "Retrieved dev-story prompt template from pack");
4128
+ logger$9.debug({ storyKey }, "Retrieved dev-story prompt template from pack");
4124
4129
  } catch (err) {
4125
4130
  const error = err instanceof Error ? err.message : String(err);
4126
- logger$8.error({
4131
+ logger$9.error({
4127
4132
  storyKey,
4128
4133
  error
4129
4134
  }, "Failed to retrieve dev-story prompt template");
@@ -4134,14 +4139,14 @@ async function runDevStory(deps, params) {
4134
4139
  storyContent = await readFile$1(storyFilePath, "utf-8");
4135
4140
  } catch (err) {
4136
4141
  if (err.code === "ENOENT") {
4137
- logger$8.error({
4142
+ logger$9.error({
4138
4143
  storyKey,
4139
4144
  storyFilePath
4140
4145
  }, "Story file not found");
4141
4146
  return makeFailureResult("story_file_not_found");
4142
4147
  }
4143
4148
  const error = err instanceof Error ? err.message : String(err);
4144
- logger$8.error({
4149
+ logger$9.error({
4145
4150
  storyKey,
4146
4151
  storyFilePath,
4147
4152
  error
@@ -4149,7 +4154,7 @@ async function runDevStory(deps, params) {
4149
4154
  return makeFailureResult(`story_file_read_error: ${error}`);
4150
4155
  }
4151
4156
  if (storyContent.trim().length === 0) {
4152
- logger$8.error({
4157
+ logger$9.error({
4153
4158
  storyKey,
4154
4159
  storyFilePath
4155
4160
  }, "Story file is empty");
@@ -4161,17 +4166,17 @@ async function runDevStory(deps, params) {
4161
4166
  const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
4162
4167
  if (testPatternDecisions.length > 0) {
4163
4168
  testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
4164
- logger$8.debug({
4169
+ logger$9.debug({
4165
4170
  storyKey,
4166
4171
  count: testPatternDecisions.length
4167
4172
  }, "Loaded test patterns from decision store");
4168
4173
  } else {
4169
4174
  testPatternsContent = DEFAULT_VITEST_PATTERNS;
4170
- logger$8.debug({ storyKey }, "No test-pattern decisions found — using default Vitest patterns");
4175
+ logger$9.debug({ storyKey }, "No test-pattern decisions found — using default Vitest patterns");
4171
4176
  }
4172
4177
  } catch (err) {
4173
4178
  const error = err instanceof Error ? err.message : String(err);
4174
- logger$8.warn({
4179
+ logger$9.warn({
4175
4180
  storyKey,
4176
4181
  error
4177
4182
  }, "Failed to load test patterns — using defaults");
@@ -4214,7 +4219,7 @@ async function runDevStory(deps, params) {
4214
4219
  }
4215
4220
  ];
4216
4221
  const { prompt, tokenCount, truncated } = assemblePrompt(template, sections, TOKEN_CEILING$1);
4217
- logger$8.info({
4222
+ logger$9.info({
4218
4223
  storyKey,
4219
4224
  tokenCount,
4220
4225
  ceiling: TOKEN_CEILING$1,
@@ -4233,7 +4238,7 @@ async function runDevStory(deps, params) {
4233
4238
  dispatchResult = await handle.result;
4234
4239
  } catch (err) {
4235
4240
  const error = err instanceof Error ? err.message : String(err);
4236
- logger$8.error({
4241
+ logger$9.error({
4237
4242
  storyKey,
4238
4243
  error
4239
4244
  }, "Dispatch threw an unexpected error");
@@ -4244,11 +4249,11 @@ async function runDevStory(deps, params) {
4244
4249
  output: dispatchResult.tokenEstimate.output
4245
4250
  };
4246
4251
  if (dispatchResult.status === "timeout") {
4247
- logger$8.error({
4252
+ logger$9.error({
4248
4253
  storyKey,
4249
4254
  durationMs: dispatchResult.durationMs
4250
4255
  }, "Dev-story dispatch timed out");
4251
- if (dispatchResult.output.length > 0) logger$8.info({
4256
+ if (dispatchResult.output.length > 0) logger$9.info({
4252
4257
  storyKey,
4253
4258
  partialOutput: dispatchResult.output.slice(0, 500)
4254
4259
  }, "Partial output before timeout");
@@ -4258,12 +4263,12 @@ async function runDevStory(deps, params) {
4258
4263
  };
4259
4264
  }
4260
4265
  if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
4261
- logger$8.error({
4266
+ logger$9.error({
4262
4267
  storyKey,
4263
4268
  exitCode: dispatchResult.exitCode,
4264
4269
  status: dispatchResult.status
4265
4270
  }, "Dev-story dispatch failed");
4266
- if (dispatchResult.output.length > 0) logger$8.info({
4271
+ if (dispatchResult.output.length > 0) logger$9.info({
4267
4272
  storyKey,
4268
4273
  partialOutput: dispatchResult.output.slice(0, 500)
4269
4274
  }, "Partial output from failed dispatch");
@@ -4275,7 +4280,7 @@ async function runDevStory(deps, params) {
4275
4280
  if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
4276
4281
  const details = dispatchResult.parseError ?? "parsed result was null";
4277
4282
  const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
4278
- logger$8.error({
4283
+ logger$9.error({
4279
4284
  storyKey,
4280
4285
  parseError: details,
4281
4286
  rawOutputSnippet: rawSnippet
@@ -4283,12 +4288,12 @@ async function runDevStory(deps, params) {
4283
4288
  let filesModified = [];
4284
4289
  try {
4285
4290
  filesModified = await getGitChangedFiles(deps.projectRoot ?? process.cwd());
4286
- if (filesModified.length > 0) logger$8.info({
4291
+ if (filesModified.length > 0) logger$9.info({
4287
4292
  storyKey,
4288
4293
  fileCount: filesModified.length
4289
4294
  }, "Recovered files_modified from git status (YAML fallback)");
4290
4295
  } catch (err) {
4291
- logger$8.warn({
4296
+ logger$9.warn({
4292
4297
  storyKey,
4293
4298
  error: err instanceof Error ? err.message : String(err)
4294
4299
  }, "Failed to recover files_modified from git");
@@ -4305,7 +4310,7 @@ async function runDevStory(deps, params) {
4305
4310
  };
4306
4311
  }
4307
4312
  const parsed = dispatchResult.parsed;
4308
- logger$8.info({
4313
+ logger$9.info({
4309
4314
  storyKey,
4310
4315
  result: parsed.result,
4311
4316
  acMet: parsed.ac_met.length
@@ -4444,7 +4449,7 @@ function extractFilesInScope(storyContent) {
4444
4449
 
4445
4450
  //#endregion
4446
4451
  //#region src/modules/compiled-workflows/code-review.ts
4447
- const logger$7 = createLogger("compiled-workflows:code-review");
4452
+ const logger$8 = createLogger("compiled-workflows:code-review");
4448
4453
  /**
4449
4454
  * Hard token ceiling for the assembled code-review prompt (50,000 tokens).
4450
4455
  * Quality reviews require seeing actual code diffs, not just file names.
@@ -4484,7 +4489,7 @@ function defaultFailResult(error, tokenUsage) {
4484
4489
  async function runCodeReview(deps, params) {
4485
4490
  const { storyKey, storyFilePath, workingDirectory, pipelineRunId, filesModified, previousIssues } = params;
4486
4491
  const cwd = workingDirectory ?? process.cwd();
4487
- logger$7.debug({
4492
+ logger$8.debug({
4488
4493
  storyKey,
4489
4494
  storyFilePath,
4490
4495
  cwd,
@@ -4495,7 +4500,7 @@ async function runCodeReview(deps, params) {
4495
4500
  template = await deps.pack.getPrompt("code-review");
4496
4501
  } catch (err) {
4497
4502
  const error = err instanceof Error ? err.message : String(err);
4498
- logger$7.error({ error }, "Failed to retrieve code-review prompt template");
4503
+ logger$8.error({ error }, "Failed to retrieve code-review prompt template");
4499
4504
  return defaultFailResult(`Failed to retrieve prompt template: ${error}`, {
4500
4505
  input: 0,
4501
4506
  output: 0
@@ -4506,7 +4511,7 @@ async function runCodeReview(deps, params) {
4506
4511
  storyContent = await readFile$1(storyFilePath, "utf-8");
4507
4512
  } catch (err) {
4508
4513
  const error = err instanceof Error ? err.message : String(err);
4509
- logger$7.error({
4514
+ logger$8.error({
4510
4515
  storyFilePath,
4511
4516
  error
4512
4517
  }, "Failed to read story file");
@@ -4526,12 +4531,12 @@ async function runCodeReview(deps, params) {
4526
4531
  const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
4527
4532
  if (scopedTotal <= TOKEN_CEILING) {
4528
4533
  gitDiffContent = scopedDiff;
4529
- logger$7.debug({
4534
+ logger$8.debug({
4530
4535
  fileCount: filesModified.length,
4531
4536
  tokenCount: scopedTotal
4532
4537
  }, "Using scoped file diff");
4533
4538
  } else {
4534
- logger$7.warn({
4539
+ logger$8.warn({
4535
4540
  estimatedTotal: scopedTotal,
4536
4541
  ceiling: TOKEN_CEILING,
4537
4542
  fileCount: filesModified.length
@@ -4545,7 +4550,7 @@ async function runCodeReview(deps, params) {
4545
4550
  const fullTotal = nonDiffTokens + countTokens(fullDiff);
4546
4551
  if (fullTotal <= TOKEN_CEILING) gitDiffContent = fullDiff;
4547
4552
  else {
4548
- logger$7.warn({
4553
+ logger$8.warn({
4549
4554
  estimatedTotal: fullTotal,
4550
4555
  ceiling: TOKEN_CEILING
4551
4556
  }, "Full git diff would exceed token ceiling — using stat-only summary");
@@ -4583,11 +4588,11 @@ async function runCodeReview(deps, params) {
4583
4588
  }
4584
4589
  ];
4585
4590
  const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
4586
- if (assembleResult.truncated) logger$7.warn({
4591
+ if (assembleResult.truncated) logger$8.warn({
4587
4592
  storyKey,
4588
4593
  tokenCount: assembleResult.tokenCount
4589
4594
  }, "Code-review prompt truncated to fit token ceiling");
4590
- logger$7.debug({
4595
+ logger$8.debug({
4591
4596
  storyKey,
4592
4597
  tokenCount: assembleResult.tokenCount,
4593
4598
  truncated: assembleResult.truncated
@@ -4605,7 +4610,7 @@ async function runCodeReview(deps, params) {
4605
4610
  dispatchResult = await handle.result;
4606
4611
  } catch (err) {
4607
4612
  const error = err instanceof Error ? err.message : String(err);
4608
- logger$7.error({
4613
+ logger$8.error({
4609
4614
  storyKey,
4610
4615
  error
4611
4616
  }, "Code-review dispatch threw unexpected error");
@@ -4621,7 +4626,7 @@ async function runCodeReview(deps, params) {
4621
4626
  const rawOutput = dispatchResult.output ?? void 0;
4622
4627
  if (dispatchResult.status === "failed") {
4623
4628
  const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""} ${dispatchResult.output ? `Stderr: ${dispatchResult.output}` : ""}`.trim();
4624
- logger$7.warn({
4629
+ logger$8.warn({
4625
4630
  storyKey,
4626
4631
  exitCode: dispatchResult.exitCode
4627
4632
  }, "Code-review dispatch failed");
@@ -4631,7 +4636,7 @@ async function runCodeReview(deps, params) {
4631
4636
  };
4632
4637
  }
4633
4638
  if (dispatchResult.status === "timeout") {
4634
- logger$7.warn({ storyKey }, "Code-review dispatch timed out");
4639
+ logger$8.warn({ storyKey }, "Code-review dispatch timed out");
4635
4640
  return {
4636
4641
  ...defaultFailResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage),
4637
4642
  rawOutput
@@ -4639,7 +4644,7 @@ async function runCodeReview(deps, params) {
4639
4644
  }
4640
4645
  if (dispatchResult.parsed === null) {
4641
4646
  const details = dispatchResult.parseError ?? "No YAML block found in output";
4642
- logger$7.warn({
4647
+ logger$8.warn({
4643
4648
  storyKey,
4644
4649
  details
4645
4650
  }, "Code-review output schema validation failed");
@@ -4656,7 +4661,7 @@ async function runCodeReview(deps, params) {
4656
4661
  const parseResult = CodeReviewResultSchema.safeParse(dispatchResult.parsed);
4657
4662
  if (!parseResult.success) {
4658
4663
  const details = parseResult.error.message;
4659
- logger$7.warn({
4664
+ logger$8.warn({
4660
4665
  storyKey,
4661
4666
  details
4662
4667
  }, "Code-review output failed schema validation");
@@ -4671,13 +4676,13 @@ async function runCodeReview(deps, params) {
4671
4676
  };
4672
4677
  }
4673
4678
  const parsed = parseResult.data;
4674
- if (parsed.agentVerdict !== parsed.verdict) logger$7.info({
4679
+ if (parsed.agentVerdict !== parsed.verdict) logger$8.info({
4675
4680
  storyKey,
4676
4681
  agentVerdict: parsed.agentVerdict,
4677
4682
  pipelineVerdict: parsed.verdict,
4678
4683
  issues: parsed.issues
4679
4684
  }, "Pipeline overrode agent verdict based on issue severities");
4680
- logger$7.info({
4685
+ logger$8.info({
4681
4686
  storyKey,
4682
4687
  verdict: parsed.verdict,
4683
4688
  issues: parsed.issues
@@ -4702,7 +4707,7 @@ function getArchConstraints(deps) {
4702
4707
  if (constraints.length === 0) return "";
4703
4708
  return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
4704
4709
  } catch (err) {
4705
- logger$7.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
4710
+ logger$8.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
4706
4711
  return "";
4707
4712
  }
4708
4713
  }
@@ -5034,7 +5039,7 @@ function detectConflictGroups(storyKeys, config) {
5034
5039
 
5035
5040
  //#endregion
5036
5041
  //#region src/modules/implementation-orchestrator/seed-methodology-context.ts
5037
- const logger$6 = createLogger("implementation-orchestrator:seed");
5042
+ const logger$7 = createLogger("implementation-orchestrator:seed");
5038
5043
  /** Max chars for the architecture summary seeded into decisions */
5039
5044
  const MAX_ARCH_CHARS = 6e3;
5040
5045
  /** Max chars per epic shard */
@@ -5068,12 +5073,12 @@ function seedMethodologyContext(db, projectRoot) {
5068
5073
  const testCount = seedTestPatterns(db, projectRoot);
5069
5074
  if (testCount === -1) result.skippedCategories.push("test-patterns");
5070
5075
  else result.decisionsCreated += testCount;
5071
- logger$6.info({
5076
+ logger$7.info({
5072
5077
  decisionsCreated: result.decisionsCreated,
5073
5078
  skippedCategories: result.skippedCategories
5074
5079
  }, "Methodology context seeding complete");
5075
5080
  } catch (err) {
5076
- logger$6.warn({ error: err instanceof Error ? err.message : String(err) }, "Methodology context seeding failed (non-fatal)");
5081
+ logger$7.warn({ error: err instanceof Error ? err.message : String(err) }, "Methodology context seeding failed (non-fatal)");
5077
5082
  }
5078
5083
  return result;
5079
5084
  }
@@ -5117,7 +5122,7 @@ function seedArchitecture(db, projectRoot) {
5117
5122
  });
5118
5123
  count = 1;
5119
5124
  }
5120
- logger$6.debug({ count }, "Seeded architecture decisions");
5125
+ logger$7.debug({ count }, "Seeded architecture decisions");
5121
5126
  return count;
5122
5127
  }
5123
5128
  /**
@@ -5145,7 +5150,7 @@ function seedEpicShards(db, projectRoot) {
5145
5150
  });
5146
5151
  count++;
5147
5152
  }
5148
- logger$6.debug({ count }, "Seeded epic shard decisions");
5153
+ logger$7.debug({ count }, "Seeded epic shard decisions");
5149
5154
  return count;
5150
5155
  }
5151
5156
  /**
@@ -5166,7 +5171,7 @@ function seedTestPatterns(db, projectRoot) {
5166
5171
  value: patterns.slice(0, MAX_TEST_PATTERNS_CHARS),
5167
5172
  rationale: "Detected from project configuration at orchestrator startup"
5168
5173
  });
5169
- logger$6.debug("Seeded test patterns decision");
5174
+ logger$7.debug("Seeded test patterns decision");
5170
5175
  return 1;
5171
5176
  }
5172
5177
  /**
@@ -5358,7 +5363,7 @@ function createPauseGate() {
5358
5363
  */
5359
5364
  function createImplementationOrchestrator(deps) {
5360
5365
  const { db, pack, contextCompiler, dispatcher, eventBus, config, projectRoot } = deps;
5361
- const logger$16 = createLogger("implementation-orchestrator");
5366
+ const logger$17 = createLogger("implementation-orchestrator");
5362
5367
  let _state = "IDLE";
5363
5368
  let _startedAt;
5364
5369
  let _completedAt;
@@ -5395,7 +5400,7 @@ function createImplementationOrchestrator(deps) {
5395
5400
  const nowMs = Date.now();
5396
5401
  for (const [phase, startMs] of starts) {
5397
5402
  const endMs = ends?.get(phase);
5398
- if (endMs === void 0) logger$16.warn({
5403
+ if (endMs === void 0) logger$17.warn({
5399
5404
  storyKey,
5400
5405
  phase
5401
5406
  }, "Phase has no end time — story may have errored mid-phase. Duration capped to now() and may be inflated.");
@@ -5442,13 +5447,13 @@ function createImplementationOrchestrator(deps) {
5442
5447
  rationale: `Story ${storyKey} completed with result=${result} in ${wallClockSeconds}s. Tokens: ${tokenAgg.input}+${tokenAgg.output}. Review cycles: ${reviewCycles}.`
5443
5448
  });
5444
5449
  } catch (decisionErr) {
5445
- logger$16.warn({
5450
+ logger$17.warn({
5446
5451
  err: decisionErr,
5447
5452
  storyKey
5448
5453
  }, "Failed to write story-metrics decision (best-effort)");
5449
5454
  }
5450
5455
  } catch (err) {
5451
- logger$16.warn({
5456
+ logger$17.warn({
5452
5457
  err,
5453
5458
  storyKey
5454
5459
  }, "Failed to write story metrics (best-effort)");
@@ -5484,7 +5489,7 @@ function createImplementationOrchestrator(deps) {
5484
5489
  token_usage_json: serialized
5485
5490
  });
5486
5491
  } catch (err) {
5487
- logger$16.warn("Failed to persist orchestrator state", { err });
5492
+ logger$17.warn("Failed to persist orchestrator state", { err });
5488
5493
  }
5489
5494
  }
5490
5495
  function recordProgress() {
@@ -5514,7 +5519,7 @@ function createImplementationOrchestrator(deps) {
5514
5519
  if (_stalledStories.has(key)) continue;
5515
5520
  _stalledStories.add(key);
5516
5521
  _storiesWithStall.add(key);
5517
- logger$16.warn({
5522
+ logger$17.warn({
5518
5523
  storyKey: key,
5519
5524
  phase: s.phase,
5520
5525
  elapsedMs: elapsed
@@ -5551,7 +5556,7 @@ function createImplementationOrchestrator(deps) {
5551
5556
  * exhausted retries the story is ESCALATED.
5552
5557
  */
5553
5558
  async function processStory(storyKey) {
5554
- logger$16.info("Processing story", { storyKey });
5559
+ logger$17.info("Processing story", { storyKey });
5555
5560
  await waitIfPaused();
5556
5561
  if (_state !== "RUNNING") return;
5557
5562
  startPhase(storyKey, "create-story");
@@ -5566,7 +5571,7 @@ function createImplementationOrchestrator(deps) {
5566
5571
  const match = files.find((f) => f.startsWith(`${storyKey}-`) && f.endsWith(".md"));
5567
5572
  if (match) {
5568
5573
  storyFilePath = join$1(artifactsDir, match);
5569
- logger$16.info({
5574
+ logger$17.info({
5570
5575
  storyKey,
5571
5576
  storyFilePath
5572
5577
  }, "Found existing story file — skipping create-story");
@@ -5667,7 +5672,7 @@ function createImplementationOrchestrator(deps) {
5667
5672
  try {
5668
5673
  storyContentForAnalysis = await readFile$1(storyFilePath ?? "", "utf-8");
5669
5674
  } catch (err) {
5670
- logger$16.error({
5675
+ logger$17.error({
5671
5676
  storyKey,
5672
5677
  storyFilePath,
5673
5678
  error: err instanceof Error ? err.message : String(err)
@@ -5675,7 +5680,7 @@ function createImplementationOrchestrator(deps) {
5675
5680
  }
5676
5681
  const analysis = analyzeStoryComplexity(storyContentForAnalysis);
5677
5682
  const batches = planTaskBatches(analysis);
5678
- logger$16.info({
5683
+ logger$17.info({
5679
5684
  storyKey,
5680
5685
  estimatedScope: analysis.estimatedScope,
5681
5686
  batchCount: batches.length,
@@ -5693,7 +5698,7 @@ function createImplementationOrchestrator(deps) {
5693
5698
  if (_state !== "RUNNING") break;
5694
5699
  const taskScope = batch.taskIds.map((id, i) => `T${id}: ${batch.taskTitles[i] ?? ""}`).join("\n");
5695
5700
  const priorFiles = allFilesModified.size > 0 ? Array.from(allFilesModified) : void 0;
5696
- logger$16.info({
5701
+ logger$17.info({
5697
5702
  storyKey,
5698
5703
  batchIndex: batch.batchIndex,
5699
5704
  taskCount: batch.taskIds.length
@@ -5717,7 +5722,7 @@ function createImplementationOrchestrator(deps) {
5717
5722
  });
5718
5723
  } catch (batchErr) {
5719
5724
  const errMsg = batchErr instanceof Error ? batchErr.message : String(batchErr);
5720
- logger$16.warn({
5725
+ logger$17.warn({
5721
5726
  storyKey,
5722
5727
  batchIndex: batch.batchIndex,
5723
5728
  error: errMsg
@@ -5737,7 +5742,7 @@ function createImplementationOrchestrator(deps) {
5737
5742
  filesModified: batchFilesModified,
5738
5743
  result: batchResult.result === "success" ? "success" : "failed"
5739
5744
  };
5740
- logger$16.info(batchMetrics, "Batch dev-story metrics");
5745
+ logger$17.info(batchMetrics, "Batch dev-story metrics");
5741
5746
  for (const f of batchFilesModified) allFilesModified.add(f);
5742
5747
  if (batchFilesModified.length > 0) batchFileGroups.push({
5743
5748
  batchIndex: batch.batchIndex,
@@ -5759,13 +5764,13 @@ function createImplementationOrchestrator(deps) {
5759
5764
  })
5760
5765
  });
5761
5766
  } catch (tokenErr) {
5762
- logger$16.warn({
5767
+ logger$17.warn({
5763
5768
  storyKey,
5764
5769
  batchIndex: batch.batchIndex,
5765
5770
  err: tokenErr
5766
5771
  }, "Failed to record batch token usage");
5767
5772
  }
5768
- if (batchResult.result === "failed") logger$16.warn({
5773
+ if (batchResult.result === "failed") logger$17.warn({
5769
5774
  storyKey,
5770
5775
  batchIndex: batch.batchIndex,
5771
5776
  error: batchResult.error
@@ -5798,7 +5803,7 @@ function createImplementationOrchestrator(deps) {
5798
5803
  result: devResult
5799
5804
  });
5800
5805
  persistState();
5801
- if (devResult.result === "failed") logger$16.warn("Dev-story reported failure, proceeding to code review", {
5806
+ if (devResult.result === "failed") logger$17.warn("Dev-story reported failure, proceeding to code review", {
5802
5807
  storyKey,
5803
5808
  error: devResult.error,
5804
5809
  filesModified: devFilesModified.length
@@ -5855,7 +5860,7 @@ function createImplementationOrchestrator(deps) {
5855
5860
  "NEEDS_MAJOR_REWORK": 2
5856
5861
  };
5857
5862
  for (const group of batchFileGroups) {
5858
- logger$16.info({
5863
+ logger$17.info({
5859
5864
  storyKey,
5860
5865
  batchIndex: group.batchIndex,
5861
5866
  fileCount: group.files.length
@@ -5892,7 +5897,7 @@ function createImplementationOrchestrator(deps) {
5892
5897
  rawOutput: lastRawOutput,
5893
5898
  tokenUsage: aggregateTokens
5894
5899
  };
5895
- logger$16.info({
5900
+ logger$17.info({
5896
5901
  storyKey,
5897
5902
  batchCount: batchFileGroups.length,
5898
5903
  verdict: worstVerdict,
@@ -5918,7 +5923,7 @@ function createImplementationOrchestrator(deps) {
5918
5923
  const isPhantomReview = reviewResult.verdict !== "SHIP_IT" && (reviewResult.issue_list === void 0 || reviewResult.issue_list.length === 0) && reviewResult.error !== void 0;
5919
5924
  if (isPhantomReview && !timeoutRetried) {
5920
5925
  timeoutRetried = true;
5921
- logger$16.warn({
5926
+ logger$17.warn({
5922
5927
  storyKey,
5923
5928
  reviewCycles,
5924
5929
  error: reviewResult.error
@@ -5928,7 +5933,7 @@ function createImplementationOrchestrator(deps) {
5928
5933
  verdict = reviewResult.verdict;
5929
5934
  issueList = reviewResult.issue_list ?? [];
5930
5935
  if (verdict === "NEEDS_MAJOR_REWORK" && reviewCycles > 0 && previousIssueList.length > 0 && issueList.length < previousIssueList.length) {
5931
- logger$16.info({
5936
+ logger$17.info({
5932
5937
  storyKey,
5933
5938
  originalVerdict: verdict,
5934
5939
  issuesBefore: previousIssueList.length,
@@ -5964,7 +5969,7 @@ function createImplementationOrchestrator(deps) {
5964
5969
  if (_decomposition !== void 0) parts.push(`decomposed: ${_decomposition.batchCount} batches`);
5965
5970
  parts.push(`${fileCount} files`);
5966
5971
  parts.push(`${totalTokensK} tokens`);
5967
- logger$16.info({
5972
+ logger$17.info({
5968
5973
  storyKey,
5969
5974
  verdict,
5970
5975
  agentVerdict: reviewResult.agentVerdict
@@ -6022,7 +6027,7 @@ function createImplementationOrchestrator(deps) {
6022
6027
  persistState();
6023
6028
  return;
6024
6029
  }
6025
- logger$16.info({
6030
+ logger$17.info({
6026
6031
  storyKey,
6027
6032
  reviewCycles: finalReviewCycles,
6028
6033
  issueCount: issueList.length
@@ -6072,7 +6077,7 @@ function createImplementationOrchestrator(deps) {
6072
6077
  fixPrompt = assembled.prompt;
6073
6078
  } catch {
6074
6079
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, minor fixes needed`;
6075
- logger$16.warn("Failed to assemble auto-approve fix prompt, using fallback", { storyKey });
6080
+ logger$17.warn("Failed to assemble auto-approve fix prompt, using fallback", { storyKey });
6076
6081
  }
6077
6082
  const handle = dispatcher.dispatch({
6078
6083
  prompt: fixPrompt,
@@ -6089,9 +6094,9 @@ function createImplementationOrchestrator(deps) {
6089
6094
  output: fixResult.tokenEstimate.output
6090
6095
  } : void 0 }
6091
6096
  });
6092
- if (fixResult.status === "timeout") logger$16.warn("Auto-approve fix timed out — approving anyway (issues were minor)", { storyKey });
6097
+ if (fixResult.status === "timeout") logger$17.warn("Auto-approve fix timed out — approving anyway (issues were minor)", { storyKey });
6093
6098
  } catch (err) {
6094
- logger$16.warn("Auto-approve fix dispatch failed — approving anyway (issues were minor)", {
6099
+ logger$17.warn("Auto-approve fix dispatch failed — approving anyway (issues were minor)", {
6095
6100
  storyKey,
6096
6101
  err
6097
6102
  });
@@ -6163,7 +6168,7 @@ function createImplementationOrchestrator(deps) {
6163
6168
  fixPrompt = assembled.prompt;
6164
6169
  } catch {
6165
6170
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, taskType=${taskType}`;
6166
- logger$16.warn("Failed to assemble fix prompt, using fallback", {
6171
+ logger$17.warn("Failed to assemble fix prompt, using fallback", {
6167
6172
  storyKey,
6168
6173
  taskType
6169
6174
  });
@@ -6186,7 +6191,7 @@ function createImplementationOrchestrator(deps) {
6186
6191
  } : void 0 }
6187
6192
  });
6188
6193
  if (fixResult.status === "timeout") {
6189
- logger$16.warn("Fix dispatch timed out — escalating story", {
6194
+ logger$17.warn("Fix dispatch timed out — escalating story", {
6190
6195
  storyKey,
6191
6196
  taskType
6192
6197
  });
@@ -6206,13 +6211,13 @@ function createImplementationOrchestrator(deps) {
6206
6211
  persistState();
6207
6212
  return;
6208
6213
  }
6209
- if (fixResult.status === "failed") logger$16.warn("Fix dispatch failed", {
6214
+ if (fixResult.status === "failed") logger$17.warn("Fix dispatch failed", {
6210
6215
  storyKey,
6211
6216
  taskType,
6212
6217
  exitCode: fixResult.exitCode
6213
6218
  });
6214
6219
  } catch (err) {
6215
- logger$16.warn("Fix dispatch failed, continuing to next review", {
6220
+ logger$17.warn("Fix dispatch failed, continuing to next review", {
6216
6221
  storyKey,
6217
6222
  taskType,
6218
6223
  err
@@ -6266,11 +6271,11 @@ function createImplementationOrchestrator(deps) {
6266
6271
  }
6267
6272
  async function run(storyKeys) {
6268
6273
  if (_state === "RUNNING" || _state === "PAUSED") {
6269
- logger$16.warn("run() called while orchestrator is already running or paused — ignoring", { state: _state });
6274
+ logger$17.warn("run() called while orchestrator is already running or paused — ignoring", { state: _state });
6270
6275
  return getStatus();
6271
6276
  }
6272
6277
  if (_state === "COMPLETE") {
6273
- logger$16.warn("run() called on a COMPLETE orchestrator — ignoring", { state: _state });
6278
+ logger$17.warn("run() called on a COMPLETE orchestrator — ignoring", { state: _state });
6274
6279
  return getStatus();
6275
6280
  }
6276
6281
  _state = "RUNNING";
@@ -6288,13 +6293,13 @@ function createImplementationOrchestrator(deps) {
6288
6293
  if (config.enableHeartbeat) startHeartbeat();
6289
6294
  if (projectRoot !== void 0) {
6290
6295
  const seedResult = seedMethodologyContext(db, projectRoot);
6291
- if (seedResult.decisionsCreated > 0) logger$16.info({
6296
+ if (seedResult.decisionsCreated > 0) logger$17.info({
6292
6297
  decisionsCreated: seedResult.decisionsCreated,
6293
6298
  skippedCategories: seedResult.skippedCategories
6294
6299
  }, "Methodology context seeded from planning artifacts");
6295
6300
  }
6296
6301
  const groups = detectConflictGroups(storyKeys);
6297
- logger$16.info("Orchestrator starting", {
6302
+ logger$17.info("Orchestrator starting", {
6298
6303
  storyCount: storyKeys.length,
6299
6304
  groupCount: groups.length,
6300
6305
  maxConcurrency: config.maxConcurrency
@@ -6306,7 +6311,7 @@ function createImplementationOrchestrator(deps) {
6306
6311
  _state = "FAILED";
6307
6312
  _completedAt = new Date().toISOString();
6308
6313
  persistState();
6309
- logger$16.error("Orchestrator failed with unhandled error", { err });
6314
+ logger$17.error("Orchestrator failed with unhandled error", { err });
6310
6315
  return getStatus();
6311
6316
  }
6312
6317
  stopHeartbeat();
@@ -6333,7 +6338,7 @@ function createImplementationOrchestrator(deps) {
6333
6338
  _pauseGate = createPauseGate();
6334
6339
  _state = "PAUSED";
6335
6340
  eventBus.emit("orchestrator:paused", {});
6336
- logger$16.info("Orchestrator paused");
6341
+ logger$17.info("Orchestrator paused");
6337
6342
  }
6338
6343
  function resume() {
6339
6344
  if (_state !== "PAUSED") return;
@@ -6344,7 +6349,7 @@ function createImplementationOrchestrator(deps) {
6344
6349
  }
6345
6350
  _state = "RUNNING";
6346
6351
  eventBus.emit("orchestrator:resumed", {});
6347
- logger$16.info("Orchestrator resumed");
6352
+ logger$17.info("Orchestrator resumed");
6348
6353
  }
6349
6354
  return {
6350
6355
  run,
@@ -7019,7 +7024,7 @@ const CritiqueOutputSchema = z.object({
7019
7024
 
7020
7025
  //#endregion
7021
7026
  //#region src/modules/phase-orchestrator/critique-loop.ts
7022
- const logger$5 = createLogger("critique-loop");
7027
+ const logger$6 = createLogger("critique-loop");
7023
7028
  /**
7024
7029
  * Maps a phase name to the critique prompt template name.
7025
7030
  * Falls back to `critique-${phase}` for unknown phases.
@@ -7073,7 +7078,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7073
7078
  critiquePrompt = critiqueTemplate.replace("{{artifact_content}}", currentArtifact).replace("{{project_context}}", projectContext);
7074
7079
  } catch (err) {
7075
7080
  const message = err instanceof Error ? err.message : String(err);
7076
- logger$5.warn({
7081
+ logger$6.warn({
7077
7082
  phaseId,
7078
7083
  promptName: critiquePromptName,
7079
7084
  err: message
@@ -7101,7 +7106,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7101
7106
  critiqueTokens.output += result.tokenEstimate.output;
7102
7107
  if (result.status !== "completed" || result.parsed === null) {
7103
7108
  const errMsg = result.parseError ?? `Critique dispatch ended with status '${result.status}'`;
7104
- logger$5.warn({
7109
+ logger$6.warn({
7105
7110
  phaseId,
7106
7111
  iteration: i + 1,
7107
7112
  err: errMsg
@@ -7120,7 +7125,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7120
7125
  lastCritiqueOutput = critiqueOutput;
7121
7126
  } catch (err) {
7122
7127
  const message = err instanceof Error ? err.message : String(err);
7123
- logger$5.warn({
7128
+ logger$6.warn({
7124
7129
  phaseId,
7125
7130
  iteration: i + 1,
7126
7131
  err: message
@@ -7160,14 +7165,14 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7160
7165
  });
7161
7166
  } catch (err) {
7162
7167
  const message = err instanceof Error ? err.message : String(err);
7163
- logger$5.warn({
7168
+ logger$6.warn({
7164
7169
  phaseId,
7165
7170
  iteration: i + 1,
7166
7171
  err: message
7167
7172
  }, "Critique loop: failed to store critique decision — continuing");
7168
7173
  }
7169
7174
  if (critiqueOutput.verdict === "pass") {
7170
- logger$5.info({
7175
+ logger$6.info({
7171
7176
  phaseId,
7172
7177
  iteration: i + 1
7173
7178
  }, "Critique loop: artifact passed critique — loop complete");
@@ -7180,7 +7185,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7180
7185
  totalMs: Date.now() - startMs
7181
7186
  };
7182
7187
  }
7183
- logger$5.info({
7188
+ logger$6.info({
7184
7189
  phaseId,
7185
7190
  iteration: i + 1,
7186
7191
  issueCount: critiqueOutput.issue_count
@@ -7193,7 +7198,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7193
7198
  refinePrompt = refineTemplate.replace("{{original_artifact}}", currentArtifact).replace("{{critique_issues}}", issuesText).replace("{{phase_context}}", phaseContext);
7194
7199
  } catch (err) {
7195
7200
  const message = err instanceof Error ? err.message : String(err);
7196
- logger$5.warn({
7201
+ logger$6.warn({
7197
7202
  phaseId,
7198
7203
  iteration: i + 1,
7199
7204
  err: message
@@ -7214,7 +7219,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7214
7219
  const originalLength = currentArtifact.length;
7215
7220
  const refinedLength = refineResult.output.length;
7216
7221
  const delta = refinedLength - originalLength;
7217
- logger$5.info({
7222
+ logger$6.info({
7218
7223
  phaseId,
7219
7224
  iteration: i + 1,
7220
7225
  originalLength,
@@ -7223,7 +7228,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7223
7228
  }, "Critique loop: refinement complete");
7224
7229
  currentArtifact = refineResult.output;
7225
7230
  } else {
7226
- logger$5.warn({
7231
+ logger$6.warn({
7227
7232
  phaseId,
7228
7233
  iteration: i + 1,
7229
7234
  status: refineResult.status
@@ -7232,7 +7237,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7232
7237
  }
7233
7238
  } catch (err) {
7234
7239
  const message = err instanceof Error ? err.message : String(err);
7235
- logger$5.warn({
7240
+ logger$6.warn({
7236
7241
  phaseId,
7237
7242
  iteration: i + 1,
7238
7243
  err: message
@@ -7243,12 +7248,12 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7243
7248
  }
7244
7249
  const remainingIssues = lastCritiqueOutput?.issues ?? [];
7245
7250
  if (remainingIssues.length > 0) {
7246
- logger$5.warn({
7251
+ logger$6.warn({
7247
7252
  phaseId,
7248
7253
  maxIterations,
7249
7254
  issueCount: remainingIssues.length
7250
7255
  }, "Critique loop: max iterations reached with unresolved issues");
7251
- for (const issue of remainingIssues) logger$5.warn({
7256
+ for (const issue of remainingIssues) logger$6.warn({
7252
7257
  phaseId,
7253
7258
  severity: issue.severity,
7254
7259
  category: issue.category,
@@ -7267,7 +7272,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7267
7272
 
7268
7273
  //#endregion
7269
7274
  //#region src/modules/phase-orchestrator/elicitation-selector.ts
7270
- const logger$4 = createLogger("elicitation-selector");
7275
+ const logger$5 = createLogger("elicitation-selector");
7271
7276
  /**
7272
7277
  * Affinity scores (0.0–1.0) for each category per content type.
7273
7278
  *
@@ -7389,10 +7394,10 @@ function loadElicitationMethods() {
7389
7394
  try {
7390
7395
  const content = readFileSync(csvPath, "utf-8");
7391
7396
  const methods = parseMethodsCsv(content);
7392
- logger$4.debug({ count: methods.length }, "Loaded elicitation methods");
7397
+ logger$5.debug({ count: methods.length }, "Loaded elicitation methods");
7393
7398
  return methods;
7394
7399
  } catch (err) {
7395
- logger$4.warn({
7400
+ logger$5.warn({
7396
7401
  csvPath,
7397
7402
  err
7398
7403
  }, "Failed to load elicitation methods CSV");
@@ -7712,7 +7717,7 @@ const ElicitationOutputSchema = z.object({
7712
7717
 
7713
7718
  //#endregion
7714
7719
  //#region src/modules/phase-orchestrator/step-runner.ts
7715
- const logger$3 = createLogger("step-runner");
7720
+ const logger$4 = createLogger("step-runner");
7716
7721
  /**
7717
7722
  * Format an array of decision records into a markdown section for injection.
7718
7723
  *
@@ -7819,7 +7824,7 @@ async function runSteps(steps, deps, runId, phase, params) {
7819
7824
  if (estimatedTokens > budgetTokens) {
7820
7825
  const decisionRefs = step.context.filter((ref) => ref.source.startsWith("decision:"));
7821
7826
  if (decisionRefs.length > 0) {
7822
- logger$3.warn({
7827
+ logger$4.warn({
7823
7828
  step: step.name,
7824
7829
  estimatedTokens,
7825
7830
  budgetTokens
@@ -7846,7 +7851,7 @@ async function runSteps(steps, deps, runId, phase, params) {
7846
7851
  }
7847
7852
  prompt = summarizedPrompt;
7848
7853
  estimatedTokens = Math.ceil(prompt.length / 4);
7849
- if (estimatedTokens <= budgetTokens) logger$3.info({
7854
+ if (estimatedTokens <= budgetTokens) logger$4.info({
7850
7855
  step: step.name,
7851
7856
  estimatedTokens,
7852
7857
  budgetTokens
@@ -8027,7 +8032,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8027
8032
  const critiqueResult = await runCritiqueLoop(artifactContent, phase, runId, phase, deps);
8028
8033
  totalInput += critiqueResult.critiqueTokens.input + critiqueResult.refinementTokens.input;
8029
8034
  totalOutput += critiqueResult.critiqueTokens.output + critiqueResult.refinementTokens.output;
8030
- logger$3.info({
8035
+ logger$4.info({
8031
8036
  step: step.name,
8032
8037
  verdict: critiqueResult.verdict,
8033
8038
  iterations: critiqueResult.iterations,
@@ -8035,7 +8040,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8035
8040
  }, "Step critique loop complete");
8036
8041
  } catch (critiqueErr) {
8037
8042
  const critiqueMsg = critiqueErr instanceof Error ? critiqueErr.message : String(critiqueErr);
8038
- logger$3.warn({
8043
+ logger$4.warn({
8039
8044
  step: step.name,
8040
8045
  err: critiqueMsg
8041
8046
  }, "Step critique loop threw an error — continuing without critique");
@@ -8045,7 +8050,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8045
8050
  const contentType = deriveContentType(phase, step.name);
8046
8051
  const selectedMethods = selectMethods({ content_type: contentType }, usedElicitationMethods);
8047
8052
  if (selectedMethods.length > 0) {
8048
- logger$3.info({
8053
+ logger$4.info({
8049
8054
  step: step.name,
8050
8055
  methods: selectedMethods.map((m) => m.name),
8051
8056
  contentType
@@ -8084,13 +8089,13 @@ async function runSteps(steps, deps, runId, phase, params) {
8084
8089
  key: `${phase}-round-${roundIndex}-insights`,
8085
8090
  value: elicitParsed.insights
8086
8091
  });
8087
- logger$3.info({
8092
+ logger$4.info({
8088
8093
  step: step.name,
8089
8094
  method: method.name,
8090
8095
  roundIndex
8091
8096
  }, "Elicitation insights stored in decision store");
8092
8097
  }
8093
- } else logger$3.warn({
8098
+ } else logger$4.warn({
8094
8099
  step: step.name,
8095
8100
  method: method.name,
8096
8101
  status: elicitResult.status
@@ -8106,7 +8111,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8106
8111
  }
8107
8112
  } catch (elicitErr) {
8108
8113
  const elicitMsg = elicitErr instanceof Error ? elicitErr.message : String(elicitErr);
8109
- logger$3.warn({
8114
+ logger$4.warn({
8110
8115
  step: step.name,
8111
8116
  err: elicitMsg
8112
8117
  }, "Step elicitation threw an error — continuing without elicitation");
@@ -8448,7 +8453,7 @@ async function runAnalysisPhase(deps, params) {
8448
8453
 
8449
8454
  //#endregion
8450
8455
  //#region src/modules/phase-orchestrator/phases/planning.ts
8451
- const logger$2 = createLogger("planning-phase");
8456
+ const logger$3 = createLogger("planning-phase");
8452
8457
  /** Maximum total prompt length in tokens (3,500 tokens × 4 chars/token = 14,000 chars) */
8453
8458
  const MAX_PROMPT_TOKENS = 3500;
8454
8459
  const MAX_PROMPT_CHARS = MAX_PROMPT_TOKENS * 4;
@@ -8675,7 +8680,7 @@ async function runPlanningMultiStep(deps, params) {
8675
8680
  const techConstraintDecisions = allAnalysisDecisions.filter((d) => d.category === "technology-constraints");
8676
8681
  const violation = detectTechStackViolation(techStack, techConstraintDecisions);
8677
8682
  if (violation) {
8678
- logger$2.warn({ violation }, "Tech stack constraint violation detected — retrying step 3 with correction");
8683
+ logger$3.warn({ violation }, "Tech stack constraint violation detected — retrying step 3 with correction");
8679
8684
  const correctionPrefix = `CRITICAL CORRECTION: Your previous output was rejected because it violates the stated technology constraints.\n\nViolation: ${violation}\n\nYou MUST NOT use TypeScript, JavaScript, or Node.js for ANY backend service. Choose from Go, Kotlin/JVM, or Rust as stated in the technology constraints.\n\nRe-generate your output with a compliant tech stack. Everything else (NFRs, domain model, out-of-scope) can remain the same.\n\n---\n\n`;
8680
8685
  const step3Template = await deps.pack.getPrompt("planning-step-3-nfrs");
8681
8686
  const stepOutputs = new Map();
@@ -8702,10 +8707,10 @@ async function runPlanningMultiStep(deps, params) {
8702
8707
  const retryTechStack = retryParsed.tech_stack;
8703
8708
  const retryViolation = retryTechStack ? detectTechStackViolation(retryTechStack, techConstraintDecisions) : null;
8704
8709
  if (!retryViolation) {
8705
- logger$2.info("Retry produced compliant tech stack — using corrected output");
8710
+ logger$3.info("Retry produced compliant tech stack — using corrected output");
8706
8711
  nfrsOutput = retryParsed;
8707
- } else logger$2.warn({ retryViolation }, "Retry still violates constraints — using original output");
8708
- } else logger$2.warn("Retry dispatch failed — using original output");
8712
+ } else logger$3.warn({ retryViolation }, "Retry still violates constraints — using original output");
8713
+ } else logger$3.warn("Retry dispatch failed — using original output");
8709
8714
  }
8710
8715
  }
8711
8716
  const frs = frsOutput.functional_requirements;
@@ -8992,7 +8997,7 @@ const ReadinessOutputSchema = z.object({
8992
8997
 
8993
8998
  //#endregion
8994
8999
  //#region src/modules/phase-orchestrator/phases/solutioning.ts
8995
- const logger$1 = createLogger("solutioning");
9000
+ const logger$2 = createLogger("solutioning");
8996
9001
  /** Base token budget for architecture generation (covers template + requirements) */
8997
9002
  const BASE_ARCH_PROMPT_TOKENS = 3e3;
8998
9003
  /** Base token budget for story generation (covers template + requirements + architecture) */
@@ -9401,7 +9406,7 @@ async function runReadinessCheck(deps, runId) {
9401
9406
  input: tokenEstimate.input,
9402
9407
  output: tokenEstimate.output
9403
9408
  };
9404
- logger$1.info({
9409
+ logger$2.info({
9405
9410
  runId,
9406
9411
  durationMs: dispatchResult.durationMs,
9407
9412
  tokens: tokenEstimate
@@ -9662,7 +9667,7 @@ async function runSolutioningPhase(deps, params) {
9662
9667
  let archResult;
9663
9668
  if (existingArchArtifact) {
9664
9669
  const existingDecisions = getDecisionsByPhaseForRun(deps.db, params.runId, "solutioning").filter((d) => d.category === "architecture");
9665
- logger$1.info({
9670
+ logger$2.info({
9666
9671
  runId: params.runId,
9667
9672
  artifactId: existingArchArtifact.id,
9668
9673
  decisionCount: existingDecisions.length
@@ -9693,7 +9698,7 @@ async function runSolutioningPhase(deps, params) {
9693
9698
  output: totalOutput
9694
9699
  }
9695
9700
  };
9696
- logger$1.info({
9701
+ logger$2.info({
9697
9702
  runId: params.runId,
9698
9703
  decisionCount: archResult.decisions.length,
9699
9704
  mode: hasSteps ? "multi-step" : "single-dispatch"
@@ -9715,7 +9720,7 @@ async function runSolutioningPhase(deps, params) {
9715
9720
  totalInput += readinessResult.tokenUsage.input;
9716
9721
  totalOutput += readinessResult.tokenUsage.output;
9717
9722
  if (readinessResult.verdict === "error") {
9718
- logger$1.error({
9723
+ logger$2.error({
9719
9724
  runId: params.runId,
9720
9725
  error: readinessResult.error
9721
9726
  }, "Readiness check agent failed");
@@ -9731,7 +9736,7 @@ async function runSolutioningPhase(deps, params) {
9731
9736
  }
9732
9737
  };
9733
9738
  }
9734
- logger$1.info({
9739
+ logger$2.info({
9735
9740
  runId: params.runId,
9736
9741
  verdict: readinessResult.verdict,
9737
9742
  coverageScore: readinessResult.coverageScore,
@@ -9747,7 +9752,7 @@ async function runSolutioningPhase(deps, params) {
9747
9752
  key: `finding-${i + 1}`,
9748
9753
  value: JSON.stringify(finding)
9749
9754
  });
9750
- logger$1.error({
9755
+ logger$2.error({
9751
9756
  runId: params.runId,
9752
9757
  verdict: "NOT_READY",
9753
9758
  coverageScore: readinessResult.coverageScore,
@@ -9813,7 +9818,7 @@ async function runSolutioningPhase(deps, params) {
9813
9818
  "",
9814
9819
  "Please generate additional or revised stories to specifically address each blocker above."
9815
9820
  ].join("\n");
9816
- logger$1.info({
9821
+ logger$2.info({
9817
9822
  runId: params.runId,
9818
9823
  blockerCount: blockers.length
9819
9824
  }, "Readiness NEEDS_WORK with blockers — retrying story generation with gap analysis");
@@ -9852,7 +9857,7 @@ async function runSolutioningPhase(deps, params) {
9852
9857
  };
9853
9858
  if (retryReadiness.verdict === "NOT_READY" || retryReadiness.verdict === "NEEDS_WORK") {
9854
9859
  const retryBlockers = retryReadiness.findings.filter((f) => f.severity === "blocker");
9855
- logger$1.error({
9860
+ logger$2.error({
9856
9861
  runId: params.runId,
9857
9862
  verdict: retryReadiness.verdict,
9858
9863
  retryBlockers: retryBlockers.length
@@ -9876,7 +9881,7 @@ async function runSolutioningPhase(deps, params) {
9876
9881
  }
9877
9882
  const retryStories = retryResult.epics.reduce((sum, epic) => sum + epic.stories.length, 0);
9878
9883
  const minorFindings$1 = retryReadiness.findings.filter((f) => f.severity === "minor");
9879
- if (minorFindings$1.length > 0) logger$1.warn({
9884
+ if (minorFindings$1.length > 0) logger$2.warn({
9880
9885
  runId: params.runId,
9881
9886
  minorFindings: minorFindings$1
9882
9887
  }, "Readiness READY with minor findings after retry");
@@ -9905,7 +9910,7 @@ async function runSolutioningPhase(deps, params) {
9905
9910
  };
9906
9911
  }
9907
9912
  const majorFindings = readinessResult.findings.filter((f) => f.severity === "major");
9908
- logger$1.warn({
9913
+ logger$2.warn({
9909
9914
  runId: params.runId,
9910
9915
  majorCount: majorFindings.length,
9911
9916
  findings: readinessResult.findings
@@ -9921,7 +9926,7 @@ async function runSolutioningPhase(deps, params) {
9921
9926
  const minorFindings = readinessResult.findings.filter((f) => f.severity === "minor");
9922
9927
  if (minorFindings.length > 0) {
9923
9928
  const verdictLabel = readinessResult.verdict === "READY" ? "READY" : "NEEDS_WORK (no blockers)";
9924
- logger$1.warn({
9929
+ logger$2.warn({
9925
9930
  runId: params.runId,
9926
9931
  verdict: readinessResult.verdict,
9927
9932
  minorFindings
@@ -10332,6 +10337,268 @@ async function runResearchPhase(deps, params) {
10332
10337
  }
10333
10338
  }
10334
10339
 
10340
+ //#endregion
10341
+ //#region src/cli/commands/health.ts
10342
+ const logger$1 = createLogger("health-cmd");
10343
+ /** Default stall threshold in seconds — also used by supervisor default */
10344
+ const DEFAULT_STALL_THRESHOLD_SECONDS = 600;
10345
+ /**
10346
+ * Determine whether a ps output line represents the substrate pipeline orchestrator.
10347
+ * Handles invocation via:
10348
+ * - `substrate run` (globally installed)
10349
+ * - `substrate-ai run`
10350
+ * - `node dist/cli/index.js run` (npm run substrate:dev)
10351
+ * - `npx substrate run`
10352
+ * - any node process whose command contains `run` with `--events` or `--stories`
10353
+ *
10354
+ * When `projectRoot` is provided, additionally checks that the command line
10355
+ * contains that path (via `--project-root` flag or as part of the binary/CWD path).
10356
+ * This ensures multi-project environments match the correct orchestrator.
10357
+ */
10358
+ function isOrchestratorProcessLine(line, projectRoot) {
10359
+ if (line.includes("grep")) return false;
10360
+ let isOrchestrator = false;
10361
+ if (line.includes("substrate run")) isOrchestrator = true;
10362
+ else if (line.includes("substrate-ai run")) isOrchestrator = true;
10363
+ else if (line.includes("index.js run")) isOrchestrator = true;
10364
+ else if (line.includes("node") && /\srun(\s|$)/.test(line) && (line.includes("--events") || line.includes("--stories"))) isOrchestrator = true;
10365
+ if (!isOrchestrator) return false;
10366
+ if (projectRoot !== void 0) return line.includes(projectRoot);
10367
+ return true;
10368
+ }
10369
+ function inspectProcessTree(opts) {
10370
+ const { projectRoot, execFileSync: execFileSyncOverride } = opts ?? {};
10371
+ const result = {
10372
+ orchestrator_pid: null,
10373
+ child_pids: [],
10374
+ zombies: []
10375
+ };
10376
+ try {
10377
+ let psOutput;
10378
+ if (execFileSyncOverride !== void 0) psOutput = execFileSyncOverride("ps", ["-eo", "pid,ppid,stat,command"], {
10379
+ encoding: "utf-8",
10380
+ timeout: 5e3
10381
+ });
10382
+ else {
10383
+ const { execFileSync } = __require("node:child_process");
10384
+ psOutput = execFileSync("ps", ["-eo", "pid,ppid,stat,command"], {
10385
+ encoding: "utf-8",
10386
+ timeout: 5e3
10387
+ });
10388
+ }
10389
+ const lines = psOutput.split("\n");
10390
+ for (const line of lines) if (isOrchestratorProcessLine(line, projectRoot)) {
10391
+ const match = line.trim().match(/^(\d+)/);
10392
+ if (match) {
10393
+ result.orchestrator_pid = parseInt(match[1], 10);
10394
+ break;
10395
+ }
10396
+ }
10397
+ if (result.orchestrator_pid !== null) for (const line of lines) {
10398
+ const parts = line.trim().split(/\s+/);
10399
+ if (parts.length >= 3) {
10400
+ const pid = parseInt(parts[0], 10);
10401
+ const ppid = parseInt(parts[1], 10);
10402
+ const stat$2 = parts[2];
10403
+ if (ppid === result.orchestrator_pid && pid !== result.orchestrator_pid) {
10404
+ result.child_pids.push(pid);
10405
+ if (stat$2.includes("Z")) result.zombies.push(pid);
10406
+ }
10407
+ }
10408
+ }
10409
+ } catch {}
10410
+ return result;
10411
+ }
10412
+ /**
10413
+ * Collect all descendant PIDs of the given root PIDs by walking the process
10414
+ * tree recursively. This ensures that grandchildren of the orchestrator
10415
+ * (e.g. node subprocesses spawned by `claude -p`) are also killed during
10416
+ * stall recovery, leaving no orphan processes.
10417
+ *
10418
+ * Returns only the descendants — the root PIDs themselves are NOT included.
10419
+ */
10420
+ function getAllDescendantPids(rootPids, execFileSyncOverride) {
10421
+ if (rootPids.length === 0) return [];
10422
+ try {
10423
+ let psOutput;
10424
+ if (execFileSyncOverride !== void 0) psOutput = execFileSyncOverride("ps", ["-eo", "pid,ppid"], {
10425
+ encoding: "utf-8",
10426
+ timeout: 5e3
10427
+ });
10428
+ else {
10429
+ const { execFileSync } = __require("node:child_process");
10430
+ psOutput = execFileSync("ps", ["-eo", "pid,ppid"], {
10431
+ encoding: "utf-8",
10432
+ timeout: 5e3
10433
+ });
10434
+ }
10435
+ const childrenOf = new Map();
10436
+ for (const line of psOutput.split("\n")) {
10437
+ const parts = line.trim().split(/\s+/);
10438
+ if (parts.length >= 2) {
10439
+ const pid = parseInt(parts[0], 10);
10440
+ const ppid = parseInt(parts[1], 10);
10441
+ if (!isNaN(pid) && !isNaN(ppid) && pid > 0) {
10442
+ if (!childrenOf.has(ppid)) childrenOf.set(ppid, []);
10443
+ childrenOf.get(ppid).push(pid);
10444
+ }
10445
+ }
10446
+ }
10447
+ const descendants = [];
10448
+ const seen = new Set(rootPids);
10449
+ const queue = [...rootPids];
10450
+ while (queue.length > 0) {
10451
+ const current = queue.shift();
10452
+ const children = childrenOf.get(current) ?? [];
10453
+ for (const child of children) if (!seen.has(child)) {
10454
+ seen.add(child);
10455
+ descendants.push(child);
10456
+ queue.push(child);
10457
+ }
10458
+ }
10459
+ return descendants;
10460
+ } catch {
10461
+ return [];
10462
+ }
10463
+ }
10464
+ /**
10465
+ * Fetch pipeline health data as a structured object without any stdout side-effects.
10466
+ * Used by runSupervisorAction to poll health without formatting overhead.
10467
+ *
10468
+ * Returns a NO_PIPELINE_RUNNING health object for all graceful "no data" cases
10469
+ * (missing DB, missing run, terminal run status). Throws only on unexpected errors.
10470
+ */
10471
+ async function getAutoHealthData(options) {
10472
+ const { runId, projectRoot } = options;
10473
+ const dbRoot = await resolveMainRepoRoot(projectRoot);
10474
+ const dbPath = join(dbRoot, ".substrate", "substrate.db");
10475
+ const NO_PIPELINE = {
10476
+ verdict: "NO_PIPELINE_RUNNING",
10477
+ run_id: null,
10478
+ status: null,
10479
+ current_phase: null,
10480
+ staleness_seconds: 0,
10481
+ last_activity: "",
10482
+ process: {
10483
+ orchestrator_pid: null,
10484
+ child_pids: [],
10485
+ zombies: []
10486
+ },
10487
+ stories: {
10488
+ active: 0,
10489
+ completed: 0,
10490
+ escalated: 0,
10491
+ details: {}
10492
+ }
10493
+ };
10494
+ if (!existsSync(dbPath)) return NO_PIPELINE;
10495
+ const dbWrapper = new DatabaseWrapper(dbPath);
10496
+ try {
10497
+ dbWrapper.open();
10498
+ const db = dbWrapper.db;
10499
+ let run;
10500
+ if (runId !== void 0) run = getPipelineRunById(db, runId);
10501
+ else run = getLatestRun(db);
10502
+ if (run === void 0) return NO_PIPELINE;
10503
+ const updatedAt = parseDbTimestampAsUtc(run.updated_at);
10504
+ const stalenessSeconds = Math.round((Date.now() - updatedAt.getTime()) / 1e3);
10505
+ let storyDetails = {};
10506
+ let active = 0;
10507
+ let completed = 0;
10508
+ let escalated = 0;
10509
+ try {
10510
+ if (run.token_usage_json) {
10511
+ const state = JSON.parse(run.token_usage_json);
10512
+ if (state.stories) for (const [key, s] of Object.entries(state.stories)) {
10513
+ storyDetails[key] = {
10514
+ phase: s.phase,
10515
+ review_cycles: s.reviewCycles
10516
+ };
10517
+ if (s.phase === "COMPLETE") completed++;
10518
+ else if (s.phase === "ESCALATED") escalated++;
10519
+ else if (s.phase !== "PENDING") active++;
10520
+ }
10521
+ }
10522
+ } catch {}
10523
+ const processInfo = inspectProcessTree({ projectRoot });
10524
+ let verdict = "NO_PIPELINE_RUNNING";
10525
+ if (run.status === "running") if (processInfo.orchestrator_pid === null && active === 0 && completed > 0) verdict = "NO_PIPELINE_RUNNING";
10526
+ else if (processInfo.zombies.length > 0) verdict = "STALLED";
10527
+ else if (processInfo.orchestrator_pid !== null && processInfo.child_pids.length > 0 && stalenessSeconds > DEFAULT_STALL_THRESHOLD_SECONDS) verdict = "HEALTHY";
10528
+ else if (stalenessSeconds > DEFAULT_STALL_THRESHOLD_SECONDS) verdict = "STALLED";
10529
+ else if (processInfo.orchestrator_pid !== null && processInfo.child_pids.length === 0 && active > 0) verdict = "STALLED";
10530
+ else verdict = "HEALTHY";
10531
+ else if (run.status === "completed" || run.status === "failed" || run.status === "stopped") verdict = "NO_PIPELINE_RUNNING";
10532
+ return {
10533
+ verdict,
10534
+ run_id: run.id,
10535
+ status: run.status,
10536
+ current_phase: run.current_phase,
10537
+ staleness_seconds: stalenessSeconds,
10538
+ last_activity: run.updated_at,
10539
+ process: processInfo,
10540
+ stories: {
10541
+ active,
10542
+ completed,
10543
+ escalated,
10544
+ details: storyDetails
10545
+ }
10546
+ };
10547
+ } finally {
10548
+ try {
10549
+ dbWrapper.close();
10550
+ } catch {}
10551
+ }
10552
+ }
10553
+ async function runHealthAction(options) {
10554
+ const { outputFormat } = options;
10555
+ try {
10556
+ const health = await getAutoHealthData(options);
10557
+ if (outputFormat === "json") process.stdout.write(formatOutput(health, "json", true) + "\n");
10558
+ else {
10559
+ const verdictLabel = health.verdict === "HEALTHY" ? "HEALTHY" : health.verdict === "STALLED" ? "STALLED" : "NO PIPELINE RUNNING";
10560
+ process.stdout.write(`\nPipeline Health: ${verdictLabel}\n`);
10561
+ if (health.run_id !== null) {
10562
+ process.stdout.write(` Run: ${health.run_id}\n`);
10563
+ process.stdout.write(` Status: ${health.status}\n`);
10564
+ process.stdout.write(` Phase: ${health.current_phase ?? "N/A"}\n`);
10565
+ process.stdout.write(` Last Active: ${health.last_activity} (${health.staleness_seconds}s ago)\n`);
10566
+ const processInfo = health.process;
10567
+ if (processInfo.orchestrator_pid !== null) {
10568
+ process.stdout.write(` Orchestrator: PID ${processInfo.orchestrator_pid}\n`);
10569
+ process.stdout.write(` Children: ${processInfo.child_pids.length} active`);
10570
+ if (processInfo.zombies.length > 0) process.stdout.write(` (${processInfo.zombies.length} ZOMBIE)`);
10571
+ process.stdout.write("\n");
10572
+ } else process.stdout.write(" Orchestrator: not running\n");
10573
+ const storyDetails = health.stories.details;
10574
+ if (Object.keys(storyDetails).length > 0) {
10575
+ process.stdout.write("\n Stories:\n");
10576
+ for (const [key, s] of Object.entries(storyDetails)) process.stdout.write(` ${key}: ${s.phase} (${s.review_cycles} review cycles)\n`);
10577
+ process.stdout.write(`\n Summary: ${health.stories.active} active, ${health.stories.completed} completed, ${health.stories.escalated} escalated\n`);
10578
+ }
10579
+ }
10580
+ }
10581
+ return 0;
10582
+ } catch (err) {
10583
+ const msg = err instanceof Error ? err.message : String(err);
10584
+ if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
10585
+ else process.stderr.write(`Error: ${msg}\n`);
10586
+ logger$1.error({ err }, "health action failed");
10587
+ return 1;
10588
+ }
10589
+ }
10590
+ function registerHealthCommand(program, _version = "0.0.0", projectRoot = process.cwd()) {
10591
+ program.command("health").description("Check pipeline health: process status, stall detection, and verdict").option("--run-id <id>", "Pipeline run ID to query (defaults to latest)").option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").action(async (opts) => {
10592
+ const outputFormat = opts.outputFormat === "json" ? "json" : "human";
10593
+ const exitCode = await runHealthAction({
10594
+ outputFormat,
10595
+ runId: opts.runId,
10596
+ projectRoot: opts.projectRoot
10597
+ });
10598
+ process.exitCode = exitCode;
10599
+ });
10600
+ }
10601
+
10335
10602
  //#endregion
10336
10603
  //#region src/cli/commands/run.ts
10337
10604
  const logger = createLogger("run-cmd");
@@ -10478,6 +10745,16 @@ async function runRunAction(options) {
10478
10745
  return 0;
10479
10746
  }
10480
10747
  }
10748
+ const staleRuns = getRunningPipelineRuns(db) ?? [];
10749
+ if (staleRuns.length > 0) {
10750
+ const processInfo = inspectProcessTree({ projectRoot });
10751
+ let swept = 0;
10752
+ for (const stale of staleRuns) if (processInfo.orchestrator_pid === null) {
10753
+ updatePipelineRun(db, stale.id, { status: "failed" });
10754
+ swept++;
10755
+ }
10756
+ if (swept > 0) process.stderr.write(`Swept ${swept} stale pipeline run(s) (dead orchestrator)\n`);
10757
+ }
10481
10758
  const pipelineRun = createPipelineRun(db, {
10482
10759
  methodology: pack.manifest.name,
10483
10760
  start_phase: "implementation",
@@ -11195,5 +11472,5 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
11195
11472
  }
11196
11473
 
11197
11474
  //#endregion
11198
- export { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
11199
- //# sourceMappingURL=run-BrI2xzk7.js.map
11475
+ export { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
11476
+ //# sourceMappingURL=run-CLpXJNQ8.js.map