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, detectCycles, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-Cx2ZhRNT.js";
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-Byzy10gG.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, 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)) updatedExisting = existingContent.replace(new RegExp(`${CLAUDE_MD_START_MARKER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${CLAUDE_MD_END_MARKER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), sectionContent.trimEnd());
1688
- else {
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-CzEyqOom.js"
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.