substrate-ai 0.20.18 → 0.20.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@ 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-BLObh_Ou.js";
|
|
8
8
|
import "../errors-1uLGqnvr.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
@@ -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-DPhVpqrX.js"
|
|
5202
5202
|
);
|
|
5203
5203
|
const runStoryFn = async (opts) => {
|
|
5204
5204
|
const exitCode = await runPipeline({
|
|
@@ -5737,6 +5737,19 @@ async function runCreateStory(deps, params) {
|
|
|
5737
5737
|
}
|
|
5738
5738
|
const implementationDecisions = await getImplementationDecisions(deps, pipelineRunId);
|
|
5739
5739
|
const epicShardContent = getEpicShard(implementationDecisions, epicId, deps.projectRoot, storyKey);
|
|
5740
|
+
let effectiveSourceAcHash = source_ac_hash;
|
|
5741
|
+
if (epicShardContent.length > 0) {
|
|
5742
|
+
const storySection = extractStorySection(epicShardContent, storyKey);
|
|
5743
|
+
if (storySection !== null) {
|
|
5744
|
+
const computedHash = hashSourceAcSection(storySection);
|
|
5745
|
+
if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$18.debug({
|
|
5746
|
+
storyKey,
|
|
5747
|
+
suppliedHash: source_ac_hash,
|
|
5748
|
+
computedHash
|
|
5749
|
+
}, "Orchestrator-supplied source_ac_hash differs from epic_shard content hash — using computed (Story 58-18)");
|
|
5750
|
+
effectiveSourceAcHash = computedHash;
|
|
5751
|
+
}
|
|
5752
|
+
}
|
|
5740
5753
|
const prevDevNotesContent = getPrevDevNotes(implementationDecisions, epicId);
|
|
5741
5754
|
let storyDefinitionContent = "";
|
|
5742
5755
|
try {
|
|
@@ -5780,9 +5793,9 @@ async function runCreateStory(deps, params) {
|
|
|
5780
5793
|
content: storyTemplateContent,
|
|
5781
5794
|
priority: "important"
|
|
5782
5795
|
},
|
|
5783
|
-
...
|
|
5796
|
+
...effectiveSourceAcHash !== void 0 ? [{
|
|
5784
5797
|
name: "source_ac_hash",
|
|
5785
|
-
content:
|
|
5798
|
+
content: effectiveSourceAcHash,
|
|
5786
5799
|
priority: "required"
|
|
5787
5800
|
}] : []
|
|
5788
5801
|
], TOKEN_CEILING);
|
|
@@ -5945,6 +5958,70 @@ function extractStorySection(shardContent, storyKey) {
|
|
|
5945
5958
|
return section.length > 0 ? section : null;
|
|
5946
5959
|
}
|
|
5947
5960
|
/**
|
|
5961
|
+
* Story 59-3: extract the list of named filesystem paths and filenames from
|
|
5962
|
+
* source AC text. Looks for backtick-wrapped strings that contain a path
|
|
5963
|
+
* separator OR end with a recognized source-file extension. The result is
|
|
5964
|
+
* a deduped list of names the source AC declares as part of the story's
|
|
5965
|
+
* artifact contract.
|
|
5966
|
+
*
|
|
5967
|
+
* Used by the orchestrator's pre-dev fidelity gate to detect create-story
|
|
5968
|
+
* output drift: if the agent produced a story file that doesn't reference
|
|
5969
|
+
* the source AC's named files (`adjacency-store.ts`, `wikilink-parser.ts`,
|
|
5970
|
+
* etc.) the gate fires and the orchestrator renames-to-stale + retries.
|
|
5971
|
+
*
|
|
5972
|
+
* Heuristic chosen over LLM-based fidelity check because deterministic,
|
|
5973
|
+
* fast, and the LLM-based source-ac-fidelity check still runs at
|
|
5974
|
+
* verification phase as a backstop for nuanced drift this gate can't see.
|
|
5975
|
+
*/
|
|
5976
|
+
function extractNamedPathsFromSource(shardContent) {
|
|
5977
|
+
const paths = new Set();
|
|
5978
|
+
const backtickPattern = /`([^`\n]+)`/g;
|
|
5979
|
+
const extensionPattern = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|md|json|sql|sh|toml|yaml|yml|html|css|scss|svelte)$/i;
|
|
5980
|
+
let match$2;
|
|
5981
|
+
while ((match$2 = backtickPattern.exec(shardContent)) !== null) {
|
|
5982
|
+
const candidate = match$2[1]?.trim();
|
|
5983
|
+
if (candidate === void 0 || candidate.length === 0) continue;
|
|
5984
|
+
if (candidate.includes(" ")) continue;
|
|
5985
|
+
if (!candidate.includes("/") && !extensionPattern.test(candidate)) continue;
|
|
5986
|
+
paths.add(candidate);
|
|
5987
|
+
}
|
|
5988
|
+
return Array.from(paths);
|
|
5989
|
+
}
|
|
5990
|
+
/**
|
|
5991
|
+
* Story 59-3: compute fidelity between a generated story file and the
|
|
5992
|
+
* named paths in the source AC. Drift is the fraction of source-AC paths
|
|
5993
|
+
* that do NOT appear anywhere in the story file content.
|
|
5994
|
+
*
|
|
5995
|
+
* Substring-match (not exact) — a source AC path
|
|
5996
|
+
* `packages/memory/src/graph/adjacency-store.ts` matches a story-file
|
|
5997
|
+
* mention of just the basename `adjacency-store.ts`. This is intentional:
|
|
5998
|
+
* stories sometimes shorten paths in prose while still preserving the
|
|
5999
|
+
* named file. Full-path or basename — both count as present. The drift
|
|
6000
|
+
* case we're catching (Run 9's WikilinkResolver substituting for
|
|
6001
|
+
* adjacency-store) has neither full nor basename present.
|
|
6002
|
+
*
|
|
6003
|
+
* Empty namedPaths list returns drift=0 (cannot drift from nothing).
|
|
6004
|
+
*/
|
|
6005
|
+
function computeStoryFileFidelity(storyFileContent, namedPaths) {
|
|
6006
|
+
if (namedPaths.length === 0) return {
|
|
6007
|
+
missing: [],
|
|
6008
|
+
present: [],
|
|
6009
|
+
drift: 0
|
|
6010
|
+
};
|
|
6011
|
+
const missing = [];
|
|
6012
|
+
const present = [];
|
|
6013
|
+
for (const path$3 of namedPaths) {
|
|
6014
|
+
const basename$2 = path$3.includes("/") ? path$3.slice(path$3.lastIndexOf("/") + 1) : path$3;
|
|
6015
|
+
if (storyFileContent.includes(path$3) || storyFileContent.includes(basename$2)) present.push(path$3);
|
|
6016
|
+
else missing.push(path$3);
|
|
6017
|
+
}
|
|
6018
|
+
return {
|
|
6019
|
+
missing,
|
|
6020
|
+
present,
|
|
6021
|
+
drift: missing.length / namedPaths.length
|
|
6022
|
+
};
|
|
6023
|
+
}
|
|
6024
|
+
/**
|
|
5948
6025
|
* Retrieve the epic shard from the pre-fetched implementation decisions.
|
|
5949
6026
|
*
|
|
5950
6027
|
* Lookup order (post-37-0 schema):
|
|
@@ -8774,6 +8851,13 @@ async function seedEpicShards(db, projectRoot) {
|
|
|
8774
8851
|
for (const shard of shards) {
|
|
8775
8852
|
const subsections = parseStorySubsections(shard.epicId, shard.content);
|
|
8776
8853
|
for (const subsection of subsections) {
|
|
8854
|
+
if (subsection.content.length > MAX_EPIC_SHARD_CHARS) logger$11.warn({
|
|
8855
|
+
epicId: shard.epicId,
|
|
8856
|
+
storyKey: subsection.key,
|
|
8857
|
+
originalLength: subsection.content.length,
|
|
8858
|
+
truncatedLength: MAX_EPIC_SHARD_CHARS,
|
|
8859
|
+
droppedChars: subsection.content.length - MAX_EPIC_SHARD_CHARS
|
|
8860
|
+
}, `Epic shard for ${subsection.key} exceeded ${MAX_EPIC_SHARD_CHARS}-char cap and was truncated; tail content lost from decisions store. Consider splitting the story or raising MAX_EPIC_SHARD_CHARS.`);
|
|
8777
8861
|
await createDecision(db, {
|
|
8778
8862
|
pipeline_run_id: null,
|
|
8779
8863
|
phase: "implementation",
|
|
@@ -8895,25 +8979,58 @@ function parseEpicShards(content) {
|
|
|
8895
8979
|
* Parse an epic section's content into per-story subsections.
|
|
8896
8980
|
*
|
|
8897
8981
|
* Matches story headings using three patterns:
|
|
8898
|
-
* - Markdown headings: #{2,6} Story \d
|
|
8899
|
-
* - Bold: **Story \d
|
|
8900
|
-
* - Bare key: \d
|
|
8982
|
+
* - Markdown headings: #{2,6} Story \d+[-._ ]\d+[a-z]* (e.g., ### Story 37-1, ### Story 1.1, ### Story 1.11a)
|
|
8983
|
+
* - Bold: **Story \d+[-._ ]\d+[a-z]*** (e.g., **Story 37-1**)
|
|
8984
|
+
* - Bare key: \d+[-._ ]\d+[a-z]*:\s (e.g., 37-1a: Title)
|
|
8901
8985
|
*
|
|
8902
8986
|
* Each subsection spans from its heading to the next matching heading or EOF.
|
|
8903
8987
|
*
|
|
8988
|
+
* Story 58-17: separator normalization. The original regex required `\d+-\d+`
|
|
8989
|
+
* (dash-only). Strata uses `### Story 1.1` (dot-separated) per its BMAD-template
|
|
8990
|
+
* convention. Without separator-agnostic parsing, every Story 1.X heading was
|
|
8991
|
+
* silently invisible to this parser, the matches.length === 0 fallback path
|
|
8992
|
+
* fired, the entire epic was stored as ONE per-epic decision (key=epicId)
|
|
8993
|
+
* truncated at 12K chars. All stories past the truncation point (1.6, 1.8,
|
|
8994
|
+
* 1.9+ in strata's case) were lost from the decisions store, which is the
|
|
8995
|
+
* actual root cause of strata obs_2026-04-20_001 — create-story received
|
|
8996
|
+
* empty input for those stories and hallucinated specs from domain priors.
|
|
8997
|
+
*
|
|
8998
|
+
* Epic 58-5 already made `extractStorySection` separator-agnostic for the
|
|
8999
|
+
* same reason; this matches that precedent at the seed-time parser.
|
|
9000
|
+
*
|
|
9001
|
+
* Story 59-2: alpha-suffix capture. BMAD-template projects subdivide stories
|
|
9002
|
+
* with letter suffixes (`### Story 1.11a`, `### Story 1.11b`, …) when an
|
|
9003
|
+
* original 1.11 ships broken and gets split for clarity. Strata's epics.md
|
|
9004
|
+
* uses this convention with 5 substories (1.11, 1.11a-d). 58-17's regex
|
|
9005
|
+
* `\d+[-._ ]\d+` truncated capture at the digit boundary, normalizing all
|
|
9006
|
+
* 5 to canonical key `1-11` and inserting 5 duplicate-key rows in the
|
|
9007
|
+
* decisions store (no UNIQUE constraint enforces uniqueness — strata
|
|
9008
|
+
* obs_2026-04-25_010). Trailing `[a-z]*` captures alpha suffixes of any
|
|
9009
|
+
* length; the `i` flag on the storyPattern (needed for `Story` heading
|
|
9010
|
+
* case variation) means uppercase is also accepted, so a stray `1.11A`
|
|
9011
|
+
* heading captures cleanly to key `1-11A` rather than truncating.
|
|
9012
|
+
*
|
|
9013
|
+
* Captured storyKey is normalized to canonical dash-form (`1.1` → `1-1`,
|
|
9014
|
+
* `1.11a` → `1-11a`) so decision keys are consistent regardless of the
|
|
9015
|
+
* source heading style. The separator-replace `[._ ] → -` does not touch
|
|
9016
|
+
* `[a-z]`, so trailing alpha is preserved through normalization.
|
|
9017
|
+
*
|
|
8904
9018
|
* AC3: If no story headings are found, returns a single per-epic fallback entry
|
|
8905
9019
|
* keyed by epicId — preserving backward-compatible behaviour for unstructured epics.
|
|
8906
9020
|
*/
|
|
8907
9021
|
function parseStorySubsections(epicId, epicContent) {
|
|
8908
|
-
const storyPattern = /(?:^#{2,6}\s+Story\s+(\d
|
|
9022
|
+
const storyPattern = /(?:^#{2,6}\s+Story\s+(\d+[-._ ]\d+[a-z]*)|^\*\*Story\s+(\d+[-._ ]\d+[a-z]*)\*\*|^(\d+[-._ ]\d+[a-z]*):\s)/gim;
|
|
8909
9023
|
const matches = [];
|
|
8910
9024
|
let match$2;
|
|
8911
9025
|
while ((match$2 = storyPattern.exec(epicContent)) !== null) {
|
|
8912
|
-
const
|
|
8913
|
-
if (
|
|
8914
|
-
storyKey,
|
|
8915
|
-
|
|
8916
|
-
|
|
9026
|
+
const rawKey = match$2[1] ?? match$2[2] ?? match$2[3];
|
|
9027
|
+
if (rawKey !== void 0) {
|
|
9028
|
+
const storyKey = rawKey.replace(/[._ ]/g, "-");
|
|
9029
|
+
matches.push({
|
|
9030
|
+
storyKey,
|
|
9031
|
+
startIdx: match$2.index
|
|
9032
|
+
});
|
|
9033
|
+
}
|
|
8917
9034
|
}
|
|
8918
9035
|
if (matches.length === 0) return [{
|
|
8919
9036
|
key: epicId,
|
|
@@ -11266,6 +11383,9 @@ async function autoIngestEpicsDependencies(db, projectRoot) {
|
|
|
11266
11383
|
};
|
|
11267
11384
|
}
|
|
11268
11385
|
const TITLE_OVERLAP_WARNING_THRESHOLD = .3;
|
|
11386
|
+
const FIDELITY_DRIFT_THRESHOLD = .5;
|
|
11387
|
+
const MIN_NAMED_PATHS_FOR_FIDELITY_GATE = 3;
|
|
11388
|
+
const MAX_FIDELITY_RETRIES = 2;
|
|
11269
11389
|
/**
|
|
11270
11390
|
* Map a terminal StoryPhase to the corresponding PerStoryStatus for run-manifest writes.
|
|
11271
11391
|
* Returns 'dispatched' for in-progress phases (used as a safe default).
|
|
@@ -12125,66 +12245,233 @@ function createImplementationOrchestrator(deps) {
|
|
|
12125
12245
|
await persistState();
|
|
12126
12246
|
return;
|
|
12127
12247
|
}
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
source_ac_hash: sourceAcHash
|
|
12145
|
-
});
|
|
12146
|
-
endPhase(storyKey, "create-story");
|
|
12147
|
-
eventBus.emit("orchestrator:story-phase-complete", {
|
|
12148
|
-
storyKey,
|
|
12149
|
-
phase: "IN_STORY_CREATION",
|
|
12150
|
-
result: createResult
|
|
12151
|
-
});
|
|
12152
|
-
if (config.pipelineRunId !== void 0 && createResult.tokenUsage !== void 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
12153
|
-
phase: "create-story",
|
|
12154
|
-
agent: "create-story",
|
|
12155
|
-
input_tokens: createResult.tokenUsage.input,
|
|
12156
|
-
output_tokens: createResult.tokenUsage.output,
|
|
12157
|
-
cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
|
|
12158
|
-
metadata: JSON.stringify({ storyKey })
|
|
12159
|
-
})).catch((tokenErr) => logger$24.warn({
|
|
12160
|
-
storyKey,
|
|
12161
|
-
err: tokenErr
|
|
12162
|
-
}, "Failed to record create-story token usage"));
|
|
12163
|
-
await persistState();
|
|
12164
|
-
if (createResult.result === "failed") {
|
|
12165
|
-
const errMsg = createResult.error ?? "create-story failed";
|
|
12166
|
-
const stderrSnippet = errMsg.includes("--- stderr ---") ? errMsg.slice(errMsg.indexOf("--- stderr ---") + 15, errMsg.indexOf("--- stderr ---") + 515) : errMsg.slice(0, 500);
|
|
12167
|
-
logger$24.error({
|
|
12248
|
+
let fidelityRetries = 0;
|
|
12249
|
+
while (storyFilePath === void 0) {
|
|
12250
|
+
try {
|
|
12251
|
+
incrementDispatches(storyKey);
|
|
12252
|
+
const dispatchStartMs = Date.now();
|
|
12253
|
+
const createResult = await runCreateStory({
|
|
12254
|
+
db,
|
|
12255
|
+
pack,
|
|
12256
|
+
contextCompiler,
|
|
12257
|
+
dispatcher,
|
|
12258
|
+
projectRoot,
|
|
12259
|
+
tokenCeilings,
|
|
12260
|
+
otlpEndpoint: _otlpEndpoint,
|
|
12261
|
+
agentId
|
|
12262
|
+
}, {
|
|
12263
|
+
epicId: storyKey.split("-")[0] ?? storyKey,
|
|
12168
12264
|
storyKey,
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
updateStory(storyKey, {
|
|
12172
|
-
phase: "ESCALATED",
|
|
12173
|
-
error: errMsg,
|
|
12174
|
-
completedAt: new Date().toISOString()
|
|
12265
|
+
pipelineRunId: config.pipelineRunId,
|
|
12266
|
+
source_ac_hash: sourceAcHash
|
|
12175
12267
|
});
|
|
12176
|
-
|
|
12177
|
-
|
|
12268
|
+
endPhase(storyKey, "create-story");
|
|
12269
|
+
eventBus.emit("orchestrator:story-phase-complete", {
|
|
12178
12270
|
storyKey,
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
issues: [errMsg]
|
|
12271
|
+
phase: "IN_STORY_CREATION",
|
|
12272
|
+
result: createResult
|
|
12182
12273
|
});
|
|
12274
|
+
if (config.pipelineRunId !== void 0 && createResult.tokenUsage !== void 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
12275
|
+
phase: "create-story",
|
|
12276
|
+
agent: "create-story",
|
|
12277
|
+
input_tokens: createResult.tokenUsage.input,
|
|
12278
|
+
output_tokens: createResult.tokenUsage.output,
|
|
12279
|
+
cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
|
|
12280
|
+
metadata: JSON.stringify({ storyKey })
|
|
12281
|
+
})).catch((tokenErr) => logger$24.warn({
|
|
12282
|
+
storyKey,
|
|
12283
|
+
err: tokenErr
|
|
12284
|
+
}, "Failed to record create-story token usage"));
|
|
12183
12285
|
await persistState();
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12286
|
+
if (createResult.result === "failed") {
|
|
12287
|
+
const errMsg = createResult.error ?? "create-story failed";
|
|
12288
|
+
const stderrSnippet = errMsg.includes("--- stderr ---") ? errMsg.slice(errMsg.indexOf("--- stderr ---") + 15, errMsg.indexOf("--- stderr ---") + 515) : errMsg.slice(0, 500);
|
|
12289
|
+
logger$24.error({
|
|
12290
|
+
storyKey,
|
|
12291
|
+
stderrSnippet
|
|
12292
|
+
}, `Create-story failed: ${stderrSnippet.split("\n")[0]}`);
|
|
12293
|
+
updateStory(storyKey, {
|
|
12294
|
+
phase: "ESCALATED",
|
|
12295
|
+
error: errMsg,
|
|
12296
|
+
completedAt: new Date().toISOString()
|
|
12297
|
+
});
|
|
12298
|
+
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12299
|
+
await emitEscalation({
|
|
12300
|
+
storyKey,
|
|
12301
|
+
lastVerdict: "create-story-failed",
|
|
12302
|
+
reviewCycles: 0,
|
|
12303
|
+
issues: [errMsg]
|
|
12304
|
+
});
|
|
12305
|
+
await persistState();
|
|
12306
|
+
return;
|
|
12307
|
+
}
|
|
12308
|
+
if (createResult.story_file === void 0 || createResult.story_file === "") {
|
|
12309
|
+
const errMsg = "create-story succeeded but returned no story_file path";
|
|
12310
|
+
updateStory(storyKey, {
|
|
12311
|
+
phase: "ESCALATED",
|
|
12312
|
+
error: errMsg,
|
|
12313
|
+
completedAt: new Date().toISOString()
|
|
12314
|
+
});
|
|
12315
|
+
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12316
|
+
await emitEscalation({
|
|
12317
|
+
storyKey,
|
|
12318
|
+
lastVerdict: "create-story-no-file",
|
|
12319
|
+
reviewCycles: 0,
|
|
12320
|
+
issues: [errMsg]
|
|
12321
|
+
});
|
|
12322
|
+
await persistState();
|
|
12323
|
+
return;
|
|
12324
|
+
}
|
|
12325
|
+
if (projectRoot !== void 0) {
|
|
12326
|
+
const expectedArtifactsDir = join$1(projectRoot, "_bmad-output", "implementation-artifacts");
|
|
12327
|
+
const escapedExpectedDir = expectedArtifactsDir.replace("/_bmad-output/", "/\\_bmad-output/");
|
|
12328
|
+
let claimedPath = createResult.story_file;
|
|
12329
|
+
if (claimedPath.startsWith(escapedExpectedDir)) {
|
|
12330
|
+
claimedPath = claimedPath.replace("/\\_bmad-output/", "/_bmad-output/");
|
|
12331
|
+
logger$24.warn({
|
|
12332
|
+
storyKey,
|
|
12333
|
+
originalClaim: createResult.story_file,
|
|
12334
|
+
normalizedClaim: claimedPath
|
|
12335
|
+
}, "create-story claimed path contains backslash-escaped underscore; normalizing");
|
|
12336
|
+
eventBus.emit("orchestrator:story-warn", {
|
|
12337
|
+
storyKey,
|
|
12338
|
+
msg: `create-story claim path was backslash-escaped; normalized to ${claimedPath}`
|
|
12339
|
+
});
|
|
12340
|
+
}
|
|
12341
|
+
if (claimedPath.startsWith(expectedArtifactsDir)) try {
|
|
12342
|
+
let actualPath = null;
|
|
12343
|
+
if (existsSync(claimedPath)) actualPath = claimedPath;
|
|
12344
|
+
else {
|
|
12345
|
+
const escapedVariant = claimedPath.replace("/_bmad-output/", "/\\_bmad-output/");
|
|
12346
|
+
if (escapedVariant !== claimedPath && existsSync(escapedVariant)) try {
|
|
12347
|
+
renameSync(escapedVariant, claimedPath);
|
|
12348
|
+
actualPath = claimedPath;
|
|
12349
|
+
logger$24.warn({
|
|
12350
|
+
storyKey,
|
|
12351
|
+
escapedVariant,
|
|
12352
|
+
canonicalPath: claimedPath
|
|
12353
|
+
}, "create-story wrote artifact to backslash-escaped path; moved to canonical location");
|
|
12354
|
+
eventBus.emit("orchestrator:story-warn", {
|
|
12355
|
+
storyKey,
|
|
12356
|
+
msg: `create-story wrote to backslash-escaped path ${escapedVariant}; corrected to ${claimedPath}`
|
|
12357
|
+
});
|
|
12358
|
+
} catch (renameErr) {
|
|
12359
|
+
actualPath = escapedVariant;
|
|
12360
|
+
logger$24.warn({
|
|
12361
|
+
storyKey,
|
|
12362
|
+
escapedVariant,
|
|
12363
|
+
canonicalPath: claimedPath,
|
|
12364
|
+
err: renameErr
|
|
12365
|
+
}, "create-story wrote to backslash-escaped path; rename to canonical failed; treating as success at escaped location");
|
|
12366
|
+
eventBus.emit("orchestrator:story-warn", {
|
|
12367
|
+
storyKey,
|
|
12368
|
+
msg: `create-story wrote to backslash-escaped path ${escapedVariant}; rename to canonical failed`
|
|
12369
|
+
});
|
|
12370
|
+
}
|
|
12371
|
+
}
|
|
12372
|
+
if (actualPath === null) {
|
|
12373
|
+
const outputTokens = createResult.tokenUsage?.output ?? 0;
|
|
12374
|
+
const errMsg = `create-story claimed success (story_file: ${createResult.story_file}) but the file does not exist on disk (output tokens: ${outputTokens})`;
|
|
12375
|
+
logger$24.error({
|
|
12376
|
+
storyKey,
|
|
12377
|
+
claimedPath: createResult.story_file,
|
|
12378
|
+
outputTokens
|
|
12379
|
+
}, errMsg);
|
|
12380
|
+
updateStory(storyKey, {
|
|
12381
|
+
phase: "ESCALATED",
|
|
12382
|
+
error: errMsg,
|
|
12383
|
+
completedAt: new Date().toISOString()
|
|
12384
|
+
});
|
|
12385
|
+
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12386
|
+
await emitEscalation({
|
|
12387
|
+
storyKey,
|
|
12388
|
+
lastVerdict: "create-story-fraud-success",
|
|
12389
|
+
reviewCycles: 0,
|
|
12390
|
+
issues: [errMsg]
|
|
12391
|
+
});
|
|
12392
|
+
await persistState();
|
|
12393
|
+
return;
|
|
12394
|
+
}
|
|
12395
|
+
if (actualPath !== createResult.story_file) createResult.story_file = actualPath;
|
|
12396
|
+
const claimedStat = statSync(actualPath);
|
|
12397
|
+
if (claimedStat.mtimeMs < dispatchStartMs) {
|
|
12398
|
+
const outputTokens = createResult.tokenUsage?.output ?? 0;
|
|
12399
|
+
const mtimeISO = new Date(claimedStat.mtimeMs).toISOString();
|
|
12400
|
+
const dispatchStartISO = new Date(dispatchStartMs).toISOString();
|
|
12401
|
+
const errMsg = `create-story claimed success but did not rewrite ${actualPath} during this dispatch (file mtime ${mtimeISO} predates dispatch start ${dispatchStartISO}; output tokens: ${outputTokens})`;
|
|
12402
|
+
logger$24.error({
|
|
12403
|
+
storyKey,
|
|
12404
|
+
claimedPath: actualPath,
|
|
12405
|
+
mtimeISO,
|
|
12406
|
+
dispatchStartISO,
|
|
12407
|
+
outputTokens
|
|
12408
|
+
}, errMsg);
|
|
12409
|
+
updateStory(storyKey, {
|
|
12410
|
+
phase: "ESCALATED",
|
|
12411
|
+
error: errMsg,
|
|
12412
|
+
completedAt: new Date().toISOString()
|
|
12413
|
+
});
|
|
12414
|
+
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12415
|
+
await emitEscalation({
|
|
12416
|
+
storyKey,
|
|
12417
|
+
lastVerdict: "create-story-fraud-success",
|
|
12418
|
+
reviewCycles: 0,
|
|
12419
|
+
issues: [errMsg]
|
|
12420
|
+
});
|
|
12421
|
+
await persistState();
|
|
12422
|
+
return;
|
|
12423
|
+
}
|
|
12424
|
+
} catch (verifyErr) {
|
|
12425
|
+
logger$24.warn({
|
|
12426
|
+
storyKey,
|
|
12427
|
+
err: verifyErr
|
|
12428
|
+
}, "create-story post-dispatch file verification threw; proceeding with claimed path");
|
|
12429
|
+
}
|
|
12430
|
+
}
|
|
12431
|
+
storyFilePath = createResult.story_file;
|
|
12432
|
+
if (createResult.story_title) try {
|
|
12433
|
+
const epicId = storyKey.split("-")[0] ?? storyKey;
|
|
12434
|
+
const implDecisions = await getDecisionsByPhase(db, "implementation");
|
|
12435
|
+
let shardContent;
|
|
12436
|
+
const perStoryShard = implDecisions.find((d) => d.category === "epic-shard" && d.key === storyKey);
|
|
12437
|
+
if (perStoryShard?.value) shardContent = perStoryShard.value;
|
|
12438
|
+
else {
|
|
12439
|
+
const epicShard = implDecisions.find((d) => d.category === "epic-shard" && d.key === epicId);
|
|
12440
|
+
if (epicShard?.value) shardContent = extractStorySection(epicShard.value, storyKey) ?? epicShard.value;
|
|
12441
|
+
}
|
|
12442
|
+
if (shardContent) {
|
|
12443
|
+
const expectedTitle = extractExpectedStoryTitle(shardContent, storyKey);
|
|
12444
|
+
if (expectedTitle) {
|
|
12445
|
+
const overlap = computeTitleOverlap(expectedTitle, createResult.story_title);
|
|
12446
|
+
if (overlap < TITLE_OVERLAP_WARNING_THRESHOLD) {
|
|
12447
|
+
const msg = `Story title mismatch: expected "${expectedTitle}" but got "${createResult.story_title}" (word overlap: ${Math.round(overlap * 100)}%). This may indicate the create-story agent received truncated context.`;
|
|
12448
|
+
logger$24.warn({
|
|
12449
|
+
storyKey,
|
|
12450
|
+
expectedTitle,
|
|
12451
|
+
generatedTitle: createResult.story_title,
|
|
12452
|
+
overlap
|
|
12453
|
+
}, msg);
|
|
12454
|
+
eventBus.emit("orchestrator:story-warn", {
|
|
12455
|
+
storyKey,
|
|
12456
|
+
msg
|
|
12457
|
+
});
|
|
12458
|
+
} else logger$24.debug({
|
|
12459
|
+
storyKey,
|
|
12460
|
+
expectedTitle,
|
|
12461
|
+
generatedTitle: createResult.story_title,
|
|
12462
|
+
overlap
|
|
12463
|
+
}, "Story title validation passed");
|
|
12464
|
+
}
|
|
12465
|
+
}
|
|
12466
|
+
} catch (titleValidationErr) {
|
|
12467
|
+
logger$24.debug({
|
|
12468
|
+
storyKey,
|
|
12469
|
+
err: titleValidationErr
|
|
12470
|
+
}, "Story title validation skipped due to error");
|
|
12471
|
+
}
|
|
12472
|
+
} catch (err) {
|
|
12473
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
12474
|
+
endPhase(storyKey, "create-story");
|
|
12188
12475
|
updateStory(storyKey, {
|
|
12189
12476
|
phase: "ESCALATED",
|
|
12190
12477
|
error: errMsg,
|
|
@@ -12193,133 +12480,95 @@ function createImplementationOrchestrator(deps) {
|
|
|
12193
12480
|
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12194
12481
|
await emitEscalation({
|
|
12195
12482
|
storyKey,
|
|
12196
|
-
lastVerdict: "create-story-
|
|
12483
|
+
lastVerdict: "create-story-exception",
|
|
12197
12484
|
reviewCycles: 0,
|
|
12198
12485
|
issues: [errMsg]
|
|
12199
12486
|
});
|
|
12200
12487
|
await persistState();
|
|
12201
12488
|
return;
|
|
12202
12489
|
}
|
|
12203
|
-
if (projectRoot !== void 0) {
|
|
12204
|
-
const expectedArtifactsDir = join$1(projectRoot, "_bmad-output", "implementation-artifacts");
|
|
12205
|
-
const claimedPath = createResult.story_file;
|
|
12206
|
-
if (claimedPath.startsWith(expectedArtifactsDir)) try {
|
|
12207
|
-
if (!existsSync(claimedPath)) {
|
|
12208
|
-
const outputTokens = createResult.tokenUsage?.output ?? 0;
|
|
12209
|
-
const errMsg = `create-story claimed success (story_file: ${claimedPath}) but the file does not exist on disk (output tokens: ${outputTokens})`;
|
|
12210
|
-
logger$24.error({
|
|
12211
|
-
storyKey,
|
|
12212
|
-
claimedPath,
|
|
12213
|
-
outputTokens
|
|
12214
|
-
}, errMsg);
|
|
12215
|
-
updateStory(storyKey, {
|
|
12216
|
-
phase: "ESCALATED",
|
|
12217
|
-
error: errMsg,
|
|
12218
|
-
completedAt: new Date().toISOString()
|
|
12219
|
-
});
|
|
12220
|
-
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12221
|
-
await emitEscalation({
|
|
12222
|
-
storyKey,
|
|
12223
|
-
lastVerdict: "create-story-fraud-success",
|
|
12224
|
-
reviewCycles: 0,
|
|
12225
|
-
issues: [errMsg]
|
|
12226
|
-
});
|
|
12227
|
-
await persistState();
|
|
12228
|
-
return;
|
|
12229
|
-
}
|
|
12230
|
-
const claimedStat = statSync(claimedPath);
|
|
12231
|
-
if (claimedStat.mtimeMs < dispatchStartMs) {
|
|
12232
|
-
const outputTokens = createResult.tokenUsage?.output ?? 0;
|
|
12233
|
-
const mtimeISO = new Date(claimedStat.mtimeMs).toISOString();
|
|
12234
|
-
const dispatchStartISO = new Date(dispatchStartMs).toISOString();
|
|
12235
|
-
const errMsg = `create-story claimed success but did not rewrite ${claimedPath} during this dispatch (file mtime ${mtimeISO} predates dispatch start ${dispatchStartISO}; output tokens: ${outputTokens})`;
|
|
12236
|
-
logger$24.error({
|
|
12237
|
-
storyKey,
|
|
12238
|
-
claimedPath,
|
|
12239
|
-
mtimeISO,
|
|
12240
|
-
dispatchStartISO,
|
|
12241
|
-
outputTokens
|
|
12242
|
-
}, errMsg);
|
|
12243
|
-
updateStory(storyKey, {
|
|
12244
|
-
phase: "ESCALATED",
|
|
12245
|
-
error: errMsg,
|
|
12246
|
-
completedAt: new Date().toISOString()
|
|
12247
|
-
});
|
|
12248
|
-
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12249
|
-
await emitEscalation({
|
|
12250
|
-
storyKey,
|
|
12251
|
-
lastVerdict: "create-story-fraud-success",
|
|
12252
|
-
reviewCycles: 0,
|
|
12253
|
-
issues: [errMsg]
|
|
12254
|
-
});
|
|
12255
|
-
await persistState();
|
|
12256
|
-
return;
|
|
12257
|
-
}
|
|
12258
|
-
} catch (verifyErr) {
|
|
12259
|
-
logger$24.warn({
|
|
12260
|
-
storyKey,
|
|
12261
|
-
err: verifyErr
|
|
12262
|
-
}, "create-story post-dispatch file verification threw; proceeding with claimed path");
|
|
12263
|
-
}
|
|
12264
|
-
}
|
|
12265
|
-
storyFilePath = createResult.story_file;
|
|
12266
|
-
if (createResult.story_title) try {
|
|
12490
|
+
if (storyFilePath !== void 0 && projectRoot !== void 0) try {
|
|
12267
12491
|
const epicId = storyKey.split("-")[0] ?? storyKey;
|
|
12268
|
-
const
|
|
12269
|
-
let
|
|
12270
|
-
const
|
|
12271
|
-
if (
|
|
12492
|
+
const fidelityImplDecisions = await getDecisionsByPhase(db, "implementation");
|
|
12493
|
+
let fidelitySourceContent;
|
|
12494
|
+
const fidelityPerStoryShard = fidelityImplDecisions.find((d) => d.category === "epic-shard" && d.key === storyKey);
|
|
12495
|
+
if (fidelityPerStoryShard?.value) fidelitySourceContent = fidelityPerStoryShard.value;
|
|
12272
12496
|
else {
|
|
12273
|
-
const
|
|
12274
|
-
if (
|
|
12275
|
-
}
|
|
12276
|
-
if (
|
|
12277
|
-
const
|
|
12278
|
-
if (
|
|
12279
|
-
const
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
logger$24.warn({
|
|
12283
|
-
storyKey,
|
|
12284
|
-
expectedTitle,
|
|
12285
|
-
generatedTitle: createResult.story_title,
|
|
12286
|
-
overlap
|
|
12287
|
-
}, msg);
|
|
12288
|
-
eventBus.emit("orchestrator:story-warn", {
|
|
12289
|
-
storyKey,
|
|
12290
|
-
msg
|
|
12291
|
-
});
|
|
12292
|
-
} else logger$24.debug({
|
|
12497
|
+
const epicShardForFidelity = fidelityImplDecisions.find((d) => d.category === "epic-shard" && d.key === epicId);
|
|
12498
|
+
if (epicShardForFidelity?.value) fidelitySourceContent = extractStorySection(epicShardForFidelity.value, storyKey) ?? void 0;
|
|
12499
|
+
}
|
|
12500
|
+
if (fidelitySourceContent !== void 0) {
|
|
12501
|
+
const namedPaths = extractNamedPathsFromSource(fidelitySourceContent);
|
|
12502
|
+
if (namedPaths.length >= MIN_NAMED_PATHS_FOR_FIDELITY_GATE) {
|
|
12503
|
+
const storyContentForFidelity = await readFile$1(storyFilePath, "utf-8");
|
|
12504
|
+
const fidelity = computeStoryFileFidelity(storyContentForFidelity, namedPaths);
|
|
12505
|
+
logger$24.debug({
|
|
12293
12506
|
storyKey,
|
|
12294
|
-
|
|
12295
|
-
|
|
12296
|
-
|
|
12297
|
-
|
|
12507
|
+
drift: fidelity.drift,
|
|
12508
|
+
missing: fidelity.missing,
|
|
12509
|
+
presentCount: fidelity.present.length,
|
|
12510
|
+
namedPathsCount: namedPaths.length
|
|
12511
|
+
}, "create-story output fidelity check");
|
|
12512
|
+
if (fidelity.drift > FIDELITY_DRIFT_THRESHOLD) {
|
|
12513
|
+
fidelityRetries++;
|
|
12514
|
+
if (fidelityRetries <= MAX_FIDELITY_RETRIES) {
|
|
12515
|
+
const stalePath = storyFilePath.replace(/\.md$/, `.stale-${Date.now()}.md`);
|
|
12516
|
+
try {
|
|
12517
|
+
renameSync(storyFilePath, stalePath);
|
|
12518
|
+
const driftPct = Math.round(fidelity.drift * 100);
|
|
12519
|
+
logger$24.warn({
|
|
12520
|
+
storyKey,
|
|
12521
|
+
drift: fidelity.drift,
|
|
12522
|
+
missing: fidelity.missing,
|
|
12523
|
+
retries: fidelityRetries,
|
|
12524
|
+
stalePath
|
|
12525
|
+
}, `create-story output drifted from source AC (${driftPct}% of ${namedPaths.length} named paths missing); renamed to ${stalePath} and retrying (${fidelityRetries}/${MAX_FIDELITY_RETRIES})`);
|
|
12526
|
+
eventBus.emit("orchestrator:story-warn", {
|
|
12527
|
+
storyKey,
|
|
12528
|
+
msg: `create-story drift detected (${fidelity.missing.length}/${namedPaths.length} named paths missing); retry ${fidelityRetries}/${MAX_FIDELITY_RETRIES}`
|
|
12529
|
+
});
|
|
12530
|
+
storyFilePath = void 0;
|
|
12531
|
+
continue;
|
|
12532
|
+
} catch (renameErr) {
|
|
12533
|
+
logger$24.warn({
|
|
12534
|
+
storyKey,
|
|
12535
|
+
err: renameErr,
|
|
12536
|
+
stalePath
|
|
12537
|
+
}, "failed to rename drifting artifact for retry; proceeding with current artifact");
|
|
12538
|
+
}
|
|
12539
|
+
} else {
|
|
12540
|
+
const errMsg = `create-story output drifted from source AC after ${MAX_FIDELITY_RETRIES} retries; ${fidelity.missing.length} of ${namedPaths.length} named paths missing: ` + fidelity.missing.join(", ");
|
|
12541
|
+
logger$24.error({
|
|
12542
|
+
storyKey,
|
|
12543
|
+
drift: fidelity.drift,
|
|
12544
|
+
missing: fidelity.missing,
|
|
12545
|
+
namedPaths
|
|
12546
|
+
}, errMsg);
|
|
12547
|
+
endPhase(storyKey, "create-story");
|
|
12548
|
+
updateStory(storyKey, {
|
|
12549
|
+
phase: "ESCALATED",
|
|
12550
|
+
error: errMsg,
|
|
12551
|
+
completedAt: new Date().toISOString()
|
|
12552
|
+
});
|
|
12553
|
+
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12554
|
+
await emitEscalation({
|
|
12555
|
+
storyKey,
|
|
12556
|
+
lastVerdict: "create-story-source-ac-drift",
|
|
12557
|
+
reviewCycles: 0,
|
|
12558
|
+
issues: [errMsg]
|
|
12559
|
+
});
|
|
12560
|
+
await persistState();
|
|
12561
|
+
return;
|
|
12562
|
+
}
|
|
12563
|
+
}
|
|
12298
12564
|
}
|
|
12299
12565
|
}
|
|
12300
|
-
} catch (
|
|
12301
|
-
logger$24.
|
|
12566
|
+
} catch (fidelityErr) {
|
|
12567
|
+
logger$24.warn({
|
|
12302
12568
|
storyKey,
|
|
12303
|
-
err:
|
|
12304
|
-
}, "
|
|
12569
|
+
err: fidelityErr
|
|
12570
|
+
}, "fidelity gate threw; proceeding without retry");
|
|
12305
12571
|
}
|
|
12306
|
-
} catch (err) {
|
|
12307
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
12308
|
-
endPhase(storyKey, "create-story");
|
|
12309
|
-
updateStory(storyKey, {
|
|
12310
|
-
phase: "ESCALATED",
|
|
12311
|
-
error: errMsg,
|
|
12312
|
-
completedAt: new Date().toISOString()
|
|
12313
|
-
});
|
|
12314
|
-
await writeStoryMetricsBestEffort(storyKey, "failed", 0);
|
|
12315
|
-
await emitEscalation({
|
|
12316
|
-
storyKey,
|
|
12317
|
-
lastVerdict: "create-story-exception",
|
|
12318
|
-
reviewCycles: 0,
|
|
12319
|
-
issues: [errMsg]
|
|
12320
|
-
});
|
|
12321
|
-
await persistState();
|
|
12322
|
-
return;
|
|
12323
12572
|
}
|
|
12324
12573
|
if (storyFilePath) try {
|
|
12325
12574
|
const storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
@@ -44050,4 +44299,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
44050
44299
|
|
|
44051
44300
|
//#endregion
|
|
44052
44301
|
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 };
|
|
44053
|
-
//# sourceMappingURL=run-
|
|
44302
|
+
//# sourceMappingURL=run-BLObh_Ou.js.map
|
|
@@ -2,7 +2,7 @@ import "./health-ZGa9E0D2.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-BLObh_Ou.js";
|
|
6
6
|
import "./routing-CcBOCuC9.js";
|
|
7
7
|
import "./decisions-C0pz9Clx.js";
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -72,6 +72,7 @@ Do NOT write a partial story file. Do NOT paraphrase surrounding context. Do NOT
|
|
|
72
72
|
- Dev Notes with file paths, import patterns, testing requirements
|
|
73
73
|
6. **Apply the scope cap** — see Scope Cap Guidance below
|
|
74
74
|
7. **Write the story file** to: `_bmad-output/implementation-artifacts/{{story_key}}-<kebab-title>.md`
|
|
75
|
+
- Pass this path to your file-writing tool **literally as written** — do NOT markdown-escape the underscore as `\_bmad-output`. The leading underscore is part of the directory name, not a markdown italic delimiter.
|
|
75
76
|
- Do NOT add a `Status:` field to the story file — story status is managed exclusively by the Dolt work graph (`wg_stories` table)
|
|
76
77
|
- Dev Agent Record section must be present but left blank (to be filled by dev agent)
|
|
77
78
|
|