substrate-ai 0.20.61 → 0.20.63
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 +575 -131
- package/dist/{health-BoXxsFSF.js → health-C-KOZrFJ.js} +227 -4
- package/dist/{health-FZVOBYND.js → health-CJqd1FzY.js} +1 -1
- package/dist/index.d.ts +28 -0
- package/dist/{run-CRz08RrU.js → run-CHUFlRbH.js} +31 -2
- package/dist/{run-BxfeSz6G.js → run-Z_-caE_i.js} +2 -2
- package/package.json +2 -2
|
@@ -7,7 +7,7 @@ import { readFile } from "fs/promises";
|
|
|
7
7
|
import { EventEmitter } from "node:events";
|
|
8
8
|
import { YAMLException, load } from "js-yaml";
|
|
9
9
|
import { existsSync, promises, readFileSync, readdirSync, statSync } from "node:fs";
|
|
10
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
10
|
+
import { execSync, spawn, spawnSync } from "node:child_process";
|
|
11
11
|
import * as path$2 from "node:path";
|
|
12
12
|
import { basename as basename$1, dirname as dirname$1, join as join$1, resolve as resolve$1 } from "node:path";
|
|
13
13
|
import { z } from "zod";
|
|
@@ -5548,6 +5548,227 @@ function createDefaultVerificationPipeline(bus, config) {
|
|
|
5548
5548
|
return new VerificationPipeline(bus, checks);
|
|
5549
5549
|
}
|
|
5550
5550
|
|
|
5551
|
+
//#endregion
|
|
5552
|
+
//#region packages/sdlc/dist/verification/cross-story-race-recovery.js
|
|
5553
|
+
/**
|
|
5554
|
+
* Detect stories whose verification results were recorded before concurrent
|
|
5555
|
+
* story commits landed.
|
|
5556
|
+
*
|
|
5557
|
+
* Stale-verification boundary condition:
|
|
5558
|
+
* t.committedAt > s.verifiedAt
|
|
5559
|
+
* AND
|
|
5560
|
+
* t.modifiedFiles ∩ (s.modifiedFiles ∪ s.testFiles) ≠ ∅
|
|
5561
|
+
*
|
|
5562
|
+
* Where:
|
|
5563
|
+
* s = the story we're checking for staleness
|
|
5564
|
+
* t = another story in the batch that may have committed after s verified
|
|
5565
|
+
*
|
|
5566
|
+
* Pure function — all data must be pre-resolved in the `batch` entries.
|
|
5567
|
+
* Returns empty array when no stale stories are detected (idempotent, no-op).
|
|
5568
|
+
*
|
|
5569
|
+
* @param batch Pre-resolved story data for all stories in the concurrent batch.
|
|
5570
|
+
* @param _manifest Manifest instance (accepted for API symmetry; not used in pure logic).
|
|
5571
|
+
* @returns Array of story keys that have stale verification results.
|
|
5572
|
+
*/
|
|
5573
|
+
function detectStaleVerifications(batch, _manifest) {
|
|
5574
|
+
if (batch.length < 2) return [];
|
|
5575
|
+
const staleKeys = [];
|
|
5576
|
+
for (const s of batch) {
|
|
5577
|
+
const sVerifiedAt = s.verifiedAt;
|
|
5578
|
+
if (sVerifiedAt === void 0) continue;
|
|
5579
|
+
const sPrimaryFiles = s.modifiedFiles ?? s.verificationResultFiles ?? [];
|
|
5580
|
+
const sTestFiles = s.testFiles ?? [];
|
|
5581
|
+
const sAllFiles = new Set([...sPrimaryFiles, ...sTestFiles]);
|
|
5582
|
+
if (sAllFiles.size === 0) continue;
|
|
5583
|
+
for (const t of batch) {
|
|
5584
|
+
if (t.storyKey === s.storyKey) continue;
|
|
5585
|
+
const tCommittedAt = t.committedAt;
|
|
5586
|
+
if (tCommittedAt === void 0) continue;
|
|
5587
|
+
let tTime, sTime;
|
|
5588
|
+
try {
|
|
5589
|
+
tTime = new Date(tCommittedAt).getTime();
|
|
5590
|
+
sTime = new Date(sVerifiedAt).getTime();
|
|
5591
|
+
} catch {
|
|
5592
|
+
continue;
|
|
5593
|
+
}
|
|
5594
|
+
if (isNaN(tTime) || isNaN(sTime)) continue;
|
|
5595
|
+
if (tTime <= sTime) continue;
|
|
5596
|
+
const tFiles = t.modifiedFiles ?? [];
|
|
5597
|
+
const hasOverlap = tFiles.some((f) => sAllFiles.has(f));
|
|
5598
|
+
if (hasOverlap) {
|
|
5599
|
+
staleKeys.push(s.storyKey);
|
|
5600
|
+
break;
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
return staleKeys;
|
|
5605
|
+
}
|
|
5606
|
+
/**
|
|
5607
|
+
* Resolves the commit timestamp for a story's implementation commit.
|
|
5608
|
+
*
|
|
5609
|
+
* Uses the canonical `feat(story-<storyKey>):` commit message pattern to
|
|
5610
|
+
* locate the story's auto-commit in git history.
|
|
5611
|
+
*
|
|
5612
|
+
* @param storyKey Story key (e.g. "70-1")
|
|
5613
|
+
* @param workingDir Absolute path to the git repo root
|
|
5614
|
+
* @returns ISO-8601 commit timestamp string, or `undefined` if not found
|
|
5615
|
+
*/
|
|
5616
|
+
function CommittedAtResolver(storyKey, workingDir) {
|
|
5617
|
+
try {
|
|
5618
|
+
const result = execSync(`git log --format=%cI --grep="feat(story-${storyKey}):" -1`, {
|
|
5619
|
+
cwd: workingDir,
|
|
5620
|
+
encoding: "utf-8",
|
|
5621
|
+
stdio: [
|
|
5622
|
+
"ignore",
|
|
5623
|
+
"pipe",
|
|
5624
|
+
"pipe"
|
|
5625
|
+
]
|
|
5626
|
+
}).trim();
|
|
5627
|
+
return result.length > 0 ? result : void 0;
|
|
5628
|
+
} catch {
|
|
5629
|
+
return void 0;
|
|
5630
|
+
}
|
|
5631
|
+
}
|
|
5632
|
+
/**
|
|
5633
|
+
* Cross-story race recovery action handler.
|
|
5634
|
+
*
|
|
5635
|
+
* Orchestrates the full recovery arc for stories with stale verification
|
|
5636
|
+
* results caused by concurrent story commits landing after verification ran:
|
|
5637
|
+
*
|
|
5638
|
+
* 1. Resolves `committedAt` for each batch story via git log.
|
|
5639
|
+
* 2. Enriches BatchEntry[] from manifest per_story_state when fields absent.
|
|
5640
|
+
* 3. Calls `detectStaleVerifications` to identify stale story keys.
|
|
5641
|
+
* 4. Returns `{ noStale: true }` immediately when none are stale (idempotent).
|
|
5642
|
+
* 5. For each stale story:
|
|
5643
|
+
* a. Transitions status to `verification-stale` in manifest.
|
|
5644
|
+
* b. Re-runs `createDefaultVerificationPipeline` against current tree.
|
|
5645
|
+
* c. On pass: transitions to `complete`, emits `pipeline:cross-story-race-recovered`.
|
|
5646
|
+
* d. On fail: transitions to `failed` with `verification_re_run: true`,
|
|
5647
|
+
* emits `pipeline:cross-story-race-still-failed`.
|
|
5648
|
+
*
|
|
5649
|
+
* Implements AC3 canonical-helper discipline: all state reads use RunManifest,
|
|
5650
|
+
* all persistence uses the injected adapter. No direct file reads of manifest.json.
|
|
5651
|
+
*
|
|
5652
|
+
* @param input Recovery input (see StaleVerificationRecoveryInput)
|
|
5653
|
+
* @returns Recovery summary
|
|
5654
|
+
*/
|
|
5655
|
+
async function runStaleVerificationRecovery(input) {
|
|
5656
|
+
const { runId, batch, workingDir, bus, manifest } = input;
|
|
5657
|
+
const enrichedBatch = [];
|
|
5658
|
+
let manifestData = null;
|
|
5659
|
+
try {
|
|
5660
|
+
manifestData = await manifest.read();
|
|
5661
|
+
} catch {}
|
|
5662
|
+
for (const entry of batch) {
|
|
5663
|
+
const committedAt = CommittedAtResolver(entry.storyKey, workingDir);
|
|
5664
|
+
let verifiedAt = entry.verifiedAt;
|
|
5665
|
+
let modifiedFiles = entry.modifiedFiles;
|
|
5666
|
+
let testFiles = entry.testFiles;
|
|
5667
|
+
let verificationResultFiles = entry.verificationResultFiles;
|
|
5668
|
+
if (manifestData !== null) {
|
|
5669
|
+
const perStory = manifestData.per_story_state[entry.storyKey];
|
|
5670
|
+
if (perStory !== void 0) {
|
|
5671
|
+
if (verifiedAt === void 0) verifiedAt = perStory.completed_at;
|
|
5672
|
+
if (modifiedFiles === void 0 && perStory.dev_story_signals?.files_modified !== void 0) modifiedFiles = perStory.dev_story_signals.files_modified;
|
|
5673
|
+
if (verificationResultFiles === void 0 && perStory.dev_story_signals?.files_modified !== void 0) verificationResultFiles = perStory.dev_story_signals.files_modified;
|
|
5674
|
+
}
|
|
5675
|
+
}
|
|
5676
|
+
const enriched = { storyKey: entry.storyKey };
|
|
5677
|
+
if (committedAt !== void 0) enriched.committedAt = committedAt;
|
|
5678
|
+
if (verifiedAt !== void 0) enriched.verifiedAt = verifiedAt;
|
|
5679
|
+
if (modifiedFiles !== void 0) enriched.modifiedFiles = modifiedFiles;
|
|
5680
|
+
if (testFiles !== void 0) enriched.testFiles = testFiles;
|
|
5681
|
+
if (verificationResultFiles !== void 0) enriched.verificationResultFiles = verificationResultFiles;
|
|
5682
|
+
enrichedBatch.push(enriched);
|
|
5683
|
+
}
|
|
5684
|
+
const staleKeys = detectStaleVerifications(enrichedBatch, manifest);
|
|
5685
|
+
if (staleKeys.length === 0) return {
|
|
5686
|
+
recovered: [],
|
|
5687
|
+
stillFailed: [],
|
|
5688
|
+
noStale: true
|
|
5689
|
+
};
|
|
5690
|
+
const recovered = [];
|
|
5691
|
+
const stillFailed = [];
|
|
5692
|
+
const verificationPipeline = createDefaultVerificationPipeline(bus);
|
|
5693
|
+
for (const storyKey of staleKeys) {
|
|
5694
|
+
const recoveryStart = Date.now();
|
|
5695
|
+
let originalFindings = [];
|
|
5696
|
+
if (manifestData !== null) {
|
|
5697
|
+
const perStory = manifestData.per_story_state[storyKey];
|
|
5698
|
+
if (perStory?.verification_result !== void 0) originalFindings = (perStory.verification_result.checks ?? []).flatMap((c) => c.findings ?? []);
|
|
5699
|
+
}
|
|
5700
|
+
await manifest.patchStoryState(storyKey, { status: "verification-stale" }).catch(() => {});
|
|
5701
|
+
let commitSha;
|
|
5702
|
+
try {
|
|
5703
|
+
commitSha = execSync("git rev-parse HEAD", {
|
|
5704
|
+
cwd: workingDir,
|
|
5705
|
+
encoding: "utf-8",
|
|
5706
|
+
stdio: [
|
|
5707
|
+
"ignore",
|
|
5708
|
+
"pipe",
|
|
5709
|
+
"pipe"
|
|
5710
|
+
]
|
|
5711
|
+
}).trim();
|
|
5712
|
+
} catch {
|
|
5713
|
+
commitSha = "unknown";
|
|
5714
|
+
}
|
|
5715
|
+
let storyContent;
|
|
5716
|
+
try {
|
|
5717
|
+
const artifactsDir = `${workingDir}/_bmad-output/implementation-artifacts`;
|
|
5718
|
+
if (existsSync(artifactsDir)) {
|
|
5719
|
+
const STALE_SUFFIX = /\.stale-\d+\.md$/;
|
|
5720
|
+
const files = readdirSync(artifactsDir);
|
|
5721
|
+
const match = files.find((f) => f.startsWith(`${storyKey}-`) && f.endsWith(".md") && !STALE_SUFFIX.test(f));
|
|
5722
|
+
if (match !== void 0) storyContent = readFileSync(`${artifactsDir}/${match}`, "utf-8");
|
|
5723
|
+
}
|
|
5724
|
+
} catch {}
|
|
5725
|
+
const verifContext = {
|
|
5726
|
+
storyKey,
|
|
5727
|
+
workingDir,
|
|
5728
|
+
commitSha,
|
|
5729
|
+
timeout: 6e4,
|
|
5730
|
+
...storyContent !== void 0 ? { storyContent } : {}
|
|
5731
|
+
};
|
|
5732
|
+
const freshSummary = await verificationPipeline.run(verifContext, "A");
|
|
5733
|
+
const freshFindings = (freshSummary.checks ?? []).flatMap((c) => c.findings ?? []);
|
|
5734
|
+
const recoveryDurationMs = Date.now() - recoveryStart;
|
|
5735
|
+
if (freshSummary.status === "pass" || freshSummary.status === "warn") {
|
|
5736
|
+
await manifest.patchStoryState(storyKey, {
|
|
5737
|
+
status: "complete",
|
|
5738
|
+
verification_result: freshSummary,
|
|
5739
|
+
completed_at: new Date().toISOString()
|
|
5740
|
+
}).catch(() => {});
|
|
5741
|
+
bus.emit("pipeline:cross-story-race-recovered", {
|
|
5742
|
+
runId,
|
|
5743
|
+
storyKey,
|
|
5744
|
+
originalFindings,
|
|
5745
|
+
freshFindings,
|
|
5746
|
+
recoveryDurationMs
|
|
5747
|
+
});
|
|
5748
|
+
recovered.push(storyKey);
|
|
5749
|
+
} else {
|
|
5750
|
+
await manifest.patchStoryState(storyKey, {
|
|
5751
|
+
status: "failed",
|
|
5752
|
+
verification_result: freshSummary,
|
|
5753
|
+
verification_re_run: true,
|
|
5754
|
+
completed_at: new Date().toISOString()
|
|
5755
|
+
}).catch(() => {});
|
|
5756
|
+
bus.emit("pipeline:cross-story-race-still-failed", {
|
|
5757
|
+
runId,
|
|
5758
|
+
storyKey,
|
|
5759
|
+
freshFindings,
|
|
5760
|
+
recoveryDurationMs
|
|
5761
|
+
});
|
|
5762
|
+
stillFailed.push(storyKey);
|
|
5763
|
+
}
|
|
5764
|
+
}
|
|
5765
|
+
return {
|
|
5766
|
+
recovered,
|
|
5767
|
+
stillFailed,
|
|
5768
|
+
noStale: false
|
|
5769
|
+
};
|
|
5770
|
+
}
|
|
5771
|
+
|
|
5551
5772
|
//#endregion
|
|
5552
5773
|
//#region packages/sdlc/dist/run-model/cli-flags.js
|
|
5553
5774
|
/**
|
|
@@ -5704,6 +5925,7 @@ const PerStoryStatusSchema = z.union([
|
|
|
5704
5925
|
z.literal("verification-failed"),
|
|
5705
5926
|
z.literal("gated"),
|
|
5706
5927
|
z.literal("skipped"),
|
|
5928
|
+
z.literal("verification-stale"),
|
|
5707
5929
|
z.string()
|
|
5708
5930
|
]);
|
|
5709
5931
|
/**
|
|
@@ -5735,7 +5957,8 @@ const PerStoryStateSchema = z.object({
|
|
|
5735
5957
|
z.literal("state-integrating"),
|
|
5736
5958
|
z.literal("both"),
|
|
5737
5959
|
z.string()
|
|
5738
|
-
]).optional()
|
|
5960
|
+
]).optional(),
|
|
5961
|
+
verification_re_run: z.boolean().optional()
|
|
5739
5962
|
});
|
|
5740
5963
|
|
|
5741
5964
|
//#endregion
|
|
@@ -7340,5 +7563,5 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
|
|
|
7340
7563
|
}
|
|
7341
7564
|
|
|
7342
7565
|
//#endregion
|
|
7343
|
-
export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, __commonJS, __require, __toESM, aggregateProbeAuthorMetrics, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, createStateStore, detectCycles, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, parseRuntimeProbes, readCurrentRunId, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runHealthAction, validateStoryKey };
|
|
7344
|
-
//# sourceMappingURL=health-
|
|
7566
|
+
export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, __commonJS, __require, __toESM, aggregateProbeAuthorMetrics, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, createStateStore, detectCycles, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, parseRuntimeProbes, readCurrentRunId, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runHealthAction, runStaleVerificationRecovery, validateStoryKey };
|
|
7567
|
+
//# sourceMappingURL=health-C-KOZrFJ.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-
|
|
1
|
+
import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-C-KOZrFJ.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./dist-W2emvN3F.js";
|
|
4
4
|
import "./decisions-C0pz9Clx.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -2479,6 +2479,34 @@ interface OrchestratorEvents {
|
|
|
2479
2479
|
/** Hash computed from the current source epic's AC section */
|
|
2480
2480
|
currentHash: string;
|
|
2481
2481
|
};
|
|
2482
|
+
/**
|
|
2483
|
+
* Cross-story race recovery succeeded: fresh verification passed for a story
|
|
2484
|
+
* whose original result was stale due to a concurrent story committing after
|
|
2485
|
+
* the original verification ran.
|
|
2486
|
+
*
|
|
2487
|
+
* Story 70-1. Motivating incidents: Epic 66 (run a832487a), Epic 67 (run a59e4c96).
|
|
2488
|
+
* Mirror of CoreEvents['pipeline:cross-story-race-recovered']; both must stay in sync.
|
|
2489
|
+
*/
|
|
2490
|
+
'pipeline:cross-story-race-recovered': {
|
|
2491
|
+
runId: string;
|
|
2492
|
+
storyKey: string;
|
|
2493
|
+
originalFindings: unknown[];
|
|
2494
|
+
freshFindings: unknown[];
|
|
2495
|
+
recoveryDurationMs: number;
|
|
2496
|
+
};
|
|
2497
|
+
/**
|
|
2498
|
+
* Cross-story race recovery completed but fresh verification still failed:
|
|
2499
|
+
* the story genuinely has issues that are not attributable to the race condition.
|
|
2500
|
+
*
|
|
2501
|
+
* Story 70-1. Motivating incidents: Epic 66 (run a832487a), Epic 67 (run a59e4c96).
|
|
2502
|
+
* Mirror of CoreEvents['pipeline:cross-story-race-still-failed']; both must stay in sync.
|
|
2503
|
+
*/
|
|
2504
|
+
'pipeline:cross-story-race-still-failed': {
|
|
2505
|
+
runId: string;
|
|
2506
|
+
storyKey: string;
|
|
2507
|
+
freshFindings: unknown[];
|
|
2508
|
+
recoveryDurationMs: number;
|
|
2509
|
+
};
|
|
2482
2510
|
}
|
|
2483
2511
|
|
|
2484
2512
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-
|
|
1
|
+
import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, runStaleVerificationRecovery, validateStoryKey } from "./health-C-KOZrFJ.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-W2emvN3F.js";
|
|
@@ -15745,7 +15745,36 @@ function createImplementationOrchestrator(deps) {
|
|
|
15745
15745
|
try {
|
|
15746
15746
|
for (const rawBatchGroups of batches) {
|
|
15747
15747
|
const batchGroups = detectAndSerializeConcurrentFileCollisions(rawBatchGroups);
|
|
15748
|
+
let collisionFired = false;
|
|
15749
|
+
const collisionListener = (_evt) => {
|
|
15750
|
+
collisionFired = true;
|
|
15751
|
+
};
|
|
15752
|
+
eventBus.on("dispatch:cross-story-file-collision", collisionListener);
|
|
15748
15753
|
await runWithConcurrency(batchGroups, config.maxConcurrency);
|
|
15754
|
+
eventBus.off("dispatch:cross-story-file-collision", collisionListener);
|
|
15755
|
+
if (collisionFired && runManifest !== null && runManifest !== void 0) {
|
|
15756
|
+
const batchStoryKeys = batchGroups.flat();
|
|
15757
|
+
const batchEntries = batchStoryKeys.map((key) => ({ storyKey: key }));
|
|
15758
|
+
const runId = config.pipelineRunId ?? "unknown";
|
|
15759
|
+
try {
|
|
15760
|
+
const recoveryResult = await runStaleVerificationRecovery({
|
|
15761
|
+
runId,
|
|
15762
|
+
batch: batchEntries,
|
|
15763
|
+
workingDir: projectRoot ?? process.cwd(),
|
|
15764
|
+
bus: toSdlcEventBus(eventBus),
|
|
15765
|
+
manifest: runManifest,
|
|
15766
|
+
adapter: db
|
|
15767
|
+
});
|
|
15768
|
+
if (!recoveryResult.noStale) logger$26.info({
|
|
15769
|
+
recovered: recoveryResult.recovered,
|
|
15770
|
+
stillFailed: recoveryResult.stillFailed,
|
|
15771
|
+
recoveredCount: recoveryResult.recovered.length,
|
|
15772
|
+
stillFailedCount: recoveryResult.stillFailed.length
|
|
15773
|
+
}, "Cross-story race recovery complete");
|
|
15774
|
+
} catch (recoveryErr) {
|
|
15775
|
+
logger$26.warn({ err: recoveryErr }, "Cross-story race recovery failed (non-fatal) — pipeline continues");
|
|
15776
|
+
}
|
|
15777
|
+
}
|
|
15749
15778
|
}
|
|
15750
15779
|
} catch (err) {
|
|
15751
15780
|
stopHeartbeat();
|
|
@@ -45601,4 +45630,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
45601
45630
|
|
|
45602
45631
|
//#endregion
|
|
45603
45632
|
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, 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 };
|
|
45604
|
-
//# sourceMappingURL=run-
|
|
45633
|
+
//# sourceMappingURL=run-CHUFlRbH.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "./health-
|
|
1
|
+
import "./health-C-KOZrFJ.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
4
|
import "./dist-W2emvN3F.js";
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-CHUFlRbH.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
|
+
"version": "0.20.63",
|
|
4
4
|
"description": "Substrate — multi-agent orchestration daemon for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"agent-memory:bootstrap": "node scripts/bootstrap-agent-memory.mjs",
|
|
52
52
|
"build": "tsc --build packages/core packages/sdlc packages/factory && tsdown",
|
|
53
|
-
"postbuild": "cp -r src/cli/templates dist/cli/templates && cp src/modules/state/schema.sql dist/schema.sql && mkdir -p dist/graphs && cp packages/sdlc/graphs/sdlc-pipeline.dot dist/graphs/",
|
|
53
|
+
"postbuild": "cp -r src/cli/templates dist/cli/templates && cp src/modules/state/schema.sql dist/schema.sql && mkdir -p dist/graphs && cp packages/sdlc/graphs/sdlc-pipeline.dot dist/graphs/ && printf '#!/usr/bin/env node\\n// Wrapper so probes can invoke as dist/cli.mjs (Story 71-1).\\n// Redirect argv[1] so isMainModule detection in cli/index.js fires correctly.\\nprocess.argv[1] = new URL(\"./cli/index.js\", import.meta.url).pathname;\\nawait import(\"./cli/index.js\");\\n' > dist/cli.mjs",
|
|
54
54
|
"check:circular": "dpdm --no-warning --exit-code circular:1 packages/core/src/index.ts packages/sdlc/src/index.ts packages/factory/src/index.ts",
|
|
55
55
|
"dev": "tsx watch src/cli/index.ts",
|
|
56
56
|
"test": "vitest run --coverage",
|