substrate-ai 0.20.28 → 0.20.31
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
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { FileStateStore, RunManifest, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts } from "../health-
|
|
2
|
+
import { FileStateStore, RunManifest, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts } from "../health-B0cPyaYJ.js";
|
|
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, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-CqtWS9wF.js";
|
|
6
6
|
import "../adapter-registry-DXLMTmfD.js";
|
|
7
|
-
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-
|
|
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-C8IJQ5i5.js";
|
|
8
8
|
import "../errors-1uLGqnvr.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
@@ -3667,7 +3667,7 @@ async function runStatusAction(options) {
|
|
|
3667
3667
|
logger$12.debug({ err }, "Work graph query failed, continuing without work graph data");
|
|
3668
3668
|
}
|
|
3669
3669
|
if (run === void 0) {
|
|
3670
|
-
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-
|
|
3670
|
+
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-C6pR6QvM.js");
|
|
3671
3671
|
const substrateDirPath = join(projectRoot, ".substrate");
|
|
3672
3672
|
const processInfo = inspectProcessTree$1({
|
|
3673
3673
|
projectRoot,
|
|
@@ -5198,7 +5198,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
5198
5198
|
await initSchema(expAdapter);
|
|
5199
5199
|
const { runRunAction: runPipeline } = await import(
|
|
5200
5200
|
/* @vite-ignore */
|
|
5201
|
-
"../run-
|
|
5201
|
+
"../run-Dt5fuOCt.js"
|
|
5202
5202
|
);
|
|
5203
5203
|
const runStoryFn = async (opts) => {
|
|
5204
5204
|
const exitCode = await runPipeline({
|
|
@@ -3043,6 +3043,21 @@ var TrivialOutputCheck = class {
|
|
|
3043
3043
|
}
|
|
3044
3044
|
const count = context.outputTokenCount;
|
|
3045
3045
|
if (count < this.threshold) {
|
|
3046
|
+
const devResult = context.devStoryResult;
|
|
3047
|
+
const recoveredAfterCheckpoint = devResult?.result === "success" && Array.isArray(devResult.files_modified) && devResult.files_modified.length > 0;
|
|
3048
|
+
if (recoveredAfterCheckpoint) {
|
|
3049
|
+
const findings$1 = [{
|
|
3050
|
+
category: "trivial-output",
|
|
3051
|
+
severity: "warn",
|
|
3052
|
+
message: `output token count ${count} is below threshold ${this.threshold} but dev-story signals success with ${devResult.files_modified.length} files modified — likely checkpoint-recovered dispatch (last dispatch was bookkeeping; earlier dispatches did the work). Verdict downgraded to warn so dispatches that legitimately recovered from checkpoint aren't blocked by the trivial-output gate.`
|
|
3053
|
+
}];
|
|
3054
|
+
return {
|
|
3055
|
+
status: "warn",
|
|
3056
|
+
details: renderFindings(findings$1),
|
|
3057
|
+
duration_ms: Date.now() - start,
|
|
3058
|
+
findings: findings$1
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3046
3061
|
const findings = [{
|
|
3047
3062
|
category: "trivial-output",
|
|
3048
3063
|
severity: "error",
|
|
@@ -3090,12 +3105,36 @@ function addExplicitAcRefs(text, ids) {
|
|
|
3090
3105
|
}
|
|
3091
3106
|
function extractAcceptanceSection(storyContent) {
|
|
3092
3107
|
const lines = storyContent.split(/\r?\n/);
|
|
3093
|
-
|
|
3108
|
+
let mode;
|
|
3109
|
+
const start = lines.findIndex((line) => {
|
|
3110
|
+
const trimmed = line.trim();
|
|
3111
|
+
if (/^##\s+Acceptance Criteria\s*$/i.test(trimmed)) {
|
|
3112
|
+
mode = "heading";
|
|
3113
|
+
return true;
|
|
3114
|
+
}
|
|
3115
|
+
if (/^\*\*Acceptance Criteria\*\*:?/i.test(trimmed)) {
|
|
3116
|
+
mode = "bold";
|
|
3117
|
+
return true;
|
|
3118
|
+
}
|
|
3119
|
+
return false;
|
|
3120
|
+
});
|
|
3094
3121
|
if (start === -1) return void 0;
|
|
3095
3122
|
let end = lines.length;
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3123
|
+
const BOLD_PARA_BOUNDARY = /^\*\*[A-Za-z][A-Za-z\s]*\*\*:/;
|
|
3124
|
+
for (let i = start + 1; i < lines.length; i += 1) {
|
|
3125
|
+
const line = lines[i] ?? "";
|
|
3126
|
+
if (/^##\s+\S/.test(line)) {
|
|
3127
|
+
end = i;
|
|
3128
|
+
break;
|
|
3129
|
+
}
|
|
3130
|
+
if (/^###\s+Story\s+/i.test(line)) {
|
|
3131
|
+
end = i;
|
|
3132
|
+
break;
|
|
3133
|
+
}
|
|
3134
|
+
if (mode === "bold" && BOLD_PARA_BOUNDARY.test(line.trim())) {
|
|
3135
|
+
end = i;
|
|
3136
|
+
break;
|
|
3137
|
+
}
|
|
3099
3138
|
}
|
|
3100
3139
|
return lines.slice(start + 1, end).join("\n");
|
|
3101
3140
|
}
|
|
@@ -3103,18 +3142,33 @@ function extractAcceptanceSection(storyContent) {
|
|
|
3103
3142
|
* Extract normalized AC ids from story markdown.
|
|
3104
3143
|
*
|
|
3105
3144
|
* Supports the BMAD default format (`### AC1:`), explicit references such as
|
|
3106
|
-
* `AC: #1`,
|
|
3145
|
+
* `AC: #1`, plain numbered criteria inside the Acceptance Criteria section,
|
|
3146
|
+
* and (Story 61-4) bullet-format ACs where each bullet line under the
|
|
3147
|
+
* Acceptance Criteria section becomes an implicit AC numbered by position
|
|
3148
|
+
* (first bullet → AC1, second → AC2, etc.). Bullet-format inference fires
|
|
3149
|
+
* only when no numbered or explicit-ref ACs were found, so projects mixing
|
|
3150
|
+
* conventions favor the explicit signal.
|
|
3107
3151
|
*/
|
|
3108
3152
|
function extractAcceptanceCriteriaIds(storyContent) {
|
|
3109
3153
|
const ids = new Set();
|
|
3110
3154
|
const acceptanceSection = extractAcceptanceSection(storyContent);
|
|
3111
3155
|
const textToScan = acceptanceSection ?? storyContent;
|
|
3112
3156
|
addExplicitAcRefs(textToScan, ids);
|
|
3113
|
-
if (acceptanceSection !== void 0)
|
|
3114
|
-
const
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3157
|
+
if (acceptanceSection !== void 0) {
|
|
3158
|
+
for (const line of acceptanceSection.split(/\r?\n/)) {
|
|
3159
|
+
const match = line.match(NUMBERED_CRITERION);
|
|
3160
|
+
if (match?.[1] !== void 0) {
|
|
3161
|
+
const id = normalizeAcId(match[1]);
|
|
3162
|
+
if (id !== void 0) ids.add(id);
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
if (ids.size === 0) {
|
|
3166
|
+
let bulletPosition = 0;
|
|
3167
|
+
for (const line of acceptanceSection.split(/\r?\n/)) if (/^\s*[-*]\s+\S/.test(line) && !NUMBERED_CRITERION.test(line)) {
|
|
3168
|
+
bulletPosition += 1;
|
|
3169
|
+
const id = normalizeAcId(String(bulletPosition));
|
|
3170
|
+
if (id !== void 0) ids.add(id);
|
|
3171
|
+
}
|
|
3118
3172
|
}
|
|
3119
3173
|
}
|
|
3120
3174
|
return sortAcIds(ids);
|
|
@@ -6067,4 +6121,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
|
|
|
6067
6121
|
|
|
6068
6122
|
//#endregion
|
|
6069
6123
|
export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDING_COUNTS, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, createStateStore, detectCycles, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, runHealthAction, validateStoryKey };
|
|
6070
|
-
//# sourceMappingURL=health-
|
|
6124
|
+
//# sourceMappingURL=health-B0cPyaYJ.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-B0cPyaYJ.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./dist-CqtWS9wF.js";
|
|
4
4
|
import "./decisions-C0pz9Clx.js";
|
|
@@ -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, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-
|
|
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-B0cPyaYJ.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-CqtWS9wF.js";
|
|
@@ -6248,28 +6248,53 @@ async function getArchConstraints$3(deps) {
|
|
|
6248
6248
|
}
|
|
6249
6249
|
}
|
|
6250
6250
|
/**
|
|
6251
|
-
* File-based fallback: read epic shard from _bmad-output
|
|
6252
|
-
*
|
|
6253
|
-
*
|
|
6251
|
+
* File-based fallback: read epic shard from _bmad-output planning files.
|
|
6252
|
+
*
|
|
6253
|
+
* Lookup order:
|
|
6254
|
+
* 1. Consolidated `_bmad-output/planning-artifacts/epics.md` — the
|
|
6255
|
+
* multi-epic-per-file convention used by external projects (strata,
|
|
6256
|
+
* ynab, NextGen Ticketing). Section extracted via heading regex.
|
|
6257
|
+
* 2. Consolidated `_bmad-output/epics.md` — alternate location.
|
|
6258
|
+
* 3. Per-epic file `_bmad-output/planning-artifacts/epic-<epicNum>-*.md`
|
|
6259
|
+
* — the per-epic convention substrate's own planning artifacts use
|
|
6260
|
+
* (Story 61-1). Returns the entire file content as the shard;
|
|
6261
|
+
* downstream `extractStorySection` callers narrow to the per-story
|
|
6262
|
+
* section by `### Story X:` heading match.
|
|
6263
|
+
*
|
|
6264
|
+
* Returns the matched section content, or empty string if no path matches.
|
|
6254
6265
|
*/
|
|
6255
6266
|
function readEpicShardFromFile(projectRoot, epicId) {
|
|
6256
6267
|
try {
|
|
6257
6268
|
const candidates = [join$1(projectRoot, "_bmad-output", "planning-artifacts", "epics.md"), join$1(projectRoot, "_bmad-output", "epics.md")];
|
|
6258
6269
|
const epicsPath = candidates.find((p) => existsSync(p));
|
|
6259
|
-
if (!epicsPath) return "";
|
|
6260
|
-
const content = readFileSync(epicsPath, "utf-8");
|
|
6261
6270
|
const epicNum = epicId.replace(/^epic-/i, "");
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6271
|
+
if (epicsPath) {
|
|
6272
|
+
const content = readFileSync(epicsPath, "utf-8");
|
|
6273
|
+
const headingPattern = new RegExp(`^(#{2,4})\\s+(?:Epic\\s+)?${epicNum}[.:\\s]`, "m");
|
|
6274
|
+
const headingMatch = headingPattern.exec(content);
|
|
6275
|
+
if (headingMatch) {
|
|
6276
|
+
const startIdx = headingMatch.index;
|
|
6277
|
+
const headingLevel = headingMatch[1].length;
|
|
6278
|
+
const hashes = "#".repeat(headingLevel);
|
|
6279
|
+
const endPattern = new RegExp(`\\n${hashes}\\s`, "g");
|
|
6280
|
+
endPattern.lastIndex = startIdx + headingMatch[0].length;
|
|
6281
|
+
const endMatch = endPattern.exec(content);
|
|
6282
|
+
const endIdx = endMatch ? endMatch.index : content.length;
|
|
6283
|
+
return content.slice(startIdx, endIdx).trim();
|
|
6284
|
+
}
|
|
6285
|
+
}
|
|
6286
|
+
const planningDir = join$1(projectRoot, "_bmad-output", "planning-artifacts");
|
|
6287
|
+
if (existsSync(planningDir)) try {
|
|
6288
|
+
const entries = readdirSync(planningDir, { encoding: "utf-8" });
|
|
6289
|
+
const perEpicPattern = new RegExp(`^epic-${epicNum}-.*\\.md$`);
|
|
6290
|
+
const matches = entries.filter((e) => perEpicPattern.test(e)).sort();
|
|
6291
|
+
if (matches.length > 0) {
|
|
6292
|
+
const perEpicPath = join$1(planningDir, matches[0]);
|
|
6293
|
+
const content = readFileSync(perEpicPath, "utf-8");
|
|
6294
|
+
return content.trim();
|
|
6295
|
+
}
|
|
6296
|
+
} catch {}
|
|
6297
|
+
return "";
|
|
6273
6298
|
} catch (err) {
|
|
6274
6299
|
logger$18.warn({
|
|
6275
6300
|
epicId,
|
|
@@ -11078,6 +11103,76 @@ function findEpicFiles(projectRoot) {
|
|
|
11078
11103
|
}
|
|
11079
11104
|
}
|
|
11080
11105
|
/**
|
|
11106
|
+
* Story 61-3: find the epic file relevant to a specific story.
|
|
11107
|
+
*
|
|
11108
|
+
* Sibling to `findEpicsFile` for the verification path
|
|
11109
|
+
* (`assembleVerificationContext` populates `sourceEpicContent` from this).
|
|
11110
|
+
* `findEpicsFile` only checks the consolidated convention (`epics.md`)
|
|
11111
|
+
* → returns undefined for projects using per-epic files (substrate's own
|
|
11112
|
+
* planning artifacts), causing `SourceAcFidelityCheck` to silently skip
|
|
11113
|
+
* with a `source-ac-source-unavailable` warn — exactly what happened on
|
|
11114
|
+
* the 60-12 redispatch (run 4700c6e8, 2026-04-27).
|
|
11115
|
+
*
|
|
11116
|
+
* Story 61-3 v2 (post-round-3): the v1 implementation honored
|
|
11117
|
+
* findEpicsFile's returned path without verifying it contained the
|
|
11118
|
+
* requested story. substrate's own findEpicsFile glob-matches
|
|
11119
|
+
* `epics-and-stories-*.md` files, so for projects with stale consolidated
|
|
11120
|
+
* files (substrate has `epics-and-stories-software-factory.md` for old
|
|
11121
|
+
* epics 40-50) the function returned that path → caller's
|
|
11122
|
+
* extractStorySection found nothing for new stories → sourceEpicContent
|
|
11123
|
+
* stayed undefined. This rev verifies file contains the story (via the
|
|
11124
|
+
* SAME `### Story X:` heading match the caller uses) before returning,
|
|
11125
|
+
* and falls through to per-epic search if not.
|
|
11126
|
+
*
|
|
11127
|
+
* Lookup order:
|
|
11128
|
+
* 1. Consolidated epics.md (existing findEpicsFile path) — return ONLY
|
|
11129
|
+
* if file content contains a `### Story <storyKey>:` heading.
|
|
11130
|
+
* 2. Per-epic file `epic-<epicNum>-*.md` derived from storyKey's first
|
|
11131
|
+
* numeric segment (e.g. storyKey '60-12' → epicNum '60' →
|
|
11132
|
+
* `epic-60-*.md`). Per-epic files contain the entire epic so a
|
|
11133
|
+
* filename match is sufficient (no content verification needed —
|
|
11134
|
+
* mirrors readEpicShardFromFile in create-story.ts).
|
|
11135
|
+
*
|
|
11136
|
+
* Returns the matched path, or undefined if no file contains the story.
|
|
11137
|
+
*/
|
|
11138
|
+
function findEpicFileForStory(projectRoot, storyKey) {
|
|
11139
|
+
const consolidated = findEpicsFile(projectRoot);
|
|
11140
|
+
if (consolidated !== void 0) {
|
|
11141
|
+
if (fileContainsStory(consolidated, storyKey)) return consolidated;
|
|
11142
|
+
}
|
|
11143
|
+
const epicNumMatch = /^(\d+)/.exec(storyKey);
|
|
11144
|
+
if (!epicNumMatch) return void 0;
|
|
11145
|
+
const epicNum = epicNumMatch[1];
|
|
11146
|
+
const planningDir = join$1(projectRoot, "_bmad-output", "planning-artifacts");
|
|
11147
|
+
if (!existsSync(planningDir)) return void 0;
|
|
11148
|
+
try {
|
|
11149
|
+
const entries = readdirSync(planningDir, { encoding: "utf-8" });
|
|
11150
|
+
const perEpicPattern = new RegExp(`^epic-${epicNum}-.*\\.md$`);
|
|
11151
|
+
const matches = entries.filter((e) => perEpicPattern.test(e)).sort();
|
|
11152
|
+
if (matches.length > 0) return join$1(planningDir, matches[0]);
|
|
11153
|
+
} catch {}
|
|
11154
|
+
return void 0;
|
|
11155
|
+
}
|
|
11156
|
+
/**
|
|
11157
|
+
* Story 61-3 v2: check whether a file's content contains a story heading
|
|
11158
|
+
* matching the storyKey, with the same separator tolerance as
|
|
11159
|
+
* `extractStorySection` (Story 60-6) so both call sites agree.
|
|
11160
|
+
*
|
|
11161
|
+
* Cheap to call (one synchronous read, one regex test); gracefully
|
|
11162
|
+
* returns false on any I/O error.
|
|
11163
|
+
*/
|
|
11164
|
+
function fileContainsStory(filePath, storyKey) {
|
|
11165
|
+
try {
|
|
11166
|
+
const content = readFileSync(filePath, "utf-8");
|
|
11167
|
+
const parts = storyKey.split(/[-._ ]/);
|
|
11168
|
+
const normalized = parts.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[-._ ]");
|
|
11169
|
+
const headingPattern = new RegExp(`^###\\s+Story\\s+${normalized}[:\\s]`, "m");
|
|
11170
|
+
return headingPattern.test(content);
|
|
11171
|
+
} catch {
|
|
11172
|
+
return false;
|
|
11173
|
+
}
|
|
11174
|
+
}
|
|
11175
|
+
/**
|
|
11081
11176
|
* Collect story keys that already have implementation artifact files.
|
|
11082
11177
|
* Scans _bmad-output/implementation-artifacts/ for files matching N-M-*.md.
|
|
11083
11178
|
*/
|
|
@@ -13831,7 +13926,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13831
13926
|
rawOutput: reviewResult.rawOutput
|
|
13832
13927
|
} : void 0;
|
|
13833
13928
|
let sourceEpicContent;
|
|
13834
|
-
const epicsPath1 =
|
|
13929
|
+
const epicsPath1 = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
|
|
13835
13930
|
if (epicsPath1) try {
|
|
13836
13931
|
const epicFull = readFileSync(epicsPath1, "utf-8");
|
|
13837
13932
|
const section = extractStorySection(epicFull, storyKey);
|
|
@@ -14104,7 +14199,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
14104
14199
|
rawOutput: reviewResult.rawOutput
|
|
14105
14200
|
} : void 0;
|
|
14106
14201
|
let sourceEpicContent2;
|
|
14107
|
-
const epicsPath2 =
|
|
14202
|
+
const epicsPath2 = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
|
|
14108
14203
|
if (epicsPath2) try {
|
|
14109
14204
|
const epicFull2 = readFileSync(epicsPath2, "utf-8");
|
|
14110
14205
|
const section2 = extractStorySection(epicFull2, storyKey);
|
|
@@ -44488,4 +44583,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
44488
44583
|
|
|
44489
44584
|
//#endregion
|
|
44490
44585
|
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 };
|
|
44491
|
-
//# sourceMappingURL=run-
|
|
44586
|
+
//# sourceMappingURL=run-C8IJQ5i5.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "./health-
|
|
1
|
+
import "./health-B0cPyaYJ.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
4
|
import "./dist-CqtWS9wF.js";
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-C8IJQ5i5.js";
|
|
6
6
|
import "./routing-CcBOCuC9.js";
|
|
7
7
|
import "./decisions-C0pz9Clx.js";
|
|
8
8
|
|