substrate-ai 0.20.90 → 0.20.92

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,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
- import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-fVo5FGun.js";
2
+ import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-dWYa13k4.js";
3
3
  import { createLogger } from "../logger-KeHncl-f.js";
4
4
  import { createEventBus } from "../helpers-CElYrONe.js";
5
- import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-i8Re6HlE.js";
6
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-CC_c9n-U.js";
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, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-l0pA6zZF.js";
6
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-BXRwQRst.js";
7
7
  import "../adapter-registry-DIcrxjH8.js";
8
- import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-BKmGNnh4.js";
9
- import "../errors-DPIwiYIO.js";
8
+ import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-CSmDEOWH.js";
9
+ import "../errors-DZuD2tVU.js";
10
10
  import "../routing-DFxoKHDt.js";
11
11
  import { WorkGraphRepository } from "../work-graph-repository-DZyJv5pV.js";
12
12
  import "../decisions-CzSIEeGP.js";
13
13
  import "../decision-router-DblHY8se.js";
14
- import "../interactive-prompt-CPVsakLe.js";
14
+ import "../interactive-prompt-DY-PFko-.js";
15
15
  import "../recovery-engine-BKGBeBnW.js";
16
16
  import "../version-manager-impl-qFBiO4Eh.js";
17
- import { registerUpgradeCommand } from "../upgrade-bldRqYko.js";
17
+ import { registerUpgradeCommand } from "../upgrade-BP0P3qr9.js";
18
18
  import { Command } from "commander";
19
19
  import { fileURLToPath } from "url";
20
20
  import { dirname, join, resolve } from "path";
@@ -6787,14 +6787,14 @@ function buildWorkGraphFromManifest(perStoryState) {
6787
6787
  };
6788
6788
  }
