substrate-ai 0.20.141 → 0.20.143

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,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
- import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-BQRsVP6s.js";
2
+ import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-FUl73R5F.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, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createPipelineRun, createStderrLogger, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initWorkGraphSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-DiNK6QOD.js";
6
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-CRvusFIv.js";
6
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-B2duge-W.js";
7
7
  import "../adapter-registry-DIcrxjH8.js";
8
- import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-Doh2Ion5.js";
8
+ import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-BkijWyWk.js";
9
9
  import "../errors-B21JUhcc.js";
10
10
  import "../routing-DFxoKHDt.js";
11
11
  import { WorkGraphRepository } from "../work-graph-repository-DZyJv5pV.js";
12
12
  import "../decisions-CzSIEeGP.js";
13
13
  import "../decision-router-BAPpON_C.js";
14
- import "../interactive-prompt-CgerI5Y6.js";
14
+ import "../interactive-prompt-CtO5Tm6u.js";
15
15
  import "../recovery-engine-BKGBeBnW.js";
16
16
  import "../version-manager-impl-qFBiO4Eh.js";
17
17
  import { registerUpgradeCommand } from "../upgrade-DB7KzD9c.js";
@@ -670,6 +670,7 @@ const WHOLESALE_SUBSTRATE_IGNORES = new Set([
670
670
  ]);
671
671
  const STAR = ".substrate/*";
672
672
  const CONFIG_NEGATION = "!.substrate/config.yaml";
673
+ const PROFILE_NEGATION = "!.substrate/project-profile.yaml";
673
674
  const CODEX_PROMPTS = ".codex/prompts/";
674
675
  const CODEX_SKILLS = ".codex/skills/";
675
676
  /**
@@ -685,6 +686,9 @@ function computeSubstrateGitignore(existing) {
685
686
  const negIdx = trimmed.lastIndexOf(CONFIG_NEGATION);
686
687
  const negationEffective = negIdx !== -1 && negIdx > starIdx;
687
688
  if (!negationEffective) append.push(CONFIG_NEGATION);
689
+ const profileNegIdx = trimmed.lastIndexOf(PROFILE_NEGATION);
690
+ const profileNegationEffective = profileNegIdx !== -1 && profileNegIdx > starIdx;
691
+ if (!profileNegationEffective) append.push(PROFILE_NEGATION);
688
692
  if (!trimmed.includes(CODEX_PROMPTS)) append.push(CODEX_PROMPTS);
689
693
  if (!trimmed.includes(CODEX_SKILLS)) append.push(CODEX_SKILLS);
690
694
  let content = lines.join("\n");
@@ -925,6 +929,18 @@ async function detectSingleProjectStack(dir) {
925
929
  break;
926
930
  }
927
931
  if (marker.file === "pyproject.toml") {
932
+ const hasUv = await fileExists(path$1.join(dir, "uv.lock"));
933
+ if (hasUv) {
934
+ baseEntry = {
935
+ path: dir,
936
+ language: "python",
937
+ buildTool: "uv",
938
+ buildCommand: "uv sync",
939
+ testCommand: "uv run pytest",
940
+ installCommand: "uv add <package>"
941
+ };
942
+ break;
943
+ }
928
944
  const hasPoetry = await fileExists(path$1.join(dir, "poetry.lock"));
929
945
  if (hasPoetry) {
930
946
  baseEntry = {
@@ -7036,7 +7052,7 @@ async function runStatusAction(options) {
7036
7052
  logger$15.debug({ err }, "Work graph query failed, continuing without work graph data");
7037
7053
  }
7038
7054
  if (run === void 0) {
7039
- const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-Cm-pA1mZ.js");
7055
+ const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-CoxLvCcT.js");
7040
7056
  const substrateDirPath = join(projectRoot, ".substrate");
7041
7057
  const processInfo = inspectProcessTree$1({
7042
7058
  projectRoot,
@@ -8565,7 +8581,7 @@ async function runSupervisorAction(options, deps = {}) {
8565
8581
  await initSchema(expAdapter);
8566
8582
  const { runRunAction: runPipeline } = await import(
8567
8583
  /* @vite-ignore */
8568
- "../run-BHRkyn_H.js"
8584
+ "../run-DRwOPt3k.js"
8569
8585
  );
