substrate-ai 0.19.0 → 0.19.1
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, EXPERIMENT_RESULT, 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, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-Bm0qSZer.js";
|
|
6
6
|
import "../adapter-registry-DXLMTmfD.js";
|
|
7
|
-
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-
|
|
7
|
+
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-Byzy10gG.js";
|
|
8
8
|
import "../errors-BSpu7pIv.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
@@ -1135,6 +1135,17 @@ const TokenCeilingsSchema = z.object({
|
|
|
1135
1135
|
"test-plan": z.number().int().positive("test-plan token ceiling must be a positive integer").optional(),
|
|
1136
1136
|
"test-expansion": z.number().int().positive("test-expansion token ceiling must be a positive integer").optional()
|
|
1137
1137
|
});
|
|
1138
|
+
/**
|
|
1139
|
+
* Per-task-type dispatch timeout overrides (milliseconds).
|
|
1140
|
+
* Keys match task types in DEFAULT_TIMEOUTS. Values override defaults.
|
|
1141
|
+
*/
|
|
1142
|
+
const DispatchTimeoutsSchema = z.object({
|
|
1143
|
+
"create-story": z.number().int().positive().optional(),
|
|
1144
|
+
"dev-story": z.number().int().positive().optional(),
|
|
1145
|
+
"code-review": z.number().int().positive().optional(),
|
|
1146
|
+
"minor-fixes": z.number().int().positive().optional(),
|
|
1147
|
+
"major-rework": z.number().int().positive().optional()
|
|
1148
|
+
});
|
|
1138
1149
|
const SubstrateConfigSchema = z.object({
|
|
1139
1150
|
config_format_version: z.enum(["1"]),
|
|
1140
1151
|
task_graph_version: z.enum(["1"]).optional(),
|
|
@@ -1143,6 +1154,7 @@ const SubstrateConfigSchema = z.object({
|
|
|
1143
1154
|
cost_tracker: CostTrackerConfigSchema.optional(),
|
|
1144
1155
|
budget: BudgetConfigSchema.optional(),
|
|
1145
1156
|
token_ceilings: TokenCeilingsSchema.optional(),
|
|
1157
|
+
dispatch_timeouts: DispatchTimeoutsSchema.optional(),
|
|
1146
1158
|
telemetry: TelemetryConfigSchema.optional()
|
|
1147
1159
|
}).strict();
|
|
1148
1160
|
const PartialSubstrateConfigSchema = z.object({
|
|
@@ -1157,6 +1169,7 @@ const PartialSubstrateConfigSchema = z.object({
|
|
|
1157
1169
|
cost_tracker: CostTrackerConfigSchema.partial().optional(),
|
|
1158
1170
|
budget: BudgetConfigSchema.partial().optional(),
|
|
1159
1171
|
token_ceilings: TokenCeilingsSchema.optional(),
|
|
1172
|
+
dispatch_timeouts: DispatchTimeoutsSchema.optional(),
|
|
1160
1173
|
telemetry: TelemetryConfigSchema.partial().optional()
|
|
1161
1174
|
}).strict();
|
|
1162
1175
|
|
|
@@ -4529,7 +4542,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
4529
4542
|
await initSchema(expAdapter);
|
|
4530
4543
|
const { runRunAction: runPipeline } = await import(
|
|
4531
4544
|
/* @vite-ignore */
|
|
4532
|
-
"../run-
|
|
4545
|
+
"../run-CzEyqOom.js"
|
|
4533
4546
|
);
|
|
4534
4547
|
const runStoryFn = async (opts) => {
|
|
4535
4548
|
const exitCode = await runPipeline({
|
package/dist/index.d.ts
CHANGED
|
@@ -1417,6 +1417,7 @@ declare function withRetry<T>(fn: () => Promise<T>, maxRetries?: number, baseDel
|
|
|
1417
1417
|
//#endregion
|
|
1418
1418
|
//#region src/modules/config/config-schema.d.ts
|
|
1419
1419
|
//# sourceMappingURL=helpers.d.ts.map
|
|
1420
|
+
|
|
1420
1421
|
declare const SubstrateConfigSchema: z.ZodObject<{
|
|
1421
1422
|
config_format_version: z.ZodEnum<{
|
|
1422
1423
|
1: "1";
|
|
@@ -1514,6 +1515,13 @@ declare const SubstrateConfigSchema: z.ZodObject<{
|
|
|
1514
1515
|
'test-plan': z.ZodOptional<z.ZodNumber>;
|
|
1515
1516
|
'test-expansion': z.ZodOptional<z.ZodNumber>;
|
|
1516
1517
|
}, z.core.$strip>>;
|
|
1518
|
+
dispatch_timeouts: z.ZodOptional<z.ZodObject<{
|
|
1519
|
+
'create-story': z.ZodOptional<z.ZodNumber>;
|
|
1520
|
+
'dev-story': z.ZodOptional<z.ZodNumber>;
|
|
1521
|
+
'code-review': z.ZodOptional<z.ZodNumber>;
|
|
1522
|
+
'minor-fixes': z.ZodOptional<z.ZodNumber>;
|
|
1523
|
+
'major-rework': z.ZodOptional<z.ZodNumber>;
|
|
1524
|
+
}, z.core.$strip>>;
|
|
1517
1525
|
telemetry: z.ZodOptional<z.ZodObject<{
|
|
1518
1526
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1519
1527
|
port: z.ZodDefault<z.ZodNumber>;
|
|
@@ -6671,6 +6671,43 @@ function defaultFailResult(error, tokenUsage) {
|
|
|
6671
6671
|
};
|
|
6672
6672
|
}
|
|
6673
6673
|
/**
|
|
6674
|
+
* Count test cases (`it(`, `test(`, `it.each(`, `test.each(`) in modified
|
|
6675
|
+
* test files. Returns a structured summary the reviewer can use as ground
|
|
6676
|
+
* truth instead of manually estimating test counts from code inspection.
|
|
6677
|
+
*/
|
|
6678
|
+
async function countTestMetrics(filesModified, cwd) {
|
|
6679
|
+
if (!filesModified || filesModified.length === 0) return "";
|
|
6680
|
+
const testFiles = filesModified.filter((f$1) => f$1.includes(".test.") || f$1.includes(".spec.") || f$1.includes("__tests__"));
|
|
6681
|
+
if (testFiles.length === 0) return "";
|
|
6682
|
+
const results = [];
|
|
6683
|
+
let totalCount = 0;
|
|
6684
|
+
for (const file of testFiles) try {
|
|
6685
|
+
const out = execSync(`grep -cE "^\\s*(it|test|it\\.each|test\\.each)\\s*\\(" "${file}" 2>/dev/null || echo 0`, {
|
|
6686
|
+
cwd,
|
|
6687
|
+
encoding: "utf-8",
|
|
6688
|
+
timeout: 5e3
|
|
6689
|
+
}).trim();
|
|
6690
|
+
const count = parseInt(out, 10) || 0;
|
|
6691
|
+
if (count > 0) {
|
|
6692
|
+
results.push({
|
|
6693
|
+
file: file.split("/").pop(),
|
|
6694
|
+
count
|
|
6695
|
+
});
|
|
6696
|
+
totalCount += count;
|
|
6697
|
+
}
|
|
6698
|
+
} catch {}
|
|
6699
|
+
if (totalCount === 0) return "";
|
|
6700
|
+
const lines = [
|
|
6701
|
+
`VERIFIED TEST COUNT (automated — use as ground truth):`,
|
|
6702
|
+
`Total test cases: ${totalCount} across ${results.length} test file(s)`,
|
|
6703
|
+
...results.map((r) => ` ${r.file}: ${r.count} test(s)`),
|
|
6704
|
+
"",
|
|
6705
|
+
"IMPORTANT: Use this verified count when evaluating AC test coverage thresholds.",
|
|
6706
|
+
"Do NOT manually estimate test counts — use the numbers above."
|
|
6707
|
+
];
|
|
6708
|
+
return lines.join("\n");
|
|
6709
|
+
}
|
|
6710
|
+
/**
|
|
6674
6711
|
* Execute the compiled code-review workflow.
|
|
6675
6712
|
*
|
|
6676
6713
|
* Steps:
|
|
@@ -6808,6 +6845,8 @@ async function runCodeReview(deps, params) {
|
|
|
6808
6845
|
}, "Injecting prior findings into code-review prompt");
|
|
6809
6846
|
}
|
|
6810
6847
|
} catch {}
|
|
6848
|
+
const testMetricsContent = await countTestMetrics(filesModified, cwd);
|
|
6849
|
+
if (testMetricsContent) logger$12.debug({ storyKey }, "Injecting verified test-count metrics into code-review context");
|
|
6811
6850
|
const sections = [
|
|
6812
6851
|
{
|
|
6813
6852
|
name: "story_content",
|
|
@@ -6819,6 +6858,11 @@ async function runCodeReview(deps, params) {
|
|
|
6819
6858
|
content: gitDiffContent,
|
|
6820
6859
|
priority: "important"
|
|
6821
6860
|
},
|
|
6861
|
+
{
|
|
6862
|
+
name: "test_metrics",
|
|
6863
|
+
content: testMetricsContent,
|
|
6864
|
+
priority: "important"
|
|
6865
|
+
},
|
|
6822
6866
|
{
|
|
6823
6867
|
name: "previous_findings",
|
|
6824
6868
|
content: previousFindingsContent,
|
|
@@ -9715,6 +9759,52 @@ function extractExpectedStoryTitle(shardContent, storyKey) {
|
|
|
9715
9759
|
}
|
|
9716
9760
|
return null;
|
|
9717
9761
|
}
|
|
9762
|
+
/**
|
|
9763
|
+
* Check whether a story's expected NEW files already exist in the working tree,
|
|
9764
|
+
* indicating the story was implicitly implemented by adjacent stories.
|
|
9765
|
+
*
|
|
9766
|
+
* Parses the consolidated epics document for the story's "Files likely touched"
|
|
9767
|
+
* section and checks for files marked as "(new)". If all expected new files
|
|
9768
|
+
* already exist, the story is considered implicitly covered.
|
|
9769
|
+
*
|
|
9770
|
+
* Returns `true` if the story appears already covered, `false` otherwise.
|
|
9771
|
+
*/
|
|
9772
|
+
function isImplicitlyCovered(storyKey, projectRoot) {
|
|
9773
|
+
const planningDir = join$1(projectRoot, "_bmad-output", "planning-artifacts");
|
|
9774
|
+
if (!existsSync(planningDir)) return false;
|
|
9775
|
+
let epicsPath;
|
|
9776
|
+
try {
|
|
9777
|
+
const entries = readdirSync(planningDir, { encoding: "utf-8" });
|
|
9778
|
+
const match$1 = entries.find((e) => /^epics[-.].*\.md$/i.test(e) && !/^epic-\d+/.test(e));
|
|
9779
|
+
if (match$1) epicsPath = join$1(planningDir, match$1);
|
|
9780
|
+
} catch {
|
|
9781
|
+
return false;
|
|
9782
|
+
}
|
|
9783
|
+
if (!epicsPath) return false;
|
|
9784
|
+
let content;
|
|
9785
|
+
try {
|
|
9786
|
+
content = readFileSync(epicsPath, "utf-8");
|
|
9787
|
+
} catch {
|
|
9788
|
+
return false;
|
|
9789
|
+
}
|
|
9790
|
+
const escapedKey = storyKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9791
|
+
const storyHeading = new RegExp(`^###\\s+Story\\s+${escapedKey}[:\\s]`, "m");
|
|
9792
|
+
const headingMatch = storyHeading.exec(content);
|
|
9793
|
+
if (!headingMatch) return false;
|
|
9794
|
+
const sectionStart = headingMatch.index;
|
|
9795
|
+
const nextHeading = content.indexOf("\n### Story ", sectionStart + 1);
|
|
9796
|
+
const section = nextHeading > 0 ? content.slice(sectionStart, nextHeading) : content.slice(sectionStart);
|
|
9797
|
+
const filesIdx = section.indexOf("Files likely touched:");
|
|
9798
|
+
if (filesIdx < 0) return false;
|
|
9799
|
+
const filesBlock = section.slice(filesIdx);
|
|
9800
|
+
const newFilePattern = /^-\s*`([^`]+)`\s*\(new\)/gm;
|
|
9801
|
+
const expectedNewFiles = [];
|
|
9802
|
+
let fm;
|
|
9803
|
+
while ((fm = newFilePattern.exec(filesBlock)) !== null) if (fm[1]) expectedNewFiles.push(fm[1]);
|
|
9804
|
+
if (expectedNewFiles.length === 0) return false;
|
|
9805
|
+
const existCount = expectedNewFiles.filter((f$1) => existsSync(join$1(projectRoot, f$1))).length;
|
|
9806
|
+
return existCount === expectedNewFiles.length;
|
|
9807
|
+
}
|
|
9718
9808
|
const TITLE_OVERLAP_WARNING_THRESHOLD = .3;
|
|
9719
9809
|
/**
|
|
9720
9810
|
* Map a StoryPhase to the corresponding WgStoryStatus for wg_stories writes.
|
|
@@ -10318,6 +10408,25 @@ function createImplementationOrchestrator(deps) {
|
|
|
10318
10408
|
}
|
|
10319
10409
|
}
|
|
10320
10410
|
} catch {}
|
|
10411
|
+
if (storyFilePath === void 0 && projectRoot && isImplicitlyCovered(storyKey, projectRoot)) {
|
|
10412
|
+
logger$21.info({ storyKey }, `Story ${storyKey} appears implicitly covered — all expected new files already exist. Skipping create-story.`);
|
|
10413
|
+
endPhase(storyKey, "create-story");
|
|
10414
|
+
eventBus.emit("orchestrator:story-phase-complete", {
|
|
10415
|
+
storyKey,
|
|
10416
|
+
phase: "IN_STORY_CREATION",
|
|
10417
|
+
result: {
|
|
10418
|
+
result: "success",
|
|
10419
|
+
story_key: storyKey,
|
|
10420
|
+
implicitlyCovered: true
|
|
10421
|
+
}
|
|
10422
|
+
});
|
|
10423
|
+
updateStory(storyKey, {
|
|
10424
|
+
phase: "COMPLETE",
|
|
10425
|
+
completedAt: new Date().toISOString()
|
|
10426
|
+
});
|
|
10427
|
+
await persistState();
|
|
10428
|
+
return;
|
|
10429
|
+
}
|
|
10321
10430
|
if (storyFilePath === void 0) try {
|
|
10322
10431
|
incrementDispatches(storyKey);
|
|
10323
10432
|
const createResult = await runCreateStory({
|
|
@@ -39338,6 +39447,7 @@ async function runRunAction(options) {
|
|
|
39338
39447
|
});
|
|
39339
39448
|
} catch {}
|
|
39340
39449
|
let tokenCeilings;
|
|
39450
|
+
let dispatchTimeouts;
|
|
39341
39451
|
let telemetryEnabled = false;
|
|
39342
39452
|
let telemetryPort = 4318;
|
|
39343
39453
|
try {
|
|
@@ -39345,6 +39455,10 @@ async function runRunAction(options) {
|
|
|
39345
39455
|
await configSystem.load();
|
|
39346
39456
|
const cfg = configSystem.getConfig();
|
|
39347
39457
|
tokenCeilings = cfg.token_ceilings;
|
|
39458
|
+
if (cfg.dispatch_timeouts) {
|
|
39459
|
+
dispatchTimeouts = Object.fromEntries(Object.entries(cfg.dispatch_timeouts).filter(([, v]) => v !== void 0));
|
|
39460
|
+
logger.info({ dispatchTimeouts }, "Loaded dispatch timeout overrides from config");
|
|
39461
|
+
}
|
|
39348
39462
|
if (cfg.telemetry?.enabled === true) {
|
|
39349
39463
|
telemetryEnabled = true;
|
|
39350
39464
|
telemetryPort = cfg.telemetry.port ?? 4318;
|
|
@@ -39631,7 +39745,10 @@ async function runRunAction(options) {
|
|
|
39631
39745
|
const dispatcher = createDispatcher({
|
|
39632
39746
|
eventBus,
|
|
39633
39747
|
adapterRegistry: injectedRegistry,
|
|
39634
|
-
config: {
|
|
39748
|
+
config: {
|
|
39749
|
+
routingResolver,
|
|
39750
|
+
...dispatchTimeouts ? { defaultTimeouts: dispatchTimeouts } : {}
|
|
39751
|
+
}
|
|
39635
39752
|
});
|
|
39636
39753
|
eventBus.on("orchestrator:story-phase-complete", (payload) => {
|
|
39637
39754
|
try {
|
|
@@ -40498,4 +40615,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
40498
40615
|
|
|
40499
40616
|
//#endregion
|
|
40500
40617
|
export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
|
|
40501
|
-
//# sourceMappingURL=run-
|
|
40618
|
+
//# sourceMappingURL=run-Byzy10gG.js.map
|
|
@@ -2,7 +2,7 @@ import "./health-Cx2ZhRNT.js";
|
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
4
|
import "./dist-Bm0qSZer.js";
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, runRunAction } from "./run-Byzy10gG.js";
|
|
6
6
|
import "./routing-CcBOCuC9.js";
|
|
7
7
|
import "./decisions-C0pz9Clx.js";
|
|
8
8
|
|