substrate-ai 0.8.1 → 0.8.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
@@ -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-VMOBJZ7f.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";
@@ -15,7 +15,7 @@ import { Command } from "commander";
15
15
  import { fileURLToPath } from "url";
16
16
  import { dirname, join, resolve } from "path";
17
17
  import { access, mkdir, readFile, writeFile } from "fs/promises";
18
- import { chmodSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, unlinkSync, writeFileSync } from "fs";
18
+ import { appendFileSync, chmodSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, unlinkSync, writeFileSync } from "fs";
19
19
  import yaml from "js-yaml";
20
20
  import { createRequire } from "node:module";
21
21
  import * as path$2 from "node:path";
@@ -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
  }
@@ -1190,6 +1207,19 @@ async function runInitAction(options) {
1190
1207
  await scaffoldStatuslineScript(projectRoot);
1191
1208
  await scaffoldClaudeSettings(projectRoot);
1192
1209
  await scaffoldClaudeCommands(projectRoot, outputFormat);
1210
+ const gitignorePath = join(projectRoot, ".gitignore");
1211
+ const runtimeEntries = [".substrate/orchestrator.pid", ".substrate/current-run-id"];
1212
+ try {
1213
+ const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf-8") : "";
1214
+ const missing = runtimeEntries.filter((e) => !existing.includes(e));
1215
+ if (missing.length > 0) {
1216
+ const block = "\n# Substrate runtime files\n" + missing.join("\n") + "\n";
1217
+ appendFileSync(gitignorePath, block);
1218
+ logger$18.info({ entries: missing }, "Added substrate runtime files to .gitignore");
1219
+ }
1220
+ } catch (err) {
1221
+ logger$18.debug({ err }, "Could not update .gitignore (non-fatal)");
1222
+ }
1193
1223
  const doltMode = options.doltMode ?? "auto";
1194
1224
  let doltInitialized = false;
1195
1225
  if (doltMode !== "skip") try {
@@ -3516,7 +3546,7 @@ async function runSupervisorAction(options, deps = {}) {
3516
3546
  await initSchema(expAdapter);
3517
3547
  const { runRunAction: runPipeline } = await import(
3518
3548
  /* @vite-ignore */
3519
- "../run-C2dsqnZU.js"
3549
+ "../run-CoRKAliC.js"
3520
3550
  );
3521
3551
  const runStoryFn = async (opts) => {
3522
3552
  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);
@@ -14509,12 +14549,42 @@ function createImplementationOrchestrator(deps) {
14509
14549
  }
14510
14550
  endPhase(storyKey, "dev-story");
14511
14551
  {
14512
- const buildVerifyResult = config.skipBuildVerify === true ? { status: "skipped" } : runBuildVerification({
14552
+ let buildVerifyResult = config.skipBuildVerify === true ? { status: "skipped" } : runBuildVerification({
14513
14553
  verifyCommand: pack.manifest.verifyCommand,
14514
14554
  verifyTimeoutMs: pack.manifest.verifyTimeoutMs,
14515
14555
  projectRoot: projectRoot ?? process.cwd(),
14516
14556
  changedFiles: gitDiffFiles
14517
14557
  });
14558
+ if (buildVerifyResult.status === "passed") {
14559
+ const resolvedRootForTsc = projectRoot ?? process.cwd();
14560
+ const tscBin = join$1(resolvedRootForTsc, "node_modules", ".bin", "tsc");
14561
+ const hasTsc = existsSync$1(tscBin) && existsSync$1(join$1(resolvedRootForTsc, "tsconfig.json"));
14562
+ if (hasTsc) try {
14563
+ execSync(`"${tscBin}" --noEmit`, {
14564
+ cwd: resolvedRootForTsc,
14565
+ timeout: 12e4,
14566
+ encoding: "utf-8",
14567
+ stdio: [
14568
+ "pipe",
14569
+ "pipe",
14570
+ "pipe"
14571
+ ]
14572
+ });
14573
+ logger$25.info({ storyKey }, "Secondary typecheck (tsc --noEmit) passed");
14574
+ } catch (tscErr) {
14575
+ const tscOutput = tscErr instanceof Error && "stdout" in tscErr ? String(tscErr.stdout ?? "").slice(0, 2e3) : "";
14576
+ logger$25.warn({
14577
+ storyKey,
14578
+ tscOutput
14579
+ }, "Secondary typecheck (tsc --noEmit) failed — treating as build failure");
14580
+ buildVerifyResult = {
14581
+ status: "failed",
14582
+ exitCode: 2,
14583
+ output: `tsc --noEmit failed:\n${tscOutput}`,
14584
+ reason: "build-verification-failed"
14585
+ };
14586
+ }
14587
+ }
14518
14588
  if (buildVerifyResult.status === "passed") {
14519
14589
  eventBus.emit("story:build-verification-passed", { storyKey });
14520
14590
  logger$25.info({ storyKey }, "Build verification passed");
@@ -21325,4 +21395,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
21325
21395
 
21326
21396
  //#endregion
21327
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 };
21328
- //# sourceMappingURL=run-VMOBJZ7f.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-VMOBJZ7f.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.1",
3
+ "version": "0.8.3",
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