substrate-ai 0.19.1 → 0.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore,
|
|
2
|
+
import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, createDatabaseAdapter, createStateStore, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-Cx2ZhRNT.js";
|
|
3
3
|
import { createLogger } from "../logger-KeHncl-f.js";
|
|
4
4
|
import { createEventBus } from "../helpers-CElYrONe.js";
|
|
5
5
|
import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, 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, EpicIngester, 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-IZJRdd9a.js";
|
|
8
8
|
import "../errors-BSpu7pIv.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
@@ -1605,6 +1605,26 @@ function buildStackAwareDevNotes(profile) {
|
|
|
1605
1605
|
//#region src/cli/commands/init.ts
|
|
1606
1606
|
const logger$15 = createLogger("init");
|
|
1607
1607
|
const __dirname = dirname(new URL(import.meta.url).pathname);
|
|
1608
|
+
const SCAFFOLD_VERSION_REGEX = /<!-- substrate:version=([\d.]+) -->/;
|
|
1609
|
+
/**
|
|
1610
|
+
* Read the substrate package version from package.json at the given root.
|
|
1611
|
+
*/
|
|
1612
|
+
function readSubstrateVersion(pkgRoot) {
|
|
1613
|
+
try {
|
|
1614
|
+
const pkg = JSON.parse(readFileSync$1(join(pkgRoot, "package.json"), "utf8"));
|
|
1615
|
+
return pkg.version ?? "0.0.0";
|
|
1616
|
+
} catch {
|
|
1617
|
+
return "0.0.0";
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Extract the version stamped in an existing CLAUDE.md scaffold section.
|
|
1622
|
+
* Returns null if no version stamp found.
|
|
1623
|
+
*/
|
|
1624
|
+
function extractScaffoldVersion(content) {
|
|
1625
|
+
const match = SCAFFOLD_VERSION_REGEX.exec(content);
|
|
1626
|
+
return match?.[1] ?? null;
|
|
1627
|
+
}
|
|
1608
1628
|
const INIT_EXIT_SUCCESS = 0;
|
|
1609
1629
|
const INIT_EXIT_ERROR = 1;
|
|
1610
1630
|
const BMAD_FRAMEWORK_DIRS = [
|
|
@@ -1671,6 +1691,8 @@ async function scaffoldClaudeMd(projectRoot, profile) {
|
|
|
1671
1691
|
logger$15.warn({ templatePath }, "CLAUDE.md substrate section template not found; skipping");
|
|
1672
1692
|
return;
|
|
1673
1693
|
}
|
|
1694
|
+
const substrateVersion = readSubstrateVersion(pkgRoot);
|
|
1695
|
+
sectionContent = sectionContent.replace("{{SUBSTRATE_VERSION}}", substrateVersion);
|
|
1674
1696
|
if (!sectionContent.endsWith("\n")) sectionContent += "\n";
|
|
1675
1697
|
const devNotesSection = buildStackAwareDevNotes(profile ?? null);
|
|
1676
1698
|
let existingContent = "";
|
|
@@ -1684,8 +1706,11 @@ async function scaffoldClaudeMd(projectRoot, profile) {
|
|
|
1684
1706
|
else newContent = sectionContent;
|
|
1685
1707
|
else {
|
|
1686
1708
|
let updatedExisting;
|
|
1687
|
-
if (existingContent.includes(CLAUDE_MD_START_MARKER))
|
|
1688
|
-
|
|
1709
|
+
if (existingContent.includes(CLAUDE_MD_START_MARKER)) {
|
|
1710
|
+
const existingVersion = extractScaffoldVersion(existingContent);
|
|
1711
|
+
if (existingVersion && existingVersion !== substrateVersion) process.stderr.write(`Updating CLAUDE.md substrate scaffold from v${existingVersion} → v${substrateVersion}\n`);
|
|
1712
|
+
updatedExisting = existingContent.replace(new RegExp(`${CLAUDE_MD_START_MARKER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${CLAUDE_MD_END_MARKER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), sectionContent.trimEnd());
|
|
1713
|
+
} else {
|
|
1689
1714
|
const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
|
|
1690
1715
|
updatedExisting = existingContent + separator + sectionContent;
|
|
1691
1716
|
}
|
|
@@ -2634,26 +2659,6 @@ function registerConfigCommand(program, _version) {
|
|
|
2634
2659
|
});
|
|
2635
2660
|
}
|
|
2636
2661
|
|
|
2637
|
-
//#endregion
|
|
2638
|
-
//#region src/modules/work-graph/errors.ts
|
|
2639
|
-
/**
|
|
2640
|
-
* Work-graph error types.
|
|
2641
|
-
*
|
|
2642
|
-
* Story 31-7: Cycle Detection in Work Graph
|
|
2643
|
-
*/
|
|
2644
|
-
/**
|
|
2645
|
-
* Thrown by `EpicIngester.ingest()` when the provided dependency list
|
|
2646
|
-
* contains a cycle. The `cycle` field contains the path of story keys
|
|
2647
|
-
* that form the cycle (first and last element are the same).
|
|
2648
|
-
*/
|
|
2649
|
-
var CyclicDependencyError = class extends Error {
|
|
2650
|
-
constructor(cycle) {
|
|
2651
|
-
super(`Cyclic dependency detected: ${cycle.join(" → ")}`);
|
|
2652
|
-
this.cycle = cycle;
|
|
2653
|
-
this.name = "CyclicDependencyError";
|
|
2654
|
-
}
|
|
2655
|
-
};
|
|
2656
|
-
|
|
2657
2662
|
//#endregion
|
|
2658
2663
|
//#region src/cli/commands/resume.ts
|
|
2659
2664
|
const logger$13 = createLogger("resume-cmd");
|
|
@@ -4542,7 +4547,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
4542
4547
|
await initSchema(expAdapter);
|
|
4543
4548
|
const { runRunAction: runPipeline } = await import(
|
|
4544
4549
|
/* @vite-ignore */
|
|
4545
|
-
"../run-
|
|
4550
|
+
"../run-YadN-tFg.js"
|
|
4546
4551
|
);
|
|
4547
4552
|
const runStoryFn = async (opts) => {
|
|
4548
4553
|
const exitCode = await runPipeline({
|
|
@@ -8620,64 +8625,6 @@ var EpicParser = class {
|
|
|
8620
8625
|
}
|
|
8621
8626
|
};
|
|
8622
8627
|
|
|
8623
|
-
//#endregion
|
|
8624
|
-
//#region src/modules/work-graph/epic-ingester.ts
|
|
8625
|
-
var EpicIngester = class {
|
|
8626
|
-
adapter;
|
|
8627
|
-
constructor(adapter) {
|
|
8628
|
-
this.adapter = adapter;
|
|
8629
|
-
}
|
|
8630
|
-
/**
|
|
8631
|
-
* Upsert stories and sync dependencies into the database.
|
|
8632
|
-
*
|
|
8633
|
-
* Both operations are wrapped in a single transaction: if either fails the
|
|
8634
|
-
* entire batch is rolled back.
|
|
8635
|
-
*
|
|
8636
|
-
* @param stories - Parsed story metadata from `EpicParser.parseStories()`.
|
|
8637
|
-
* @param dependencies - Parsed dependency edges from `EpicParser.parseDependencies()`.
|
|
8638
|
-
* @returns `IngestResult` with counts of affected rows.
|
|
8639
|
-
*/
|
|
8640
|
-
async ingest(stories, dependencies) {
|
|
8641
|
-
const cycle = detectCycles(dependencies);
|
|
8642
|
-
if (cycle !== null) throw new CyclicDependencyError(cycle);
|
|
8643
|
-
return this.adapter.transaction(async (tx) => {
|
|
8644
|
-
let storiesUpserted = 0;
|
|
8645
|
-
for (const story of stories) {
|
|
8646
|
-
const existing = await tx.query("SELECT status FROM wg_stories WHERE story_key = ?", [story.story_key]);
|
|
8647
|
-
if (existing.length > 0) await tx.query("UPDATE wg_stories SET title = ?, updated_at = ? WHERE story_key = ?", [
|
|
8648
|
-
story.title,
|
|
8649
|
-
new Date().toISOString(),
|
|
8650
|
-
story.story_key
|
|
8651
|
-
]);
|
|
8652
|
-
else {
|
|
8653
|
-
const now = new Date().toISOString();
|
|
8654
|
-
await tx.query("INSERT INTO wg_stories (story_key, epic, title, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)", [
|
|
8655
|
-
story.story_key,
|
|
8656
|
-
String(story.epic_num),
|
|
8657
|
-
story.title,
|
|
8658
|
-
"planned",
|
|
8659
|
-
now,
|
|
8660
|
-
now
|
|
8661
|
-
]);
|
|
8662
|
-
storiesUpserted++;
|
|
8663
|
-
}
|
|
8664
|
-
}
|
|
8665
|
-
const epicNum = stories.length > 0 ? stories[0].epic_num : null;
|
|
8666
|
-
if (epicNum !== null) await tx.query(`DELETE FROM story_dependencies WHERE source = 'explicit' AND story_key LIKE ?`, [`${epicNum}-%`]);
|
|
8667
|
-
for (const dep of dependencies) await tx.query("INSERT INTO story_dependencies (story_key, depends_on, dependency_type, source) VALUES (?, ?, ?, ?)", [
|
|
8668
|
-
dep.story_key,
|
|
8669
|
-
dep.depends_on,
|
|
8670
|
-
dep.dependency_type,
|
|
8671
|
-
dep.source
|
|
8672
|
-
]);
|
|
8673
|
-
return {
|
|
8674
|
-
storiesUpserted,
|
|
8675
|
-
dependenciesReplaced: dependencies.length
|
|
8676
|
-
};
|
|
8677
|
-
});
|
|
8678
|
-
}
|
|
8679
|
-
};
|
|
8680
|
-
|
|
8681
8628
|
//#endregion
|
|
8682
8629
|
//#region src/cli/commands/ingest-epic.ts
|
|
8683
8630
|
function registerIngestEpicCommand(program) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<!-- substrate:start -->
|
|
2
|
+
<!-- substrate:version={{SUBSTRATE_VERSION}} -->
|
|
2
3
|
## Substrate Pipeline
|
|
3
4
|
|
|
4
5
|
This project uses Substrate for automated implementation pipelines. **When the user asks you to implement, build, or run the pipeline — go straight to running substrate. Do NOT explore the codebase, read source files, or plan the implementation yourself.** Substrate orchestrates sub-agents that handle all of that.
|