substrate-ai 0.21.13 → 0.21.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-DBBrM_te.js";
2
+ import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-kr5GC1SN.js";
3
3
  import { createLogger } from "../logger-KeHncl-f.js";
4
4
  import { createEventBus } from "../helpers-CElYrONe.js";
5
5
  import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createGitWorktreeManager, createPipelineRun, createStderrLogger, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initWorkGraphSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-BZGqn-XQ.js";
6
6
  import "../adapter-registry-DXLMTmfD.js";
7
- import { ACCEPTANCE_CONTRACT_PROFILE_PATH, JOURNEY_DEFERRALS_PATH, JOURNEY_REGISTRY_PATH, RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, clearGateDemotion, computePrecision, computeRecall, demoteGate, loadAcceptanceContractFromTrustedTree, loadJourneyRegistryFromFile, loadJourneyRegistryFromTrustedTree, parseAcceptanceContract, parseJourneyDeferrals, parseJourneyRegistry, parseRuntimeProbes, readAcceptanceMetrics, readCurrentRunId, readGateState, recordCanary, recordOverride, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck, runCanary } from "../manifest-read-Bq2_Ojbv.js";
8
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-B31go5Ud.js";
7
+ import { ACCEPTANCE_CONTRACT_PROFILE_PATH, JOURNEY_CANDIDATE_PATH, JOURNEY_DEFERRALS_PATH, JOURNEY_REGISTRY_PATH, RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, clearGateDemotion, computePrecision, computeRecall, demoteGate, diffJourneySets, loadAcceptanceContractFromTrustedTree, loadJourneyRegistryFromFile, loadJourneyRegistryFromTrustedTree, parseAcceptanceContract, parseJourneyCandidate, parseJourneyDeferrals, parseJourneyRegistry, parseRuntimeProbes, ratifyCandidate, readAcceptanceMetrics, readCurrentRunId, readGateState, recordCanary, recordOverride, renderRegistryDiff, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck, runCanary } from "../manifest-read-CcK_LIaI.js";
8
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-DR_D61vF.js";
9
9
  import "../errors-xSeGw6pf.js";
10
- import { runAcceptanceJudge } from "../acceptance-judge-eIZZha1C.js";
10
+ import { AcceptanceDeriveResultSchema, assemblePrompt, getTokenCeiling, runAcceptanceJudge } from "../acceptance-judge-lAv5EvYA.js";
11
11
  import "../routing-DZT5PN3N.js";
12
12
  import { WorkGraphRepository } from "../work-graph-repository-4cKsf8Lf.js";
13
13
  import "../decisions-BAaxpVD0.js";
14
14
  import "../decision-router-Dyby0fUf.js";
15
- import "../interactive-prompt-CV9rLUNT.js";
15
+ import "../interactive-prompt-B5KE69I6.js";
16
16
  import "../recovery-engine-dtLHyV4M.js";
17
17
  import "../version-manager-impl-DMTw551Q.js";
18
18
  import { registerUpgradeCommand } from "../upgrade-CNGc12AV.js";
@@ -21,16 +21,16 @@ import { fileURLToPath } from "url";
21
21
  import { dirname, join, resolve } from "path";
22
22
  import { access, mkdir, readFile, readdir, unlink, writeFile } from "fs/promises";
23
23
  import { EventEmitter } from "node:events";
24
- import yaml from "js-yaml";
24
+ import yaml, { dump } from "js-yaml";
25
25
  import * as actualFS from "node:fs";
26
26
  import { existsSync, promises, readFileSync, writeFileSync } from "node:fs";
27
27
  import { execFile, spawnSync } from "node:child_process";
28
28
  import * as path$1 from "node:path";
29
29
  import { basename as basename$1, dirname as dirname$1, join as join$1, posix, relative, resolve as resolve$1, win32 } from "node:path";
30
- import { randomUUID } from "node:crypto";
30
+ import { createHash, randomUUID } from "node:crypto";
31
31
  import { z } from "zod";
32
32
  import * as fs from "node:fs/promises";
33
- import { lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, writeFile as writeFile$1 } from "node:fs/promises";
33
+ import { lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
34
34
  import { chmodSync, cpSync, existsSync as existsSync$1, lstatSync, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdir as readdir$2, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1, rmSync as rmSync$1, statSync as statSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "fs";
35
35
  import { homedir } from "os";
36
36
  import { createRequire } from "node:module";
@@ -39,6 +39,7 @@ import * as readline from "node:readline";
39
39
  import { createInterface } from "node:readline";
40
40
  import { randomUUID as randomUUID$1 } from "crypto";
41
41
  import { createInterface as createInterface$1 } from "readline";
42
+ import { createInterface as createInterface$2 } from "node:readline/promises";
42
43
 
43
44
  //#region packages/core/dist/monitor/recommendation-engine.js
44
45
  var RecommendationEngine = class {
@@ -46,14 +47,14 @@ var RecommendationEngine = class {
46
47
  _filters;
47
48
  _historyDays;
48
49
  _logger;
49
- constructor(monitorDb, config = {}, logger$19) {
50
+ constructor(monitorDb, config = {}, logger$20) {
50
51
  this._monitorDb = monitorDb;
51
52
  this._filters = {
52
53
  threshold_percentage: config.recommendation_threshold_percentage ?? 5,
53
54
  min_sample_size: config.min_sample_size ?? 10
54
55
  };
55
56
  this._historyDays = config.recommendation_history_days ?? 90;
56
- this._logger = logger$19 ?? createStderrLogger("monitor:recommendation-engine");
57
+ this._logger = logger$20 ?? createStderrLogger("monitor:recommendation-engine");
57
58
  }
58
59
  generateRecommendations() {
59
60
  const sinceDate = new Date(Date.now() - this._historyDays * 24 * 60 * 60 * 1e3).toISOString();
@@ -1311,7 +1312,7 @@ function buildStackAwareDevNotes(profile) {
1311
1312
 
1312
1313
  //#endregion
1313
1314
  //#region src/cli/commands/init.ts
1314
- const logger$18 = createLogger("init");
1315
+ const logger$19 = createLogger("init");
1315
1316
  const __dirname = dirname(new URL(import.meta.url).pathname);
1316
1317
  const SCAFFOLD_VERSION_REGEX = /<!-- substrate:version=([\d.]+) -->/;
1317
1318
  /**
@@ -1352,7 +1353,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
1352
1353
  const version = resolveBmadMethodVersion();
1353
1354
  if (force && bmadExists) process.stderr.write(`Warning: Replacing existing _bmad/ framework with bmad-method@${version}\n`);
1354
1355
  process.stdout.write(`Scaffolding BMAD framework from bmad-method@${version}\n`);
1355
- logger$18.info({
1356
+ logger$19.info({
1356
1357
  version,
1357
1358
  dest: bmadDest
1358
1359
  }, "Scaffolding BMAD framework");
@@ -1362,7 +1363,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
1362
1363
  const destDir = join(bmadDest, dir);
1363
1364
  mkdirSync$1(destDir, { recursive: true });
1364
1365
  cpSync(srcDir, destDir, { recursive: true });
1365
- logger$18.info({
1366
+ logger$19.info({
1366
1367
  dir,
1367
1368
  dest: destDir
1368
1369
  }, "Scaffolded BMAD framework directory");
@@ -1381,7 +1382,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
1381
1382
  "document_output_language: English"
1382
1383
  ].join("\n") + "\n";
1383
1384
  await writeFile(configFile, configStub, "utf8");
1384
- logger$18.info({ configFile }, "Generated _bmad/_config/config.yaml stub");
1385
+ logger$19.info({ configFile }, "Generated _bmad/_config/config.yaml stub");
1385
1386
  }
1386
1387
  }
1387
1388
  const CLAUDE_MD_START_MARKER = "<!-- substrate:start -->";
@@ -1396,7 +1397,7 @@ async function scaffoldClaudeMd(projectRoot, profile) {
1396
1397
  try {
1397
1398
  sectionContent = await readFile(templatePath, "utf8");
1398
1399
  } catch {
1399
- logger$18.warn({ templatePath }, "CLAUDE.md substrate section template not found; skipping");
1400
+ logger$19.warn({ templatePath }, "CLAUDE.md substrate section template not found; skipping");
1400
1401
  return;
1401
1402
  }
1402
1403
  const substrateVersion = readSubstrateVersion(pkgRoot);
@@ -1432,7 +1433,7 @@ async function scaffoldClaudeMd(projectRoot, profile) {
1432
1433
  else newContent = updatedExisting;
1433
1434
  }
1434
1435
  await writeFile(claudeMdPath, newContent, "utf8");
1435
- logger$18.info({ claudeMdPath }, "Wrote substrate section to CLAUDE.md");
1436
+ logger$19.info({ claudeMdPath }, "Wrote substrate section to CLAUDE.md");
1436
1437
  }
1437
1438
  async function scaffoldAgentsMd(projectRoot, profile) {
1438
1439
  const agentsMdPath = join(projectRoot, "AGENTS.md");
@@ -1444,7 +1445,7 @@ async function scaffoldAgentsMd(projectRoot, profile) {
1444
1445
  try {
1445
1446
  sectionContent = await readFile(templatePath, "utf8");
1446
1447
  } catch {
1447
- logger$18.warn({ templatePath }, "AGENTS.md substrate section template not found; skipping");
1448
+ logger$19.warn({ templatePath }, "AGENTS.md substrate section template not found; skipping");
1448
1449
  return;
1449
1450
  }
1450
1451
  const substrateVersion = readSubstrateVersion(pkgRoot);
@@ -1465,7 +1466,7 @@ async function scaffoldAgentsMd(projectRoot, profile) {
1465
1466
  newContent = existingContent + separator + sectionContent;
1466
1467
  }
1467
1468
  await writeFile(agentsMdPath, newContent, "utf8");
1468
- logger$18.info({ agentsMdPath }, "Wrote substrate section to AGENTS.md");
1469
+ logger$19.info({ agentsMdPath }, "Wrote substrate section to AGENTS.md");
1469
1470
  }
1470
1471
  async function scaffoldGeminiMd(projectRoot, profile) {
1471
1472
  const geminiMdPath = join(projectRoot, "GEMINI.md");
@@ -1477,7 +1478,7 @@ async function scaffoldGeminiMd(projectRoot, profile) {
1477
1478
  try {
1478
1479
  sectionContent = await readFile(templatePath, "utf8");
1479
1480
  } catch {
1480
- logger$18.warn({ templatePath }, "GEMINI.md substrate section template not found; skipping");
1481
+ logger$19.warn({ templatePath }, "GEMINI.md substrate section template not found; skipping");
1481
1482
  return;
1482
1483
  }
1483
1484
  const substrateVersion = readSubstrateVersion(pkgRoot);
@@ -1498,7 +1499,7 @@ async function scaffoldGeminiMd(projectRoot, profile) {
1498
1499
  newContent = existingContent + separator + sectionContent;
1499
1500
  }
1500
1501
  await writeFile(geminiMdPath, newContent, "utf8");
1501
- logger$18.info({ geminiMdPath }, "Wrote substrate section to GEMINI.md");
1502
+ logger$19.info({ geminiMdPath }, "Wrote substrate section to GEMINI.md");
1502
1503
  }
1503
1504
  async function scaffoldStatuslineScript(projectRoot) {
1504
1505
  const pkgRoot = findPackageRoot(__dirname);
@@ -1509,7 +1510,7 @@ async function scaffoldStatuslineScript(projectRoot) {
1509
1510
  try {
1510
1511
  content = await readFile(templatePath, "utf8");
1511
1512
  } catch {
1512
- logger$18.warn({ templatePath }, "statusline.sh template not found; skipping");
1513
+ logger$19.warn({ templatePath }, "statusline.sh template not found; skipping");
1513
1514
  return;
1514
1515
  }
1515
1516
  const claudeDir = join(projectRoot, ".claude");
@@ -1517,7 +1518,7 @@ async function scaffoldStatuslineScript(projectRoot) {
1517
1518
  mkdirSync$1(claudeDir, { recursive: true });
1518
1519
  await writeFile(statuslinePath, content, "utf8");
1519
1520
  chmodSync(statuslinePath, 493);
1520
- logger$18.info({ statuslinePath }, "Wrote .claude/statusline.sh");
1521
+ logger$19.info({ statuslinePath }, "Wrote .claude/statusline.sh");
1521
1522
  }
1522
1523
  async function scaffoldClaudeSettings(projectRoot) {
1523
1524
  const claudeDir = join(projectRoot, ".claude");
@@ -1533,7 +1534,7 @@ async function scaffoldClaudeSettings(projectRoot) {
1533
1534
  if (!merged["$schema"]) merged["$schema"] = "https://json.schemastore.org/claude-code-settings.json";
1534
1535
  mkdirSync$1(claudeDir, { recursive: true });
1535
1536
  await writeFile(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
1536
- logger$18.info({ settingsPath }, "Wrote substrate settings to .claude/settings.json");
1537
+ logger$19.info({ settingsPath }, "Wrote substrate settings to .claude/settings.json");
1537
1538
  }
1538
1539
  /**
1539
1540
  * H5.2 (field finding #2): write substrate's own slash commands
@@ -1552,7 +1553,7 @@ function scaffoldSubstrateSlashCommands(projectRoot) {
1552
1553
  let templatesDir = join(pkgRoot, "dist", "cli", "templates", "claude-commands");
1553
1554
  if (!existsSync$1(templatesDir)) templatesDir = join(pkgRoot, "src", "cli", "templates", "claude-commands");
1554
1555
  if (!existsSync$1(templatesDir)) {
1555
- logger$18.warn({ templatesDir }, "substrate slash-command templates not found; skipping");
1556
+ logger$19.warn({ templatesDir }, "substrate slash-command templates not found; skipping");
1556
1557
  return 0;
1557
1558
  }
1558
1559
  const commandsDir = join(projectRoot, ".claude", "commands");
@@ -1564,19 +1565,19 @@ function scaffoldSubstrateSlashCommands(projectRoot) {
1564
1565
  writeFileSync$1(join(commandsDir, file), readFileSync$1(join(templatesDir, file), "utf8"));
1565
1566
  written += 1;
1566
1567
  } catch (err) {
1567
- logger$18.warn({
1568
+ logger$19.warn({
1568
1569
  file,
1569
1570
  err
1570
1571
  }, "failed to write substrate slash command (init continues)");
1571
1572
  }
1572
1573
  }
1573
- logger$18.info({
1574
+ logger$19.info({
1574
1575
  written,
1575
1576
  commandsDir
1576
1577
  }, "Scaffolded substrate slash commands");
1577
1578
  return written;
1578
1579
  } catch (err) {
1579
- logger$18.warn({ err }, "scaffoldSubstrateSlashCommands failed; init continues");
1580
+ logger$19.warn({ err }, "scaffoldSubstrateSlashCommands failed; init continues");
1580
1581
  return 0;
1581
1582
  }
1582
1583
  }
@@ -1650,7 +1651,7 @@ async function compileBmadAgents(bmadDir) {
1650
1651
  writeFileSync$1(mdPath, result.xml, "utf-8");
1651
1652
  compiled++;
1652
1653
  } catch (compileErr) {
1653
- logger$18.debug({
1654
+ logger$19.debug({
1654
1655
  err: compileErr,
1655
1656
  file
1656
1657
  }, "Failed to compile agent YAML");
@@ -1797,9 +1798,9 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1797
1798
  const _require = createRequire(join(__dirname, "synthetic.js"));
1798
1799
  try {
1799
1800
  const compiledCount = await compileBmadAgents(bmadDir);
1800
- if (compiledCount > 0) logger$18.info({ compiledCount }, "Compiled agent YAML files to MD");
1801
+ if (compiledCount > 0) logger$19.info({ compiledCount }, "Compiled agent YAML files to MD");
1801
1802
  } catch (compileErr) {
1802
- logger$18.warn({ err: compileErr }, "Agent compilation failed; agent commands may be incomplete");
1803
+ logger$19.warn({ err: compileErr }, "Agent compilation failed; agent commands may be incomplete");
1803
1804
  }
1804
1805
  const resolveExport = (mod, name) => {
1805
1806
  if (typeof mod[name] === "function") return mod[name];
@@ -1813,7 +1814,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1813
1814
  const manifestGenPath = join(installerLibPath, "core", "manifest-generator.js");
1814
1815
  const pathUtilsPath = join(installerLibPath, "ide", "shared", "path-utils.js");
1815
1816
  if (!existsSync$1(agentGenPath)) {
1816
- logger$18.info("bmad-method generators not available (requires bmad-method with agent/workflow/task-tool generators)");
1817
+ logger$19.info("bmad-method generators not available (requires bmad-method with agent/workflow/task-tool generators)");
1817
1818
  return;
1818
1819
  }
1819
1820
  const agentMod = _require(agentGenPath);
@@ -1823,11 +1824,11 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1823
1824
  if (existsSync$1(workflowGenPath)) {
1824
1825
  const workflowMod = _require(workflowGenPath);
1825
1826
  WorkflowCommandGenerator = resolveExport(workflowMod, "WorkflowCommandGenerator");
1826
- } else logger$18.info("bmad-method workflow-command-generator not available; will try skill-based installation");
1827
+ } else logger$19.info("bmad-method workflow-command-generator not available; will try skill-based installation");
1827
1828
  if (existsSync$1(taskToolGenPath)) {
1828
1829
  const taskToolMod = _require(taskToolGenPath);
1829
1830
  TaskToolCommandGenerator = resolveExport(taskToolMod, "TaskToolCommandGenerator");
1830
- } else logger$18.info("bmad-method task-tool-command-generator not available; will try skill-based installation");
1831
+ } else logger$19.info("bmad-method task-tool-command-generator not available; will try skill-based installation");
1831
1832
  let ManifestGenerator = null;
1832
1833
  if (existsSync$1(manifestGenPath)) {
1833
1834
  const manifestMod = _require(manifestGenPath);
@@ -1859,7 +1860,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1859
1860
  const manifestGen = new ManifestGenerator();
1860
1861
  await manifestGen.generateManifests(bmadDir, allModules, [], { ides: ["claude-code"] });
1861
1862
  } catch (manifestErr) {
1862
- logger$18.warn({ err: manifestErr }, "ManifestGenerator failed; workflow/task commands may be incomplete");
1863
+ logger$19.warn({ err: manifestErr }, "ManifestGenerator failed; workflow/task commands may be incomplete");
1863
1864
  }
1864
1865
  const commandsDir = join(projectRoot, ".claude", "commands");
1865
1866
  mkdirSync$1(commandsDir, { recursive: true });
@@ -1887,7 +1888,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1887
1888
  const total = agentCount + workflowCount + taskToolCount + skillCount;
1888
1889
  if (outputFormat !== "json") if (skillCount > 0) process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(skillCount)} skills)\n`);
1889
1890
  else process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(workflowCount)} workflows, ${String(taskToolCount)} tasks/tools)\n`);
1890
- logger$18.info({
1891
+ logger$19.info({
1891
1892
  agentCount,
1892
1893
  workflowCount,
1893
1894
  taskToolCount,
@@ -1898,7 +1899,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
1898
1899
  } catch (err) {
1899
1900
  const msg = err instanceof Error ? err.message : String(err);
1900
1901
  if (outputFormat !== "json") process.stderr.write(`Warning: .claude/commands/ generation failed: ${msg}\n`);
1901
- logger$18.warn({ err }, "scaffoldClaudeCommands failed; init continues");
1902
+ logger$19.warn({ err }, "scaffoldClaudeCommands failed; init continues");
1902
1903
  }
1903
1904
  }
1904
1905
  /**
@@ -1927,7 +1928,7 @@ function syncCommandsAsPrompts(commandsDir, promptsDir, ownershipPrefixes, nameP
1927
1928
  unlinkSync$1(join(promptsDir, entry.name));
1928
1929
  }
1929
1930
  } catch (err) {
1930
- logger$18.debug({
1931
+ logger$19.debug({
1931
1932
  err,
1932
1933
  promptsDir
1933
1934
  }, "Failed to prune stale prompts");
@@ -1970,7 +1971,7 @@ function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, name
1970
1971
  });
1971
1972
  }
1972
1973
  } catch (err) {
1973
- logger$18.debug({
1974
+ logger$19.debug({
1974
1975
  err,
1975
1976
  destSkillsDir
1976
1977
  }, "Failed to prune stale skills");
@@ -1996,7 +1997,7 @@ function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, name
1996
1997
  op: stage,
1997
1998
  err: msg
1998
1999
  });
1999
- logger$18.warn({
2000
+ logger$19.warn({
2000
2001
  skill: entry.name,
2001
2002
  dest,
2002
2003
  stage,
@@ -2006,7 +2007,7 @@ function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, name
2006
2007
  }
2007
2008
  if (failures.length > 0 && count === 0) {
2008
2009
  const first = failures[0];
2009
- logger$18.warn({
2010
+ logger$19.warn({
2010
2011
  destSkillsDir,
2011
2012
  attempted: failures.length,
2012
2013
  dominantStage: first.op,
@@ -2033,7 +2034,7 @@ const PROJECT_OWNERSHIP_PREFIXES = ["bmad-", "substrate-"];
2033
2034
  function scaffoldCodexProject(projectRoot, outputFormat) {
2034
2035
  if (process.env["SUBSTRATE_NO_CODEX_SCAFFOLD"] === "1") {
2035
2036
  if (outputFormat !== "json") process.stdout.write(" Skipping .codex/ scaffolding (SUBSTRATE_NO_CODEX_SCAFFOLD=1)\n");
2036
- logger$18.debug("SUBSTRATE_NO_CODEX_SCAFFOLD=1 — skipping .codex/ scaffolding");
2037
+ logger$19.debug("SUBSTRATE_NO_CODEX_SCAFFOLD=1 — skipping .codex/ scaffolding");
2037
2038
  return;
2038
2039
  }
2039
2040
  const claudeCommandsDir = join(projectRoot, ".claude", "commands");
@@ -2046,16 +2047,16 @@ function scaffoldCodexProject(projectRoot, outputFormat) {
2046
2047
  const skillCount = syncSkillsToTarget(claudeSkillsDir, codexSkillsDir, PROJECT_OWNERSHIP_PREFIXES, "");
2047
2048
  const total = promptCount + skillCount;
2048
2049
  if (outputFormat !== "json" && total > 0) process.stdout.write(`Generated ${String(total)} Codex artifacts (${String(promptCount)} prompts, ${String(skillCount)} skills)\n`);
2049
- if (total > 0) logger$18.info({
2050
+ if (total > 0) logger$19.info({
2050
2051
  promptCount,
2051
2052
  skillCount,
2052
2053
  codexDir
2053
2054
  }, "Generated .codex/");
2054
- else logger$18.debug({ codexDir }, "No Codex artifacts generated; source Claude content not found");
2055
+ else logger$19.debug({ codexDir }, "No Codex artifacts generated; source Claude content not found");
2055
2056
  } catch (err) {
2056
2057
  const msg = err instanceof Error ? err.message : String(err);
2057
2058
  if (outputFormat !== "json") process.stderr.write(`Warning: .codex/ generation failed: ${msg}\n`);
2058
- logger$18.warn({ err }, "scaffoldCodexProject failed; init continues");
2059
+ logger$19.warn({ err }, "scaffoldCodexProject failed; init continues");
2059
2060
  }
2060
2061
  }
2061
2062
  /**
@@ -2073,7 +2074,7 @@ function scaffoldCodexProject(projectRoot, outputFormat) {
2073
2074
  function scaffoldCodexUser(projectRoot, homeDir, outputFormat) {
2074
2075
  if (process.env["SUBSTRATE_NO_CODEX_SCAFFOLD"] === "1") {
2075
2076
  if (outputFormat !== "json") process.stdout.write(" Skipping ~/.codex/ scaffolding (SUBSTRATE_NO_CODEX_SCAFFOLD=1)\n");
2076
- logger$18.debug("SUBSTRATE_NO_CODEX_SCAFFOLD=1 — skipping ~/.codex/ scaffolding");
2077
+ logger$19.debug("SUBSTRATE_NO_CODEX_SCAFFOLD=1 — skipping ~/.codex/ scaffolding");
2077
2078
  return;
2078
2079
  }
2079
2080
  const claudeCommandsDir = join(projectRoot, ".claude", "commands");
@@ -2086,16 +2087,16 @@ function scaffoldCodexUser(projectRoot, homeDir, outputFormat) {
2086
2087
  const skillCount = syncSkillsToTarget(claudeSkillsDir, userSkillsDir, ["substrate-"], "substrate-");
2087
2088
  const total = promptCount + skillCount;
2088
2089
  if (outputFormat !== "json" && total > 0) process.stdout.write(`Installed ${String(total)} Codex artifacts to ${userCodexDir} (${String(promptCount)} prompts, ${String(skillCount)} skills)\n`);
2089
- if (total > 0) logger$18.info({
2090
+ if (total > 0) logger$19.info({
2090
2091
  promptCount,
2091
2092
  skillCount,
2092
2093
  userCodexDir
2093
2094
  }, "Installed user-scope Codex content");
2094
- else logger$18.debug({ userCodexDir }, "No user-scope Codex content installed; source Claude content not found");
2095
+ else logger$19.debug({ userCodexDir }, "No user-scope Codex content installed; source Claude content not found");
2095
2096
  } catch (err) {
2096
2097
  const msg = err instanceof Error ? err.message : String(err);
2097
2098
  if (outputFormat !== "json") process.stderr.write(`Warning: user-scope Codex install failed: ${msg}\n`);
2098
- logger$18.warn({ err }, "scaffoldCodexUser failed; init continues");
2099
+ logger$19.warn({ err }, "scaffoldCodexUser failed; init continues");
2099
2100
  }
2100
2101
  }
2101
2102
  const PROVIDER_DEFAULTS = DEFAULT_CONFIG.providers;
@@ -2216,7 +2217,7 @@ async function runInitAction(options) {
2216
2217
  discoveryReport = await registry.discoverAndRegister();
2217
2218
  } catch (err) {
2218
2219
  const message = err instanceof Error ? err.message : String(err);
2219
- logger$18.error({ err }, "Adapter discovery failed");
2220
+ logger$19.error({ err }, "Adapter discovery failed");
2220
2221
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, `Adapter discovery failed: ${message}`) + "\n");
2221
2222
  else process.stderr.write(` Error: adapter discovery failed — ${message}\n`);
2222
2223
  return INIT_EXIT_ERROR;
@@ -2265,7 +2266,7 @@ async function runInitAction(options) {
2265
2266
  try {
2266
2267
  detectedProfile = await detectProjectProfile(dbRoot);
2267
2268
  } catch (err) {
2268
- logger$18.warn({ err }, "Project profile detection failed; skipping");
2269
+ logger$19.warn({ err }, "Project profile detection failed; skipping");
2269
2270
  }
2270
2271
  if (detectedProfile === null) {
2271
2272
  if (outputFormat !== "json") process.stdout.write(" No project stack detected. Create .substrate/project-profile.yaml manually to enable polyglot support.\n");
@@ -2299,12 +2300,12 @@ async function runInitAction(options) {
2299
2300
  return INIT_EXIT_ERROR;
2300
2301
  }
2301
2302
  if (force && existsSync$1(localManifest)) {
2302
- logger$18.info({ pack: packName }, "Replacing existing pack with bundled version");
2303
+ logger$19.info({ pack: packName }, "Replacing existing pack with bundled version");
2303
2304
  process.stderr.write(`Warning: Replacing existing pack '${packName}' with bundled version\n`);
2304
2305
  }
2305
2306
  mkdirSync$1(dirname(packPath), { recursive: true });
2306
2307
  cpSync(bundledPackPath, packPath, { recursive: true });
2307
- logger$18.info({
2308
+ logger$19.info({
2308
2309
  pack: packName,
2309
2310
  dest: packPath
2310
2311
  }, "Scaffolded methodology pack");
@@ -2346,10 +2347,10 @@ async function runInitAction(options) {
2346
2347
  const { content, changed } = computeSubstrateGitignore(existing);
2347
2348
  if (changed) {
2348
2349
  writeFileSync$1(gitignorePath, content);
2349
- logger$18.info("Updated .gitignore: track only .substrate/config.yaml");
2350
+ logger$19.info("Updated .gitignore: track only .substrate/config.yaml");
2350
2351
  }
2351
2352
  } catch (err) {
2352
- logger$18.debug({ err }, "Could not update .gitignore (non-fatal)");
2353
+ logger$19.debug({ err }, "Could not update .gitignore (non-fatal)");
2353
2354
  }
2354
2355
  const doltMode = options.doltMode ?? "auto";
2355
2356
  let doltInitialized = false;
@@ -2363,7 +2364,7 @@ async function runInitAction(options) {
2363
2364
  process.stderr.write(`${err.message}\n`);
2364
2365
  return INIT_EXIT_ERROR;
2365
2366
  }
2366
- logger$18.debug("Dolt not installed, skipping auto-init");
2367
+ logger$19.debug("Dolt not installed, skipping auto-init");
2367
2368
  } else {
2368
2369
  const msg = err instanceof Error ? err.message : String(err);
2369
2370
  if (doltMode === "force") {
@@ -2373,7 +2374,7 @@ async function runInitAction(options) {
2373
2374
  process.stderr.write(`⚠ Dolt state store initialization failed: ${msg}\n Pipeline metrics, cost tracking, and health monitoring will not persist.\n Fix the issue and re-run: substrate init --dolt\n`);
2374
2375
  }
2375
2376
  }
2376
- else logger$18.debug("Dolt step was skipped (--no-dolt)");
2377
+ else logger$19.debug("Dolt step was skipped (--no-dolt)");
2377
2378
  const successMsg = `Pack '${packName}' and database initialized successfully at ${dbPath}`;
2378
2379
  if (outputFormat === "json") process.stdout.write(formatOutput({
2379
2380
  pack: packName,
@@ -2411,7 +2412,7 @@ async function runInitAction(options) {
2411
2412
  const msg = err instanceof Error ? err.message : String(err);
2412
2413
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
2413
2414
  else process.stderr.write(`Error: ${msg}\n`);
2414
- logger$18.error({ err }, "init failed");
2415
+ logger$19.error({ err }, "init failed");
2415
2416
  return INIT_EXIT_ERROR;
2416
2417
  }
2417
2418
  }
@@ -2435,7 +2436,7 @@ function registerInitCommand(program, _version, registry) {
2435
2436
 
2436
2437
  //#endregion
2437
2438
  //#region src/cli/commands/config.ts
2438
- const logger$17 = createLogger("config-cmd");
2439
+ const logger$18 = createLogger("config-cmd");
2439
2440
  const CONFIG_EXIT_SUCCESS = 0;
2440
2441
  const CONFIG_EXIT_ERROR = 1;
2441
2442
  const CONFIG_EXIT_INVALID = 2;
@@ -2461,7 +2462,7 @@ async function runConfigShow(opts = {}) {
2461
2462
  return CONFIG_EXIT_INVALID;
2462
2463
  }
2463
2464
  const message = err instanceof Error ? err.message : String(err);
2464
- logger$17.error({ err }, "Failed to load configuration");
2465
+ logger$18.error({ err }, "Failed to load configuration");
2465
2466
  process.stderr.write(` Error loading configuration: ${message}\n`);
2466
2467
  return CONFIG_EXIT_ERROR;
2467
2468
  }
@@ -2535,7 +2536,7 @@ async function runConfigExport(opts = {}) {
2535
2536
  return CONFIG_EXIT_INVALID;
2536
2537
  }
2537
2538
  const message = err instanceof Error ? err.message : String(err);
2538
- logger$17.error({ err }, "Failed to load configuration");
2539
+ logger$18.error({ err }, "Failed to load configuration");
2539
2540
  process.stderr.write(`Error loading configuration: ${message}\n`);
2540
2541
  return CONFIG_EXIT_ERROR;
2541
2542
  }
@@ -6455,7 +6456,7 @@ async function detectManifestDriftAgainstWorkingTree(manifest, projectRoot) {
6455
6456
 
6456
6457
  //#endregion
6457
6458
  //#region src/cli/commands/resume.ts
6458
- const logger$16 = createLogger("resume-cmd");
6459
+ const logger$17 = createLogger("resume-cmd");
6459
6460
  /**
6460
6461
  * Format a human-readable duration from an ISO-8601 timestamp to "now".
6461
6462
  */
@@ -6525,7 +6526,7 @@ async function runResumeAction(options) {
6525
6526
  return 1;
6526
6527
  }
6527
6528
  } catch (driftErr) {
6528
- logger$16.debug({ err: driftErr }, "manifest drift check failed — proceeding with resume");
6529
+ logger$17.debug({ err: driftErr }, "manifest drift check failed — proceeding with resume");
6529
6530
  }
6530
6531
  }
6531
6532
  const doltDir = join(dbRoot, ".substrate", "state", ".dolt");
@@ -6595,15 +6596,15 @@ async function runResumeAction(options) {
6595
6596
  const manifestStories = manifestData.cli_flags["stories"] ?? manifestData.story_scope;
6596
6597
  if (Array.isArray(manifestStories) && manifestStories.length > 0) {
6597
6598
  scopedStories = manifestStories;
6598
- logger$16.debug({
6599
+ logger$17.debug({
6599
6600
  runId,
6600
6601
  stories: scopedStories
6601
6602
  }, "resume scope loaded from manifest");
6602
6603
  }
6603
6604
  } catch {
6604
- logger$16.debug({ runId }, "manifest read failed in resume — using legacy config_json scope");
6605
+ logger$17.debug({ runId }, "manifest read failed in resume — using legacy config_json scope");
6605
6606
  }
6606
- else logger$16.debug({ runId }, "Run manifest not found for scope preservation — using legacy config_json scope");
6607
+ else logger$17.debug({ runId }, "Run manifest not found for scope preservation — using legacy config_json scope");
6607
6608
  }
6608
6609
  return runFullPipelineFromPhase({
6609
6610
  packName,
@@ -6626,7 +6627,7 @@ async function runResumeAction(options) {
6626
6627
  const msg = err instanceof Error ? err.message : String(err);
6627
6628
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
6628
6629
  else process.stderr.write(`Error: ${msg}\n`);
6629
- logger$16.error({ err }, "auto resume failed");
6630
+ logger$17.error({ err }, "auto resume failed");
6630
6631
  return 1;
6631
6632
  } finally {
6632
6633
  try {
@@ -6879,11 +6880,11 @@ async function runFullPipelineFromPhase(options) {
6879
6880
  output_tokens: output,
6880
6881
  cost_usd: costUsd
6881
6882
  }).catch((err) => {
6882
- logger$16.warn({ err }, "Failed to record token usage");
6883
+ logger$17.warn({ err }, "Failed to record token usage");
6883
6884
  });
6884
6885
  }
6885
6886
  } catch (err) {
6886
- logger$16.warn({ err }, "Failed to record token usage");
6887
+ logger$17.warn({ err }, "Failed to record token usage");
6887
6888
  }
6888
6889
  });
6889
6890
  const storyKeys = await resolveStoryKeys(adapter, projectRoot, {
@@ -6952,7 +6953,7 @@ async function runFullPipelineFromPhase(options) {
6952
6953
  const msg = err instanceof Error ? err.message : String(err);
6953
6954
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
6954
6955
  else process.stderr.write(`Error: ${msg}\n`);
6955
- logger$16.error({ err }, "pipeline from phase failed");
6956
+ logger$17.error({ err }, "pipeline from phase failed");
6956
6957
  return 1;
6957
6958
  } finally {
6958
6959
  try {
@@ -6982,7 +6983,7 @@ function registerResumeCommand(program, _version = "0.0.0", projectRoot = proces
6982
6983
 
6983
6984
  //#endregion
6984
6985
  //#region src/cli/commands/status.ts
6985
- const logger$15 = createLogger("status-cmd");
6986
+ const logger$16 = createLogger("status-cmd");
6986
6987
  /**
6987
6988
  * Map a manifest per-story status string to the appropriate WorkGraphCounts bucket.
6988
6989
  * Unknown strings are treated as `inProgress` (safe default).
@@ -7094,9 +7095,9 @@ async function runStatusAction(options) {
7094
7095
  const manifestData = await resolvedManifest.read();
7095
7096
  manifestPerStoryState = manifestData.per_story_state;
7096
7097
  workGraph = buildWorkGraphFromManifest(manifestData.per_story_state);
7097
- logger$15.debug({ runId: run?.id }, "status: workGraph built from manifest per_story_state");
7098
+ logger$16.debug({ runId: run?.id }, "status: workGraph built from manifest per_story_state");
7098
7099
  } catch {
7099
- logger$15.debug({ runId: run?.id }, "status: manifest read failed — falling back to wg_stories");
7100
+ logger$16.debug({ runId: run?.id }, "status: manifest read failed — falling back to wg_stories");
7100
7101
  }
7101
7102
  if (workGraph === void 0) try {
7102
7103
  const wgRepo = new WorkGraphRepository(adapter);
@@ -7133,10 +7134,10 @@ async function runStatusAction(options) {
7133
7134
  };
7134
7135
  }
7135
7136
  } catch (err) {
7136
- logger$15.debug({ err }, "Work graph query failed, continuing without work graph data");
7137
+ logger$16.debug({ err }, "Work graph query failed, continuing without work graph data");
7137
7138
  }
7138
7139
  if (run === void 0) {
7139
- const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-DAOWdkka.js");
7140
+ const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-CvsH53bv.js");
7140
7141
  const substrateDirPath = join(projectRoot, ".substrate");
7141
7142
  const processInfo = inspectProcessTree$1({
7142
7143
  projectRoot,
@@ -7295,7 +7296,7 @@ async function runStatusAction(options) {
7295
7296
  const msg = err instanceof Error ? err.message : String(err);
7296
7297
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
7297
7298
  else process.stderr.write(`Error: ${msg}\n`);
7298
- logger$15.error({ err }, "status action failed");
7299
+ logger$16.error({ err }, "status action failed");
7299
7300
  return 1;
7300
7301
  } finally {
7301
7302
  try {
@@ -7639,7 +7640,7 @@ Analyze thoroughly and return ONLY the JSON array with no additional text.`;
7639
7640
 
7640
7641
  //#endregion
7641
7642
  //#region src/cli/commands/amend.ts
7642
- const logger$14 = createLogger("amend-cmd");
7643
+ const logger$15 = createLogger("amend-cmd");
7643
7644
  /**
7644
7645
  * Detect and apply supersessions after a phase completes in an amendment run.
7645
7646
  *
@@ -7670,7 +7671,7 @@ async function runPostPhaseSupersessionDetection(adapter, amendmentRunId, curren
7670
7671
  });
7671
7672
  } catch (err) {
7672
7673
  const msg = err instanceof Error ? err.message : String(err);
7673
- logger$14.warn({
7674
+ logger$15.warn({
7674
7675
  err,
7675
7676
  originalId: parentMatch.id,
7676
7677
  supersedingId: newDec.id
@@ -7807,7 +7808,7 @@ async function runAmendAction(options) {
7807
7808
  for (let i = startIdx; i < phaseOrder.length; i++) {
7808
7809
  const currentPhase = phaseOrder[i];
7809
7810
  const amendmentContext = handler.loadContextForPhase(currentPhase);
7810
- logger$14.info({
7811
+ logger$15.info({
7811
7812
  phase: currentPhase,
7812
7813
  amendmentContextLen: amendmentContext.length
7813
7814
  }, "Amendment context loaded for phase");
@@ -7928,7 +7929,7 @@ async function runAmendAction(options) {
7928
7929
  } catch (err) {
7929
7930
  const msg = err instanceof Error ? err.message : String(err);
7930
7931
  process.stderr.write(`Error: ${msg}\n`);
7931
- logger$14.error({ err }, "amend failed");
7932
+ logger$15.error({ err }, "amend failed");
7932
7933
  return 1;
7933
7934
  } finally {
7934
7935
  try {
@@ -8665,7 +8666,7 @@ async function runSupervisorAction(options, deps = {}) {
8665
8666
  await initSchema(expAdapter);
8666
8667
  const { runRunAction: runPipeline } = await import(
8667
8668
  /* @vite-ignore */
8668
- "../run-CGuoRwXB.js"
8669
+ "../run-UilZoIOh.js"
8669
8670
  );
8670
8671
  const runStoryFn = async (opts) => {
8671
8672
  const exitCode = await runPipeline({
@@ -8915,7 +8916,7 @@ function registerSupervisorCommand(program, _version = "0.0.0", projectRoot = pr
8915
8916
 
8916
8917
  //#endregion
8917
8918
  //#region src/cli/commands/metrics.ts
8918
- const logger$13 = createLogger("metrics-cmd");
8919
+ const logger$14 = createLogger("metrics-cmd");
8919
8920
  async function openTelemetryAdapter(basePath) {
8920
8921
  try {
8921
8922
  const adapter = createDatabaseAdapter({
@@ -9274,7 +9275,7 @@ async function runMetricsAction(options) {
9274
9275
  }
9275
9276
  }
9276
9277
  } catch (err) {
9277
- logger$13.debug({ err }, "getScenarioResultsForRun failed");
9278
+ logger$14.debug({ err }, "getScenarioResultsForRun failed");
9278
9279
  }
9279
9280
  if (rows.length === 0) {
9280
9281
  const msg = `No factory run found with id: ${run}`;
@@ -9310,7 +9311,7 @@ async function runMetricsAction(options) {
9310
9311
  }
9311
9312
  }
9312
9313
  } catch (err) {
9313
- logger$13.debug({ err }, "getTwinRunsForRun failed — twin_runs table may not exist yet");
9314
+ logger$14.debug({ err }, "getTwinRunsForRun failed — twin_runs table may not exist yet");
9314
9315
  }
9315
9316
  }
9316
9317
  return 0;
@@ -9320,7 +9321,7 @@ async function runMetricsAction(options) {
9320
9321
  try {
9321
9322
  factoryRuns$1 = await getFactoryRunSummaries(adapter, limit);
9322
9323
  } catch (err) {
9323
- logger$13.debug({ err }, "getFactoryRunSummaries failed in factory-only mode");
9324
+ logger$14.debug({ err }, "getFactoryRunSummaries failed in factory-only mode");
9324
9325
  }
9325
9326
  if (outputFormat === "json") process.stdout.write(formatOutput({ graph_runs: factoryRuns$1 }, "json", true) + "\n");
9326
9327
  else if (factoryRuns$1.length === 0) process.stdout.write("No factory runs recorded yet.\n");
@@ -9423,7 +9424,7 @@ async function runMetricsAction(options) {
9423
9424
  try {
9424
9425
  factoryRuns = await getFactoryRunSummaries(adapter, limit);
9425
9426
  } catch (err) {
9426
- logger$13.debug({ err }, "getFactoryRunSummaries failed — table may not exist in older databases");
9427
+ logger$14.debug({ err }, "getFactoryRunSummaries failed — table may not exist in older databases");
9427
9428
  }
9428
9429
  if (outputFormat === "json") {
9429
9430
  const runsWithBreakdown = runs.map((run$1) => ({
@@ -9509,7 +9510,7 @@ async function runMetricsAction(options) {
9509
9510
  const msg = err instanceof Error ? err.message : String(err);
9510
9511
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
9511
9512
  else process.stderr.write(`Error: ${msg}\n`);
9512
- logger$13.error({ err }, "metrics action failed");
9513
+ logger$14.error({ err }, "metrics action failed");
9513
9514
  return 1;
9514
9515
  } finally {
9515
9516
  try {
@@ -9565,7 +9566,7 @@ function registerMetricsCommand(program, _version = "0.0.0", projectRoot = proce
9565
9566
  function getLatestSessionId(_adapter) {
9566
9567
  return null;
9567
9568
  }
9568
- const logger$12 = createLogger("cost-cmd");
9569
+ const logger$13 = createLogger("cost-cmd");
9569
9570
  const COST_EXIT_SUCCESS = 0;
9570
9571
  const COST_EXIT_ERROR = 1;
9571
9572
  /**
@@ -9809,7 +9810,7 @@ async function runCostAction(options) {
9809
9810
  } catch (err) {
9810
9811
  const message = err instanceof Error ? err.message : String(err);
9811
9812
  process.stderr.write(`Error: ${message}\n`);
9812
- logger$12.error({ err }, "runCostAction failed");
9813
+ logger$13.error({ err }, "runCostAction failed");
9813
9814
  return COST_EXIT_ERROR;
9814
9815
  } finally {
9815
9816
  if (adapter !== null) try {
@@ -9843,7 +9844,7 @@ function registerCostCommand(program, version = "0.0.0", projectRoot = process.c
9843
9844
 
9844
9845
  //#endregion
9845
9846
  //#region src/cli/commands/monitor.ts
9846
- const logger$11 = createLogger("monitor-cmd");
9847
+ const logger$12 = createLogger("monitor-cmd");
9847
9848
  const MONITOR_EXIT_SUCCESS = 0;
9848
9849
  const MONITOR_EXIT_ERROR = 1;
9849
9850
  /**
@@ -10046,7 +10047,7 @@ async function runMonitorReportAction(options) {
10046
10047
  } catch (err) {
10047
10048
  const message = err instanceof Error ? err.message : String(err);
10048
10049
  process.stderr.write(`Error: ${message}\n`);
10049
- logger$11.error({ err }, "runMonitorReportAction failed");
10050
+ logger$12.error({ err }, "runMonitorReportAction failed");
10050
10051
  return MONITOR_EXIT_ERROR;
10051
10052
  } finally {
10052
10053
  if (monitorDb !== null) try {
@@ -10108,7 +10109,7 @@ async function runMonitorStatusAction(options) {
10108
10109
  } catch (err) {
10109
10110
  const message = err instanceof Error ? err.message : String(err);
10110
10111
  process.stderr.write(`Error: ${message}\n`);
10111
- logger$11.error({ err }, "runMonitorStatusAction failed");
10112
+ logger$12.error({ err }, "runMonitorStatusAction failed");
10112
10113
  return MONITOR_EXIT_ERROR;
10113
10114
  } finally {
10114
10115
  if (monitorDb !== null) try {
@@ -10143,7 +10144,7 @@ async function runMonitorResetAction(options) {
10143
10144
  } catch (err) {
10144
10145
  const message = err instanceof Error ? err.message : String(err);
10145
10146
  process.stderr.write(`Error: ${message}\n`);
10146
- logger$11.error({ err }, "runMonitorResetAction failed");
10147
+ logger$12.error({ err }, "runMonitorResetAction failed");
10147
10148
  return MONITOR_EXIT_ERROR;
10148
10149
  } finally {
10149
10150
  if (monitorDb !== null) try {
@@ -10191,7 +10192,7 @@ async function runMonitorRecommendationsAction(options) {
10191
10192
  } catch (err) {
10192
10193
  const message = err instanceof Error ? err.message : String(err);
10193
10194
  process.stderr.write(`Error: ${message}\n`);
10194
- logger$11.error({ err }, "runMonitorRecommendationsAction failed");
10195
+ logger$12.error({ err }, "runMonitorRecommendationsAction failed");
10195
10196
  return MONITOR_EXIT_ERROR;
10196
10197
  } finally {
10197
10198
  if (monitorDb !== null) try {
@@ -10269,7 +10270,7 @@ function registerMonitorCommand(program, version = "0.0.0", projectRoot = proces
10269
10270
 
10270
10271
  //#endregion
10271
10272
  //#region src/cli/commands/merge.ts
10272
- const logger$10 = createLogger("merge-cmd");
10273
+ const logger$11 = createLogger("merge-cmd");
10273
10274
  const MERGE_EXIT_SUCCESS = 0;
10274
10275
  const MERGE_EXIT_CONFLICT = 1;
10275
10276
  const MERGE_EXIT_ERROR = 2;
@@ -10307,7 +10308,7 @@ async function mergeTask(taskId, targetBranch, projectRoot) {
10307
10308
  projectRoot
10308
10309
  });
10309
10310
  try {
10310
- logger$10.info({
10311
+ logger$11.info({
10311
10312
  taskId,
10312
10313
  targetBranch
10313
10314
  }, "Running conflict detection...");
@@ -10329,7 +10330,7 @@ async function mergeTask(taskId, targetBranch, projectRoot) {
10329
10330
  } catch (err) {
10330
10331
  const message = err instanceof Error ? err.message : String(err);
10331
10332
  console.error(`Error merging task "${taskId}": ${message}`);
10332
- logger$10.error({
10333
+ logger$11.error({
10333
10334
  taskId,
10334
10335
  err
10335
10336
  }, "merge --task failed");
@@ -10383,7 +10384,7 @@ async function mergeAll(targetBranch, projectRoot, taskIds) {
10383
10384
  error: message
10384
10385
  });
10385
10386
  console.log(` Error for task "${taskId}": ${message}`);
10386
- logger$10.error({
10387
+ logger$11.error({
10387
10388
  taskId,
10388
10389
  err
10389
10390
  }, "merge --all: task failed");
@@ -10436,7 +10437,7 @@ function registerMergeCommand(program, projectRoot = process.cwd()) {
10436
10437
 
10437
10438
  //#endregion
10438
10439
  //#region src/cli/commands/worktrees.ts
10439
- const logger$9 = createLogger("worktrees-cmd");
10440
+ const logger$10 = createLogger("worktrees-cmd");
10440
10441
  const WORKTREES_EXIT_SUCCESS = 0;
10441
10442
  const WORKTREES_EXIT_ERROR = 1;
10442
10443
  /** Valid task statuses for filtering */
@@ -10563,7 +10564,7 @@ async function listWorktreesAction(options) {
10563
10564
  try {
10564
10565
  worktreeInfos = await manager.listWorktrees();
10565
10566
  } catch (err) {
10566
- logger$9.error({ err }, "Failed to list worktrees");
10567
+ logger$10.error({ err }, "Failed to list worktrees");
10567
10568
  const message = err instanceof Error ? err.message : String(err);
10568
10569
  process.stderr.write(`Error listing worktrees: ${message}\n`);
10569
10570
  return WORKTREES_EXIT_ERROR;
@@ -10590,7 +10591,7 @@ async function listWorktreesAction(options) {
10590
10591
  } catch (err) {
10591
10592
  const message = err instanceof Error ? err.message : String(err);
10592
10593
  process.stderr.write(`Error: ${message}\n`);
10593
- logger$9.error({ err }, "listWorktreesAction failed");
10594
+ logger$10.error({ err }, "listWorktreesAction failed");
10594
10595
  return WORKTREES_EXIT_ERROR;
10595
10596
  }
10596
10597
  }
@@ -10619,7 +10620,7 @@ async function cleanupWorktreesAction(options) {
10619
10620
  } catch (err) {
10620
10621
  const message = err instanceof Error ? err.message : String(err);
10621
10622
  process.stderr.write(`Error cleaning up worktree for task "${taskId}": ${message}\n`);
10622
- logger$9.error({
10623
+ logger$10.error({
10623
10624
  err,
10624
10625
  taskId
10625
10626
  }, "cleanupWorktreesAction (single) failed");
@@ -10633,13 +10634,13 @@ async function cleanupWorktreesAction(options) {
10633
10634
  } catch (err) {
10634
10635
  const message = err instanceof Error ? err.message : String(err);
10635
10636
  process.stderr.write(`Error during bulk cleanup: ${message}\n`);
10636
- logger$9.error({ err }, "cleanupWorktreesAction (bulk) failed");
10637
+ logger$10.error({ err }, "cleanupWorktreesAction (bulk) failed");
10637
10638
  return WORKTREES_EXIT_ERROR;
10638
10639
  }
10639
10640
  } catch (err) {
10640
10641
  const message = err instanceof Error ? err.message : String(err);
10641
10642
  process.stderr.write(`Error: ${message}\n`);
10642
- logger$9.error({ err }, "cleanupWorktreesAction failed");
10643
+ logger$10.error({ err }, "cleanupWorktreesAction failed");
10643
10644
  return WORKTREES_EXIT_ERROR;
10644
10645
  }
10645
10646
  }
@@ -10690,7 +10691,7 @@ function registerWorktreesCommand(program, version = "0.0.0", projectRoot = proc
10690
10691
 
10691
10692
  //#endregion
10692
10693
  //#region src/cli/commands/brainstorm.ts
10693
- const logger$8 = createLogger("brainstorm-cmd");
10694
+ const logger$9 = createLogger("brainstorm-cmd");
10694
10695
  /**
10695
10696
  * Detect whether the project has existing planning artifacts that indicate
10696
10697
  * this is an amendment session (vs. a brand-new project brainstorm).
@@ -10736,13 +10737,13 @@ async function loadAmendmentContextDocuments(projectRoot) {
10736
10737
  try {
10737
10738
  brief = await readFile(briefPath, "utf-8");
10738
10739
  } catch {
10739
- logger$8.warn({ briefPath }, "product-brief.md not found — continuing without brief context");
10740
+ logger$9.warn({ briefPath }, "product-brief.md not found — continuing without brief context");
10740
10741
  process.stderr.write(`Warning: product-brief.md not found at ${briefPath}\n`);
10741
10742
  }
10742
10743
  try {
10743
10744
  prd = await readFile(prdPath, "utf-8");
10744
10745
  } catch {
10745
- logger$8.warn({ prdPath }, "requirements.md not found — continuing without PRD context");
10746
+ logger$9.warn({ prdPath }, "requirements.md not found — continuing without PRD context");
10746
10747
  process.stderr.write(`Warning: requirements.md not found at ${prdPath}\n`);
10747
10748
  }
10748
10749
  return {
@@ -10951,7 +10952,7 @@ async function dispatchToPersonas(userPrompt, context, llmDispatch) {
10951
10952
  }
10952
10953
  ];
10953
10954
  const defaultDispatch = async (prompt, personaName) => {
10954
- logger$8.debug({
10955
+ logger$9.debug({
10955
10956
  personaName,
10956
10957
  promptLength: prompt.length
10957
10958
  }, "Dispatching to persona (stub mode)");
@@ -10968,7 +10969,7 @@ async function dispatchToPersonas(userPrompt, context, llmDispatch) {
10968
10969
  };
10969
10970
  } catch (err) {
10970
10971
  const msg = err instanceof Error ? err.message : String(err);
10971
- logger$8.error({
10972
+ logger$9.error({
10972
10973
  err,
10973
10974
  personaName: persona.name
10974
10975
  }, "Persona dispatch failed");
@@ -11120,7 +11121,7 @@ async function runBrainstormSession(options, llmDispatch, rlInterface) {
11120
11121
  }
11121
11122
  });
11122
11123
  rl.on("error", (err) => {
11123
- logger$8.error({ err }, "readline error");
11124
+ logger$9.error({ err }, "readline error");
11124
11125
  if (!sessionEnded) endSession(false);
11125
11126
  });
11126
11127
  });
@@ -11161,7 +11162,7 @@ function registerBrainstormCommand(program, _version = "0.0.0", projectRoot = pr
11161
11162
 
11162
11163
  //#endregion
11163
11164
  //#region src/cli/commands/retry-escalated.ts
11164
- const logger$7 = createLogger("retry-escalated-cmd");
11165
+ const logger$8 = createLogger("retry-escalated-cmd");
11165
11166
  async function runRetryEscalatedAction(options) {
11166
11167
  const { runId, dryRun, force, outputFormat, projectRoot, concurrency, pack: packName, registry: injectedRegistry, agent: agentId, events: eventsFlag } = options;
11167
11168
  const dbRoot = await resolveMainRepoRoot(projectRoot);
@@ -11202,7 +11203,7 @@ async function runRetryEscalatedAction(options) {
11202
11203
  process.stdout.write(`[INFO] ${storyKey}: Context ceiling set to ${contextCeiling} tokens due to prior context spike pattern.\n`);
11203
11204
  }
11204
11205
  } catch (err) {
11205
- logger$7.warn({
11206
+ logger$8.warn({
11206
11207
  err,
11207
11208
  storyKey
11208
11209
  }, "Failed to read efficiency profile — skipping gate");
@@ -11364,11 +11365,11 @@ async function runRetryEscalatedAction(options) {
11364
11365
  output_tokens: output,
11365
11366
  cost_usd: costUsd
11366
11367
  }).catch((err) => {
11367
- logger$7.warn({ err }, "Failed to record token usage");
11368
+ logger$8.warn({ err }, "Failed to record token usage");
11368
11369
  });
11369
11370
  }
11370
11371
  } catch (err) {
11371
- logger$7.warn({ err }, "Failed to record token usage");
11372
+ logger$8.warn({ err }, "Failed to record token usage");
11372
11373
  }
11373
11374
  });
11374
11375
  if (outputFormat === "human") {
@@ -11397,7 +11398,7 @@ async function runRetryEscalatedAction(options) {
11397
11398
  const msg = err instanceof Error ? err.message : String(err);
11398
11399
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
11399
11400
  else process.stderr.write(`Error: ${msg}\n`);
11400
- logger$7.error({ err }, "retry-escalated failed");
11401
+ logger$8.error({ err }, "retry-escalated failed");
11401
11402
  return 1;
11402
11403
  } finally {
11403
11404
  try {
@@ -11430,7 +11431,7 @@ function registerRetryEscalatedCommand(program, _version = "0.0.0", projectRoot
11430
11431
 
11431
11432
  //#endregion
11432
11433
  //#region src/cli/commands/cancel.ts
11433
- const logger$6 = createLogger("cancel-cmd");
11434
+ const logger$7 = createLogger("cancel-cmd");
11434
11435
  async function runCancelAction(options) {
11435
11436
  const { outputFormat, projectRoot, force } = options;
11436
11437
  const dbRoot = await resolveMainRepoRoot(projectRoot);
@@ -11469,7 +11470,7 @@ async function runCancelAction(options) {
11469
11470
  }
11470
11471
  } catch (err) {
11471
11472
  const msg = err instanceof Error ? err.message : String(err);
11472
- logger$6.warn({
11473
+ logger$7.warn({
11473
11474
  pid,
11474
11475
  err: msg
11475
11476
  }, "Failed to kill orchestrator");
@@ -11499,7 +11500,7 @@ async function runCancelAction(options) {
11499
11500
  await adapter.close();
11500
11501
  }
11501
11502
  } catch (err) {
11502
- logger$6.warn({ err }, "Could not update pipeline run status (non-fatal)");
11503
+ logger$7.warn({ err }, "Could not update pipeline run status (non-fatal)");
11503
11504
  }
11504
11505
  if (outputFormat === "json") process.stdout.write(formatOutput({
11505
11506
  cancelled: true,
@@ -11652,7 +11653,7 @@ function emitDiff(diff, ctx) {
11652
11653
 
11653
11654
  //#endregion
11654
11655
  //#region src/cli/commands/probe-author.ts
11655
- const logger$5 = createLogger("cli:probe-author");
11656
+ const logger$6 = createLogger("cli:probe-author");
11656
11657
  /**
11657
11658
  * A minimum-viable logger that routes everything to stderr. Used by the
11658
11659
  * subcommand to keep stdout reserved for the JSON result payload.
@@ -11721,7 +11722,7 @@ async function runProbeAuthorDispatch(opts, projectRoot, registry) {
11721
11722
  logger: stderrLogger
11722
11723
  });
11723
11724
  const workingDir = opts.workingDir !== void 0 ? resolve$1(opts.workingDir) : resolve$1(storyFilePath, "..");
11724
- logger$5.info({
11725
+ logger$6.info({
11725
11726
  storyKey: opts.storyKey,
11726
11727
  storyFile: storyFilePath,
11727
11728
  epicFile: epicFilePath,
@@ -11943,7 +11944,7 @@ function registerHistoryCommand(program) {
11943
11944
 
11944
11945
  //#endregion
11945
11946
  //#region src/cli/commands/repo-map.ts
11946
- const logger$4 = createLogger("cli:repo-map");
11947
+ const logger$5 = createLogger("cli:repo-map");
11947
11948
  /** Validate that a symbol name contains only safe identifier characters. */
11948
11949
  function isValidSymbolName(name) {
11949
11950
  return /^[a-zA-Z0-9_]+$/.test(name);
@@ -11978,15 +11979,15 @@ function registerRepoMapCommand(program) {
11978
11979
  const colRows = await doltClient.query(`SHOW COLUMNS FROM repo_map_symbols LIKE 'dependencies'`);
11979
11980
  if (colRows.length === 0) {
11980
11981
  await doltClient.query(`ALTER TABLE repo_map_symbols ADD COLUMN dependencies JSON`);
11981
- logger$4.info("Applied migration: added dependencies column to repo_map_symbols");
11982
+ logger$5.info("Applied migration: added dependencies column to repo_map_symbols");
11982
11983
  }
11983
11984
  } catch {
11984
- logger$4.debug("Skipping repo_map_symbols migration: table not yet created");
11985
+ logger$5.debug("Skipping repo_map_symbols migration: table not yet created");
11985
11986
  }
11986
- const symbolRepo = new DoltSymbolRepository(doltClient, logger$4);
11987
+ const symbolRepo = new DoltSymbolRepository(doltClient, logger$5);
11987
11988
  const metaRepo = new DoltRepoMapMetaRepository(doltClient);
11988
- const repoMapModule = new RepoMapModule(metaRepo, logger$4);
11989
- const queryEngine = new RepoMapQueryEngine(symbolRepo, logger$4);
11989
+ const repoMapModule = new RepoMapModule(metaRepo, logger$5);
11990
+ const queryEngine = new RepoMapQueryEngine(symbolRepo, logger$5);
11990
11991
  if (options.show === true || !options.update && !options.query && !options.dryRun) {
11991
11992
  const meta = await metaRepo.getMeta();
11992
11993
  const staleResult = await repoMapModule.checkStaleness();
@@ -12012,9 +12013,9 @@ function registerRepoMapCommand(program) {
12012
12013
  return;
12013
12014
  }
12014
12015
  if (options.update === true) {
12015
- logger$4.info("repo-map --update: triggering incremental update");
12016
- const gitClient = new GitClient(logger$4);
12017
- const grammarLoader = new GrammarLoader(logger$4);
12016
+ logger$5.info("repo-map --update: triggering incremental update");
12017
+ const gitClient = new GitClient(logger$5);
12018
+ const grammarLoader = new GrammarLoader(logger$5);
12018
12019
  if (grammarLoader.getGrammar(".ts") === null) {
12019
12020
  const msg = "tree-sitter grammars not installed. Run `npm install tree-sitter tree-sitter-typescript tree-sitter-javascript tree-sitter-python` in the substrate installation directory.";
12020
12021
  if (options.outputFormat === "json") console.log(JSON.stringify({
@@ -12025,15 +12026,15 @@ function registerRepoMapCommand(program) {
12025
12026
  process.exitCode = 1;
12026
12027
  return;
12027
12028
  }
12028
- const parser = new SymbolParser(grammarLoader, logger$4);
12029
- const storage = new RepoMapStorage(symbolRepo, metaRepo, gitClient, logger$4);
12029
+ const parser = new SymbolParser(grammarLoader, logger$5);
12030
+ const storage = new RepoMapStorage(symbolRepo, metaRepo, gitClient, logger$5);
12030
12031
  let updateWarning;
12031
12032
  try {
12032
12033
  await storage.incrementalUpdate(dbRoot, parser);
12033
12034
  } catch (err) {
12034
12035
  if (err instanceof AppError && err.code === ERR_REPO_MAP_STORAGE_WRITE) {
12035
12036
  updateWarning = err.message;
12036
- logger$4.warn({ err }, "repo-map --update: storage write error (partial update)");
12037
+ logger$5.warn({ err }, "repo-map --update: storage write error (partial update)");
12037
12038
  } else throw err;
12038
12039
  }
12039
12040
  const meta = await metaRepo.getMeta();
@@ -12053,7 +12054,7 @@ function registerRepoMapCommand(program) {
12053
12054
  return;
12054
12055
  }
12055
12056
  if (options.query !== void 0) {
12056
- logger$4.debug({ symbol: options.query }, "repo-map --query");
12057
+ logger$5.debug({ symbol: options.query }, "repo-map --query");
12057
12058
  const result = await queryEngine.query({
12058
12059
  symbols: [options.query],
12059
12060
  maxTokens: 4e3
@@ -12075,7 +12076,7 @@ function registerRepoMapCommand(program) {
12075
12076
  process.exitCode = 1;
12076
12077
  return;
12077
12078
  }
12078
- const injector = new RepoMapInjector(queryEngine, logger$4);
12079
+ const injector = new RepoMapInjector(queryEngine, logger$5);
12079
12080
  const injectionResult = await injector.buildContext(storyContent, 2e3);
12080
12081
  console.log(JSON.stringify({
12081
12082
  text: injectionResult.text,
@@ -12089,7 +12090,7 @@ function registerRepoMapCommand(program) {
12089
12090
 
12090
12091
  //#endregion
12091
12092
  //#region src/cli/commands/routing.ts
12092
- const logger$3 = createLogger("cli:routing");
12093
+ const logger$4 = createLogger("cli:routing");
12093
12094
  function registerRoutingCommand(program) {
12094
12095
  program.command("routing").description("Show routing configuration and auto-tune history").option("--history", "Show the routing auto-tune log (model changes applied)").option("--output-format <format>", "Output format: text or json", "text").action(async (options) => {
12095
12096
  const dbRoot = await resolveMainRepoRoot(process.cwd());
@@ -12097,7 +12098,7 @@ function registerRoutingCommand(program) {
12097
12098
  try {
12098
12099
  await store.initialize();
12099
12100
  if (options.history === true) {
12100
- logger$3.debug("routing --history: fetching tune log");
12101
+ logger$4.debug("routing --history: fetching tune log");
12101
12102
  const raw$1 = await store.getMetric("global", "routing_tune_log");
12102
12103
  let entries = [];
12103
12104
  if (Array.isArray(raw$1)) entries = raw$1.sort((a, b) => b.appliedAt.localeCompare(a.appliedAt));
@@ -12392,7 +12393,7 @@ function registerFactoryCommand$1(program) {
12392
12393
 
12393
12394
  //#endregion
12394
12395
  //#region src/cli/commands/reconcile-from-disk.ts
12395
- const logger$2 = createLogger("reconcile-from-disk");
12396
+ const logger$3 = createLogger("reconcile-from-disk");
12396
12397
  /**
12397
12398
  * The reconcile write (obs_2026-05-26_031). Keyed on `story_key` ALONE —
12398
12399
  * `wg_stories` has no `run_id` column (cols: story_key, epic, title, status,
@@ -12464,7 +12465,7 @@ async function readRunEntry(dbRoot, resolvedRunId) {
12464
12465
  stories
12465
12466
  };
12466
12467
  } catch {
12467
- logger$2.debug({ runId: resolvedRunId }, "failed to read individual run manifest");
12468
+ logger$3.debug({ runId: resolvedRunId }, "failed to read individual run manifest");
12468
12469
  return null;
12469
12470
  }
12470
12471
  }
@@ -12599,7 +12600,7 @@ async function runReconcileFromDiskAction(options) {
12599
12600
  const latestRun = await getLatestRun(probeAdapter);
12600
12601
  if (latestRun?.id) resolvedRunId = latestRun.id;
12601
12602
  } catch {
12602
- logger$2.debug("Dolt fallback failed during run-id resolution");
12603
+ logger$3.debug("Dolt fallback failed during run-id resolution");
12603
12604
  } finally {
12604
12605
  await probeAdapter.close().catch(swallowDebug("reconcile-probe-close"));
12605
12606
  }
@@ -12680,7 +12681,7 @@ async function runReconcileFromDiskAction(options) {
12680
12681
  stdoutTail: failedGateResult?.stdoutTail,
12681
12682
  durationMs: durationMs$1
12682
12683
  });
12683
- logger$2.info({
12684
+ logger$3.info({
12684
12685
  runId: resolvedRunId,
12685
12686
  failedGate: failedGateName,
12686
12687
  exitCode: failedGateResult?.exitCode
@@ -12738,7 +12739,7 @@ async function runReconcileFromDiskAction(options) {
12738
12739
  record.storyKey
12739
12740
  ]);
12740
12741
  });
12741
- logger$2.info({
12742
+ logger$3.info({
12742
12743
  runId: resolvedRunId,
12743
12744
  affectedStories: reconcilableRecords.map((r) => r.storyKey)
12744
12745
  }, "reconcile-from-disk: Dolt update complete");
@@ -12793,7 +12794,7 @@ function registerReconcileFromDiskCommand(program, _version = "0.0.0", projectRo
12793
12794
 
12794
12795
  //#endregion
12795
12796
  //#region src/cli/commands/report.ts
12796
- const logger$1 = createLogger("report");
12797
+ const logger$2 = createLogger("report");
12797
12798
  /**
12798
12799
  * v0.20.110: Minimum output_tokens for a verified/recovered story to be
12799
12800
  * trusted as having actually produced work. Below this, the story is flagged
@@ -12948,7 +12949,7 @@ async function readNotificationsForRun(runId, dbRoot) {
12948
12949
  const parsed = JSON.parse(raw);
12949
12950
  notifications.push(parsed);
12950
12951
  } catch (err) {
12951
- if (err.code !== "ENOENT") logger$1.warn({
12952
+ if (err.code !== "ENOENT") logger$2.warn({
12952
12953
  err,
12953
12954
  filePath
12954
12955
  }, "failed to read notification file — skipping");
@@ -12957,7 +12958,7 @@ async function readNotificationsForRun(runId, dbRoot) {
12957
12958
  try {
12958
12959
  await unlink(filePath);
12959
12960
  } catch (err) {
12960
- if (err.code !== "ENOENT") logger$1.warn({
12961
+ if (err.code !== "ENOENT") logger$2.warn({
12961
12962
  err,
12962
12963
  filePath
12963
12964
  }, "failed to delete notification file — continuing");
@@ -13290,7 +13291,7 @@ async function resolveLatestRunId(dbRoot) {
13290
13291
  const latest = await getLatestRun(probeAdapter);
13291
13292
  return latest?.id ?? null;
13292
13293
  } catch {
13293
- logger$1.debug("Dolt fallback failed during run-id resolution");
13294
+ logger$2.debug("Dolt fallback failed during run-id resolution");
13294
13295
  return null;
13295
13296
  } finally {
13296
13297
  await probeAdapter.close().catch(swallowDebug("report-probe-close"));
@@ -13301,7 +13302,7 @@ async function runReportAction(options) {
13301
13302
  const effectiveProjectRoot = process.env["SUBSTRATE_PROJECT_ROOT"] ?? projectRoot;
13302
13303
  const dbRoot = _dbRoot ?? await resolveMainRepoRoot(effectiveProjectRoot);
13303
13304
  const runsDir = join(dbRoot, ".substrate", "runs");
13304
- logger$1.debug({
13305
+ logger$2.debug({
13305
13306
  runArg,
13306
13307
  effectiveProjectRoot,
13307
13308
  dbRoot
@@ -13316,7 +13317,7 @@ async function runReportAction(options) {
13316
13317
  const data = await canonical.manifest.read();
13317
13318
  manifest = data;
13318
13319
  } catch {
13319
- logger$1.debug({ runId: resolvedRunId }, "canonical manifest read failed — using raw shim");
13320
+ logger$2.debug({ runId: resolvedRunId }, "canonical manifest read failed — using raw shim");
13320
13321
  }
13321
13322
  if (!manifest) manifest = await readRawManifest(runsDir, resolvedRunId);
13322
13323
  } else {
@@ -13327,7 +13328,7 @@ async function runReportAction(options) {
13327
13328
  const data = await canonical.manifest.read();
13328
13329
  manifest = data;
13329
13330
  } catch {
13330
- logger$1.debug({ runId: canonical.runId }, "canonical manifest read failed — using raw shim");
13331
+ logger$2.debug({ runId: canonical.runId }, "canonical manifest read failed — using raw shim");
13331
13332
  manifest = null;
13332
13333
  }
13333
13334
  }
@@ -13339,7 +13340,7 @@ async function runReportAction(options) {
13339
13340
  const data = await reread.manifest.read();
13340
13341
  manifest = data;
13341
13342
  } catch {
13342
- logger$1.debug({ runId: resolvedRunId }, "manifest read failed after Dolt resolution");
13343
+ logger$2.debug({ runId: resolvedRunId }, "manifest read failed after Dolt resolution");
13343
13344
  }
13344
13345
  if (!manifest) manifest = await readRawManifest(runsDir, resolvedRunId);
13345
13346
  }
@@ -13368,18 +13369,18 @@ async function runReportAction(options) {
13368
13369
  const state = manifest.per_story_state[row.story_key];
13369
13370
  if (state && !state.completed_at && row.completed_at) state.completed_at = row.completed_at;
13370
13371
  }
13371
- logger$1.debug({ storyCount: rows.length }, "Dolt wg_stories enrichment applied");
13372
+ logger$2.debug({ storyCount: rows.length }, "Dolt wg_stories enrichment applied");
13372
13373
  }
13373
13374
  } catch (err) {
13374
- logger$1.debug({ err }, "Dolt enrichment unavailable — using manifest-only data (degraded mode)");
13375
+ logger$2.debug({ err }, "Dolt enrichment unavailable — using manifest-only data (degraded mode)");
13375
13376
  } finally {
13376
13377
  if (doltClient !== null) await doltClient.close().catch((err) => {
13377
- logger$1.debug({ err }, "DoltClient.close() failed — non-fatal");
13378
+ logger$2.debug({ err }, "DoltClient.close() failed — non-fatal");
13378
13379
  });
13379
13380
  }
13380
13381
  }
13381
13382
  const halts = await readNotificationsForRun(resolvedRunId, dbRoot).catch((err) => {
13382
- logger$1.debug({ err }, "notification read failed — continuing without halt data");
13383
+ logger$2.debug({ err }, "notification read failed — continuing without halt data");
13383
13384
  return [];
13384
13385
  });
13385
13386
  const storyOutputTokens = new Map();
@@ -13392,7 +13393,7 @@ async function runReportAction(options) {
13392
13393
  const storyMetricsRows = await getStoryMetricsForRun(metricsAdapter, resolvedRunId);
13393
13394
  for (const row of storyMetricsRows) if (typeof row.output_tokens === "number") storyOutputTokens.set(row.story_key, row.output_tokens);
13394
13395
  } catch (err) {
13395
- logger$1.debug({ err }, "story_metrics read failed — low-output flagging unavailable");
13396
+ logger$2.debug({ err }, "story_metrics read failed — low-output flagging unavailable");
13396
13397
  } finally {
13397
13398
  await metricsAdapter.close().catch(swallowDebug("report-metrics-close"));
13398
13399
  }
@@ -13406,7 +13407,7 @@ async function runReportAction(options) {
13406
13407
  const rmData = await rmForAc.read();
13407
13408
  acPerStoryState = rmData.per_story_state;
13408
13409
  } catch {
13409
- logger$1.debug({ runId: resolvedRunId }, "RunManifest.read() for --verify-ac failed — using raw manifest fallback");
13410
+ logger$2.debug({ runId: resolvedRunId }, "RunManifest.read() for --verify-ac failed — using raw manifest fallback");
13410
13411
  }
13411
13412
  const storyEntries = Object.entries(acPerStoryState);
13412
13413
  for (const [storyKey, state] of storyEntries) {
@@ -13428,7 +13429,7 @@ async function runReportAction(options) {
13428
13429
  confidence: result.confidence
13429
13430
  };
13430
13431
  } catch (err) {
13431
- logger$1.debug({
13432
+ logger$2.debug({
13432
13433
  err,
13433
13434
  storyKey
13434
13435
  }, "ac traceability check failed for story (skipping)");
@@ -13461,6 +13462,141 @@ function registerReportCommand(program, _version = "0.0.0", projectRoot = proces
13461
13462
  });
13462
13463
  }
13463
13464
 
13465
+ //#endregion
13466
+ //#region src/modules/compiled-workflows/acceptance-derive.ts
13467
+ const logger$1 = createLogger("compiled-workflows:acceptance-derive");
13468
+ /** Cap on injected source-document content (chars) — PRDs can be book-length. */
13469
+ const SOURCE_CONTENT_CAP = 12e4;
13470
+ /** Shape problems the schema can't express: duplicate ids, id/end-state prefix drift. */
13471
+ function validateDerivedJourneys(journeys) {
13472
+ if (journeys.length === 0) return "derive produced zero journeys — a PRD with no identifiable user journeys should be reported via result: failed with an error, not an empty success";
13473
+ const seen = new Set();
13474
+ for (const j of journeys) {
13475
+ if (seen.has(j.id)) return `duplicate journey id "${j.id}"`;
13476
+ seen.add(j.id);
13477
+ for (const es of j.end_states) if (!es.id.startsWith(`${j.id}.`)) return `end-state "${es.id}" of journey "${j.id}" must use the "<journey-id>.<letter>" convention`;
13478
+ }
13479
+ return void 0;
13480
+ }
13481
+ async function runAcceptanceDerive(deps, params) {
13482
+ const { prdRelPath, prdContent, uxJourneysContent, existingRegistryYaml } = params;
13483
+ let template;
13484
+ try {
13485
+ template = await deps.pack.getPrompt("acceptance-derive");
13486
+ } catch (err) {
13487
+ return {
13488
+ result: "failed",
13489
+ error: `Failed to retrieve acceptance-derive prompt: ${err instanceof Error ? err.message : String(err)}`,
13490
+ tokenUsage: {
13491
+ input: 0,
13492
+ output: 0
13493
+ }
13494
+ };
13495
+ }
13496
+ const truncated = prdContent.length > SOURCE_CONTENT_CAP;
13497
+ const buildPrompt = (correctivePreamble) => {
13498
+ const { prompt } = assemblePrompt(template, [
13499
+ {
13500
+ name: "source_path",
13501
+ content: prdRelPath,
13502
+ priority: "required"
13503
+ },
13504
+ {
13505
+ name: "source_content",
13506
+ content: (truncated ? `(truncated to first ${String(SOURCE_CONTENT_CAP)} chars)\n` : "") + prdContent.slice(0, SOURCE_CONTENT_CAP),
13507
+ priority: "required"
13508
+ },
13509
+ {
13510
+ name: "ux_journeys",
13511
+ content: uxJourneysContent ?? "(no UX journey artifact provided)",
13512
+ priority: "required"
13513
+ },
13514
+ {
13515
+ name: "existing_registry",
13516
+ content: existingRegistryYaml ?? "(no existing registry — this is a first derivation)",
13517
+ priority: "required"
13518
+ }
13519
+ ], getTokenCeiling("acceptance-derive", deps.tokenCeilings).ceiling);
13520
+ return correctivePreamble !== void 0 ? `${correctivePreamble}\n\n${prompt}` : prompt;
13521
+ };
13522
+ let totalTokens = {
13523
+ input: 0,
13524
+ output: 0
13525
+ };
13526
+ let lastProblem = "unknown";
13527
+ for (let attempt = 0; attempt < 2; attempt++) {
13528
+ const prompt = attempt === 0 ? buildPrompt() : buildPrompt(`PREVIOUS ATTEMPT REJECTED: ${lastProblem}. Emit ONLY the YAML block per the Output Contract — unique journey ids, end-state ids prefixed "<journey-id>.", surfaces from the enum.`);
13529
+ const handle = deps.dispatcher.dispatch({
13530
+ prompt,
13531
+ agent: deps.agentId ?? "claude-code",
13532
+ taskType: "acceptance-derive",
13533
+ outputSchema: AcceptanceDeriveResultSchema,
13534
+ maxTurns: 30,
13535
+ ...deps.otlpEndpoint !== void 0 ? { otlpEndpoint: deps.otlpEndpoint } : {}
13536
+ });
13537
+ let dispatchResult;
13538
+ try {
13539
+ dispatchResult = await handle.result;
13540
+ } catch (err) {
13541
+ return {
13542
+ result: "failed",
13543
+ error: `Dispatch error: ${err instanceof Error ? err.message : String(err)}`,
13544
+ tokenUsage: totalTokens
13545
+ };
13546
+ }
13547
+ totalTokens = {
13548
+ input: totalTokens.input + dispatchResult.tokenEstimate.input,
13549
+ output: totalTokens.output + dispatchResult.tokenEstimate.output
13550
+ };
13551
+ if (dispatchResult.status === "failed" || dispatchResult.status === "timeout") return {
13552
+ result: "failed",
13553
+ error: `Dispatch status: ${dispatchResult.status}. ${dispatchResult.parseError ?? ""}`.trim(),
13554
+ tokenUsage: totalTokens
13555
+ };
13556
+ const parsed = AcceptanceDeriveResultSchema.safeParse(dispatchResult.parsed);
13557
+ if (!parsed.success) {
13558
+ lastProblem = `output failed schema validation (${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 500)})`;
13559
+ logger$1.warn({
13560
+ prdRelPath,
13561
+ attempt,
13562
+ lastProblem
13563
+ }, "RP1.1: derive output invalid");
13564
+ continue;
13565
+ }
13566
+ if (parsed.data.result === "failed") return {
13567
+ result: "failed",
13568
+ error: "acceptance-derive-refused",
13569
+ details: parsed.data.error ?? "derive agent reported failure without a reason",
13570
+ tokenUsage: totalTokens
13571
+ };
13572
+ const shapeProblem = validateDerivedJourneys(parsed.data.journeys);
13573
+ if (shapeProblem !== void 0) {
13574
+ lastProblem = shapeProblem;
13575
+ logger$1.warn({
13576
+ prdRelPath,
13577
+ attempt,
13578
+ shapeProblem
13579
+ }, "RP1.1: derived journeys malformed");
13580
+ continue;
13581
+ }
13582
+ logger$1.info({
13583
+ prdRelPath,
13584
+ journeys: parsed.data.journeys.map((j) => `${j.id}[${j.criticality}]`)
13585
+ }, "RP1.1: derive candidates accepted");
13586
+ return {
13587
+ result: "success",
13588
+ journeys: parsed.data.journeys,
13589
+ tokenUsage: totalTokens
13590
+ };
13591
+ }
13592
+ return {
13593
+ result: "failed",
13594
+ error: "acceptance-derive-invalid",
13595
+ details: `derive agent produced invalid output twice — last problem: ${lastProblem}`,
13596
+ tokenUsage: totalTokens
13597
+ };
13598
+ }
13599
+
13464
13600
  //#endregion
13465
13601
  //#region src/cli/commands/acceptance.ts
13466
13602
  const ACCEPTANCE_EXIT_SUCCESS = 0;
@@ -13673,6 +13809,225 @@ function registerAcceptanceCommand(program, version, registry) {
13673
13809
  process.stdout.write(JSON.stringify(output, null, 2) + "\n");
13674
13810
  process.exit(result.result === "success" ? ACCEPTANCE_EXIT_SUCCESS : ACCEPTANCE_EXIT_ERROR);
13675
13811
  });
13812
+ acceptanceCmd.command("derive").description("Derive a journey-registry CANDIDATE from a PRD (planning-lineage agent). Writes journeys.candidate.yaml — non-authoritative, ignored by the gate, promoted only by your explicit ratify action.").requiredOption("--prd <path>", "source document (PRD) to derive from — project-relative").option("--ux <path>", "optional UX journey artifact to derive alongside the PRD").option("--out <path>", `candidate output path (default: ${JOURNEY_CANDIDATE_PATH})`).option("--force", "overwrite an existing candidate file", false).option("--agent <id>", "agent adapter id", "claude-code").option("--pack <name>", "methodology pack carrying the derive prompt", "bmad").action(async (opts) => {
13813
+ if (process.env.LOG_LEVEL === void 0) process.env.LOG_LEVEL = "silent";
13814
+ if (registry === void 0) {
13815
+ process.stdout.write("acceptance derive: adapter registry unavailable in this invocation context\n");
13816
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13817
+ }
13818
+ const projectRoot = process.cwd();
13819
+ const prdAbs = resolve$1(projectRoot, opts.prd);
13820
+ const prdRel = relative(projectRoot, prdAbs);
13821
+ if (prdRel.startsWith("..") || prdRel === "") {
13822
+ process.stdout.write(`acceptance derive: --prd must resolve inside the project root (got ${prdAbs})\n`);
13823
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13824
+ }
13825
+ let prdContent;
13826
+ try {
13827
+ prdContent = await readFile$1(prdAbs, "utf-8");
13828
+ } catch (err) {
13829
+ process.stdout.write(`acceptance derive: cannot read PRD at ${prdAbs}: ${String(err)}\n`);
13830
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13831
+ return;
13832
+ }
13833
+ let uxContent;
13834
+ if (opts.ux !== void 0) try {
13835
+ uxContent = await readFile$1(resolve$1(projectRoot, opts.ux), "utf-8");
13836
+ } catch (err) {
13837
+ process.stdout.write(`acceptance derive: cannot read UX artifact at ${opts.ux}: ${String(err)}\n`);
13838
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13839
+ return;
13840
+ }
13841
+ let existingRegistryYaml;
13842
+ try {
13843
+ existingRegistryYaml = await readFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), "utf-8");
13844
+ } catch {
13845
+ existingRegistryYaml = void 0;
13846
+ }
13847
+ const outPath = opts.out !== void 0 ? resolve$1(projectRoot, opts.out) : join$1(projectRoot, JOURNEY_CANDIDATE_PATH);
13848
+ if (!opts.force) try {
13849
+ await readFile$1(outPath, "utf-8");
13850
+ process.stdout.write(`acceptance derive: candidate already exists at ${outPath} — review it, or re-run with --force to overwrite\n`);
13851
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13852
+ } catch {}
13853
+ const eventBus = createEventBus();
13854
+ const adapter = new InMemoryDatabaseAdapter();
13855
+ const packLoader = createPackLoader();
13856
+ let pack;
13857
+ try {
13858
+ pack = await packLoader.load(join$1(projectRoot, "packs", opts.pack));
13859
+ } catch (err) {
13860
+ process.stdout.write(`acceptance derive: failed to load pack '${opts.pack}': ${String(err)}\n`);
13861
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13862
+ return;
13863
+ }
13864
+ const contextCompiler = createContextCompiler({ db: adapter });
13865
+ const dispatcher = createDispatcher({
13866
+ eventBus,
13867
+ adapterRegistry: registry,
13868
+ logger: {
13869
+ debug: () => {},
13870
+ info: () => {},
13871
+ warn: () => {},
13872
+ error: () => {}
13873
+ }
13874
+ });
13875
+ process.stderr.write(`deriving journey candidates from ${prdRel} (real agent dispatch — may take a few minutes)…\n`);
13876
+ const result = await runAcceptanceDerive({
13877
+ db: adapter,
13878
+ pack,
13879
+ contextCompiler,
13880
+ dispatcher,
13881
+ agentId: opts.agent
13882
+ }, {
13883
+ prdRelPath: prdRel,
13884
+ prdContent,
13885
+ ...uxContent !== void 0 ? { uxJourneysContent: uxContent } : {},
13886
+ ...existingRegistryYaml !== void 0 ? { existingRegistryYaml } : {}
13887
+ });
13888
+ await dispatcher.shutdown();
13889
+ if (result.result !== "success" || result.journeys === void 0) {
13890
+ process.stdout.write(`acceptance derive: FAILED — ${result.error ?? "unknown"}${result.details !== void 0 ? `: ${result.details}` : ""}\n`);
13891
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13892
+ return;
13893
+ }
13894
+ const sourceSha = createHash("sha256").update(prdContent, "utf-8").digest("hex");
13895
+ const candidateDoc = {
13896
+ candidate: true,
13897
+ derived_from: prdRel,
13898
+ source_sha256: sourceSha,
13899
+ derived_at: new Date().toISOString(),
13900
+ journeys: result.journeys
13901
+ };
13902
+ const header = "# CANDIDATE journey registry — NOT authoritative.\n# Derived by `substrate acceptance derive`; the acceptance gate IGNORES this file.\n# Review (edit freely), then promote to journeys.yaml via your explicit ratify action.\n";
13903
+ try {
13904
+ await mkdir$1(dirname$1(outPath), { recursive: true });
13905
+ await writeFile$1(outPath, header + dump(candidateDoc, { lineWidth: 120 }), "utf-8");
13906
+ } catch (err) {
13907
+ process.stdout.write(`acceptance derive: failed to write candidate at ${outPath}: ${String(err)}\n`);
13908
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13909
+ return;
13910
+ }
13911
+ const needsElaboration = result.journeys.filter((j) => j.end_states.length === 0);
13912
+ process.stdout.write(`candidate written: ${relative(projectRoot, outPath)}\n ${String(result.journeys.length)} journeys (${String(result.journeys.filter((j) => j.criticality === "critical").length)} critical), ${String(result.journeys.reduce((n, j) => n + j.end_states.length, 0))} end-states` + (needsElaboration.length > 0 ? `, ${String(needsElaboration.length)} journey(s) need end-state elaboration: ${needsElaboration.map((j) => j.id).join(", ")}` : "") + `
13913
+ derived from ${prdRel} (sha256 ${sourceSha.slice(0, 12)}…)\n`);
13914
+ if (existingRegistryYaml !== void 0) {
13915
+ const parsedExisting = parseJourneyRegistry(existingRegistryYaml);
13916
+ if (parsedExisting.ok) process.stdout.write(`delta vs ratified registry v${String(parsedExisting.registry.version)}:\n${renderRegistryDiff(diffJourneySets(parsedExisting.registry.journeys, result.journeys))}\n`);
13917
+ }
13918
+ process.stdout.write("This candidate is NOT authoritative and the gate ignores it. Review every journey against the PRD — a journey missing here is invisible to the whole acceptance machinery.\n");
13919
+ process.exit(ACCEPTANCE_EXIT_SUCCESS);
13920
+ });
13921
+ acceptanceCmd.command("ratify").description(`Promote ${JOURNEY_CANDIDATE_PATH} to ${JOURNEY_REGISTRY_PATH} with a recorded provenance block. Interactive confirm unless --yes. The candidate file is deleted on success.`).option("--exclude <spec>", "exclude a candidate journey: \"UJ-2: reason text\" (repeatable; reason mandatory)", (v, acc) => [...acc, v], []).option("--epic <spec>", "assign an epic at ratify time: \"UJ-1=2\" (repeatable; critical journeys require one)", (v, acc) => [...acc, v], []).option("--ratified-by <name>", "who is ratifying (recorded in provenance)", "operator").option("--yes", "skip the interactive confirmation", false).action(async (opts) => {
13922
+ const projectRoot = process.cwd();
13923
+ const candidatePath = join$1(projectRoot, JOURNEY_CANDIDATE_PATH);
13924
+ let candidateContent;
13925
+ try {
13926
+ candidateContent = await readFile$1(candidatePath, "utf-8");
13927
+ } catch {
13928
+ process.stdout.write(`acceptance ratify: no candidate at ${JOURNEY_CANDIDATE_PATH} — run \`substrate acceptance derive --prd <path>\` first\n`);
13929
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13930
+ return;
13931
+ }
13932
+ const parsedCandidate = parseJourneyCandidate(candidateContent);
13933
+ if (!parsedCandidate.ok) {
13934
+ process.stdout.write(`acceptance ratify: candidate invalid:\n${parsedCandidate.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n")}\n`);
13935
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13936
+ return;
13937
+ }
13938
+ const candidate = parsedCandidate.candidate;
13939
+ const excludes = [];
13940
+ for (const spec of opts.exclude) {
13941
+ const sep = spec.indexOf(":");
13942
+ const id = sep >= 0 ? spec.slice(0, sep).trim() : spec.trim();
13943
+ const reason = sep >= 0 ? spec.slice(sep + 1).trim() : "";
13944
+ if (reason === "") {
13945
+ process.stdout.write(`acceptance ratify: --exclude "${spec}" has no reason — use "ID: reason" (reasonless exclusions are unauditable)\n`);
13946
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13947
+ return;
13948
+ }
13949
+ excludes.push({
13950
+ candidate: id,
13951
+ reason
13952
+ });
13953
+ }
13954
+ const epicAssignments = {};
13955
+ for (const spec of opts.epic) {
13956
+ const sep = spec.indexOf("=");
13957
+ const id = sep >= 0 ? spec.slice(0, sep).trim() : "";
13958
+ const n = sep >= 0 ? Number(spec.slice(sep + 1).trim()) : NaN;
13959
+ if (id === "" || !Number.isInteger(n) || n <= 0) {
13960
+ process.stdout.write(`acceptance ratify: --epic "${spec}" must be "JOURNEY-ID=<positive integer>"\n`);
13961
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13962
+ return;
13963
+ }
13964
+ epicAssignments[id] = n;
13965
+ }
13966
+ let existingRegistry;
13967
+ try {
13968
+ const existingContent = await readFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), "utf-8");
13969
+ const parsedExisting = parseJourneyRegistry(existingContent);
13970
+ if (!parsedExisting.ok) {
13971
+ process.stdout.write(`acceptance ratify: existing ${JOURNEY_REGISTRY_PATH} is INVALID — fix or remove it before re-ratifying:\n${parsedExisting.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n")}\n`);
13972
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13973
+ return;
13974
+ }
13975
+ existingRegistry = parsedExisting.registry;
13976
+ } catch {
13977
+ existingRegistry = void 0;
13978
+ }
13979
+ let sourceContent;
13980
+ try {
13981
+ sourceContent = await readFile$1(join$1(projectRoot, candidate.derived_from), "utf-8");
13982
+ } catch (err) {
13983
+ process.stdout.write(`acceptance ratify: cannot read source ${candidate.derived_from} (recorded in the candidate): ${String(err)}\n`);
13984
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13985
+ return;
13986
+ }
13987
+ const result = ratifyCandidate(candidate, {
13988
+ excludes,
13989
+ ratifiedBy: opts.ratifiedBy,
13990
+ sourceContent,
13991
+ now: new Date().toISOString(),
13992
+ ...existingRegistry !== void 0 ? { existingRegistry } : {},
13993
+ epicAssignments
13994
+ });
13995
+ if (!result.ok) {
13996
+ process.stdout.write(`acceptance ratify: the candidate would not ratify into a VALID registry — edit ${JOURNEY_CANDIDATE_PATH} (it is editable by design), assign epics via --epic, or exclude journeys via --exclude:\n` + result.issues.map((i) => ` ${i.path}: ${i.message}`).join("\n") + "\n");
13997
+ process.exit(ACCEPTANCE_EXIT_ERROR);
13998
+ return;
13999
+ }
14000
+ const reg = result.registry;
14001
+ process.stdout.write(`ratifying → ${JOURNEY_REGISTRY_PATH} v${String(reg.version)}${existingRegistry !== void 0 ? ` (replacing v${String(existingRegistry.version)})` : ""}\n` + reg.journeys.map((j) => ` ${j.id} [${j.criticality}${j.epic !== void 0 ? ` epic ${String(j.epic)}` : ""}] ${j.title} — ${String(j.end_states.length)} end-state(s)\n`).join("") + (reg.provenance?.excluded !== void 0 ? reg.provenance.excluded.map((e) => ` excluded: ${e.candidate} — ${e.reason}\n`).join("") : ""));
14002
+ if (existingRegistry !== void 0) process.stdout.write(`delta vs v${String(existingRegistry.version)}:\n${renderRegistryDiff(diffJourneySets(existingRegistry.journeys, candidate.journeys))}\n`);
14003
+ for (const w of result.warnings) process.stdout.write(`WARNING: ${w}\n`);
14004
+ if (!opts.yes) {
14005
+ const rl = createInterface$2({
14006
+ input: process.stdin,
14007
+ output: process.stderr
14008
+ });
14009
+ const answer = await rl.question("ratify? [y/N] ");
14010
+ rl.close();
14011
+ if (answer.trim().toLowerCase() !== "y") {
14012
+ process.stdout.write("aborted — candidate left in place\n");
14013
+ process.exit(ACCEPTANCE_EXIT_ERROR);
14014
+ return;
14015
+ }
14016
+ }
14017
+ const registryHeader = "# Journey registry — ratified via `substrate acceptance ratify`.\n# The acceptance gate reads THIS file from the trusted tree. COMMIT it.\n";
14018
+ try {
14019
+ await mkdir$1(dirname$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH)), { recursive: true });
14020
+ await writeFile$1(join$1(projectRoot, JOURNEY_REGISTRY_PATH), registryHeader + dump(reg, { lineWidth: 120 }), "utf-8");
14021
+ await unlink$1(candidatePath);
14022
+ } catch (err) {
14023
+ process.stdout.write(`acceptance ratify: write failed: ${String(err)}\n`);
14024
+ process.exit(ACCEPTANCE_EXIT_ERROR);
14025
+ return;
14026
+ }
14027
+ process.stdout.write(`ratified: ${JOURNEY_REGISTRY_PATH} v${String(reg.version)} (provenance recorded, ratified_by: ${opts.ratifiedBy}; candidate deleted)\nCOMMIT the registry — the gate reads the trusted (committed) tree.
14028
+ `);
14029
+ process.exit(ACCEPTANCE_EXIT_SUCCESS);
14030
+ });
13676
14031
  acceptanceCmd.command("canary <journeyId>").description("Self-test the gate: revert a journey's wiring commit(s), re-judge, require the verdict to flip. A miss auto-demotes the gate to advisory. Set LOG_LEVEL=silent for clean JSON.").requiredOption("--wiring-commit <sha...>", "commit SHA(s) that wired the journey (reverted in a scratch clone)").option("--registry-file <path>", `registry YAML (default: ${JOURNEY_REGISTRY_PATH} in cwd)`).option("--agent <id>", "agent adapter id", "claude-code").option("--pack <name>", "methodology pack carrying the judge prompt", "bmad").action(async (journeyId, opts) => {
13677
14032
  if (process.env.LOG_LEVEL === void 0) process.env.LOG_LEVEL = "silent";
13678
14033
  if (registry === void 0) {
@@ -13707,7 +14062,7 @@ function registerAcceptanceCommand(program, version, registry) {
13707
14062
  process.exit(ACCEPTANCE_EXIT_ERROR);
13708
14063
  return;
13709
14064
  }
13710
- const { runAcceptanceJudge: runAcceptanceJudge$1 } = await import("../acceptance-judge-CKNJdq03.js");
14065
+ const { runAcceptanceJudge: runAcceptanceJudge$1 } = await import("../acceptance-judge-D5Iba2D_.js");
13711
14066
  const eventBus = createEventBus();
13712
14067
  const adapter = new InMemoryDatabaseAdapter();
13713
14068
  const packLoader = createPackLoader();