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 +22 -6
- package/dist/{health-Cm-pA1mZ.js → health-CoxLvCcT.js} +2 -2
- package/dist/{health-BQRsVP6s.js → health-FUl73R5F.js} +2 -2
- package/dist/{interactive-prompt-CgerI5Y6.js → interactive-prompt-CtO5Tm6u.js} +2 -2
- package/dist/{manifest-read-Doh2Ion5.js → manifest-read-BkijWyWk.js} +222 -12
- package/dist/modules/interactive-prompt/index.js +2 -2
- package/dist/{run-CRvusFIv.js → run-B2duge-W.js} +101 -10
- package/dist/{run-BHRkyn_H.js → run-DRwOPt3k.js} +4 -4
- package/package.json +1 -1
- package/packs/bmad/prompts/probe-author.md +4 -0
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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$
|
|
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$
|
|
2143
|
-
stderrTail: tail$
|
|
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) =>
|
|
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-
|
|
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-
|
|
4
|
-
import { runInteractivePrompt } from "../../interactive-prompt-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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 ?? "
|
|
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-
|
|
48124
|
+
//# sourceMappingURL=run-B2duge-W.js.map
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import "./health-
|
|
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-
|
|
6
|
-
import "./manifest-read-
|
|
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-
|
|
11
|
+
import "./interactive-prompt-CtO5Tm6u.js";
|
|
12
12
|
import "./recovery-engine-BKGBeBnW.js";
|
|
13
13
|
|
|
14
14
|
export { runRunAction };
|
package/package.json
CHANGED
|
@@ -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:
|