substrate-ai 0.8.2 → 0.8.4

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
@@ -2,7 +2,7 @@
2
2
  import { DoltClient, DoltNotInstalled, FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, WorkGraphRepository, buildPipelineStatusOutput, checkDoltInstalled, createDatabaseAdapter, createDoltClient, createStateStore, detectCycles, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, initSchema, initializeDolt, isSyncAdapter, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot } from "../health-C-VRJruD.js";
3
3
  import { createLogger } from "../logger-D2fS2ccL.js";
4
4
  import { AdapterRegistry } from "../adapter-registry-D2zdMwVu.js";
5
- import { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createConfigSystem, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, registerRunCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-B4n563g1.js";
5
+ import { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createConfigSystem, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, registerRunCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-CG1LOXIa.js";
6
6
  import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema } from "../config-migrator-CtGelIsG.js";
7
7
  import { ConfigError, createEventBus } from "../helpers-CpMs8VZX.js";
8
8
  import { RoutingRecommender } from "../routing-BVrxrM6v.js";
@@ -272,49 +272,56 @@ const STACK_MARKERS = [
272
272
  language: "go",
273
273
  buildTool: "go",
274
274
  buildCommand: "go build ./...",
275
- testCommand: "go test ./..."
275
+ testCommand: "go test ./...",
276
+ installCommand: "go get <package>"
276
277
  },
277
278
  {
278
279
  file: "build.gradle.kts",
279
280
  language: "kotlin",
280
281
  buildTool: "gradle",
281
282
  buildCommand: "./gradlew build",
282
- testCommand: "./gradlew test"
283
+ testCommand: "./gradlew test",
284
+ installCommand: "add dependency to build.gradle.kts"
283
285
  },
284
286
  {
285
287
  file: "build.gradle",
286
288
  language: "java",
287
289
  buildTool: "gradle",
288
290
  buildCommand: "./gradlew build",
289
- testCommand: "./gradlew test"
291
+ testCommand: "./gradlew test",
292
+ installCommand: "add dependency to build.gradle"
290
293
  },
291
294
  {
292
295
  file: "pom.xml",
293
296
  language: "java",
294
297
  buildTool: "maven",
295
298
  buildCommand: "mvn compile",
296
- testCommand: "mvn test"
299
+ testCommand: "mvn test",
300
+ installCommand: "add dependency to pom.xml"
297
301
  },
298
302
  {
299
303
  file: "Cargo.toml",
300
304
  language: "rust",
301
305
  buildTool: "cargo",
302
306
  buildCommand: "cargo build",
303
- testCommand: "cargo test"
307
+ testCommand: "cargo test",
308
+ installCommand: "cargo add <package>"
304
309
  },
305
310
  {
306
311
  file: "pyproject.toml",
307
312
  language: "python",
308
313
  buildTool: "pip",
309
314
  buildCommand: "pip install -e .",
310
- testCommand: "pytest"
315
+ testCommand: "pytest",
316
+ installCommand: "pip install <package>"
311
317
  },
312
318
  {
313
319
  file: "package.json",
314
320
  language: "typescript",
315
321
  buildTool: "npm",
316
322
  buildCommand: "npm run build",
317
- testCommand: "npm test"
323
+ testCommand: "npm test",
324
+ installCommand: "npm install <package>"
318
325
  }
319
326
  ];
