substrate-ai 0.20.3 → 0.20.5

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.
@@ -1,4 +1,4 @@
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, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-BfeoutPu.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-DHLR9Iz1.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-srr3BfCc.js";
@@ -6386,478 +6386,6 @@ async function runGitCommand(args, cwd, logLabel) {
6386
6386
  });
6387
6387
  }
6388
6388
 
6389
- //#endregion
6390
- //#region packages/sdlc/dist/verification/checks/phantom-review-check.js
6391
- /**
6392
- * PhantomReviewCheck — Story 51-2.
6393
- *
6394
- * Tier A verification check that detects when a code review dispatch failed
6395
- * but was recorded as a passing verdict. Stories that were never actually
6396
- * reviewed should not be counted as verified.
6397
- *
6398
- * Architecture constraints (FR-V9):
6399
- * - No LLM calls.
6400
- * - No shell invocations — pure static signal inspection over VerificationContext fields.
6401
- * - Runs first in Tier A (before TrivialOutputCheck, before BuildCheck).
6402
- */
6403
- /**
6404
- * Detects phantom reviews — dispatches that failed or produced no output but
6405
- * were recorded as passing verdicts.
6406
- *
6407
- * AC1: dispatch failed (non-zero exit, timeout, crash) → fail
6408
- * AC2: empty or null rawOutput → fail
6409
- * AC3: schema_validation_failed error → fail
6410
- * AC5: valid review (non-empty rawOutput, no dispatchFailed) → pass
6411
- * AC6: name='phantom-review', tier='A'
6412
- */
6413
- var PhantomReviewCheck = class {
6414
- name = "phantom-review";
6415
- tier = "A";
6416
- async run(context) {
6417
- const start = Date.now();
6418
- const review = context.reviewResult;
6419
- if (!review) return {
6420
- status: "pass",
6421
- details: "phantom-review: no review result in context — skipping check",
6422
- duration_ms: Date.now() - start
6423
- };
6424
- if (review.dispatchFailed === true) {
6425
- const reason = review.error === "schema_validation_failed" ? "schema validation failed" : `dispatch failed${review.error ? ` — ${review.error}` : ""}`;
6426
- return {
6427
- status: "fail",
6428
- details: `phantom-review: ${reason}`,
6429
- duration_ms: Date.now() - start
6430
- };
6431
- }
6432
- if (review.rawOutput !== void 0 && review.rawOutput.trim().length === 0) return {
6433
- status: "fail",
6434
- details: "phantom-review: empty review output",
6435
- duration_ms: Date.now() - start
6436
- };
6437
- return {
6438
- status: "pass",
6439
- details: "phantom-review: review output is valid",
6440
- duration_ms: Date.now() - start
6441
- };
6442
- }
6443
- };
6444
-
6445
- //#endregion
6446
- //#region packages/sdlc/dist/verification/checks/trivial-output-check.js
6447
- /**
6448
- * TrivialOutputCheck — Story 51-3.
6449
- *
6450
- * Tier A verification check that flags story dispatches which produced
6451
- * fewer output tokens than the configured threshold. A very low output
6452
- * token count is a strong signal that the agent exited early (e.g. hit a
6453
- * maxTurns limit, encountered a fatal error, or did no real work).
6454
- *
6455
- * Architecture constraints (DC-6, FR-V9):
6456
- * - No LLM calls.
6457
- * - No shell invocations — pure in-process computation.
6458
- * - Runs in Tier A: before BuildCheck, after PhantomReviewCheck.
6459
- */
6460
- /**
6461
- * Default minimum output-token count a story must produce to be
6462
- * considered non-trivial. Configurable via trivialOutputThreshold config field.
6463
- */
6464
- const DEFAULT_TRIVIAL_OUTPUT_THRESHOLD = 100;
6465
- /**
6466
- * Checks that a completed story dispatch produced at least `threshold` output
6467
- * tokens. Dispatches that produced fewer tokens are flagged as failures with
6468
- * an actionable suggestion to re-run with increased maxTurns.
6469
- *
6470
- * AC1: fail when outputTokenCount < threshold.
6471
- * AC2: details string includes "Re-run with increased maxTurns".
6472
- * AC3: pass when outputTokenCount >= threshold.
6473
- * AC4: threshold is configurable via trivialOutputThreshold config field.
6474
- * AC5: warn (not fail) when outputTokenCount is undefined.
6475
- * AC6: implements VerificationCheck with name='trivial-output', tier='A'.
6476
- */
6477
- var TrivialOutputCheck = class {
6478
- name = "trivial-output";
6479
- tier = "A";
6480
- threshold;
6481
- constructor(config) {
6482
- this.threshold = config?.trivialOutputThreshold ?? DEFAULT_TRIVIAL_OUTPUT_THRESHOLD;
6483
- }
6484
- async run(context) {
6485
- const start = Date.now();
6486
- if (context.outputTokenCount === void 0) return {
6487
- status: "warn",
6488
- details: "trivial-output: output token count unavailable — skipping check",
6489
- duration_ms: Date.now() - start
6490
- };
6491
- const count = context.outputTokenCount;
6492
- if (count < this.threshold) return {
6493
- status: "fail",
6494
- details: `trivial-output: output token count ${count} is below threshold ${this.threshold} — Re-run with increased maxTurns`,
6495
- duration_ms: Date.now() - start
6496
- };
6497
- return {
6498
- status: "pass",
6499
- details: `output token count ${count} meets threshold ${this.threshold}`,
6500
- duration_ms: Date.now() - start
6501
- };
6502
- }
6503
- };
6504
-
6505
- //#endregion
6506
- //#region packages/sdlc/dist/verification/checks/acceptance-criteria-evidence-check.js
6507
- /**
6508
- * AcceptanceCriteriaEvidenceCheck.
6509
- *
6510
- * Tier A verification check that compares a story's declared acceptance
6511
- * criteria against structured dev-story output. The check is intentionally
6512
- * deterministic: no LLM calls, no shell commands, no repository inspection.
6513
- */
6514
- const EXPLICIT_AC_REF = /\bAC\s*:?\s*#?\s*(\d+)\b/gi;
6515
- const NUMBERED_CRITERION = /^\s*(?:[-*]\s*)?(?:\[[ xX]\]\s*)?(\d+)[.)]\s+\S/;
6516
- function normalizeAcId(value) {
6517
- const parsed = Number.parseInt(value, 10);
6518
- if (!Number.isFinite(parsed) || parsed <= 0) return void 0;
6519
- return `AC${parsed}`;
6520
- }
6521
- function sortAcIds(ids) {
6522
- return Array.from(ids).sort((a, b) => {
6523
- const aNum = Number.parseInt(a.replace(/^AC/i, ""), 10);
6524
- const bNum = Number.parseInt(b.replace(/^AC/i, ""), 10);
6525
- return aNum - bNum;
6526
- });
6527
- }
6528
- function addExplicitAcRefs(text, ids) {
6529
- EXPLICIT_AC_REF.lastIndex = 0;
6530
- let match$2;
6531
- while ((match$2 = EXPLICIT_AC_REF.exec(text)) !== null) {
6532
- const id = normalizeAcId(match$2[1] ?? "");
6533
- if (id !== void 0) ids.add(id);
6534
- }
6535
- }
6536
- function extractAcceptanceSection(storyContent) {
6537
- const lines = storyContent.split(/\r?\n/);
6538
- const start = lines.findIndex((line) => /^##\s+Acceptance Criteria\s*$/i.test(line.trim()));
6539
- if (start === -1) return void 0;
6540
- let end = lines.length;
6541
- for (let i = start + 1; i < lines.length; i += 1) if (/^##\s+\S/.test(lines[i] ?? "")) {
6542
- end = i;
6543
- break;
6544
- }
6545
- return lines.slice(start + 1, end).join("\n");
6546
- }
6547
- /**
6548
- * Extract normalized AC ids from story markdown.
6549
- *
6550
- * Supports the BMAD default format (`### AC1:`), explicit references such as
6551
- * `AC: #1`, and plain numbered criteria inside the Acceptance Criteria section.
6552
- */
6553
- function extractAcceptanceCriteriaIds(storyContent) {
6554
- const ids = new Set();
6555
- const acceptanceSection = extractAcceptanceSection(storyContent);
6556
- const textToScan = acceptanceSection ?? storyContent;
6557
- addExplicitAcRefs(textToScan, ids);
6558
- if (acceptanceSection !== void 0) for (const line of acceptanceSection.split(/\r?\n/)) {
6559
- const match$2 = line.match(NUMBERED_CRITERION);
6560
- if (match$2?.[1] !== void 0) {
6561
- const id = normalizeAcId(match$2[1]);
6562
- if (id !== void 0) ids.add(id);
6563
- }
6564
- }
6565
- return sortAcIds(ids);
6566
- }
6567
- function extractClaimedAcceptanceCriteriaIds(values) {
6568
- const ids = new Set();
6569
- for (const value of values ?? []) {
6570
- addExplicitAcRefs(value, ids);
6571
- const bareNumber = value.trim().match(/^#?(\d+)\b/);
6572
- if (bareNumber?.[1] !== void 0) {
6573
- const id = normalizeAcId(bareNumber[1]);
6574
- if (id !== void 0) ids.add(id);
6575
- }
6576
- }
6577
- return sortAcIds(ids);
6578
- }
6579
- function normalizeTestOutcome(value) {
6580
- if (value === void 0) return void 0;
6581
- return value.toLowerCase().includes("fail") ? "fail" : "pass";
6582
- }
6583
- function formatIds(ids) {
6584
- return ids.join(", ");
6585
- }
6586
- var AcceptanceCriteriaEvidenceCheck = class {
6587
- name = "acceptance-criteria-evidence";
6588
- tier = "A";
6589
- async run(context) {
6590
- const start = Date.now();
6591
- const storyContent = context.storyContent?.trim();
6592
- if (!storyContent) return {
6593
- status: "warn",
6594
- details: "acceptance-criteria-evidence: story content unavailable - skipping AC evidence check",
6595
- duration_ms: Date.now() - start
6596
- };
6597
- const expectedIds = extractAcceptanceCriteriaIds(storyContent);
6598
- if (expectedIds.length === 0) return {
6599
- status: "warn",
6600
- details: "acceptance-criteria-evidence: no numbered acceptance criteria found in story",
6601
- duration_ms: Date.now() - start
6602
- };
6603
- const devResult = context.devStoryResult;
6604
- if (devResult === void 0) return {
6605
- status: "warn",
6606
- details: `acceptance-criteria-evidence: dev-story result unavailable for ${formatIds(expectedIds)}`,
6607
- duration_ms: Date.now() - start
6608
- };
6609
- const acFailures = devResult.ac_failures ?? [];
6610
- if (acFailures.length > 0) return {
6611
- status: "fail",
6612
- details: `acceptance-criteria-evidence: dev-story reported AC failures: ${acFailures.join("; ")}`,
6613
- duration_ms: Date.now() - start
6614
- };
6615
- const testOutcome = normalizeTestOutcome(devResult.tests);
6616
- if (testOutcome === "fail") return {
6617
- status: "fail",
6618
- details: "acceptance-criteria-evidence: dev-story reported failing tests",
6619
- duration_ms: Date.now() - start
6620
- };
6621
- const claimedIds = new Set(extractClaimedAcceptanceCriteriaIds(devResult.ac_met));
6622
- const missingIds = expectedIds.filter((id) => !claimedIds.has(id));
6623
- if (missingIds.length > 0) return {
6624
- status: "fail",
6625
- details: `acceptance-criteria-evidence: missing dev-story AC evidence for ${formatIds(missingIds)}; expected ${formatIds(expectedIds)}, claimed ${formatIds(sortAcIds(claimedIds)) || "none"}`,
6626
- duration_ms: Date.now() - start
6627
- };
6628
- if (testOutcome === void 0) return {
6629
- status: "warn",
6630
- details: `acceptance-criteria-evidence: AC evidence covers ${formatIds(expectedIds)} but test outcome is unavailable`,
6631
- duration_ms: Date.now() - start
6632
- };
6633
- return {
6634
- status: "pass",
6635
- details: `acceptance-criteria-evidence: AC evidence covers ${formatIds(expectedIds)}; tests=${testOutcome}`,
6636
- duration_ms: Date.now() - start
6637
- };
6638
- }
6639
- };
6640
-
6641
- //#endregion
6642
- //#region packages/sdlc/dist/verification/checks/build-check.js
6643
- /** Hard timeout for the build command in milliseconds (FR-V11). */
6644
- const BUILD_CHECK_TIMEOUT_MS = 6e4;
6645
- /** Maximum characters to include in details string from build output. */
6646
- const MAX_OUTPUT_CHARS = 2e3;
6647
- /**
6648
- * Detect the build command for a project based on files present in `workingDir`.
6649
- *
6650
- * Returns an empty string when no recognized build system is found, which
6651
- * causes BuildCheck to return a 'warn' result without blocking the pipeline.
6652
- *
6653
- * NOTE: Do NOT import from src/modules/agent-dispatch/dispatcher-impl.ts —
6654
- * that would create a circular dependency from packages/sdlc/ → monolith src/.
6655
- * This function inlines the detection logic independently.
6656
- */
6657
- function detectBuildCommand(workingDir) {
6658
- if (existsSync(join$1(workingDir, "turbo.json"))) return "turbo build";
6659
- if (existsSync(join$1(workingDir, "pnpm-lock.yaml"))) return "pnpm run build";
6660
- if (existsSync(join$1(workingDir, "yarn.lock"))) return "yarn build";
6661
- if (existsSync(join$1(workingDir, "bun.lockb"))) return "bun run build";
6662
- if (existsSync(join$1(workingDir, "package.json"))) return "npm run build";
6663
- const nonNodeMarkers = [
6664
- "pyproject.toml",
6665
- "poetry.lock",
6666
- "setup.py",
6667
- "Cargo.toml",
6668
- "go.mod"
6669
- ];
6670
- for (const marker of nonNodeMarkers) if (existsSync(join$1(workingDir, marker))) return "";
6671
- return "";
6672
- }
6673
- /**
6674
- * Runs the project's build command and returns pass/warn/fail based on exit code.
6675
- *
6676
- * AC1: exit code 0 → pass
6677
- * AC2: non-zero exit code → fail with truncated output in details
6678
- * AC3: timeout → kill process group, return fail with timeout message
6679
- * AC4: no recognized build system → warn without blocking
6680
- * AC5: explicit buildCommand override respected; empty string → warn (skip)
6681
- * AC6: name === 'build', tier === 'A'
6682
- */
6683
- var BuildCheck = class {
6684
- name = "build";
6685
- tier = "A";
6686
- async run(context) {
6687
- const start = Date.now();
6688
- const cmd = context.buildCommand !== void 0 ? context.buildCommand : detectBuildCommand(context.workingDir);
6689
- if (cmd === "") return {
6690
- status: "warn",
6691
- details: `build-skip: no build command detected for project at ${context.workingDir}`,
6692
- duration_ms: Date.now() - start
6693
- };
6694
- return new Promise((resolve$6) => {
6695
- const child = spawn(cmd, [], {
6696
- cwd: context.workingDir,
6697
- detached: true,
6698
- shell: true,
6699
- stdio: [
6700
- "ignore",
6701
- "pipe",
6702
- "pipe"
6703
- ]
6704
- });
6705
- let output = "";
6706
- child.stdout?.on("data", (chunk) => {
6707
- output += chunk.toString();
6708
- });
6709
- child.stderr?.on("data", (chunk) => {
6710
- output += chunk.toString();
6711
- });
6712
- const timeoutHandle = setTimeout(() => {
6713
- try {
6714
- process.kill(-child.pid, "SIGKILL");
6715
- } catch {}
6716
- resolve$6({
6717
- status: "fail",
6718
- details: `build-timeout: command exceeded ${BUILD_CHECK_TIMEOUT_MS}ms`,
6719
- duration_ms: Date.now() - start
6720
- });
6721
- }, BUILD_CHECK_TIMEOUT_MS);
6722
- child.on("close", (code) => {
6723
- clearTimeout(timeoutHandle);
6724
- if (code === 0) resolve$6({
6725
- status: "pass",
6726
- details: "build passed",
6727
- duration_ms: Date.now() - start
6728
- });
6729
- else {
6730
- const truncated = output.length > MAX_OUTPUT_CHARS ? output.slice(0, MAX_OUTPUT_CHARS) + "... (truncated)" : output;
6731
- resolve$6({
6732
- status: "fail",
6733
- details: `build failed (exit ${code}): ${truncated}`,
6734
- duration_ms: Date.now() - start
6735
- });
6736
- }
6737
- });
6738
- });
6739
- }
6740
- };
6741
-
6742
- //#endregion
6743
- //#region packages/sdlc/dist/verification/verification-pipeline.js
6744
- /**
6745
- * Compute the worst-case aggregate status across a list of check results.
6746
- * Precedence: fail > warn > pass.
6747
- */
6748
- function aggregateStatus(checks) {
6749
- let result = "pass";
6750
- for (const c of checks) {
6751
- if (c.status === "fail") return "fail";
6752
- if (c.status === "warn") result = "warn";
6753
- }
6754
- return result;
6755
- }
6756
- /**
6757
- * Runs an ordered chain of VerificationCheck implementations after each story dispatch.
6758
- *
6759
- * Checks are stored in registration order. When `run()` is called with `tier: 'A'`
6760
- * only Tier A checks execute; when called with `tier: 'B'` only Tier B checks execute.
6761
- * (Story 51-5 will invoke both tiers at the appropriate orchestration points.)
6762
- */
6763
- var VerificationPipeline = class {
6764
- _bus;
6765
- _checks = [];
6766
- /**
6767
- * @param bus Typed event bus for emitting verification events.
6768
- * @param checks Optional initial list of checks to register at construction time.
6769
- */
6770
- constructor(bus, checks = []) {
6771
- this._bus = bus;
6772
- for (const check of checks) this.register(check);
6773
- }
6774
- /**
6775
- * Register a VerificationCheck.
6776
- *
6777
- * Checks are stored in insertion order within their tier.
6778
- * Tier A checks always run before Tier B checks regardless of registration order.
6779
- */
6780
- register(check) {
6781
- this._checks.push(check);
6782
- }
6783
- /**
6784
- * Execute all checks matching the specified tier sequentially.
6785
- *
6786
- * AC2: Tier A checks execute in registration order.
6787
- * AC4: Results are aggregated into a VerificationSummary.
6788
- * AC5: verification:check-complete and verification:story-complete events are emitted.
6789
- * AC6: Unhandled exceptions are caught and recorded as warn.
6790
- *
6791
- * @param context Verification context for the story being verified.
6792
- * @param tier Which tier of checks to execute ('A' | 'B'). Defaults to 'A'.
6793
- */
6794
- async run(context, tier = "A") {
6795
- const pipelineStart = Date.now();
6796
- const checks = this._checks.filter((c) => c.tier === tier);
6797
- const checkResults = [];
6798
- for (const check of checks) {
6799
- const checkStart = Date.now();
6800
- let result;
6801
- try {
6802
- const runResult = await check.run(context);
6803
- result = {
6804
- checkName: check.name,
6805
- status: runResult.status,
6806
- details: runResult.details,
6807
- duration_ms: runResult.duration_ms
6808
- };
6809
- } catch (err) {
6810
- const elapsed = Date.now() - checkStart;
6811
- const message = err instanceof Error ? err.message : String(err);
6812
- process.stderr.write(`[verification-pipeline] check "${check.name}" threw an unhandled exception: ${message}\n`);
6813
- result = {
6814
- checkName: check.name,
6815
- status: "warn",
6816
- details: message,
6817
- duration_ms: elapsed
6818
- };
6819
- }
6820
- checkResults.push(result);
6821
- this._bus.emit("verification:check-complete", {
6822
- storyKey: context.storyKey,
6823
- checkName: result.checkName,
6824
- status: result.status,
6825
- details: result.details,
6826
- duration_ms: result.duration_ms
6827
- });
6828
- }
6829
- const summary = {
6830
- storyKey: context.storyKey,
6831
- checks: checkResults,
6832
- status: aggregateStatus(checkResults),
6833
- duration_ms: Date.now() - pipelineStart
6834
- };
6835
- this._bus.emit("verification:story-complete", summary);
6836
- return summary;
6837
- }
6838
- };
6839
- /**
6840
- * Create a VerificationPipeline pre-loaded with the canonical check set.
6841
- *
6842
- * Canonical Tier A check order (architecture section 3.5):
6843
- * 1. PhantomReviewCheck — story 51-2 (runs first: unreviewed stories skipped)
6844
- * 2. TrivialOutputCheck — story 51-3
6845
- * 3. AcceptanceCriteriaEvidenceCheck
6846
- * 4. BuildCheck — story 51-4
6847
- *
6848
- * @param bus Typed event bus for verification events.
6849
- * @param config Optional config (used to forward threshold to TrivialOutputCheck).
6850
- */
6851
- function createDefaultVerificationPipeline(bus, config) {
6852
- const checks = [
6853
- new PhantomReviewCheck(),
6854
- new TrivialOutputCheck(config),
6855
- new AcceptanceCriteriaEvidenceCheck(),
6856
- new BuildCheck()
6857
- ];
6858
- return new VerificationPipeline(bus, checks);
6859
- }
6860
-
6861
6389
  //#endregion
6862
6390
  //#region src/modules/compiled-workflows/story-complexity.ts
6863
6391
  const logger$16 = createLogger("compiled-workflows:story-complexity");
@@ -10952,6 +10480,29 @@ function persistVerificationResult(storyKey, summary, runManifest) {
10952
10480
  storyKey
10953
10481
  }, "manifest verification_result write failed — pipeline continues"));
