substrate-ai 0.20.34 → 0.20.36

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 { FileStateStore, RunManifest, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts } from "../health-CnV6ndAb.js";
2
+ import { FileStateStore, RunManifest, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, parseRuntimeProbes, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts } from "../health-BAcRfZ4s.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, 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, tagRunAsBaseline, updatePipelineRun } from "../dist-BnMsd9hC.js";
6
6
  import "../adapter-registry-DXLMTmfD.js";
7
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-BQxm1Qix.js";
7
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-YBY2vrF4.js";
8
8
  import "../errors-DSGhhrgv.js";
9
9
  import "../routing-CcBOCuC9.js";
10
10
  import "../decisions-C0pz9Clx.js";
@@ -20,7 +20,7 @@ import { execFile, spawn } from "node:child_process";
20
20
  import * as path$3 from "node:path";
21
21
  import * as path$2 from "node:path";
22
22
  import * as path$1 from "node:path";
23
- import { join as join$1 } from "node:path";
23
+ import { basename as basename$1, join as join$1 } from "node:path";
24
24
  import { randomUUID } from "node:crypto";
25
25
  import { z } from "zod";
26
26
  import * as fs from "node:fs/promises";
@@ -3667,7 +3667,7 @@ async function runStatusAction(options) {
3667
3667
  logger$12.debug({ err }, "Work graph query failed, continuing without work graph data");
3668
3668
  }