8570
8586
  const runStoryFn = async (opts) => {
8571
8587
  const exitCode = await runPipeline({
@@ -1,7 +1,7 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-BQRsVP6s.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-FUl73R5F.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./dist-DiNK6QOD.js";
4
- import "./manifest-read-Doh2Ion5.js";
4
+ import "./manifest-read-BkijWyWk.js";
5
5
  import "./work-graph-repository-DZyJv5pV.js";
6
6
  import "./decisions-CzSIEeGP.js";
7
7
 
@@ -1,6 +1,6 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
2
  import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-DiNK6QOD.js";
3
- import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-Doh2Ion5.js";
3
+ import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-BkijWyWk.js";
4
4
  import { createRequire } from "module";
5
5
  import { dirname, join } from "path";
6
6
  import { existsSync, readFileSync } from "node:fs";
@@ -1000,4 +1000,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
1000
1000
 
1001
1001
  //#endregion
1002
1002
  export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, runHealthAction, validateStoryKey };
1003
- //# sourceMappingURL=health-BQRsVP6s.js.map
1003
+ //# sourceMappingURL=health-FUl73R5F.js.map
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { readCurrentRunId, resolveMainRepoRoot } from "./manifest-read-Doh2Ion5.js";
2
+ import { readCurrentRunId, resolveMainRepoRoot } from "./manifest-read-BkijWyWk.js";
3
3
  import { join } from "node:path";
4
4
  import { mkdir, readFile, writeFile } from "node:fs/promises";
5
5
  import * as readline from "node:readline";
@@ -180,4 +180,4 @@ async function runInteractivePrompt(decisionContext) {
180
180
 
181
181
  //#endregion
182
182
  export { runInteractivePrompt };
183
- //# sourceMappingURL=interactive-prompt-CgerI5Y6.js.map
183
+ //# sourceMappingURL=interactive-prompt-CtO5Tm6u.js.map
@@ -8,7 +8,7 @@ import { YAMLException, load } from "js-yaml";
8
8
  import { existsSync, promises, readFileSync, readdirSync, statSync } from "node:fs";
9
9
  import { execSync, spawn } from "node:child_process";
10
10
  import * as path$2 from "node:path";
11
- import { basename as basename$1, dirname as dirname$1, join as join$1, resolve as resolve$1 } from "node:path";
11
+ import { basename as basename$1, delimiter, dirname as dirname$1, join as join$1, resolve as resolve$1 } from "node:path";
12
12
  import { z } from "zod";
13
13
  import { mkdir as mkdir$1, open, readFile as readFile$1, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
14
14
  import * as fs from "fs";
@@ -2043,11 +2043,11 @@ function findCodeEvidence(opts) {
2043
2043
  /** Hard timeout for the build command in milliseconds (FR-V11). */
2044
2044
  const BUILD_CHECK_TIMEOUT_MS = 6e4;
2045
2045
  /** Maximum characters to include in details string from build output. */
2046
- const MAX_OUTPUT_CHARS = 2e3;
2046
+ const MAX_OUTPUT_CHARS$1 = 2e3;
2047
2047
  /** Per-stream tail size cap for structured findings (story 55-1 convention). */
2048
2048
  const TAIL_BYTES = 4 * 1024;
2049
2049
  /** Return the last N bytes of a UTF-8 string, sliced by string length for simplicity. */
2050
- function tail$1(text, bytes = TAIL_BYTES) {
2050
+ function tail$2(text, bytes = TAIL_BYTES) {
2051
2051
  return text.length <= bytes ? text : text.slice(text.length - bytes);
2052
2052
  }
2053
2053
  /**
@@ -2061,11 +2061,9 @@ function tail$1(text, bytes = TAIL_BYTES) {
2061
2061
  * This function inlines the detection logic independently.
2062
2062
  */
2063
2063
  function detectBuildCommand(workingDir) {
2064
+ const profileCommand = readProfileBuildCommand(workingDir);
2065
+ if (profileCommand !== void 0) return profileCommand;
2064
2066
  if (existsSync(join$1(workingDir, "turbo.json"))) return "turbo build";
2065
- if (existsSync(join$1(workingDir, "pnpm-lock.yaml"))) return "pnpm run build";
2066
- if (existsSync(join$1(workingDir, "yarn.lock"))) return "yarn build";
2067
- if (existsSync(join$1(workingDir, "bun.lockb"))) return "bun run build";
2068
- if (existsSync(join$1(workingDir, "package.json"))) return "npm run build";
2069
2067
  const nonNodeMarkers = [
2070
2068
  "pyproject.toml",
2071
2069
  "poetry.lock",
@@ -2074,9 +2072,29 @@ function detectBuildCommand(workingDir) {
2074
2072
  "go.mod"
2075
2073
  ];
2076
2074
  for (const marker of nonNodeMarkers) if (existsSync(join$1(workingDir, marker))) return "";
2075
+ if (existsSync(join$1(workingDir, "pnpm-lock.yaml"))) return "pnpm run build";
2076
+ if (existsSync(join$1(workingDir, "yarn.lock"))) return "yarn build";
2077
+ if (existsSync(join$1(workingDir, "bun.lockb"))) return "bun run build";
2078
+ if (existsSync(join$1(workingDir, "package.json"))) return "npm run build";
2077
2079
  return "";
2078
2080
  }
2079
2081
  /**
2082
+ * Read `project.buildCommand` from `.substrate/project-profile.yaml` under
2083
+ * `workingDir`. Line-based parse (same approach as the monolith's
2084
+ * resolveInstallCommand) to avoid a yaml dependency. Returns undefined when
2085
+ * the profile is absent, unreadable, or has no buildCommand.
2086
+ */
2087
+ function readProfileBuildCommand(workingDir) {
2088
+ const profilePath = join$1(workingDir, ".substrate", "project-profile.yaml");
2089
+ if (!existsSync(profilePath)) return void 0;
2090
+ try {
2091
+ const content = readFileSync(profilePath, "utf-8");
2092
+ const match = content.match(/^\s*buildCommand:\s*['"]?(.+?)['"]?\s*$/m);
2093
+ if (match?.[1] !== void 0 && match[1].length > 0) return match[1];
2094
+ } catch {}
2095
+ return void 0;
2096
+ }
2097
+ /**
2080
2098
  * Runs the project's build command and returns pass/warn/fail based on exit code.
2081
2099
  *
2082
2100
  * AC1: exit code 0 → pass
@@ -2139,8 +2157,8 @@ var BuildCheck = class {
2139
2157
  severity: "error",
2140
2158
  message: `command exceeded ${BUILD_CHECK_TIMEOUT_MS}ms`,
2141
2159
  command: cmd,
2142
- stdoutTail: tail$1(stdout),
2143
- stderrTail: tail$1(stderr),
2160
+ stdoutTail: tail$2(stdout),
2161
+ stderrTail: tail$2(stderr),
2144
2162
  durationMs: duration
2145
2163
  }];
2146
2164
  resolve$2({
@@ -2160,13 +2178,169 @@ var BuildCheck = class {
2160
2178
  findings: []
2161
2179
  });
2162
2180
  else {
2163
- const truncated = output.length > MAX_OUTPUT_CHARS ? output.slice(0, MAX_OUTPUT_CHARS) + "... (truncated)" : output;
2181
+ const truncated = output.length > MAX_OUTPUT_CHARS$1 ? output.slice(0, MAX_OUTPUT_CHARS$1) + "... (truncated)" : output;
2164
2182
  const findings = [{
2165
2183
  category: "build-error",
2166
2184
  severity: "error",
2167
2185
  message: `build failed (exit ${code}): ${truncated}`,
2168
2186
  command: cmd,
2169
2187
  ...code !== null ? { exitCode: code } : {},
2188
+ stdoutTail: tail$2(stdout),
2189
+ stderrTail: tail$2(stderr),
2190
+ durationMs: duration
2191
+ }];
2192
+ resolve$2({
2193
+ status: "fail",
2194
+ details: renderFindings(findings),
2195
+ duration_ms: duration,
2196
+ findings
2197
+ });
2198
+ }
2199
+ });
2200
+ });
2201
+ }
2202
+ };
2203
+
2204
+ //#endregion
2205
+ //#region packages/sdlc/dist/verification/checks/test-suite-check.js
2206
+ /** Hard ceiling for the suite run (ms). Suites are slower than builds. */
2207
+ const TEST_SUITE_CHECK_TIMEOUT_MS = 3e5;
2208
+ /** Cap on captured output embedded in the finding. */
2209
+ const MAX_OUTPUT_CHARS = 4e3;
2210
+ function tail$1(s, n = 2e3) {
2211
+ return s.length > n ? s.slice(-n) : s;
2212
+ }
2213
+ /**
2214
+ * Read `project.testCommand` from `.substrate/project-profile.yaml` under
2215
+ * `workingDir`. Line-based parse (no yaml dependency; same pattern as
2216
+ * detectBuildCommand's profile read). Returns undefined when absent.
2217
+ */
2218
+ function detectTestCommand(workingDir) {
2219
+ const profilePath = join$1(workingDir, ".substrate", "project-profile.yaml");
2220
+ if (!existsSync(profilePath)) return void 0;
2221
+ try {
2222
+ const content = readFileSync(profilePath, "utf-8");
2223
+ const match = content.match(/^\s*testCommand:\s*['"]?(.+?)['"]?\s*$/m);
2224
+ if (match?.[1] !== void 0 && match[1].length > 0) return match[1];
2225
+ } catch {}
2226
+ return void 0;
2227
+ }
2228
+ var TestSuiteCheck = class {
2229
+ name = "test-suite";
2230
+ tier = "A";
2231
+ async run(context) {
2232
+ const start = Date.now();
2233
+ const explicitOverride = context.testCommand !== void 0;
2234
+ const cmd = explicitOverride ? context.testCommand : detectTestCommand(context.workingDir);
2235
+ if (!explicitOverride && process.env.VITEST !== void 0 && process.env.SUBSTRATE_ALLOW_NESTED_TESTS !== "1") {
2236
+ const findings = [{
2237
+ category: "test-suite-skip",
2238
+ severity: "warn",
2239
+ message: "recursion guard: refusing to run an auto-detected test suite from inside a test runner (VITEST is set). Pass an explicit testCommand, or set SUBSTRATE_ALLOW_NESTED_TESTS=1 in a harness that deliberately nests suite execution."
2240
+ }];
2241
+ return {
2242
+ status: "warn",
2243
+ details: renderFindings(findings),
2244
+ duration_ms: Date.now() - start,
2245
+ findings
2246
+ };
2247
+ }
2248
+ if (cmd === void 0 || cmd === "") {
2249
+ const findings = [{
2250
+ category: "test-suite-skip",
2251
+ severity: "warn",
2252
+ message: `no test command configured for project at ${context.workingDir} — set project.testCommand in .substrate/project-profile.yaml (substrate init detects it) so verification runs the real suite`
2253
+ }];
2254
+ return {
2255
+ status: "warn",
2256
+ details: renderFindings(findings),
2257
+ duration_ms: Date.now() - start,
2258
+ findings
2259
+ };
2260
+ }
2261
+ return new Promise((resolve$2) => {
2262
+ const env = { ...process.env };
2263
+ const parentNodeOpts = env["NODE_OPTIONS"] ?? "";
2264
+ if (!parentNodeOpts.includes("--max-old-space-size")) env["NODE_OPTIONS"] = `${parentNodeOpts} --max-old-space-size=2048`.trim();
2265
+ const child = spawn(cmd, [], {
2266
+ cwd: context.workingDir,
2267
+ detached: true,
2268
+ shell: true,
2269
+ env,
2270
+ stdio: [
2271
+ "ignore",
2272
+ "pipe",
2273
+ "pipe"
2274
+ ]
2275
+ });
2276
+ let stdout = "";
2277
+ let stderr = "";
2278
+ let output = "";
2279
+ child.stdout?.on("data", (chunk) => {
2280
+ const s = chunk.toString();
2281
+ stdout += s;
2282
+ output += s;
2283
+ });
2284
+ child.stderr?.on("data", (chunk) => {
2285
+ const s = chunk.toString();
2286
+ stderr += s;
2287
+ output += s;
2288
+ });
2289
+ const timeoutHandle = setTimeout(() => {
2290
+ try {
2291
+ process.kill(-child.pid, "SIGKILL");
2292
+ } catch {}
2293
+ const duration = Date.now() - start;
2294
+ const findings = [{
2295
+ category: "test-suite-timeout",
2296
+ severity: "error",
2297
+ message: `test suite exceeded ${TEST_SUITE_CHECK_TIMEOUT_MS}ms`,
2298
+ command: cmd,
2299
+ stdoutTail: tail$1(stdout),
2300
+ stderrTail: tail$1(stderr),
2301
+ durationMs: duration
2302
+ }];
2303
+ resolve$2({
2304
+ status: "fail",
2305
+ details: renderFindings(findings),
2306
+ duration_ms: duration,
2307
+ findings
2308
+ });
2309
+ }, TEST_SUITE_CHECK_TIMEOUT_MS);
2310
+ child.on("error", (err) => {
2311
+ clearTimeout(timeoutHandle);
2312
+ const duration = Date.now() - start;
2313
+ const findings = [{
2314
+ category: "test-suite-error",
2315
+ severity: "error",
2316
+ message: `test command could not be spawned: ${err.message}`,
2317
+ command: cmd,
2318
+ durationMs: duration
2319
+ }];
2320
+ resolve$2({
2321
+ status: "fail",
2322
+ details: renderFindings(findings),
2323
+ duration_ms: duration,
2324
+ findings
2325
+ });
2326
+ });
2327
+ child.on("close", (code) => {
2328
+ clearTimeout(timeoutHandle);
2329
+ const duration = Date.now() - start;
2330
+ if (code === 0) resolve$2({
2331
+ status: "pass",
2332
+ details: `test suite passed (${cmd})`,
2333
+ duration_ms: duration,
2334
+ findings: []
2335
+ });
2336
+ else {
2337
+ const truncated = output.length > MAX_OUTPUT_CHARS ? output.slice(0, MAX_OUTPUT_CHARS) + "... (truncated)" : output;
2338
+ const findings = [{
2339
+ category: "test-suite-fail",
2340
+ severity: "error",
2341
+ message: `test suite failed (exit ${String(code)}): ${truncated}`,
2342
+ command: cmd,
2343
+ ...code !== null ? { exitCode: code } : {},
2170
2344
  stdoutTail: tail$1(stdout),
2171
2345
  stderrTail: tail$1(stderr),
2172
2346
  durationMs: duration
@@ -2380,6 +2554,35 @@ function parseRuntimeProbes(storyContent) {
2380
2554
 
2381
2555
  //#endregion
2382
2556
  //#region packages/sdlc/dist/verification/probes/executor.js
2557
+ /**
2558
+ * H1.3 (hardening program, field finding #6): shape the probe environment so
2559
+ * probe commands run in the PROJECT'S environment, not the orchestrator's.
2560
+ *
2561
+ * The field failure: probe `registry-rejects-undeclared-source` ran bare
2562
+ * `python` from the inherited PATH — outside the project venv — and died with
2563
+ * `ModuleNotFoundError: No module named 'structlog'` even though the behavior
2564
+ * it tested passed in-env. That single false negative flipped an
2565
+ * LGTM_WITH_NOTES story to VERIFICATION_FAILED and destabilized the rest of
2566
+ * the run.
2567
+ *
2568
+ * When the working dir carries a project-local env (`.venv/bin` — created by
2569
+ * uv, venv, virtualenv alike), prepend it to PATH and set VIRTUAL_ENV so bare
2570
+ * `python`/`pytest`/console-script invocations resolve inside the project.
2571
+ * PATH prepending (rather than command rewriting) is quoting-hazard-free and
2572
+ * tool-agnostic. POSIX layout only (`bin/`) — matches substrate's supported
2573
+ * platforms; extend for `Scripts/` if Windows dispatch ever lands.
2574
+ *
2575
+ * Pure given (cwd, baseEnv) + exported for testing.
2576
+ */
2577
+ function buildProbeEnv(cwd, baseEnv = process.env) {
2578
+ const venvBin = join$1(cwd, ".venv", "bin");
2579
+ if (!existsSync(venvBin)) return baseEnv;
2580
+ return {
2581
+ ...baseEnv,
2582
+ VIRTUAL_ENV: join$1(cwd, ".venv"),
2583
+ PATH: `${venvBin}${delimiter}${baseEnv.PATH ?? ""}`
2584
+ };
2585
+ }
2383
2586
  /** Return the last N bytes of a UTF-8 string (sliced by length for simplicity). */
2384
2587
  function tail(text, bytes = PROBE_TAIL_BYTES) {
2385
2588
  return text.length <= bytes ? text : text.slice(text.length - bytes);
@@ -2868,7 +3071,13 @@ function probesInvokeProductionTrigger(probes) {
2868
3071
  for (const probe of probes) for (const pattern of TRIGGER_COMMAND_PATTERNS) if (pattern.test(probe.command)) return true;
2869
3072
  return false;
2870
3073
  }
2871
- const defaultExecutors = { host: (probe, cwd) => executeProbeOnHost(probe, { cwd: cwd ?? process.cwd() }) };
3074
+ const defaultExecutors = { host: (probe, cwd) => {
3075
+ const effectiveCwd = cwd ?? process.cwd();
3076
+ return executeProbeOnHost(probe, {
3077
+ cwd: effectiveCwd,
3078
+ env: buildProbeEnv(effectiveCwd)
3079
+ });
3080
+ } };
2872
3081
  var RuntimeProbeCheck = class {
2873
3082
  name = "runtime-probes";
2874
3083
  tier = "A";
@@ -4082,6 +4291,7 @@ function createDefaultVerificationPipeline(bus, config) {
4082
4291
  new TrivialOutputCheck(config),
4083
4292
  new AcceptanceCriteriaEvidenceCheck(),
4084
4293
  new BuildCheck(),
4294
+ new TestSuiteCheck(),
4085
4295
  new RuntimeProbeCheck(),
4086
4296
  new SourceAcFidelityCheck(),
4087
4297
  new SourceAcShelloutCheck(),
@@ -5865,4 +6075,4 @@ async function resolveRunManifest(dbRoot, runId) {
5865
6075
 
5866
6076
  //#endregion
5867
6077
  export { FindingsInjector, RunManifest, RuntimeProbeListSchema, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, readCurrentRunId, renderFindings, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck, runStaleVerificationRecovery };
5868
- //# sourceMappingURL=manifest-read-Doh2Ion5.js.map
6078
+ //# sourceMappingURL=manifest-read-BkijWyWk.js.map
@@ -1,6 +1,6 @@
1
1
  import "../../logger-KeHncl-f.js";
2
2
  import "../../dist-DiNK6QOD.js";
3
- import "../../manifest-read-Doh2Ion5.js";
4
- import { runInteractivePrompt } from "../../interactive-prompt-CgerI5Y6.js";
3
+ import "../../manifest-read-BkijWyWk.js";
4
+ import { runInteractivePrompt } from "../../interactive-prompt-CtO5Tm6u.js";
5
5
 
6
6
  export { runInteractivePrompt };
@@ -1,11 +1,11 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-BQRsVP6s.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-FUl73R5F.js";
2
2
  import { createLogger } from "./logger-KeHncl-f.js";
3
3
  import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
4
4
  import { ADVISORY_NOTES, CLAUDE_AUTH_FAILURE_HINT, CODEX_SANDBOX_BLOCK_HINT, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, createStderrLogger, detectClaudeAuthFailure, detectCodexSandboxBlock, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-DiNK6QOD.js";
5
- import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-Doh2Ion5.js";
5
+ import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-BkijWyWk.js";
6
6
  import { WorkGraphRepository, detectCycles } from "./work-graph-repository-DZyJv5pV.js";
7
7
  import { deriveExitCode, routeDecision } from "./decision-router-BAPpON_C.js";
8
- import { runInteractivePrompt } from "./interactive-prompt-CgerI5Y6.js";
8
+ import { runInteractivePrompt } from "./interactive-prompt-CtO5Tm6u.js";
9
9
  import { runRecoveryEngine } from "./recovery-engine-BKGBeBnW.js";
10
10
  import { basename, dirname, extname, join } from "path";
11
11
  import { access, readFile, readdir, stat } from "fs/promises";
@@ -557,7 +557,8 @@ var GitWorktreeManagerImpl = class {
557
557
  baseBranch,
558
558
  copyFiles: this._copyFiles
559
559
  }, "createWorktree");
560
- await createWorktree(this._projectRoot, taskId, branchName, baseBranch, this._copyFiles);
560
+ const copyFiles = this._copyFiles.includes(".substrate/project-profile.yaml") ? this._copyFiles : [...this._copyFiles, ".substrate/project-profile.yaml"];
561
+ await createWorktree(this._projectRoot, taskId, branchName, baseBranch, copyFiles);
561
562
  const createdAt = new Date();
562
563
  this._eventBus.emit("worktree:created", {
563
564
  taskId,
@@ -8253,6 +8254,22 @@ function resolveDefaultTestPatterns(projectRoot) {
8253
8254
  //#endregion
8254
8255
  //#region src/modules/compiled-workflows/install-command.ts
8255
8256
  /**
8257
+ * Read a single `<key>: value` line from the project profile under
8258
+ * `projectRoot` (H1.2). Line-based parse, no yaml dependency. Returns
8259
+ * undefined when the profile or key is absent.
8260
+ */
8261
+ function resolveProfileCommand(projectRoot, key) {
8262
+ if (!projectRoot) return void 0;
8263
+ const profilePath = join$1(projectRoot, ".substrate", "project-profile.yaml");
8264
+ if (!existsSync(profilePath)) return void 0;
8265
+ try {
8266
+ const content = readFileSync(profilePath, "utf-8");
8267
+ const match$2 = content.match(new RegExp(`^\\s*${key}:\\s*['"]?(.+?)['"]?\\s*$`, "m"));
8268
+ if (match$2?.[1] && match$2[1].length > 0) return match$2[1];
8269
+ } catch {}
8270
+ return void 0;
8271
+ }
8272
+ /**
8256
8273
  * Returns the install command string for the current project.
8257
8274
  * Used as a template variable ({{install_command}}) in the dev-story prompt.
8258
8275
  */
@@ -8276,6 +8293,7 @@ function resolveInstallCommand(projectRoot) {
8276
8293
  cargo: "cargo add <package>",
8277
8294
  pip: "pip install <package>",
8278
8295
  poetry: "poetry add <package>",
8296
+ uv: "uv add <package>",
8279
8297
  gradle: "add dependency to build.gradle",
8280
8298
  maven: "add dependency to pom.xml"
8281
8299
  };
@@ -8516,7 +8534,7 @@ async function runDevStory(deps, params) {
8516
8534
  },
8517
8535
  {
8518
8536
  name: "verify_command",
8519
- content: deps.pack.manifest.verifyCommand !== false ? deps.pack.manifest.verifyCommand ?? "npx turbo build" : "",
8537
+ content: deps.pack.manifest.verifyCommand !== false ? deps.pack.manifest.verifyCommand ?? resolveProfileCommand(deps.projectRoot, "buildCommand") ?? "" : "",
8520
8538
  priority: "optional"
8521
8539
  },
8522
8540
  {
@@ -11740,6 +11758,8 @@ function shouldRunTscCheck(projectRoot) {
11740
11758
  if (!project) return true;
11741
11759
  const packages = project["packages"];
11742
11760
  if (Array.isArray(packages) && packages.length > 0) return packages.some((p) => p.language === "typescript" || p.language === "javascript");
11761
+ const language = project["language"];
11762
+ if (typeof language === "string" && language.length > 0) return language === "typescript" || language === "javascript";
11743
11763
  const buildCommand = project["buildCommand"];
11744
11764
  if (typeof buildCommand === "string" && buildCommand.length > 0) {
11745
11765
  const tsIndicators = [
@@ -12586,6 +12606,8 @@ function assembleVerificationContext(opts) {
12586
12606
  } catch {
12587
12607
  commitSha = "unknown";
12588
12608
  }
12609
+ const profileBuildCommand = readProfileKey(opts.workingDir, "buildCommand");
12610
+ const profileTestCommand = readProfileKey(opts.workingDir, "testCommand");
12589
12611
  return {
12590
12612
  storyKey: opts.storyKey,
12591
12613
  workingDir: opts.workingDir,
@@ -12596,10 +12618,26 @@ function assembleVerificationContext(opts) {
12596
12618
  devStoryResult: opts.devStoryResult,
12597
12619
  outputTokenCount: opts.outputTokenCount,
12598
12620
  sourceEpicContent: opts.sourceEpicContent,
12599
- runId: opts.runId
12621
+ runId: opts.runId,
12622
+ ...profileBuildCommand !== void 0 ? { buildCommand: profileBuildCommand } : {},
12623
+ ...profileTestCommand !== void 0 ? { testCommand: profileTestCommand } : {}
12600
12624
  };
12601
12625
  }
12602
12626
  /**
12627
+ * Read a single `<key>: value` line from `.substrate/project-profile.yaml`
12628
+ * under `workingDir` (H1.2). Line-based parse — no yaml dependency.
12629
+ */
12630
+ function readProfileKey(workingDir, key) {
12631
+ const profilePath = join$1(workingDir, ".substrate", "project-profile.yaml");
12632
+ if (!existsSync(profilePath)) return void 0;
12633
+ try {
12634
+ const content = readFileSync(profilePath, "utf-8");
12635
+ const match$2 = content.match(new RegExp(`^\\s*${key}:\\s*['"]?(.+?)['"]?\\s*$`, "m"));
12636
+ if (match$2?.[1] && match$2[1].length > 0) return match$2[1];
12637
+ } catch {}
12638
+ return void 0;
12639
+ }
12640
+ /**
12603
12641
  * In-memory store for VerificationSummary results, keyed by story key.
12604
12642
  *
12605
12643
  * Persists for the lifetime of the orchestrator instance. Does NOT write
@@ -13452,6 +13490,34 @@ function summarizeEscalationIssues(issues, cap = 4e3) {
13452
13490
  * the opaque verdict. Best-effort: a probe failure yields an empty list (never
13453
13491
  * blocks escalation). Exported for unit testing.
13454
13492
  */
13493
+ /**
13494
+ * H1.4 (hardening program, field finding #13): classify a story's ground-truth
13495
+ * git diff into implementation vs. pipeline-artifact changes.
13496
+ *
13497
+ * The field failure: story 2-3 returned status=complete with "239 tests pass"
13498
+ * while its branch contained ONLY the create-story spec file — zero source,
13499
+ * zero tests (the 239 were the pre-existing suite; true but vacuous). The
13500
+ * zero-diff gate never fired because the spec .md IS a diff entry.
13501
+ *
13502
+ * A file counts as implementation when it lives outside substrate's own
13503
+ * artifact trees (`_bmad-output/`, `.substrate/`). Story specs, planning
13504
+ * artifacts, and manifest state are pipeline bookkeeping — a "successful"
13505
+ * dev pass whose diff is bookkeeping-only produced no implementation.
13506
+ *
13507
+ * Pure + exported for unit testing.
13508
+ */
13509
+ function classifyImplementationDiff(files) {
13510
+ const isArtifact = (f$1) => {
13511
+ const norm = f$1.replace(/\\/g, "/").replace(/^\.\//, "");
13512
+ return norm.startsWith("_bmad-output/") || norm.startsWith(".substrate/");
13513
+ };
13514
+ const artifactOnly = files.filter(isArtifact);
13515
+ const hasImplementation = files.some((f$1) => !isArtifact(f$1));
13516
+ return {
13517
+ hasImplementation,
13518
+ artifactOnly
13519
+ };
13520
+ }
13455
13521
  function detectWorkOutsideWorktree(effectiveProjectRoot, projectRoot, checkDiff) {
13456
13522
  const inWorktreeMode = effectiveProjectRoot !== void 0 && projectRoot !== void 0 && effectiveProjectRoot !== projectRoot;
13457
13523
  if (!inWorktreeMode) return [];
@@ -15662,6 +15728,31 @@ function createImplementationOrchestrator(deps) {
15662
15728
  }
15663
15729
  }
15664
15730
  }
15731
+ if (devStoryWasSuccess && gitDiffFiles !== void 0 && gitDiffFiles.length > 0) {
15732
+ const implClassification = classifyImplementationDiff(gitDiffFiles);
15733
+ if (!implClassification.hasImplementation) {
15734
+ logger$27.warn({
15735
+ storyKey,
15736
+ artifactFiles: implClassification.artifactOnly.slice(0, 10)
15737
+ }, "dev-story reported success but the diff contains only pipeline artifacts — no implementation was produced");
15738
+ endPhase(storyKey, "dev-story", devStoryModel);
15739
+ updateStory(storyKey, {
15740
+ phase: "ESCALATED",
15741
+ error: "no-implementation",
15742
+ completedAt: new Date().toISOString()
15743
+ });
15744
+ await writeStoryMetricsBestEffort(storyKey, "escalated", 0);
15745
+ await emitEscalation({
15746
+ storyKey,
15747
+ lastVerdict: "no-implementation",
15748
+ reviewCycles: 0,
15749
+ issues: [`dev-story reported COMPLETE but every changed file is a pipeline artifact (${implClassification.artifactOnly.slice(0, 10).join(", ")}) — no source or test files were produced. Self-reported test results on such a story are vacuous (they exercise the pre-existing suite).`],
15750
+ escalationReason: "no-implementation"
15751
+ });
15752
+ await persistState();
15753
+ return;
15754
+ }
15755
+ }
15665
15756
  let _devOutputCommitHookFailure;
15666
15757
  const _commitFirstEligible = !noWorktree && _worktreeManager !== void 0 && effectiveProjectRoot !== void 0 && effectiveProjectRoot !== projectRoot;
15667
15758
  if (_commitFirstEligible && effectiveProjectRoot !== void 0) {
@@ -29930,7 +30021,7 @@ var require_uri_all = __commonJS({ "node_modules/uri-js/dist/es5/uri.all.js"(exp
29930
30021
  var damp = 700;
29931
30022
  var initialBias = 72;
29932
30023
  var initialN = 128;
29933
- var delimiter = "-";
30024
+ var delimiter$1 = "-";
29934
30025
  /** Regular expressions */
29935
30026
  var regexPunycode = /^xn--/;
29936
30027
  var regexNonASCII = /[^\0-\x7E]/;
@@ -30085,7 +30176,7 @@ var require_uri_all = __commonJS({ "node_modules/uri-js/dist/es5/uri.all.js"(exp
30085
30176
  var i = 0;
30086
30177
  var n$1 = initialN;
30087
30178
  var bias = initialBias;
30088
- var basic = input.lastIndexOf(delimiter);
30179
+ var basic = input.lastIndexOf(delimiter$1);
30089
30180
  if (basic < 0) basic = 0;
30090
30181
  for (var j$1 = 0; j$1 < basic; ++j$1) {
30091
30182
  if (input.charCodeAt(j$1) >= 128) error$1("not-basic");
@@ -30147,7 +30238,7 @@ var require_uri_all = __commonJS({ "node_modules/uri-js/dist/es5/uri.all.js"(exp
30147
30238
  }
30148
30239
  var basicLength = output.length;
30149
30240
  var handledCPCount = basicLength;
30150
- if (basicLength) output.push(delimiter);
30241
+ if (basicLength) output.push(delimiter$1);
30151
30242
  while (handledCPCount < inputLength) {
30152
30243
  var m = maxInt;
30153
30244
  var _iteratorNormalCompletion2 = true;
@@ -48030,4 +48121,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
48030
48121
 
48031
48122
  //#endregion
48032
48123
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
48033
- //# sourceMappingURL=run-CRvusFIv.js.map
48124
+ //# sourceMappingURL=run-B2duge-W.js.map
@@ -1,14 +1,14 @@
1
- import "./health-BQRsVP6s.js";
1
+ import "./health-FUl73R5F.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
4
  import "./dist-DiNK6QOD.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-CRvusFIv.js";
6
- import "./manifest-read-Doh2Ion5.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-B2duge-W.js";
6
+ import "./manifest-read-BkijWyWk.js";
7
7
  import "./routing-DFxoKHDt.js";
8
8
  import "./work-graph-repository-DZyJv5pV.js";
9
9
  import "./decisions-CzSIEeGP.js";
10
10
  import "./decision-router-BAPpON_C.js";
11
- import "./interactive-prompt-CgerI5Y6.js";
11
+ import "./interactive-prompt-CtO5Tm6u.js";
12
12
  import "./recovery-engine-BKGBeBnW.js";
13
13
 
14
14
  export { runRunAction };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.141",
3
+ "version": "0.20.143",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -8,6 +8,10 @@ You are a **probe-author agent**. Your sole responsibility is to author `## Runt
8
8
 
9
9
  ## Context
10
10
 
11
+ ### Project Environment
12
+
13
+ {{project_env}}
14
+
11
15
  ### Rendered Acceptance Criteria (Story Artifact)
12
16
 
13
17
  The following is the story's rendered AC section, as produced by the create-story agent: