substrate-ai 0.20.6 → 0.20.8

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.
@@ -0,0 +1,4 @@
1
+ import { AdapterRegistry } from "./dist-CqtWS9wF.js";
2
+ import "./adapter-registry-DXLMTmfD.js";
3
+
4
+ export { AdapterRegistry };
package/dist/cli/index.js CHANGED
@@ -1,15 +1,15 @@
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-BIS34IYK.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, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts } from "../health-DXW-E2vb.js";
3
3
  import { createLogger } from "../logger-KeHncl-f.js";
4
4
  import { createEventBus } from "../helpers-CElYrONe.js";
5
- import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, GlobalSettingsSchema, 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-srr3BfCc.js";
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-CqtWS9wF.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-BAc1zfMQ.js";
8
- import "../errors-CSTQNabo.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-Bz3dW9Wn.js";
8
+ import "../errors-1uLGqnvr.js";
9
9
  import "../routing-CcBOCuC9.js";
10
10
  import "../decisions-C0pz9Clx.js";
11
11
  import "../version-manager-impl-BmOWu8ml.js";
12
- import { registerUpgradeCommand } from "../upgrade-iTr8nbbE.js";
12
+ import { registerUpgradeCommand } from "../upgrade-k15NGTno.js";
13
13
  import { Command } from "commander";
14
14
  import { fileURLToPath } from "url";
15
15
  import { dirname, join, resolve } from "path";
@@ -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-3-qy8XEI.js");
3670
+ const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-Q8-69N9P.js");
3671
3671
  const substrateDirPath = join(projectRoot, ".substrate");