3669
3669
  if (run === void 0) {
3670
- const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-Bqzqu6zC.js");
3670
+ const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-DvAr7miW.js");
3671
3671
  const substrateDirPath = join(projectRoot, ".substrate");
3672
3672
  const processInfo = inspectProcessTree$1({
3673
3673
  projectRoot,
@@ -5198,7 +5198,7 @@ async function runSupervisorAction(options, deps = {}) {
5198
5198
  await initSchema(expAdapter);
5199
5199
  const { runRunAction: runPipeline } = await import(
5200
5200
  /* @vite-ignore */
5201
- "../run-B7jP4apv.js"
5201
+ "../run-__o2iU0w.js"
5202
5202
  );
5203
5203
  const runStoryFn = async (opts) => {
5204
5204
  const exitCode = await runPipeline({
@@ -8382,6 +8382,134 @@ function registerDiffCommand(program) {
8382
8382
  });
8383
8383
  }
8384
8384
 
8385
+ //#endregion
8386
+ //#region src/cli/commands/probes-diff.ts
8387
+ /**
8388
+ * Diff two probe sets by `name` (the canonical identity of a probe per
8389
+ * `RuntimeProbeListSchema`). Differences in command/timeout/assertion
8390
+ * shape between same-named probes appear in `inBoth` for downstream
8391
+ * shape-comparison; this function does NOT diff probe internals.
8392
+ */
8393
+ function computeProbesDiff(probesA, probesB) {
8394
+ const byNameA = new Map(probesA.map((p) => [p.name, p]));
8395
+ const byNameB = new Map(probesB.map((p) => [p.name, p]));
8396
+ const onlyInA = [];
8397
+ const onlyInB = [];
8398
+ const inBoth = [];
8399
+ for (const [name, a] of byNameA) {
8400
+ const b = byNameB.get(name);
8401
+ if (b === void 0) onlyInA.push(a);
8402
+ else inBoth.push({
8403
+ name,
8404
+ a,
8405
+ b
8406
+ });
8407
+ }
8408
+ for (const [name, b] of byNameB) if (!byNameA.has(name)) onlyInB.push(b);
8409
+ return {
8410
+ onlyInA,
8411
+ onlyInB,
8412
+ inBoth
8413
+ };
8414
+ }
8415
+ /**
8416
+ * Read an artifact file and extract its `## Runtime Probes` probe set.
8417
+ * Returns an empty array (not error) when the file has no probes section —
8418
+ * an artifact without probes is a valid input to the diff (e.g., the
8419
+ * disabled-arm output when probe-author was off).
8420
+ *
8421
+ * Throws when the file is unreadable OR when the probes block is present
8422
+ * but malformed (parse errors). Callers who want to tolerate parse errors
8423
+ * should catch.
8424
+ */
8425
+ function extractProbesFromArtifact(artifactPath) {
8426
+ if (!existsSync(artifactPath)) throw new Error(`probes-diff: artifact file not found: ${artifactPath}`);
8427
+ const content = readFileSync(artifactPath, "utf-8");
8428
+ const result = parseRuntimeProbes(content);
8429
+ if (result.kind === "absent") return [];
8430
+ if (result.kind === "invalid") throw new Error(`probes-diff: artifact has malformed ## Runtime Probes section: ${artifactPath}\n${result.error}`);
8431
+ return result.probes;
8432
+ }
8433
+ function registerProbesCommand(program) {
8434
+ const probes = program.command("probes").description("Inspect runtime-probe sections across story artifacts (Story 60-14)");
8435
+ probes.command("diff <artifactA> <artifactB>").description("Diff `## Runtime Probes` sections across two story-artifact files").option("--output-format <format>", "Output format: human (default) or json", "human").option("--story-key <key>", "Optional story key for output context (informational)").action(async (artifactA, artifactB, options) => {
8436
+ const format = options.outputFormat === "json" ? "json" : "human";
8437
+ let probesA;
8438
+ let probesB;
8439
+ try {
8440
+ probesA = extractProbesFromArtifact(artifactA);
8441
+ } catch (err) {
8442
+ const msg = err instanceof Error ? err.message : String(err);
8443
+ emitError(format, `failed to read artifact A: ${msg}`);
8444
+ process.exitCode = 1;
8445
+ return;
8446
+ }
8447
+ try {
8448
+ probesB = extractProbesFromArtifact(artifactB);
8449
+ } catch (err) {
8450
+ const msg = err instanceof Error ? err.message : String(err);
8451
+ emitError(format, `failed to read artifact B: ${msg}`);
8452
+ process.exitCode = 1;
8453
+ return;
8454
+ }
8455
+ const diff = computeProbesDiff(probesA, probesB);
8456
+ emitDiff(diff, {
8457
+ artifactA,
8458
+ artifactB,
8459
+ storyKey: options.storyKey,
8460
+ format,
8461
+ countsA: probesA.length,
8462
+ countsB: probesB.length
8463
+ });
8464
+ });
8465
+ }
8466
+ function emitError(format, message) {
8467
+ if (format === "json") process.stdout.write(JSON.stringify({
8468
+ success: false,
8469
+ error: message
8470
+ }) + "\n");
8471
+ else process.stderr.write(`probes diff error: ${message}\n`);
8472
+ }
8473
+ function emitDiff(diff, ctx) {
8474
+ if (ctx.format === "json") {
8475
+ process.stdout.write(JSON.stringify({
8476
+ success: true,
8477
+ storyKey: ctx.storyKey,
8478
+ artifactA: ctx.artifactA,
8479
+ artifactB: ctx.artifactB,
8480
+ counts: {
8481
+ a: ctx.countsA,
8482
+ b: ctx.countsB,
8483
+ inBoth: diff.inBoth.length
8484
+ },
8485
+ onlyInA: diff.onlyInA.map((p) => ({
8486
+ name: p.name,
8487
+ sandbox: p.sandbox,
8488
+ command: p.command
8489
+ })),
8490
+ onlyInB: diff.onlyInB.map((p) => ({
8491
+ name: p.name,
8492
+ sandbox: p.sandbox,
8493
+ command: p.command
8494
+ })),
8495
+ inBoth: diff.inBoth.map((m) => ({ name: m.name }))
8496
+ }, null, 2) + "\n");
8497
+ return;
8498
+ }
8499
+ const aLabel = basename$1(ctx.artifactA);
8500
+ const bLabel = basename$1(ctx.artifactB);
8501
+ process.stdout.write(`\nprobes diff${ctx.storyKey ? ` (story ${ctx.storyKey})` : ""}\n`);
8502
+ process.stdout.write(` A: ${ctx.artifactA} — ${ctx.countsA} probe(s)\n`);
8503
+ process.stdout.write(` B: ${ctx.artifactB} — ${ctx.countsB} probe(s)\n\n`);
8504
+ process.stdout.write(`Probes only in A (${aLabel}): ${diff.onlyInA.length}\n`);
8505
+ for (const p of diff.onlyInA) process.stdout.write(` - ${p.name} [${p.sandbox}]\n`);
8506
+ process.stdout.write(`\nProbes only in B (${bLabel}): ${diff.onlyInB.length}\n`);
8507
+ for (const p of diff.onlyInB) process.stdout.write(` - ${p.name} [${p.sandbox}]\n`);
8508
+ process.stdout.write(`\nProbes in both: ${diff.inBoth.length}\n`);
8509
+ for (const m of diff.inBoth) process.stdout.write(` - ${m.name}\n`);
8510
+ process.stdout.write("\n");
8511
+ }
8512
+
8385
8513
  //#endregion
8386
8514
  //#region src/cli/commands/history.ts
8387
8515
  function registerHistoryCommand(program) {
@@ -8985,6 +9113,7 @@ async function createProgram() {
8985
9113
  registerDiffCommand(program);
8986
9114
  registerHistoryCommand(program);
8987
9115
  registerMigrateCommand(program);
9116
+ registerProbesCommand(program);
8988
9117
  registerRepoMapCommand(program);
8989
9118
  registerRoutingCommand(program);
8990
9119
  registerCostCommand(program, version);
@@ -6343,5 +6343,5 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
6343
6343
  }
6344
6344
 
6345
6345
  //#endregion
6346
- export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, createStateStore, detectCycles, detectsEventDrivenAC, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, runHealthAction, validateStoryKey };
6347
- //# sourceMappingURL=health-CnV6ndAb.js.map
6346
+ export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, createStateStore, detectCycles, detectsEventDrivenAC, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, parseRuntimeProbes, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, runHealthAction, validateStoryKey };
6347
+ //# sourceMappingURL=health-BAcRfZ4s.js.map
@@ -1,4 +1,4 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-CnV6ndAb.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-BAcRfZ4s.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./dist-BnMsd9hC.js";
4
4
  import "./decisions-C0pz9Clx.js";
package/dist/index.d.ts CHANGED
@@ -2106,6 +2106,17 @@ interface OrchestratorEvents {
2106
2106
  storyKey: string;
2107
2107
  reason: string;
2108
2108
  };
2109
+ /**
2110
+ * Story 60-14: probe-author phase mode resolved at orchestrator start.
2111
+ * Emitted once per run with the effective mode and where it came from
2112
+ * (CLI flag, env var, or default). Powers the A/B validation harness
2113
+ * by recording which arm of the experiment a given run belongs to.
2114
+ */
2115
+ 'probe-author:enabled': {
2116
+ runId: string;
2117
+ mode: 'enabled' | 'disabled';
2118
+ source: 'cli' | 'env' | 'default';
2119
+ };
2109
2120
  /**
2110
2121
  * Story 62-3: code-review agent emitted YAML output that failed schema
2111
2122
  * validation (typically a parse error from unquoted-colon-in-value or
@@ -1,4 +1,4 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, detectsEventDrivenAC, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-CnV6ndAb.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, detectsEventDrivenAC, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-BAcRfZ4s.js";
2
2
  import { createLogger } from "./logger-KeHncl-f.js";
3
3
  import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
4
4
  import { ADVISORY_NOTES, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-BnMsd9hC.js";
@@ -12176,6 +12176,7 @@ function createImplementationOrchestrator(deps) {
12176
12176
  _drainResolve = resolve$6;
12177
12177
  });
12178
12178
  let _otlpEndpoint;
12179
+ let _probeAuthorEffectiveMode = "enabled";
12179
12180
  const verificationStore = new VerificationStore();
12180
12181
  const verificationPipeline = createDefaultVerificationPipeline(toSdlcEventBus(eventBus));
12181
12182
  const _stateStoreCache = new Map();
@@ -13321,7 +13322,7 @@ function createImplementationOrchestrator(deps) {
13321
13322
  error: err instanceof Error ? err.message : String(err)
13322
13323
  }, "Failed to parse interface contracts — continuing without contract declarations");
13323
13324
  }
13324
- if (storyFilePath) try {
13325
+ if (storyFilePath && _probeAuthorEffectiveMode === "enabled") try {
13325
13326
  let probeAuthorEpicContent = "";
13326
13327
  const probeAuthorEpicsPath = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
13327
13328
  if (probeAuthorEpicsPath) try {
@@ -14171,6 +14172,79 @@ function createImplementationOrchestrator(deps) {
14171
14172
  let schemaValidationRetries = 0;
14172
14173
  let previousIterationWasMalformed = false;
14173
14174
  const MAX_SCHEMA_VALIDATION_RETRIES = 3;
14175
+ async function runVerificationAndComplete(args) {
14176
+ const { recordedVerdict, finalReviewCycles, reviewResult, autoApprove } = args;
14177
+ endPhase(storyKey, "code-review");
14178
+ if (config.skipVerification !== true) {
14179
+ const latestReviewSignals = reviewResult != null ? {
14180
+ dispatchFailed: reviewResult.dispatchFailed,
14181
+ error: reviewResult.error,
14182
+ rawOutput: reviewResult.rawOutput
14183
+ } : void 0;
14184
+ let sourceEpicContent;
14185
+ const epicsPath = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
14186
+ if (epicsPath) try {
14187
+ const epicFull = readFileSync(epicsPath, "utf-8");
14188
+ const section = extractStorySection(epicFull, storyKey);
14189
+ if (section) sourceEpicContent = section;
14190
+ } catch {}
14191
+ await persistDevStorySignals(storyKey, devStorySignals, runManifest);
14192
+ const verifContext = assembleVerificationContext({
14193
+ storyKey,
14194
+ workingDir: projectRoot ?? process.cwd(),
14195
+ reviewResult: latestReviewSignals,
14196
+ storyContent: storyContentForVerification,
14197
+ devStoryResult: devStorySignals,
14198
+ outputTokenCount: devOutputTokenCount,
14199
+ sourceEpicContent
14200
+ });
14201
+ const verifSummary = await verificationPipeline.run(verifContext, "A");
14202
+ verificationStore.set(storyKey, verifSummary);
14203
+ await persistVerificationResult(storyKey, verifSummary, runManifest);
14204
+ if (verifSummary.status === "fail") {
14205
+ updateStory(storyKey, {
14206
+ phase: "VERIFICATION_FAILED",
14207
+ completedAt: new Date().toISOString()
14208
+ });
14209
+ persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
14210
+ err,
14211
+ storyKey
14212
+ }, "StateStore write failed after verification-failed"));
14213
+ await writeStoryMetricsBestEffort(storyKey, "verification-failed", finalReviewCycles);
14214
+ await persistState();
14215
+ return "verification-failed";
14216
+ }
14217
+ }
14218
+ if (autoApprove !== void 0) eventBus.emit("story:auto-approved", {
14219
+ storyKey,
14220
+ verdict: recordedVerdict,
14221
+ reviewCycles: finalReviewCycles,
14222
+ maxReviewCycles: config.maxReviewCycles,
14223
+ issueCount: autoApprove.issueCount,
14224
+ reason: autoApprove.reason
14225
+ });
14226
+ const completeUpdate = {
14227
+ phase: "COMPLETE",
14228
+ completedAt: new Date().toISOString()
14229
+ };
14230
+ if (autoApprove !== void 0) completeUpdate.reviewCycles = finalReviewCycles;
14231
+ if (autoApprove?.downgradeLastVerdict !== void 0) completeUpdate.lastVerdict = autoApprove.downgradeLastVerdict;
14232
+ updateStory(storyKey, completeUpdate);
14233
+ if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
14234
+ if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
14235
+ storyKey,
14236
+ category: "verification-result-missing"
14237
+ }, "post-COMPLETE invariant: verification_result absent in manifest");
14238
+ }).catch(() => {});
14239
+ await writeStoryMetricsBestEffort(storyKey, recordedVerdict, finalReviewCycles);
14240
+ await writeStoryOutcomeBestEffort(storyKey, "complete", finalReviewCycles);
14241
+ eventBus.emit("orchestrator:story-complete", {
14242
+ storyKey,
14243
+ reviewCycles: finalReviewCycles
14244
+ });
14245
+ await persistState();
14246
+ return "completed";
14247
+ }
14174
14248
  while (keepReviewing) {
14175
14249
  await waitIfPaused();
14176
14250
  if (_state !== "RUNNING") return;
@@ -14457,65 +14531,13 @@ function createImplementationOrchestrator(deps) {
14457
14531
  return;
14458
14532
  }
14459
14533
  if (verdict === "SHIP_IT" || verdict === "LGTM_WITH_NOTES") {
14460
- endPhase(storyKey, "code-review");
14461
- if (config.skipVerification !== true) {
14462
- const latestReviewSignals = reviewResult != null ? {
14463
- dispatchFailed: reviewResult.dispatchFailed,
14464
- error: reviewResult.error,
14465
- rawOutput: reviewResult.rawOutput
14466
- } : void 0;
14467
- let sourceEpicContent;
14468
- const epicsPath1 = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
14469
- if (epicsPath1) try {
14470
- const epicFull = readFileSync(epicsPath1, "utf-8");
14471
- const section = extractStorySection(epicFull, storyKey);
14472
- if (section) sourceEpicContent = section;
14473
- } catch {}
14474
- await persistDevStorySignals(storyKey, devStorySignals, runManifest);
14475
- const verifContext = assembleVerificationContext({
14476
- storyKey,
14477
- workingDir: projectRoot ?? process.cwd(),
14478
- reviewResult: latestReviewSignals,
14479
- storyContent: storyContentForVerification,
14480
- devStoryResult: devStorySignals,
14481
- outputTokenCount: devOutputTokenCount,
14482
- sourceEpicContent
14483
- });
14484
- const verifSummary = await verificationPipeline.run(verifContext, "A");
14485
- verificationStore.set(storyKey, verifSummary);
14486
- await persistVerificationResult(storyKey, verifSummary, runManifest);
14487
- if (verifSummary.status === "fail") {
14488
- updateStory(storyKey, {
14489
- phase: "VERIFICATION_FAILED",
14490
- completedAt: new Date().toISOString()
14491
- });
14492
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
14493
- err,
14494
- storyKey
14495
- }, "StateStore write failed after verification-failed"));
14496
- await writeStoryMetricsBestEffort(storyKey, "verification-failed", reviewCycles);
14497
- await persistState();
14498
- return;
14499
- }
14500
- }
14501
- updateStory(storyKey, {
14502
- phase: "COMPLETE",
14503
- completedAt: new Date().toISOString()
14504
- });
14505
- if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
14506
- if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
14507
- storyKey,
14508
- category: "verification-result-missing"
14509
- }, "post-COMPLETE invariant: verification_result absent in manifest");
14510
- }).catch(() => {});
14511
14534
  const completedReviewCycles = reviewCycles + 1;
14512
- await writeStoryMetricsBestEffort(storyKey, verdict, completedReviewCycles);
14513
- await writeStoryOutcomeBestEffort(storyKey, "complete", completedReviewCycles);
14514
- eventBus.emit("orchestrator:story-complete", {
14515
- storyKey,
14516
- reviewCycles: completedReviewCycles
14535
+ const outcome = await runVerificationAndComplete({
14536
+ recordedVerdict: verdict,
14537
+ finalReviewCycles: completedReviewCycles,
14538
+ reviewResult
14517
14539
  });
14518
- await persistState();
14540
+ if (outcome === "verification-failed") return;
14519
14541
  if (verdict === "LGTM_WITH_NOTES" && reviewResult.notes && config.pipelineRunId) try {
14520
14542
  await createDecision(db, {
14521
14543
  pipeline_run_id: config.pipelineRunId,
@@ -14730,73 +14752,16 @@ function createImplementationOrchestrator(deps) {
14730
14752
  err
14731
14753
  }, "Auto-approve fix dispatch failed — approving anyway (issues were minor)");
14732
14754
  }
14733
- endPhase(storyKey, "code-review");
14734
- if (config.skipVerification !== true) {
14735
- const latestReviewSignals = reviewResult != null ? {
14736
- dispatchFailed: reviewResult.dispatchFailed,
14737
- error: reviewResult.error,
14738
- rawOutput: reviewResult.rawOutput
14739
- } : void 0;
14740
- let sourceEpicContent2;
14741
- const epicsPath2 = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
14742
- if (epicsPath2) try {
14743
- const epicFull2 = readFileSync(epicsPath2, "utf-8");
14744
- const section2 = extractStorySection(epicFull2, storyKey);
14745
- if (section2) sourceEpicContent2 = section2;
14746
- } catch {}
14747
- await persistDevStorySignals(storyKey, devStorySignals, runManifest);
14748
- const verifContext = assembleVerificationContext({
14749
- storyKey,
14750
- workingDir: projectRoot ?? process.cwd(),
14751
- reviewResult: latestReviewSignals,
14752
- storyContent: storyContentForVerification,
14753
- devStoryResult: devStorySignals,
14754
- outputTokenCount: devOutputTokenCount,
14755
- sourceEpicContent: sourceEpicContent2
14756
- });
14757
- const verifSummary = await verificationPipeline.run(verifContext, "A");
14758
- verificationStore.set(storyKey, verifSummary);
14759
- await persistVerificationResult(storyKey, verifSummary, runManifest);
14760
- if (verifSummary.status === "fail") {
14761
- updateStory(storyKey, {
14762
- phase: "VERIFICATION_FAILED",
14763
- completedAt: new Date().toISOString()
14764
- });
14765
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
14766
- err,
14767
- storyKey
14768
- }, "StateStore write failed after verification-failed"));
14769
- await writeStoryMetricsBestEffort(storyKey, "verification-failed", finalReviewCycles);
14770
- await persistState();
14771
- return;
14755
+ const outcome = await runVerificationAndComplete({
14756
+ recordedVerdict: verdict,
14757
+ finalReviewCycles,
14758
+ reviewResult,
14759
+ autoApprove: {
14760
+ issueCount: issueList.length,
14761
+ reason: `Review cycles exhausted (${finalReviewCycles}/${config.maxReviewCycles}) with only minor issues — auto-approving`
14772
14762
  }
14773
- }
14774
- eventBus.emit("story:auto-approved", {
14775
- storyKey,
14776
- verdict,
14777
- reviewCycles: finalReviewCycles,
14778
- maxReviewCycles: config.maxReviewCycles,
14779
- issueCount: issueList.length,
14780
- reason: `Review cycles exhausted (${finalReviewCycles}/${config.maxReviewCycles}) with only minor issues — auto-approving`
14781
- });
14782
- updateStory(storyKey, {
14783
- phase: "COMPLETE",
14784
- reviewCycles: finalReviewCycles,
14785
- completedAt: new Date().toISOString()
14786
14763
  });
14787
- if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
14788
- if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
14789
- storyKey,
14790
- category: "verification-result-missing"
14791
- }, "post-COMPLETE invariant: verification_result absent in manifest");
14792
- }).catch(() => {});
14793
- await writeStoryMetricsBestEffort(storyKey, verdict, finalReviewCycles);
14794
- await writeStoryOutcomeBestEffort(storyKey, "complete", finalReviewCycles);
14795
- eventBus.emit("orchestrator:story-complete", {
14796
- storyKey,
14797
- reviewCycles: finalReviewCycles
14798
- });
14799
- await persistState();
14764
+ if (outcome === "verification-failed") return;
14800
14765
  keepReviewing = false;
14801
14766
  return;
14802
14767
  }
@@ -14995,74 +14960,17 @@ function createImplementationOrchestrator(deps) {
14995
14960
  reviewCycles: finalReviewCycles,
14996
14961
  issueCount: issueList.length
14997
14962
  }, "Minor-fixes dispatch timed out — auto-approving as LGTM_WITH_NOTES (original findings retained as warnings)");
14998
- endPhase(storyKey, "code-review");
14999
- if (config.skipVerification !== true) {
15000
- const latestReviewSignals = reviewResult != null ? {
15001
- dispatchFailed: reviewResult.dispatchFailed,
15002
- error: reviewResult.error,
15003
- rawOutput: reviewResult.rawOutput
15004
- } : void 0;
15005
- let sourceEpicContent3;
15006
- const epicsPath3 = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
15007
- if (epicsPath3) try {
15008
- const epicFull3 = readFileSync(epicsPath3, "utf-8");
15009
- const section3 = extractStorySection(epicFull3, storyKey);
15010
- if (section3) sourceEpicContent3 = section3;
15011
- } catch {}
15012
- await persistDevStorySignals(storyKey, devStorySignals, runManifest);
15013
- const verifContext = assembleVerificationContext({
15014
- storyKey,
15015
- workingDir: projectRoot ?? process.cwd(),
15016
- reviewResult: latestReviewSignals,
15017
- storyContent: storyContentForVerification,
15018
- devStoryResult: devStorySignals,
15019
- outputTokenCount: devOutputTokenCount,
15020
- sourceEpicContent: sourceEpicContent3
15021
- });
15022
- const verifSummary = await verificationPipeline.run(verifContext, "A");
15023
- verificationStore.set(storyKey, verifSummary);
15024
- await persistVerificationResult(storyKey, verifSummary, runManifest);
15025
- if (verifSummary.status === "fail") {
15026
- updateStory(storyKey, {
15027
- phase: "VERIFICATION_FAILED",
15028
- completedAt: new Date().toISOString()
15029
- });
15030
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
15031
- err,
15032
- storyKey
15033
- }, "StateStore write failed after verification-failed"));
15034
- await writeStoryMetricsBestEffort(storyKey, "verification-failed", finalReviewCycles);
15035
- await persistState();
15036
- return;
14963
+ const outcome = await runVerificationAndComplete({
14964
+ recordedVerdict: downgradedVerdict,
14965
+ finalReviewCycles,
14966
+ reviewResult,
14967
+ autoApprove: {
14968
+ issueCount: issueList.length,
14969
+ reason: `Minor-fixes dispatch timed out (cycle ${finalReviewCycles}) auto-approving as LGTM_WITH_NOTES with original findings retained as warnings`,
14970
+ downgradeLastVerdict: downgradedVerdict
15037
14971
  }
15038
- }
15039
- eventBus.emit("story:auto-approved", {
15040
- storyKey,
15041
- verdict: downgradedVerdict,
15042
- reviewCycles: finalReviewCycles,
15043
- maxReviewCycles: config.maxReviewCycles,
15044
- issueCount: issueList.length,
15045
- reason: `Minor-fixes dispatch timed out (cycle ${finalReviewCycles}) — auto-approving as LGTM_WITH_NOTES with original findings retained as warnings`
15046
- });
15047
- updateStory(storyKey, {
15048
- phase: "COMPLETE",
15049
- reviewCycles: finalReviewCycles,
15050
- lastVerdict: downgradedVerdict,
15051
- completedAt: new Date().toISOString()
15052
14972
  });
15053
- if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
15054
- if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
15055
- storyKey,
15056
- category: "verification-result-missing"
15057
- }, "post-COMPLETE invariant: verification_result absent in manifest");
15058
- }).catch(() => {});
15059
- await writeStoryMetricsBestEffort(storyKey, downgradedVerdict, finalReviewCycles);
15060
- await writeStoryOutcomeBestEffort(storyKey, "complete", finalReviewCycles);
15061
- eventBus.emit("orchestrator:story-complete", {
15062
- storyKey,
15063
- reviewCycles: finalReviewCycles
15064
- });
15065
- await persistState();
14973
+ if (outcome === "verification-failed") return;
15066
14974
  keepReviewing = false;
15067
14975
  return;
15068
14976
  }
@@ -15327,6 +15235,33 @@ function createImplementationOrchestrator(deps) {
15327
15235
  storyKeys,
15328
15236
  pipelineRunId: config.pipelineRunId
15329
15237
  });
15238
+ {
15239
+ const cliMode = config.probeAuthorMode;
15240
+ let effectiveMode;
15241
+ let source;
15242
+ if (cliMode === "enabled" || cliMode === "disabled") {
15243
+ effectiveMode = cliMode;
15244
+ source = "cli";
15245
+ } else {
15246
+ const envValue = process.env.SUBSTRATE_PROBE_AUTHOR_ENABLED;
15247
+ if (envValue === "false" || envValue === "0") {
15248
+ effectiveMode = "disabled";
15249
+ source = "env";
15250
+ } else if (envValue === "true" || envValue === "1") {
15251
+ effectiveMode = "enabled";
15252
+ source = "env";
15253
+ } else {
15254
+ effectiveMode = "enabled";
15255
+ source = "default";
15256
+ }
15257
+ }
15258
+ _probeAuthorEffectiveMode = effectiveMode;
15259
+ eventBus.emit("probe-author:enabled", {
15260
+ runId: config.pipelineRunId ?? "",
15261
+ mode: effectiveMode,
15262
+ source
15263
+ });
15264
+ }
15330
15265
  await persistState();
15331
15266
  recordProgress();
15332
15267
  if (config.enableHeartbeat) startHeartbeat();
@@ -43831,7 +43766,18 @@ function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
43831
43766
  });
43832
43767
  }
43833
43768
  async function runRunAction(options) {
43834
- 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, skipVerification, epic: epicNumber, dryRun, maxReviewCycles = 2, engine, agent: agentId, registry: injectedRegistry, haltOn, costCeiling } = options;
43769
+ 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, skipVerification, epic: epicNumber, dryRun, maxReviewCycles = 2, engine, agent: agentId, registry: injectedRegistry, haltOn, costCeiling, probeAuthor } = options;
43770
+ const VALID_PROBE_AUTHOR_MODES = [
43771
+ "enabled",
43772
+ "disabled",
43773
+ "auto"
43774
+ ];
43775
+ if (probeAuthor !== void 0 && !VALID_PROBE_AUTHOR_MODES.includes(probeAuthor)) {
43776
+ const errorMsg = `Invalid --probe-author value '${probeAuthor}'. Valid values: enabled | disabled | auto`;
43777
+ if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, errorMsg) + "\n");
43778
+ else process.stderr.write(`Error: ${errorMsg}\n`);
43779
+ return 1;
43780
+ }
43835
43781
  const VALID_HALT_ON = [
43836
43782
  "all",
43837
43783
  "critical",
@@ -44026,6 +43972,7 @@ async function runRunAction(options) {
44026
43972
  meshUrl,
44027
43973
  meshProjectId
44028
43974
  } : {},
43975
+ ...probeAuthor !== void 0 ? { probeAuthor } : {},
44029
43976
  engineType: resolvedEngine,
44030
43977
  maxReviewCycles: effectiveMaxReviewCycles,
44031
43978
  retryBudget: configRetryBudget ?? 2,
@@ -44563,7 +44510,8 @@ async function runRunAction(options) {
44563
44510
  pipelineRunId: pipelineRun.id,
44564
44511
  enableHeartbeat: eventsFlag === true,
44565
44512
  skipPreflight: skipPreflight === true,
44566
- ...skipVerification === true ? { skipVerification: true } : {}
44513
+ ...skipVerification === true ? { skipVerification: true } : {},
44514
+ ...probeAuthor !== void 0 ? { probeAuthorMode: probeAuthor } : {}
44567
44515
  },
44568
44516
  projectRoot,
44569
44517
  tokenCeilings,
@@ -44694,7 +44642,7 @@ async function runRunAction(options) {
44694
44642
  }
44695
44643
  }
44696
44644
  async function runFullPipeline(options) {
44697
- const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, skipVerification, maxReviewCycles = 2, retryBudget, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort, agentId, meshUrl: fpMeshUrl, meshProjectId: fpMeshProjectId, engineType: fpEngineType } = options;
44645
+ const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, skipVerification, maxReviewCycles = 2, retryBudget, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort, agentId, meshUrl: fpMeshUrl, meshProjectId: fpMeshProjectId, engineType: fpEngineType, probeAuthor } = options;
44698
44646
  if (!existsSync$1(dbDir)) mkdirSync$1(dbDir, { recursive: true });
44699
44647
  let doltServerFull = null;
44700
44648
  try {
@@ -44995,7 +44943,8 @@ async function runFullPipeline(options) {
44995
44943
  retryBudget: retryBudget ?? 2,
44996
44944
  pipelineRunId: runId,
44997
44945
  skipPreflight: skipPreflight === true,
44998
- ...skipVerification === true ? { skipVerification: true } : {}
44946
+ ...skipVerification === true ? { skipVerification: true } : {},
44947
+ ...probeAuthor !== void 0 ? { probeAuthorMode: probeAuthor } : {}
44999
44948
  },
45000
44949
  projectRoot,
45001
44950
  tokenCeilings,
@@ -45151,7 +45100,7 @@ async function runFullPipeline(options) {
45151
45100
  }
45152
45101
  }
45153
45102
  function registerRunCommand(program, _version = "0.0.0", projectRoot = process.cwd(), registry) {
45154
- 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("--skip-verification", "Skip the post-dispatch verification pipeline (Story 51-5)").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)").option("--engine <type>", "Execution engine: linear (default) or graph").option("--agent <id>", "Agent backend: claude-code (default), codex, or gemini").option("--halt-on <severity>", "Halt pipeline on escalation severity: all | critical | none (default: none)", "none").option("--cost-ceiling <amount>", "Maximum cost ceiling in USD (positive number); halts pipeline when exceeded", parseFloat).action(async (opts) => {
45103
+ 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("--skip-verification", "Skip the post-dispatch verification pipeline (Story 51-5)").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)").option("--engine <type>", "Execution engine: linear (default) or graph").option("--agent <id>", "Agent backend: claude-code (default), codex, or gemini").option("--halt-on <severity>", "Halt pipeline on escalation severity: all | critical | none (default: none)", "none").option("--cost-ceiling <amount>", "Maximum cost ceiling in USD (positive number); halts pipeline when exceeded", parseFloat).option("--probe-author <mode>", "probe-author phase mode: enabled | disabled | auto (default: auto = SUBSTRATE_PROBE_AUTHOR_ENABLED env, default true) (Story 60-14)", "auto").action(async (opts) => {
45155
45104
  if (opts.helpAgent) {
45156
45105
  process.exitCode = await runHelpAgent();
45157
45106
  return;
@@ -45193,7 +45142,8 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
45193
45142
  agent: opts.agent,
45194
45143
  registry,
45195
45144
  haltOn: opts.haltOn,
45196
- costCeiling: opts.costCeiling
45145
+ costCeiling: opts.costCeiling,
45146
+ probeAuthor: opts.probeAuthor
45197
45147
  });
45198
45148
  process.exitCode = exitCode;
45199
45149
  });
@@ -45201,4 +45151,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
45201
45151
 
45202
45152
  //#endregion
45203
45153
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict, wireNdjsonEmitter };
45204
- //# sourceMappingURL=run-BQxm1Qix.js.map
45154
+ //# sourceMappingURL=run-YBY2vrF4.js.map
@@ -1,8 +1,8 @@
1
- import "./health-CnV6ndAb.js";
1
+ import "./health-BAcRfZ4s.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
4
  import "./dist-BnMsd9hC.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-BQxm1Qix.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-YBY2vrF4.js";
6
6
  import "./routing-CcBOCuC9.js";
7
7
  import "./decisions-C0pz9Clx.js";
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.34",
3
+ "version": "0.20.36",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",