substrate-ai 0.6.2 → 0.6.3

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,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltClient, DoltNotInstalled, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, FileStateStore, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SUBSTRATE_OWNED_SETTINGS_KEYS, SymbolParser, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, checkDoltInstalled, createConfigSystem, createContextCompiler, createDatabaseAdapter, createDispatcher, createDoltClient, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStateStore, createStopAfterGate, createTelemetryAdvisor, detectCycles, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, initSchema, initializeDolt, isSyncAdapter, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-DCmne2q6.js";
2
+ import { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltClient, DoltNotInstalled, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, FileStateStore, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SUBSTRATE_OWNED_SETTINGS_KEYS, SymbolParser, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, checkDoltInstalled, createConfigSystem, createContextCompiler, createDatabaseAdapter, createDispatcher, createDoltClient, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStateStore, createStopAfterGate, createTelemetryAdvisor, detectCycles, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, initSchema, initializeDolt, isSyncAdapter, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-GwwiCYXX.js";
3
3
  import { createLogger } from "../logger-D2fS2ccL.js";
4
4
  import { AdapterRegistry } from "../adapter-registry-D2zdMwVu.js";
5
5
  import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema } from "../config-migrator-DtZW1maj.js";
6
6
  import { ConfigError, createEventBus } from "../helpers-BihqWgVe.js";
7
- import { RoutingRecommender } from "../routing-BUE9pIxW.js";
7
+ import { RoutingRecommender } from "../routing-CobBiKeV.js";
8
8
  import { addTokenUsage, createDecision, createPipelineRun, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getTokenUsageSummary, listRequirements, updatePipelineRun } from "../decisions-C6MF2Cax.js";
9
9
  import { ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, OPERATIONAL_FINDING, STORY_METRICS, aggregateTokenUsageForRun, compareRunMetrics, getBaselineRunMetrics, getRunMetrics, getStoryMetricsForRun, incrementRunRestarts, listRunMetrics, tagRunAsBaseline } from "../operational-BRpT8MYF.js";
10
10
  import { abortMerge, createWorktree, getConflictingFiles, getMergedFiles, getOrphanedWorktrees, performMerge, removeBranch, removeWorktree, simulateMerge, verifyGitVersion } from "../git-utils-C-fdrHF_.js";
@@ -432,8 +432,8 @@ async function detectMonorepoProfile(rootDir) {
432
432
  return { project: {
433
433
  type: "monorepo",
434
434
  tool: "turborepo",
435
- buildCommand: "turbo build",
436
- testCommand: "turbo test",
435
+ buildCommand: "npx turbo build",
436
+ testCommand: "npx turbo test",
437
437
  packages
438
438
  } };
439
439
  }
@@ -1557,7 +1557,7 @@ function mapInternalPhaseToEventPhase(internalPhase) {
1557
1557
  }
1558
1558
  }
1559
1559
  async function runResumeAction(options) {
1560
- const { runId: specifiedRunId, stopAfter, outputFormat, projectRoot, concurrency, pack: packName, events: eventsFlag, registry } = options;
1560
+ const { runId: specifiedRunId, stopAfter, outputFormat, projectRoot, concurrency, pack: packName, events: eventsFlag, registry, maxReviewCycles = 2 } = options;
1561
1561
  if (stopAfter !== void 0 && !VALID_PHASES.includes(stopAfter)) {
1562
1562
  const errorMsg = `Invalid phase: "${stopAfter}". Valid phases: ${VALID_PHASES.join(", ")}`;
1563
1563
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, errorMsg) + "\n");
@@ -1654,7 +1654,7 @@ async function runResumeAction(options) {
1654
1654
  }
1655
1655
  }
1656
1656
  async function runFullPipelineFromPhase(options) {
1657
- const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, events: eventsFlag, existingRunId, projectRoot, registry: injectedRegistry, stories: explicitStories } = options;
1657
+ const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, events: eventsFlag, existingRunId, projectRoot, registry: injectedRegistry, stories: explicitStories, maxReviewCycles = 2 } = options;
1658
1658
  if (!existsSync(dbDir)) mkdirSync(dbDir, { recursive: true });
