substrate-ai 0.17.1 → 0.18.0

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.
@@ -0,0 +1,4 @@
1
+ import { AdapterRegistry } from "./dist-Bm0qSZer.js";
2
+ import "./adapter-registry-DXLMTmfD.js";
3
+
4
+ export { AdapterRegistry };
package/dist/cli/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, detectCycles, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-DswaC1q5.js";
2
+ import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, detectCycles, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-Cx2ZhRNT.js";
3
3
  import { createLogger } from "../logger-KeHncl-f.js";
4
4
  import { createEventBus } from "../helpers-CElYrONe.js";
5
- import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, EXPERIMENT_RESULT, GlobalSettingsSchema, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-CLvAwmT7.js";
5
+ import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, EXPERIMENT_RESULT, GlobalSettingsSchema, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-Bm0qSZer.js";
6
6
  import "../adapter-registry-DXLMTmfD.js";
7
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-Bku8fmY3.js";
8
- import "../errors-D1LU8CZ9.js";
7
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-gXtnH8lO.js";
8
+ import "../errors-BSpu7pIv.js";
9
9
  import "../routing-CcBOCuC9.js";
10
10
  import "../decisions-C0pz9Clx.js";
11
11
  import "../version-manager-impl-BmOWu8ml.js";
12
- import { registerUpgradeCommand } from "../upgrade-DT0I_-1E.js";
12
+ import { registerUpgradeCommand } from "../upgrade-BcL4ZV3o.js";
13
13
  import { Command } from "commander";
14
14
  import { fileURLToPath } from "url";
15
15
  import { dirname, join, resolve } from "path";
@@ -24,7 +24,7 @@ import { isAbsolute, join as join$1 } from "node:path";
24
24
  import { z } from "zod";
25
25
  import * as fs from "node:fs/promises";
26
26
  import { access as access$1, readFile as readFile$1, readdir as readdir$1 } from "node:fs/promises";
27
- import { appendFileSync, chmodSync, cpSync, existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync, statSync, unlinkSync, writeFileSync as writeFileSync$1 } from "fs";
27
+ import { appendFileSync, chmodSync, cpSync, existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync, rmSync as rmSync$1, statSync, unlinkSync, writeFileSync as writeFileSync$1 } from "fs";
28
28
  import { homedir } from "os";
29
29
  import { createRequire } from "node:module";
30
30
  import { fileURLToPath as fileURLToPath$1 } from "node:url";
@@ -1757,14 +1757,16 @@ function clearBmadCommandFiles(commandsDir) {
1757
1757
  }
1758
1758
  async function compileBmadAgents(bmadDir) {
1759
1759
  const _require = createRequire(join(__dirname, "synthetic.js"));
1760
- let compilerPath;
1760
+ let compileAgent;
1761
1761
  try {
1762
1762
  const pkgJsonPath = _require.resolve("bmad-method/package.json");
1763
- compilerPath = join(dirname(pkgJsonPath), "tools", "cli", "lib", "agent", "compiler.js");
1763
+ const compilerPath = join(dirname(pkgJsonPath), "tools", "cli", "lib", "agent", "compiler.js");
1764
+ if (!existsSync$1(compilerPath)) return 0;
1765
+ const mod = _require(compilerPath);
1766
+ compileAgent = mod.compileAgent;
1764
1767
  } catch {
1765
1768
  return 0;
1766
1769
  }
1767
- const { compileAgent } = _require(compilerPath);
1768
1770
  const agentDirs = [];
1769
1771
  const coreAgentsDir = join(bmadDir, "core", "agents");
1770
1772
  if (existsSync$1(coreAgentsDir)) agentDirs.push(coreAgentsDir);
@@ -1800,6 +1802,76 @@ async function compileBmadAgents(bmadDir) {
1800
1802
  } catch {}
1801
1803
  return compiled;
1802
1804
  }
1805
+ /**
1806
+ * Parse a single CSV line, respecting double-quoted fields that may contain
1807
+ * commas and escaped quotes (RFC 4180). Returns an array of field values.
1808
+ */
1809
+ function parseCSVLine(line) {
1810
+ const fields = [];
1811
+ let current = "";
1812
+ let inQuotes = false;
1813
+ for (let i = 0; i < line.length; i++) {
1814
+ const ch = line[i];
1815
+ if (inQuotes) if (ch === "\"") if (i + 1 < line.length && line[i + 1] === "\"") {
1816
+ current += "\"";
1817
+ i++;
1818
+ } else inQuotes = false;
1819
+ else current += ch;
1820
+ else if (ch === "\"") inQuotes = true;
1821
+ else if (ch === ",") {
1822
+ fields.push(current);
1823
+ current = "";
1824
+ } else current += ch;
1825
+ }
1826
+ fields.push(current);
1827
+ return fields;
1828
+ }
1829
+ /**
1830
+ * Install skills from `_bmad/_config/skill-manifest.csv` into `.claude/skills/`.
1831
+ *
1832
+ * Each row in the CSV specifies a canonicalId and a path to the SKILL.md file.
1833
+ * The entire source directory (dirname of the path) is copied to
1834
+ * `.claude/skills/<canonicalId>/`, matching bmad-method's installVerbatimSkills.
1835
+ *
1836
+ * @returns Number of skills installed.
1837
+ */
1838
+ function installSkillsFromManifest(projectRoot, bmadDir) {
1839
+ const csvPath = join(bmadDir, "_config", "skill-manifest.csv");
1840
+ if (!existsSync$1(csvPath)) return 0;
1841
+ const csvContent = readFileSync$1(csvPath, "utf-8");
1842
+ const lines = csvContent.split("\n").filter((l) => l.trim() !== "");
1843
+ if (lines.length < 2) return 0;
1844
+ const headers = parseCSVLine(lines[0]);
1845
+ const canonicalIdIdx = headers.indexOf("canonicalId");
1846
+ const pathIdx = headers.indexOf("path");
1847
+ if (canonicalIdIdx < 0 || pathIdx < 0) return 0;
1848
+ const bmadFolderName = "_bmad";
1849
+ const bmadPrefix = bmadFolderName + "/";
1850
+ const skillsDir = join(projectRoot, ".claude", "skills");
1851
+ mkdirSync$1(skillsDir, { recursive: true });
1852
+ if (existsSync$1(skillsDir)) try {
1853
+ for (const entry of readdirSync$1(skillsDir, { withFileTypes: true })) if (entry.isDirectory() && entry.name.startsWith("bmad")) rmSync$1(join(skillsDir, entry.name), {
1854
+ recursive: true,
1855
+ force: true
1856
+ });
1857
+ } catch {}
1858
+ let count = 0;
1859
+ for (let i = 1; i < lines.length; i++) {
1860
+ const fields = parseCSVLine(lines[i]);
1861
+ const canonicalId = fields[canonicalIdIdx]?.trim();
1862
+ const skillPath = fields[pathIdx]?.trim();
1863
+ if (!canonicalId || !skillPath) continue;
1864
+ const relativePath = skillPath.startsWith(bmadPrefix) ? skillPath.slice(bmadPrefix.length) : skillPath;
1865
+ const sourceFile = join(bmadDir, relativePath);
1866
+ const sourceDir = dirname(sourceFile);
1867
+ if (!existsSync$1(sourceDir)) continue;
1868
+ const destDir = join(skillsDir, canonicalId);
1869
+ mkdirSync$1(destDir, { recursive: true });
1870
+ cpSync(sourceDir, destDir, { recursive: true });
1871
+ count++;
1872
+ }
1873
+ return count;
1874
+ }
1803
1875
  async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1804
1876
  const bmadDir = join(projectRoot, "_bmad");
1805
1877
  if (!existsSync$1(bmadDir)) return;
