substrate-ai 0.19.18 → 0.19.20

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-CtFYOaeA.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, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-D8V9_Pn7.js";
2
+ import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-CkQncTB5.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, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-RlHA9HPJ.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, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-CtFYOaeA.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-tWQlCR2A.js";
8
- import "../errors-C3Z7RYu9.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-MGg8SzDA.js";
8
+ import "../errors-CWSATPPa.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-2LJZtYUC.js";
12
+ import { registerUpgradeCommand } from "../upgrade-UCMt4b7A.js";
13
13
  import { Command } from "commander";
14
14
  import { fileURLToPath } from "url";
15
15
  import { dirname, join, resolve } from "path";
@@ -3215,7 +3215,7 @@ async function runStatusAction(options) {
3215
3215
  if (run === void 0) run = await getLatestRun(adapter);
3216
3216
  }
3217
3217
  if (run === void 0) {
3218
- const { inspectProcessTree } = await import("../health-BfwizUAY.js");
3218
+ const { inspectProcessTree } = await import("../health-DlKuVhQH.js");
3219
3219
  const substrateDirPath = join(projectRoot, ".substrate");
3220
3220
  const processInfo = inspectProcessTree({
3221
3221
  projectRoot,
@@ -4102,7 +4102,7 @@ function defaultSupervisorDeps() {
4102
4102
  if (cached === null) {
4103
4103
  const { AdapterRegistry: AR } = await import(
4104
4104
  /* @vite-ignore */
4105
- "../adapter-registry-DcoerWf8.js"
4105
+ "../adapter-registry-BDvUQgG3.js"
4106
4106
  );
4107
4107
  cached = new AR();
4108
4108
  await cached.discoverAndRegister();
@@ -4544,11 +4544,11 @@ async function runSupervisorAction(options, deps = {}) {
4544
4544
  try {
4545
4545
  const { createExperimenter } = await import(
4546
4546
  /* @vite-ignore */
4547
- "../experimenter-k8BhW6rB.js"
4547
+ "../experimenter-ChKZzonq.js"
4548
4548
  );
4549
4549
  const { getLatestRun: getLatest } = await import(
4550
4550
  /* @vite-ignore */
4551
- "../decisions-DG-DLD3C.js"
4551
+ "../decisions-BEAzpqOy.js"
4552
4552
  );
4553
4553
  const expAdapter = createDatabaseAdapter({
4554
4554
  backend: "auto",
@@ -4558,7 +4558,7 @@ async function runSupervisorAction(options, deps = {}) {
4558
4558
  await initSchema(expAdapter);
4559
4559
  const { runRunAction: runPipeline } = await import(
4560
4560
  /* @vite-ignore */
4561
- "../run-C3F7ylXg.js"
4561
+ "../run-DVwQH8Ea.js"
4562
4562
  );
4563
4563
  const runStoryFn = async (opts) => {
4564
4564
  const exitCode = await runPipeline({
@@ -5088,7 +5088,7 @@ async function runMetricsAction(options) {
5088
5088
  const routingConfigPath = join(dbDir, "routing.yml");
5089
5089
  let routingConfig = null;
5090
5090
  if (existsSync$1(routingConfigPath)) try {
5091
- const { loadModelRoutingConfig } = await import("../routing-CyuCd4j4.js");
5091
+ const { loadModelRoutingConfig } = await import("../routing-DXoZWjBO.js");
5092
5092
  routingConfig = loadModelRoutingConfig(routingConfigPath);
5093
5093
  } catch {}
5094
5094
  if (routingConfig === null) routingConfig = {
@@ -7279,7 +7279,7 @@ async function runRetryEscalatedAction(options) {
7279
7279
  projectRoot,
7280
7280
  agentId
7281
7281
  });
7282
- const ndjsonEmitter = eventsFlag === true ? createEventEmitter() : void 0;
7282
+ const ndjsonEmitter = eventsFlag === true ? createEventEmitter(process.stdout) : void 0;
7283
7283
  if (ndjsonEmitter !== void 0) {
7284
7284
  ndjsonEmitter.emit({
7285
7285
  type: "pipeline:start",
@@ -7338,11 +7338,14 @@ async function runRetryEscalatedAction(options) {
7338
7338
  key: payload.storyKey,
7339
7339
  reason: payload.lastVerdict,
7340
7340
  cycles: payload.reviewCycles,
7341
- issues: payload.issues.map((i) => ({
7342
- severity: i.severity ?? "unknown",
7343
- file: i.file ?? "",
7344
- desc: i.description ?? ""
7345
- })),
7341
+ issues: payload.issues.map((i) => {
7342
+ const iss = i;
7343
+ return {
7344
+ severity: iss.severity ?? "unknown",
7345
+ file: iss.file ?? "",
7346
+ desc: iss.description ?? ""
7347
+ };
7348
+ }),
7346
7349
  ...payload.diagnosis !== void 0 ? { diagnosis: payload.diagnosis } : {}
7347
7350
  });
7348
7351
  });
@@ -8245,8 +8248,8 @@ async function createProgram() {
8245
8248
  /** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
8246
8249
  function checkForUpdatesInBackground(currentVersion) {
8247
8250
  if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
8248
- import("../upgrade-BsF4sxEE.js").then(async () => {
8249
- const { createVersionManager } = await import("../version-manager-impl-tcnWjYl8.js");
8251
+ import("../upgrade-D_od33Mu.js").then(async () => {
8252
+ const { createVersionManager } = await import("../version-manager-impl-DA5apVDT.js");
8250
8253
  const vm = createVersionManager();
8251
8254
  const result = await vm.checkForUpdates();
8252
8255
  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-RlHA9HPJ.js";
1
+ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-CtFYOaeA.js";
2
2
  import "./decisions-C0pz9Clx.js";
3
3
 
4
4
  export { getLatestRun };
@@ -480,16 +480,20 @@ function estimateOutputQuality(output) {
480
480
  if (matches) fileModificationMentions += matches.length;
481
481
  }
482
482
  const mentionsErrors = ERROR_PATTERNS.some((p) => p.test(output));
483
- let score = 50;
483
+ const hasYamlBlock = /```yaml[\s\S]*?```/.test(output) || /^result:\s/m.test(output);
484
+ const mentionsCompletion = /(?:all tasks? (?:complete|done|finished)|implementation complete|AC\d? met|story complete)/i.test(output);
485
+ let score = 30;
486
+ if (hasYamlBlock) score += 20;
484
487
  if (mentionsTestExecution) score += 10;
485
488
  if (mentionsTestPass) score += 15;
486
- if (fileModificationMentions > 0) score += Math.min(15, fileModificationMentions * 5);
487
- if (output.length > 1e3) score += 5;
489
+ if (mentionsCompletion) score += 10;
490
+ if (fileModificationMentions > 0) score += Math.min(10, fileModificationMentions * 3);
488
491
  if (output.length > 5e3) score += 5;
489
- score -= hedgingPhrases.length * 10;
490
- if (mentionsTestFailure) score -= 10;
492
+ score -= hedgingPhrases.length * 15;
493
+ if (mentionsTestFailure) score -= 15;
491
494
  if (mentionsErrors) score -= 10;
492
- if (output.length < 200) score -= 15;
495
+ if (output.length < 200) score -= 20;
496
+ if (!hasYamlBlock && output.length > 1e3) score -= 10;
493
497
  score = Math.max(0, Math.min(100, score));
494
498
  return {
495
499
  hedgingCount: hedgingPhrases.length,
@@ -10438,4 +10442,4 @@ async function callLLM(params) {
10438
10442
 
10439
10443
  //#endregion
10440
10444
  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, 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 };
10441
- //# sourceMappingURL=dist-RlHA9HPJ.js.map
10445
+ //# sourceMappingURL=dist-CtFYOaeA.js.map
@@ -1,4 +1,4 @@
1
- import { AdtError } from "./dist-RlHA9HPJ.js";
1
+ import { AdtError } from "./dist-CtFYOaeA.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-C3Z7RYu9.js.map
74
+ //# sourceMappingURL=errors-CWSATPPa.js.map
@@ -1,3 +1,3 @@
1
- import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-RlHA9HPJ.js";
1
+ import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-CtFYOaeA.js";
2
2
 
3
3
  export { createExperimenter };
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-RlHA9HPJ.js";
2
+ import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-CtFYOaeA.js";
3
3
  import { createRequire } from "module";
4
4
  import { dirname, join } from "path";
5
5
  import { existsSync, readFileSync } from "node:fs";
@@ -1930,4 +1930,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
1930
1930
 
1931
1931
  //#endregion
1932
1932
  export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createStateStore, detectCycles, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runHealthAction, validateStoryKey };
1933
- //# sourceMappingURL=health-D8V9_Pn7.js.map
1933
+ //# sourceMappingURL=health-CkQncTB5.js.map
@@ -1,6 +1,6 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-D8V9_Pn7.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-CkQncTB5.js";
2
2
  import "./logger-KeHncl-f.js";
3
- import "./dist-RlHA9HPJ.js";
3
+ import "./dist-CtFYOaeA.js";
4
4
  import "./decisions-C0pz9Clx.js";
5
5
 
6
6
  export { inspectProcessTree };
package/dist/index.d.ts CHANGED
@@ -147,6 +147,28 @@ interface StoryDoneEvent {
147
147
  /** Number of review cycles completed */
148
148
  review_cycles: number;
149
149
  }
150
+ /**
151
+ * Emitted when the orchestrator auto-approves a story after exhausting
152
+ * review cycles with only minor issues remaining. Provides transparency
153
+ * about why a NEEDS_MINOR_FIXES verdict resulted in COMPLETE status.
154
+ */
155
+ interface StoryAutoApprovedEvent {
156
+ type: 'story:auto-approved';
157
+ /** ISO-8601 timestamp generated at emit time */
158
+ ts: string;
159
+ /** Story key (e.g., "10-1") */
160
+ key: string;
161
+ /** Final review verdict (always NEEDS_MINOR_FIXES for auto-approve) */
162
+ verdict: string;
163
+ /** Number of review cycles completed */
164
+ review_cycles: number;
165
+ /** Maximum review cycles configured */
166
+ max_review_cycles: number;
167
+ /** Number of remaining issues at auto-approve time */
168
+ issue_count: number;
169
+ /** Human-readable reason for auto-approval */
170
+ reason: string;
171
+ }
150
172
  /**
151
173
  * An individual issue from a code review, included in escalation events.
152
174
  */
@@ -620,7 +642,7 @@ interface PipelinePhaseCompleteEvent {
620
642
  * }
621
643
  * ```
622
644
  */
623
- type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | PipelinePreFlightFailureEvent | PipelineProfileStaleEvent | PipelineContractMismatchEvent | PipelineContractVerificationSummaryEvent | StoryPhaseEvent | StoryDoneEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | StoryZeroDiffEscalationEvent | StoryBuildVerificationFailedEvent | StoryBuildVerificationPassedEvent | StoryInterfaceChangeWarningEvent | StoryMetricsEvent | SupervisorPollEvent | SupervisorKillEvent | SupervisorRestartEvent | SupervisorAbortEvent | SupervisorSummaryEvent | SupervisorAnalysisCompleteEvent | SupervisorAnalysisErrorEvent | SupervisorExperimentStartEvent | SupervisorExperimentSkipEvent | SupervisorExperimentRecommendationsEvent | SupervisorExperimentCompleteEvent | SupervisorExperimentErrorEvent | RoutingModelSelectedEvent | PipelinePhaseStartEvent | PipelinePhaseCompleteEvent; //#endregion
645
+ type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | PipelinePreFlightFailureEvent | PipelineProfileStaleEvent | PipelineContractMismatchEvent | PipelineContractVerificationSummaryEvent | StoryPhaseEvent | StoryDoneEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | StoryZeroDiffEscalationEvent | StoryBuildVerificationFailedEvent | StoryBuildVerificationPassedEvent | StoryInterfaceChangeWarningEvent | StoryMetricsEvent | SupervisorPollEvent | SupervisorKillEvent | SupervisorRestartEvent | SupervisorAbortEvent | SupervisorSummaryEvent | SupervisorAnalysisCompleteEvent | SupervisorAnalysisErrorEvent | SupervisorExperimentStartEvent | SupervisorExperimentSkipEvent | SupervisorExperimentRecommendationsEvent | SupervisorExperimentCompleteEvent | SupervisorExperimentErrorEvent | RoutingModelSelectedEvent | PipelinePhaseStartEvent | PipelinePhaseCompleteEvent | StoryAutoApprovedEvent; //#endregion
624
646
  //#region packages/core/dist/types.d.ts
625
647
 
626
648
  /**
@@ -1951,6 +1973,15 @@ interface OrchestratorEvents {
1951
1973
  rationale: string;
1952
1974
  };
1953
1975
  };
1976
+ /** Story auto-approved after exhausting review cycles with only minor issues */
1977
+ 'story:auto-approved': {
1978
+ storyKey: string;
1979
+ verdict: string;
1980
+ reviewCycles: number;
1981
+ maxReviewCycles: number;
1982
+ issueCount: number;
1983
+ reason: string;
1984
+ };
1954
1985
  /** A non-fatal warning occurred during story processing */
1955
1986
  'orchestrator:story-warn': {
1956
1987
  storyKey: string;
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-RlHA9HPJ.js";
3
+ import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-CtFYOaeA.js";
4
4
  import "./adapter-registry-DXLMTmfD.js";
5
- import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-C3Z7RYu9.js";
5
+ import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-CWSATPPa.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-RlHA9HPJ.js";
1
+ import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-CtFYOaeA.js";
2
2
  import "./routing-CcBOCuC9.js";
3
3
 
4
4
  export { loadModelRoutingConfig };
@@ -1,8 +1,8 @@
1
- import "./health-D8V9_Pn7.js";
1
+ import "./health-CkQncTB5.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
- import "./dist-RlHA9HPJ.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-tWQlCR2A.js";
4
+ import "./dist-CtFYOaeA.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-MGg8SzDA.js";
6
6
  import "./routing-CcBOCuC9.js";
7
7
  import "./decisions-C0pz9Clx.js";
8
8
 
@@ -1,7 +1,7 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, detectCycles, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, resolveMainRepoRoot, validateStoryKey } from "./health-D8V9_Pn7.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, detectCycles, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, resolveMainRepoRoot, validateStoryKey } from "./health-CkQncTB5.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, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-RlHA9HPJ.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, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-CtFYOaeA.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";
@@ -1247,6 +1247,48 @@ const PIPELINE_EVENT_METADATA = [
1247
1247
  }
1248
1248
  ]
1249
1249
  },
1250
+ {
1251
+ type: "story:auto-approved",
1252
+ description: "Story auto-approved after exhausting review cycles with only minor issues.",
1253
+ when: "When review cycles reach the maximum and the final verdict is NEEDS_MINOR_FIXES (not MAJOR_REWORK).",
1254
+ fields: [
1255
+ {
1256
+ name: "ts",
1257
+ type: "string",
1258
+ description: "Timestamp."
1259
+ },
1260
+ {
1261
+ name: "key",
1262
+ type: "string",
1263
+ description: "Story key."
1264
+ },
1265
+ {
1266
+ name: "verdict",
1267
+ type: "string",
1268
+ description: "Final review verdict (NEEDS_MINOR_FIXES)."
1269
+ },
1270
+ {
1271
+ name: "review_cycles",
1272
+ type: "number",
1273
+ description: "Review cycles completed."
1274
+ },
1275
+ {
1276
+ name: "max_review_cycles",
1277
+ type: "number",
1278
+ description: "Maximum review cycles configured."
1279
+ },
1280
+ {
1281
+ name: "issue_count",
1282
+ type: "number",
1283
+ description: "Remaining issues at auto-approve time."
1284
+ },
1285
+ {
1286
+ name: "reason",
1287
+ type: "string",
1288
+ description: "Human-readable reason for auto-approval."
1289
+ }
1290
+ ]
1291
+ },
1250
1292
  {
1251
1293
  type: "routing:model-selected",
1252
1294
  description: "Model routing resolver selected a model for a dispatch.",
@@ -10569,6 +10611,7 @@ function createImplementationOrchestrator(deps) {
10569
10611
  const _phaseStartMs = new Map();
10570
10612
  const _phaseEndMs = new Map();
10571
10613
  const _storyDispatches = new Map();
10614
+ let _completedDispatches = 0;
10572
10615
  let _maxConcurrentActual = 0;
10573
10616
  let _packageSnapshot;
10574
10617
  let _contractMismatches;
@@ -10587,6 +10630,7 @@ function createImplementationOrchestrator(deps) {
10587
10630
  function endPhase(storyKey, phase) {
10588
10631
  if (!_phaseEndMs.has(storyKey)) _phaseEndMs.set(storyKey, new Map());
10589
10632
  _phaseEndMs.get(storyKey).set(phase, Date.now());
10633
+ _completedDispatches++;
10590
10634
  }
10591
10635
  function incrementDispatches(storyKey) {
10592
10636
  _storyDispatches.set(storyKey, (_storyDispatches.get(storyKey) ?? 0) + 1);
@@ -10686,25 +10730,63 @@ function createImplementationOrchestrator(deps) {
10686
10730
  }
10687
10731
  let diffStats;
10688
10732
  try {
10689
- const statOutput = execSync("git diff --stat HEAD", {
10690
- cwd: projectRoot ?? process.cwd(),
10691
- encoding: "utf-8",
10692
- timeout: 5e3,
10693
- stdio: [
10694
- "ignore",
10695
- "pipe",
10696
- "pipe"
10697
- ]
10698
- });
10699
- const summaryLine = statOutput.trim().split("\n").pop() ?? "";
10700
- const filesMatch = summaryLine.match(/(\d+)\s+files?\s+changed/);
10701
- const insMatch = summaryLine.match(/(\d+)\s+insertions?/);
10702
- const delMatch = summaryLine.match(/(\d+)\s+deletions?/);
10703
- diffStats = {
10704
- filesChanged: filesMatch ? parseInt(filesMatch[1], 10) : 0,
10705
- insertions: insMatch ? parseInt(insMatch[1], 10) : 0,
10706
- deletions: delMatch ? parseInt(delMatch[1], 10) : 0
10707
- };
10733
+ const cwd = projectRoot ?? process.cwd();
10734
+ const changedFiles = checkGitDiffFiles(cwd);
10735
+ if (changedFiles.length > 0) {
10736
+ let insertions = 0;
10737
+ let deletions = 0;
10738
+ try {
10739
+ const numstat = execSync("git diff --numstat HEAD", {
10740
+ cwd,
10741
+ encoding: "utf-8",
10742
+ timeout: 5e3,
10743
+ stdio: [
10744
+ "ignore",
10745
+ "pipe",
10746
+ "pipe"
10747
+ ]
10748
+ });
10749
+ for (const line of numstat.trim().split("\n")) {
10750
+ const parts = line.split(" ");
10751
+ if (parts.length >= 2) {
10752
+ const ins = parseInt(parts[0], 10);
10753
+ const del = parseInt(parts[1], 10);
10754
+ if (!isNaN(ins)) insertions += ins;
10755
+ if (!isNaN(del)) deletions += del;
10756
+ }
10757
+ }
10758
+ } catch {}
10759
+ try {
10760
+ const untracked = execSync("git ls-files --others --exclude-standard", {
10761
+ cwd,
10762
+ encoding: "utf-8",
10763
+ timeout: 5e3,
10764
+ stdio: [
10765
+ "ignore",
10766
+ "pipe",
10767
+ "pipe"
10768
+ ]
10769
+ });
10770
+ for (const file of untracked.trim().split("\n").filter(Boolean)) try {
10771
+ const wc = execSync(`wc -l < "${file}"`, {
10772
+ cwd,
10773
+ encoding: "utf-8",
10774
+ timeout: 3e3,
10775
+ stdio: [
10776
+ "ignore",
10777
+ "pipe",
10778
+ "pipe"
10779
+ ]
10780
+ });
10781
+ insertions += parseInt(wc.trim(), 10) || 0;
10782
+ } catch {}
10783
+ } catch {}
10784
+ diffStats = {
10785
+ filesChanged: changedFiles.length,
10786
+ insertions,
10787
+ deletions
10788
+ };
10789
+ }
10708
10790
  } catch {}
10709
10791
  eventBus.emit("story:metrics", {
10710
10792
  storyKey,
@@ -10930,11 +11012,10 @@ function createImplementationOrchestrator(deps) {
10930
11012
  _heartbeatTimer = setInterval(() => {
10931
11013
  if (_state !== "RUNNING") return;
10932
11014
  let active = 0;
10933
- let completed = 0;
10934
11015
  let queued = 0;
10935
- for (const s$1 of _stories.values()) if (s$1.phase === "COMPLETE" || s$1.phase === "ESCALATED") completed++;
10936
- else if (s$1.phase === "PENDING") queued++;
10937
- else active++;
11016
+ for (const s$1 of _stories.values()) if (s$1.phase === "PENDING") queued++;
11017
+ else if (s$1.phase !== "COMPLETE" && s$1.phase !== "ESCALATED") active++;
11018
+ const completed = _completedDispatches;
10938
11019
  eventBus.emit("orchestrator:heartbeat", {
10939
11020
  runId: config.pipelineRunId ?? "",
10940
11021
  activeDispatches: active,
@@ -12466,6 +12547,14 @@ function createImplementationOrchestrator(deps) {
12466
12547
  }, "Auto-approve fix dispatch failed — approving anyway (issues were minor)");
12467
12548
  }
12468
12549
  endPhase(storyKey, "code-review");
12550
+ eventBus.emit("story:auto-approved", {
12551
+ storyKey,
12552
+ verdict,
12553
+ reviewCycles: finalReviewCycles,
12554
+ maxReviewCycles: config.maxReviewCycles,
12555
+ issueCount: issueList.length,
12556
+ reason: `Review cycles exhausted (${finalReviewCycles}/${config.maxReviewCycles}) with only minor issues — auto-approving`
12557
+ });
12469
12558
  updateStory(storyKey, {
12470
12559
  phase: "COMPLETE",
12471
12560
  reviewCycles: finalReviewCycles,
@@ -12484,6 +12573,7 @@ function createImplementationOrchestrator(deps) {
12484
12573
  await waitIfPaused();
12485
12574
  if (_state !== "RUNNING") return;
12486
12575
  updateStory(storyKey, { phase: "NEEDS_FIXES" });
12576
+ startPhase(storyKey, "fix");
12487
12577
  const taskType = verdict === "NEEDS_MINOR_FIXES" ? "minor-fixes" : "major-rework";
12488
12578
  const fixModel = taskType === "major-rework" ? "claude-opus-4-6" : void 0;
12489
12579
  try {
@@ -12634,6 +12724,7 @@ function createImplementationOrchestrator(deps) {
12634
12724
  ..._otlpEndpoint !== void 0 ? { otlpEndpoint: _otlpEndpoint } : {}
12635
12725
  });
12636
12726
  const fixResult = await handle.result;
12727
+ endPhase(storyKey, "fix");
12637
12728
  eventBus.emit("orchestrator:story-phase-complete", {
12638
12729
  storyKey,
12639
12730
  phase: taskType === "minor-fixes" ? "IN_MINOR_FIX" : "IN_MAJOR_FIX",
@@ -40306,6 +40397,18 @@ function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
40306
40397
  source: payload.source
40307
40398
  });
40308
40399
  });
40400
+ eventBus.on("story:auto-approved", (payload) => {
40401
+ ndjsonEmitter.emit({
40402
+ type: "story:auto-approved",
40403
+ ts: new Date().toISOString(),
40404
+ key: payload.storyKey,
40405
+ verdict: payload.verdict,
40406
+ review_cycles: payload.reviewCycles,
40407
+ max_review_cycles: payload.maxReviewCycles,
40408
+ issue_count: payload.issueCount,
40409
+ reason: payload.reason
40410
+ });
40411
+ });
40309
40412
  eventBus.on("orchestrator:story-complete", (payload) => {
40310
40413
  ndjsonEmitter.emit({
40311
40414
  type: "story:done",
@@ -41716,4 +41819,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
41716
41819
 
41717
41820
  //#endregion
41718
41821
  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, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
41719
- //# sourceMappingURL=run-tWQlCR2A.js.map
41822
+ //# sourceMappingURL=run-MGg8SzDA.js.map
@@ -1,5 +1,5 @@
1
- import "./dist-RlHA9HPJ.js";
1
+ import "./dist-CtFYOaeA.js";
2
2
  import "./version-manager-impl-BmOWu8ml.js";
3
- import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-2LJZtYUC.js";
3
+ import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-UCMt4b7A.js";
4
4
 
5
5
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
@@ -1,4 +1,4 @@
1
- import { createVersionManager } from "./dist-RlHA9HPJ.js";
1
+ import { createVersionManager } from "./dist-CtFYOaeA.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-2LJZtYUC.js.map
126
+ //# sourceMappingURL=upgrade-UCMt4b7A.js.map
@@ -1,4 +1,4 @@
1
- import { VersionManagerImpl, createVersionManager } from "./dist-RlHA9HPJ.js";
1
+ import { VersionManagerImpl, createVersionManager } from "./dist-CtFYOaeA.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.19.18",
3
+ "version": "0.19.20",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,4 +0,0 @@
1
- import { AdapterRegistry } from "./dist-RlHA9HPJ.js";
2
- import "./adapter-registry-DXLMTmfD.js";
3
-
4
- export { AdapterRegistry };