3672
3672
  const processInfo = inspectProcessTree$1({
3673
3673
  projectRoot,
@@ -4615,7 +4615,7 @@ function defaultSupervisorDeps() {
4615
4615
  if (cached === null) {
4616
4616
  const { AdapterRegistry: AR } = await import(
4617
4617
  /* @vite-ignore */
4618
- "../adapter-registry-CwjKI1sO.js"
4618
+ "../adapter-registry-N0Klnk7Y.js"
4619
4619
  );
4620
4620
  cached = new AR();
4621
4621
  await cached.discoverAndRegister();
@@ -5182,11 +5182,11 @@ async function runSupervisorAction(options, deps = {}) {
5182
5182
  try {
5183
5183
  const { createExperimenter } = await import(
5184
5184
  /* @vite-ignore */
5185
- "../experimenter-DaXUHfJO.js"
5185
+ "../experimenter-VEJHtfLh.js"
5186
5186
  );
5187
5187
  const { getLatestRun: getLatest } = await import(
5188
5188
  /* @vite-ignore */
5189
- "../decisions-Ca77UwMA.js"
5189
+ "../decisions-7UJcRETq.js"
5190
5190
  );
5191
5191
  const expAdapter = createDatabaseAdapter({
5192
5192
  backend: "auto",
@@ -5196,7 +5196,7 @@ async function runSupervisorAction(options, deps = {}) {
5196
5196
  await initSchema(expAdapter);
5197
5197
  const { runRunAction: runPipeline } = await import(
5198
5198
  /* @vite-ignore */
5199
- "../run-Dif8PJRd.js"
5199
+ "../run-C3kaptjF.js"
5200
5200
  );
5201
5201
  const runStoryFn = async (opts) => {
5202
5202
  const exitCode = await runPipeline({
@@ -5728,7 +5728,7 @@ async function runMetricsAction(options) {
5728
5728
  const routingConfigPath = join(dbDir, "routing.yml");
5729
5729
  let routingConfig = null;
5730
5730
  if (existsSync$1(routingConfigPath)) try {
5731
- const { loadModelRoutingConfig } = await import("../routing-BX6ObE8S.js");
5731
+ const { loadModelRoutingConfig } = await import("../routing-Ccpb_syA.js");
5732
5732
  routingConfig = loadModelRoutingConfig(routingConfigPath);
5733
5733
  } catch {}
5734
5734
  if (routingConfig === null) routingConfig = {
@@ -8995,8 +8995,8 @@ async function createProgram() {
8995
8995
  /** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
8996
8996
  function checkForUpdatesInBackground(currentVersion) {
8997
8997
  if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
8998
- import("../upgrade-Cm8B3cXL.js").then(async () => {
8999
- const { createVersionManager } = await import("../version-manager-impl-XiJHzIbR.js");
8998
+ import("../upgrade-CVaD7iUR.js").then(async () => {
8999
+ const { createVersionManager } = await import("../version-manager-impl-CEiZEsmi.js");
9000
9000
  const vm = createVersionManager();
9001
9001
  const result = await vm.checkForUpdates();
9002
9002
  if (result.updateAvailable) {
@@ -1,4 +1,4 @@
1
- import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-srr3BfCc.js";
1
+ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-CqtWS9wF.js";
2
2
  import "./decisions-C0pz9Clx.js";
3
3
 
4
4
  export { getLatestRun };
@@ -4044,15 +4044,27 @@ async function aggregateTokenUsageForStory(adapter, runId, storyKey) {
4044
4044
  //#endregion
4045
4045
  //#region packages/core/dist/persistence/queries/retry-escalated.js
4046
4046
  /**
4047
+ * Pipeline-run statuses that make escalation-diagnosis decisions non-actionable.
4048
+ * Runs in these states are terminated (abandoned / stopped manually) and their
4049
+ * per-story escalations are historical noise — the work either shipped in a
4050
+ * later run or was never going to be retried in this run's lifetime.
4051
+ */
4052
+ const TERMINAL_RUN_STATUSES = ["failed", "stopped"];
4053
+ /**
4047
4054
  * Query the decision store for escalation-diagnosis decisions and classify
4048
4055
  * each story key as retryable or skipped.
4049
4056
  *
4050
4057
  * Key format in the DB: `{storyKey}:{runId}`
4051
4058
  *
4059
+ * Scoping:
4052
4060
  * - When `runId` is provided, only decisions whose key contains that runId
4053
- * are considered (AC5 scoping).
4054
- * - When `runId` is omitted, the runId of the last (most recently created)
4055
- * escalation-diagnosis decision is used as the default (AC1 defaulting).
4061
+ * are considered (AC5). The caller is explicit; no status filter is applied
4062
+ * so a user can still inspect diagnoses from a terminal run by naming it.
4063
+ * - When `runId` is omitted, the latest run whose `pipeline_runs.status` is
4064
+ * NOT terminal (`failed` / `stopped`) is used. Terminal runs are abandoned
4065
+ * or manually stopped — their per-story diagnoses are historical noise and
4066
+ * would generate false-positive retry proposals for work that either
4067
+ * shipped in a later run or will never be retried in that run's lifetime.
4056
4068
  *
4057
4069
  * @param adapter The database adapter
4058
4070
  * @param runId Optional run ID to scope the query
@@ -4083,7 +4095,13 @@ async function getRetryableEscalations(adapter, runId) {
4083
4095
  });
4084
4096
  }
4085
4097
  if (parsed.length === 0) return result;
4086
- const effectiveRunId = runId ?? parsed[parsed.length - 1].decisionRunId;
4098
+ let effectiveRunId;
4099
+ if (runId !== void 0) effectiveRunId = runId;
4100
+ else {
4101
+ const candidateRunId = await pickLatestNonTerminalRunId(adapter, parsed);
4102
+ if (candidateRunId === void 0) return result;
4103
+ effectiveRunId = candidateRunId;
4104
+ }
4087
4105
  const lastEntryByKey = new Map();
4088
4106
  for (const entry of parsed) {
4089
4107
  if (entry.decisionRunId !== effectiveRunId) continue;
@@ -4103,6 +4121,34 @@ async function getRetryableEscalations(adapter, runId) {
4103
4121
  }
4104
4122
  return result;
4105
4123
  }
4124
+ /**
4125
+ * Walk the parsed decision list newest-last (as supplied), map distinct runIds
4126
+ * to their pipeline-run status, and return the runId of the newest decision
4127
+ * whose run is NOT in a terminal status.
4128
+ *
4129
+ * Returns `undefined` when every referenced run is terminal or missing —
4130
+ * signalling "nothing retryable" to the caller.
4131
+ *
4132
+ * The adapter query is a single SELECT against `pipeline_runs` restricted to
4133
+ * the distinct runIds we actually care about; keeps the cost O(unique-runs)
4134
+ * rather than O(decisions).
4135
+ */
4136
+ async function pickLatestNonTerminalRunId(adapter, parsed) {
4137
+ const uniqueRunIds = Array.from(new Set(parsed.map((p) => p.decisionRunId)));
4138
+ if (uniqueRunIds.length === 0) return void 0;
4139
+ const statusByRunId = new Map();
4140
+ for (const id of uniqueRunIds) {
4141
+ const rows = await adapter.query("SELECT id, status FROM pipeline_runs WHERE id = ?", [id]);
4142
+ if (rows.length > 0 && rows[0]) statusByRunId.set(rows[0].id, rows[0].status);
4143
+ }
4144
+ for (let i = parsed.length - 1; i >= 0; i -= 1) {
4145
+ const entry = parsed[i];
4146
+ const status = statusByRunId.get(entry.decisionRunId);
4147
+ if (status !== void 0 && TERMINAL_RUN_STATUSES.includes(status)) continue;
4148
+ return entry.decisionRunId;
4149
+ }
4150
+ return void 0;
4151
+ }
4106
4152
 
4107
4153
  //#endregion
4108
4154
  //#region packages/core/dist/persistence/monitor-database.js
@@ -10894,4 +10940,4 @@ async function callLLM(params) {
10894
10940
 
10895
10941
  //#endregion
10896
10942
  export { ADVISORY_NOTES, AdapterRegistry, AdtError, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, Categorizer, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, ConsumerAnalyzer, CostTrackerConfigSchema, DEFAULT_CONFIG, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, DoltNotInstalled, DoltQueryError, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, GeminiCLIAdapter, GlobalSettingsSchema, IngestionServer, LEARNING_FINDING, LogTurnAnalyzer, ModelRoutingConfigSchema, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProviderPolicySchema, ProvidersSchema, Recommender, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TASK_TYPE_PHASE_MAP, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryConfigSchema, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, VersionManagerImpl, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, callLLM, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDatabaseAdapter as createDatabaseAdapter$1, createDecision, createDoltClient, createExperimenter, createPipelineRun, createRequirement, createVersionManager, detectInterfaceChanges, determineVerdict, getActiveDecisions, getAllCostEntriesFiltered, getArtifactByTypeForRun, getArtifactsByRun, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getModelTier, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadModelRoutingConfig, loadParentRunDecisions, registerArtifact, resolvePromptFile, supersedeDecision, tagRunAsBaseline, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics };
10897
- //# sourceMappingURL=dist-srr3BfCc.js.map
10943
+ //# sourceMappingURL=dist-CqtWS9wF.js.map
@@ -1,4 +1,4 @@
1
- import { AdtError } from "./dist-srr3BfCc.js";
1
+ import { AdtError } from "./dist-CqtWS9wF.js";
2
2
 
3
3
  //#region src/core/errors.ts
4
4
  /** Error thrown when task configuration is invalid */
@@ -71,4 +71,4 @@ var TaskGraphIncompatibleFormatError = class extends AdtError {
71
71
 
72
72
  //#endregion
73
73
  export { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError };
74
- //# sourceMappingURL=errors-CSTQNabo.js.map
74
+ //# sourceMappingURL=errors-1uLGqnvr.js.map
@@ -1,3 +1,3 @@
1
- import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-srr3BfCc.js";
1
+ import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-CqtWS9wF.js";
2
2
 
3
3
  export { createExperimenter };
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { DoltClient, DoltQueryError, LEARNING_FINDING, createDatabaseAdapter$1 as createDatabaseAdapter, createDecision, getDecisionsByCategory, getLatestRun, getPipelineRunById, initSchema } from "./dist-srr3BfCc.js";
2
+ import { DoltClient, DoltQueryError, LEARNING_FINDING, createDatabaseAdapter$1 as createDatabaseAdapter, createDecision, getDecisionsByCategory, getLatestRun, getPipelineRunById, initSchema } from "./dist-CqtWS9wF.js";
3
3
  import { createRequire } from "module";
4
4
  import { dirname, join } from "path";
5
5
  import { readFile } from "fs/promises";
@@ -5286,4 +5286,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
5286
5286
 
5287
5287
  //#endregion
5288
5288
  export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, 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, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, runHealthAction, validateStoryKey };
5289
- //# sourceMappingURL=health-BIS34IYK.js.map
5289
+ //# sourceMappingURL=health-DXW-E2vb.js.map
@@ -1,6 +1,6 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-BIS34IYK.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-DXW-E2vb.js";
2
2
  import "./logger-KeHncl-f.js";
3
- import "./dist-srr3BfCc.js";
3
+ import "./dist-CqtWS9wF.js";
4
4
  import "./decisions-C0pz9Clx.js";
5
5
 
6
6
  export { inspectProcessTree };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { childLogger, createLogger, logger } from "./logger-KeHncl-f.js";
2
2
  import { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-CElYrONe.js";
3
- import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-srr3BfCc.js";
3
+ import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-CqtWS9wF.js";
4
4
  import "./adapter-registry-DXLMTmfD.js";
5
- import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-CSTQNabo.js";
5
+ import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-1uLGqnvr.js";
6
6
 
7
7
  //#region src/core/di.ts
8
8
  /**
@@ -1,4 +1,4 @@
1
- import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-srr3BfCc.js";
1
+ import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-CqtWS9wF.js";
2
2
  import "./routing-CcBOCuC9.js";
3
3
 
4
4
  export { loadModelRoutingConfig };
@@ -1,7 +1,7 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-BIS34IYK.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-DXW-E2vb.js";
2
2
  import { createLogger } from "./logger-KeHncl-f.js";
3
3
  import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
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-srr3BfCc.js";
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-CqtWS9wF.js";
5
5
  import { basename, dirname, extname, join } from "path";
6
6
  import { access, readFile, readdir, stat } from "fs/promises";
7
7
  import { EventEmitter } from "node:events";
@@ -43840,4 +43840,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
43840
43840
 
43841
43841
  //#endregion
43842
43842
  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 };
43843
- //# sourceMappingURL=run-BAc1zfMQ.js.map
43843
+ //# sourceMappingURL=run-Bz3dW9Wn.js.map
@@ -1,8 +1,8 @@
1
- import "./health-BIS34IYK.js";
1
+ import "./health-DXW-E2vb.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
- import "./dist-srr3BfCc.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-BAc1zfMQ.js";
4
+ import "./dist-CqtWS9wF.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-Bz3dW9Wn.js";
6
6
  import "./routing-CcBOCuC9.js";
7
7
  import "./decisions-C0pz9Clx.js";
8
8
 
@@ -1,5 +1,5 @@
1
- import "./dist-srr3BfCc.js";
1
+ import "./dist-CqtWS9wF.js";
2
2
  import "./version-manager-impl-BmOWu8ml.js";
3
- import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-iTr8nbbE.js";
3
+ import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-k15NGTno.js";
4
4
 
5
5
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
@@ -1,4 +1,4 @@
1
- import { createVersionManager } from "./dist-srr3BfCc.js";
1
+ import { createVersionManager } from "./dist-CqtWS9wF.js";
2
2
  import { execSync, spawn } from "child_process";
3
3
  import * as readline from "readline";
4
4
 
@@ -123,4 +123,4 @@ function registerUpgradeCommand(program) {
123
123
 
124
124
  //#endregion
125
125
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
126
- //# sourceMappingURL=upgrade-iTr8nbbE.js.map
126
+ //# sourceMappingURL=upgrade-k15NGTno.js.map
@@ -1,4 +1,4 @@
1
- import { VersionManagerImpl, createVersionManager } from "./dist-srr3BfCc.js";
1
+ import { VersionManagerImpl, createVersionManager } from "./dist-CqtWS9wF.js";
2
2
  import "./version-manager-impl-BmOWu8ml.js";
3
3
 
4
4
  export { createVersionManager };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.6",
3
+ "version": "0.20.8",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -64,6 +64,96 @@ Use this exact format for each item:
64
64
  - The transport annotation `(queue: ...)` or `(api: ...)` or `(from story X-Y)` is optional but recommended when applicable
65
65
  - **The `## Interface Contracts` section is optional** — omit it entirely if the story has no cross-story schema dependencies
66
66
 
67
+ ## Runtime Verification Guidance
68
+
69
+ **Decide whether this story's artifact is runtime-dependent.** An artifact is runtime-dependent if correctness depends on execution — systemd units, container definitions (Podman Quadlet, Docker Compose), install scripts, migration runners, anything whose behavior is only observable by running it against a real host or ephemeral sandbox.
70
+
71
+ If the artifact is runtime-dependent, add a `## Runtime Probes` section to the story file. Each probe is a short shell command whose exit status answers "does this artifact actually work?".
72
+
73
+ **If the artifact is NOT runtime-dependent — TypeScript/JavaScript code + tests, type-only refactors, documentation, build or tsconfig edits — omit the `## Runtime Probes` section entirely.** Adding one for a static-output story produces a `pass` (skip) with no benefit. The default substrate self-development case (source code + tests) has no probes.
74
+
75
+ ### Probe YAML shape
76
+
77
+ Declare probes as a YAML list inside a single fenced `yaml` block directly under the `## Runtime Probes` heading. Each entry has this shape:
78
+
79
+ ```text
80
+ - name: <hyphen-separated-identifier> # required; unique within story
81
+ sandbox: host | twin # required; one of host | twin
82
+ command: <shell command line(s)> # required
83
+ timeout_ms: 60000 # optional; defaults to 60000
84
+ description: <optional context> # optional
85
+ ```
86
+
87
+ Required fields: `name`, `sandbox`, `command`. `timeout_ms` and `description` are optional. Probe names must be unique within one story.
88
+
89
+ ### Sandbox choice
90
+
91
+ - **`sandbox: twin`** — default for probes that mutate host state: starting services, binding ports, writing outside the project working directory, running privileged commands. Safer; ephemeral.
92
+ - **`sandbox: host`** — only when the probe is strictly read-only from the host's perspective (linting a file, parsing config, asserting a command exists, pulling an image into a local cache) OR when the host context itself is what the story needs to verify.
93
+ - **When in doubt, pick `twin`.**
94
+
95
+ ### Probe granularity
96
+
97
+ For stories with multiple runtime concerns (install + start + connect), declare **separate named probes per concern** rather than one monolithic probe. Finding messages reference probe names; granular probes produce actionable failures and let retries focus on the specific failure.
98
+
99
+ Probe names are hyphen-separated identifiers, not sentences: `dolt-image-pullable`, not `verify that the dolt image can be pulled`.
100
+
101
+ ### Examples by artifact class
102
+
103
+ **Systemd unit:**
104
+
105
+ ```yaml
106
+ - name: unit-is-active
107
+ sandbox: twin
108
+ command: systemctl is-active my-service.service
109
+ description: unit started and has not crashed
110
+ ```
111
+
112
+ **Container / Podman Quadlet** (catches the wrong-image-path class — strata Story 1-4):
113
+
114
+ ```yaml
115
+ - name: dolt-image-pullable
116
+ sandbox: host
117
+ command: podman pull ghcr.io/dolthub/dolt-sql-server:latest
118
+ description: image reference resolves and is pullable
119
+ ```
120
+
121
+ **Install script:**
122
+
123
+ ```yaml
124
+ - name: installer-exits-clean
125
+ sandbox: twin
126
+ command: bash ./install.sh --dry-run
127
+ - name: installed-binary-reports-version
128
+ sandbox: twin
129
+ command: /usr/local/bin/my-tool --version
130
+ ```
131
+
132
+ **Database migration:**
133
+
134
+ ```yaml
135
+ - name: migration-applies-cleanly
136
+ sandbox: twin
137
+ command: npm run migrate:up && npm run migrate:status
138
+ description: migration applies and schema_migrations reports the new version
139
+ ```
140
+
141
+ **Docker Compose:**
142
+
143
+ ```yaml
144
+ - name: compose-parses
145
+ sandbox: host
146
+ command: docker compose -f ./compose.yaml config --quiet
147
+ description: compose file is syntactically valid
148
+ - name: compose-service-starts
149
+ sandbox: twin
150
+ command: docker compose -f ./compose.yaml up -d api && docker compose -f ./compose.yaml ps api | grep -q running
151
+ ```
152
+
153
+ ### Framing
154
+
155
+ Treat the probes you draft as a **first pass** the human author will refine. Probes execute on a real host (or — for `sandbox: twin` — a real ephemeral sandbox), so command correctness matters. Prefer conservative commands that exit 0 only on true success and non-zero on any real failure.
156
+
67
157
  ## Scope Cap Guidance
68
158
 
69
159
  **Aim for 6-7 acceptance criteria and 7-8 tasks per story.**
@@ -1,4 +0,0 @@
1
- import { AdapterRegistry } from "./dist-srr3BfCc.js";
2
- import "./adapter-registry-DXLMTmfD.js";
3
-
4
- export { AdapterRegistry };