substrate-ai 0.2.15 → 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-DNYByk0U.js";
4
- import { aggregateTokenUsageForRun, aggregateTokenUsageForStory, getStoryMetricsForRun, writeRunMetrics, writeStoryMetrics } from "./metrics-BSg8VIHd.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
+ 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;
@@ -5371,6 +5376,7 @@ function createImplementationOrchestrator(deps) {
5371
5376
  const HEARTBEAT_INTERVAL_MS = 3e4;
5372
5377
  const WATCHDOG_TIMEOUT_MS = 6e5;
5373
5378
  const _stalledStories = new Set();
5379
+ const _storiesWithStall = new Set();
5374
5380
  const _phaseStartMs = new Map();
5375
5381
  const _phaseEndMs = new Map();
5376
5382
  const _storyDispatches = new Map();
@@ -5394,7 +5400,7 @@ function createImplementationOrchestrator(deps) {
5394
5400
  const nowMs = Date.now();
5395
5401
  for (const [phase, startMs] of starts) {
5396
5402
  const endMs = ends?.get(phase);
5397
- if (endMs === void 0) logger$16.warn({
5403
+ if (endMs === void 0) logger$17.warn({
5398
5404
  storyKey,
5399
5405
  phase
5400
5406
  }, "Phase has no end time — story may have errored mid-phase. Duration capped to now() and may be inflated.");
@@ -5424,8 +5430,30 @@ function createImplementationOrchestrator(deps) {
5424
5430
  review_cycles: reviewCycles,
5425
5431
  dispatches: _storyDispatches.get(storyKey) ?? 0
5426
5432
  });
5433
+ try {
5434
+ const runId = config.pipelineRunId ?? "unknown";
5435
+ createDecision(db, {
5436
+ pipeline_run_id: config.pipelineRunId,
5437
+ phase: "implementation",
5438
+ category: STORY_METRICS,
5439
+ key: `${storyKey}:${runId}`,
5440
+ value: JSON.stringify({
5441
+ wall_clock_seconds: wallClockSeconds,
5442
+ input_tokens: tokenAgg.input,
5443
+ output_tokens: tokenAgg.output,
5444
+ review_cycles: reviewCycles,
5445
+ stalled: _storiesWithStall.has(storyKey)
5446
+ }),
5447
+ rationale: `Story ${storyKey} completed with result=${result} in ${wallClockSeconds}s. Tokens: ${tokenAgg.input}+${tokenAgg.output}. Review cycles: ${reviewCycles}.`
5448
+ });
5449
+ } catch (decisionErr) {
5450
+ logger$17.warn({
5451
+ err: decisionErr,
5452
+ storyKey
5453
+ }, "Failed to write story-metrics decision (best-effort)");
5454
+ }
5427
5455
  } catch (err) {
5428
- logger$16.warn({
5456
+ logger$17.warn({
5429
5457
  err,
5430
5458
  storyKey
5431
5459
  }, "Failed to write story metrics (best-effort)");
@@ -5461,7 +5489,7 @@ function createImplementationOrchestrator(deps) {
5461
5489
  token_usage_json: serialized
5462
5490
  });
5463
5491
  } catch (err) {
5464
- logger$16.warn("Failed to persist orchestrator state", { err });
5492
+ logger$17.warn("Failed to persist orchestrator state", { err });
5465
5493
  }
5466
5494
  }
5467
5495
  function recordProgress() {
@@ -5490,7 +5518,8 @@ function createImplementationOrchestrator(deps) {
5490
5518
  for (const [key, s] of _stories) if (s.phase !== "PENDING" && s.phase !== "COMPLETE" && s.phase !== "ESCALATED") {
5491
5519
  if (_stalledStories.has(key)) continue;
5492
5520
  _stalledStories.add(key);
5493
- logger$16.warn({
5521
+ _storiesWithStall.add(key);
5522
+ logger$17.warn({
5494
5523
  storyKey: key,
5495
5524
  phase: s.phase,
5496
5525
  elapsedMs: elapsed
@@ -5527,7 +5556,7 @@ function createImplementationOrchestrator(deps) {
5527
5556
  * exhausted retries the story is ESCALATED.
5528
5557
  */
5529
5558
  async function processStory(storyKey) {
5530
- logger$16.info("Processing story", { storyKey });
5559
+ logger$17.info("Processing story", { storyKey });
5531
5560
  await waitIfPaused();
5532
5561
  if (_state !== "RUNNING") return;
5533
5562
  startPhase(storyKey, "create-story");
@@ -5542,7 +5571,7 @@ function createImplementationOrchestrator(deps) {
5542
5571
  const match = files.find((f) => f.startsWith(`${storyKey}-`) && f.endsWith(".md"));
5543
5572
  if (match) {
5544
5573
  storyFilePath = join$1(artifactsDir, match);
5545
- logger$16.info({
5574
+ logger$17.info({
5546
5575
  storyKey,
5547
5576
  storyFilePath
5548
5577
  }, "Found existing story file — skipping create-story");
@@ -5643,7 +5672,7 @@ function createImplementationOrchestrator(deps) {
5643
5672
  try {
5644
5673
  storyContentForAnalysis = await readFile$1(storyFilePath ?? "", "utf-8");
5645
5674
  } catch (err) {
5646
- logger$16.error({
5675
+ logger$17.error({
5647
5676
  storyKey,
5648
5677
  storyFilePath,
5649
5678
  error: err instanceof Error ? err.message : String(err)
@@ -5651,7 +5680,7 @@ function createImplementationOrchestrator(deps) {
5651
5680
  }
5652
5681
  const analysis = analyzeStoryComplexity(storyContentForAnalysis);
5653
5682
  const batches = planTaskBatches(analysis);
5654
- logger$16.info({
5683
+ logger$17.info({
5655
5684
  storyKey,
5656
5685
  estimatedScope: analysis.estimatedScope,
5657
5686
  batchCount: batches.length,
@@ -5669,7 +5698,7 @@ function createImplementationOrchestrator(deps) {
5669
5698
  if (_state !== "RUNNING") break;
5670
5699
  const taskScope = batch.taskIds.map((id, i) => `T${id}: ${batch.taskTitles[i] ?? ""}`).join("\n");
5671
5700
  const priorFiles = allFilesModified.size > 0 ? Array.from(allFilesModified) : void 0;
5672
- logger$16.info({
5701
+ logger$17.info({
5673
5702
  storyKey,
5674
5703
  batchIndex: batch.batchIndex,
5675
5704
  taskCount: batch.taskIds.length
@@ -5693,7 +5722,7 @@ function createImplementationOrchestrator(deps) {
5693
5722
  });
5694
5723
  } catch (batchErr) {
5695
5724
  const errMsg = batchErr instanceof Error ? batchErr.message : String(batchErr);
5696
- logger$16.warn({
5725
+ logger$17.warn({
5697
5726
  storyKey,
5698
5727
  batchIndex: batch.batchIndex,
5699
5728
  error: errMsg
@@ -5713,7 +5742,7 @@ function createImplementationOrchestrator(deps) {
5713
5742
  filesModified: batchFilesModified,
5714
5743
  result: batchResult.result === "success" ? "success" : "failed"
5715
5744
  };
5716
- logger$16.info(batchMetrics, "Batch dev-story metrics");
5745
+ logger$17.info(batchMetrics, "Batch dev-story metrics");
5717
5746
  for (const f of batchFilesModified) allFilesModified.add(f);
5718
5747
  if (batchFilesModified.length > 0) batchFileGroups.push({
5719
5748
  batchIndex: batch.batchIndex,
@@ -5735,13 +5764,13 @@ function createImplementationOrchestrator(deps) {
5735
5764
  })
5736
5765
  });
5737
5766
  } catch (tokenErr) {
5738
- logger$16.warn({
5767
+ logger$17.warn({
5739
5768
  storyKey,
5740
5769
  batchIndex: batch.batchIndex,
5741
5770
  err: tokenErr
5742
5771
  }, "Failed to record batch token usage");
5743
5772
  }
5744
- if (batchResult.result === "failed") logger$16.warn({
5773
+ if (batchResult.result === "failed") logger$17.warn({
5745
5774
  storyKey,
5746
5775
  batchIndex: batch.batchIndex,
5747
5776
  error: batchResult.error
@@ -5774,7 +5803,7 @@ function createImplementationOrchestrator(deps) {
5774
5803
  result: devResult
5775
5804
  });
5776
5805
  persistState();
5777
- 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", {
5778
5807
  storyKey,
5779
5808
  error: devResult.error,
5780
5809
  filesModified: devFilesModified.length
@@ -5831,7 +5860,7 @@ function createImplementationOrchestrator(deps) {
5831
5860
  "NEEDS_MAJOR_REWORK": 2
5832
5861
  };
5833
5862
  for (const group of batchFileGroups) {
5834
- logger$16.info({
5863
+ logger$17.info({
5835
5864
  storyKey,
5836
5865
  batchIndex: group.batchIndex,
5837
5866
  fileCount: group.files.length
@@ -5868,7 +5897,7 @@ function createImplementationOrchestrator(deps) {
5868
5897
  rawOutput: lastRawOutput,
5869
5898
  tokenUsage: aggregateTokens
5870
5899
  };
5871
- logger$16.info({
5900
+ logger$17.info({
5872
5901
  storyKey,
5873
5902
  batchCount: batchFileGroups.length,
5874
5903
  verdict: worstVerdict,
@@ -5894,7 +5923,7 @@ function createImplementationOrchestrator(deps) {
5894
5923
  const isPhantomReview = reviewResult.verdict !== "SHIP_IT" && (reviewResult.issue_list === void 0 || reviewResult.issue_list.length === 0) && reviewResult.error !== void 0;
5895
5924
  if (isPhantomReview && !timeoutRetried) {
5896
5925
  timeoutRetried = true;
5897
- logger$16.warn({
5926
+ logger$17.warn({
5898
5927
  storyKey,
5899
5928
  reviewCycles,
5900
5929
  error: reviewResult.error
@@ -5904,7 +5933,7 @@ function createImplementationOrchestrator(deps) {
5904
5933
  verdict = reviewResult.verdict;
5905
5934
  issueList = reviewResult.issue_list ?? [];
5906
5935
  if (verdict === "NEEDS_MAJOR_REWORK" && reviewCycles > 0 && previousIssueList.length > 0 && issueList.length < previousIssueList.length) {
5907
- logger$16.info({
5936
+ logger$17.info({
5908
5937
  storyKey,
5909
5938
  originalVerdict: verdict,
5910
5939
  issuesBefore: previousIssueList.length,
@@ -5940,7 +5969,7 @@ function createImplementationOrchestrator(deps) {
5940
5969
  if (_decomposition !== void 0) parts.push(`decomposed: ${_decomposition.batchCount} batches`);
5941
5970
  parts.push(`${fileCount} files`);
5942
5971
  parts.push(`${totalTokensK} tokens`);
5943
- logger$16.info({
5972
+ logger$17.info({
5944
5973
  storyKey,
5945
5974
  verdict,
5946
5975
  agentVerdict: reviewResult.agentVerdict
@@ -5998,7 +6027,7 @@ function createImplementationOrchestrator(deps) {
5998
6027
  persistState();
5999
6028
  return;
6000
6029
  }
6001
- logger$16.info({
6030
+ logger$17.info({
6002
6031
  storyKey,
6003
6032
  reviewCycles: finalReviewCycles,
6004
6033
  issueCount: issueList.length
@@ -6048,7 +6077,7 @@ function createImplementationOrchestrator(deps) {
6048
6077
  fixPrompt = assembled.prompt;
6049
6078
  } catch {
6050
6079
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, minor fixes needed`;
6051
- 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 });
6052
6081
  }
6053
6082
  const handle = dispatcher.dispatch({
6054
6083
  prompt: fixPrompt,
@@ -6065,9 +6094,9 @@ function createImplementationOrchestrator(deps) {
6065
6094
  output: fixResult.tokenEstimate.output
6066
6095
  } : void 0 }
6067
6096
  });
6068
- 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 });
6069
6098
  } catch (err) {
6070
- 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)", {
6071
6100
  storyKey,
6072
6101
  err
6073
6102
  });
@@ -6139,7 +6168,7 @@ function createImplementationOrchestrator(deps) {
6139
6168
  fixPrompt = assembled.prompt;
6140
6169
  } catch {
6141
6170
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, taskType=${taskType}`;
6142
- logger$16.warn("Failed to assemble fix prompt, using fallback", {
6171
+ logger$17.warn("Failed to assemble fix prompt, using fallback", {
6143
6172
  storyKey,
6144
6173
  taskType
6145
6174
  });
@@ -6162,7 +6191,7 @@ function createImplementationOrchestrator(deps) {
6162
6191
  } : void 0 }
6163
6192
  });
6164
6193
  if (fixResult.status === "timeout") {
6165
- logger$16.warn("Fix dispatch timed out — escalating story", {
6194
+ logger$17.warn("Fix dispatch timed out — escalating story", {
6166
6195
  storyKey,
6167
6196
  taskType
6168
6197
  });
@@ -6182,13 +6211,13 @@ function createImplementationOrchestrator(deps) {
6182
6211
  persistState();
6183
6212
  return;
6184
6213
  }
6185
- if (fixResult.status === "failed") logger$16.warn("Fix dispatch failed", {
6214
+ if (fixResult.status === "failed") logger$17.warn("Fix dispatch failed", {
6186
6215
  storyKey,
6187
6216
  taskType,
6188
6217
  exitCode: fixResult.exitCode
6189
6218
  });
6190
6219
  } catch (err) {
6191
- logger$16.warn("Fix dispatch failed, continuing to next review", {
6220
+ logger$17.warn("Fix dispatch failed, continuing to next review", {
6192
6221
  storyKey,
6193
6222
  taskType,
6194
6223
  err
@@ -6242,11 +6271,11 @@ function createImplementationOrchestrator(deps) {
6242
6271
  }
6243
6272
  async function run(storyKeys) {
6244
6273
  if (_state === "RUNNING" || _state === "PAUSED") {
6245
- 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 });
6246
6275
  return getStatus();
6247
6276
  }
6248
6277
  if (_state === "COMPLETE") {
6249
- 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 });
6250
6279
  return getStatus();
6251
6280
  }
6252
6281
  _state = "RUNNING";
@@ -6264,13 +6293,13 @@ function createImplementationOrchestrator(deps) {
6264
6293
  if (config.enableHeartbeat) startHeartbeat();
6265
6294
  if (projectRoot !== void 0) {
6266
6295
  const seedResult = seedMethodologyContext(db, projectRoot);
6267
- if (seedResult.decisionsCreated > 0) logger$16.info({
6296
+ if (seedResult.decisionsCreated > 0) logger$17.info({
6268
6297
  decisionsCreated: seedResult.decisionsCreated,
6269
6298
  skippedCategories: seedResult.skippedCategories
6270
6299
  }, "Methodology context seeded from planning artifacts");
6271
6300
  }
6272
6301
  const groups = detectConflictGroups(storyKeys);
6273
- logger$16.info("Orchestrator starting", {
6302
+ logger$17.info("Orchestrator starting", {
6274
6303
  storyCount: storyKeys.length,
6275
6304
  groupCount: groups.length,
6276
6305
  maxConcurrency: config.maxConcurrency
@@ -6282,7 +6311,7 @@ function createImplementationOrchestrator(deps) {
6282
6311
  _state = "FAILED";
6283
6312
  _completedAt = new Date().toISOString();
6284
6313
  persistState();
6285
- logger$16.error("Orchestrator failed with unhandled error", { err });
6314
+ logger$17.error("Orchestrator failed with unhandled error", { err });
6286
6315
  return getStatus();
6287
6316
  }
6288
6317
  stopHeartbeat();
@@ -6309,7 +6338,7 @@ function createImplementationOrchestrator(deps) {
6309
6338
  _pauseGate = createPauseGate();
6310
6339
  _state = "PAUSED";
6311
6340
  eventBus.emit("orchestrator:paused", {});
6312
- logger$16.info("Orchestrator paused");
6341
+ logger$17.info("Orchestrator paused");
6313
6342
  }
6314
6343
  function resume() {
6315
6344
  if (_state !== "PAUSED") return;
@@ -6320,7 +6349,7 @@ function createImplementationOrchestrator(deps) {
6320
6349
  }
6321
6350
  _state = "RUNNING";
6322
6351
  eventBus.emit("orchestrator:resumed", {});
6323
- logger$16.info("Orchestrator resumed");
6352
+ logger$17.info("Orchestrator resumed");
6324
6353
  }
6325
6354
  return {
6326
6355
  run,
@@ -6995,7 +7024,7 @@ const CritiqueOutputSchema = z.object({
6995
7024
 
6996
7025
  //#endregion
6997
7026
  //#region src/modules/phase-orchestrator/critique-loop.ts
6998
- const logger$5 = createLogger("critique-loop");
7027
+ const logger$6 = createLogger("critique-loop");
6999
7028
  /**
7000
7029
  * Maps a phase name to the critique prompt template name.
7001
7030
  * Falls back to `critique-${phase}` for unknown phases.
@@ -7049,7 +7078,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7049
7078
  critiquePrompt = critiqueTemplate.replace("{{artifact_content}}", currentArtifact).replace("{{project_context}}", projectContext);
7050
7079
  } catch (err) {
7051
7080
  const message = err instanceof Error ? err.message : String(err);
7052
- logger$5.warn({
7081
+ logger$6.warn({
7053
7082
  phaseId,
7054
7083
  promptName: critiquePromptName,
7055
7084
  err: message
@@ -7077,7 +7106,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7077
7106
  critiqueTokens.output += result.tokenEstimate.output;
7078
7107
  if (result.status !== "completed" || result.parsed === null) {
7079
7108
  const errMsg = result.parseError ?? `Critique dispatch ended with status '${result.status}'`;
7080
- logger$5.warn({
7109
+ logger$6.warn({
7081
7110
  phaseId,
7082
7111
  iteration: i + 1,
7083
7112
  err: errMsg
@@ -7096,7 +7125,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7096
7125
  lastCritiqueOutput = critiqueOutput;
7097
7126
  } catch (err) {
7098
7127
  const message = err instanceof Error ? err.message : String(err);
7099
- logger$5.warn({
7128
+ logger$6.warn({
7100
7129
  phaseId,
7101
7130
  iteration: i + 1,
7102
7131
  err: message
@@ -7136,14 +7165,14 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7136
7165
  });
7137
7166
  } catch (err) {
7138
7167
  const message = err instanceof Error ? err.message : String(err);
7139
- logger$5.warn({
7168
+ logger$6.warn({
7140
7169
  phaseId,
7141
7170
  iteration: i + 1,
7142
7171
  err: message
7143
7172
  }, "Critique loop: failed to store critique decision — continuing");
7144
7173
  }
7145
7174
  if (critiqueOutput.verdict === "pass") {
7146
- logger$5.info({
7175
+ logger$6.info({
7147
7176
  phaseId,
7148
7177
  iteration: i + 1
7149
7178
  }, "Critique loop: artifact passed critique — loop complete");
@@ -7156,7 +7185,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7156
7185
  totalMs: Date.now() - startMs
7157
7186
  };
7158
7187
  }
7159
- logger$5.info({
7188
+ logger$6.info({
7160
7189
  phaseId,
7161
7190
  iteration: i + 1,
7162
7191
  issueCount: critiqueOutput.issue_count
@@ -7169,7 +7198,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7169
7198
  refinePrompt = refineTemplate.replace("{{original_artifact}}", currentArtifact).replace("{{critique_issues}}", issuesText).replace("{{phase_context}}", phaseContext);
7170
7199
  } catch (err) {
7171
7200
  const message = err instanceof Error ? err.message : String(err);
7172
- logger$5.warn({
7201
+ logger$6.warn({
7173
7202
  phaseId,
7174
7203
  iteration: i + 1,
7175
7204
  err: message
@@ -7190,7 +7219,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7190
7219
  const originalLength = currentArtifact.length;
7191
7220
  const refinedLength = refineResult.output.length;
7192
7221
  const delta = refinedLength - originalLength;
7193
- logger$5.info({
7222
+ logger$6.info({
7194
7223
  phaseId,
7195
7224
  iteration: i + 1,
7196
7225
  originalLength,
@@ -7199,7 +7228,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7199
7228
  }, "Critique loop: refinement complete");
7200
7229
  currentArtifact = refineResult.output;
7201
7230
  } else {
7202
- logger$5.warn({
7231
+ logger$6.warn({
7203
7232
  phaseId,
7204
7233
  iteration: i + 1,
7205
7234
  status: refineResult.status
@@ -7208,7 +7237,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7208
7237
  }
7209
7238
  } catch (err) {
7210
7239
  const message = err instanceof Error ? err.message : String(err);
7211
- logger$5.warn({
7240
+ logger$6.warn({
7212
7241
  phaseId,
7213
7242
  iteration: i + 1,
7214
7243
  err: message
@@ -7219,12 +7248,12 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7219
7248
  }
7220
7249
  const remainingIssues = lastCritiqueOutput?.issues ?? [];
7221
7250
  if (remainingIssues.length > 0) {
7222
- logger$5.warn({
7251
+ logger$6.warn({
7223
7252
  phaseId,
7224
7253
  maxIterations,
7225
7254
  issueCount: remainingIssues.length
7226
7255
  }, "Critique loop: max iterations reached with unresolved issues");
7227
- for (const issue of remainingIssues) logger$5.warn({
7256
+ for (const issue of remainingIssues) logger$6.warn({
7228
7257
  phaseId,
7229
7258
  severity: issue.severity,
7230
7259
  category: issue.category,
@@ -7243,7 +7272,7 @@ async function runCritiqueLoop(artifact, phaseId, runId, phase, deps, options =
7243
7272
 
7244
7273
  //#endregion
7245
7274
  //#region src/modules/phase-orchestrator/elicitation-selector.ts
7246
- const logger$4 = createLogger("elicitation-selector");
7275
+ const logger$5 = createLogger("elicitation-selector");
7247
7276
  /**
7248
7277
  * Affinity scores (0.0–1.0) for each category per content type.
7249
7278
  *
@@ -7365,10 +7394,10 @@ function loadElicitationMethods() {
7365
7394
  try {
7366
7395
  const content = readFileSync(csvPath, "utf-8");
7367
7396
  const methods = parseMethodsCsv(content);
7368
- logger$4.debug({ count: methods.length }, "Loaded elicitation methods");
7397
+ logger$5.debug({ count: methods.length }, "Loaded elicitation methods");
7369
7398
  return methods;
7370
7399
  } catch (err) {
7371
- logger$4.warn({
7400
+ logger$5.warn({
7372
7401
  csvPath,
7373
7402
  err
7374
7403
  }, "Failed to load elicitation methods CSV");
@@ -7688,7 +7717,7 @@ const ElicitationOutputSchema = z.object({
7688
7717
 
7689
7718
  //#endregion
7690
7719
  //#region src/modules/phase-orchestrator/step-runner.ts
7691
- const logger$3 = createLogger("step-runner");
7720
+ const logger$4 = createLogger("step-runner");
7692
7721
  /**
7693
7722
  * Format an array of decision records into a markdown section for injection.
7694
7723
  *
@@ -7795,7 +7824,7 @@ async function runSteps(steps, deps, runId, phase, params) {
7795
7824
  if (estimatedTokens > budgetTokens) {
7796
7825
  const decisionRefs = step.context.filter((ref) => ref.source.startsWith("decision:"));
7797
7826
  if (decisionRefs.length > 0) {
7798
- logger$3.warn({
7827
+ logger$4.warn({
7799
7828
  step: step.name,
7800
7829
  estimatedTokens,
7801
7830
  budgetTokens
@@ -7822,7 +7851,7 @@ async function runSteps(steps, deps, runId, phase, params) {
7822
7851
  }
7823
7852
  prompt = summarizedPrompt;
7824
7853
  estimatedTokens = Math.ceil(prompt.length / 4);
7825
- if (estimatedTokens <= budgetTokens) logger$3.info({
7854
+ if (estimatedTokens <= budgetTokens) logger$4.info({
7826
7855
  step: step.name,
7827
7856
  estimatedTokens,
7828
7857
  budgetTokens
@@ -8003,7 +8032,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8003
8032
  const critiqueResult = await runCritiqueLoop(artifactContent, phase, runId, phase, deps);
8004
8033
  totalInput += critiqueResult.critiqueTokens.input + critiqueResult.refinementTokens.input;
8005
8034
  totalOutput += critiqueResult.critiqueTokens.output + critiqueResult.refinementTokens.output;
8006
- logger$3.info({
8035
+ logger$4.info({
8007
8036
  step: step.name,
8008
8037
  verdict: critiqueResult.verdict,
8009
8038
  iterations: critiqueResult.iterations,
@@ -8011,7 +8040,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8011
8040
  }, "Step critique loop complete");
8012
8041
  } catch (critiqueErr) {
8013
8042
  const critiqueMsg = critiqueErr instanceof Error ? critiqueErr.message : String(critiqueErr);
8014
- logger$3.warn({
8043
+ logger$4.warn({
8015
8044
  step: step.name,
8016
8045
  err: critiqueMsg
8017
8046
  }, "Step critique loop threw an error — continuing without critique");
@@ -8021,7 +8050,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8021
8050
  const contentType = deriveContentType(phase, step.name);
8022
8051
  const selectedMethods = selectMethods({ content_type: contentType }, usedElicitationMethods);
8023
8052
  if (selectedMethods.length > 0) {
8024
- logger$3.info({
8053
+ logger$4.info({
8025
8054
  step: step.name,
8026
8055
  methods: selectedMethods.map((m) => m.name),
8027
8056
  contentType
@@ -8060,13 +8089,13 @@ async function runSteps(steps, deps, runId, phase, params) {
8060
8089
  key: `${phase}-round-${roundIndex}-insights`,
8061
8090
  value: elicitParsed.insights
8062
8091
  });
8063
- logger$3.info({
8092
+ logger$4.info({
8064
8093
  step: step.name,
8065
8094
  method: method.name,
8066
8095
  roundIndex
8067
8096
  }, "Elicitation insights stored in decision store");
8068
8097
  }
8069
- } else logger$3.warn({
8098
+ } else logger$4.warn({
8070
8099
  step: step.name,
8071
8100
  method: method.name,
8072
8101
  status: elicitResult.status
@@ -8082,7 +8111,7 @@ async function runSteps(steps, deps, runId, phase, params) {
8082
8111
  }
8083
8112
  } catch (elicitErr) {
8084
8113
  const elicitMsg = elicitErr instanceof Error ? elicitErr.message : String(elicitErr);
8085
- logger$3.warn({
8114
+ logger$4.warn({
8086
8115
  step: step.name,
8087
8116
  err: elicitMsg
8088
8117
  }, "Step elicitation threw an error — continuing without elicitation");
@@ -8424,7 +8453,7 @@ async function runAnalysisPhase(deps, params) {
8424
8453
 
8425
8454
  //#endregion
8426
8455
  //#region src/modules/phase-orchestrator/phases/planning.ts
8427
- const logger$2 = createLogger("planning-phase");
8456
+ const logger$3 = createLogger("planning-phase");
8428
8457
  /** Maximum total prompt length in tokens (3,500 tokens × 4 chars/token = 14,000 chars) */
8429
8458
  const MAX_PROMPT_TOKENS = 3500;
8430
8459
  const MAX_PROMPT_CHARS = MAX_PROMPT_TOKENS * 4;
@@ -8651,7 +8680,7 @@ async function runPlanningMultiStep(deps, params) {
8651
8680
  const techConstraintDecisions = allAnalysisDecisions.filter((d) => d.category === "technology-constraints");
8652
8681
  const violation = detectTechStackViolation(techStack, techConstraintDecisions);
8653
8682
  if (violation) {
8654
- 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");
8655
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`;
8656
8685
  const step3Template = await deps.pack.getPrompt("planning-step-3-nfrs");
8657
8686
  const stepOutputs = new Map();
@@ -8678,10 +8707,10 @@ async function runPlanningMultiStep(deps, params) {
8678
8707
  const retryTechStack = retryParsed.tech_stack;
8679
8708
  const retryViolation = retryTechStack ? detectTechStackViolation(retryTechStack, techConstraintDecisions) : null;
8680
8709
  if (!retryViolation) {
8681
- logger$2.info("Retry produced compliant tech stack — using corrected output");
8710
+ logger$3.info("Retry produced compliant tech stack — using corrected output");
8682
8711
  nfrsOutput = retryParsed;
8683
- } else logger$2.warn({ retryViolation }, "Retry still violates constraints — using original output");
8684
- } 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");
8685
8714
  }
8686
8715
  }
8687
8716
  const frs = frsOutput.functional_requirements;
@@ -8968,7 +8997,7 @@ const ReadinessOutputSchema = z.object({
8968
8997
 
8969
8998
  //#endregion
8970
8999
  //#region src/modules/phase-orchestrator/phases/solutioning.ts
8971
- const logger$1 = createLogger("solutioning");
9000
+ const logger$2 = createLogger("solutioning");
8972
9001
  /** Base token budget for architecture generation (covers template + requirements) */
8973
9002
  const BASE_ARCH_PROMPT_TOKENS = 3e3;
8974
9003
  /** Base token budget for story generation (covers template + requirements + architecture) */
@@ -9377,7 +9406,7 @@ async function runReadinessCheck(deps, runId) {
9377
9406
  input: tokenEstimate.input,
9378
9407
  output: tokenEstimate.output
9379
9408
  };
9380
- logger$1.info({
9409
+ logger$2.info({
9381
9410
  runId,
9382
9411
  durationMs: dispatchResult.durationMs,
9383
9412
  tokens: tokenEstimate
@@ -9638,7 +9667,7 @@ async function runSolutioningPhase(deps, params) {
9638
9667
  let archResult;
9639
9668
  if (existingArchArtifact) {
9640
9669
  const existingDecisions = getDecisionsByPhaseForRun(deps.db, params.runId, "solutioning").filter((d) => d.category === "architecture");
9641
- logger$1.info({
9670
+ logger$2.info({
9642
9671
  runId: params.runId,
9643
9672
  artifactId: existingArchArtifact.id,
9644
9673
  decisionCount: existingDecisions.length
@@ -9669,7 +9698,7 @@ async function runSolutioningPhase(deps, params) {
9669
9698
  output: totalOutput
9670
9699
  }
9671
9700
  };
9672
- logger$1.info({
9701
+ logger$2.info({
9673
9702
  runId: params.runId,
9674
9703
  decisionCount: archResult.decisions.length,
9675
9704
  mode: hasSteps ? "multi-step" : "single-dispatch"
@@ -9691,7 +9720,7 @@ async function runSolutioningPhase(deps, params) {
9691
9720
  totalInput += readinessResult.tokenUsage.input;
9692
9721
  totalOutput += readinessResult.tokenUsage.output;
9693
9722
  if (readinessResult.verdict === "error") {
9694
- logger$1.error({
9723
+ logger$2.error({
9695
9724
  runId: params.runId,
9696
9725
  error: readinessResult.error
9697
9726
  }, "Readiness check agent failed");
@@ -9707,7 +9736,7 @@ async function runSolutioningPhase(deps, params) {
9707
9736
  }
9708
9737
  };
9709
9738
  }
9710
- logger$1.info({
9739
+ logger$2.info({
9711
9740
  runId: params.runId,
9712
9741
  verdict: readinessResult.verdict,
9713
9742
  coverageScore: readinessResult.coverageScore,
@@ -9723,7 +9752,7 @@ async function runSolutioningPhase(deps, params) {
9723
9752
  key: `finding-${i + 1}`,
9724
9753
  value: JSON.stringify(finding)
9725
9754
  });
9726
- logger$1.error({
9755
+ logger$2.error({
9727
9756
  runId: params.runId,
9728
9757
  verdict: "NOT_READY",
9729
9758
  coverageScore: readinessResult.coverageScore,
@@ -9789,7 +9818,7 @@ async function runSolutioningPhase(deps, params) {
9789
9818
  "",
9790
9819
  "Please generate additional or revised stories to specifically address each blocker above."
9791
9820
  ].join("\n");
9792
- logger$1.info({
9821
+ logger$2.info({
9793
9822
  runId: params.runId,
9794
9823
  blockerCount: blockers.length
9795
9824
  }, "Readiness NEEDS_WORK with blockers — retrying story generation with gap analysis");
@@ -9828,7 +9857,7 @@ async function runSolutioningPhase(deps, params) {
9828
9857
  };
9829
9858
  if (retryReadiness.verdict === "NOT_READY" || retryReadiness.verdict === "NEEDS_WORK") {
9830
9859
  const retryBlockers = retryReadiness.findings.filter((f) => f.severity === "blocker");
9831
- logger$1.error({
9860
+ logger$2.error({
9832
9861
  runId: params.runId,
9833
9862
  verdict: retryReadiness.verdict,
9834
9863
  retryBlockers: retryBlockers.length
@@ -9852,7 +9881,7 @@ async function runSolutioningPhase(deps, params) {
9852
9881
  }
9853
9882
  const retryStories = retryResult.epics.reduce((sum, epic) => sum + epic.stories.length, 0);
9854
9883
  const minorFindings$1 = retryReadiness.findings.filter((f) => f.severity === "minor");
9855
- if (minorFindings$1.length > 0) logger$1.warn({
9884
+ if (minorFindings$1.length > 0) logger$2.warn({
9856
9885
  runId: params.runId,
9857
9886
  minorFindings: minorFindings$1
9858
9887
  }, "Readiness READY with minor findings after retry");
@@ -9881,7 +9910,7 @@ async function runSolutioningPhase(deps, params) {
9881
9910
  };
9882
9911
  }
9883
9912
  const majorFindings = readinessResult.findings.filter((f) => f.severity === "major");
9884
- logger$1.warn({
9913
+ logger$2.warn({
9885
9914
  runId: params.runId,
9886
9915
  majorCount: majorFindings.length,
9887
9916
  findings: readinessResult.findings
@@ -9897,7 +9926,7 @@ async function runSolutioningPhase(deps, params) {
9897
9926
  const minorFindings = readinessResult.findings.filter((f) => f.severity === "minor");
9898
9927
  if (minorFindings.length > 0) {
9899
9928
  const verdictLabel = readinessResult.verdict === "READY" ? "READY" : "NEEDS_WORK (no blockers)";
9900
- logger$1.warn({
9929
+ logger$2.warn({
9901
9930
  runId: params.runId,
9902
9931
  verdict: readinessResult.verdict,
9903
9932
  minorFindings
@@ -10308,6 +10337,268 @@ async function runResearchPhase(deps, params) {
10308
10337
  }
10309
10338
  }
10310
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
+
10311
10602
  //#endregion
10312
10603
  //#region src/cli/commands/run.ts
10313
10604
  const logger = createLogger("run-cmd");
@@ -10454,6 +10745,16 @@ async function runRunAction(options) {
10454
10745
  return 0;
10455
10746
  }
10456
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
+ }
10457
10758
  const pipelineRun = createPipelineRun(db, {
10458
10759
  methodology: pack.manifest.name,
10459
10760
  start_phase: "implementation",
@@ -11171,5 +11472,5 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
11171
11472
  }
11172
11473
 
11173
11474
  //#endregion
11174
- 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 };
11175
- //# sourceMappingURL=run-CoP8UQU3.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