substrate-ai 0.2.28 → 0.2.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
- import { createLogger } from "./logger-D2fS2ccL.js";
2
- import { createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-DljGJnFF.js";
1
+ import { createLogger, deepMask } from "./logger-D2fS2ccL.js";
2
+ import { CURRENT_CONFIG_FORMAT_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator } from "./config-migrator-DSi8KhQC.js";
3
+ import { ConfigError, ConfigIncompatibleFormatError, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-RL22dYtn.js";
3
4
  import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./decisions-Dq4cAA2L.js";
4
5
  import { ESCALATION_DIAGNOSIS, OPERATIONAL_FINDING, STORY_METRICS, STORY_OUTCOME, TEST_EXPANSION_FINDING, TEST_PLAN, aggregateTokenUsageForRun, aggregateTokenUsageForStory, getStoryMetricsForRun, writeRunMetrics, writeStoryMetrics } from "./operational-CnMlvWqc.js";
5
6
  import { createRequire } from "module";
6
- import { dirname, join } from "path";
7
- import { access, readFile, readdir, stat } from "fs/promises";
7
+ import { dirname, join, resolve } from "path";
8
+ import { access, mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
8
9
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
9
10
  import yaml from "js-yaml";
10
11
  import { createRequire as createRequire$1 } from "node:module";
@@ -14,6 +15,7 @@ import { dirname as dirname$1, join as join$1, resolve as resolve$1 } from "node
14
15
  import BetterSqlite3 from "better-sqlite3";
15
16
  import { fileURLToPath } from "node:url";
16
17
  import { existsSync as existsSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1 } from "node:fs";
18
+ import { homedir } from "os";
17
19
  import { freemem, platform } from "node:os";
18
20
  import { createHash, randomUUID } from "node:crypto";
19
21
  import { readFile as readFile$1, stat as stat$1 } from "node:fs/promises";
@@ -21,6 +23,70 @@ import { readFile as readFile$1, stat as stat$1 } from "node:fs/promises";
21
23
  //#region rolldown:runtime
22
24
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
23
25
 
26
+ //#endregion
27
+ //#region src/modules/config/defaults.ts
28
+ const DEFAULT_CLAUDE_PROVIDER = {
29
+ enabled: false,
30
+ subscription_routing: "auto",
31
+ max_concurrent: 2,
32
+ rate_limit: {
33
+ tokens: 22e4,
34
+ window_seconds: 18e3
35
+ },
36
+ api_key_env: "ANTHROPIC_API_KEY",
37
+ api_billing: false
38
+ };
39
+ const DEFAULT_CODEX_PROVIDER = {
40
+ enabled: false,
41
+ subscription_routing: "api",
42
+ max_concurrent: 2,
43
+ api_key_env: "OPENAI_API_KEY",
44
+ api_billing: true
45
+ };
46
+ const DEFAULT_GEMINI_PROVIDER = {
47
+ enabled: false,
48
+ subscription_routing: "api",
49
+ max_concurrent: 2,
50
+ api_key_env: "GOOGLE_API_KEY",
51
+ api_billing: true
52
+ };
53
+ const DEFAULT_GLOBAL_SETTINGS = {
54
+ log_level: "info",
55
+ max_concurrent_tasks: 4,
56
+ budget_cap_tokens: 0,
57
+ budget_cap_usd: 0
58
+ };
59
+ const DEFAULT_ROUTING_POLICY = {
60
+ default_provider: "claude",
61
+ rules: [
62
+ {
63
+ task_type: "planning",
64
+ preferred_provider: "claude",
65
+ fallback_providers: ["gemini", "codex"]
66
+ },
67
+ {
68
+ task_type: "coding",
69
+ preferred_provider: "claude",
70
+ fallback_providers: ["codex", "gemini"]
71
+ },
72
+ {
73
+ task_type: "review",
74
+ preferred_provider: "claude",
75
+ fallback_providers: ["gemini"]
76
+ }
77
+ ]
78
+ };
79
+ const DEFAULT_CONFIG = {
80
+ config_format_version: "1",
81
+ task_graph_version: "1",
82
+ global: DEFAULT_GLOBAL_SETTINGS,
83
+ providers: {
84
+ claude: DEFAULT_CLAUDE_PROVIDER,
85
+ codex: DEFAULT_CODEX_PROVIDER,
86
+ gemini: DEFAULT_GEMINI_PROVIDER
87
+ }
88
+ };
89
+
24
90
  //#endregion
25
91
  //#region src/utils/git-root.ts
26
92
  /**
@@ -539,7 +605,7 @@ const migration010RunMetrics = {
539
605
 
540
606
  //#endregion
541
607
  //#region src/persistence/migrations/index.ts
542
- const logger$21 = createLogger("persistence:migrations");
608
+ const logger$22 = createLogger("persistence:migrations");
543
609
  const MIGRATIONS = [
544
610
  initialSchemaMigration,
545
611
  costTrackerSchemaMigration,
@@ -557,7 +623,7 @@ const MIGRATIONS = [
557
623
  * Safe to call multiple times — already-applied migrations are skipped.
558
624
  */
559
625
  function runMigrations(db) {
560
- logger$21.info("Starting migration runner");
626
+ logger$22.info("Starting migration runner");
561
627
  db.exec(`
562
628
  CREATE TABLE IF NOT EXISTS schema_migrations (
563
629
  version INTEGER PRIMARY KEY,
@@ -568,12 +634,12 @@ function runMigrations(db) {
568
634
  const appliedVersions = new Set(db.prepare("SELECT version FROM schema_migrations").all().map((row) => row.version));
569
635
  const pending = MIGRATIONS.filter((m) => !appliedVersions.has(m.version)).sort((a, b) => a.version - b.version);
570
636
  if (pending.length === 0) {
571
- logger$21.info("No pending migrations");
637
+ logger$22.info("No pending migrations");
572
638
  return;
573
639
  }
574
640
  const insertMigration = db.prepare("INSERT INTO schema_migrations (version, name) VALUES (?, ?)");
575
641
  for (const migration of pending) {
576
- logger$21.info({
642
+ logger$22.info({
577
643
  version: migration.version,
578
644
  name: migration.name
579
645
  }, "Applying migration");
@@ -587,14 +653,14 @@ function runMigrations(db) {
587
653
  });
588
654
  applyMigration();
589
655
  }
590
- logger$21.info({ version: migration.version }, "Migration applied successfully");
656
+ logger$22.info({ version: migration.version }, "Migration applied successfully");
591
657
  }
592
- logger$21.info({ count: pending.length }, "All pending migrations applied");
658
+ logger$22.info({ count: pending.length }, "All pending migrations applied");
593
659
  }
594
660
 
595
661
  //#endregion
596
662
  //#region src/persistence/database.ts
597
- const logger$20 = createLogger("persistence:database");
663
+ const logger$21 = createLogger("persistence:database");
598
664
  /**
599
665
  * Thin wrapper that opens a SQLite database, applies required PRAGMAs,
600
666
  * and exposes the raw BetterSqlite3 instance.
@@ -611,14 +677,14 @@ var DatabaseWrapper = class {
611
677
  */
612
678
  open() {
613
679
  if (this._db !== null) return;
614
- logger$20.info({ path: this._path }, "Opening SQLite database");
680
+ logger$21.info({ path: this._path }, "Opening SQLite database");
615
681
  this._db = new BetterSqlite3(this._path);
616
682
  const walResult = this._db.pragma("journal_mode = WAL");
617
- if (walResult?.[0]?.journal_mode !== "wal") logger$20.warn({ result: walResult?.[0]?.journal_mode }, "WAL pragma did not return expected \"wal\" — journal_mode may be \"memory\" or unsupported");
683
+ if (walResult?.[0]?.journal_mode !== "wal") logger$21.warn({ result: walResult?.[0]?.journal_mode }, "WAL pragma did not return expected \"wal\" — journal_mode may be \"memory\" or unsupported");
618
684
  this._db.pragma("busy_timeout = 5000");
619
685
  this._db.pragma("synchronous = NORMAL");
620
686
  this._db.pragma("foreign_keys = ON");
621
- logger$20.info({ path: this._path }, "SQLite database opened with WAL mode");
687
+ logger$21.info({ path: this._path }, "SQLite database opened with WAL mode");
622
688
  }
623
689
  /**
624
690
  * Close the database. Idempotent — calling close() when already closed is a no-op.
@@ -627,7 +693,7 @@ var DatabaseWrapper = class {
627
693
  if (this._db === null) return;
628
694
  this._db.close();
629
695
  this._db = null;
630
- logger$20.info({ path: this._path }, "SQLite database closed");
696
+ logger$21.info({ path: this._path }, "SQLite database closed");
631
697
  }
632
698
  /**
633
699
  * Return the raw BetterSqlite3 instance.
@@ -1361,6 +1427,246 @@ function formatPipelineSummary(run, tokenSummary, decisionsCount, storiesCount,
1361
1427
  return lines.join("\n");
1362
1428
  }
1363
1429
 
1430
+ //#endregion
1431
+ //#region src/modules/config/version-utils.ts
1432
+ /**
1433
+ * Check whether a version string is in a list of supported versions.
1434
+ *
1435
+ * @param version - Version string to check
1436
+ * @param supported - List of supported version strings
1437
+ * @returns true if version is in the supported list
1438
+ */
1439
+ function isVersionSupported(version, supported) {
1440
+ return supported.includes(version);
1441
+ }
1442
+ /**
1443
+ * Format the standard "unsupported version" error message.
1444
+ *
1445
+ * @param formatType - 'config' or 'task_graph'
1446
+ * @param version - The unsupported version string found
1447
+ * @param supported - List of supported version strings
1448
+ * @returns Formatted error message string
1449
+ */
1450
+ function formatUnsupportedVersionError(formatType, version, supported) {
1451
+ if (formatType === "config") return `Configuration format version "${version}" is not supported. This toolkit supports: ${supported.join(", ")}. Please upgrade the toolkit: npm install -g substrate@latest`;
1452
+ return `Task graph format version "${version}" is not supported. This toolkit supports: ${supported.join(", ")}. Please upgrade the toolkit: npm install -g substrate@latest`;
1453
+ }
1454
+
1455
+ //#endregion
1456
+ //#region src/modules/config/config-system-impl.ts
1457
+ const logger$20 = createLogger("config");
1458
+ function deepMerge(base, override) {
1459
+ const result = { ...base };
1460
+ for (const [key, val] of Object.entries(override)) if (val !== null && val !== void 0 && typeof val === "object" && !Array.isArray(val) && typeof result[key] === "object" && result[key] !== null && !Array.isArray(result[key])) result[key] = deepMerge(result[key], val);
1461
+ else if (val !== void 0) result[key] = val;
1462
+ return result;
1463
+ }
1464
+ /**
1465
+ * Map of ADT_ environment variable names to config paths.
1466
+ * Only overrides scalar values; does not support nested structures via env.
1467
+ */
1468
+ const ENV_VAR_MAP = {
1469
+ ADT_LOG_LEVEL: "global.log_level",
1470
+ ADT_MAX_CONCURRENT_TASKS: "global.max_concurrent_tasks",
1471
+ ADT_BUDGET_CAP_TOKENS: "global.budget_cap_tokens",
1472
+ ADT_BUDGET_CAP_USD: "global.budget_cap_usd",
1473
+ ADT_WORKSPACE_DIR: "global.workspace_dir",
1474
+ ADT_CLAUDE_ENABLED: "providers.claude.enabled",
1475
+ ADT_CODEX_ENABLED: "providers.codex.enabled",
1476
+ ADT_GEMINI_ENABLED: "providers.gemini.enabled"
1477
+ };
1478
+ /**
1479
+ * Read relevant environment variables and return a partial config overlay.
1480
+ */
1481
+ function readEnvOverrides() {
1482
+ const overrides = {};
1483
+ for (const [envKey, configPath] of Object.entries(ENV_VAR_MAP)) {
1484
+ const rawValue = process.env[envKey];
1485
+ if (rawValue === void 0) continue;
1486
+ const parts = configPath.split(".");
1487
+ let cursor = overrides;
1488
+ for (let i = 0; i < parts.length - 1; i++) {
1489
+ const part = parts[i] ?? "";
1490
+ if (cursor[part] === void 0) cursor[part] = {};
1491
+ cursor = cursor[part];
1492
+ }
1493
+ const lastKey = parts[parts.length - 1] ?? "";
1494
+ if (rawValue === "true") cursor[lastKey] = true;
1495
+ else if (rawValue === "false") cursor[lastKey] = false;
1496
+ else if (/^\d+$/.test(rawValue)) cursor[lastKey] = parseInt(rawValue, 10);
1497
+ else if (/^\d*\.\d+$/.test(rawValue)) cursor[lastKey] = parseFloat(rawValue);
1498
+ else cursor[lastKey] = rawValue;
1499
+ }
1500
+ const parsed = PartialSubstrateConfigSchema.safeParse(overrides);
1501
+ if (!parsed.success) {
1502
+ logger$20.warn({ errors: parsed.error.issues }, "Invalid environment variable overrides ignored");
1503
+ return {};
1504
+ }
1505
+ return parsed.data;
1506
+ }
1507
+ /**
1508
+ * Get a value from a nested object using dot-notation key.
1509
+ */
1510
+ function getByPath(obj, path$1) {
1511
+ const parts = path$1.split(".");
1512
+ let cursor = obj;
1513
+ for (const part of parts) {
1514
+ if (cursor === null || cursor === void 0 || typeof cursor !== "object") return void 0;
1515
+ cursor = cursor[part];
1516
+ }
1517
+ return cursor;
1518
+ }
1519
+ /**
1520
+ * Return a deep clone of `obj` with `path` set to `value`.
1521
+ * Creates intermediate objects as needed.
1522
+ */
1523
+ function setByPath(obj, path$1, value) {
1524
+ const parts = path$1.split(".");
1525
+ const result = { ...obj };
1526
+ let cursor = result;
1527
+ for (let i = 0; i < parts.length - 1; i++) {
1528
+ const part = parts[i] ?? "";
1529
+ const existing = cursor[part];
1530
+ if (existing === null || existing === void 0 || typeof existing !== "object") cursor[part] = {};
1531
+ else cursor[part] = { ...existing };
1532
+ cursor = cursor[part];
1533
+ }
1534
+ const lastKey = parts[parts.length - 1] ?? "";
1535
+ cursor[lastKey] = value;
1536
+ return result;
1537
+ }
1538
+ var ConfigSystemImpl = class {
1539
+ _config = null;
1540
+ _projectConfigDir;
1541
+ _globalConfigDir;
1542
+ _cliOverrides;
1543
+ constructor(options = {}) {
1544
+ this._projectConfigDir = options.projectConfigDir ? resolve(options.projectConfigDir) : resolve(process.cwd(), ".substrate");
1545
+ this._globalConfigDir = options.globalConfigDir ? resolve(options.globalConfigDir) : resolve(homedir(), ".substrate");
1546
+ this._cliOverrides = options.cliOverrides ?? {};
1547
+ }
1548
+ get isLoaded() {
1549
+ return this._config !== null;
1550
+ }
1551
+ async load() {
1552
+ let merged = structuredClone(DEFAULT_CONFIG);
1553
+ const globalConfig = await this._loadYamlFile(join(this._globalConfigDir, "config.yaml"));
1554
+ if (globalConfig !== null) merged = deepMerge(merged, globalConfig);
1555
+ const projectConfig = await this._loadYamlFile(join(this._projectConfigDir, "config.yaml"));
1556
+ if (projectConfig !== null) merged = deepMerge(merged, projectConfig);
1557
+ const envOverrides = readEnvOverrides();
1558
+ if (Object.keys(envOverrides).length > 0) merged = deepMerge(merged, envOverrides);
1559
+ if (Object.keys(this._cliOverrides).length > 0) merged = deepMerge(merged, this._cliOverrides);
1560
+ const result = SubstrateConfigSchema.safeParse(merged);
1561
+ if (!result.success) {
1562
+ const issues = result.error.issues.map((issue) => ` • ${issue.path.join(".")}: ${issue.message}`).join("\n");
1563
+ throw new ConfigError(`Configuration validation failed:\n${issues}`, { issues: result.error.issues });
1564
+ }
1565
+ this._config = result.data;
1566
+ logger$20.debug("Configuration loaded successfully");
1567
+ }
1568
+ getConfig() {
1569
+ if (this._config === null) throw new ConfigError("Configuration has not been loaded. Call load() before getConfig().", {});
1570
+ return this._config;
1571
+ }
1572
+ get(key) {
1573
+ const config = this.getConfig();
1574
+ return getByPath(config, key);
1575
+ }
1576
+ async set(key, value) {
1577
+ const current = this.getConfig();
1578
+ const existing = getByPath(current, key);
1579
+ if (existing === void 0) throw new ConfigError(`Unknown config key: ${key}`, { key });
1580
+ if (typeof existing === "object" && existing !== null) throw new ConfigError(`Cannot set object key "${key}" — use a more specific dot-notation path`, { key });
1581
+ let projectConfigRaw = {};
1582
+ const projectConfigPath = join(this._projectConfigDir, "config.yaml");
1583
+ const existingYaml = await this._loadYamlFile(projectConfigPath);
1584
+ if (existingYaml !== null) projectConfigRaw = existingYaml;
1585
+ const updated = setByPath(projectConfigRaw, key, value);
1586
+ const partial = PartialSubstrateConfigSchema.safeParse(updated);
1587
+ if (!partial.success) {
1588
+ const issues = partial.error.issues.map((i) => ` • ${i.path.join(".")}: ${i.message}`).join("\n");
1589
+ throw new ConfigError(`Invalid value for "${key}":\n${issues}`, {
1590
+ key,
1591
+ value,
1592
+ issues: partial.error.issues
1593
+ });
1594
+ }
1595
+ await mkdir(this._projectConfigDir, { recursive: true });
1596
+ const yamlStr = yaml.dump(updated);
1597
+ await writeFile(projectConfigPath, yamlStr, "utf-8");
1598
+ await this.load();
1599
+ }
1600
+ getMasked() {
1601
+ const config = this.getConfig();
1602
+ return deepMask(config);
1603
+ }
1604
+ getConfigFormatVersion() {
1605
+ return CURRENT_CONFIG_FORMAT_VERSION;
1606
+ }
1607
+ isCompatible(version) {
1608
+ return SUPPORTED_CONFIG_FORMAT_VERSIONS.includes(version);
1609
+ }
1610
+ async _fileExists(filePath) {
1611
+ try {
1612
+ await access(filePath);
1613
+ return true;
1614
+ } catch {
1615
+ return false;
1616
+ }
1617
+ }
1618
+ async _loadYamlFile(filePath) {
1619
+ if (!await this._fileExists(filePath)) return null;
1620
+ try {
1621
+ const raw = await readFile(filePath, "utf-8");
1622
+ let parsed = yaml.load(raw);
1623
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
1624
+ const rawObj = parsed;
1625
+ const version = rawObj["config_format_version"];
1626
+ if (version !== void 0 && typeof version === "string" && !isVersionSupported(version, SUPPORTED_CONFIG_FORMAT_VERSIONS)) if (defaultConfigMigrator.canMigrate(version, CURRENT_CONFIG_FORMAT_VERSION)) {
1627
+ const migrationOutput = defaultConfigMigrator.migrate(rawObj, version, CURRENT_CONFIG_FORMAT_VERSION, filePath);
1628
+ if (migrationOutput.result.success) {
1629
+ logger$20.info({
1630
+ from: version,
1631
+ to: CURRENT_CONFIG_FORMAT_VERSION,
1632
+ backup: migrationOutput.result.backupPath
1633
+ }, "Config auto-migrated successfully");
1634
+ parsed = migrationOutput.config;
1635
+ } else throw new ConfigIncompatibleFormatError(`Config migration failed: ${migrationOutput.result.manualStepsRequired.join("; ")}`, {
1636
+ filePath,
1637
+ version
1638
+ });
1639
+ } else throw new ConfigIncompatibleFormatError(formatUnsupportedVersionError("config", version, SUPPORTED_CONFIG_FORMAT_VERSIONS), { filePath });
1640
+ }
1641
+ const result = PartialSubstrateConfigSchema.safeParse(parsed);
1642
+ if (!result.success) {
1643
+ const issues = result.error.issues.map((i) => ` • ${i.path.join(".")}: ${i.message}`).join("\n");
1644
+ throw new ConfigError(`Invalid config file at ${filePath}:\n${issues}`, {
1645
+ filePath,
1646
+ issues: result.error.issues
1647
+ });
1648
+ }
1649
+ return result.data;
1650
+ } catch (err) {
1651
+ if (err instanceof ConfigError) throw err;
1652
+ if (err instanceof ConfigIncompatibleFormatError) throw err;
1653
+ const message = err instanceof Error ? err.message : String(err);
1654
+ throw new ConfigError(`Failed to read config file at ${filePath}: ${message}`, { filePath });
1655
+ }
1656
+ }
1657
+ };
1658
+ /**
1659
+ * Create a new ConfigSystem instance.
1660
+ *
1661
+ * @example
1662
+ * const config = createConfigSystem()
1663
+ * await config.load()
1664
+ * const cfg = config.getConfig()
1665
+ */
1666
+ function createConfigSystem(options = {}) {
1667
+ return new ConfigSystemImpl(options);
1668
+ }
1669
+
1364
1670
  //#endregion
1365
1671
  //#region src/modules/implementation-orchestrator/event-emitter.ts
1366
1672
  /**
@@ -7123,6 +7429,27 @@ function createPauseGate() {
7123
7429
  };
7124
7430
  }
7125
7431
  /**
7432
+ * Build the targeted_files content string from a code-review issue list.
7433
+ * Deduplicates file paths and includes line numbers where available.
7434
+ * Returns empty string when no issues have file references.
7435
+ */
7436
+ function buildTargetedFilesContent(issueList) {
7437
+ const seen = new Map();
7438
+ for (const issue of issueList) {
7439
+ const iss = issue;
7440
+ if (!iss.file) continue;
7441
+ if (!seen.has(iss.file)) seen.set(iss.file, new Set());
7442
+ if (iss.line !== void 0) seen.get(iss.file).add(iss.line);
7443
+ }
7444
+ if (seen.size === 0) return "";
7445
+ const lines = [];
7446
+ for (const [file, lineNums] of seen) if (lineNums.size > 0) {
7447
+ const sorted = [...lineNums].sort((a, b) => a - b);
7448
+ lines.push(`- ${file} (lines: ${sorted.join(", ")})`);
7449
+ } else lines.push(`- ${file}`);
7450
+ return lines.join("\n");
7451
+ }
7452
+ /**
7126
7453
  * Factory function that creates an ImplementationOrchestrator instance.
7127
7454
  *
7128
7455
  * @param deps - Injected dependencies (db, pack, contextCompiler, dispatcher,
@@ -7131,7 +7458,7 @@ function createPauseGate() {
7131
7458
  */
7132
7459
  function createImplementationOrchestrator(deps) {
7133
7460
  const { db, pack, contextCompiler, dispatcher, eventBus, config, projectRoot, tokenCeilings } = deps;
7134
- const logger$22 = createLogger("implementation-orchestrator");
7461
+ const logger$23 = createLogger("implementation-orchestrator");
7135
7462
  let _state = "IDLE";
7136
7463
  let _startedAt;
7137
7464
  let _completedAt;
@@ -7174,7 +7501,7 @@ function createImplementationOrchestrator(deps) {
7174
7501
  const nowMs = Date.now();
7175
7502
  for (const [phase, startMs] of starts) {
7176
7503
  const endMs = ends?.get(phase);
7177
- if (endMs === void 0) logger$22.warn({
7504
+ if (endMs === void 0) logger$23.warn({
7178
7505
  storyKey,
7179
7506
  phase
7180
7507
  }, "Phase has no end time — story may have errored mid-phase. Duration capped to now() and may be inflated.");
@@ -7223,7 +7550,7 @@ function createImplementationOrchestrator(deps) {
7223
7550
  rationale: `Story ${storyKey} completed with result=${result} in ${wallClockSeconds}s. Tokens: ${tokenAgg.input}+${tokenAgg.output}. Review cycles: ${reviewCycles}.`
7224
7551
  });
7225
7552
  } catch (decisionErr) {
7226
- logger$22.warn({
7553
+ logger$23.warn({
7227
7554
  err: decisionErr,
7228
7555
  storyKey
7229
7556
  }, "Failed to write story-metrics decision (best-effort)");
@@ -7251,13 +7578,13 @@ function createImplementationOrchestrator(deps) {
7251
7578
  dispatches: _storyDispatches.get(storyKey) ?? 0
7252
7579
  });
7253
7580
  } catch (emitErr) {
7254
- logger$22.warn({
7581
+ logger$23.warn({
7255
7582
  err: emitErr,
7256
7583
  storyKey
7257
7584
  }, "Failed to emit story:metrics event (best-effort)");
7258
7585
  }
7259
7586
  } catch (err) {
7260
- logger$22.warn({
7587
+ logger$23.warn({
7261
7588
  err,
7262
7589
  storyKey
7263
7590
  }, "Failed to write story metrics (best-effort)");
@@ -7286,7 +7613,7 @@ function createImplementationOrchestrator(deps) {
7286
7613
  rationale: `Story ${storyKey} ${outcome} after ${reviewCycles} review cycle(s).`
7287
7614
  });
7288
7615
  } catch (err) {
7289
- logger$22.warn({
7616
+ logger$23.warn({
7290
7617
  err,
7291
7618
  storyKey
7292
7619
  }, "Failed to write story-outcome decision (best-effort)");
@@ -7312,7 +7639,7 @@ function createImplementationOrchestrator(deps) {
7312
7639
  rationale: `Escalation diagnosis for ${payload.storyKey}: ${diagnosis.recommendedAction} — ${diagnosis.rationale}`
7313
7640
  });
7314
7641
  } catch (err) {
7315
- logger$22.warn({
7642
+ logger$23.warn({
7316
7643
  err,
7317
7644
  storyKey: payload.storyKey
7318
7645
  }, "Failed to persist escalation diagnosis (best-effort)");
@@ -7362,7 +7689,7 @@ function createImplementationOrchestrator(deps) {
7362
7689
  token_usage_json: serialized
7363
7690
  });
7364
7691
  } catch (err) {
7365
- logger$22.warn("Failed to persist orchestrator state", { err });
7692
+ logger$23.warn("Failed to persist orchestrator state", { err });
7366
7693
  }
7367
7694
  }
7368
7695
  function recordProgress() {
@@ -7409,7 +7736,7 @@ function createImplementationOrchestrator(deps) {
7409
7736
  }
7410
7737
  if (childActive) {
7411
7738
  _lastProgressTs = Date.now();
7412
- logger$22.debug({
7739
+ logger$23.debug({
7413
7740
  storyKey: key,
7414
7741
  phase: s.phase,
7415
7742
  childPids
@@ -7418,7 +7745,7 @@ function createImplementationOrchestrator(deps) {
7418
7745
  }
7419
7746
  _stalledStories.add(key);
7420
7747
  _storiesWithStall.add(key);
7421
- logger$22.warn({
7748
+ logger$23.warn({
7422
7749
  storyKey: key,
7423
7750
  phase: s.phase,
7424
7751
  elapsedMs: elapsed,
@@ -7463,7 +7790,7 @@ function createImplementationOrchestrator(deps) {
7463
7790
  for (let attempt = 0; attempt < MEMORY_PRESSURE_BACKOFF_MS.length; attempt++) {
7464
7791
  const memState = dispatcher.getMemoryState();
7465
7792
  if (!memState.isPressured) return true;
7466
- logger$22.warn({
7793
+ logger$23.warn({
7467
7794
  storyKey,
7468
7795
  freeMB: memState.freeMB,
7469
7796
  thresholdMB: memState.thresholdMB,
@@ -7483,11 +7810,11 @@ function createImplementationOrchestrator(deps) {
7483
7810
  * exhausted retries the story is ESCALATED.
7484
7811
  */
7485
7812
  async function processStory(storyKey) {
7486
- logger$22.info("Processing story", { storyKey });
7813
+ logger$23.info("Processing story", { storyKey });
7487
7814
  {
7488
7815
  const memoryOk = await checkMemoryPressure(storyKey);
7489
7816
  if (!memoryOk) {
7490
- logger$22.warn({ storyKey }, "Memory pressure exhausted — escalating story without dispatch");
7817
+ logger$23.warn({ storyKey }, "Memory pressure exhausted — escalating story without dispatch");
7491
7818
  _stories.set(storyKey, {
7492
7819
  phase: "ESCALATED",
7493
7820
  reviewCycles: 0,
@@ -7521,14 +7848,14 @@ function createImplementationOrchestrator(deps) {
7521
7848
  if (match) {
7522
7849
  const candidatePath = join$1(artifactsDir, match);
7523
7850
  const validation = await isValidStoryFile(candidatePath);
7524
- if (!validation.valid) logger$22.warn({
7851
+ if (!validation.valid) logger$23.warn({
7525
7852
  storyKey,
7526
7853
  storyFilePath: candidatePath,
7527
7854
  reason: validation.reason
7528
7855
  }, `Existing story file for ${storyKey} is invalid (${validation.reason}) — re-creating`);
7529
7856
  else {
7530
7857
  storyFilePath = candidatePath;
7531
- logger$22.info({
7858
+ logger$23.info({
7532
7859
  storyKey,
7533
7860
  storyFilePath
7534
7861
  }, "Found existing story file — skipping create-story");
@@ -7640,10 +7967,10 @@ function createImplementationOrchestrator(deps) {
7640
7967
  pipelineRunId: config.pipelineRunId
7641
7968
  });
7642
7969
  testPlanPhaseResult = testPlanResult.result;
7643
- if (testPlanResult.result === "success") logger$22.info({ storyKey }, "Test plan generated successfully");
7644
- else logger$22.warn({ storyKey }, "Test planning returned failed result — proceeding to dev-story without test plan");
7970
+ if (testPlanResult.result === "success") logger$23.info({ storyKey }, "Test plan generated successfully");
7971
+ else logger$23.warn({ storyKey }, "Test planning returned failed result — proceeding to dev-story without test plan");
7645
7972
  } catch (err) {
7646
- logger$22.warn({
7973
+ logger$23.warn({
7647
7974
  storyKey,
7648
7975
  err
7649
7976
  }, "Test planning failed — proceeding to dev-story without test plan");
@@ -7667,7 +7994,7 @@ function createImplementationOrchestrator(deps) {
7667
7994
  try {
7668
7995
  storyContentForAnalysis = await readFile$1(storyFilePath ?? "", "utf-8");
7669
7996
  } catch (err) {
7670
- logger$22.error({
7997
+ logger$23.error({
7671
7998
  storyKey,
7672
7999
  storyFilePath,
7673
8000
  error: err instanceof Error ? err.message : String(err)
@@ -7675,7 +8002,7 @@ function createImplementationOrchestrator(deps) {
7675
8002
  }
7676
8003
  const analysis = analyzeStoryComplexity(storyContentForAnalysis);
7677
8004
  const batches = planTaskBatches(analysis);
7678
- logger$22.info({
8005
+ logger$23.info({
7679
8006
  storyKey,
7680
8007
  estimatedScope: analysis.estimatedScope,
7681
8008
  batchCount: batches.length,
@@ -7693,7 +8020,7 @@ function createImplementationOrchestrator(deps) {
7693
8020
  if (_state !== "RUNNING") break;
7694
8021
  const taskScope = batch.taskIds.map((id, i) => `T${id}: ${batch.taskTitles[i] ?? ""}`).join("\n");
7695
8022
  const priorFiles = allFilesModified.size > 0 ? Array.from(allFilesModified) : void 0;
7696
- logger$22.info({
8023
+ logger$23.info({
7697
8024
  storyKey,
7698
8025
  batchIndex: batch.batchIndex,
7699
8026
  taskCount: batch.taskIds.length
@@ -7718,7 +8045,7 @@ function createImplementationOrchestrator(deps) {
7718
8045
  });
7719
8046
  } catch (batchErr) {
7720
8047
  const errMsg = batchErr instanceof Error ? batchErr.message : String(batchErr);
7721
- logger$22.warn({
8048
+ logger$23.warn({
7722
8049
  storyKey,
7723
8050
  batchIndex: batch.batchIndex,
7724
8051
  error: errMsg
@@ -7738,7 +8065,7 @@ function createImplementationOrchestrator(deps) {
7738
8065
  filesModified: batchFilesModified,
7739
8066
  result: batchResult.result === "success" ? "success" : "failed"
7740
8067
  };
7741
- logger$22.info(batchMetrics, "Batch dev-story metrics");
8068
+ logger$23.info(batchMetrics, "Batch dev-story metrics");
7742
8069
  for (const f of batchFilesModified) allFilesModified.add(f);
7743
8070
  if (batchFilesModified.length > 0) batchFileGroups.push({
7744
8071
  batchIndex: batch.batchIndex,
@@ -7760,13 +8087,13 @@ function createImplementationOrchestrator(deps) {
7760
8087
  })
7761
8088
  });
7762
8089
  } catch (tokenErr) {
7763
- logger$22.warn({
8090
+ logger$23.warn({
7764
8091
  storyKey,
7765
8092
  batchIndex: batch.batchIndex,
7766
8093
  err: tokenErr
7767
8094
  }, "Failed to record batch token usage");
7768
8095
  }
7769
- if (batchResult.result === "failed") logger$22.warn({
8096
+ if (batchResult.result === "failed") logger$23.warn({
7770
8097
  storyKey,
7771
8098
  batchIndex: batch.batchIndex,
7772
8099
  error: batchResult.error
@@ -7802,7 +8129,7 @@ function createImplementationOrchestrator(deps) {
7802
8129
  });
7803
8130
  persistState();
7804
8131
  if (devResult.result === "success") devStoryWasSuccess = true;
7805
- else logger$22.warn("Dev-story reported failure, proceeding to code review", {
8132
+ else logger$23.warn("Dev-story reported failure, proceeding to code review", {
7806
8133
  storyKey,
7807
8134
  error: devResult.error,
7808
8135
  filesModified: devFilesModified.length
@@ -7830,7 +8157,7 @@ function createImplementationOrchestrator(deps) {
7830
8157
  if (devStoryWasSuccess) {
7831
8158
  gitDiffFiles = checkGitDiffFiles(projectRoot ?? process.cwd());
7832
8159
  if (gitDiffFiles.length === 0) {
7833
- logger$22.warn({ storyKey }, "Zero-diff detected after COMPLETE dev-story — no file changes in git working tree");
8160
+ logger$23.warn({ storyKey }, "Zero-diff detected after COMPLETE dev-story — no file changes in git working tree");
7834
8161
  eventBus.emit("orchestrator:zero-diff-escalation", {
7835
8162
  storyKey,
7836
8163
  reason: "zero-diff-on-complete"
@@ -7861,7 +8188,7 @@ function createImplementationOrchestrator(deps) {
7861
8188
  });
7862
8189
  if (buildVerifyResult.status === "passed") {
7863
8190
  eventBus.emit("story:build-verification-passed", { storyKey });
7864
- logger$22.info({ storyKey }, "Build verification passed");
8191
+ logger$23.info({ storyKey }, "Build verification passed");
7865
8192
  } else if (buildVerifyResult.status === "failed" || buildVerifyResult.status === "timeout") {
7866
8193
  const truncatedOutput = (buildVerifyResult.output ?? "").slice(0, 2e3);
7867
8194
  const reason = buildVerifyResult.reason ?? "build-verification-failed";
@@ -7870,7 +8197,7 @@ function createImplementationOrchestrator(deps) {
7870
8197
  exitCode: buildVerifyResult.exitCode ?? 1,
7871
8198
  output: truncatedOutput
7872
8199
  });
7873
- logger$22.warn({
8200
+ logger$23.warn({
7874
8201
  storyKey,
7875
8202
  reason,
7876
8203
  exitCode: buildVerifyResult.exitCode
@@ -7900,7 +8227,7 @@ function createImplementationOrchestrator(deps) {
7900
8227
  storyKey
7901
8228
  });
7902
8229
  if (icResult.potentiallyAffectedTests.length > 0) {
7903
- logger$22.warn({
8230
+ logger$23.warn({
7904
8231
  storyKey,
7905
8232
  modifiedInterfaces: icResult.modifiedInterfaces,
7906
8233
  potentiallyAffectedTests: icResult.potentiallyAffectedTests
@@ -7945,7 +8272,7 @@ function createImplementationOrchestrator(deps) {
7945
8272
  "NEEDS_MAJOR_REWORK": 2
7946
8273
  };
7947
8274
  for (const group of batchFileGroups) {
7948
- logger$22.info({
8275
+ logger$23.info({
7949
8276
  storyKey,
7950
8277
  batchIndex: group.batchIndex,
7951
8278
  fileCount: group.files.length
@@ -7983,7 +8310,7 @@ function createImplementationOrchestrator(deps) {
7983
8310
  rawOutput: lastRawOutput,
7984
8311
  tokenUsage: aggregateTokens
7985
8312
  };
7986
- logger$22.info({
8313
+ logger$23.info({
7987
8314
  storyKey,
7988
8315
  batchCount: batchFileGroups.length,
7989
8316
  verdict: worstVerdict,
@@ -8010,7 +8337,7 @@ function createImplementationOrchestrator(deps) {
8010
8337
  const isPhantomReview = reviewResult.dispatchFailed === true || reviewResult.verdict !== "SHIP_IT" && (reviewResult.issue_list === void 0 || reviewResult.issue_list.length === 0) && reviewResult.error !== void 0;
8011
8338
  if (isPhantomReview && !timeoutRetried) {
8012
8339
  timeoutRetried = true;
8013
- logger$22.warn({
8340
+ logger$23.warn({
8014
8341
  storyKey,
8015
8342
  reviewCycles,
8016
8343
  error: reviewResult.error
@@ -8020,7 +8347,7 @@ function createImplementationOrchestrator(deps) {
8020
8347
  verdict = reviewResult.verdict;
8021
8348
  issueList = reviewResult.issue_list ?? [];
8022
8349
  if (verdict === "NEEDS_MAJOR_REWORK" && reviewCycles > 0 && previousIssueList.length > 0 && issueList.length < previousIssueList.length) {
8023
- logger$22.info({
8350
+ logger$23.info({
8024
8351
  storyKey,
8025
8352
  originalVerdict: verdict,
8026
8353
  issuesBefore: previousIssueList.length,
@@ -8056,7 +8383,7 @@ function createImplementationOrchestrator(deps) {
8056
8383
  if (_decomposition !== void 0) parts.push(`decomposed: ${_decomposition.batchCount} batches`);
8057
8384
  parts.push(`${fileCount} files`);
8058
8385
  parts.push(`${totalTokensK} tokens`);
8059
- logger$22.info({
8386
+ logger$23.info({
8060
8387
  storyKey,
8061
8388
  verdict,
8062
8389
  agentVerdict: reviewResult.agentVerdict
@@ -8108,7 +8435,7 @@ function createImplementationOrchestrator(deps) {
8108
8435
  filesModified: devFilesModified,
8109
8436
  workingDirectory: projectRoot
8110
8437
  });
8111
- logger$22.debug({
8438
+ logger$23.debug({
8112
8439
  storyKey,
8113
8440
  expansion_priority: expansionResult.expansion_priority,
8114
8441
  coverage_gaps: expansionResult.coverage_gaps.length
@@ -8121,7 +8448,7 @@ function createImplementationOrchestrator(deps) {
8121
8448
  value: JSON.stringify(expansionResult)
8122
8449
  });
8123
8450
  } catch (expansionErr) {
8124
- logger$22.warn({
8451
+ logger$23.warn({
8125
8452
  storyKey,
8126
8453
  error: expansionErr instanceof Error ? expansionErr.message : String(expansionErr)
8127
8454
  }, "Test expansion failed — story verdict unchanged");
@@ -8148,7 +8475,7 @@ function createImplementationOrchestrator(deps) {
8148
8475
  persistState();
8149
8476
  return;
8150
8477
  }
8151
- logger$22.info({
8478
+ logger$23.info({
8152
8479
  storyKey,
8153
8480
  reviewCycles: finalReviewCycles,
8154
8481
  issueCount: issueList.length
@@ -8158,9 +8485,13 @@ function createImplementationOrchestrator(deps) {
8158
8485
  updateStory(storyKey, { phase: "NEEDS_FIXES" });
8159
8486
  try {
8160
8487
  let fixPrompt;
8488
+ let autoApproveMaxTurns;
8161
8489
  try {
8162
8490
  const fixTemplate = await pack.getPrompt("fix-story");
8163
8491
  const storyContent = await readFile$1(storyFilePath ?? "", "utf-8");
8492
+ const complexity = computeStoryComplexity(storyContent);
8493
+ autoApproveMaxTurns = resolveFixStoryMaxTurns(complexity.complexityScore);
8494
+ logComplexityResult(storyKey, complexity, autoApproveMaxTurns);
8164
8495
  let reviewFeedback;
8165
8496
  if (issueList.length === 0) reviewFeedback = `Verdict: ${verdict}\nIssues: Minor issues flagged but no specifics provided. Review the story ACs and fix any remaining gaps.`;
8166
8497
  else reviewFeedback = [
@@ -8177,6 +8508,7 @@ function createImplementationOrchestrator(deps) {
8177
8508
  const constraints = decisions.filter((d) => d.category === "architecture");
8178
8509
  archConstraints = constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
8179
8510
  } catch {}
8511
+ const targetedFilesContent = buildTargetedFilesContent(issueList);
8180
8512
  const sections = [
8181
8513
  {
8182
8514
  name: "story_content",
@@ -8192,19 +8524,25 @@ function createImplementationOrchestrator(deps) {
8192
8524
  name: "arch_constraints",
8193
8525
  content: archConstraints,
8194
8526
  priority: "optional"
8195
- }
8527
+ },
8528
+ ...targetedFilesContent ? [{
8529
+ name: "targeted_files",
8530
+ content: targetedFilesContent,
8531
+ priority: "important"
8532
+ }] : []
8196
8533
  ];
8197
8534
  const assembled = assemblePrompt(fixTemplate, sections, 24e3);
8198
8535
  fixPrompt = assembled.prompt;
8199
8536
  } catch {
8200
8537
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, minor fixes needed`;
8201
- logger$22.warn("Failed to assemble auto-approve fix prompt, using fallback", { storyKey });
8538
+ logger$23.warn("Failed to assemble auto-approve fix prompt, using fallback", { storyKey });
8202
8539
  }
8203
8540
  const handle = dispatcher.dispatch({
8204
8541
  prompt: fixPrompt,
8205
8542
  agent: "claude-code",
8206
8543
  taskType: "minor-fixes",
8207
- workingDirectory: projectRoot
8544
+ workingDirectory: projectRoot,
8545
+ ...autoApproveMaxTurns !== void 0 ? { maxTurns: autoApproveMaxTurns } : {}
8208
8546
  });
8209
8547
  const fixResult = await handle.result;
8210
8548
  eventBus.emit("orchestrator:story-phase-complete", {
@@ -8215,9 +8553,9 @@ function createImplementationOrchestrator(deps) {
8215
8553
  output: fixResult.tokenEstimate.output
8216
8554
  } : void 0 }
8217
8555
  });
8218
- if (fixResult.status === "timeout") logger$22.warn("Auto-approve fix timed out — approving anyway (issues were minor)", { storyKey });
8556
+ if (fixResult.status === "timeout") logger$23.warn("Auto-approve fix timed out — approving anyway (issues were minor)", { storyKey });
8219
8557
  } catch (err) {
8220
- logger$22.warn("Auto-approve fix dispatch failed — approving anyway (issues were minor)", {
8558
+ logger$23.warn("Auto-approve fix dispatch failed — approving anyway (issues were minor)", {
8221
8559
  storyKey,
8222
8560
  err
8223
8561
  });
@@ -8251,7 +8589,7 @@ function createImplementationOrchestrator(deps) {
8251
8589
  try {
8252
8590
  const fixTemplate = await pack.getPrompt(templateName);
8253
8591
  const storyContent = await readFile$1(storyFilePath ?? "", "utf-8");
8254
- if (isMajorRework) {
8592
+ {
8255
8593
  const complexity = computeStoryComplexity(storyContent);
8256
8594
  fixMaxTurns = resolveFixStoryMaxTurns(complexity.complexityScore);
8257
8595
  logComplexityResult(storyKey, complexity, fixMaxTurns);
@@ -8305,28 +8643,36 @@ function createImplementationOrchestrator(deps) {
8305
8643
  content: "",
8306
8644
  priority: "optional"
8307
8645
  }
8308
- ] : [
8309
- {
8310
- name: "story_content",
8311
- content: storyContent,
8312
- priority: "required"
8313
- },
8314
- {
8315
- name: "review_feedback",
8316
- content: reviewFeedback,
8317
- priority: "required"
8318
- },
8319
- {
8320
- name: "arch_constraints",
8321
- content: archConstraints,
8322
- priority: "optional"
8323
- }
8324
- ];
8646
+ ] : (() => {
8647
+ const targetedFilesContent = buildTargetedFilesContent(issueList);
8648
+ return [
8649
+ {
8650
+ name: "story_content",
8651
+ content: storyContent,
8652
+ priority: "required"
8653
+ },
8654
+ {
8655
+ name: "review_feedback",
8656
+ content: reviewFeedback,
8657
+ priority: "required"
8658
+ },
8659
+ {
8660
+ name: "arch_constraints",
8661
+ content: archConstraints,
8662
+ priority: "optional"
8663
+ },
8664
+ ...targetedFilesContent ? [{
8665
+ name: "targeted_files",
8666
+ content: targetedFilesContent,
8667
+ priority: "important"
8668
+ }] : []
8669
+ ];
8670
+ })();
8325
8671
  const assembled = assemblePrompt(fixTemplate, sections, 24e3);
8326
8672
  fixPrompt = assembled.prompt;
8327
8673
  } catch {
8328
8674
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, taskType=${taskType}`;
8329
- logger$22.warn("Failed to assemble fix prompt, using fallback", {
8675
+ logger$23.warn("Failed to assemble fix prompt, using fallback", {
8330
8676
  storyKey,
8331
8677
  taskType
8332
8678
  });
@@ -8345,6 +8691,7 @@ function createImplementationOrchestrator(deps) {
8345
8691
  agent: "claude-code",
8346
8692
  taskType,
8347
8693
  ...fixModel !== void 0 ? { model: fixModel } : {},
8694
+ ...fixMaxTurns !== void 0 ? { maxTurns: fixMaxTurns } : {},
8348
8695
  ...projectRoot !== void 0 ? { workingDirectory: projectRoot } : {}
8349
8696
  });
8350
8697
  const fixResult = await handle.result;
@@ -8357,7 +8704,7 @@ function createImplementationOrchestrator(deps) {
8357
8704
  } : void 0 }
8358
8705
  });
8359
8706
  if (fixResult.status === "timeout") {
8360
- logger$22.warn("Fix dispatch timed out — escalating story", {
8707
+ logger$23.warn("Fix dispatch timed out — escalating story", {
8361
8708
  storyKey,
8362
8709
  taskType
8363
8710
  });
@@ -8379,7 +8726,7 @@ function createImplementationOrchestrator(deps) {
8379
8726
  }
8380
8727
  if (fixResult.status === "failed") {
8381
8728
  if (isMajorRework) {
8382
- logger$22.warn("Major rework dispatch failed — escalating story", {
8729
+ logger$23.warn("Major rework dispatch failed — escalating story", {
8383
8730
  storyKey,
8384
8731
  exitCode: fixResult.exitCode
8385
8732
  });
@@ -8399,14 +8746,14 @@ function createImplementationOrchestrator(deps) {
8399
8746
  persistState();
8400
8747
  return;
8401
8748
  }
8402
- logger$22.warn("Fix dispatch failed", {
8749
+ logger$23.warn("Fix dispatch failed", {
8403
8750
  storyKey,
8404
8751
  taskType,
8405
8752
  exitCode: fixResult.exitCode
8406
8753
  });
8407
8754
  }
8408
8755
  } catch (err) {
8409
- logger$22.warn("Fix dispatch failed, continuing to next review", {
8756
+ logger$23.warn("Fix dispatch failed, continuing to next review", {
8410
8757
  storyKey,
8411
8758
  taskType,
8412
8759
  err
@@ -8469,11 +8816,11 @@ function createImplementationOrchestrator(deps) {
8469
8816
  }
8470
8817
  async function run(storyKeys) {
8471
8818
  if (_state === "RUNNING" || _state === "PAUSED") {
8472
- logger$22.warn("run() called while orchestrator is already running or paused — ignoring", { state: _state });
8819
+ logger$23.warn("run() called while orchestrator is already running or paused — ignoring", { state: _state });
8473
8820
  return getStatus();
8474
8821
  }
8475
8822
  if (_state === "COMPLETE") {
8476
- logger$22.warn("run() called on a COMPLETE orchestrator — ignoring", { state: _state });
8823
+ logger$23.warn("run() called on a COMPLETE orchestrator — ignoring", { state: _state });
8477
8824
  return getStatus();
8478
8825
  }
8479
8826
  _state = "RUNNING";
@@ -8491,13 +8838,13 @@ function createImplementationOrchestrator(deps) {
8491
8838
  if (config.enableHeartbeat) startHeartbeat();
8492
8839
  if (projectRoot !== void 0) {
8493
8840
  const seedResult = seedMethodologyContext(db, projectRoot);
8494
- if (seedResult.decisionsCreated > 0) logger$22.info({
8841
+ if (seedResult.decisionsCreated > 0) logger$23.info({
8495
8842
  decisionsCreated: seedResult.decisionsCreated,
8496
8843
  skippedCategories: seedResult.skippedCategories
8497
8844
  }, "Methodology context seeded from planning artifacts");
8498
8845
  }
8499
8846
  const groups = detectConflictGroups(storyKeys, { moduleMap: pack.manifest.conflictGroups });
8500
- logger$22.info("Orchestrator starting", {
8847
+ logger$23.info("Orchestrator starting", {
8501
8848
  storyCount: storyKeys.length,
8502
8849
  groupCount: groups.length,
8503
8850
  maxConcurrency: config.maxConcurrency
@@ -8509,7 +8856,7 @@ function createImplementationOrchestrator(deps) {
8509
8856
  _state = "FAILED";
8510
8857
  _completedAt = new Date().toISOString();
8511
8858
  persistState();
8512
- logger$22.error("Orchestrator failed with unhandled error", { err });
8859
+ logger$23.error("Orchestrator failed with unhandled error", { err });
8513
8860
  return getStatus();
8514
8861
  }
8515
8862
  stopHeartbeat();
@@ -8536,7 +8883,7 @@ function createImplementationOrchestrator(deps) {
8536
8883
  _pauseGate = createPauseGate();
8537
8884
  _state = "PAUSED";
8538
8885
  eventBus.emit("orchestrator:paused", {});
8539
- logger$22.info("Orchestrator paused");
8886
+ logger$23.info("Orchestrator paused");
8540
8887
  }
8541
8888
  function resume() {
8542
8889
  if (_state !== "PAUSED") return;
@@ -8547,7 +8894,7 @@ function createImplementationOrchestrator(deps) {
8547
8894
  }
8548
8895
  _state = "RUNNING";
8549
8896
  eventBus.emit("orchestrator:resumed", {});
8550
- logger$22.info("Orchestrator resumed");
8897
+ logger$23.info("Orchestrator resumed");
8551
8898
  }
8552
8899
  return {
8553
8900
  run,
@@ -12643,6 +12990,14 @@ async function runRunAction(options) {
12643
12990
  process.exit(130);
12644
12991
  });
12645
12992
  } catch {}
12993
+ let tokenCeilings;
12994
+ try {
12995
+ const configSystem = createConfigSystem({ projectConfigDir: dbDir });
12996
+ await configSystem.load();
12997
+ tokenCeilings = configSystem.getConfig().token_ceilings;
12998
+ } catch {
12999
+ logger.debug("Config loading skipped — using default token ceilings");
13000
+ }
12646
13001
  if (startPhase !== void 0) return runFullPipeline({
12647
13002
  packName,
12648
13003
  packPath,
@@ -12654,6 +13009,7 @@ async function runRunAction(options) {
12654
13009
  concurrency,
12655
13010
  outputFormat,
12656
13011
  projectRoot,
13012
+ tokenCeilings,
12657
13013
  ...eventsFlag === true ? { events: true } : {},
12658
13014
  ...skipUx === true ? { skipUx: true } : {},
12659
13015
  ...researchFlag === true ? { research: true } : {},
@@ -13060,7 +13416,8 @@ async function runRunAction(options) {
13060
13416
  pipelineRunId: pipelineRun.id,
13061
13417
  enableHeartbeat: eventsFlag === true
13062
13418
  },
13063
- projectRoot
13419
+ projectRoot,
13420
+ tokenCeilings
13064
13421
  });
13065
13422
  if (outputFormat === "human" && progressRenderer === void 0 && ndjsonEmitter === void 0) {
13066
13423
  process.stdout.write(`Starting pipeline: ${storyKeys.length} story/stories, concurrency=${concurrency}\n`);
@@ -13156,7 +13513,7 @@ async function runRunAction(options) {
13156
13513
  }
13157
13514
  }
13158
13515
  async function runFullPipeline(options) {
13159
- const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, registry: injectedRegistry } = options;
13516
+ const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, registry: injectedRegistry, tokenCeilings } = options;
13160
13517
  if (!existsSync(dbDir)) mkdirSync(dbDir, { recursive: true });
13161
13518
  const dbWrapper = new DatabaseWrapper(dbPath);
13162
13519
  try {
@@ -13363,7 +13720,8 @@ async function runFullPipeline(options) {
13363
13720
  maxReviewCycles: 2,
13364
13721
  pipelineRunId: runId
13365
13722
  },
13366
- projectRoot
13723
+ projectRoot,
13724
+ tokenCeilings
13367
13725
  });
13368
13726
  eventBus.on("orchestrator:story-phase-complete", (payload) => {
13369
13727
  try {
@@ -13500,5 +13858,5 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
13500
13858
  }
13501
13859
 
13502
13860
  //#endregion
13503
- export { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
13504
- //# sourceMappingURL=run-BCyrbL3w.js.map
13861
+ export { DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createConfigSystem, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
13862
+ //# sourceMappingURL=run-Ajt187oE.js.map