substrate-ai 0.20.35 → 0.20.37

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-B7O3HgSR.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-VgLqFM7X.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 {
@@ -15234,6 +15235,33 @@ function createImplementationOrchestrator(deps) {
15234
15235
  storyKeys,
15235
15236
  pipelineRunId: config.pipelineRunId
15236
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
+ }
15237
15265
  await persistState();
15238
15266
  recordProgress();
15239
15267
  if (config.enableHeartbeat) startHeartbeat();
@@ -43738,7 +43766,18 @@ function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
43738
43766
  });
43739
43767
  }
43740
43768
  async function runRunAction(options) {
43741
- 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
+ }
43742
43781
  const VALID_HALT_ON = [
43743
43782
  "all",
43744
43783
  "critical",
@@ -43933,6 +43972,7 @@ async function runRunAction(options) {
43933
43972
  meshUrl,
43934
43973
  meshProjectId
43935
43974
  } : {},
43975
+ ...probeAuthor !== void 0 ? { probeAuthor } : {},
43936
43976
  engineType: resolvedEngine,
43937
43977
  maxReviewCycles: effectiveMaxReviewCycles,
43938
43978
  retryBudget: configRetryBudget ?? 2,
@@ -44470,7 +44510,8 @@ async function runRunAction(options) {
44470
44510
  pipelineRunId: pipelineRun.id,
44471
44511
  enableHeartbeat: eventsFlag === true,
44472
44512
  skipPreflight: skipPreflight === true,
44473
- ...skipVerification === true ? { skipVerification: true } : {}
44513
+ ...skipVerification === true ? { skipVerification: true } : {},
44514
+ ...probeAuthor !== void 0 ? { probeAuthorMode: probeAuthor } : {}
44474
44515
  },
44475
44516
  projectRoot,
44476
44517
  tokenCeilings,
@@ -44601,7 +44642,7 @@ async function runRunAction(options) {
44601
44642
  }
44602
44643
  }
44603
44644
  async function runFullPipeline(options) {
44604
- 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;
44605
44646
  if (!existsSync$1(dbDir)) mkdirSync$1(dbDir, { recursive: true });
44606
44647
  let doltServerFull = null;
44607
44648
  try {
@@ -44902,7 +44943,8 @@ async function runFullPipeline(options) {
44902
44943
  retryBudget: retryBudget ?? 2,
44903
44944
  pipelineRunId: runId,
44904
44945
  skipPreflight: skipPreflight === true,
44905
- ...skipVerification === true ? { skipVerification: true } : {}
44946
+ ...skipVerification === true ? { skipVerification: true } : {},
44947
+ ...probeAuthor !== void 0 ? { probeAuthorMode: probeAuthor } : {}
44906
44948
  },
44907
44949
  projectRoot,
44908
44950
  tokenCeilings,
@@ -45058,7 +45100,7 @@ async function runFullPipeline(options) {
45058
45100
  }
45059
45101
  }
45060
45102
  function registerRunCommand(program, _version = "0.0.0", projectRoot = process.cwd(), registry) {
45061
- 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) => {
45062
45104
  if (opts.helpAgent) {
45063
45105
  process.exitCode = await runHelpAgent();
45064
45106
  return;
@@ -45100,7 +45142,8 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
45100
45142
  agent: opts.agent,
45101
45143
  registry,
45102
45144
  haltOn: opts.haltOn,
45103
- costCeiling: opts.costCeiling
45145
+ costCeiling: opts.costCeiling,
45146
+ probeAuthor: opts.probeAuthor
45104
45147
  });
45105
45148
  process.exitCode = exitCode;
45106
45149
  });
@@ -45108,4 +45151,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
45108
45151
 
45109
45152
  //#endregion
45110
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 };
45111
- //# sourceMappingURL=run-B7O3HgSR.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-B7O3HgSR.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.35",
3
+ "version": "0.20.37",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",