substrate-ai 0.20.7 → 0.20.10
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/adapter-registry-N0Klnk7Y.js +4 -0
- package/dist/cli/index.js +24 -16
- package/dist/{decisions-Ca77UwMA.js → decisions-7UJcRETq.js} +1 -1
- package/dist/{dist-srr3BfCc.js → dist-CqtWS9wF.js} +51 -5
- package/dist/{errors-CSTQNabo.js → errors-1uLGqnvr.js} +2 -2
- package/dist/{experimenter-DaXUHfJO.js → experimenter-VEJHtfLh.js} +1 -1
- package/dist/{health-BIS34IYK.js → health-C6Up5GCr.js} +86 -36
- package/dist/{health-3-qy8XEI.js → health-C73H5CUZ.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{routing-BX6ObE8S.js → routing-Ccpb_syA.js} +1 -1
- package/dist/{run-BAc1zfMQ.js → run-BcwaSYTg.js} +85 -85
- package/dist/{run-Dif8PJRd.js → run-CvCQpsy0.js} +3 -3
- package/dist/{upgrade-Cm8B3cXL.js → upgrade-CVaD7iUR.js} +2 -2
- package/dist/{upgrade-iTr8nbbE.js → upgrade-k15NGTno.js} +2 -2
- package/dist/{version-manager-impl-XiJHzIbR.js → version-manager-impl-CEiZEsmi.js} +1 -1
- package/package.json +1 -1
- package/packs/bmad/prompts/create-story.md +14 -9
- package/dist/adapter-registry-CwjKI1sO.js +0 -4
package/dist/cli/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
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-C6Up5GCr.js";
|
|
3
3
|
import { createLogger } from "../logger-KeHncl-f.js";
|
|
4
4
|
import { createEventBus } from "../helpers-CElYrONe.js";
|
|
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-
|
|
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-
|
|
8
|
-
import "../errors-
|
|
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-BcwaSYTg.js";
|
|
8
|
+
import "../errors-1uLGqnvr.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
11
11
|
import "../version-manager-impl-BmOWu8ml.js";
|
|
12
|
-
import { registerUpgradeCommand } from "../upgrade-
|
|
12
|
+
import { registerUpgradeCommand } from "../upgrade-k15NGTno.js";
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
import { fileURLToPath } from "url";
|
|
15
15
|
import { dirname, join, resolve } from "path";
|
|
@@ -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-C73H5CUZ.js");
|
|
3671
3671
|
const substrateDirPath = join(projectRoot, ".substrate");
|
|
3672
3672
|
const processInfo = inspectProcessTree$1({
|
|
3673
3673
|
projectRoot,
|
|
@@ -3712,6 +3712,7 @@ async function runStatusAction(options) {
|
|
|
3712
3712
|
} catch {}
|
|
3713
3713
|
const verificationResult = manifestPerStoryState?.[row.story_key]?.verification_result;
|
|
3714
3714
|
const verificationFindings = rollupFindingCounts(verificationResult);
|
|
3715
|
+
const verificationRan = verificationResult !== void 0 && verificationResult !== null;
|
|
3715
3716
|
return {
|
|
3716
3717
|
story_key: row.story_key,
|
|
3717
3718
|
result: row.result,
|
|
@@ -3723,7 +3724,8 @@ async function runStatusAction(options) {
|
|
|
3723
3724
|
},
|
|
3724
3725
|
review_cycles: row.review_cycles ?? 0,
|
|
3725
3726
|
dispatches: row.dispatches ?? 0,
|
|
3726
|
-
verification_findings: verificationFindings
|
|
3727
|
+
verification_findings: verificationFindings,
|
|
3728
|
+
verification_ran: verificationRan
|
|
3727
3729
|
};
|
|
3728
3730
|
});
|
|
3729
3731
|
let pipelineWallClockMs = 0;
|
|
@@ -4615,7 +4617,7 @@ function defaultSupervisorDeps() {
|
|
|
4615
4617
|
if (cached === null) {
|
|
4616
4618
|
const { AdapterRegistry: AR } = await import(
|
|
4617
4619
|
/* @vite-ignore */
|
|
4618
|
-
"../adapter-registry-
|
|
4620
|
+
"../adapter-registry-N0Klnk7Y.js"
|
|
4619
4621
|
);
|
|
4620
4622
|
cached = new AR();
|
|
4621
4623
|
await cached.discoverAndRegister();
|
|
@@ -5182,11 +5184,11 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
5182
5184
|
try {
|
|
5183
5185
|
const { createExperimenter } = await import(
|
|
5184
5186
|
/* @vite-ignore */
|
|
5185
|
-
"../experimenter-
|
|
5187
|
+
"../experimenter-VEJHtfLh.js"
|
|
5186
5188
|
);
|
|
5187
5189
|
const { getLatestRun: getLatest } = await import(
|
|
5188
5190
|
/* @vite-ignore */
|
|
5189
|
-
"../decisions-
|
|
5191
|
+
"../decisions-7UJcRETq.js"
|
|
5190
5192
|
);
|
|
5191
5193
|
const expAdapter = createDatabaseAdapter({
|
|
5192
5194
|
backend: "auto",
|
|
@@ -5196,7 +5198,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
5196
5198
|
await initSchema(expAdapter);
|
|
5197
5199
|
const { runRunAction: runPipeline } = await import(
|
|
5198
5200
|
/* @vite-ignore */
|
|
5199
|
-
"../run-
|
|
5201
|
+
"../run-CvCQpsy0.js"
|
|
5200
5202
|
);
|
|
5201
5203
|
const runStoryFn = async (opts) => {
|
|
5202
5204
|
const exitCode = await runPipeline({
|
|
@@ -5728,7 +5730,7 @@ async function runMetricsAction(options) {
|
|
|
5728
5730
|
const routingConfigPath = join(dbDir, "routing.yml");
|
|
5729
5731
|
let routingConfig = null;
|
|
5730
5732
|
if (existsSync$1(routingConfigPath)) try {
|
|
5731
|
-
const { loadModelRoutingConfig } = await import("../routing-
|
|
5733
|
+
const { loadModelRoutingConfig } = await import("../routing-Ccpb_syA.js");
|
|
5732
5734
|
routingConfig = loadModelRoutingConfig(routingConfigPath);
|
|
5733
5735
|
} catch {}
|
|
5734
5736
|
if (routingConfig === null) routingConfig = {
|
|
@@ -5959,12 +5961,17 @@ async function runMetricsAction(options) {
|
|
|
5959
5961
|
}
|
|
5960
5962
|
} catch {}
|
|
5961
5963
|
const findingCountsByStoryRun = new Map();
|
|
5964
|
+
const verificationRanByStoryRun = new Map();
|
|
5962
5965
|
const uniqueRunIds = Array.from(new Set(storyMetrics.map((sm) => sm.run_id).filter((id) => id !== "")));
|
|
5963
5966
|
for (const uniqueRunId of uniqueRunIds) try {
|
|
5964
5967
|
const { manifest } = await resolveRunManifest(dbRoot, uniqueRunId);
|
|
5965
5968
|
if (manifest === null) continue;
|
|
5966
5969
|
const data = await manifest.read();
|
|
5967
|
-
for (const [storyKey, entry] of Object.entries(data.per_story_state))
|
|
5970
|
+
for (const [storyKey, entry] of Object.entries(data.per_story_state)) {
|
|
5971
|
+
const key = `${storyKey}:${uniqueRunId}`;
|
|
5972
|
+
findingCountsByStoryRun.set(key, rollupFindingCounts(entry.verification_result));
|
|
5973
|
+
verificationRanByStoryRun.set(key, entry.verification_result !== void 0 && entry.verification_result !== null);
|
|
5974
|
+
}
|
|
5968
5975
|
} catch {}
|
|
5969
5976
|
let factoryRuns = [];
|
|
5970
5977
|
try {
|
|
@@ -5980,7 +5987,8 @@ async function runMetricsAction(options) {
|
|
|
5980
5987
|
}));
|
|
5981
5988
|
const storyMetricsWithFindings = storyMetrics.map((sm) => ({
|
|
5982
5989
|
...sm,
|
|
5983
|
-
verification_findings: findingCountsByStoryRun.get(`${sm.story_key}:${sm.run_id}`) ?? { ...ZERO_FINDING_COUNTS }
|
|
5990
|
+
verification_findings: findingCountsByStoryRun.get(`${sm.story_key}:${sm.run_id}`) ?? { ...ZERO_FINDING_COUNTS },
|
|
5991
|
+
verification_ran: verificationRanByStoryRun.get(`${sm.story_key}:${sm.run_id}`) ?? false
|
|
5984
5992
|
}));
|
|
5985
5993
|
const jsonPayload = {
|
|
5986
5994
|
runs: runsWithBreakdown,
|
|
@@ -8995,8 +9003,8 @@ async function createProgram() {
|
|
|
8995
9003
|
/** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
|
|
8996
9004
|
function checkForUpdatesInBackground(currentVersion) {
|
|
8997
9005
|
if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
|
|
8998
|
-
import("../upgrade-
|
|
8999
|
-
const { createVersionManager } = await import("../version-manager-impl-
|
|
9006
|
+
import("../upgrade-CVaD7iUR.js").then(async () => {
|
|
9007
|
+
const { createVersionManager } = await import("../version-manager-impl-CEiZEsmi.js");
|
|
9000
9008
|
const vm = createVersionManager();
|
|
9001
9009
|
const result = await vm.checkForUpdates();
|
|
9002
9010
|
if (result.updateAvailable) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-
|
|
1
|
+
import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-CqtWS9wF.js";
|
|
2
2
|
import "./decisions-C0pz9Clx.js";
|
|
3
3
|
|
|
4
4
|
export { getLatestRun };
|
|
@@ -4044,15 +4044,27 @@ async function aggregateTokenUsageForStory(adapter, runId, storyKey) {
|
|
|
4044
4044
|
//#endregion
|
|
4045
4045
|
//#region packages/core/dist/persistence/queries/retry-escalated.js
|
|
4046
4046
|
/**
|
|
4047
|
+
* Pipeline-run statuses that make escalation-diagnosis decisions non-actionable.
|
|
4048
|
+
* Runs in these states are terminated (abandoned / stopped manually) and their
|
|
4049
|
+
* per-story escalations are historical noise — the work either shipped in a
|
|
4050
|
+
* later run or was never going to be retried in this run's lifetime.
|
|
4051
|
+
*/
|
|
4052
|
+
const TERMINAL_RUN_STATUSES = ["failed", "stopped"];
|
|
4053
|
+
/**
|
|
4047
4054
|
* Query the decision store for escalation-diagnosis decisions and classify
|
|
4048
4055
|
* each story key as retryable or skipped.
|
|
4049
4056
|
*
|
|
4050
4057
|
* Key format in the DB: `{storyKey}:{runId}`
|
|
4051
4058
|
*
|
|
4059
|
+
* Scoping:
|
|
4052
4060
|
* - When `runId` is provided, only decisions whose key contains that runId
|
|
4053
|
-
* are considered (AC5
|
|
4054
|
-
*
|
|
4055
|
-
*
|
|
4061
|
+
* are considered (AC5). The caller is explicit; no status filter is applied
|
|
4062
|
+
* so a user can still inspect diagnoses from a terminal run by naming it.
|
|
4063
|
+
* - When `runId` is omitted, the latest run whose `pipeline_runs.status` is
|
|
4064
|
+
* NOT terminal (`failed` / `stopped`) is used. Terminal runs are abandoned
|
|
4065
|
+
* or manually stopped — their per-story diagnoses are historical noise and
|
|
4066
|
+
* would generate false-positive retry proposals for work that either
|
|
4067
|
+
* shipped in a later run or will never be retried in that run's lifetime.
|
|
4056
4068
|
*
|
|
4057
4069
|
* @param adapter The database adapter
|
|
4058
4070
|
* @param runId Optional run ID to scope the query
|
|
@@ -4083,7 +4095,13 @@ async function getRetryableEscalations(adapter, runId) {
|
|
|
4083
4095
|
});
|
|
4084
4096
|
}
|
|
4085
4097
|
if (parsed.length === 0) return result;
|
|
4086
|
-
|
|
4098
|
+
let effectiveRunId;
|
|
4099
|
+
if (runId !== void 0) effectiveRunId = runId;
|
|
4100
|
+
else {
|
|
4101
|
+
const candidateRunId = await pickLatestNonTerminalRunId(adapter, parsed);
|
|
4102
|
+
if (candidateRunId === void 0) return result;
|
|
4103
|
+
effectiveRunId = candidateRunId;
|
|
4104
|
+
}
|
|
4087
4105
|
const lastEntryByKey = new Map();
|
|
4088
4106
|
for (const entry of parsed) {
|
|
4089
4107
|
if (entry.decisionRunId !== effectiveRunId) continue;
|
|
@@ -4103,6 +4121,34 @@ async function getRetryableEscalations(adapter, runId) {
|
|
|
4103
4121
|
}
|
|
4104
4122
|
return result;
|
|
4105
4123
|
}
|
|
4124
|
+
/**
|
|
4125
|
+
* Walk the parsed decision list newest-last (as supplied), map distinct runIds
|
|
4126
|
+
* to their pipeline-run status, and return the runId of the newest decision
|
|
4127
|
+
* whose run is NOT in a terminal status.
|
|
4128
|
+
*
|
|
4129
|
+
* Returns `undefined` when every referenced run is terminal or missing —
|
|
4130
|
+
* signalling "nothing retryable" to the caller.
|
|
4131
|
+
*
|
|
4132
|
+
* The adapter query is a single SELECT against `pipeline_runs` restricted to
|
|
4133
|
+
* the distinct runIds we actually care about; keeps the cost O(unique-runs)
|
|
4134
|
+
* rather than O(decisions).
|
|
4135
|
+
*/
|
|
4136
|
+
async function pickLatestNonTerminalRunId(adapter, parsed) {
|
|
4137
|
+
const uniqueRunIds = Array.from(new Set(parsed.map((p) => p.decisionRunId)));
|
|
4138
|
+
if (uniqueRunIds.length === 0) return void 0;
|
|
4139
|
+
const statusByRunId = new Map();
|
|
4140
|
+
for (const id of uniqueRunIds) {
|
|
4141
|
+
const rows = await adapter.query("SELECT id, status FROM pipeline_runs WHERE id = ?", [id]);
|
|
4142
|
+
if (rows.length > 0 && rows[0]) statusByRunId.set(rows[0].id, rows[0].status);
|
|
4143
|
+
}
|
|
4144
|
+
for (let i = parsed.length - 1; i >= 0; i -= 1) {
|
|
4145
|
+
const entry = parsed[i];
|
|
4146
|
+
const status = statusByRunId.get(entry.decisionRunId);
|
|
4147
|
+
if (status !== void 0 && TERMINAL_RUN_STATUSES.includes(status)) continue;
|
|
4148
|
+
return entry.decisionRunId;
|
|
4149
|
+
}
|
|
4150
|
+
return void 0;
|
|
4151
|
+
}
|
|
4106
4152
|
|
|
4107
4153
|
//#endregion
|
|
4108
4154
|
//#region packages/core/dist/persistence/monitor-database.js
|
|
@@ -10894,4 +10940,4 @@ async function callLLM(params) {
|
|
|
10894
10940
|
|
|
10895
10941
|
//#endregion
|
|
10896
10942
|
export { ADVISORY_NOTES, AdapterRegistry, AdtError, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, Categorizer, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, ConsumerAnalyzer, CostTrackerConfigSchema, DEFAULT_CONFIG, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, DoltNotInstalled, DoltQueryError, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, GeminiCLIAdapter, GlobalSettingsSchema, IngestionServer, LEARNING_FINDING, LogTurnAnalyzer, ModelRoutingConfigSchema, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProviderPolicySchema, ProvidersSchema, Recommender, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TASK_TYPE_PHASE_MAP, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryConfigSchema, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, VersionManagerImpl, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, callLLM, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDatabaseAdapter as createDatabaseAdapter$1, createDecision, createDoltClient, createExperimenter, createPipelineRun, createRequirement, createVersionManager, detectInterfaceChanges, determineVerdict, getActiveDecisions, getAllCostEntriesFiltered, getArtifactByTypeForRun, getArtifactsByRun, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getModelTier, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadModelRoutingConfig, loadParentRunDecisions, registerArtifact, resolvePromptFile, supersedeDecision, tagRunAsBaseline, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics };
|
|
10897
|
-
//# sourceMappingURL=dist-
|
|
10943
|
+
//# sourceMappingURL=dist-CqtWS9wF.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdtError } from "./dist-
|
|
1
|
+
import { AdtError } from "./dist-CqtWS9wF.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/errors.ts
|
|
4
4
|
/** Error thrown when task configuration is invalid */
|
|
@@ -71,4 +71,4 @@ var TaskGraphIncompatibleFormatError = class extends AdtError {
|
|
|
71
71
|
|
|
72
72
|
//#endregion
|
|
73
73
|
export { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError };
|
|
74
|
-
//# sourceMappingURL=errors-
|
|
74
|
+
//# sourceMappingURL=errors-1uLGqnvr.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-
|
|
1
|
+
import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-CqtWS9wF.js";
|
|
2
2
|
|
|
3
3
|
export { createExperimenter };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
2
|
-
import { DoltClient, DoltQueryError, LEARNING_FINDING, createDatabaseAdapter$1 as createDatabaseAdapter, createDecision, getDecisionsByCategory, getLatestRun, getPipelineRunById, initSchema } from "./dist-
|
|
2
|
+
import { DoltClient, DoltQueryError, LEARNING_FINDING, createDatabaseAdapter$1 as createDatabaseAdapter, createDecision, getDecisionsByCategory, getLatestRun, getPipelineRunById, initSchema } from "./dist-CqtWS9wF.js";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
import { dirname, join } from "path";
|
|
5
5
|
import { readFile } from "fs/promises";
|
|
@@ -4185,6 +4185,11 @@ var RunManifest = class RunManifest {
|
|
|
4185
4185
|
baseDir;
|
|
4186
4186
|
/** Optional Dolt adapter for degraded-mode fallback on read. */
|
|
4187
4187
|
doltAdapter;
|
|
4188
|
+
/**
|
|
4189
|
+
* Serializes all write operations on this instance to prevent lost-update races.
|
|
4190
|
+
* Initialized to a resolved promise; each enqueued operation chains off the tail.
|
|
4191
|
+
*/
|
|
4192
|
+
_writeChain = Promise.resolve();
|
|
4188
4193
|
constructor(runId, baseDir = defaultBaseDir(), doltAdapter = null) {
|
|
4189
4194
|
this.runId = runId;
|
|
4190
4195
|
this.baseDir = baseDir;
|
|
@@ -4231,7 +4236,22 @@ var RunManifest = class RunManifest {
|
|
|
4231
4236
|
await this.write(merged);
|
|
4232
4237
|
}
|
|
4233
4238
|
/**
|
|
4234
|
-
*
|
|
4239
|
+
* Append `fn` to the per-instance write chain so all write operations execute
|
|
4240
|
+
* strictly sequentially, preventing lost-update races on concurrent callers.
|
|
4241
|
+
*
|
|
4242
|
+
* The chain itself never rejects (errors are swallowed on the chain side);
|
|
4243
|
+
* the returned promise resolves or rejects exactly when `fn` settles, so
|
|
4244
|
+
* fire-and-forget `.catch()` callers still receive failure signals.
|
|
4245
|
+
*/
|
|
4246
|
+
_enqueue(fn) {
|
|
4247
|
+
const next = this._writeChain.then(() => fn());
|
|
4248
|
+
this._writeChain = next.then(() => void 0, () => void 0);
|
|
4249
|
+
return next;
|
|
4250
|
+
}
|
|
4251
|
+
/**
|
|
4252
|
+
* Raw implementation of the atomic manifest write.
|
|
4253
|
+
* Must only be called from within an `_enqueue`-d function to maintain
|
|
4254
|
+
* the serialization invariant.
|
|
4235
4255
|
*
|
|
4236
4256
|
* Sequence:
|
|
4237
4257
|
* 1. Auto-increment `generation`, set `updated_at`
|
|
@@ -4241,7 +4261,7 @@ var RunManifest = class RunManifest {
|
|
|
4241
4261
|
* 5. If primary exists, copy to `.bak`
|
|
4242
4262
|
* 6. Rename `.tmp` → primary path
|
|
4243
4263
|
*/
|
|
4244
|
-
async
|
|
4264
|
+
async _writeImpl(data) {
|
|
4245
4265
|
let currentGeneration = 0;
|
|
4246
4266
|
const existing = await tryReadFile(this.primaryPath);
|
|
4247
4267
|
if (existing !== null) currentGeneration = existing.generation;
|
|
@@ -4267,6 +4287,15 @@ var RunManifest = class RunManifest {
|
|
|
4267
4287
|
await promises.rename(tmp, this.primaryPath);
|
|
4268
4288
|
}
|
|
4269
4289
|
/**
|
|
4290
|
+
* Atomically write the manifest to disk.
|
|
4291
|
+
*
|
|
4292
|
+
* Enqueues the write via `_enqueue` so concurrent calls are serialized.
|
|
4293
|
+
* The returned promise resolves when this call's write completes.
|
|
4294
|
+
*/
|
|
4295
|
+
async write(data) {
|
|
4296
|
+
return this._enqueue(() => this._writeImpl(data));
|
|
4297
|
+
}
|
|
4298
|
+
/**
|
|
4270
4299
|
* Return a bound `RunManifest` instance without performing any file I/O.
|
|
4271
4300
|
*
|
|
4272
4301
|
* Use `open()` when you want to call instance methods (`read()`, `patchCLIFlags()`)
|
|
@@ -4280,13 +4309,9 @@ var RunManifest = class RunManifest {
|
|
|
4280
4309
|
return new RunManifest(runId, baseDir, doltAdapter);
|
|
4281
4310
|
}
|
|
4282
4311
|
/**
|
|
4283
|
-
*
|
|
4284
|
-
* CLI flags into `cli_flags`, and write the result atomically.
|
|
4285
|
-
*
|
|
4286
|
-
* Non-fatal: callers should wrap in try/catch and log a warning on failure.
|
|
4287
|
-
* The pipeline must not abort if manifest write fails.
|
|
4312
|
+
* Raw implementation — must only be called from within `_enqueue`.
|
|
4288
4313
|
*/
|
|
4289
|
-
async
|
|
4314
|
+
async _patchCLIFlagsImpl(flags) {
|
|
4290
4315
|
let existingData;
|
|
4291
4316
|
try {
|
|
4292
4317
|
const read = await RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
|
|
@@ -4310,7 +4335,7 @@ var RunManifest = class RunManifest {
|
|
|
4310
4335
|
created_at: now
|
|
4311
4336
|
};
|
|
4312
4337
|
}
|
|
4313
|
-
await this.
|
|
4338
|
+
await this._writeImpl({
|
|
4314
4339
|
...existingData,
|
|
4315
4340
|
cli_flags: {
|
|
4316
4341
|
...existingData.cli_flags,
|
|
@@ -4319,21 +4344,20 @@ var RunManifest = class RunManifest {
|
|
|
4319
4344
|
});
|
|
4320
4345
|
}
|
|
4321
4346
|
/**
|
|
4322
|
-
*
|
|
4323
|
-
*
|
|
4324
|
-
* Reads the current manifest (or creates a minimal default if absent),
|
|
4325
|
-
* shallowly merges `updates` into `per_story_state[storyKey]`, and writes
|
|
4326
|
-
* the result atomically via a single `write()` call.
|
|
4327
|
-
*
|
|
4328
|
-
* Fields not included in `updates` on an existing entry are preserved unchanged.
|
|
4329
|
-
*
|
|
4330
|
-
* Non-fatal: callers MUST wrap in `.catch((err) => logger.warn(...))`.
|
|
4331
|
-
* The pipeline must never abort due to a manifest write failure.
|
|
4347
|
+
* Read the current manifest (or create a minimal default), merge the provided
|
|
4348
|
+
* CLI flags into `cli_flags`, and write the result atomically.
|
|
4332
4349
|
*
|
|
4333
|
-
*
|
|
4334
|
-
*
|
|
4350
|
+
* Enqueues the operation via `_enqueue` so concurrent calls are serialized.
|
|
4351
|
+
* Non-fatal: callers should wrap in try/catch and log a warning on failure.
|
|
4352
|
+
* The pipeline must not abort if manifest write fails.
|
|
4335
4353
|
*/
|
|
4336
|
-
async
|
|
4354
|
+
async patchCLIFlags(flags) {
|
|
4355
|
+
return this._enqueue(() => this._patchCLIFlagsImpl(flags));
|
|
4356
|
+
}
|
|
4357
|
+
/**
|
|
4358
|
+
* Raw implementation — must only be called from within `_enqueue`.
|
|
4359
|
+
*/
|
|
4360
|
+
async _patchStoryStateImpl(storyKey, updates) {
|
|
4337
4361
|
let existingData;
|
|
4338
4362
|
try {
|
|
4339
4363
|
const read = await RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
|
|
@@ -4365,7 +4389,7 @@ var RunManifest = class RunManifest {
|
|
|
4365
4389
|
...existing,
|
|
4366
4390
|
...updates
|
|
4367
4391
|
};
|
|
4368
|
-
await this.
|
|
4392
|
+
await this._writeImpl({
|
|
4369
4393
|
...existingData,
|
|
4370
4394
|
per_story_state: {
|
|
4371
4395
|
...existingData.per_story_state,
|
|
@@ -4374,22 +4398,28 @@ var RunManifest = class RunManifest {
|
|
|
4374
4398
|
});
|
|
4375
4399
|
}
|
|
4376
4400
|
/**
|
|
4377
|
-
* Atomically
|
|
4401
|
+
* Atomically upsert the per-story lifecycle state for a single story key.
|
|
4378
4402
|
*
|
|
4379
|
-
* Reads the current manifest
|
|
4380
|
-
*
|
|
4381
|
-
*
|
|
4382
|
-
*
|
|
4403
|
+
* Reads the current manifest (or creates a minimal default if absent),
|
|
4404
|
+
* shallowly merges `updates` into `per_story_state[storyKey]`, and writes
|
|
4405
|
+
* the result atomically via a single `write()` call.
|
|
4406
|
+
*
|
|
4407
|
+
* Fields not included in `updates` on an existing entry are preserved unchanged.
|
|
4383
4408
|
*
|
|
4409
|
+
* Enqueues the operation via `_enqueue` so concurrent calls are serialized.
|
|
4384
4410
|
* Non-fatal: callers MUST wrap in `.catch((err) => logger.warn(...))`.
|
|
4385
4411
|
* The pipeline must never abort due to a manifest write failure.
|
|
4386
4412
|
*
|
|
4387
|
-
*
|
|
4388
|
-
*
|
|
4389
|
-
*
|
|
4390
|
-
* @param entry - Recovery entry to append (attempt_number is 1-indexed)
|
|
4413
|
+
* @param storyKey - Story key (e.g. '52-4')
|
|
4414
|
+
* @param updates - Partial PerStoryState fields to merge
|
|
4391
4415
|
*/
|
|
4392
|
-
async
|
|
4416
|
+
async patchStoryState(storyKey, updates) {
|
|
4417
|
+
return this._enqueue(() => this._patchStoryStateImpl(storyKey, updates));
|
|
4418
|
+
}
|
|
4419
|
+
/**
|
|
4420
|
+
* Raw implementation — must only be called from within `_enqueue`.
|
|
4421
|
+
*/
|
|
4422
|
+
async _appendRecoveryEntryImpl(entry) {
|
|
4393
4423
|
let existingData;
|
|
4394
4424
|
try {
|
|
4395
4425
|
const read = await RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
|
|
@@ -4425,7 +4455,27 @@ var RunManifest = class RunManifest {
|
|
|
4425
4455
|
run_total: existingData.cost_accumulation.run_total + entry.cost_usd
|
|
4426
4456
|
}
|
|
4427
4457
|
};
|
|
4428
|
-
await this.
|
|
4458
|
+
await this._writeImpl(updated);
|
|
4459
|
+
}
|
|
4460
|
+
/**
|
|
4461
|
+
* Atomically append a recovery entry and update cost accumulation.
|
|
4462
|
+
*
|
|
4463
|
+
* Reads the current manifest, appends `entry` to `recovery_history[]`,
|
|
4464
|
+
* increments `cost_accumulation.per_story[entry.story_key]` by `entry.cost_usd`,
|
|
4465
|
+
* increments `cost_accumulation.run_total` by `entry.cost_usd`, then writes
|
|
4466
|
+
* atomically via a single `write()` call.
|
|
4467
|
+
*
|
|
4468
|
+
* Enqueues the operation via `_enqueue` so concurrent calls are serialized.
|
|
4469
|
+
* Non-fatal: callers MUST wrap in `.catch((err) => logger.warn(...))`.
|
|
4470
|
+
* The pipeline must never abort due to a manifest write failure.
|
|
4471
|
+
*
|
|
4472
|
+
* `entry.cost_usd` is the cost of this single retry attempt only (NOT cumulative).
|
|
4473
|
+
* Cumulative per-story retry cost is tracked in `cost_accumulation.per_story`.
|
|
4474
|
+
*
|
|
4475
|
+
* @param entry - Recovery entry to append (attempt_number is 1-indexed)
|
|
4476
|
+
*/
|
|
4477
|
+
async appendRecoveryEntry(entry) {
|
|
4478
|
+
return this._enqueue(() => this._appendRecoveryEntryImpl(entry));
|
|
4429
4479
|
}
|
|
4430
4480
|
/**
|
|
4431
4481
|
* Create a new manifest with `generation: 0` and write it.
|
|
@@ -5286,4 +5336,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
|
|
|
5286
5336
|
|
|
5287
5337
|
//#endregion
|
|
5288
5338
|
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 };
|
|
5289
|
-
//# sourceMappingURL=health-
|
|
5339
|
+
//# sourceMappingURL=health-C6Up5GCr.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
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-C6Up5GCr.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
|
-
import "./dist-
|
|
3
|
+
import "./dist-CqtWS9wF.js";
|
|
4
4
|
import "./decisions-C0pz9Clx.js";
|
|
5
5
|
|
|
6
6
|
export { inspectProcessTree };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { childLogger, createLogger, logger } from "./logger-KeHncl-f.js";
|
|
2
2
|
import { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-CElYrONe.js";
|
|
3
|
-
import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-
|
|
3
|
+
import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-CqtWS9wF.js";
|
|
4
4
|
import "./adapter-registry-DXLMTmfD.js";
|
|
5
|
-
import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-
|
|
5
|
+
import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-1uLGqnvr.js";
|
|
6
6
|
|
|
7
7
|
//#region src/core/di.ts
|
|
8
8
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-
|
|
1
|
+
import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-CqtWS9wF.js";
|
|
2
2
|
import "./routing-CcBOCuC9.js";
|
|
3
3
|
|
|
4
4
|
export { loadModelRoutingConfig };
|
|
@@ -1,7 +1,7 @@
|
|
|
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-C6Up5GCr.js";
|
|
2
2
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
3
3
|
import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
|
|
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-
|
|
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";
|
|
5
5
|
import { basename, dirname, extname, join } from "path";
|
|
6
6
|
import { access, readFile, readdir, stat } from "fs/promises";
|
|
7
7
|
import { EventEmitter } from "node:events";
|
|
@@ -10462,20 +10462,23 @@ var VerificationStore = class {
|
|
|
10462
10462
|
* verification results survive process crashes.
|
|
10463
10463
|
*
|
|
10464
10464
|
* Design notes:
|
|
10465
|
-
* - Non-fatal: the
|
|
10466
|
-
*
|
|
10465
|
+
* - Non-fatal: the `.catch()` handler swallows any rejection and logs at warn.
|
|
10466
|
+
* - Returns a `Promise<void>` so callers can optionally `await` it to ensure
|
|
10467
|
+
* ordering (Story 57-2). Fire-and-forget callers that discard the return
|
|
10468
|
+
* value continue to compile and work correctly.
|
|
10467
10469
|
* - Reuses the single RunManifest instance injected by the orchestrator to
|
|
10468
10470
|
* avoid concurrent-write conflicts with the atomic-write lock.
|
|
10469
10471
|
* - `runManifest` is optional (`undefined | null`) — callers from contexts
|
|
10470
|
-
* where no manifest is configured pass `null` and this function
|
|
10472
|
+
* where no manifest is configured pass `null` and this function returns a
|
|
10473
|
+
* resolved promise (no-op).
|
|
10471
10474
|
*
|
|
10472
10475
|
* @param storyKey - Story key being verified (e.g. '52-7')
|
|
10473
10476
|
* @param summary - VerificationSummary returned by VerificationPipeline.run()
|
|
10474
10477
|
* @param runManifest - RunManifest instance to write to, or null/undefined to skip
|
|
10475
10478
|
*/
|
|
10476
10479
|
function persistVerificationResult(storyKey, summary, runManifest) {
|
|
10477
|
-
if (runManifest == null) return;
|
|
10478
|
-
runManifest.patchStoryState(storyKey, { verification_result: summary }).catch((err) => _logger.warn({
|
|
10480
|
+
if (runManifest == null) return Promise.resolve();
|
|
10481
|
+
return runManifest.patchStoryState(storyKey, { verification_result: summary }).catch((err) => _logger.warn({
|
|
10479
10482
|
err,
|
|
10480
10483
|
storyKey
|
|
10481
10484
|
}, "manifest verification_result write failed — pipeline continues"));
|
|
@@ -12072,21 +12075,17 @@ function createImplementationOrchestrator(deps) {
|
|
|
12072
12075
|
phase: "IN_STORY_CREATION",
|
|
12073
12076
|
result: createResult
|
|
12074
12077
|
});
|
|
12075
|
-
if (config.pipelineRunId !== void 0 && createResult.tokenUsage !== void 0)
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
storyKey,
|
|
12087
|
-
err: tokenErr
|
|
12088
|
-
}, "Failed to record create-story token usage");
|
|
12089
|
-
}
|
|
12078
|
+
if (config.pipelineRunId !== void 0 && createResult.tokenUsage !== void 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
12079
|
+
phase: "create-story",
|
|
12080
|
+
agent: "create-story",
|
|
12081
|
+
input_tokens: createResult.tokenUsage.input,
|
|
12082
|
+
output_tokens: createResult.tokenUsage.output,
|
|
12083
|
+
cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
|
|
12084
|
+
metadata: JSON.stringify({ storyKey })
|
|
12085
|
+
})).catch((tokenErr) => logger$24.warn({
|
|
12086
|
+
storyKey,
|
|
12087
|
+
err: tokenErr
|
|
12088
|
+
}, "Failed to record create-story token usage"));
|
|
12090
12089
|
await persistState();
|
|
12091
12090
|
if (createResult.result === "failed") {
|
|
12092
12091
|
const errMsg = createResult.error ?? "create-story failed";
|
|
@@ -12256,21 +12255,17 @@ function createImplementationOrchestrator(deps) {
|
|
|
12256
12255
|
}, "Test planning failed — proceeding to dev-story without test plan");
|
|
12257
12256
|
}
|
|
12258
12257
|
endPhase(storyKey, "test-plan");
|
|
12259
|
-
if (config.pipelineRunId !== void 0 && testPlanTokenUsage !== void 0)
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12267
|
-
|
|
12268
|
-
|
|
12269
|
-
|
|
12270
|
-
storyKey,
|
|
12271
|
-
err: tokenErr
|
|
12272
|
-
}, "Failed to record test-plan token usage");
|
|
12273
|
-
}
|
|
12258
|
+
if (config.pipelineRunId !== void 0 && testPlanTokenUsage !== void 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
12259
|
+
phase: "test-plan",
|
|
12260
|
+
agent: "test-plan",
|
|
12261
|
+
input_tokens: testPlanTokenUsage.input,
|
|
12262
|
+
output_tokens: testPlanTokenUsage.output,
|
|
12263
|
+
cost_usd: estimateDispatchCost(testPlanTokenUsage.input, testPlanTokenUsage.output),
|
|
12264
|
+
metadata: JSON.stringify({ storyKey })
|
|
12265
|
+
})).catch((tokenErr) => logger$24.warn({
|
|
12266
|
+
storyKey,
|
|
12267
|
+
err: tokenErr
|
|
12268
|
+
}, "Failed to record test-plan token usage"));
|
|
12274
12269
|
eventBus.emit("orchestrator:story-phase-complete", {
|
|
12275
12270
|
storyKey,
|
|
12276
12271
|
phase: "IN_TEST_PLANNING",
|
|
@@ -12419,28 +12414,24 @@ function createImplementationOrchestrator(deps) {
|
|
|
12419
12414
|
batchIndex: batch.batchIndex,
|
|
12420
12415
|
files: batchFilesModified
|
|
12421
12416
|
});
|
|
12422
|
-
if (config.pipelineRunId !== void 0 && batchResult.tokenUsage !== void 0)
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
metadata: JSON.stringify({
|
|
12430
|
-
storyKey,
|
|
12431
|
-
batchIndex: batch.batchIndex,
|
|
12432
|
-
taskIds: batch.taskIds,
|
|
12433
|
-
durationMs: batchDurationMs,
|
|
12434
|
-
result: batchMetrics.result
|
|
12435
|
-
})
|
|
12436
|
-
});
|
|
12437
|
-
} catch (tokenErr) {
|
|
12438
|
-
logger$24.warn({
|
|
12417
|
+
if (config.pipelineRunId !== void 0 && batchResult.tokenUsage !== void 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
12418
|
+
phase: "dev-story",
|
|
12419
|
+
agent: `batch-${batch.batchIndex}`,
|
|
12420
|
+
input_tokens: batchResult.tokenUsage.input,
|
|
12421
|
+
output_tokens: batchResult.tokenUsage.output,
|
|
12422
|
+
cost_usd: estimateDispatchCost(batchResult.tokenUsage.input, batchResult.tokenUsage.output),
|
|
12423
|
+
metadata: JSON.stringify({
|
|
12439
12424
|
storyKey,
|
|
12440
12425
|
batchIndex: batch.batchIndex,
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12426
|
+
taskIds: batch.taskIds,
|
|
12427
|
+
durationMs: batchDurationMs,
|
|
12428
|
+
result: batchMetrics.result
|
|
12429
|
+
})
|
|
12430
|
+
})).catch((tokenErr) => logger$24.warn({
|
|
12431
|
+
storyKey,
|
|
12432
|
+
batchIndex: batch.batchIndex,
|
|
12433
|
+
err: tokenErr
|
|
12434
|
+
}, "Failed to record batch token usage"));
|
|
12444
12435
|
if (batchResult.tokenUsage?.output !== void 0) devOutputTokenCount = (devOutputTokenCount ?? 0) + batchResult.tokenUsage.output;
|
|
12445
12436
|
if (batchResult.result === "failed") logger$24.warn({
|
|
12446
12437
|
storyKey,
|
|
@@ -12478,21 +12469,17 @@ function createImplementationOrchestrator(deps) {
|
|
|
12478
12469
|
});
|
|
12479
12470
|
devFilesModified = devResult.files_modified ?? [];
|
|
12480
12471
|
devOutputTokenCount = devResult.tokenUsage?.output ?? void 0;
|
|
12481
|
-
if (config.pipelineRunId !== void 0 && devResult.tokenUsage !== void 0)
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
storyKey,
|
|
12493
|
-
err: tokenErr
|
|
12494
|
-
}, "Failed to record dev-story token usage");
|
|
12495
|
-
}
|
|
12472
|
+
if (config.pipelineRunId !== void 0 && devResult.tokenUsage !== void 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
12473
|
+
phase: "dev-story",
|
|
12474
|
+
agent: "dev-story",
|
|
12475
|
+
input_tokens: devResult.tokenUsage.input,
|
|
12476
|
+
output_tokens: devResult.tokenUsage.output,
|
|
12477
|
+
cost_usd: estimateDispatchCost(devResult.tokenUsage.input, devResult.tokenUsage.output),
|
|
12478
|
+
metadata: JSON.stringify({ storyKey })
|
|
12479
|
+
})).catch((tokenErr) => logger$24.warn({
|
|
12480
|
+
storyKey,
|
|
12481
|
+
err: tokenErr
|
|
12482
|
+
}, "Failed to record dev-story token usage"));
|
|
12496
12483
|
eventBus.emit("orchestrator:story-phase-complete", {
|
|
12497
12484
|
storyKey,
|
|
12498
12485
|
phase: "IN_DEV",
|
|
@@ -13151,23 +13138,22 @@ function createImplementationOrchestrator(deps) {
|
|
|
13151
13138
|
...baselineHeadSha ? { baselineCommit: baselineHeadSha } : {}
|
|
13152
13139
|
});
|
|
13153
13140
|
}
|
|
13154
|
-
if (config.pipelineRunId !== void 0 && reviewResult
|
|
13155
|
-
|
|
13141
|
+
if (config.pipelineRunId !== void 0 && reviewResult?.tokenUsage !== void 0) {
|
|
13142
|
+
const reviewTokens = reviewResult.tokenUsage;
|
|
13143
|
+
Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
|
|
13156
13144
|
phase: "code-review",
|
|
13157
13145
|
agent: useBatchedReview ? "code-review-batched" : "code-review",
|
|
13158
|
-
input_tokens:
|
|
13159
|
-
output_tokens:
|
|
13160
|
-
cost_usd: estimateDispatchCost(
|
|
13146
|
+
input_tokens: reviewTokens.input,
|
|
13147
|
+
output_tokens: reviewTokens.output,
|
|
13148
|
+
cost_usd: estimateDispatchCost(reviewTokens.input, reviewTokens.output),
|
|
13161
13149
|
metadata: JSON.stringify({
|
|
13162
13150
|
storyKey,
|
|
13163
13151
|
reviewCycle: reviewCycles
|
|
13164
13152
|
})
|
|
13165
|
-
})
|
|
13166
|
-
} catch (tokenErr) {
|
|
13167
|
-
logger$24.warn({
|
|
13153
|
+
})).catch((tokenErr) => logger$24.warn({
|
|
13168
13154
|
storyKey,
|
|
13169
13155
|
err: tokenErr
|
|
13170
|
-
}, "Failed to record code-review token usage");
|
|
13156
|
+
}, "Failed to record code-review token usage"));
|
|
13171
13157
|
}
|
|
13172
13158
|
const isPhantomReview = reviewResult.dispatchFailed === true || reviewResult.verdict !== "SHIP_IT" && reviewResult.verdict !== "LGTM_WITH_NOTES" && (reviewResult.issue_list === void 0 || reviewResult.issue_list.length === 0) && reviewResult.error !== void 0;
|
|
13173
13159
|
if (isPhantomReview && !timeoutRetried) {
|
|
@@ -13282,7 +13268,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13282
13268
|
});
|
|
13283
13269
|
const verifSummary = await verificationPipeline.run(verifContext, "A");
|
|
13284
13270
|
verificationStore.set(storyKey, verifSummary);
|
|
13285
|
-
persistVerificationResult(storyKey, verifSummary, runManifest);
|
|
13271
|
+
await persistVerificationResult(storyKey, verifSummary, runManifest);
|
|
13286
13272
|
if (verifSummary.status === "fail") {
|
|
13287
13273
|
updateStory(storyKey, {
|
|
13288
13274
|
phase: "VERIFICATION_FAILED",
|
|
@@ -13301,6 +13287,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
13301
13287
|
phase: "COMPLETE",
|
|
13302
13288
|
completedAt: new Date().toISOString()
|
|
13303
13289
|
});
|
|
13290
|
+
if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
|
|
13291
|
+
if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$24.warn({
|
|
13292
|
+
storyKey,
|
|
13293
|
+
category: "verification-result-missing"
|
|
13294
|
+
}, "post-COMPLETE invariant: verification_result absent in manifest");
|
|
13295
|
+
}).catch(() => {});
|
|
13304
13296
|
const completedReviewCycles = reviewCycles + 1;
|
|
13305
13297
|
await writeStoryMetricsBestEffort(storyKey, verdict, completedReviewCycles);
|
|
13306
13298
|
await writeStoryOutcomeBestEffort(storyKey, "complete", completedReviewCycles);
|
|
@@ -13540,7 +13532,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
13540
13532
|
});
|
|
13541
13533
|
const verifSummary = await verificationPipeline.run(verifContext, "A");
|
|
13542
13534
|
verificationStore.set(storyKey, verifSummary);
|
|
13543
|
-
persistVerificationResult(storyKey, verifSummary, runManifest);
|
|
13535
|
+
await persistVerificationResult(storyKey, verifSummary, runManifest);
|
|
13544
13536
|
if (verifSummary.status === "fail") {
|
|
13545
13537
|
updateStory(storyKey, {
|
|
13546
13538
|
phase: "VERIFICATION_FAILED",
|
|
@@ -13568,6 +13560,12 @@ function createImplementationOrchestrator(deps) {
|
|
|
13568
13560
|
reviewCycles: finalReviewCycles,
|
|
13569
13561
|
completedAt: new Date().toISOString()
|
|
13570
13562
|
});
|
|
13563
|
+
if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
|
|
13564
|
+
if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$24.warn({
|
|
13565
|
+
storyKey,
|
|
13566
|
+
category: "verification-result-missing"
|
|
13567
|
+
}, "post-COMPLETE invariant: verification_result absent in manifest");
|
|
13568
|
+
}).catch(() => {});
|
|
13571
13569
|
await writeStoryMetricsBestEffort(storyKey, verdict, finalReviewCycles);
|
|
13572
13570
|
await writeStoryOutcomeBestEffort(storyKey, "complete", finalReviewCycles);
|
|
13573
13571
|
eventBus.emit("orchestrator:story-complete", {
|
|
@@ -18477,7 +18475,8 @@ async function buildRunReportFromManifest(runId, runsDir, adapter, opts) {
|
|
|
18477
18475
|
...vr !== void 0 && {
|
|
18478
18476
|
verificationStatus: vr.status,
|
|
18479
18477
|
verificationChecks: vr.checks
|
|
18480
|
-
}
|
|
18478
|
+
},
|
|
18479
|
+
verification_ran: state.verification_result !== void 0 && state.verification_result !== null
|
|
18481
18480
|
});
|
|
18482
18481
|
}
|
|
18483
18482
|
const escalationFindings = Object.values(escalationDiagnoses).map((d) => d.finding);
|
|
@@ -18608,6 +18607,7 @@ async function buildRunReport(adapter, runId, opts) {
|
|
|
18608
18607
|
verificationStatus: vr.status,
|
|
18609
18608
|
verificationChecks: vr.checks
|
|
18610
18609
|
},
|
|
18610
|
+
verification_ran: vr !== void 0,
|
|
18611
18611
|
...qualityScore !== void 0 && { qualityScore },
|
|
18612
18612
|
...s$1.primary_agent_id && { agentId: s$1.primary_agent_id },
|
|
18613
18613
|
...s$1.primary_model && { model: s$1.primary_model },
|
|
@@ -43840,4 +43840,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
43840
43840
|
|
|
43841
43841
|
//#endregion
|
|
43842
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 };
|
|
43843
|
-
//# sourceMappingURL=run-
|
|
43843
|
+
//# sourceMappingURL=run-BcwaSYTg.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "./health-
|
|
1
|
+
import "./health-C6Up5GCr.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
|
-
import "./dist-
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-
|
|
4
|
+
import "./dist-CqtWS9wF.js";
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-BcwaSYTg.js";
|
|
6
6
|
import "./routing-CcBOCuC9.js";
|
|
7
7
|
import "./decisions-C0pz9Clx.js";
|
|
8
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./dist-
|
|
1
|
+
import "./dist-CqtWS9wF.js";
|
|
2
2
|
import "./version-manager-impl-BmOWu8ml.js";
|
|
3
|
-
import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-
|
|
3
|
+
import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-k15NGTno.js";
|
|
4
4
|
|
|
5
5
|
export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createVersionManager } from "./dist-
|
|
1
|
+
import { createVersionManager } from "./dist-CqtWS9wF.js";
|
|
2
2
|
import { execSync, spawn } from "child_process";
|
|
3
3
|
import * as readline from "readline";
|
|
4
4
|
|
|
@@ -123,4 +123,4 @@ function registerUpgradeCommand(program) {
|
|
|
123
123
|
|
|
124
124
|
//#endregion
|
|
125
125
|
export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
|
|
126
|
-
//# sourceMappingURL=upgrade-
|
|
126
|
+
//# sourceMappingURL=upgrade-k15NGTno.js.map
|
package/package.json
CHANGED
|
@@ -32,15 +32,16 @@ a different story from the epic scope. The story key, title, and core scope are
|
|
|
32
32
|
## Instructions
|
|
33
33
|
|
|
34
34
|
1. **Use the Story Definition as your primary input** — it specifies exactly what this story builds. The epic scope provides surrounding context only.
|
|
35
|
-
2. **
|
|
36
|
-
3. **
|
|
37
|
-
4. **
|
|
35
|
+
2. **Acceptance-criteria text from the Story Definition is read-only input.** Any AC clause from the source that contains `MUST`, `MUST NOT`, `SHALL`, `SHALL NOT`, enumerated file or directory paths, or explicit technology / storage / data-format choices (e.g., "plain JSON file", "LanceDB table", "systemd unit") must appear in the rendered story artifact's Acceptance Criteria section **verbatim**. Never soften, abstract, or paraphrase a hard clause — reshaping "MUST remove X" into "consider deprecating X" silently strips the requirement and ships code that violates its own spec. When in doubt, copy the source clause literally and add any clarifying BDD phrasing alongside it, not in place of it.
|
|
36
|
+
3. **Apply architecture constraints** — every constraint listed above is mandatory (file paths, import style, test framework, etc.)
|
|
37
|
+
4. **Use previous dev notes** as guardrails — don't repeat mistakes, build on patterns that worked
|
|
38
|
+
5. **Fill out the story template** with:
|
|
38
39
|
- A clear user story (As a / I want / So that)
|
|
39
|
-
- Acceptance criteria
|
|
40
|
+
- Acceptance criteria: preserve the hard-clause text from the Story Definition verbatim. BDD Given/When/Then phrasing is **optional** — permitted for behavior-oriented criteria where it adds clarity, not mandatory. Never let BDD reshape a MUST / MUST NOT / SHALL clause; copy those clauses literally and, if BDD adds clarity, append the Given/When/Then alongside the original clause rather than replacing it. Aim for the same number of ACs as the source — do not condense clauses into fewer items to hit a target count.
|
|
40
41
|
- Concrete tasks broken into 2–4 hour subtasks, each tied to specific ACs
|
|
41
42
|
- Dev Notes with file paths, import patterns, testing requirements
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
6. **Apply the scope cap** — see Scope Cap Guidance below
|
|
44
|
+
7. **Write the story file** to: `_bmad-output/implementation-artifacts/{{story_key}}-<kebab-title>.md`
|
|
44
45
|
- Do NOT add a `Status:` field to the story file — story status is managed exclusively by the Dolt work graph (`wg_stories` table)
|
|
45
46
|
- Dev Agent Record section must be present but left blank (to be filled by dev agent)
|
|
46
47
|
|
|
@@ -66,7 +67,9 @@ Use this exact format for each item:
|
|
|
66
67
|
|
|
67
68
|
## Runtime Verification Guidance
|
|
68
69
|
|
|
69
|
-
**
|
|
70
|
+
**If the Story Definition already contains a `## Runtime Probes` section, transfer it verbatim** — including every probe entry, YAML fenced block, and surrounding prose — into the rendered story artifact. Do not independently re-evaluate whether the story is runtime-dependent; the epic author already decided when they authored probes in the source. Adding, removing, renaming, or reshaping a source-declared probe silently subverts the author's runtime contract.
|
|
71
|
+
|
|
72
|
+
**If the Story Definition has no `## Runtime Probes` section, decide whether this story's artifact is runtime-dependent.** An artifact is runtime-dependent if correctness depends on execution — systemd units, container definitions (Podman Quadlet, Docker Compose), install scripts, migration runners, anything whose behavior is only observable by running it against a real host or ephemeral sandbox.
|
|
70
73
|
|
|
71
74
|
If the artifact is runtime-dependent, add a `## Runtime Probes` section to the story file. Each probe is a short shell command whose exit status answers "does this artifact actually work?".
|
|
72
75
|
|
|
@@ -156,11 +159,13 @@ Treat the probes you draft as a **first pass** the human author will refine. Pro
|
|
|
156
159
|
|
|
157
160
|
## Scope Cap Guidance
|
|
158
161
|
|
|
159
|
-
**Aim for 6-7 acceptance criteria and 7-8 tasks per story
|
|
162
|
+
**Aim for 6-7 acceptance criteria and 7-8 tasks per story** when you are authoring ACs from scratch.
|
|
160
163
|
|
|
161
164
|
Each story will be implemented by an AI agent in a single pass. Stories with more than 7 ACs tend to exceed agent capabilities and require decomposition, adding latency and complexity to the pipeline.
|
|
162
165
|
|
|
163
|
-
If the
|
|
166
|
+
**The scope cap does NOT license condensing source ACs.** If the Story Definition supplies more ACs than the guidance target, preserve them all verbatim — never collapse hard clauses (MUST / MUST NOT / SHALL / enumerated paths) into fewer items just to hit a count. If the source scope is too large for a single story, surface that as a failure (`result: failure`, `error: source scope exceeds single-story capacity — split upstream`) rather than silently dropping ACs.
|
|
167
|
+
|
|
168
|
+
If the scope *you are authoring from scratch* requires more than 7 ACs, split into multiple sequential stories (e.g., `7-1a: Core Setup`, `7-1b: Advanced Features`). Splitting is preferable to cramming too much scope into a single story.
|
|
164
169
|
|
|
165
170
|
This is guidance, not enforcement — if the scope genuinely fits in a slightly larger story, use your judgment. The goal is to avoid stories that will predictably fail during implementation.
|
|
166
171
|
|