320
327
  async function fileExists(filePath) {
@@ -333,22 +340,26 @@ async function detectNodeBuildTool(dir) {
333
340
  if (await fileExists(path$2.join(dir, "pnpm-lock.yaml"))) return {
334
341
  buildTool: "pnpm",
335
342
  buildCommand: "pnpm run build",
336
- testCommand: "pnpm test"
343
+ testCommand: "pnpm test",
344
+ installCommand: "pnpm add <package>"
337
345
  };
338
346
  if (await fileExists(path$2.join(dir, "yarn.lock"))) return {
339
347
  buildTool: "yarn",
340
348
  buildCommand: "yarn build",
341
- testCommand: "yarn test"
349
+ testCommand: "yarn test",
350
+ installCommand: "yarn add <package>"
342
351
  };
343
352
  if (await fileExists(path$2.join(dir, "bun.lockb"))) return {
344
353
  buildTool: "bun",
345
354
  buildCommand: "bun run build",
346
- testCommand: "bun test"
355
+ testCommand: "bun test",
356
+ installCommand: "bun add <package>"
347
357
  };
348
358
  return {
349
359
  buildTool: "npm",
350
360
  buildCommand: "npm run build",
351
- testCommand: "npm test"
361
+ testCommand: "npm test",
362
+ installCommand: "npm install <package>"
352
363
  };
353
364
  }
354
365
  /**
@@ -372,7 +383,8 @@ async function detectSingleProjectStack(dir) {
372
383
  language: "typescript",
373
384
  buildTool: nodeInfo.buildTool,
374
385
  buildCommand: nodeInfo.buildCommand,
375
- testCommand: nodeInfo.testCommand
386
+ testCommand: nodeInfo.testCommand,
387
+ installCommand: nodeInfo.installCommand
376
388
  };
377
389
  }
378
390
  if (marker.file === "pyproject.toml") {
@@ -382,7 +394,8 @@ async function detectSingleProjectStack(dir) {
382
394
  language: "python",
383
395
  buildTool: hasPoetry ? "poetry" : "pip",
384
396
  buildCommand: hasPoetry ? "poetry build" : "pip install -e .",
385
- testCommand: "pytest"
397
+ testCommand: "pytest",
398
+ installCommand: hasPoetry ? "poetry add <package>" : "pip install <package>"
386
399
  };
387
400
  }
388
401
  return {
@@ -390,7 +403,8 @@ async function detectSingleProjectStack(dir) {
390
403
  language: marker.language,
391
404
  buildTool: marker.buildTool,
392
405
  buildCommand: marker.buildCommand,
393
- testCommand: marker.testCommand
406
+ testCommand: marker.testCommand,
407
+ installCommand: marker.installCommand
394
408
  };
395
409
  }
396
410
  return {
@@ -398,7 +412,8 @@ async function detectSingleProjectStack(dir) {
398
412
  language: "typescript",
399
413
  buildTool: "npm",
400
414
  buildCommand: "npm run build",
401
- testCommand: "npm test"
415
+ testCommand: "npm test",
416
+ installCommand: "npm install <package>"
402
417
  };
403
418
  }
404
419
  /**
@@ -435,6 +450,7 @@ async function detectMonorepoProfile(rootDir) {
435
450
  tool: "turborepo",
436
451
  buildCommand: "npx turbo build",
437
452
  testCommand: "npx turbo test",
453
+ installCommand: "npm install <package>",
438
454
  packages
439
455
  } };
440
456
  }
@@ -469,6 +485,7 @@ async function detectProjectProfile(rootDir) {
469
485
  framework: stackEntry.framework,
470
486
  buildCommand: stackEntry.buildCommand ?? "npm run build",
471
487
  testCommand: stackEntry.testCommand ?? "npm test",
488
+ installCommand: stackEntry.installCommand ?? "npm install <package>",
472
489
  packages: []
473
490
  } };
474
491
  }
@@ -1634,9 +1651,11 @@ async function runResumeAction(options) {
1634
1651
  }
1635
1652
  if (outputFormat === "human") process.stdout.write(`Resuming from phase: ${resumePhase}\n`);
1636
1653
  let concept = "";
1654
+ let scopedStories;
1637
1655
  try {
1638
1656
  const config = JSON.parse(run.config_json ?? "{}");
1639
1657
  concept = config.concept ?? "";
1658
+ if (Array.isArray(config.explicitStories) && config.explicitStories.length > 0) scopedStories = config.explicitStories;
1640
1659
  } catch {}
1641
1660
  const dbDir = dbPath.replace("/substrate.db", "");
1642
1661
  return runFullPipelineFromPhase({
@@ -1653,7 +1672,7 @@ async function runResumeAction(options) {
1653
1672
  existingRunId: runId,
1654
1673
  projectRoot,
1655
1674
  registry,
1656
- stories: options.stories
1675
+ stories: options.stories ?? scopedStories
1657
1676
  });
1658
1677
  } catch (err) {
1659
1678
  const msg = err instanceof Error ? err.message : String(err);
@@ -3276,7 +3295,8 @@ async function handleStallRecovery(health, state, config, deps, io) {
3276
3295
  const REVIEW_PHASES = new Set(["IN_REVIEW", "code-review"]);
3277
3296
  const activePhases = Object.values(health.stories.details ?? {}).map((s) => s.phase);
3278
3297
  const inReviewPhase = activePhases.some((p) => REVIEW_PHASES.has(p));
3279
- const effectiveThreshold = inReviewPhase ? stallThreshold * 2 : stallThreshold;
3298
+ const orchestratorIdle = health.process.child_pids.length === 0 && health.stories.active > 0;
3299
+ const effectiveThreshold = inReviewPhase && !orchestratorIdle ? stallThreshold * 2 : stallThreshold;
3280
3300
  if (health.staleness_seconds < effectiveThreshold) return null;
3281
3301
  const directPids = [...health.process.orchestrator_pid !== null ? [health.process.orchestrator_pid] : [], ...health.process.child_pids];
3282
3302
  const descendantPids = getAllDescendants(directPids);
@@ -3529,7 +3549,7 @@ async function runSupervisorAction(options, deps = {}) {
3529
3549
  await initSchema(expAdapter);
3530
3550
  const { runRunAction: runPipeline } = await import(
3531
3551
  /* @vite-ignore */
3532
- "../run-8Lez83bG.js"
3552
+ "../run-CoRKAliC.js"
3533
3553
  );
