substrate-ai 0.2.36 → 0.2.38

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,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createConfigSystem, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveStoryKeys, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-B9OkdDIk.js";
2
+ import { DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createConfigSystem, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveStoryKeys, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-RJ0EHbfM.js";
3
3
  import { createLogger } from "../logger-D2fS2ccL.js";
4
4
  import { AdapterRegistry } from "../adapter-registry-PsWhP_1Q.js";
5
5
  import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema } from "../config-migrator-DSi8KhQC.js";
@@ -2581,7 +2581,7 @@ async function runSupervisorAction(options, deps = {}) {
2581
2581
  const expDb = expDbWrapper.db;
2582
2582
  const { runRunAction: runPipeline } = await import(
2583
2583
  /* @vite-ignore */
2584
- "../run-LStYIzcb.js"
2584
+ "../run-Q-rgJf4a.js"
2585
2585
  );
2586
2586
  const runStoryFn = async (opts) => {
2587
2587
  const exitCode = await runPipeline({
@@ -1,20 +1,23 @@
1
1
  <!-- substrate:start -->
2
2
  ## Substrate Pipeline
3
3
 
4
- This project uses Substrate for automated implementation pipelines. Substrate runs are long-running (5–40 minutes). Plan accordingly.
4
+ 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.
5
5
 
6
6
  ### Running the Pipeline
7
7
 
8
- **Preferred Supervisor mode** (handles stalls, auto-restarts, post-run analysis):
8
+ **Just run it.** Substrate auto-detects which pipeline phase to start from (analysis planning → solutioning → implementation) and auto-discovers pending stories. You do not need to determine the phase or find story keys manually.
9
+
9
10
  ```
10
- substrate supervisor --output-format json --stories 7-1,7-2
11
+ substrate supervisor --output-format json
11
12
  ```
12
13
 
13
- **Direct mode** (simpler, no auto-recovery):
14
+ To target specific stories (if the user names them):
14
15
  ```
15
- substrate run --events --stories 7-1,7-2
16
+ substrate supervisor --output-format json --stories 1-1,1-2,1-3
16
17
  ```
17
18
 
19
+ If substrate needs input it can't auto-detect (e.g., a project concept for analysis), it will exit with a clear error message telling you what to provide.
20
+
18
21
  **CRITICAL execution rules:**
19
22
  - Pipeline runs take **5–40 minutes**. You MUST use `run_in_background: true` or `timeout: 600000` (10 min) when invoking via Bash tool. Default 2-minute timeout WILL kill the pipeline.
20
23
  - **NEVER pipe substrate output** to `head`, `tail`, `grep`, or any command that may close the pipe early — this causes EPIPE stalls that hang the process.
@@ -1,4 +1,4 @@
1
- import { registerRunCommand, runRunAction } from "./run-B9OkdDIk.js";
1
+ import { registerRunCommand, runRunAction } from "./run-RJ0EHbfM.js";
2
2
  import "./logger-D2fS2ccL.js";
3
3
  import "./config-migrator-DSi8KhQC.js";
4
4
  import "./helpers-RL22dYtn.js";
@@ -9559,6 +9559,83 @@ function sortStoryKeys(keys) {
9559
9559
  });
9560
9560
  }
9561
9561
 
9562
+ //#endregion
9563
+ //#region src/modules/phase-orchestrator/phase-detection.ts
9564
+ const PHASE_ARTIFACTS = [
9565
+ {
9566
+ phase: "research",
9567
+ type: "research-findings",
9568
+ optional: true
9569
+ },
9570
+ {
9571
+ phase: "analysis",
9572
+ type: "product-brief",
9573
+ optional: false
9574
+ },
9575
+ {
9576
+ phase: "planning",
9577
+ type: "prd",
9578
+ optional: false
9579
+ },
9580
+ {
9581
+ phase: "solutioning",
9582
+ type: "stories",
9583
+ optional: false
9584
+ }
9585
+ ];
9586
+ /**
9587
+ * Detect the next phase to run based on DB state.
9588
+ *
9589
+ * Detection logic:
9590
+ * 1. If stories exist (decisions/epics.md) → implementation
9591
+ * 2. Walk forward through phases checking for completion artifacts
9592
+ * 3. Skip optional phases (research) if no artifact found
9593
+ * 4. The first required phase WITHOUT an artifact is where we start
9594
+ * 5. If nothing exists → analysis (needs concept)
9595
+ */
9596
+ function detectStartPhase(db, projectRoot) {
9597
+ try {
9598
+ const storyKeys = resolveStoryKeys(db, projectRoot);
9599
+ if (storyKeys.length > 0) return {
9600
+ phase: "implementation",
9601
+ reason: `${storyKeys.length} stories ready for implementation`,
9602
+ needsConcept: false
9603
+ };
9604
+ } catch {}
9605
+ let lastCompletedPhase;
9606
+ try {
9607
+ for (const entry of PHASE_ARTIFACTS) {
9608
+ const row = db.prepare("SELECT id FROM artifacts WHERE phase = ? AND type = ? LIMIT 1").get(entry.phase, entry.type);
9609
+ if (row !== void 0) lastCompletedPhase = entry.phase;
9610
+ else if (!entry.optional) {
9611
+ const needsConcept = entry.phase === "analysis";
9612
+ const reason = lastCompletedPhase !== void 0 ? `${lastCompletedPhase} phase complete — continuing with ${entry.phase}` : "No pipeline state found — starting from the beginning";
9613
+ return {
9614
+ phase: entry.phase,
9615
+ needsConcept,
9616
+ reason
9617
+ };
9618
+ }
9619
+ }
9620
+ } catch {
9621
+ return {
9622
+ phase: "analysis",
9623
+ reason: "No pipeline state found — starting from the beginning",
9624
+ needsConcept: true
9625
+ };
9626
+ }
9627
+ if (lastCompletedPhase !== void 0) return {
9628
+ phase: "solutioning",
9629
+ reason: "All phases completed but no stories found — re-running solutioning",
9630
+ needsConcept: false
9631
+ };
9632
+ return {
9633
+ phase: "analysis",
9634
+ reason: "No pipeline state found — starting from the beginning",
9635
+ needsConcept: true
9636
+ };
9637
+ }
9638
+
9562
9639
  //#endregion
9563
9640
  //#region src/modules/phase-orchestrator/built-in-phases.ts
9564
9641
  function logPhase(message) {
@@ -13560,12 +13637,37 @@ async function runRunAction(options) {
13560
13637
  return 1;
13561
13638
  }
13562
13639
  }
13563
- if (startPhase !== void 0) return runFullPipeline({
13640
+ let effectiveStartPhase = startPhase;
13641
+ if (effectiveStartPhase === void 0) {
13642
+ mkdirSync(dbDir, { recursive: true });
13643
+ try {
13644
+ const detectDb = new DatabaseWrapper(dbPath);
13645
+ try {
13646
+ detectDb.open();
13647
+ runMigrations(detectDb.db);
13648
+ const detection = detectStartPhase(detectDb.db, projectRoot);
13649
+ if (detection.phase !== "implementation") {
13650
+ effectiveStartPhase = detection.phase;
13651
+ if (outputFormat === "human") process.stdout.write(`[AUTO-DETECT] ${detection.reason}\n`);
13652
+ if (detection.needsConcept && concept === void 0) {
13653
+ const errorMsg = `Pipeline needs to start from ${detection.phase} phase, which requires a concept.\nProvide --concept "your idea" or --concept-file path/to/brief.md`;
13654
+ if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, errorMsg) + "\n");
13655
+ else process.stderr.write(`Error: ${errorMsg}\n`);
13656
+ detectDb.close();
13657
+ return 1;
13658
+ }
13659
+ } else if (outputFormat === "human") process.stdout.write(`[AUTO-DETECT] ${detection.reason}\n`);
13660
+ } finally {
13661
+ detectDb.close();
13662
+ }
13663
+ } catch {}
13664
+ }
13665
+ if (effectiveStartPhase !== void 0) return runFullPipeline({
13564
13666
  packName,
13565
13667
  packPath,
13566
13668
  dbDir,
13567
13669
  dbPath,
13568
- startPhase,
13670
+ startPhase: effectiveStartPhase,
13569
13671
  stopAfter,
13570
13672
  concept,
13571
13673
  concurrency,
@@ -14431,4 +14533,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
14431
14533
 
14432
14534
  //#endregion
14433
14535
  export { DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createConfigSystem, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, resolveStoryKeys, runAnalysisPhase, runMigrations, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
14434
- //# sourceMappingURL=run-B9OkdDIk.js.map
14536
+ //# sourceMappingURL=run-RJ0EHbfM.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.2.36",
3
+ "version": "0.2.38",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",