6789
6789
  async function runStatusAction(options) {
6790
- const { outputFormat, runId, projectRoot, stateStore, history } = options;
6790
+ const { outputFormat, runId, projectRoot, historyReader, history } = options;
6791
6791
  if (history === true) {
6792
- if (!stateStore) {
6792
+ if (!historyReader) {
6793
6793
  process.stdout.write("History not available with file backend. Use Dolt backend for state history.\n");
6794
6794
  return 0;
6795
6795
  }
6796
6796
  try {
6797
- const entries = await stateStore.getHistory(20);
6797
+ const entries = await historyReader.getHistory(20);
6798
6798
  if (outputFormat === "json") {
6799
6799
  process.stdout.write(JSON.stringify(entries, null, 2) + "\n");
6800
6800
  return 0;
@@ -6890,7 +6890,7 @@ async function runStatusAction(options) {
6890
6890
  logger$15.debug({ err }, "Work graph query failed, continuing without work graph data");
6891
6891
  }
6892
6892
  if (run === void 0) {
6893
- const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-DzquK08l.js");
6893
+ const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-CgY9akax.js");
6894
6894
  const substrateDirPath = join(projectRoot, ".substrate");
6895
6895
  const processInfo = inspectProcessTree$1({
6896
6896
  projectRoot,
@@ -6916,12 +6916,6 @@ async function runStatusAction(options) {
6916
6916
  const decisionsCount = decisionsCountRows[0]?.cnt ?? 0;
6917
6917
  const storiesCountRows = await adapter.query(`SELECT COUNT(*) as cnt FROM requirements WHERE pipeline_run_id = ? AND source = 'solutioning-phase'`, [run.id]);
6918
6918
  const storiesCount = storiesCountRows[0]?.cnt ?? 0;
6919
- let storeStories = [];
6920
- if (stateStore) try {
6921
- storeStories = await stateStore.queryStories({});
6922
- } catch (err) {
6923
- logger$15.debug({ err }, "StateStore query failed, continuing without store data");
6924
- }
6925
6919
  if (outputFormat === "json") {
6926
6920
  const statusOutput = buildPipelineStatusOutput(run, tokenSummary, decisionsCount, storiesCount);
6927
6921
  const storyMetricsRows = await getStoryMetricsForRun(adapter, run.id);
@@ -6988,7 +6982,6 @@ async function runStatusAction(options) {
6988
6982
  stories_per_hour: storiesPerHour,
6989
6983
  cost_usd: totalCostUsd
6990
6984
  },
6991
- story_states: storeStories,
6992
6985
  workGraph: workGraph ?? null,
6993
6986
  latest_heartbeat_per_story_state: latestHeartbeatPerStoryState ?? {}
6994
6987
  };
@@ -7032,13 +7025,6 @@ async function runStatusAction(options) {
7032
7025
  }
7033
7026
  }
7034
7027
  }
7035
- if (storeStories.length > 0) {
7036
- process.stdout.write("\nStateStore Story States:\n");
7037
- for (const s of storeStories) if (s.phase === "CHECKPOINT") {
7038
- const filesCount = s.checkpointFilesCount ?? 0;
7039
- process.stdout.write(` ${s.storyKey}: ${s.phase} (${filesCount} files modified)\n`);
7040
- } else process.stdout.write(` ${s.storyKey}: ${s.phase} (${s.reviewCycles} review cycles)\n`);
7041
- }
7042
7028
  if (workGraph !== void 0) {
7043
7029
  const { summary, readyStories, blockedStories } = workGraph;
7044
7030
  process.stdout.write("\nWork Graph:\n");
@@ -7075,29 +7061,26 @@ function registerStatusCommand(program, _version = "0.0.0", projectRoot = proces
7075
7061
  program.command("status").description("Show status of the most recent (or specified) pipeline run").option("--run-id <id>", "Pipeline run ID to query (defaults to latest)").option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--history", "Show Dolt commit history for the state store").action(async (opts) => {
7076
7062
  const outputFormat = opts.outputFormat === "json" ? "json" : "human";
7077
7063
  const root = opts.projectRoot;
7078
- let stateStore;
7064
+ let historyReader;
7079
7065
  const doltStatePath = join(root, ".substrate", "state", ".dolt");
7080
7066
  if (existsSync$1(doltStatePath)) try {
7081
- stateStore = createStateStore({
7082
- backend: "dolt",
7083
- basePath: join(root, ".substrate", "state")
7084
- });
7085
- await stateStore.initialize();
7067
+ historyReader = createDoltOperatorReader({ basePath: join(root, ".substrate", "state") });
7068
+ await historyReader.initialize();
7086
7069
  } catch {
7087
- stateStore = void 0;
7070
+ historyReader = void 0;
7088
7071
  }
7089
7072
  try {
7090
7073
  const exitCode = await runStatusAction({
7091
7074
  outputFormat,
7092
7075
  runId: opts.runId,
7093
7076
  projectRoot: root,
7094
- stateStore,
7077
+ ...historyReader !== void 0 && { historyReader },
7095
7078
  history: opts.history
7096
7079
  });
7097
7080
  process.exitCode = exitCode;
7098
7081
  } finally {
7099
7082
  try {
7100
- await stateStore?.close();
7083
+ await historyReader?.close();
7101
7084
  } catch {}
7102
7085
  }
7103
7086
  });
@@ -7855,7 +7838,7 @@ function defaultSupervisorDeps() {
7855
7838
  if (cached === null) {
7856
7839
  const { AdapterRegistry: AR } = await import(
7857
7840
  /* @vite-ignore */
7858
- "../adapter-registry-B6px5DpL.js"
7841
+ "../adapter-registry-BZ0cVi8C.js"
7859
7842
  );
7860
7843
  cached = new AR();
7861
7844
  await cached.discoverAndRegister();
@@ -8422,11 +8405,11 @@ async function runSupervisorAction(options, deps = {}) {
8422
8405
  try {
8423
8406
  const { createExperimenter } = await import(
8424
8407
  /* @vite-ignore */
8425
- "../experimenter-DgeyT6XB.js"
8408
+ "../experimenter-GfhQpMis.js"
8426
8409
  );
8427
8410
  const { getLatestRun: getLatest } = await import(
8428
8411
  /* @vite-ignore */
8429
- "../decisions-CMUW6gO5.js"
8412
+ "../decisions-CsNAM-T-.js"
8430
8413
  );
8431
8414
  const expAdapter = createDatabaseAdapter({
8432
8415
  backend: "auto",
@@ -8436,7 +8419,7 @@ async function runSupervisorAction(options, deps = {}) {
8436
8419
  await initSchema(expAdapter);
8437
8420
  const { runRunAction: runPipeline } = await import(
8438
8421
  /* @vite-ignore */
8439
- "../run-AN24Jark.js"
8422
+ "../run-DPQ4DT5Q.js"
8440
8423
  );
8441
8424
  const runStoryFn = async (opts) => {
8442
8425
  const exitCode = await runPipeline({
@@ -8790,7 +8773,7 @@ function printFactoryRunTable(runs) {
8790
8773
  }
8791
8774
  }
8792
8775
  async function runMetricsAction(options) {
8793
- const { outputFormat, projectRoot, limit = 10, compare, tagBaseline, analysis, sprint, story, taskType, since, aggregate, efficiency, recommendations, turns, consumers, categories, compareStories, routingRecommendations, run, factory, probeAuthorSummary, probeAuthorClassSummary } = options;
8776
+ const { outputFormat, projectRoot, limit = 10, compare, tagBaseline, analysis, story, efficiency, recommendations, turns, consumers, categories, compareStories, routingRecommendations, run, factory, probeAuthorSummary, probeAuthorClassSummary } = options;
8794
8777
  const telemetryModes = [
8795
8778
  efficiency,
8796
8779
  recommendations,
@@ -8944,13 +8927,9 @@ async function runMetricsAction(options) {
8944
8927
  if (routingRecommendations === true) {
8945
8928
  const dbRoot$1 = await resolveMainRepoRoot(projectRoot);
8946
8929
  const dbDir = join(dbRoot$1, ".substrate");
8947
- const doltStatePath = join(dbDir, "state", ".dolt");
8948
- const doltExists = existsSync$1(doltStatePath);
8949
- const stateBackend = doltExists ? "dolt" : "file";
8950
- const stateBasePath = join(dbDir, "state");
8951
8930
  const stateStore = createStateStore({
8952
- backend: stateBackend,
8953
- basePath: stateBasePath
8931
+ backend: "file",
8932
+ basePath: dbDir
8954
8933
  });
8955
8934
  await stateStore.initialize();
8956
8935
  try {
@@ -8968,7 +8947,7 @@ async function runMetricsAction(options) {
8968
8947
  const routingConfigPath = join(dbDir, "routing.yml");
8969
8948
  let routingConfig = null;
8970
8949
  if (existsSync$1(routingConfigPath)) try {
8971
- const { loadModelRoutingConfig } = await import("../routing-BdwJkF3S.js");
8950
+ const { loadModelRoutingConfig } = await import("../routing-CD5PGDLe.js");
8972
8951
  routingConfig = loadModelRoutingConfig(routingConfigPath);
8973
8952
  } catch {}
8974
8953
  if (routingConfig === null) routingConfig = {
@@ -9141,26 +9120,6 @@ async function runMetricsAction(options) {
9141
9120
  return 0;
9142
9121
  }
9143
9122
  const runs = await listRunMetrics(adapter, limit);
9144
- let doltMetrics;
9145
- const doltStatePath = join(dbRoot, ".substrate", "state", ".dolt");
9146
- const hasDoltFilters = sprint !== void 0 || story !== void 0 || taskType !== void 0 || since !== void 0 || aggregate === true;
9147
- if (existsSync$1(doltStatePath) && hasDoltFilters) try {
9148
- const stateStore = createStateStore({
9149
- backend: "dolt",
9150
- basePath: join(dbRoot, ".substrate", "state")
9151
- });
9152
- await stateStore.initialize();
9153
- const doltFilter = {};
9154
- if (sprint !== void 0) doltFilter.sprint = sprint;
9155
- if (story !== void 0) doltFilter.storyKey = story;
9156
- if (taskType !== void 0) doltFilter.taskType = taskType;
9157
- if (since !== void 0) doltFilter.since = since;
9158
- if (aggregate !== void 0) doltFilter.aggregate = aggregate;
9159
- doltMetrics = await stateStore.queryMetrics(doltFilter);
9160
- await stateStore.close();
9161
- } catch (doltErr) {
9162
- logger$13.warn({ err: doltErr }, "StateStore query failed — falling back to SQLite metrics only");
9163
- }
9164
9123
  const storyMetricDecisions = await getDecisionsByCategory(adapter, STORY_METRICS);
9165
9124
  const storyMetrics = storyMetricDecisions.map((d) => {
9166
9125
  const colonIdx = d.key.indexOf(":");
@@ -9250,8 +9209,8 @@ async function runMetricsAction(options) {
9250
9209
  };
9251
9210
  if (probeAuthorSummary) {
9252
9211
  const allMetrics = storyMetricsWithFindings.map((sm) => sm.probe_author);
9253
- const aggregate$1 = aggregateProbeAuthorMetrics(allMetrics, storyMetricsWithFindings.length);
9254
- jsonPayload.probe_author_summary = aggregate$1;
9212
+ const aggregate = aggregateProbeAuthorMetrics(allMetrics, storyMetricsWithFindings.length);
9213
+ jsonPayload.probe_author_summary = aggregate;
9255
9214
  }
9256
9215
  if (probeAuthorClassSummary) {
9257
9216
  const classSummaryEntries = storyMetricsWithFindings.map((sm) => {
@@ -9263,26 +9222,9 @@ async function runMetricsAction(options) {
9263
9222
  });
9264
9223
  jsonPayload.probe_author_class_summary = rollupProbeAuthorByClass(classSummaryEntries);
9265
9224
  }
9266
- if (doltMetrics !== void 0) if (aggregate) {
9267
- const aggregateResults = doltMetrics.map((m) => ({
9268
- task_type: m.taskType,
9269
- count: m.count ?? 0,
9270
- avg_cost_usd: m.costUsd ?? 0,
9271
- sum_tokens_in: m.tokensIn ?? 0,
9272
- sum_tokens_out: m.tokensOut ?? 0
9273
- }));
9274
- const aggregateTotals = {
9275
- total_count: aggregateResults.reduce((sum, r) => sum + r.count, 0),
9276
- total_avg_cost_usd: aggregateResults.reduce((sum, r) => sum + r.avg_cost_usd, 0),
9277
- total_tokens_in: aggregateResults.reduce((sum, r) => sum + r.sum_tokens_in, 0),
9278
- total_tokens_out: aggregateResults.reduce((sum, r) => sum + r.sum_tokens_out, 0)
9279
- };
9280
- jsonPayload.aggregate_metrics = aggregateResults;
9281
- jsonPayload.aggregate_totals = aggregateTotals;
9282
- } else jsonPayload.dolt_metrics = doltMetrics;
9283
9225
  process.stdout.write(formatOutput(jsonPayload, "json", true) + "\n");
9284
9226
  } else {
9285
- if (runs.length === 0 && storyMetrics.length === 0 && (doltMetrics === void 0 || doltMetrics.length === 0) && factoryRuns.length === 0) {
9227
+ if (runs.length === 0 && storyMetrics.length === 0 && factoryRuns.length === 0) {
9286
9228
  process.stdout.write("No run metrics recorded yet. Run `substrate run` to generate metrics.\n");
9287
9229
  return 0;
9288
9230
  }
@@ -9317,41 +9259,6 @@ async function runMetricsAction(options) {
9317
9259
  process.stdout.write(` ${sm.story_key.padEnd(16)} ${runShort.padEnd(12)} ${String(sm.wall_clock_seconds).padStart(8)} ${sm.input_tokens.toLocaleString().padStart(10)} ${sm.output_tokens.toLocaleString().padStart(11)} ${String(sm.review_cycles).padStart(7)} ${stalledStr.padStart(8)}${costStr}\n`);
9318
9260
  }
9319
9261
  }
9320
- if (doltMetrics !== void 0 && doltMetrics.length > 0) if (aggregate) {
9321
- process.stdout.write(`\nStateStore Aggregate Metrics (by task type)\n`);
9322
- process.stdout.write("─".repeat(80) + "\n");
9323
- process.stdout.write(` ${"Task Type".padEnd(20)} ${"Count".padStart(8)} ${"Avg Cost".padStart(12)} ${"Sum Tokens In".padStart(14)} ${"Sum Tokens Out".padStart(15)}\n`);
9324
- process.stdout.write(" " + "─".repeat(72) + "\n");
9325
- let totalCount = 0;
9326
- let totalCost = 0;
9327
- let totalTokensIn = 0;
9328
- let totalTokensOut = 0;
9329
- for (const m of doltMetrics) {
9330
- const count = m.count ?? 0;
9331
- const avgCost = m.costUsd !== void 0 ? `$${m.costUsd.toFixed(4)}` : "-";
9332
- const sumIn = m.tokensIn !== void 0 ? m.tokensIn.toLocaleString() : "-";
9333
- const sumOut = m.tokensOut !== void 0 ? m.tokensOut.toLocaleString() : "-";
9334
- totalCount += count;
9335
- totalCost += m.costUsd ?? 0;
9336
- totalTokensIn += m.tokensIn ?? 0;
9337
- totalTokensOut += m.tokensOut ?? 0;
9338
- process.stdout.write(` ${m.taskType.padEnd(20)} ${String(count).padStart(8)} ${avgCost.padStart(12)} ${sumIn.padStart(14)} ${sumOut.padStart(15)}\n`);
9339
- }
9340
- process.stdout.write(" " + "─".repeat(72) + "\n");
9341
- process.stdout.write(` ${"TOTAL".padEnd(20)} ${String(totalCount).padStart(8)} ${`$${totalCost.toFixed(4)}`.padStart(12)} ${totalTokensIn.toLocaleString().padStart(14)} ${totalTokensOut.toLocaleString().padStart(15)}\n`);
9342
- } else {
9343
- process.stdout.write(`\nStateStore Metrics (${doltMetrics.length} records)\n`);
9344
- process.stdout.write("─".repeat(80) + "\n");
9345
- process.stdout.write(` ${"Story".padEnd(16)} ${"Task Type".padEnd(16)} ${"Tokens In".padStart(10)} ${"Tokens Out".padStart(11)} ${"Wall(ms)".padStart(10)} ${"Result".padEnd(12)}\n`);
9346
- process.stdout.write(" " + "─".repeat(76) + "\n");
9347
- for (const m of doltMetrics) {
9348
- const tokIn = m.tokensIn !== void 0 ? m.tokensIn.toLocaleString() : "-";
9349
- const tokOut = m.tokensOut !== void 0 ? m.tokensOut.toLocaleString() : "-";
9350
- const wall = m.wallClockMs !== void 0 ? String(m.wallClockMs) : "-";
9351
- const res = m.result ?? "-";
9352
- process.stdout.write(` ${m.storyKey.padEnd(16)} ${m.taskType.padEnd(16)} ${tokIn.padStart(10)} ${tokOut.padStart(11)} ${wall.padStart(10)} ${res.padEnd(12)}\n`);
9353
- }
9354
- }
9355
9262
  if (factoryRuns.length > 0) printFactoryRunTable(factoryRuns);
9356
9263
  }
9357
9264
  return 0;
@@ -9368,7 +9275,7 @@ async function runMetricsAction(options) {
9368
9275
  }
9369
9276
  }
9370
9277
  function registerMetricsCommand(program, _version = "0.0.0", projectRoot = process.cwd()) {
9371
- program.command("metrics").description("Show historical pipeline run metrics and cross-run comparison").option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--limit <n>", "Number of runs to show (default: 10)", (v) => parseInt(v, 10), 10).option("--compare <run-id-a,run-id-b>", "Compare two runs side-by-side (comma-separated IDs, e.g. abc123,def456)").option("--tag-baseline <run-id>", "Mark a run as the performance baseline").option("--analysis <run-id>", "Read and output the analysis report for the specified run (AC5 of Story 17-3)").option("--sprint <sprint>", "Filter StateStore metrics by sprint (e.g. sprint-1)").option("--story <story-key>", "Filter StateStore metrics by story key (e.g. 26-1)").option("--task-type <type>", "Filter StateStore metrics by task type (e.g. dev-story)").option("--since <iso-date>", "Filter StateStore metrics at or after this ISO timestamp").option("--aggregate", "Aggregate StateStore metrics grouped by task_type").option("--efficiency", "Show telemetry efficiency scores for recent stories").option("--recommendations", "Show all telemetry recommendations across stories").option("--turns <storyKey>", "Show per-turn analysis for a specific story").option("--consumers <storyKey>", "Show consumer stats for a specific story").option("--categories", "Show category stats (optionally scoped by --story <storyKey>)").option("--compare-stories <storyA,storyB>", "Compare efficiency scores of two stories side-by-side (comma-separated keys)").option("--routing-recommendations", "Show routing recommendations derived from phase token breakdown history").option("--run <run-id>", "Show per-iteration score history for a specific factory run").option("--factory", "Show only factory graph run metrics (excludes SDLC runs)").option("--probe-author-summary", "Print cross-run probe-author KPI aggregate (Story 60-15)").option("--probe-author-class-summary", "Print cross-run probe-author KPI aggregate broken down by trigger class (Story 65-6)").action(async (opts) => {
9278
+ program.command("metrics").description("Show historical pipeline run metrics and cross-run comparison").option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--limit <n>", "Number of runs to show (default: 10)", (v) => parseInt(v, 10), 10).option("--compare <run-id-a,run-id-b>", "Compare two runs side-by-side (comma-separated IDs, e.g. abc123,def456)").option("--tag-baseline <run-id>", "Mark a run as the performance baseline").option("--analysis <run-id>", "Read and output the analysis report for the specified run (AC5 of Story 17-3)").option("--story <story-key>", "Filter recommendations by story key (e.g. 26-1)").option("--efficiency", "Show telemetry efficiency scores for recent stories").option("--recommendations", "Show all telemetry recommendations across stories").option("--turns <storyKey>", "Show per-turn analysis for a specific story").option("--consumers <storyKey>", "Show consumer stats for a specific story").option("--categories", "Show category stats (optionally scoped by --story <storyKey>)").option("--compare-stories <storyA,storyB>", "Compare efficiency scores of two stories side-by-side (comma-separated keys)").option("--routing-recommendations", "Show routing recommendations derived from phase token breakdown history").option("--run <run-id>", "Show per-iteration score history for a specific factory run").option("--factory", "Show only factory graph run metrics (excludes SDLC runs)").option("--probe-author-summary", "Print cross-run probe-author KPI aggregate (Story 60-15)").option("--probe-author-class-summary", "Print cross-run probe-author KPI aggregate broken down by trigger class (Story 65-6)").action(async (opts) => {
9372
9279
  const outputFormat = opts.outputFormat === "json" ? "json" : "human";
9373
9280
  let compareIds;
9374
9281
  if (opts.compare !== void 0) {
@@ -9392,11 +9299,7 @@ function registerMetricsCommand(program, _version = "0.0.0", projectRoot = proce
9392
9299
  ...compareIds !== void 0 && { compare: compareIds },
9393
9300
  ...opts.tagBaseline !== void 0 && { tagBaseline: opts.tagBaseline },
9394
9301
  ...opts.analysis !== void 0 && { analysis: opts.analysis },
9395
- ...opts.sprint !== void 0 && { sprint: opts.sprint },
9396
9302
  ...opts.story !== void 0 && { story: opts.story },
9397
- ...opts.taskType !== void 0 && { taskType: opts.taskType },
9398
- ...opts.since !== void 0 && { since: opts.since },
9399
- ...opts.aggregate !== void 0 && { aggregate: opts.aggregate },
9400
9303
  ...opts.efficiency !== void 0 && { efficiency: opts.efficiency },
9401
9304
  ...opts.recommendations !== void 0 && { recommendations: opts.recommendations },
9402
9305
  ...opts.turns !== void 0 && { turns: opts.turns },
@@ -11451,207 +11354,6 @@ function registerCancelCommand(program, projectRoot = process.cwd()) {
11451
11354
  });
11452
11355
  }
11453
11356
 
11454
- //#endregion
11455
- //#region src/cli/commands/contracts.ts
11456
- function registerContractsCommand(program) {
11457
- program.command("contracts").description("Show contract declarations and verification status").option("--output-format <format>", "Output format: text or json", "text").action(async (options) => {
11458
- const dbRoot = await resolveMainRepoRoot(process.cwd());
11459
- const statePath = join$1(dbRoot, ".substrate", "state");
11460
- const doltStatePath = join$1(statePath, ".dolt");
11461
- const storeConfig = existsSync(doltStatePath) ? {
11462
- backend: "dolt",
11463
- basePath: statePath
11464
- } : {
11465
- backend: "file",
11466
- basePath: statePath
11467
- };
11468
- const store = createStateStore(storeConfig);
11469
- try {
11470
- await store.initialize();
11471
- const contracts = await store.queryContracts();
11472
- if (contracts.length === 0) {
11473
- console.log("No contracts stored. Run a pipeline to populate contract data.");
11474
- return;
11475
- }
11476
- const storyKeys = [...new Set(contracts.map((c) => c.storyKey))];
11477
- const verificationMap = new Map();
11478
- for (const sk of storyKeys) {
11479
- const verifications = await store.getContractVerification(sk);
11480
- const contractVerdicts = new Map();
11481
- for (const v of verifications) contractVerdicts.set(v.contractName, v.verdict);
11482
- verificationMap.set(sk, contractVerdicts);
11483
- }
11484
- const mergedRecords = contracts.map((c) => {
11485
- const verdicts = verificationMap.get(c.storyKey);
11486
- const verdict = verdicts?.get(c.contractName);
11487
- return {
11488
- storyKey: c.storyKey,
11489
- contractName: c.contractName,
11490
- direction: c.direction,
11491
- schemaPath: c.schemaPath,
11492
- verificationStatus: verdict === "pass" ? "✓ pass" : verdict === "fail" ? "✗ fail" : "? pending",
11493
- verdict: verdict ?? "pending"
11494
- };
11495
- });
11496
- if (options.outputFormat === "json") {
11497
- console.log(JSON.stringify(mergedRecords, null, 2));
11498
- return;
11499
- }
11500
- const headers = [
11501
- "Story Key",
11502
- "Contract Name",
11503
- "Direction",
11504
- "Schema Path",
11505
- "Status"
11506
- ];
11507
- const rows = mergedRecords.map((r) => [
11508
- r.storyKey,
11509
- r.contractName,
11510
- r.direction,
11511
- r.schemaPath,
11512
- r.verificationStatus
11513
- ]);
11514
- const colWidths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)));
11515
- const formatRow$1 = (cells) => cells.map((c, i) => c.padEnd(colWidths[i])).join(" ");
11516
- console.log(formatRow$1(headers));
11517
- console.log(colWidths.map((w) => "-".repeat(w)).join(" "));
11518
- for (const row of rows) console.log(formatRow$1(row));
11519
- } finally {
11520
- await store.close();
11521
- }
11522
- });
11523
- }
11524
-
11525
- //#endregion
11526
- //#region src/utils/degraded-mode-hint.ts
11527
- /**
11528
- * Determine the appropriate degraded-mode hint message based on whether Dolt
11529
- * is installed and/or initialized at the given state path.
11530
- *
11531
- * @param statePath - Absolute path to the substrate state directory
11532
- * (e.g. `/project/.substrate/state`).
11533
- */
11534
- async function getDegradedModeHint(statePath) {
11535
- try {
11536
- await checkDoltInstalled();
11537
- if (!existsSync(join$1(statePath, ".dolt"))) return {
11538
- hint: "Note: Dolt is installed but not initialized. Run `substrate init --dolt` to enable diff and history features.",
11539
- doltInstalled: true
11540
- };
11541
- return {
11542
- hint: "Note: Running on file backend. Diff and history require Dolt.",
11543
- doltInstalled: true
11544
- };
11545
- } catch (err) {
11546
- if (err instanceof DoltNotInstalled) return {
11547
- hint: "Note: Dolt is not installed. Install it from https://docs.dolthub.com/introduction/installation, then run `substrate init --dolt` to enable diff and history features.",
11548
- doltInstalled: false
11549
- };
11550
- throw err;
11551
- }
11552
- }
11553
- /**
11554
- * Emit a degraded-mode hint for the given command.
11555
- *
11556
- * - **Text mode**: writes the hint to `process.stderr` (not stdout).
11557
- * - **JSON mode**: does NOT write to stderr; the caller is responsible for
11558
- * writing the returned `hint` field to stdout as part of its JSON envelope.
11559
- *
11560
- * @param options - Hint options including output format, command name, and
11561
- * the resolved state directory path.
11562
- * @returns The hint message and a flag indicating whether Dolt is installed.
11563
- */
11564
- async function emitDegradedModeHint(options) {
11565
- const { hint, doltInstalled } = await getDegradedModeHint(options.statePath);
11566
- if (options.outputFormat !== "json") process.stderr.write(`\n${hint}\n`);
11567
- return {
11568
- hint,
11569
- doltInstalled
11570
- };
11571
- }
11572
-
11573
- //#endregion
11574
- //#region src/cli/commands/diff.ts
11575
- function registerDiffCommand(program) {
11576
- program.command("diff [storyKey]").description("Show stat-based diff of database changes for a story or sprint").option("--sprint <sprintId>", "Diff all stories in the specified sprint").option("--output-format <format>", "Output format: text or json", "text").action(async (storyKey, options) => {
11577
- if (storyKey === void 0 && options.sprint === void 0) {
11578
- console.error("Error: provide a story key or --sprint <sprintId>");
11579
- process.exitCode = 1;
11580
- return;
11581
- }
11582
- const dbRoot = await resolveMainRepoRoot(process.cwd());
11583
- const statePath = join$1(dbRoot, ".substrate", "state");
11584
- const doltStatePath = join$1(statePath, ".dolt");
11585
- const storeConfig = existsSync(doltStatePath) ? {
11586
- backend: "dolt",
11587
- basePath: statePath
11588
- } : {
11589
- backend: "file",
11590
- basePath: statePath
11591
- };
11592
- const store = createStateStore(storeConfig);
11593
- try {
11594
- await store.initialize();
11595
- if (store instanceof FileStateStore) {
11596
- const result = await emitDegradedModeHint({
11597
- outputFormat: options.outputFormat,
11598
- command: "diff",
11599
- statePath
11600
- });
11601
- if (options.outputFormat === "json") console.log(JSON.stringify({
11602
- backend: "file",
11603
- hint: result.hint,
11604
- diff: null
11605
- }));
11606
- return;
11607
- }
11608
- if (storyKey !== void 0) {
11609
- const diff = await store.diffStory(storyKey);
11610
- if (options.outputFormat === "json") {
11611
- console.log(JSON.stringify(diff, null, 2));
11612
- return;
11613
- }
11614
- console.log(`Diff for story ${storyKey}:`);
11615
- if (diff.tables.length === 0) console.log(" (no changes)");
11616
- else for (const t of diff.tables) console.log(` ${t.table}: +${t.added.length} -${t.deleted.length} ~${t.modified.length}`);
11617
- } else {
11618
- const stories = await store.queryStories({ sprint: options.sprint });
11619
- const tableMap = new Map();
11620
- for (const story of stories) {
11621
- const diff = await store.diffStory(story.storyKey);
11622
- for (const t of diff.tables) {
11623
- const existing = tableMap.get(t.table);
11624
- if (existing === void 0) tableMap.set(t.table, {
11625
- table: t.table,
11626
- added: [...t.added],
11627
- deleted: [...t.deleted],
11628
- modified: [...t.modified]
11629
- });
11630
- else {
11631
- existing.added = [...existing.added, ...t.added];
11632
- existing.deleted = [...existing.deleted, ...t.deleted];
11633
- existing.modified = [...existing.modified, ...t.modified];
11634
- }
11635
- }
11636
- }
11637
- const aggregated = Array.from(tableMap.values());
11638
- if (options.outputFormat === "json") {
11639
- console.log(JSON.stringify({
11640
- sprint: options.sprint,
11641
- tables: aggregated
11642
- }, null, 2));
11643
- return;
11644
- }
11645
- console.log(`Diff for sprint ${options.sprint}:`);
11646
- if (aggregated.length === 0) console.log(" (no changes)");
11647
- else for (const t of aggregated) console.log(` ${t.table}: +${t.added.length} -${t.deleted.length} ~${t.modified.length}`);
11648
- }
11649
- } finally {
11650
- await store.close();
11651
- }
11652
- });
11653
- }
11654
-
11655
11357
  //#endregion
11656
11358
  //#region src/cli/commands/probes-diff.ts
11657
11359
  /**
@@ -11980,6 +11682,54 @@ function emitError(format, message) {
11980
11682
  return 1;
11981
11683
  }
11982
11684
 
11685
+ //#endregion
11686
+ //#region src/utils/degraded-mode-hint.ts
11687
+ /**
11688
+ * Determine the appropriate degraded-mode hint message based on whether Dolt
11689
+ * is installed and/or initialized at the given state path.
11690
+ *
11691
+ * @param statePath - Absolute path to the substrate state directory
11692
+ * (e.g. `/project/.substrate/state`).
11693
+ */
11694
+ async function getDegradedModeHint(statePath) {
11695
+ try {
11696
+ await checkDoltInstalled();
11697
+ if (!existsSync(join$1(statePath, ".dolt"))) return {
11698
+ hint: "Note: Dolt is installed but not initialized. Run `substrate init --dolt` to enable history.",
11699
+ doltInstalled: true
11700
+ };
11701
+ return {
11702
+ hint: "Note: Running on file backend. History requires Dolt.",
11703
+ doltInstalled: true
11704
+ };
11705
+ } catch (err) {
11706
+ if (err instanceof DoltNotInstalled) return {
11707
+ hint: "Note: Dolt is not installed. Install it from https://docs.dolthub.com/introduction/installation, then run `substrate init --dolt` to enable history.",
11708
+ doltInstalled: false
11709
+ };
11710
+ throw err;
11711
+ }
11712
+ }
11713
+ /**
11714
+ * Emit a degraded-mode hint for the given command.
11715
+ *
11716
+ * - **Text mode**: writes the hint to `process.stderr` (not stdout).
11717
+ * - **JSON mode**: does NOT write to stderr; the caller is responsible for
11718
+ * writing the returned `hint` field to stdout as part of its JSON envelope.
11719
+ *
11720
+ * @param options - Hint options including output format, command name, and
11721
+ * the resolved state directory path.
11722
+ * @returns The hint message and a flag indicating whether Dolt is installed.
11723
+ */
11724
+ async function emitDegradedModeHint(options) {
11725
+ const { hint, doltInstalled } = await getDegradedModeHint(options.statePath);
11726
+ if (options.outputFormat !== "json") process.stderr.write(`\n${hint}\n`);
11727
+ return {
11728
+ hint,
11729
+ doltInstalled
11730
+ };
11731
+ }
11732
+
11983
11733
  //#endregion
11984
11734
  //#region src/cli/commands/history.ts
11985
11735
  function registerHistoryCommand(program) {
@@ -11988,29 +11738,22 @@ function registerHistoryCommand(program) {
11988
11738
  const dbRoot = await resolveMainRepoRoot(process.cwd());
11989
11739
  const statePath = join$1(dbRoot, ".substrate", "state");
11990
11740
  const doltStatePath = join$1(statePath, ".dolt");
11991
- const storeConfig = existsSync(doltStatePath) ? {
11992
- backend: "dolt",
11993
- basePath: statePath
11994
- } : {
11995
- backend: "file",
11996
- basePath: statePath
11997
- };
11998
- const store = createStateStore(storeConfig);
11741
+ if (!existsSync(doltStatePath)) {
11742
+ const result = await emitDegradedModeHint({
11743
+ outputFormat: options.outputFormat,
11744
+ command: "history",
11745
+ statePath
11746
+ });
11747
+ if (options.outputFormat === "json") console.log(JSON.stringify({
11748
+ backend: "file",
11749
+ hint: result.hint,
11750
+ entries: []
11751
+ }));
11752
+ return;
11753
+ }
11754
+ const store = createDoltOperatorReader({ basePath: statePath });
11999
11755
  try {
12000
11756
  await store.initialize();
12001
- if (store instanceof FileStateStore) {
12002
- const result = await emitDegradedModeHint({
12003
- outputFormat: options.outputFormat,
12004
- command: "history",
12005
- statePath
12006
- });
12007
- if (options.outputFormat === "json") console.log(JSON.stringify({
12008
- backend: "file",
12009
- hint: result.hint,
12010
- entries: []
12011
- }));
12012
- return;
12013
- }
12014
11757
  const entries = await store.getHistory(limit);
12015
11758
  if (entries.length === 0) {
12016
11759
  console.log("No history available.");
@@ -12182,16 +11925,7 @@ const logger$3 = createLogger("cli:routing");
12182
11925
  function registerRoutingCommand(program) {
12183
11926
  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) => {
12184
11927
  const dbRoot = await resolveMainRepoRoot(process.cwd());
12185
- const statePath = join$1(dbRoot, ".substrate", "state");
12186
- const doltStatePath = join$1(statePath, ".dolt");
12187
- const storeConfig = existsSync(doltStatePath) ? {
12188
- backend: "dolt",
12189
- basePath: statePath
12190
- } : {
12191
- backend: "file",
12192
- basePath: statePath
12193
- };
12194
- const store = createStateStore(storeConfig);
11928
+ const store = new FileStateStore({ basePath: join$1(dbRoot, ".substrate") });
12195
11929
  try {
12196
11930
  await store.initialize();
12197
11931
  if (options.history === true) {
@@ -13562,8 +13296,6 @@ async function createProgram() {
13562
13296
  registerMetricsCommand(program, version);
13563
13297
  registerRetryEscalatedCommand(program, version, process.cwd(), registry);
13564
13298
  registerCancelCommand(program, process.cwd());
13565
- registerContractsCommand(program);
13566
- registerDiffCommand(program);
13567
13299
  registerHistoryCommand(program);
13568
13300
  registerMigrateCommand(program);
13569
13301
  registerProbesCommand(program);
@@ -13589,8 +13321,8 @@ async function createProgram() {
13589
13321
  /** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
13590
13322
  function checkForUpdatesInBackground(currentVersion) {
13591
13323
  if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
13592
- import("../upgrade-BeqdIFCx.js").then(async () => {
13593
- const { createVersionManager } = await import("../version-manager-impl-CZ1AbRt3.js");
13324
+ import("../upgrade-DCDe5u0P.js").then(async () => {
13325
+ const { createVersionManager } = await import("../version-manager-impl-B8MpvZQz.js");
13594
13326
  const vm = createVersionManager();
13595
13327
  const result = await vm.checkForUpdates();
13596
13328
  if (result.updateAvailable) {