3534
3554
  const runStoryFn = async (opts) => {
3535
3555
  const exitCode = await runPipeline({
@@ -7196,6 +7196,41 @@ function resolveDefaultTestPatterns(projectRoot) {
7196
7196
  return VITEST_DEFAULT_PATTERNS;
7197
7197
  }
7198
7198
 
7199
+ //#endregion
7200
+ //#region src/modules/compiled-workflows/install-command.ts
7201
+ /**
7202
+ * Returns the install command string for the current project.
7203
+ * Used as a template variable ({{install_command}}) in the dev-story prompt.
7204
+ */
7205
+ function resolveInstallCommand(projectRoot) {
7206
+ if (!projectRoot) return "the appropriate package install command for this project";
7207
+ const profilePath = join$1(projectRoot, ".substrate", "project-profile.yaml");
7208
+ if (!existsSync$1(profilePath)) return "the appropriate package install command for this project";
7209
+ try {
7210
+ const content = readFileSync$1(profilePath, "utf-8");
7211
+ const match$1 = content.match(/^\s*installCommand:\s*['"]?(.+?)['"]?\s*$/m);
7212
+ if (match$1?.[1]) return match$1[1];
7213
+ const toolMatch = content.match(/^\s*buildTool:\s*['"]?(\w+)['"]?\s*$/m);
7214
+ if (toolMatch?.[1]) {
7215
+ const tool = toolMatch[1];
7216
+ const commands = {
7217
+ npm: "npm install <package>",
7218
+ pnpm: "pnpm add <package>",
7219
+ yarn: "yarn add <package>",
7220
+ bun: "bun add <package>",
7221
+ go: "go get <package>",
7222
+ cargo: "cargo add <package>",
7223
+ pip: "pip install <package>",
7224
+ poetry: "poetry add <package>",
7225
+ gradle: "add dependency to build.gradle",
7226
+ maven: "add dependency to pom.xml"
7227
+ };
7228
+ return commands[tool] ?? "the appropriate package install command for this project";
7229
+ }
7230
+ } catch {}
7231
+ return "the appropriate package install command for this project";
7232
+ }
7233
+
7199
7234
  //#endregion
7200
7235
  //#region src/modules/compiled-workflows/dev-story.ts
7201
7236
  const logger$16 = createLogger("compiled-workflows:dev-story");
@@ -7419,6 +7454,11 @@ async function runDevStory(deps, params) {
7419
7454
  name: "verify_command",
7420
7455
  content: deps.pack.manifest.verifyCommand !== false ? deps.pack.manifest.verifyCommand ?? "npx turbo build" : "",
7421
7456
  priority: "optional"
7457
+ },
7458
+ {
7459
+ name: "install_command",
7460
+ content: resolveInstallCommand(deps.projectRoot),
7461
+ priority: "optional"
7422
7462
  }
7423
7463
  ];
7424
7464
  const { prompt, tokenCount, truncated } = assemblePrompt(template, sections, TOKEN_CEILING);
@@ -21355,4 +21395,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
21355
21395
 
21356
21396
  //#endregion
21357
21397
  export { AdapterTelemetryPersistence, AppError, DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, GitClient, GrammarLoader, IngestionServer, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createConfigSystem, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, registerRunCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict };
21358
- //# sourceMappingURL=run-B4n563g1.js.map
21398
+ //# sourceMappingURL=run-CG1LOXIa.js.map
@@ -1,6 +1,6 @@
1
1
  import "./health-C-VRJruD.js";
2
2
  import "./logger-D2fS2ccL.js";
3
- import { registerRunCommand, runRunAction } from "./run-B4n563g1.js";
3
+ import { registerRunCommand, runRunAction } from "./run-CG1LOXIa.js";
4
4
  import "./config-migrator-CtGelIsG.js";
5
5
  import "./helpers-CpMs8VZX.js";
6
6
  import "./routing-BVrxrM6v.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -44,6 +44,7 @@
44
44
  "README.md"
45
45
  ],
46
46
  "scripts": {
47
+ "agent-memory:bootstrap": "node scripts/bootstrap-agent-memory.mjs",
47
48
  "build": "tsdown",
48
49
  "postbuild": "cp -r src/cli/templates dist/cli/templates && cp src/modules/state/schema.sql dist/schema.sql",
49
50
  "dev": "tsx watch src/cli/index.ts",
@@ -39,7 +39,7 @@ Implement the story above completely. Follow tasks in exact order. Do not stop u
39
39
  - Make tests pass with minimal code
40
40
  - Refactor while keeping tests green
41
41
  - **Use exact names from the story spec.** When the story specifies a field, variable, class, or method name, use that exact name in your implementation. Only deviate if the name would cause a compilation error (e.g., conflicts with a reserved word or inherited property), and add a code comment explaining why.
42
- - **If you import a new package that is not already in package.json, install it immediately** (`npm install <package>` or the appropriate workspace command). The build verification gate runs after dev-story — missing dependencies will fail the build and escalate the story.
42
+ - **If you import a new package that is not already installed, install it immediately** (`{{install_command}}` or the appropriate workspace command). The build verification gate runs after dev-story — missing dependencies will fail the build and escalate the story.
43
43
 
44
44
  3. **After each task**:
45
45
  - Verify tests pass