10954
10482
  }
10483
+ /**
10484
+ * Flatten every finding from a VerificationSummary's checks into a single
10485
+ * prompt-ready string. Returns '' when the summary is undefined, contains
10486
+ * no checks, or every check emits zero findings (e.g. every check passed).
10487
+ *
10488
+ * The output is intended for direct injection into retry/rework/fix
10489
+ * prompt templates via a `{{verification_findings}}` section — kept
10490
+ * human-readable and minimal. Each finding is rendered as a single
10491
+ * `ERROR [category] message` / `WARN [...]` / `INFO [...]` line via the
10492
+ * renderFindings helper from the verification module; lines are grouped
10493
+ * by check name for readability.
10494
+ */
10495
+ function renderVerificationFindingsForPrompt(summary) {
10496
+ if (!summary) return "";
10497
+ const blocks = [];
10498
+ for (const check of summary.checks) {
10499
+ const findings = check.findings ?? [];
10500
+ if (findings.length === 0) continue;
10501
+ const rendered = renderFindings(findings);
10502
+ blocks.push(`- ${check.checkName}:\n${rendered.replace(/^/gm, " ")}`);
10503
+ }
10504
+ return blocks.join("\n");
10505
+ }
10955
10506
 
10956
10507
  //#endregion
10957
10508
  //#region src/modules/implementation-orchestrator/cost-governance.ts
