substrate-ai 0.20.118 → 0.20.120

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
@@ -3,7 +3,7 @@ import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipeline
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, InMemoryDatabaseAdapter, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createPipelineRun, createStderrLogger, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initWorkGraphSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-Bc0-6VcX.js";
6
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-ChYRCHEg.js";
6
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-0JiAo0rp.js";
7
7
  import "../adapter-registry-DIcrxjH8.js";
8
8
  import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-BE70EnPy.js";
9
9
  import "../errors-CwQM_6Yk.js";
@@ -8419,7 +8419,7 @@ async function runSupervisorAction(options, deps = {}) {
8419
8419
  await initSchema(expAdapter);
8420
8420
  const { runRunAction: runPipeline } = await import(
8421
8421
  /* @vite-ignore */
8422
- "../run-C9G6UVVH.js"
8422
+ "../run-CB-oiwic.js"
8423
8423
  );
8424
8424
  const runStoryFn = async (opts) => {
8425
8425
  const exitCode = await runPipeline({
@@ -12632,7 +12632,7 @@ function classifyStoryOutcome(state, _manifest) {
12632
12632
  */
12633
12633
  function enrichEscalation(storyKey, state, runId, manifest) {
12634
12634
  const root_cause = state.escalation_reason ?? "unknown";
12635
- const recovery_attempts = state.review_cycles ?? (manifest.recovery_history ?? []).filter((e) => e.story_key === storyKey).length;
12635
+ const recovery_attempts = Math.max(state.review_cycles ?? 0, (manifest.recovery_history ?? []).filter((e) => e.story_key === storyKey).length);
12636
12636
  const blast_radius = `Story ${storyKey} in run ${runId} — ${recovery_attempts} recovery attempt(s)`;
12637
12637
  let suggested_operator_action;
12638
12638
  switch (root_cause) {
@@ -2,7 +2,7 @@ import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_
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, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, createStderrLogger, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-Bc0-6VcX.js";
5
- import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-BE70EnPy.js";
5
+ import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-BE70EnPy.js";
6
6
  import { WorkGraphRepository, detectCycles } from "./work-graph-repository-DZyJv5pV.js";
7
7
  import { deriveExitCode, routeDecision } from "./decision-router-DblHY8se.js";
8
8
  import { runInteractivePrompt } from "./interactive-prompt-B4sDQpFI.js";
@@ -13046,7 +13046,32 @@ function titleToWordSet(title) {
13046
13046
  "this",
13047
13047
  "via"
13048
13048
  ]);
13049
- return new Set(title.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/[\s-]+/).filter((w) => w.length > 2 && !stopWords.has(w)));
13049
+ return new Set(title.toLowerCase().replace(/[\u0000-\u001F\u007F]/g, " ").split(/[\s-]+/).filter((w) => w.length > 2 && !stopWords.has(w)));
13050
+ }
13051
+ /**
13052
+ * Sanitize a create-story-emitted story title before it is used to compose the
13053
+ * dev-story auto-commit subject (`feat(story-N-M): <title>`).
13054
+ *
13055
+ * F-commitmsg (2026-05-26, run 376a3930 / story 78-1): create-story's structured
13056
+ * `story_title` can absorb stray stdout — a story whose domain is `substrate report`
13057
+ * bled the report banner (rows of `═` box-drawing characters + "Run: …/Verdict: …"
13058
+ * text) into the title, producing a multi-line, box-drawing-filled commit subject.
13059
+ * A commit subject must be a single clean line, so:
13060
+ * - reject outright (→ undefined) any title containing box-drawing/block glyphs
13061
+ * (U+2500–U+259F) — that is unambiguous stdout contamination, not a real title;
13062
+ * - otherwise take the first non-empty line, strip control chars, collapse
13063
+ * whitespace, and cap the length.
13064
+ * Returning undefined makes commitDevStoryOutput fall back to its safe default
13065
+ * ("implementation"), yielding `feat(story-N-M): implementation` rather than a
13066
+ * mangled subject. Exported for unit testing.
13067
+ */
13068
+ function sanitizeStoryTitle(raw) {
13069
+ if (typeof raw !== "string") return void 0;
13070
+ if (/[\u2500-\u259F]/.test(raw)) return void 0;
13071
+ const firstLine = raw.split("\n").map((l) => l.trim()).find((l) => l.length > 0) ?? "";
13072
+ const cleaned = Array.from(firstLine).map((ch) => ch.charCodeAt(0) < 32 || ch.charCodeAt(0) === 127 ? " " : ch).join("").replace(/\s+/g, " ").trim();
13073
+ if (cleaned.length === 0) return void 0;
13074
+ return cleaned.length > 120 ? `${cleaned.slice(0, 117)}...` : cleaned;
13050
13075
  }
13051
13076
  /**
13052
13077
  * Compute the word overlap ratio between two titles.
@@ -14072,6 +14097,7 @@ function createImplementationOrchestrator(deps) {
14072
14097
  return;
14073
14098
  }
14074
14099
  let fidelityRetries = 0;
14100
+ let probeRetries = 0;
14075
14101
  let priorDriftFeedback;
14076
14102
  while (storyFilePath === void 0) {
14077
14103
  try {
@@ -14258,7 +14284,7 @@ function createImplementationOrchestrator(deps) {
14258
14284
  }
14259
14285
  }
14260
14286
  storyFilePath = createResult.story_file;
14261
- _capturedStoryTitle = createResult.story_title;
14287
+ _capturedStoryTitle = sanitizeStoryTitle(createResult.story_title);
14262
14288
  if (createResult.story_title) try {
14263
14289
  const epicId = storyKey.split("-")[0] ?? storyKey;
14264
14290
  const implDecisions = await getDecisionsByPhase(db, "implementation");
@@ -14446,6 +14472,43 @@ function createImplementationOrchestrator(deps) {
14446
14472
  err: fidelityErr
14447
14473
  }, "fidelity gate threw; proceeding without retry");
14448
14474
  }
14475
+ if (storyFilePath !== void 0 && effectiveProjectRoot !== void 0) try {
14476
+ const probeContent = await readFile$1(storyFilePath, "utf-8");
14477
+ const probeParse = parseRuntimeProbes(probeContent);
14478
+ if (probeParse.kind === "invalid" && probeRetries < MAX_FIDELITY_RETRIES) {
14479
+ probeRetries++;
14480
+ const stalePath = storyFilePath.replace(/\.md$/, `.stale-probe-${Date.now()}.md`);
14481
+ renameSync(storyFilePath, stalePath);
14482
+ logger$27.warn({
14483
+ storyKey,
14484
+ error: probeParse.error,
14485
+ retries: probeRetries,
14486
+ stalePath
14487
+ }, `create-story produced an invalid ## Runtime Probes block (${probeParse.error}); renamed to ${stalePath} and retrying (${probeRetries}/${MAX_FIDELITY_RETRIES})`);
14488
+ eventBus.emit("orchestrator:story-warn", {
14489
+ storyKey,
14490
+ msg: `invalid runtime-probe YAML; retry ${probeRetries}/${MAX_FIDELITY_RETRIES}`
14491
+ });
14492
+ priorDriftFeedback = [
14493
+ `### Prior Dispatch — Invalid Runtime Probes YAML (retry ${probeRetries}/${MAX_FIDELITY_RETRIES})`,
14494
+ "",
14495
+ `The previous artifact's \`## Runtime Probes\` block was not valid YAML and has been moved to \`${stalePath}\`.`,
14496
+ "",
14497
+ `Parse error: ${probeParse.error}`,
14498
+ "",
14499
+ "When re-authoring the probes, the fenced ```yaml block MUST be valid YAML:",
14500
+ "- Inside a `command: |` block scalar, EVERY line (including blank-line continuations) must be indented to at least the block indentation. A multi-line shell string with an unindented (column-0) line — e.g. a `git commit -m \"subject\\n\\nCo-Authored-By: ...\"` whose trailer sits at column 0 — terminates the scalar and breaks the YAML.",
14501
+ "- Prefer single-line commands, or keep every continuation line indented under the block scalar."
14502
+ ].join("\n");
14503
+ storyFilePath = void 0;
14504
+ continue;
14505
+ }
14506
+ } catch (probeGateErr) {
14507
+ logger$27.warn({
14508
+ storyKey,
14509
+ err: probeGateErr
14510
+ }, "probe-validity gate threw; proceeding without retry (verification backstop)");
14511
+ }
14449
14512
  }
14450
14513
  if (storyFilePath) try {
14451
14514
  const storyContent = await readFile$1(storyFilePath, "utf-8");
@@ -47200,4 +47263,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
47200
47263
 
47201
47264
  //#endregion
47202
47265
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
47203
- //# sourceMappingURL=run-ChYRCHEg.js.map
47266
+ //# sourceMappingURL=run-0JiAo0rp.js.map
@@ -2,7 +2,7 @@ import "./health-DSg6dtya.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
4
  import "./dist-Bc0-6VcX.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-ChYRCHEg.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-0JiAo0rp.js";
6
6
  import "./manifest-read-BE70EnPy.js";
7
7
  import "./routing-DFxoKHDt.js";
8
8
  import "./work-graph-repository-DZyJv5pV.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.118",
3
+ "version": "0.20.120",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",