@@ -1822,17 +1894,39 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1822
1894
  if (def && typeof def[name] === "function") return def[name];
1823
1895
  throw new Error(`${name} is not a constructor`);
1824
1896
  };
1825
- const agentMod = _require(join(installerLibPath, "ide", "shared", "agent-command-generator.js"));
1897
+ const agentGenPath = join(installerLibPath, "ide", "shared", "agent-command-generator.js");
1898
+ const workflowGenPath = join(installerLibPath, "ide", "shared", "workflow-command-generator.js");
1899
+ const taskToolGenPath = join(installerLibPath, "ide", "shared", "task-tool-command-generator.js");
1900
+ const manifestGenPath = join(installerLibPath, "core", "manifest-generator.js");
1901
+ const pathUtilsPath = join(installerLibPath, "ide", "shared", "path-utils.js");
1902
+ if (!existsSync$1(agentGenPath)) {
1903
+ logger$15.info("bmad-method generators not available (requires bmad-method with agent/workflow/task-tool generators)");
1904
+ return;
1905
+ }
1906
+ const agentMod = _require(agentGenPath);
1826
1907
  const AgentCommandGenerator = resolveExport(agentMod, "AgentCommandGenerator");
1827
- const workflowMod = _require(join(installerLibPath, "ide", "shared", "workflow-command-generator.js"));
1828
- const WorkflowCommandGenerator = resolveExport(workflowMod, "WorkflowCommandGenerator");
1829
- const taskToolMod = _require(join(installerLibPath, "ide", "shared", "task-tool-command-generator.js"));
1830
- const TaskToolCommandGenerator = resolveExport(taskToolMod, "TaskToolCommandGenerator");
1831
- const manifestMod = _require(join(installerLibPath, "core", "manifest-generator.js"));
1832
- const ManifestGenerator = resolveExport(manifestMod, "ManifestGenerator");
1833
- const pathUtilsMod = _require(join(installerLibPath, "ide", "shared", "path-utils.js"));
1834
- const pathUtils = { toDashPath: pathUtilsMod.toDashPath ?? pathUtilsMod.default?.toDashPath };
1908
+ let WorkflowCommandGenerator = null;
1909
+ let TaskToolCommandGenerator = null;
1910
+ if (existsSync$1(workflowGenPath)) {
1911
+ const workflowMod = _require(workflowGenPath);
1912
+ WorkflowCommandGenerator = resolveExport(workflowMod, "WorkflowCommandGenerator");
1913
+ } else logger$15.info("bmad-method workflow-command-generator not available; will try skill-based installation");
1914
+ if (existsSync$1(taskToolGenPath)) {
1915
+ const taskToolMod = _require(taskToolGenPath);
1916
+ TaskToolCommandGenerator = resolveExport(taskToolMod, "TaskToolCommandGenerator");
1917
+ } else logger$15.info("bmad-method task-tool-command-generator not available; will try skill-based installation");
1918
+ let ManifestGenerator = null;
1919
+ if (existsSync$1(manifestGenPath)) {
1920
+ const manifestMod = _require(manifestGenPath);
1921
+ ManifestGenerator = resolveExport(manifestMod, "ManifestGenerator");
1922
+ }
1923
+ let pathUtils = null;
1924
+ if (existsSync$1(pathUtilsPath)) {
1925
+ const pathUtilsMod = _require(pathUtilsPath);
1926
+ pathUtils = { toDashPath: pathUtilsMod.toDashPath ?? pathUtilsMod.default?.toDashPath };
1927
+ }
1835
1928
  const writeDashFallback = async (baseDir, artifacts, acceptTypes) => {
1929
+ if (!pathUtils) return 0;
1836
1930
  let written = 0;
1837
1931
  for (const artifact of artifacts) {
1838
1932
  if (!acceptTypes.includes(artifact.type)) continue;
@@ -1848,7 +1942,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1848
1942
  };
1849
1943
  const nonCoreModules = scanBmadModules(bmadDir);
1850
1944
  const allModules = ["core", ...nonCoreModules];
1851
- try {
1945
+ if (ManifestGenerator) try {
1852
1946
  const manifestGen = new ManifestGenerator();
1853
1947
  await manifestGen.generateManifests(bmadDir, allModules, [], { ides: ["claude-code"] });
1854
1948
  } catch (manifestErr) {
@@ -1860,18 +1954,28 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1860
1954
  const agentGen = new AgentCommandGenerator("_bmad");
1861
1955
  const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, nonCoreModules);
1862
1956
  const agentCount = typeof agentGen.writeDashArtifacts === "function" ? await agentGen.writeDashArtifacts(commandsDir, agentArtifacts) : await writeDashFallback(commandsDir, agentArtifacts, ["agent-launcher"]);
1863
- const workflowGen = new WorkflowCommandGenerator("_bmad");
1864
- const { artifacts: workflowArtifacts } = await workflowGen.collectWorkflowArtifacts(bmadDir);
1865
- const workflowCount = typeof workflowGen.writeDashArtifacts === "function" ? await workflowGen.writeDashArtifacts(commandsDir, workflowArtifacts) : await writeDashFallback(commandsDir, workflowArtifacts, ["workflow-command", "workflow-launcher"]);
1866
- const taskToolGen = new TaskToolCommandGenerator("_bmad");
1867
- const { artifacts: taskToolArtifacts } = await taskToolGen.collectTaskToolArtifacts(bmadDir);
1868
- const taskToolCount = typeof taskToolGen.writeDashArtifacts === "function" ? await taskToolGen.writeDashArtifacts(commandsDir, taskToolArtifacts) : await writeDashFallback(commandsDir, taskToolArtifacts, ["task", "tool"]);
1869
- const total = agentCount + workflowCount + taskToolCount;
1870
- if (outputFormat !== "json") process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(workflowCount)} workflows, ${String(taskToolCount)} tasks/tools)\n`);
1957
+ let workflowCount = 0;
1958
+ if (WorkflowCommandGenerator) {
1959
+ const workflowGen = new WorkflowCommandGenerator("_bmad");
1960
+ const { artifacts: workflowArtifacts } = await workflowGen.collectWorkflowArtifacts(bmadDir);
1961
+ workflowCount = typeof workflowGen.writeDashArtifacts === "function" ? await workflowGen.writeDashArtifacts(commandsDir, workflowArtifacts) : await writeDashFallback(commandsDir, workflowArtifacts, ["workflow-command", "workflow-launcher"]);
1962
+ }
1963
+ let taskToolCount = 0;
1964
+ if (TaskToolCommandGenerator) {
1965
+ const taskToolGen = new TaskToolCommandGenerator("_bmad");
1966
+ const { artifacts: taskToolArtifacts } = await taskToolGen.collectTaskToolArtifacts(bmadDir);
1967
+ taskToolCount = typeof taskToolGen.writeDashArtifacts === "function" ? await taskToolGen.writeDashArtifacts(commandsDir, taskToolArtifacts) : await writeDashFallback(commandsDir, taskToolArtifacts, ["task", "tool"]);
1968
+ }
1969
+ let skillCount = 0;
1970
+ if (!WorkflowCommandGenerator && !TaskToolCommandGenerator) skillCount = installSkillsFromManifest(projectRoot, bmadDir);
1971
+ const total = agentCount + workflowCount + taskToolCount + skillCount;
1972
+ if (outputFormat !== "json") if (skillCount > 0) process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(skillCount)} skills)\n`);
1973
+ else process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(workflowCount)} workflows, ${String(taskToolCount)} tasks/tools)\n`);
1871
1974
  logger$15.info({
1872
1975
  agentCount,
1873
1976
  workflowCount,
1874
1977
  taskToolCount,
1978
+ skillCount,
1875
1979
  total,
1876
1980
  commandsDir
1877
1981
  }, "Generated .claude/commands/");
@@ -2130,7 +2234,7 @@ async function runInitAction(options) {
2130
2234
  if (doltMode === "auto") await checkDoltInstalled();
2131
2235
  await initializeDolt({
2132
2236
  projectRoot,
2133
- schemaPath: fileURLToPath$1(new URL("../../modules/state/schema.sql", import.meta.url))
2237
+ schemaPath: fileURLToPath$1(new URL("../schema.sql", import.meta.url))
2134
2238
  });
2135
2239
  doltInitialized = true;
2136
2240
  } catch (err) {
@@ -3025,7 +3129,7 @@ async function runStatusAction(options) {
3025
3129
  if (run === void 0) run = await getLatestRun(adapter);
3026
3130
  }
3027
3131
  if (run === void 0) {
3028
- const { inspectProcessTree } = await import("../health-GEDGgGan.js");
3132
+ const { inspectProcessTree } = await import("../health-DRywcMxP.js");
3029
3133
  const substrateDirPath = join(projectRoot, ".substrate");
3030
3134
  const processInfo = inspectProcessTree({
3031
3135
  projectRoot,
@@ -3910,7 +4014,7 @@ function defaultSupervisorDeps() {
3910
4014
  if (cached === null) {
3911
4015
  const { AdapterRegistry: AR } = await import(
3912
4016
  /* @vite-ignore */
3913
- "../adapter-registry-DbLuI3IA.js"
4017
+ "../adapter-registry-bsm0SCZW.js"
3914
4018
  );
3915
4019
  cached = new AR();
3916
4020
  await cached.discoverAndRegister();
@@ -4264,10 +4368,17 @@ async function runSupervisorAction(options, deps = {}) {
4264
4368
  }
4265
4369
  while (true) {
4266
4370
  const health = await getHealth({
4267
- runId,
4371
+ runId: state.runId ?? runId,
4268
4372
  projectRoot
4269
4373
  });
4270
4374
  const ts = new Date().toISOString();
4375
+ if (state.runId === void 0 && health.run_id !== null) {
4376
+ state = {
4377
+ ...state,
4378
+ runId: health.run_id
4379
+ };
4380
+ log(`Supervisor: auto-bound to active run ${health.run_id}`);
4381
+ }
4271
4382
  if (outputFormat === "json") {
4272
4383
  const tokenSnapshot = health.run_id !== null ? await getTokenSnapshot(health.run_id, projectRoot) : {
4273
4384
  input: 0,
@@ -4345,11 +4456,11 @@ async function runSupervisorAction(options, deps = {}) {
4345
4456
  try {
4346
4457
  const { createExperimenter } = await import(
4347
4458
  /* @vite-ignore */
4348
- "../experimenter-D0k2wT3I.js"
4459
+ "../experimenter-DV-ZC-uX.js"
4349
4460
  );
4350
4461
  const { getLatestRun: getLatest } = await import(
4351
4462
  /* @vite-ignore */
4352
- "../decisions-CGNEausW.js"
4463
+ "../decisions-DMpHsVUn.js"
4353
4464
  );
4354
4465
  const expAdapter = createDatabaseAdapter({
4355
4466
  backend: "auto",
@@ -4359,7 +4470,7 @@ async function runSupervisorAction(options, deps = {}) {
4359
4470
  await initSchema(expAdapter);
4360
4471
  const { runRunAction: runPipeline } = await import(
4361
4472
  /* @vite-ignore */
4362
- "../run-N5rHJu-Y.js"
4473
+ "../run-m7RCkpmx.js"
4363
4474
  );
4364
4475
  const runStoryFn = async (opts) => {
4365
4476
  const exitCode = await runPipeline({
@@ -4889,7 +5000,7 @@ async function runMetricsAction(options) {
4889
5000
  const routingConfigPath = join(dbDir, "routing.yml");
4890
5001
  let routingConfig = null;
4891
5002
  if (existsSync$1(routingConfigPath)) try {
4892
- const { loadModelRoutingConfig } = await import("../routing-B1aoIz7L.js");
5003
+ const { loadModelRoutingConfig } = await import("../routing-CXLeUI-t.js");
4893
5004
  routingConfig = loadModelRoutingConfig(routingConfigPath);
4894
5005
  } catch {}
4895
5006
  if (routingConfig === null) routingConfig = {
@@ -8726,8 +8837,8 @@ async function createProgram() {
8726
8837
  /** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
8727
8838
  function checkForUpdatesInBackground(currentVersion) {
8728
8839
  if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
8729
- import("../upgrade-DPdh5w4p.js").then(async () => {
8730
- const { createVersionManager } = await import("../version-manager-impl-BHnUB2tl.js");
8840
+ import("../upgrade-CbwnF2hv.js").then(async () => {
8841
+ const { createVersionManager } = await import("../version-manager-impl-DBx3ovp9.js");
8731
8842
  const vm = createVersionManager();
8732
8843
  const result = await vm.checkForUpdates();
8733
8844
  if (result.updateAvailable) {
@@ -1,4 +1,4 @@
1
- import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-CLvAwmT7.js";
1
+ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-Bm0qSZer.js";
2
2
  import "./decisions-C0pz9Clx.js";
3
3
 
4
4
  export { getLatestRun };
@@ -3004,12 +3004,15 @@ async function updatePipelineRunConfig(adapter, id, configJson) {
3004
3004
  async function createPipelineRun(adapter, input) {
3005
3005
  const validated = CreatePipelineRunInputSchema.parse(input);
3006
3006
  const id = crypto.randomUUID();
3007
- await adapter.query(`INSERT INTO pipeline_runs (id, methodology, current_phase, status, config_json)
3008
- VALUES (?, ?, ?, 'running', ?)`, [
3007
+ const nowUtc = new Date().toISOString();
3008
+ await adapter.query(`INSERT INTO pipeline_runs (id, methodology, current_phase, status, config_json, created_at, updated_at)
3009
+ VALUES (?, ?, ?, 'running', ?, ?, ?)`, [
3009
3010
  id,
3010
3011
  validated.methodology,
3011
3012
  validated.start_phase ?? null,
3012
- validated.config_json ?? null
3013
+ validated.config_json ?? null,
3014
+ nowUtc,
3015
+ nowUtc
3013
3016
  ]);
3014
3017
  const rows = await adapter.query("SELECT * FROM pipeline_runs WHERE id = ?", [id]);
3015
3018
  return rows[0];
@@ -10236,4 +10239,4 @@ async function callLLM(params) {
10236
10239
 
10237
10240
  //#endregion
10238
10241
  export { ADVISORY_NOTES, AdapterRegistry, AdtError, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, Categorizer, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, ConsumerAnalyzer, CostTrackerConfigSchema, DEFAULT_CONFIG, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, DoltNotInstalled, DoltQueryError, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, GeminiCLIAdapter, GlobalSettingsSchema, IngestionServer, LogTurnAnalyzer, ModelRoutingConfigSchema, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProviderPolicySchema, ProvidersSchema, Recommender, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TASK_TYPE_PHASE_MAP, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryConfigSchema, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, VersionManagerImpl, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, callLLM, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDatabaseAdapter as createDatabaseAdapter$1, createDecision, createDoltClient, createExperimenter, createPipelineRun, createRequirement, createVersionManager, detectInterfaceChanges, determineVerdict, getActiveDecisions, getAllCostEntriesFiltered, getArtifactByTypeForRun, getArtifactsByRun, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getModelTier, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadModelRoutingConfig, loadParentRunDecisions, registerArtifact, resolvePromptFile, supersedeDecision, tagRunAsBaseline, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics };
10239
- //# sourceMappingURL=dist-CLvAwmT7.js.map
10242
+ //# sourceMappingURL=dist-Bm0qSZer.js.map
@@ -1,4 +1,4 @@
1
- import { AdtError } from "./dist-CLvAwmT7.js";
1
+ import { AdtError } from "./dist-Bm0qSZer.js";
2
2
 
3
3
  //#region src/core/errors.ts
4
4
  /** Error thrown when task configuration is invalid */
@@ -71,4 +71,4 @@ var TaskGraphIncompatibleFormatError = class extends AdtError {
71
71
 
72
72
  //#endregion
73
73
  export { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError };
74
- //# sourceMappingURL=errors-D1LU8CZ9.js.map
74
+ //# sourceMappingURL=errors-BSpu7pIv.js.map
@@ -1,3 +1,3 @@
1
- import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-CLvAwmT7.js";
1
+ import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-Bm0qSZer.js";
2
2
 
3
3
  export { createExperimenter };
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-CLvAwmT7.js";
2
+ import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-Bm0qSZer.js";
3
3
  import { createRequire } from "module";
4
4
  import { dirname, join } from "path";
5
5
  import { existsSync, readFileSync } from "node:fs";
@@ -1930,4 +1930,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
1930
1930
 
1931
1931
  //#endregion
1932
1932
  export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createStateStore, detectCycles, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runHealthAction, validateStoryKey };
1933
- //# sourceMappingURL=health-DswaC1q5.js.map
1933
+ //# sourceMappingURL=health-Cx2ZhRNT.js.map
@@ -1,6 +1,6 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-DswaC1q5.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-Cx2ZhRNT.js";
2
2
  import "./logger-KeHncl-f.js";
3
- import "./dist-CLvAwmT7.js";
3
+ import "./dist-Bm0qSZer.js";
4
4
  import "./decisions-C0pz9Clx.js";
5
5
 
6
6
  export { inspectProcessTree };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { childLogger, createLogger, logger } from "./logger-KeHncl-f.js";
2
2
  import { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-CElYrONe.js";
3
- import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-CLvAwmT7.js";
3
+ import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-Bm0qSZer.js";
4
4
  import "./adapter-registry-DXLMTmfD.js";
5
- import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-D1LU8CZ9.js";
5
+ import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-BSpu7pIv.js";
6
6
 
7
7
  //#region src/core/di.ts
8
8
  /**
@@ -1,4 +1,4 @@
1
- import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-CLvAwmT7.js";
1
+ import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-Bm0qSZer.js";
2
2
  import "./routing-CcBOCuC9.js";
3
3
 
4
4
  export { loadModelRoutingConfig };
@@ -1,7 +1,7 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, resolveMainRepoRoot, validateStoryKey } from "./health-DswaC1q5.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, resolveMainRepoRoot, validateStoryKey } from "./health-Cx2ZhRNT.js";
2
2
  import { createLogger } from "./logger-KeHncl-f.js";
3
3
  import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
4
- import { ADVISORY_NOTES, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getPipelineRunById, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, loadModelRoutingConfig, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-CLvAwmT7.js";
4
+ import { ADVISORY_NOTES, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getPipelineRunById, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, loadModelRoutingConfig, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-Bm0qSZer.js";
5
5
  import { basename, dirname, extname, join } from "path";
6
6
  import { access, readFile, readdir, stat } from "fs/promises";
7
7
  import { EventEmitter } from "node:events";
@@ -10149,6 +10149,9 @@ function createImplementationOrchestrator(deps) {
10149
10149
  completedDispatches: completed,
10150
10150
  queuedDispatches: queued
10151
10151
  });
10152
+ if (config.pipelineRunId !== void 0) updatePipelineRun(db, config.pipelineRunId, { current_phase: "implementation" }).catch((err) => {
10153
+ logger$21.debug({ err }, "Heartbeat: failed to touch updated_at (non-fatal)");
10154
+ });
10152
10155
  const elapsed = Date.now() - _lastProgressTs;
10153
10156
  let childPids = [];
10154
10157
  let childActive = false;
@@ -22250,12 +22253,17 @@ var RunStateManager = class {
22250
22253
  * or `PARTIAL_SUCCESS` for the pipeline to exit normally.
22251
22254
  *
22252
22255
  * Story 42-16.
22256
+ * Story 49-3: AutoSummarizer integration for long-running convergence loops.
22253
22257
  */
22254
22258
  /**
22255
22259
  * Create a new `ConvergenceController` instance backed by an in-memory outcome map.
22260
+ *
22261
+ * @param config - Optional configuration. Pass `{ autoSummarizer }` to enable
22262
+ * automatic context compression in long-running convergence loops.
22256
22263
  */
22257
- function createConvergenceController() {
22264
+ function createConvergenceController(config) {
22258
22265
  const outcomes = new Map();
22266
+ let storedContexts = [];
22259
22267
  /** Returns true only when id is non-empty AND exists in graph.nodes. */
22260
22268
  function isValidTarget(id, graph) {
22261
22269
  return id !== "" && graph.nodes.has(id);
@@ -22315,6 +22323,23 @@ function createConvergenceController() {
22315
22323
  ];
22316
22324
  for (const candidate of candidates) if (isValidTarget(candidate, graph)) return candidate;
22317
22325
  return null;
22326
+ },
22327
+ recordIterationContext(ctx) {
22328
+ storedContexts.push(ctx);
22329
+ },
22330
+ async prepareForIteration(currentIndex) {
22331
+ if (!config?.autoSummarizer || storedContexts.length === 0) return storedContexts;
22332
+ const uncompressedContexts = storedContexts.filter((c) => !("compressed" in c));
22333
+ if (config.autoSummarizer.shouldTrigger(uncompressedContexts)) {
22334
+ const compressionResult = await config.autoSummarizer.compress(uncompressedContexts, currentIndex);
22335
+ const alreadyCompressed = storedContexts.filter((c) => "compressed" in c);
22336
+ const merged = [...alreadyCompressed, ...compressionResult.iterations].sort((a, b) => a.index - b.index);
22337
+ storedContexts = merged;
22338
+ }
22339
+ return storedContexts;
22340
+ },
22341
+ getStoredContexts() {
22342
+ return storedContexts;
22318
22343
  }
22319
22344
  };
22320
22345
  }
@@ -22925,6 +22950,43 @@ async function getFactoryRunSummaries(adapter, limit = 20) {
22925
22950
  });
22926
22951
  }
22927
22952
 
22953
+ //#endregion
22954
+ //#region packages/factory/dist/graph/fidelity.js
22955
+ /**
22956
+ * Map a raw fidelity string to a SummaryLevel for context compression.
22957
+ *
22958
+ * Returns null when no summarization should be applied (fidelity is 'full',
22959
+ * empty, or an unrecognized value). Used by the executor before every node
22960
+ * dispatch to determine whether to call summaryEngine.summarize().
22961
+ */
22962
+ function parseFidelityLevel(fidelity) {
22963
+ const FIDELITY_MAP = {
22964
+ high: "high",
22965
+ "summary:high": "high",
22966
+ medium: "medium",
22967
+ "summary:medium": "medium",
22968
+ low: "low",
22969
+ draft: "low",
22970
+ "summary:low": "low"
22971
+ };
22972
+ return FIDELITY_MAP[fidelity] ?? null;
22973
+ }
22974
+ /**
22975
+ * Resolve the effective fidelity string for a node about to be dispatched.
22976
+ *
22977
+ * Precedence (highest to lowest):
22978
+ * 1. incomingEdge.fidelity (non-empty)
22979
+ * 2. node.fidelity (non-empty)
22980
+ * 3. graph.defaultFidelity (non-empty)
22981
+ * 4. '' (no fidelity set — parseFidelityLevel will return null)
22982
+ */
22983
+ function resolveFidelity(node, incomingEdge, graph) {
22984
+ if (incomingEdge?.fidelity) return incomingEdge.fidelity;
22985
+ if (node.fidelity) return node.fidelity;
22986
+ if (graph.defaultFidelity) return graph.defaultFidelity;
22987
+ return "";
22988
+ }
22989
+
22928
22990
  //#endregion
22929
22991
  //#region packages/factory/dist/graph/executor.js
22930
22992
  /**
@@ -23060,6 +23122,7 @@ function createGraphExecutor() {
23060
23122
  let firstResumedFidelity = "";
23061
23123
  let skipCycleCheck = false;
23062
23124
  let skipCompletedPush = false;
23125
+ let lastIncomingEdge = void 0;
23063
23126
  let scenarioManifest = null;
23064
23127
  if (config.scenarioStore) scenarioManifest = await config.scenarioStore.discover();
23065
23128
  const runStateManager = config.dotSource ? new RunStateManager({ runDir: config.logsRoot }) : null;
@@ -23207,6 +23270,7 @@ function createGraphExecutor() {
23207
23270
  satisfactionScoreHistory: plateauResult.scores
23208
23271
  });
23209
23272
  injectRemediationContext(context, remediation);
23273
+ await controller.prepareForIteration(convergenceIteration);
23210
23274
  skipCycleCheck = true;
23211
23275
  currentNode = retryNode;
23212
23276
  continue;
@@ -23273,6 +23337,25 @@ function createGraphExecutor() {
23273
23337
  fidelity: firstResumedFidelity
23274
23338
  } : currentNode;
23275
23339
  firstResumedFidelity = "";
23340
+ if (config.summaryEngine) {
23341
+ const effectiveFidelity = resolveFidelity(nodeToDispatch, lastIncomingEdge, graph);
23342
+ const summaryLevel = parseFidelityLevel(effectiveFidelity);
23343
+ if (summaryLevel !== null) {
23344
+ const nodeContextContent = context.getString("factory.nodeContext", "");
23345
+ if (nodeContextContent !== "") {
23346
+ const summary = await config.summaryEngine.summarize(nodeContextContent, summaryLevel);
23347
+ context.set("factory.compressedNodeContext", summary.content);
23348
+ context.set("factory.nodeContext", summary.content);
23349
+ config.eventBus?.emit("graph:context-summarized", {
23350
+ runId: config.runId,
23351
+ nodeId: nodeToDispatch.id,
23352
+ level: summaryLevel,
23353
+ originalTokenCount: summary.originalTokenCount ?? 0,
23354
+ summaryTokenCount: summary.summaryTokenCount ?? 0
23355
+ });
23356
+ }
23357
+ }
23358
+ }
23276
23359
  const startedAt = Date.now();
23277
23360
  let outcome = await dispatchWithRetry(nodeToDispatch, context, graph, config, nodeRetries);
23278
23361
  if (Date.now() - startedAt < 50) await new Promise((r) => setTimeout(r, 50));
@@ -23311,6 +23394,11 @@ function createGraphExecutor() {
23311
23394
  {
23312
23395
  const controllerStatus = outcome.status === "SUCCESS" ? "SUCCESS" : outcome.status === "PARTIAL_SUCCESS" ? "PARTIAL_SUCCESS" : "FAILURE";
23313
23396
  controller.recordOutcome(nodeToDispatch.id, controllerStatus);
23397
+ const iterContent = context.getString("factory.nodeContext", "");
23398
+ controller.recordIterationContext({
23399
+ index: convergenceIteration,
23400
+ content: iterContent
23401
+ });
23314
23402
  }
23315
23403
  if (outcome.contextUpdates) for (const [key, value] of Object.entries(outcome.contextUpdates)) context.set(key, value);
23316
23404
  context.set("outcome", outcome.status.toLowerCase());
@@ -23398,6 +23486,7 @@ function createGraphExecutor() {
23398
23486
  }
23399
23487
  const nextNode = graph.nodes.get(edge.toNode);
23400
23488
  if (!nextNode) throw new Error(`Edge target node "${edge.toNode}" not found in graph`);
23489
+ lastIncomingEdge = edge;
23401
23490
  currentNode = nextNode;
23402
23491
  }
23403
23492
  } };
@@ -36236,6 +36325,419 @@ function registerScenariosCommand(program) {
36236
36325
  });
36237
36326
  }
36238
36327
 
36328
+ //#endregion
36329
+ //#region packages/factory/dist/context/summary-cache.js
36330
+ var SummaryCache = class {
36331
+ config;
36332
+ constructor(config) {
36333
+ this.config = config;
36334
+ }
36335
+ summaryPath(hash, level) {
36336
+ return join$1(this.config.storageDir, this.config.runId, "summaries", `${hash}-${level}.json`);
36337
+ }
36338
+ originalPath(hash) {
36339
+ return join$1(this.config.storageDir, this.config.runId, "summaries", `${hash}.orig`);
36340
+ }
36341
+ async put(summary, originalContent) {
36342
+ const dir = join$1(this.config.storageDir, this.config.runId, "summaries");
36343
+ await mkdir$1(dir, { recursive: true });
36344
+ const record = {
36345
+ summary,
36346
+ cachedAt: new Date().toISOString()
36347
+ };
36348
+ await writeFile$1(this.summaryPath(summary.originalHash, summary.level), JSON.stringify(record, null, 2));
36349
+ if (originalContent !== void 0 && this.config.storeOriginals !== false) await writeFile$1(this.originalPath(summary.originalHash), originalContent);
36350
+ }
36351
+ async get(originalHash, level) {
36352
+ try {
36353
+ const raw = await readFile$1(this.summaryPath(originalHash, level), "utf-8");
36354
+ const record = JSON.parse(raw);
36355
+ return record.summary;
36356
+ } catch (err) {
36357
+ if (err.code === "ENOENT") return null;
36358
+ throw err;
36359
+ }
36360
+ }
36361
+ async getOriginal(originalHash) {
36362
+ try {
36363
+ return await readFile$1(this.originalPath(originalHash), "utf-8");
36364
+ } catch (err) {
36365
+ if (err.code === "ENOENT") return null;
36366
+ throw err;
36367
+ }
36368
+ }
36369
+ };
36370
+ var CachingSummaryEngine = class {
36371
+ inner;
36372
+ cache;
36373
+ name;
36374
+ constructor(inner, cache) {
36375
+ this.inner = inner;
36376
+ this.cache = cache;
36377
+ this.name = `caching(${inner.name})`;
36378
+ }
36379
+ async summarize(content, targetLevel, opts) {
36380
+ const originalHash = createHash("sha256").update(content).digest("hex");
36381
+ const cached = await this.cache.get(originalHash, targetLevel);
36382
+ if (cached !== null) return cached;
36383
+ const summary = await this.inner.summarize(content, targetLevel, opts);
36384
+ await this.cache.put(summary, content);
36385
+ return summary;
36386
+ }
36387
+ async expand(summary, targetLevel, opts) {
36388
+ const original = await this.cache.getOriginal(summary.originalHash);
36389
+ if (original !== null) return original;
36390
+ return this.inner.expand(summary, targetLevel, opts);
36391
+ }
36392
+ };
36393
+
36394
+ //#endregion
36395
+ //#region packages/factory/dist/context/summary-metrics.js
36396
+ /**
36397
+ * Compute the compression ratio of a summary.
36398
+ * Returns summaryTokenCount / originalTokenCount in [0, 1].
36399
+ * Returns -1 as a sentinel when token counts are absent or originalTokenCount is zero.
36400
+ */
36401
+ function computeCompressionRatio(summary) {
36402
+ if (summary.originalTokenCount === void 0 || summary.originalTokenCount === 0 || summary.summaryTokenCount === void 0) return -1;
36403
+ return summary.summaryTokenCount / summary.originalTokenCount;
36404
+ }
36405
+ /**
36406
+ * Extract key facts from content:
36407
+ * - Fenced code blocks (triple-backtick)
36408
+ * - File-path tokens matching known extensions
36409
+ * - Error-type names
36410
+ */
36411
+ function extractKeyFacts(content) {
36412
+ const facts = new Set();
36413
+ const codeBlockRegex = /```[\s\S]*?```/g;
36414
+ let match$1;
36415
+ while ((match$1 = codeBlockRegex.exec(content)) !== null) facts.add(match$1[0].trim());
36416
+ const filePathRegex = /[\w./]+(\.ts|\.js|\.json|\.md|\.go|\.py|\.yaml|\.yml)\b/g;
36417
+ while ((match$1 = filePathRegex.exec(content)) !== null) facts.add(match$1[0]);
36418
+ const errorTypeRegex = /\b(Error|Exception|ENOENT|ETIMEDOUT|TypeError|SyntaxError)\b/g;
36419
+ while ((match$1 = errorTypeRegex.exec(content)) !== null) facts.add(match$1[0]);
36420
+ return facts;
36421
+ }
36422
+ /**
36423
+ * Compute the key-fact retention rate between original and summarized content.
36424
+ * Returns the fraction of original key facts that appear in the summarized content.
36425
+ * Returns 1.0 when the original has no key facts.
36426
+ */
36427
+ function computeKeyFactRetentionRate(original, summarized) {
36428
+ const originalFacts = extractKeyFacts(original);
36429
+ const summarizedFacts = extractKeyFacts(summarized);
36430
+ if (originalFacts.size === 0) return 1;
36431
+ const preserved = [...originalFacts].filter((f$1) => summarizedFacts.has(f$1)).length;
36432
+ return preserved / originalFacts.size;
36433
+ }
36434
+
36435
+ //#endregion
36436
+ //#region packages/factory/dist/context/cli-command.js
36437
+ /** Build a CLIJsonOutput envelope. */
36438
+ function buildJsonOutput(command, data, version) {
36439
+ return {
36440
+ timestamp: new Date().toISOString(),
36441
+ version,
36442
+ command,
36443
+ data
36444
+ };
36445
+ }
36446
+ /** Minimal stub SummaryEngine used when no engineFactory is provided. */
36447
+ var StubSummaryEngine = class {
36448
+ name = "stub";
36449
+ async summarize(content, targetLevel) {
36450
+ const originalHash = createHash("sha256").update(content).digest("hex");
36451
+ return {
36452
+ level: targetLevel,
36453
+ content,
36454
+ originalHash,
36455
+ createdAt: new Date().toISOString()
36456
+ };
36457
+ }
36458
+ async expand(summary) {
36459
+ return summary.content;
36460
+ }
36461
+ };
36462
+ /**
36463
+ * Scan all `*.json` summary files in summariesDir to find the most recently
36464
+ * stored summary matching the given iteration number.
36465
+ *
36466
+ * Matches on `record.summary.iterationIndex === iteration`.
36467
+ * Returns null if no match is found.
36468
+ */
36469
+ async function findSummaryForIteration(summariesDir, iteration) {
36470
+ let allFiles;
36471
+ try {
36472
+ allFiles = await readdir$1(summariesDir);
36473
+ } catch {
36474
+ return null;
36475
+ }
36476
+ const jsonFiles = allFiles.filter((f$1) => f$1.endsWith(".json"));
36477
+ const matches = [];
36478
+ for (const file of jsonFiles) try {
36479
+ const raw = await readFile$1(join$1(summariesDir, file), "utf-8");
36480
+ const record = JSON.parse(raw);
36481
+ if (record.summary.iterationIndex === iteration) matches.push({
36482
+ hash: record.summary.originalHash,
36483
+ record,
36484
+ cachedAt: new Date(record.cachedAt).getTime()
36485
+ });
36486
+ } catch {}
36487
+ if (matches.length === 0) return null;
36488
+ matches.sort((a, b) => b.cachedAt - a.cachedAt);
36489
+ const best = matches[0];
36490
+ return {
36491
+ hash: best.hash,
36492
+ record: best.record
36493
+ };
36494
+ }
36495
+ /**
36496
+ * Core logic for `factory context summarize`.
36497
+ *
36498
+ * Loads the original content, runs it through CachingSummaryEngine, stores the
36499
+ * result, and prints compression statistics.
36500
+ *
36501
+ * @returns Exit code: 0 on success, 1 on error.
36502
+ */
36503
+ async function summarizeAction(opts, deps, output = {
36504
+ stdout: process.stdout,
36505
+ stderr: process.stderr
36506
+ }) {
36507
+ const { stdout, stderr } = output;
36508
+ if (!/^\d+$/.test(opts.iteration)) {
36509
+ stderr.write(`Error: --iteration must be a non-negative integer, got: ${opts.iteration}\n`);
36510
+ return 1;
36511
+ }
36512
+ const iteration = parseInt(opts.iteration, 10);
36513
+ const validLevels = [
36514
+ "full",
36515
+ "high",
36516
+ "medium",
36517
+ "low"
36518
+ ];
36519
+ if (!validLevels.includes(opts.level)) {
36520
+ stderr.write(`Error: --level must be one of: full, high, medium, low. Got: ${opts.level}\n`);
36521
+ return 1;
36522
+ }
36523
+ const level = opts.level;
36524
+ const summariesDir = join$1(deps.storageDir, "runs", opts.run, "summaries");
36525
+ try {
36526
+ await stat$1(summariesDir);
36527
+ } catch {
36528
+ stderr.write(`Error: Run directory not found: ${summariesDir}\n`);
36529
+ return 1;
36530
+ }
36531
+ const found = await findSummaryForIteration(summariesDir, iteration);
36532
+ if (!found) {
36533
+ stderr.write(`Error: No summary found for iteration ${iteration} in run ${opts.run}\n`);
36534
+ return 1;
36535
+ }
36536
+ const cache = new SummaryCache({
36537
+ runId: opts.run,
36538
+ storageDir: join$1(deps.storageDir, "runs")
36539
+ });
36540
+ const originalContent = await cache.getOriginal(found.hash);
36541
+ if (originalContent === null) {
36542
+ stderr.write(`Error: Original content (.orig) not found for hash ${found.hash.slice(0, 8)} in run ${opts.run}\n`);
36543
+ return 1;
36544
+ }
36545
+ const innerEngine = deps.engineFactory ? deps.engineFactory() : new StubSummaryEngine();
36546
+ const engine = new CachingSummaryEngine(innerEngine, cache);
36547
+ const summary = await engine.summarize(originalContent, level);
36548
+ await cache.put(summary, originalContent);
36549
+ const compressionRatio = computeCompressionRatio(summary);
36550
+ if (opts.outputFormat === "json") {
36551
+ const data = {
36552
+ hash: summary.originalHash,
36553
+ level: summary.level,
36554
+ compressionRatio,
36555
+ summaryTokenCount: summary.summaryTokenCount,
36556
+ originalTokenCount: summary.originalTokenCount
36557
+ };
36558
+ stdout.write(JSON.stringify(buildJsonOutput("factory context summarize", data, deps.version)) + "\n");
36559
+ } else {
36560
+ const ratioStr = compressionRatio >= 0 ? compressionRatio.toFixed(2) : "n/a";
36561
+ stdout.write(`Summarized iteration ${iteration} → level ${level} | hash: ${summary.originalHash.slice(0, 8)} | compression: ${ratioStr}\n`);
36562
+ }
36563
+ return 0;
36564
+ }
36565
+ /**
36566
+ * Core logic for `factory context expand`.
36567
+ *
36568
+ * Finds the stored summary for the given iteration, then expands it back
36569
+ * toward full content (lossless if .orig exists, LLM fallback otherwise).
36570
+ *
36571
+ * @returns Exit code: 0 on success, 1 on error.
36572
+ */
36573
+ async function expandAction(opts, deps, output = {
36574
+ stdout: process.stdout,
36575
+ stderr: process.stderr
36576
+ }) {
36577
+ const { stdout, stderr } = output;
36578
+ if (!/^\d+$/.test(opts.iteration)) {
36579
+ stderr.write(`Error: --iteration must be a non-negative integer, got: ${opts.iteration}\n`);
36580
+ return 1;
36581
+ }
36582
+ const iteration = parseInt(opts.iteration, 10);
36583
+ const summariesDir = join$1(deps.storageDir, "runs", opts.run, "summaries");
36584
+ try {
36585
+ await stat$1(summariesDir);
36586
+ } catch {
36587
+ stderr.write(`Error: Run directory not found: ${summariesDir}\n`);
36588
+ return 1;
36589
+ }
36590
+ const found = await findSummaryForIteration(summariesDir, iteration);
36591
+ if (!found) {
36592
+ stderr.write(`Error: No summary found for iteration ${iteration} in run ${opts.run}\n`);
36593
+ return 1;
36594
+ }
36595
+ const cache = new SummaryCache({
36596
+ runId: opts.run,
36597
+ storageDir: join$1(deps.storageDir, "runs")
36598
+ });
36599
+ const innerEngine = deps.engineFactory ? deps.engineFactory() : new StubSummaryEngine();
36600
+ const engine = new CachingSummaryEngine(innerEngine, cache);
36601
+ const expandedContent = await engine.expand(found.record.summary, "full");
36602
+ if (opts.outputFormat === "json") {
36603
+ const data = {
36604
+ hash: found.record.summary.originalHash,
36605
+ level: found.record.summary.level,
36606
+ expandedLength: expandedContent.length,
36607
+ content: expandedContent
36608
+ };
36609
+ stdout.write(JSON.stringify(buildJsonOutput("factory context expand", data, deps.version)) + "\n");
36610
+ } else stdout.write(expandedContent + "\n");
36611
+ return 0;
36612
+ }
36613
+ /**
36614
+ * Core logic for `factory context stats`.
36615
+ *
36616
+ * Reads all stored summary records for a run, computes compression metrics,
36617
+ * and prints a formatted table (or JSON array).
36618
+ *
36619
+ * @returns Exit code: 0 on success, 1 on error.
36620
+ */
36621
+ async function statsAction(opts, deps, output = {
36622
+ stdout: process.stdout,
36623
+ stderr: process.stderr
36624
+ }) {
36625
+ const { stdout, stderr } = output;
36626
+ const summariesDir = join$1(deps.storageDir, "runs", opts.run, "summaries");
36627
+ try {
36628
+ await stat$1(summariesDir);
36629
+ } catch {
36630
+ stderr.write(`Error: Run directory not found: ${summariesDir}\n`);
36631
+ return 1;
36632
+ }
36633
+ let allFiles;
36634
+ try {
36635
+ allFiles = await readdir$1(summariesDir);
36636
+ } catch {
36637
+ stderr.write(`Error: Could not read summaries directory: ${summariesDir}\n`);
36638
+ return 1;
36639
+ }
36640
+ const jsonFiles = allFiles.filter((f$1) => f$1.endsWith(".json"));
36641
+ const rows = [];
36642
+ for (const file of jsonFiles) try {
36643
+ const raw = await readFile$1(join$1(summariesDir, file), "utf-8");
36644
+ const record = JSON.parse(raw);
36645
+ const compressionRatio = computeCompressionRatio(record.summary);
36646
+ let keyFactRetentionRate = -1;
36647
+ try {
36648
+ const origPath = join$1(summariesDir, `${record.summary.originalHash}.orig`);
36649
+ const originalContent = await readFile$1(origPath, "utf-8");
36650
+ keyFactRetentionRate = computeKeyFactRetentionRate(originalContent, record.summary.content);
36651
+ } catch {}
36652
+ rows.push({
36653
+ hash: record.summary.originalHash,
36654
+ level: record.summary.level,
36655
+ compressionRatio,
36656
+ keyFactRetentionRate,
36657
+ cachedAt: record.cachedAt
36658
+ });
36659
+ } catch {}
36660
+ rows.sort((a, b) => new Date(a.cachedAt).getTime() - new Date(b.cachedAt).getTime());
36661
+ if (opts.outputFormat === "json") {
36662
+ stdout.write(JSON.stringify(buildJsonOutput("factory context stats", rows, deps.version)) + "\n");
36663
+ return 0;
36664
+ }
36665
+ if (rows.length === 0) {
36666
+ stdout.write("No summaries found.\n");
36667
+ return 0;
36668
+ }
36669
+ const headers = [
36670
+ "Hash",
36671
+ "Level",
36672
+ "CompRatio",
36673
+ "KeyRetention",
36674
+ "CachedAt"
36675
+ ];
36676
+ const tableRows = rows.map((row) => ({
36677
+ Hash: row.hash.slice(0, 8),
36678
+ Level: row.level,
36679
+ CompRatio: row.compressionRatio >= 0 ? row.compressionRatio.toFixed(4) : "n/a",
36680
+ KeyRetention: row.keyFactRetentionRate >= 0 ? row.keyFactRetentionRate.toFixed(4) : "n/a",
36681
+ CachedAt: row.cachedAt
36682
+ }));
36683
+ const widths = headers.map((h) => {
36684
+ const dataMax = tableRows.reduce((max, row) => {
36685
+ const val = row[h] ?? "";
36686
+ return Math.max(max, val.length);
36687
+ }, 0);
36688
+ return Math.max(h.length, dataMax);
36689
+ });
36690
+ const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(" | ");
36691
+ const separator = widths.map((w) => "-".repeat(w)).join("-+-");
36692
+ stdout.write(headerLine + "\n");
36693
+ stdout.write(separator + "\n");
36694
+ for (const row of tableRows) {
36695
+ const line = headers.map((h, i) => (row[h] ?? "").padEnd(widths[i])).join(" | ");
36696
+ stdout.write(line + "\n");
36697
+ }
36698
+ return 0;
36699
+ }
36700
+ /**
36701
+ * Register the `context` subcommand group on the provided factory command.
36702
+ *
36703
+ * Subcommands registered:
36704
+ * factory context summarize --run <id> --iteration <n> --level <level>
36705
+ * factory context expand --run <id> --iteration <n>
36706
+ * factory context stats --run <id>
36707
+ *
36708
+ * @param factoryCmd - The factory Commander command to attach to
36709
+ * @param version - CLI version string for JSON output (e.g. "1.2.3")
36710
+ * @param storageDir - Base storage directory (defaults to `{cwd}/.substrate`)
36711
+ * @param engineFactory - Optional SummaryEngine factory for testing injection
36712
+ */
36713
+ function registerContextCommand(factoryCmd, version, storageDir, engineFactory) {
36714
+ const resolvedStorageDir = storageDir ?? join$1(process.cwd(), ".substrate");
36715
+ const contextCmd = factoryCmd.command("context").description("Inspect and manage pyramid summaries for factory runs");
36716
+ contextCmd.command("summarize").description("Compress and store a run iteration to the target summary level").requiredOption("--run <id>", "Run ID").requiredOption("--iteration <n>", "Iteration number").requiredOption("--level <level>", "Summary level: high | medium | low").option("--output-format <format>", "Output format: text | json", "text").action(async (opts) => {
36717
+ const code = await summarizeAction(opts, {
36718
+ storageDir: resolvedStorageDir,
36719
+ version,
36720
+ ...engineFactory !== void 0 ? { engineFactory } : {}
36721
+ });
36722
+ if (code !== 0) process.exit(code);
36723
+ });
36724
+ contextCmd.command("expand").description("Expand a stored summary for a run iteration back to full content").requiredOption("--run <id>", "Run ID").requiredOption("--iteration <n>", "Iteration number").option("--output-format <format>", "Output format: text | json", "text").action(async (opts) => {
36725
+ const code = await expandAction(opts, {
36726
+ storageDir: resolvedStorageDir,
36727
+ version,
36728
+ ...engineFactory !== void 0 ? { engineFactory } : {}
36729
+ });
36730
+ if (code !== 0) process.exit(code);
36731
+ });
36732
+ contextCmd.command("stats").description("Report per-run compression statistics for all stored summaries").requiredOption("--run <id>", "Run ID").option("--output-format <format>", "Output format: text | json", "text").action(async (opts) => {
36733
+ const code = await statsAction(opts, {
36734
+ storageDir: resolvedStorageDir,
36735
+ version
36736
+ });
36737
+ if (code !== 0) process.exit(code);
36738
+ });
36739
+ }
36740
+
36239
36741
  //#endregion
36240
36742
  //#region packages/factory/dist/twins/schema.js
36241
36743
  /**
@@ -37119,6 +37621,7 @@ function registerFactoryCommand(program, options) {
37119
37621
  else process.stdout.write(`✗ ${passedCount}/${TOTAL_RULE_COUNT} rules passed, ${errors.length} ${errLabel}, ${warnings.length} ${warnLabel}\n`);
37120
37622
  if (errors.length > 0) process.exit(1);
37121
37623
  });
37624
+ registerContextCommand(factoryCmd, "0.0.0");
37122
37625
  const twinsCmd = factoryCmd.command("twins").description("Digital twin template management");
37123
37626
  twinsCmd.command("templates").description("List available built-in twin templates").action(() => {
37124
37627
  const templates = listTwinTemplates();
@@ -37757,9 +38260,8 @@ async function runRunAction(options) {
37757
38260
  }
37758
38261
  const staleRuns = await getRunningPipelineRuns(adapter) ?? [];
37759
38262
  if (staleRuns.length > 0) {
37760
- const processInfo = inspectProcessTree({ projectRoot });
37761
38263
  let swept = 0;
37762
- for (const stale of staleRuns) if (processInfo.orchestrator_pid === null) {
38264
+ for (const stale of staleRuns) {
37763
38265
  await updatePipelineRun(adapter, stale.id, { status: "failed" });
37764
38266
  swept++;
37765
38267
  }
@@ -38439,6 +38941,8 @@ async function runFullPipeline(options) {
38439
38941
  input_tokens: result.tokenUsage.input,
38440
38942
  output_tokens: result.tokenUsage.output,
38441
38943
  cost_usd: costUsd
38944
+ }).catch((err) => {
38945
+ logger.warn({ err }, "Failed to record analysis token usage (non-fatal)");
38442
38946
  });
38443
38947
  }
38444
38948
  if (result.result === "failed") {
@@ -38462,6 +38966,8 @@ async function runFullPipeline(options) {
38462
38966
  input_tokens: result.tokenUsage.input,
38463
38967
  output_tokens: result.tokenUsage.output,
38464
38968
  cost_usd: costUsd
38969
+ }).catch((err) => {
38970
+ logger.warn({ err }, "Failed to record planning token usage (non-fatal)");
38465
38971
  });
38466
38972
  }
38467
38973
  if (result.result === "failed") {
@@ -38488,6 +38994,8 @@ async function runFullPipeline(options) {
38488
38994
  input_tokens: result.tokenUsage.input,
38489
38995
  output_tokens: result.tokenUsage.output,
38490
38996
  cost_usd: costUsd
38997
+ }).catch((err) => {
38998
+ logger.warn({ err }, "Failed to record research token usage (non-fatal)");
38491
38999
  });
38492
39000
  }
38493
39001
  if (result.result === "failed") {
@@ -38511,6 +39019,8 @@ async function runFullPipeline(options) {
38511
39019
  input_tokens: result.tokenUsage.input,
38512
39020
  output_tokens: result.tokenUsage.output,
38513
39021
  cost_usd: costUsd
39022
+ }).catch((err) => {
39023
+ logger.warn({ err }, "Failed to record ux-design token usage (non-fatal)");
38514
39024
  });
38515
39025
  }
38516
39026
  if (result.result === "failed") {
@@ -38534,6 +39044,8 @@ async function runFullPipeline(options) {
38534
39044
  input_tokens: result.tokenUsage.input,
38535
39045
  output_tokens: result.tokenUsage.output,
38536
39046
  cost_usd: costUsd
39047
+ }).catch((err) => {
39048
+ logger.warn({ err }, "Failed to record solutioning token usage (non-fatal)");
38537
39049
  });
38538
39050
  }
38539
39051
  if (result.result === "failed") {
@@ -38752,4 +39264,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
38752
39264
 
38753
39265
  //#endregion
38754
39266
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
38755
- //# sourceMappingURL=run-Bku8fmY3.js.map
39267
+ //# sourceMappingURL=run-gXtnH8lO.js.map
@@ -1,8 +1,8 @@
1
- import "./health-DswaC1q5.js";
1
+ import "./health-Cx2ZhRNT.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
- import "./dist-CLvAwmT7.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-Bku8fmY3.js";
4
+ import "./dist-Bm0qSZer.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-gXtnH8lO.js";
6
6
  import "./routing-CcBOCuC9.js";
7
7
  import "./decisions-C0pz9Clx.js";
8
8
 
@@ -1,4 +1,4 @@
1
- import { createVersionManager } from "./dist-CLvAwmT7.js";
1
+ import { createVersionManager } from "./dist-Bm0qSZer.js";
2
2
  import { execSync, spawn } from "child_process";
3
3
  import * as readline from "readline";
4
4
 
@@ -123,4 +123,4 @@ function registerUpgradeCommand(program) {
123
123
 
124
124
  //#endregion
125
125
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
126
- //# sourceMappingURL=upgrade-DT0I_-1E.js.map
126
+ //# sourceMappingURL=upgrade-BcL4ZV3o.js.map
@@ -1,5 +1,5 @@
1
- import "./dist-CLvAwmT7.js";
1
+ import "./dist-Bm0qSZer.js";
2
2
  import "./version-manager-impl-BmOWu8ml.js";
3
- import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-DT0I_-1E.js";
3
+ import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-BcL4ZV3o.js";
4
4
 
5
5
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
@@ -1,4 +1,4 @@
1
- import { VersionManagerImpl, createVersionManager } from "./dist-CLvAwmT7.js";
1
+ import { VersionManagerImpl, createVersionManager } from "./dist-Bm0qSZer.js";
2
2
  import "./version-manager-impl-BmOWu8ml.js";
3
3
 
4
4
  export { createVersionManager };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -68,10 +68,10 @@
68
68
  "substrate:dev": "node dist/cli/index.js"
69
69
  },
70
70
  "dependencies": {
71
- "bmad-method": "^6.0.3",
71
+ "bmad-method": "^6.2.2",
72
72
  "commander": "^12.1.0",
73
73
  "js-yaml": "^4.1.1",
74
- "mysql2": "^3.19.0",
74
+ "mysql2": "^3.20.0",
75
75
  "pino": "^9.6.0",
76
76
  "semver": "^7.6.3",
77
77
  "zod": "^4.3.6"
@@ -1,4 +0,0 @@
1
- import { AdapterRegistry } from "./dist-CLvAwmT7.js";
2
- import "./adapter-registry-DXLMTmfD.js";
3
-
4
- export { AdapterRegistry };