@@ -13912,6 +13463,7 @@ function createImplementationOrchestrator(deps) {
13912
13463
  archConstraints = constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
13913
13464
  } catch {}
13914
13465
  const targetedFilesContent = buildTargetedFilesContent(issueList);
13466
+ const verificationFindingsContent = renderVerificationFindingsForPrompt(verificationStore.get(storyKey));
13915
13467
  const sections = [
13916
13468
  {
13917
13469
  name: "story_content",
@@ -13932,6 +13484,11 @@ function createImplementationOrchestrator(deps) {
13932
13484
  name: "targeted_files",
13933
13485
  content: targetedFilesContent,
13934
13486
  priority: "important"
13487
+ }] : [],
13488
+ ...verificationFindingsContent ? [{
13489
+ name: "verification_findings",
13490
+ content: verificationFindingsContent,
13491
+ priority: "important"
13935
13492
  }] : []
13936
13493
  ];
13937
13494
  const assembled = assemblePrompt(fixTemplate, sections, 24e3);
@@ -14100,6 +13657,7 @@ function createImplementationOrchestrator(deps) {
14100
13657
  const findings = await getProjectFindings(db);
14101
13658
  if (findings !== "") priorFindingsContent = "Prior pipeline findings — avoid repeating these patterns:\n\n" + findings;
14102
13659
  } catch {}