1659
1659
  const adapter = createDatabaseAdapter({
1660
1660
  backend: "auto",
@@ -1791,7 +1791,7 @@ async function runFullPipelineFromPhase(options) {
1791
1791
  eventBus,
1792
1792
  config: {
1793
1793
  maxConcurrency: concurrency,
1794
- maxReviewCycles: 2,
1794
+ maxReviewCycles,
1795
1795
  pipelineRunId: runId,
1796
1796
  enableHeartbeat: eventsFlag === true
1797
1797
  },
@@ -1971,7 +1971,7 @@ async function runFullPipelineFromPhase(options) {
1971
1971
  }
1972
1972
  }
1973
1973
  function registerResumeCommand(program, _version = "0.0.0", projectRoot = process.cwd(), registry) {
1974
- program.command("resume").description("Resume a previously interrupted pipeline run").option("--run-id <id>", "Pipeline run ID to resume (defaults to latest)").option("--pack <name>", "Methodology pack name", "bmad").option("--stop-after <phase>", "Stop pipeline after this phase completes (overrides saved state)").option("--concurrency <n>", "Maximum parallel conflict groups", (v) => parseInt(v, 10), 3).option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--events", "Emit structured NDJSON events on stdout for programmatic consumption").action(async (opts) => {
1974
+ program.command("resume").description("Resume a previously interrupted pipeline run").option("--run-id <id>", "Pipeline run ID to resume (defaults to latest)").option("--pack <name>", "Methodology pack name", "bmad").option("--stop-after <phase>", "Stop pipeline after this phase completes (overrides saved state)").option("--concurrency <n>", "Maximum parallel conflict groups", (v) => parseInt(v, 10), 3).option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--events", "Emit structured NDJSON events on stdout for programmatic consumption").option("--max-review-cycles <n>", "Maximum review cycles per story (default: 2)", (v) => parseInt(v, 10), 2).action(async (opts) => {
1975
1975
  const outputFormat = opts.outputFormat === "json" ? "json" : "human";
1976
1976
  const exitCode = await runResumeAction({
1977
1977
  runId: opts.runId,
@@ -1981,6 +1981,7 @@ function registerResumeCommand(program, _version = "0.0.0", projectRoot = proces
1981
1981
  concurrency: opts.concurrency,
1982
1982
  pack: opts.pack,
1983
1983
  events: opts.events,
1984
+ maxReviewCycles: opts.maxReviewCycles,
1984
1985
  registry
1985
1986
  });
1986
1987
  process.exitCode = exitCode;
@@ -2074,7 +2075,7 @@ async function runStatusAction(options) {
2074
2075
  if (runId !== void 0 && runId !== "") run = await getPipelineRunById(adapter, runId);
2075
2076
  else run = await getLatestRun(adapter);
2076
2077
  if (run === void 0) {
2077
- const errorMsg = runId !== void 0 ? `Pipeline run '${runId}' not found.` : "No pipeline runs found. Run `substrate run` first.";
2078
+ const errorMsg = runId !== void 0 ? `Pipeline run '${runId}' not found.` : "No pipeline runs found. Run `substrate run --events` to start a pipeline first.";
2078
2079
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, errorMsg) + "\n");
2079
2080
  else process.stderr.write(`Error: ${errorMsg}\n`);
2080
2081
  return 1;
@@ -3485,7 +3486,7 @@ async function runSupervisorAction(options, deps = {}) {
3485
3486
  await initSchema(expAdapter);
3486
3487
  const { runRunAction: runPipeline } = await import(
3487
3488
  /* @vite-ignore */
3488
- "../run-CcUT8-DF.js"
3489
+ "../run-B5-a932y.js"
3489
3490
  );
3490
3491
  const runStoryFn = async (opts) => {
3491
3492
  const exitCode = await runPipeline({
@@ -4001,7 +4002,7 @@ async function runMetricsAction(options) {
4001
4002
  const routingConfigPath = join(dbDir, "routing.yml");
4002
4003
  let routingConfig = null;
4003
4004
  if (existsSync(routingConfigPath)) try {
4004
- const { loadModelRoutingConfig } = await import("../routing-DbR9FPmj.js");
4005
+ const { loadModelRoutingConfig } = await import("../routing-CpsRPjLE.js");
4005
4006
  routingConfig = loadModelRoutingConfig(routingConfigPath);
4006
4007
  } catch {}
4007
4008
  if (routingConfig === null) routingConfig = {
@@ -263,7 +263,7 @@ var RoutingResolver = class RoutingResolver {
263
263
  return new RoutingResolver(config, logger$1);
264
264
  } catch (err) {
265
265
  if (err instanceof RoutingConfigError && err.code === "CONFIG_NOT_FOUND") {
266
- logger$1.warn({
266
+ logger$1.debug({
267
267
  configPath: filePath,
268
268
  component: "routing",
269
269
  reason: "config not found"
@@ -829,4 +829,4 @@ var RoutingTuner = class {
829
829
 
830
830
  //#endregion
831
831
  export { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig };
832
- //# sourceMappingURL=routing-BUE9pIxW.js.map
832
+ //# sourceMappingURL=routing-CobBiKeV.js.map
@@ -1,4 +1,4 @@
1
1
  import "./logger-D2fS2ccL.js";
2
- import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./routing-BUE9pIxW.js";
2
+ import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./routing-CobBiKeV.js";
3
3
 
4
4
  export { loadModelRoutingConfig };
@@ -1,8 +1,8 @@
1
- import { registerRunCommand, runRunAction } from "./run-DCmne2q6.js";
1
+ import { registerRunCommand, runRunAction } from "./run-GwwiCYXX.js";
2
2
  import "./logger-D2fS2ccL.js";
3
3
  import "./config-migrator-DtZW1maj.js";
4
4
  import "./helpers-BihqWgVe.js";
5
- import "./routing-BUE9pIxW.js";
5
+ import "./routing-CobBiKeV.js";
6
6
  import "./decisions-C6MF2Cax.js";
7
7
  import "./operational-BRpT8MYF.js";
8
8
 
@@ -1,7 +1,7 @@
1
1
  import { createLogger, deepMask } from "./logger-D2fS2ccL.js";
2
2
  import { CURRENT_CONFIG_FORMAT_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator } from "./config-migrator-DtZW1maj.js";
3
3
  import { ConfigError, ConfigIncompatibleFormatError, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-BihqWgVe.js";
4
- import { RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, loadModelRoutingConfig } from "./routing-BUE9pIxW.js";
4
+ import { RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, loadModelRoutingConfig } from "./routing-CobBiKeV.js";
5
5
  import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./decisions-C6MF2Cax.js";
6
6
  import { ADVISORY_NOTES, ESCALATION_DIAGNOSIS, OPERATIONAL_FINDING, STORY_METRICS, STORY_OUTCOME, TEST_EXPANSION_FINDING, TEST_PLAN, aggregateTokenUsageForRun, aggregateTokenUsageForStory, getStoryMetricsForRun, writeRunMetrics, writeStoryMetrics } from "./operational-BRpT8MYF.js";
7
7
  import { createRequire } from "module";
@@ -7202,7 +7202,7 @@ function detectPackageManager(projectRoot) {
7202
7202
  if (existsSync$1(join$1(projectRoot, "turbo.json"))) return {
7203
7203
  packageManager: "none",
7204
7204
  lockfile: "turbo.json",
7205
- command: "turbo build"
7205
+ command: "npx turbo build"
7206
7206
  };
7207
7207
  const nodeCandidates = [
7208
7208
  {
@@ -12511,7 +12511,7 @@ function detectInterfaceChanges(options) {
12511
12511
  for (const name of allNames) {
12512
12512
  let grepOutput = "";
12513
12513
  try {
12514
- grepOutput = execSync(`grep -r --include="*.test.ts" --include="*.spec.ts" -l "${name}" .`, {
12514
+ grepOutput = execSync(`grep -r --include="*.test.ts" --include="*.spec.ts" --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=.next --exclude-dir=coverage -l "${name}" .`, {
12515
12515
  cwd: projectRoot,
12516
12516
  encoding: "utf-8",
12517
12517
  timeout: 1e4,
@@ -16004,6 +16004,9 @@ function createTelemetryAdvisor(deps) {
16004
16004
 
16005
16005
  //#endregion
16006
16006
  //#region src/modules/implementation-orchestrator/orchestrator-impl.ts
16007
+ function estimateDispatchCost(input, output) {
16008
+ return (input * 3 + output * 15) / 1e6;
16009
+ }
16007
16010
  function createPauseGate() {
16008
16011
  let resolve$2;
16009
16012
  const promise = new Promise((res) => {
@@ -16719,7 +16722,7 @@ function createImplementationOrchestrator(deps) {
16719
16722
  agent: "create-story",
16720
16723
  input_tokens: createResult.tokenUsage.input,
16721
16724
  output_tokens: createResult.tokenUsage.output,
16722
- cost_usd: 0,
16725
+ cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
16723
16726
  metadata: JSON.stringify({ storyKey })
16724
16727
  });
16725
16728
  } catch (tokenErr) {
@@ -16897,7 +16900,7 @@ function createImplementationOrchestrator(deps) {
16897
16900
  agent: "test-plan",
16898
16901
  input_tokens: testPlanTokenUsage.input,
16899
16902
  output_tokens: testPlanTokenUsage.output,
16900
- cost_usd: 0,
16903
+ cost_usd: estimateDispatchCost(testPlanTokenUsage.input, testPlanTokenUsage.output),
16901
16904
  metadata: JSON.stringify({ storyKey })
16902
16905
  });
16903
16906
  } catch (tokenErr) {
@@ -17012,7 +17015,7 @@ function createImplementationOrchestrator(deps) {
17012
17015
  agent: `batch-${batch.batchIndex}`,
17013
17016
  input_tokens: batchResult.tokenUsage.input,
17014
17017
  output_tokens: batchResult.tokenUsage.output,
17015
- cost_usd: 0,
17018
+ cost_usd: estimateDispatchCost(batchResult.tokenUsage.input, batchResult.tokenUsage.output),
17016
17019
  metadata: JSON.stringify({
17017
17020
  storyKey,
17018
17021
  batchIndex: batch.batchIndex,
@@ -17068,7 +17071,7 @@ function createImplementationOrchestrator(deps) {
17068
17071
  agent: "dev-story",
17069
17072
  input_tokens: devResult.tokenUsage.input,
17070
17073
  output_tokens: devResult.tokenUsage.output,
17071
- cost_usd: 0,
17074
+ cost_usd: estimateDispatchCost(devResult.tokenUsage.input, devResult.tokenUsage.output),
17072
17075
  metadata: JSON.stringify({ storyKey })
17073
17076
  });
17074
17077
  } catch (tokenErr) {
@@ -17304,7 +17307,7 @@ function createImplementationOrchestrator(deps) {
17304
17307
  agent: useBatchedReview ? "code-review-batched" : "code-review",
17305
17308
  input_tokens: reviewResult.tokenUsage.input,
17306
17309
  output_tokens: reviewResult.tokenUsage.output,
17307
- cost_usd: 0,
17310
+ cost_usd: estimateDispatchCost(reviewResult.tokenUsage.input, reviewResult.tokenUsage.output),
17308
17311
  metadata: JSON.stringify({
17309
17312
  storyKey,
17310
17313
  reviewCycle: reviewCycles
@@ -17694,6 +17697,20 @@ function createImplementationOrchestrator(deps) {
17694
17697
  const constraints = decisions.filter((d) => d.category === "architecture");
17695
17698
  archConstraints = constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
17696
17699
  } catch {}
17700
+ let gitDiffContent = "";
17701
+ try {
17702
+ const diffFiles = checkGitDiffFiles(projectRoot ?? process.cwd());
17703
+ if (diffFiles.length > 0) gitDiffContent = execSync(`git diff HEAD -- ${diffFiles.map((f) => `"${f}"`).join(" ")}`, {
17704
+ cwd: projectRoot ?? process.cwd(),
17705
+ encoding: "utf-8",
17706
+ timeout: 1e4,
17707
+ stdio: [
17708
+ "ignore",
17709
+ "pipe",
17710
+ "pipe"
17711
+ ]
17712
+ }).trim();
17713
+ } catch {}
17697
17714
  const sections = isMajorRework ? [
17698
17715
  {
17699
17716
  name: "story_content",
@@ -17712,7 +17729,7 @@ function createImplementationOrchestrator(deps) {
17712
17729
  },
17713
17730
  {
17714
17731
  name: "git_diff",
17715
- content: "",
17732
+ content: gitDiffContent,
17716
17733
  priority: "optional"
17717
17734
  }
17718
17735
  ] : (() => {
@@ -22477,7 +22494,7 @@ function mapInternalPhaseToEventPhase(internalPhase) {
22477
22494
  }
22478
22495
  }
22479
22496
  async function runRunAction(options) {
22480
- const { pack: packName, from: startPhase, stopAfter, concept: conceptArg, conceptFile, stories: storiesArg, concurrency, outputFormat, projectRoot, events: eventsFlag, verbose: verboseFlag, tui: tuiFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, epic: epicNumber, dryRun, registry: injectedRegistry } = options;
22497
+ const { pack: packName, from: startPhase, stopAfter, concept: conceptArg, conceptFile, stories: storiesArg, concurrency, outputFormat, projectRoot, events: eventsFlag, verbose: verboseFlag, tui: tuiFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, epic: epicNumber, dryRun, maxReviewCycles = 2, registry: injectedRegistry } = options;
22481
22498
  if (startPhase !== void 0 && !VALID_PHASES.includes(startPhase)) {
22482
22499
  const errorMsg = `Invalid phase '${startPhase}'. Valid phases: ${VALID_PHASES.join(", ")}`;
22483
22500
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, errorMsg) + "\n");
@@ -22615,7 +22632,8 @@ async function runRunAction(options) {
22615
22632
  ...telemetryEnabled ? {
22616
22633
  telemetryEnabled: true,
22617
22634
  telemetryPort
22618
- } : {}
22635
+ } : {},
22636
+ maxReviewCycles
22619
22637
  });
22620
22638
  let storyKeys = [...parsedStoryKeys];
22621
22639
  if (!existsSync(dbDir)) mkdirSync(dbDir, { recursive: true });
@@ -23117,7 +23135,7 @@ async function runRunAction(options) {
23117
23135
  type: "pipeline:pre-flight-failure",
23118
23136
  ts: new Date().toISOString(),
23119
23137
  exitCode: payload.exitCode,
23120
- output: payload.output
23138
+ output: payload.output + "\nTip: Use --skip-preflight to bypass, or check your build command in .substrate/project-profile.yaml"
23121
23139
  });
23122
23140
  });
23123
23141
  eventBus.on("pipeline:contract-mismatch", (payload) => {
@@ -23180,7 +23198,7 @@ async function runRunAction(options) {
23180
23198
  eventBus,
23181
23199
  config: {
23182
23200
  maxConcurrency: concurrency,
23183
- maxReviewCycles: 2,
23201
+ maxReviewCycles,
23184
23202
  pipelineRunId: pipelineRun.id,
23185
23203
  enableHeartbeat: eventsFlag === true,
23186
23204
  skipPreflight: skipPreflight === true
@@ -23299,7 +23317,7 @@ async function runRunAction(options) {
23299
23317
  }
23300
23318
  }
23301
23319
  async function runFullPipeline(options) {
23302
- const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort } = options;
23320
+ const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, maxReviewCycles = 2, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort } = options;
23303
23321
  if (!existsSync(dbDir)) mkdirSync(dbDir, { recursive: true });
23304
23322
  const adapter = createDatabaseAdapter({
23305
23323
  backend: "auto",
@@ -23519,7 +23537,7 @@ async function runFullPipeline(options) {
23519
23537
  eventBus,
23520
23538
  config: {
23521
23539
  maxConcurrency: concurrency,
23522
- maxReviewCycles: 2,
23540
+ maxReviewCycles,
23523
23541
  pipelineRunId: runId,
23524
23542
  skipPreflight: skipPreflight === true
23525
23543
  },
@@ -23628,7 +23646,7 @@ async function runFullPipeline(options) {
23628
23646
  }
23629
23647
  }
23630
23648
  function registerRunCommand(program, _version = "0.0.0", projectRoot = process.cwd(), registry) {
23631
- program.command("run").description("Run the autonomous pipeline (use --from to start from a specific phase)").option("--pack <name>", "Methodology pack name", "bmad").option("--from <phase>", "Start from this phase: analysis, planning, solutioning, implementation").option("--stop-after <phase>", "Stop pipeline after this phase completes").option("--concept <text>", "Inline concept text (required when --from analysis)").option("--concept-file <path>", "Path to a file containing the concept text").option("--stories <keys>", "Comma-separated story keys (e.g., 10-1,10-2)").option("--epic <n>", "Scope story discovery to a single epic number (e.g., 27)", (v) => parseInt(v, 10)).option("--concurrency <n>", "Maximum parallel conflict groups", (v) => parseInt(v, 10), 3).option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--events", "Emit structured NDJSON events on stdout for programmatic consumption").option("--verbose", "Show detailed pino log output").option("--help-agent", "Print a machine-optimized prompt fragment for AI agents and exit").option("--tui", "Show TUI dashboard").option("--skip-ux", "Skip the UX design phase even if enabled in the pack manifest").option("--research", "Enable the research phase even if not set in the pack manifest").option("--skip-research", "Skip the research phase even if enabled in the pack manifest").option("--skip-preflight", "Skip the pre-flight build check (escape hatch for known-broken projects)").option("--dry-run", "Preview routing and repo-map injection without dispatching (Story 28-9)").action(async (opts) => {
23649
+ program.command("run").description("Run the autonomous pipeline (use --from to start from a specific phase)").option("--pack <name>", "Methodology pack name", "bmad").option("--from <phase>", "Start from this phase: analysis, planning, solutioning, implementation").option("--stop-after <phase>", "Stop pipeline after this phase completes").option("--concept <text>", "Inline concept text (required when --from analysis)").option("--concept-file <path>", "Path to a file containing the concept text").option("--stories <keys>", "Comma-separated story keys (e.g., 10-1,10-2)").option("--epic <n>", "Scope story discovery to a single epic number (e.g., 27)", (v) => parseInt(v, 10)).option("--concurrency <n>", "Maximum parallel conflict groups", (v) => parseInt(v, 10), 3).option("--project-root <path>", "Project root directory", projectRoot).option("--output-format <format>", "Output format: human (default) or json", "human").option("--events", "Emit structured NDJSON events on stdout for programmatic consumption").option("--verbose", "Show detailed pino log output").option("--help-agent", "Print a machine-optimized prompt fragment for AI agents and exit").option("--tui", "Show TUI dashboard").option("--skip-ux", "Skip the UX design phase even if enabled in the pack manifest").option("--research", "Enable the research phase even if not set in the pack manifest").option("--skip-research", "Skip the research phase even if enabled in the pack manifest").option("--skip-preflight", "Skip the pre-flight build check (escape hatch for known-broken projects)").option("--max-review-cycles <n>", "Maximum review cycles per story (default: 2)", (v) => parseInt(v, 10), 2).option("--dry-run", "Preview routing and repo-map injection without dispatching (Story 28-9)").action(async (opts) => {
23632
23650
  if (opts.helpAgent) {
23633
23651
  process.exitCode = await runHelpAgent();
23634
23652
  return;
@@ -23663,6 +23681,7 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
23663
23681
  research: opts.research,
23664
23682
  skipResearch: opts.skipResearch,
23665
23683
  skipPreflight: opts.skipPreflight,
23684
+ maxReviewCycles: opts.maxReviewCycles,
23666
23685
  dryRun: opts.dryRun,
23667
23686
  registry
23668
23687
  });
@@ -23672,4 +23691,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
23672
23691
 
23673
23692
  //#endregion
23674
23693
  export { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltClient, DoltNotInstalled, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, FileStateStore, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SUBSTRATE_OWNED_SETTINGS_KEYS, SymbolParser, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, checkDoltInstalled, createConfigSystem, createContextCompiler, createDatabaseAdapter, createDispatcher, createDoltClient, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStateStore, createStopAfterGate, createTelemetryAdvisor, detectCycles, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, initSchema, initializeDolt, isSyncAdapter, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
23675
- //# sourceMappingURL=run-DCmne2q6.js.map
23694
+ //# sourceMappingURL=run-GwwiCYXX.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",