13660
+ const verificationFindingsContent = renderVerificationFindingsForPrompt(verificationStore.get(storyKey));
14103
13661
  const sections = isMajorRework ? [
14104
13662
  {
14105
13663
  name: "story_content",
@@ -14125,7 +13683,12 @@ function createImplementationOrchestrator(deps) {
14125
13683
  name: "prior_findings",
14126
13684
  content: priorFindingsContent,
14127
13685
  priority: "optional"
14128
- }
13686
+ },
13687
+ ...verificationFindingsContent ? [{
13688
+ name: "verification_findings",
13689
+ content: verificationFindingsContent,
13690
+ priority: "important"
13691
+ }] : []
14129
13692
  ] : (() => {
14130
13693
  const targetedFilesContent = buildTargetedFilesContent(issueList);
14131
13694
  return [
@@ -14153,7 +13716,12 @@ function createImplementationOrchestrator(deps) {
14153
13716
  name: "prior_findings",
14154
13717
  content: priorFindingsContent,
14155
13718
  priority: "optional"
14156
- }
13719
+ },
13720
+ ...verificationFindingsContent ? [{
13721
+ name: "verification_findings",
13722
+ content: verificationFindingsContent,
13723
+ priority: "important"
13724
+ }] : []
14157
13725
  ];
14158
13726
  })();
14159
13727
  const assembled = assemblePrompt(fixTemplate, sections, 24e3);
@@ -44272,4 +43840,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
44272
43840
 
44273
43841
  //#endregion
44274
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 };
44275
- //# sourceMappingURL=run-8UnjRlkK.js.map
43843
+ //# sourceMappingURL=run-ofO9AWFc.js.map
@@ -1,8 +1,8 @@
1
- import "./health-BfeoutPu.js";
1
+ import "./health-DHLR9Iz1.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
4
  import "./dist-srr3BfCc.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-8UnjRlkK.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-ofO9AWFc.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.3",
3
+ "version": "0.20.5",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -17,6 +17,9 @@
17
17
  ### Prior Pipeline Findings
18
18
  {{prior_findings}}
19
19
 
20
+ ### Automated Verification Findings
21
+ {{verification_findings}}
22
+
20
23
  ---
21
24
 
22
25
  ## Mission
@@ -17,6 +17,9 @@
17
17
  ### Prior Pipeline Findings
18
18
  {{prior_findings}}
19
19
 
20
+ ### Automated Verification Findings
21
+ {{verification_findings}}
22
+
20
23
  ---
21
24
 
22
25
  ## Mission