substrate-ai 0.20.150 → 0.20.152
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/adapter-registry-BsBP3j5i.js +4 -0
- package/dist/cli/index.js +64 -16
- package/dist/cli/templates/__tests__/docs-match-behavior.test.ts +69 -0
- package/dist/cli/templates/claude-commands/substrate-metrics.md +12 -0
- package/dist/cli/templates/claude-commands/substrate-run.md +21 -0
- package/dist/cli/templates/claude-commands/substrate-supervisor.md +15 -0
- package/dist/cli/templates/claude-md-substrate-section.md +14 -1
- package/dist/{decisions-7ALaVvR9.js → decisions-DH12X_94.js} +1 -1
- package/dist/{dist-C6pEdj12.js → dist-90byyGPp.js} +6 -1
- package/dist/{errors-1xcRMTz_.js → errors-ST3E8qWc.js} +2 -2
- package/dist/{experimenter-CRt7RrrW.js → experimenter-CyA9K5u6.js} +1 -1
- package/dist/{health-CcOYQsgZ.js → health-Bj5OYB7r.js} +3 -3
- package/dist/{health-Bhwd_HX9.js → health-DK5Kk5Bi.js} +3 -3
- package/dist/index.js +2 -2
- package/dist/{interactive-prompt-BVTTIU3t.js → interactive-prompt-Du_Yt_N4.js} +2 -2
- package/dist/{manifest-read-8oNapRvD.js → manifest-read-BAN_-QKy.js} +35 -4
- package/dist/modules/interactive-prompt/index.js +3 -3
- package/dist/{routing-BCXJlbUS.js → routing-pCkRxj09.js} +1 -1
- package/dist/{run-B_G9KCd-.js → run-BbXX6gY5.js} +5 -5
- package/dist/{run-B9lhuahO.js → run-DbT2-Wzg.js} +100 -31
- package/dist/{upgrade-DcvPseav.js → upgrade-Dw6jKkH3.js} +2 -2
- package/dist/{upgrade-CT6TGMup.js → upgrade-unZndH-S.js} +2 -2
- package/dist/{version-manager-impl-zazA11ph.js → version-manager-impl--XXnwjMd.js} +1 -1
- package/package.json +1 -1
- package/dist/adapter-registry-DPE1OgrZ.js +0 -4
package/dist/cli/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
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-Bj5OYB7r.js";
|
|
3
3
|
import { createLogger } from "../logger-KeHncl-f.js";
|
|
4
4
|
import { createEventBus } from "../helpers-CElYrONe.js";
|
|
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, createGitWorktreeManager, 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-
|
|
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, createGitWorktreeManager, 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-90byyGPp.js";
|
|
6
6
|
import "../adapter-registry-DXLMTmfD.js";
|
|
7
|
-
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 { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-
|
|
9
|
-
import "../errors-
|
|
7
|
+
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-BAN_-QKy.js";
|
|
8
|
+
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-DbT2-Wzg.js";
|
|
9
|
+
import "../errors-ST3E8qWc.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-Du_Yt_N4.js";
|
|
15
15
|
import "../recovery-engine-BKGBeBnW.js";
|
|
16
16
|
import "../version-manager-impl-qFBiO4Eh.js";
|
|
17
|
-
import { registerUpgradeCommand } from "../upgrade-
|
|
17
|
+
import { registerUpgradeCommand } from "../upgrade-Dw6jKkH3.js";
|
|
18
18
|
import { Command } from "commander";
|
|
19
19
|
import { fileURLToPath } from "url";
|
|
20
20
|
import { dirname, join, resolve } from "path";
|
|
@@ -1525,6 +1525,51 @@ async function scaffoldClaudeSettings(projectRoot) {
|
|
|
1525
1525
|
await writeFile(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
1526
1526
|
logger$18.info({ settingsPath }, "Wrote substrate settings to .claude/settings.json");
|
|
1527
1527
|
}
|
|
1528
|
+
/**
|
|
1529
|
+
* H5.2 (field finding #2): write substrate's own slash commands
|
|
1530
|
+
* (/substrate-run, /substrate-supervisor, /substrate-metrics) into
|
|
1531
|
+
* `.claude/commands/`. Pre-fix, the init summary ADVERTISED these commands
|
|
1532
|
+
* but nothing ever wrote them — the bmad generator populates `.claude/skills/`
|
|
1533
|
+
* only, so operators found an empty (or user-files-only) commands dir.
|
|
1534
|
+
*
|
|
1535
|
+
* Only files named `substrate-*.md` are owned (overwritten); user files are
|
|
1536
|
+
* never touched. Works with pre-existing / gitignored `.claude/` dirs —
|
|
1537
|
+
* mkdirSync recursive + per-file writes make no assumptions about state.
|
|
1538
|
+
*/
|
|
1539
|
+
function scaffoldSubstrateSlashCommands(projectRoot) {
|
|
1540
|
+
try {
|
|
1541
|
+
const pkgRoot = findPackageRoot(__dirname);
|
|
1542
|
+
let templatesDir = join(pkgRoot, "dist", "cli", "templates", "claude-commands");
|
|
1543
|
+
if (!existsSync$1(templatesDir)) templatesDir = join(pkgRoot, "src", "cli", "templates", "claude-commands");
|
|
1544
|
+
if (!existsSync$1(templatesDir)) {
|
|
1545
|
+
logger$18.warn({ templatesDir }, "substrate slash-command templates not found; skipping");
|
|
1546
|
+
return 0;
|
|
1547
|
+
}
|
|
1548
|
+
const commandsDir = join(projectRoot, ".claude", "commands");
|
|
1549
|
+
mkdirSync$1(commandsDir, { recursive: true });
|
|
1550
|
+
let written = 0;
|
|
1551
|
+
for (const file of readdirSync$1(templatesDir)) {
|
|
1552
|
+
if (!file.startsWith("substrate-") || !file.endsWith(".md")) continue;
|
|
1553
|
+
try {
|
|
1554
|
+
writeFileSync$1(join(commandsDir, file), readFileSync$1(join(templatesDir, file), "utf8"));
|
|
1555
|
+
written += 1;
|
|
1556
|
+
} catch (err) {
|
|
1557
|
+
logger$18.warn({
|
|
1558
|
+
file,
|
|
1559
|
+
err
|
|
1560
|
+
}, "failed to write substrate slash command (init continues)");
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
logger$18.info({
|
|
1564
|
+
written,
|
|
1565
|
+
commandsDir
|
|
1566
|
+
}, "Scaffolded substrate slash commands");
|
|
1567
|
+
return written;
|
|
1568
|
+
} catch (err) {
|
|
1569
|
+
logger$18.warn({ err }, "scaffoldSubstrateSlashCommands failed; init continues");
|
|
1570
|
+
return 0;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1528
1573
|
function resolveBmadMethodInstallerLibPath(fromDir = __dirname) {
|
|
1529
1574
|
try {
|
|
1530
1575
|
const _require = createRequire(join(fromDir, "synthetic.js"));
|
|
@@ -2278,6 +2323,7 @@ async function runInitAction(options) {
|
|
|
2278
2323
|
await scaffoldStatuslineScript(projectRoot);
|
|
2279
2324
|
await scaffoldClaudeSettings(projectRoot);
|
|
2280
2325
|
await scaffoldClaudeCommands(projectRoot, outputFormat);
|
|
2326
|
+
scaffoldSubstrateSlashCommands(projectRoot);
|
|
2281
2327
|
scaffoldCodexProject(projectRoot, outputFormat);
|
|
2282
2328
|
if (options.installUserScope) {
|
|
2283
2329
|
const homeDir = process.env["HOME"] ?? process.env["USERPROFILE"];
|
|
@@ -7080,7 +7126,7 @@ async function runStatusAction(options) {
|
|
|
7080
7126
|
logger$15.debug({ err }, "Work graph query failed, continuing without work graph data");
|
|
7081
7127
|
}
|
|
7082
7128
|
if (run === void 0) {
|
|
7083
|
-
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-
|
|
7129
|
+
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-DK5Kk5Bi.js");
|
|
7084
7130
|
const substrateDirPath = join(projectRoot, ".substrate");
|
|
7085
7131
|
const processInfo = inspectProcessTree$1({
|
|
7086
7132
|
projectRoot,
|
|
@@ -8028,7 +8074,7 @@ function defaultSupervisorDeps() {
|
|
|
8028
8074
|
if (cached === null) {
|
|
8029
8075
|
const { AdapterRegistry: AR } = await import(
|
|
8030
8076
|
/* @vite-ignore */
|
|
8031
|
-
"../adapter-registry-
|
|
8077
|
+
"../adapter-registry-BsBP3j5i.js"
|
|
8032
8078
|
);
|
|
8033
8079
|
cached = new AR();
|
|
8034
8080
|
await cached.discoverAndRegister();
|
|
@@ -8595,11 +8641,11 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
8595
8641
|
try {
|
|
8596
8642
|
const { createExperimenter } = await import(
|
|
8597
8643
|
/* @vite-ignore */
|
|
8598
|
-
"../experimenter-
|
|
8644
|
+
"../experimenter-CyA9K5u6.js"
|
|
8599
8645
|
);
|
|
8600
8646
|
const { getLatestRun: getLatest } = await import(
|
|
8601
8647
|
/* @vite-ignore */
|
|
8602
|
-
"../decisions-
|
|
8648
|
+
"../decisions-DH12X_94.js"
|
|
8603
8649
|
);
|
|
8604
8650
|
const expAdapter = createDatabaseAdapter({
|
|
8605
8651
|
backend: "auto",
|
|
@@ -8609,7 +8655,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
8609
8655
|
await initSchema(expAdapter);
|
|
8610
8656
|
const { runRunAction: runPipeline } = await import(
|
|
8611
8657
|
/* @vite-ignore */
|
|
8612
|
-
"../run-
|
|
8658
|
+
"../run-BbXX6gY5.js"
|
|
8613
8659
|
);
|
|
8614
8660
|
const runStoryFn = async (opts) => {
|
|
8615
8661
|
const exitCode = await runPipeline({
|
|
@@ -9134,7 +9180,7 @@ async function runMetricsAction(options) {
|
|
|
9134
9180
|
const routingConfigPath = join(dbDir, "routing.yml");
|
|
9135
9181
|
let routingConfig = null;
|
|
9136
9182
|
if (existsSync$1(routingConfigPath)) try {
|
|
9137
|
-
const { loadModelRoutingConfig } = await import("../routing-
|
|
9183
|
+
const { loadModelRoutingConfig } = await import("../routing-pCkRxj09.js");
|
|
9138
9184
|
routingConfig = loadModelRoutingConfig(routingConfigPath);
|
|
9139
9185
|
} catch {}
|
|
9140
9186
|
if (routingConfig === null) routingConfig = {
|
|
@@ -13106,7 +13152,9 @@ function assembleReport(runId, manifest, halts, storyOutputTokens) {
|
|
|
13106
13152
|
completed_at: completedAt,
|
|
13107
13153
|
wall_clock_ms: totalWallMs
|
|
13108
13154
|
};
|
|
13109
|
-
const
|
|
13155
|
+
const runTotal = manifest.cost_accumulation?.run_total ?? 0;
|
|
13156
|
+
const perStoryCostSum = Object.values(perStoryState).reduce((sum, st) => sum + (typeof st?.cost_usd === "number" ? st.cost_usd : 0), 0);
|
|
13157
|
+
const spent = runTotal > 0 ? runTotal : perStoryCostSum;
|
|
13110
13158
|
const ceiling = manifest.cost_accumulation != null ? manifest.cli_flags?.cost_ceiling : void 0;
|
|
13111
13159
|
const utilization = ceiling != null && ceiling > 0 ? `${(spent / ceiling * 100).toFixed(1)}%` : void 0;
|
|
13112
13160
|
const overCeiling = ceiling != null ? spent > ceiling : false;
|
|
@@ -13460,8 +13508,8 @@ async function createProgram() {
|
|
|
13460
13508
|
/** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
|
|
13461
13509
|
function checkForUpdatesInBackground(currentVersion) {
|
|
13462
13510
|
if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
|
|
13463
|
-
import("../upgrade-
|
|
13464
|
-
const { createVersionManager } = await import("../version-manager-impl
|
|
13511
|
+
import("../upgrade-unZndH-S.js").then(async () => {
|
|
13512
|
+
const { createVersionManager } = await import("../version-manager-impl--XXnwjMd.js");
|
|
13465
13513
|
const vm = createVersionManager();
|
|
13466
13514
|
const result = await vm.checkForUpdates();
|
|
13467
13515
|
if (result.updateAvailable) {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* H5.3: docs-match-behavior gate for the consumer CLAUDE.md template.
|
|
3
|
+
*
|
|
4
|
+
* The template (`claude-md-substrate-section.md`) is what every consumer
|
|
5
|
+
* project's Claude session reads before driving substrate — when it drifts
|
|
6
|
+
* from the code, agents act on behavior that no longer exists (the
|
|
7
|
+
* income-sources run repeatedly hit this class). This suite pins the
|
|
8
|
+
* load-bearing claims to their code-side sources of truth:
|
|
9
|
+
*
|
|
10
|
+
* - every finalization mode in the config schema is documented
|
|
11
|
+
* - the ff-only merge default and the three-way opt-in are stated
|
|
12
|
+
* - the external worktree base default (H4.2) is stated
|
|
13
|
+
* - every `story:*` / `pipeline:*` event the template names exists in
|
|
14
|
+
* EVENT_TYPE_NAMES (no phantom events)
|
|
15
|
+
*
|
|
16
|
+
* Ship rule (execution-plan H5.3 AC1): a change to finalizeStory /
|
|
17
|
+
* merge-to-main / verification-check registration that alters documented
|
|
18
|
+
* behavior must update the template in the same commit — this suite is the
|
|
19
|
+
* enforcement for the pinned claims; reviewers enforce the rest.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { describe, it, expect } from 'vitest'
|
|
23
|
+
import { readFileSync } from 'node:fs'
|
|
24
|
+
import { resolve, dirname } from 'node:path'
|
|
25
|
+
import { fileURLToPath } from 'node:url'
|
|
26
|
+
import { EVENT_TYPE_NAMES } from '../../../modules/implementation-orchestrator/event-types.js'
|
|
27
|
+
|
|
28
|
+
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
29
|
+
const TEMPLATE = readFileSync(resolve(HERE, '..', 'claude-md-substrate-section.md'), 'utf-8')
|
|
30
|
+
const CONFIG_SCHEMA = readFileSync(
|
|
31
|
+
resolve(HERE, '..', '..', '..', 'modules', 'config', 'config-schema.ts'),
|
|
32
|
+
'utf-8',
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
describe('consumer CLAUDE.md template ↔ behavior parity (H5.3)', () => {
|
|
36
|
+
it('documents every finalization mode the config schema accepts', () => {
|
|
37
|
+
const enumMatch = /finalization:[\s\S]*?mode: z\.enum\(\[([^\]]+)\]\)/.exec(CONFIG_SCHEMA)
|
|
38
|
+
expect(enumMatch).not.toBeNull()
|
|
39
|
+
const modes = [...enumMatch![1]!.matchAll(/'([a-z]+)'/g)].map((m) => m[1]!)
|
|
40
|
+
expect(modes.length).toBeGreaterThanOrEqual(3)
|
|
41
|
+
for (const mode of modes) {
|
|
42
|
+
expect(TEMPLATE, `finalization mode "${mode}" missing from template`).toContain(`\`${mode}\``)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('states the ff-only merge default and the three-way opt-in (H3.3)', () => {
|
|
47
|
+
expect(TEMPLATE).toContain('fast-forward-only')
|
|
48
|
+
expect(TEMPLATE).toContain('merge_strategy: three-way')
|
|
49
|
+
expect(TEMPLATE).toContain('ff-only-merge-not-possible')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('states the external worktree base default (H4.2)', () => {
|
|
53
|
+
expect(TEMPLATE).toContain('~/.substrate/worktrees/')
|
|
54
|
+
expect(TEMPLATE).toContain('worktree.base: in-repo')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('every event name the template cites exists in EVENT_TYPE_NAMES', () => {
|
|
58
|
+
const cited = [...TEMPLATE.matchAll(/`((?:story|pipeline):[a-z-]+)`/g)].map((m) => m[1]!)
|
|
59
|
+
expect(cited.length).toBeGreaterThan(0)
|
|
60
|
+
const known = new Set<string>(EVENT_TYPE_NAMES)
|
|
61
|
+
const phantom = cited.filter((e) => !known.has(e))
|
|
62
|
+
expect(phantom, `template cites events that do not exist: ${phantom.join(', ')}`).toEqual([])
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('documents the commit-first discipline (H0.1) — the branch is the durable copy', () => {
|
|
66
|
+
expect(TEMPLATE).toContain('commit-first')
|
|
67
|
+
expect(TEMPLATE).toContain('wip(story-')
|
|
68
|
+
})
|
|
69
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show substrate run metrics and the latest completion report
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Report on substrate pipeline outcomes for this project:
|
|
6
|
+
|
|
7
|
+
1. `substrate report --run latest` — per-story outcomes, cost, escalation diagnostics, halt notifications. Add `--verify-ac` for the AC-to-test traceability matrix.
|
|
8
|
+
2. `substrate metrics --output-format json` — historical run metrics.
|
|
9
|
+
|
|
10
|
+
Summarize conversationally: how many stories verified/recovered/escalated/failed, total cost, and anything the operator must act on (escalations, halts, unmerged deliverable branches listed under "Finalization").
|
|
11
|
+
|
|
12
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run the substrate implementation pipeline (guided)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run the substrate pipeline for this project.
|
|
6
|
+
|
|
7
|
+
**Before dispatching, confirm scope with the user if they did not name stories.** Without `--stories`, substrate auto-discovers ALL pending stories and may dispatch 30+ at once.
|
|
8
|
+
|
|
9
|
+
Steps:
|
|
10
|
+
|
|
11
|
+
1. If the user named stories (e.g. "1-1,1-2"), run:
|
|
12
|
+
`substrate run --events --stories <keys>`
|
|
13
|
+
Otherwise ask which stories to run, or confirm a full auto-discovery run is intended.
|
|
14
|
+
2. Pipeline runs take 5–40 minutes. Use a background invocation or a timeout of at least 10 minutes — the default 2-minute tool timeout WILL kill the pipeline. NEVER pipe substrate output through `head`/`tail`/`grep` (EPIPE stalls).
|
|
15
|
+
3. Poll `substrate status --output-format json` every 60–90s while it runs; `substrate health --output-format json` if it goes quiet for 15+ minutes.
|
|
16
|
+
4. When it completes, summarize per-story outcomes and run `substrate report --run latest`.
|
|
17
|
+
|
|
18
|
+
Autonomy: default halts on critical+fatal. For fully autonomous runs use:
|
|
19
|
+
`substrate run --halt-on none --non-interactive --events --output-format json`
|
|
20
|
+
|
|
21
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Attach the substrate supervisor to an active pipeline run
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Attach the substrate supervisor to the pipeline run that is active in this project:
|
|
6
|
+
|
|
7
|
+
`substrate supervisor --output-format json`
|
|
8
|
+
|
|
9
|
+
Notes:
|
|
10
|
+
- The supervisor monitors an active run (stall detection, kill-and-restart recovery, post-run analysis) — it does NOT start one. Start the run first (see /substrate-run).
|
|
11
|
+
- Only attach to runs started in this session; attaching to another session's run risks killing healthy dispatches.
|
|
12
|
+
- Long-running: use a background invocation or a generous timeout.
|
|
13
|
+
- After the run, read the analysis with `substrate metrics --analysis <run_id> --output-format json`.
|
|
14
|
+
|
|
15
|
+
$ARGUMENTS
|
|
@@ -81,7 +81,17 @@ The Recovery Engine runs a 3-tier auto-fix ladder before any halt — Tier A ret
|
|
|
81
81
|
|
|
82
82
|
### Per-Story Worktree Behavior
|
|
83
83
|
|
|
84
|
-
Each dispatched story runs in
|
|
84
|
+
Each dispatched story runs in an isolated git worktree on its own branch (`substrate/story-<key>`). By default the worktree lives OUTSIDE the repo at `~/.substrate/worktrees/<projectname>-<hash8>/<key>/`; set `worktree.base: in-repo` in `.substrate/config.yaml` to restore the legacy `.substrate-worktrees/<key>/` location. Substrate auto-commits the story's work to the branch (`feat(story-N-M): ...`) at dev-story completion — commit-first, before review — so the branch is always the durable copy; failure paths add `wip(story-<key>)` checkpoints. After verification failure, the worktree and branch are preserved for `substrate reconcile-from-disk` inspection. Use `--no-worktree` if your project doesn't support worktrees (submodules, bare repos).
|
|
85
|
+
|
|
86
|
+
### Finalization — how verified work integrates
|
|
87
|
+
|
|
88
|
+
`finalization.mode` in `.substrate/config.yaml` (or `--finalization <mode>` per run):
|
|
89
|
+
|
|
90
|
+
- **`merge`** (default): local merge into the branch the run started from. The merge is **fast-forward-only by default** — if the base branch moved during the run, the story escalates `ff-only-merge-not-possible` instead of synthesizing a merge commit. Set `finalization.merge_strategy: three-way` to allow merge commits — **required for concurrent multi-story runs** (later stories cannot fast-forward past earlier merges). A dirty parent tree whose changes intersect the story's diff escalates `parent-tree-dirtied-by-run` naming the files.
|
|
91
|
+
- **`branch`**: verified work stays on `substrate/story-<key>` — nothing self-merges; the branch is the deliverable. The safe brownfield mode.
|
|
92
|
+
- **`pr`**: branch + `git push` + `gh pr create` (one PR per story). Degrades to `branch` with a warning when push/gh fail — never blocks the story.
|
|
93
|
+
|
|
94
|
+
Lifecycle events on the NDJSON stream: `story:committed` → (`story:merged`) → `story:finalized {mode, branch, sha, pr_url?}`. `substrate report` lists unmerged deliverable branches under "Finalization". Optional `finalization.epic_gate_command` runs before the LAST story of an epic integrates (non-zero exit → `epic-gate-failed`, branch preserved).
|
|
85
95
|
|
|
86
96
|
### Key Commands Reference
|
|
87
97
|
|
|
@@ -92,6 +102,7 @@ Each dispatched story runs in `.substrate-worktrees/story-<key>` on its own bran
|
|
|
92
102
|
| `substrate run --non-interactive` | Suppress stdin prompts; combine with `--halt-on none` for fully autonomous |
|
|
93
103
|
| `substrate run --verify-ac` | On-demand AC-to-Test traceability matrix |
|
|
94
104
|
| `substrate run --no-worktree` | Disable per-story git worktrees (use for submodules or bare repos) |
|
|
105
|
+
| `substrate run --finalization <mode>` | Integration mode: `merge` (default) / `branch` (never self-merge) / `pr` |
|
|
95
106
|
| `substrate report [--run <id\|latest>]` | Per-run completion report — outcomes, cost, escalation diagnostics, halt notifications |
|
|
96
107
|
| `substrate report --verify-ac` | Append AC-to-Test traceability matrix to the report |
|
|
97
108
|
| `substrate reconcile-from-disk [--dry-run] [--yes]` | Path A reconciliation when pipeline reports failed but tree is coherent |
|
|
@@ -120,6 +131,8 @@ Substrate writes per-project state under `.substrate/` in a few flavors:
|
|
|
120
131
|
|
|
121
132
|
The defensible default for most projects is to ignore everything under `.substrate/` except the operator config. Local telemetry stays on each developer's machine — operators see their own corpus locally via `substrate metrics`; cross-machine sharing of routing telemetry is a future feature, not currently supported.
|
|
122
133
|
|
|
134
|
+
Besides `.substrate/`, `substrate init` also scaffolds project-root artifacts that ARE intentional and worth tracking in git: `CLAUDE.md`, `AGENTS.md`, `GEMINI.md` (pipeline instructions per agent CLI), `packs/<pack-name>/` (the methodology pack's prompts — the pipeline reads these at dispatch time), `.claude/commands/substrate-*.md` + `.claude/skills/`, and `.codex/` mirrors. Track them; they are inputs to every run, not state. If your team prefers not to commit the non-Claude agent files (`AGENTS.md`, `GEMINI.md`, `.codex/`), gitignore them explicitly — substrate regenerates them on `substrate init`.
|
|
135
|
+
|
|
123
136
|
```gitignore
|
|
124
137
|
# Substrate state — track only the operator config; everything else is
|
|
125
138
|
# per-process, per-run, or local-machine accumulation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-
|
|
1
|
+
import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-90byyGPp.js";
|
|
2
2
|
import "./decisions-CzSIEeGP.js";
|
|
3
3
|
|
|
4
4
|
export { getLatestRun };
|
|
@@ -3223,10 +3223,12 @@ async function initTelemetrySchema(adapter) {
|
|
|
3223
3223
|
cache_hit_sub_score DOUBLE NOT NULL DEFAULT 0,
|
|
3224
3224
|
io_ratio_sub_score DOUBLE NOT NULL DEFAULT 0,
|
|
3225
3225
|
context_management_sub_score DOUBLE NOT NULL DEFAULT 0,
|
|
3226
|
+
token_density_sub_score DOUBLE NOT NULL DEFAULT 0,
|
|
3226
3227
|
avg_cache_hit_rate DOUBLE NOT NULL DEFAULT 0,
|
|
3227
3228
|
avg_io_ratio DOUBLE NOT NULL DEFAULT 0,
|
|
3228
3229
|
context_spike_count INTEGER NOT NULL DEFAULT 0,
|
|
3229
3230
|
total_turns INTEGER NOT NULL DEFAULT 0,
|
|
3231
|
+
cold_start_turns_excluded INTEGER NOT NULL DEFAULT 0,
|
|
3230
3232
|
per_model_json TEXT NOT NULL DEFAULT '[]',
|
|
3231
3233
|
per_source_json TEXT NOT NULL DEFAULT '[]',
|
|
3232
3234
|
dispatch_id TEXT,
|
|
@@ -3243,6 +3245,9 @@ async function initTelemetrySchema(adapter) {
|
|
|
3243
3245
|
]) try {
|
|
3244
3246
|
await adapter.exec(`ALTER TABLE efficiency_scores ADD COLUMN ${col} TEXT`);
|
|
3245
3247
|
} catch {}
|
|
3248
|
+
for (const [col, ddl] of [["token_density_sub_score", "DOUBLE NOT NULL DEFAULT 0"], ["cold_start_turns_excluded", "INTEGER NOT NULL DEFAULT 0"]]) try {
|
|
3249
|
+
await adapter.exec(`ALTER TABLE efficiency_scores ADD COLUMN ${col} ${ddl}`);
|
|
3250
|
+
} catch {}
|
|
3246
3251
|
await adapter.exec(`
|
|
3247
3252
|
CREATE TABLE IF NOT EXISTS recommendations (
|
|
3248
3253
|
id VARCHAR(16) NOT NULL,
|
|
@@ -12595,4 +12600,4 @@ async function callLLM(params) {
|
|
|
12595
12600
|
|
|
12596
12601
|
//#endregion
|
|
12597
12602
|
export { ADVISORY_NOTES, AdapterRegistry, AdtError, BRANCH_PREFIX, BudgetConfigSchema, CLAUDE_AUTH_FAILURE_HINT, CODEX_SANDBOX_BLOCK_HINT, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, Categorizer, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, ConsumerAnalyzer, CostTrackerConfigSchema, DEFAULT_CONFIG, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, DoltNotInstalled, DoltQueryError, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, GeminiCLIAdapter, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, LEARNING_FINDING, LogTurnAnalyzer, ModelRoutingConfigSchema, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProviderPolicySchema, ProvidersSchema, Recommender, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TASK_TYPE_PHASE_MAP, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryConfigSchema, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, VersionManagerImpl, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, callLLM, checkDoltInstalled, classifyVersionGap, compareRunMetrics, createAmendmentRun, createConfigSystem, createDatabaseAdapter as createDatabaseAdapter$1, createDecision, createExperimenter, createGitWorktreeManager, createPipelineRun, createRequirement, createStderrLogger, createVersionManager, detectClaudeAuthFailure, detectCodexSandboxBlock, detectInterfaceChanges, determineVerdict, getActiveDecisions, getAllCostEntriesFiltered, getArtifactByTypeForRun, getArtifactsByRun, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getModelTier, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initWorkGraphSchema, initializeDolt, listRequirements, listRunMetrics, loadModelRoutingConfig, loadParentRunDecisions, registerArtifact, resolvePromptFile, supersedeDecision, swallowDebug, tagRunAsBaseline, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics };
|
|
12598
|
-
//# sourceMappingURL=dist-
|
|
12603
|
+
//# sourceMappingURL=dist-90byyGPp.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdtError } from "./dist-
|
|
1
|
+
import { AdtError } from "./dist-90byyGPp.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/errors.ts
|
|
4
4
|
/** Error thrown when task configuration is invalid */
|
|
@@ -71,4 +71,4 @@ var TaskGraphIncompatibleFormatError = class extends AdtError {
|
|
|
71
71
|
|
|
72
72
|
//#endregion
|
|
73
73
|
export { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError };
|
|
74
|
-
//# sourceMappingURL=errors-
|
|
74
|
+
//# sourceMappingURL=errors-ST3E8qWc.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-
|
|
1
|
+
import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-90byyGPp.js";
|
|
2
2
|
|
|
3
3
|
export { createExperimenter };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
2
|
-
import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-
|
|
3
|
-
import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-
|
|
2
|
+
import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-90byyGPp.js";
|
|
3
|
+
import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-BAN_-QKy.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-Bj5OYB7r.js.map
|
|
@@ -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-Bj5OYB7r.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
|
-
import "./dist-
|
|
4
|
-
import "./manifest-read-
|
|
3
|
+
import "./dist-90byyGPp.js";
|
|
4
|
+
import "./manifest-read-BAN_-QKy.js";
|
|
5
5
|
import "./work-graph-repository-DZyJv5pV.js";
|
|
6
6
|
import "./decisions-CzSIEeGP.js";
|
|
7
7
|
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { childLogger, createLogger, logger } from "./logger-KeHncl-f.js";
|
|
2
2
|
import { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-CElYrONe.js";
|
|
3
|
-
import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-
|
|
3
|
+
import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-90byyGPp.js";
|
|
4
4
|
import "./adapter-registry-DXLMTmfD.js";
|
|
5
|
-
import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-
|
|
5
|
+
import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-ST3E8qWc.js";
|
|
6
6
|
|
|
7
7
|
//#region src/core/di.ts
|
|
8
8
|
/**
|
|
@@ -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-BAN_-QKy.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-Du_Yt_N4.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
2
|
-
import { LEARNING_FINDING, createDecision, getDecisionsByCategory } from "./dist-
|
|
2
|
+
import { LEARNING_FINDING, createDecision, getDecisionsByCategory } from "./dist-90byyGPp.js";
|
|
3
3
|
import * as path$1 from "path";
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import { readFile } from "fs/promises";
|
|
@@ -2235,6 +2235,20 @@ function detectTestCommand(workingDir) {
|
|
|
2235
2235
|
} catch {}
|
|
2236
2236
|
return void 0;
|
|
2237
2237
|
}
|
|
2238
|
+
/**
|
|
2239
|
+
* H7 (trust-boundary hardening): detect exit-code LAUNDERING in a resolved test
|
|
2240
|
+
* command — a wrapper that forces exit 0 regardless of the real suite result
|
|
2241
|
+
* (`… || true`, `… || :`, `… || exit 0`, `… ; true`, `… ; exit 0`). A
|
|
2242
|
+
* reward-hacking agent used this to make a genuinely-red suite report pass
|
|
2243
|
+
* (verified against compiled dist in the red-team review). Legitimate commands
|
|
2244
|
+
* do not mask their own exit code, so this is a tampering signal, not a style
|
|
2245
|
+
* nit. Note: cannot catch arbitrary in-language masking (e.g. `python -c
|
|
2246
|
+
* "...sys.exit(0)"`) — the trusted-profile read is the primary defense; this is
|
|
2247
|
+
* belt-and-braces for the shell-wrapper class and the --no-worktree path.
|
|
2248
|
+
*/
|
|
2249
|
+
function detectsExitCodeLaundering(command) {
|
|
2250
|
+
return /(\|\||;)\s*(true|:|exit\s+0)(\s|;|$)/.test(command);
|
|
2251
|
+
}
|
|
2238
2252
|
var TestSuiteCheck = class {
|
|
2239
2253
|
name = "test-suite";
|
|
2240
2254
|
tier = "A";
|
|
@@ -2255,6 +2269,19 @@ var TestSuiteCheck = class {
|
|
|
2255
2269
|
findings
|
|
2256
2270
|
};
|
|
2257
2271
|
}
|
|
2272
|
+
if (cmd !== void 0 && cmd !== "" && detectsExitCodeLaundering(cmd)) {
|
|
2273
|
+
const findings = [{
|
|
2274
|
+
category: "test-command-tampered",
|
|
2275
|
+
severity: "error",
|
|
2276
|
+
message: `test command masks its own exit code (\`${cmd}\`) — a wrapper like \`|| true\` / \`; exit 0\` forces a pass regardless of the real suite result. Remove the exit-code mask; the suite must fail the story when tests fail.`
|
|
2277
|
+
}];
|
|
2278
|
+
return {
|
|
2279
|
+
status: "fail",
|
|
2280
|
+
details: renderFindings(findings),
|
|
2281
|
+
duration_ms: Date.now() - start,
|
|
2282
|
+
findings
|
|
2283
|
+
};
|
|
2284
|
+
}
|
|
2258
2285
|
if (cmd === void 0 || cmd === "") {
|
|
2259
2286
|
const findings = [{
|
|
2260
2287
|
category: "test-suite-skip",
|
|
@@ -2486,7 +2513,7 @@ var ContaminationCheck = class {
|
|
|
2486
2513
|
duration_ms: Date.now() - start,
|
|
2487
2514
|
findings: []
|
|
2488
2515
|
};
|
|
2489
|
-
const allowedLanguages = readProfileLanguages(context.workingDir);
|
|
2516
|
+
const allowedLanguages = context.trustedLanguages ?? readProfileLanguages(context.workingDir);
|
|
2490
2517
|
if (allowedLanguages.length === 0) {
|
|
2491
2518
|
const findings$1 = [{
|
|
2492
2519
|
category: "contamination-skip",
|
|
@@ -3449,9 +3476,13 @@ var RuntimeProbeCheck = class {
|
|
|
3449
3476
|
});
|
|
3450
3477
|
}
|
|
3451
3478
|
const status = findings.some((f) => f.severity === "error") ? "fail" : findings.some((f) => f.severity === "warn") ? "warn" : "pass";
|
|
3479
|
+
const deferredCount = findings.filter((f) => f.category === CATEGORY_DEFERRED).length;
|
|
3480
|
+
const failedCount = findings.filter((f) => f.severity === "error").length;
|
|
3481
|
+
const ranCount = parsed.probes.filter((probe) => probe.sandbox !== "twin").length;
|
|
3482
|
+
const summaryLine = `runtime-probes: ${ranCount} ran (${ranCount - failedCount} passed, ${failedCount} failed)` + (deferredCount > 0 ? `, ${deferredCount} deferred (sandbox=twin, Phase 3)` : "");
|
|
3452
3483
|
return {
|
|
3453
3484
|
status,
|
|
3454
|
-
details: findings.length > 0 ? renderFindings(findings) :
|
|
3485
|
+
details: findings.length > 0 ? `${summaryLine}\n${renderFindings(findings)}` : summaryLine,
|
|
3455
3486
|
duration_ms: Date.now() - start,
|
|
3456
3487
|
findings
|
|
3457
3488
|
};
|
|
@@ -6300,4 +6331,4 @@ async function resolveRunManifest(dbRoot, runId) {
|
|
|
6300
6331
|
|
|
6301
6332
|
//#endregion
|
|
6302
6333
|
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 };
|
|
6303
|
-
//# sourceMappingURL=manifest-read-
|
|
6334
|
+
//# sourceMappingURL=manifest-read-BAN_-QKy.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../logger-KeHncl-f.js";
|
|
2
|
-
import "../../dist-
|
|
3
|
-
import "../../manifest-read-
|
|
4
|
-
import { runInteractivePrompt } from "../../interactive-prompt-
|
|
2
|
+
import "../../dist-90byyGPp.js";
|
|
3
|
+
import "../../manifest-read-BAN_-QKy.js";
|
|
4
|
+
import { runInteractivePrompt } from "../../interactive-prompt-Du_Yt_N4.js";
|
|
5
5
|
|
|
6
6
|
export { runInteractivePrompt };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-
|
|
1
|
+
import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-90byyGPp.js";
|
|
2
2
|
import "./routing-DFxoKHDt.js";
|
|
3
3
|
|
|
4
4
|
export { loadModelRoutingConfig };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import "./health-
|
|
1
|
+
import "./health-Bj5OYB7r.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
|
-
import "./dist-
|
|
5
|
-
import "./manifest-read-
|
|
6
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-
|
|
4
|
+
import "./dist-90byyGPp.js";
|
|
5
|
+
import "./manifest-read-BAN_-QKy.js";
|
|
6
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-DbT2-Wzg.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-Du_Yt_N4.js";
|
|
12
12
|
import "./recovery-engine-BKGBeBnW.js";
|
|
13
13
|
|
|
14
14
|
export { runRunAction };
|
|
@@ -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-Bj5OYB7r.js";
|
|
2
2
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
3
3
|
import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
|
|
4
|
-
import { ADVISORY_NOTES, BRANCH_PREFIX, 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, createGitWorktreeManager, createPipelineRun, createRequirement, 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-
|
|
5
|
-
import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-
|
|
4
|
+
import { ADVISORY_NOTES, BRANCH_PREFIX, 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, createGitWorktreeManager, createPipelineRun, createRequirement, 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-90byyGPp.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-BAN_-QKy.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-Du_Yt_N4.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";
|
|
@@ -951,7 +951,7 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
951
951
|
{
|
|
952
952
|
name: "reason",
|
|
953
953
|
type: "string",
|
|
954
|
-
description: "Escalation reason. Common values: review-cycles-exhausted (default review-loop max hit); create-story-no-file (create-story phase did not write a story artifact); dev-story-no-commit (substrate auto-commit found no committable changes — agent produced nothing or all changes were outside the worktree); dev-story-commit-failed (substrate auto-commit failed — typically a pre-commit hook rejected the commit; stderr captured in issues); merge-to-main-error (unexpected error in the merge-to-main phase); merge-conflict-detected (story branch could not be merged due to conflicts). v0.20.87+."
|
|
954
|
+
description: "Escalation reason. Common values: review-cycles-exhausted (default review-loop max hit); create-story-no-file (create-story phase did not write a story artifact); dev-story-no-commit (substrate auto-commit found no committable changes — agent produced nothing or all changes were outside the worktree); dev-story-commit-failed (substrate auto-commit failed — typically a pre-commit hook rejected the commit; stderr captured in issues); merge-to-main-error (unexpected error in the merge-to-main phase); merge-conflict-detected (story branch could not be merged due to conflicts); parent-tree-dirtied-by-run (uncommitted parent changes intersect the story diff — merge refused, H3.3); ff-only-merge-not-possible (base moved and merge_strategy is ff-only — set finalization.merge_strategy: three-way or integrate manually, H3.3); epic-gate-failed (finalization.epic_gate_command exited non-zero before the last story of an epic integrated, H3.4); story-file-missing (story artifact gone from working tree AND branch HEAD — check wip/feat commits on the story branch, H5.5). v0.20.87+."
|
|
955
955
|
},
|
|
956
956
|
{
|
|
957
957
|
name: "cycles",
|
|
@@ -7304,6 +7304,41 @@ async function stageIntentToAdd(files, workingDirectory) {
|
|
|
7304
7304
|
* Run a git command in the specified directory and return its stdout output.
|
|
7305
7305
|
* Returns '' on any error and logs a warning.
|
|
7306
7306
|
*/
|
|
7307
|
+
/**
|
|
7308
|
+
* H5.5 (story-artifact resilience): recover a story file from the branch
|
|
7309
|
+
* HEAD when the working-tree copy has gone missing (live-smoke incident
|
|
7310
|
+
* 2026-07-06: a fix-phase agent DELETED the committed story artifact; the
|
|
7311
|
+
* re-review hit ENOENT and was misclassified `consecutive-review-timeouts`
|
|
7312
|
+
* while the file sat safely in the H0.1 feat commit the whole time).
|
|
7313
|
+
*
|
|
7314
|
+
* Reads `git show HEAD:<relpath>` in the worktree and, on success, WRITES
|
|
7315
|
+
* the content back to the working tree so downstream phases find it too.
|
|
7316
|
+
* Returns the content, or undefined when the file isn't in HEAD either.
|
|
7317
|
+
*/
|
|
7318
|
+
async function recoverStoryFileFromBranch(storyFilePath, workingDirectory) {
|
|
7319
|
+
const rel = relative(workingDirectory, resolve$1(workingDirectory, storyFilePath));
|
|
7320
|
+
if (rel.startsWith("..")) {
|
|
7321
|
+
logger$20.warn({
|
|
7322
|
+
storyFilePath,
|
|
7323
|
+
workingDirectory
|
|
7324
|
+
}, "recoverStoryFileFromBranch: path outside the worktree — not recoverable");
|
|
7325
|
+
return void 0;
|
|
7326
|
+
}
|
|
7327
|
+
const content = await runGitCommand(["show", `HEAD:${rel}`], workingDirectory, "recover-story-file");
|
|
7328
|
+
if (content.trim().length === 0) return void 0;
|
|
7329
|
+
try {
|
|
7330
|
+
const abs = resolve$1(workingDirectory, rel);
|
|
7331
|
+
await mkdir$1(dirname$1(abs), { recursive: true });
|
|
7332
|
+
await writeFile$1(abs, content, "utf-8");
|
|
7333
|
+
logger$20.warn({ storyFilePath: abs }, "H5.5: story file restored to the working tree from branch HEAD");
|
|
7334
|
+
} catch (writeErr) {
|
|
7335
|
+
logger$20.warn({
|
|
7336
|
+
storyFilePath,
|
|
7337
|
+
err: writeErr
|
|
7338
|
+
}, "H5.5: recovered story content but could not restore the file (continuing with in-memory content)");
|
|
7339
|
+
}
|
|
7340
|
+
return content;
|
|
7341
|
+
}
|
|
7307
7342
|
async function runGitCommand(args, cwd, logLabel) {
|
|
7308
7343
|
return new Promise((resolve$6) => {
|
|
7309
7344
|
let stdout = "";
|
|
@@ -7746,20 +7781,28 @@ async function runDevStory(deps, params) {
|
|
|
7746
7781
|
try {
|
|
7747
7782
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
7748
7783
|
} catch (err) {
|
|
7749
|
-
|
|
7784
|
+
const recovered = await recoverStoryFileFromBranch(storyFilePath, deps.projectRoot ?? process.cwd());
|
|
7785
|
+
if (recovered !== void 0) {
|
|
7786
|
+
logger$18.warn({
|
|
7787
|
+
storyKey,
|
|
7788
|
+
storyFilePath
|
|
7789
|
+
}, "story file missing from working tree — recovered from branch HEAD (H5.5)");
|
|
7790
|
+
storyContent = recovered;
|
|
7791
|
+
} else if (err.code === "ENOENT") {
|
|
7750
7792
|
logger$18.error({
|
|
7751
7793
|
storyKey,
|
|
7752
7794
|
storyFilePath
|
|
7753
7795
|
}, "Story file not found");
|
|
7754
7796
|
return makeFailureResult("story_file_not_found");
|
|
7797
|
+
} else {
|
|
7798
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
7799
|
+
logger$18.error({
|
|
7800
|
+
storyKey,
|
|
7801
|
+
storyFilePath,
|
|
7802
|
+
error
|
|
7803
|
+
}, "Failed to read story file");
|
|
7804
|
+
return makeFailureResult(`story_file_read_error: ${error}`);
|
|
7755
7805
|
}
|
|
7756
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
7757
|
-
logger$18.error({
|
|
7758
|
-
storyKey,
|
|
7759
|
-
storyFilePath,
|
|
7760
|
-
error
|
|
7761
|
-
}, "Failed to read story file");
|
|
7762
|
-
return makeFailureResult(`story_file_read_error: ${error}`);
|
|
7763
7806
|
}
|
|
7764
7807
|
if (storyContent.trim().length === 0) {
|
|
7765
7808
|
logger$18.error({
|
|
@@ -8525,14 +8568,20 @@ async function runCodeReview(deps, params) {
|
|
|
8525
8568
|
storyContent = await readFile$1(storyFilePath, "utf-8");
|
|
8526
8569
|
} catch (err) {
|
|
8527
8570
|
const error = err instanceof Error ? err.message : String(err);
|
|
8528
|
-
|
|
8529
|
-
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8571
|
+
const recovered = await recoverStoryFileFromBranch(storyFilePath, cwd);
|
|
8572
|
+
if (recovered !== void 0) {
|
|
8573
|
+
logger$17.warn({ storyFilePath }, "story file missing from working tree — recovered from branch HEAD (H5.5)");
|
|
8574
|
+
storyContent = recovered;
|
|
8575
|
+
} else {
|
|
8576
|
+
logger$17.error({
|
|
8577
|
+
storyFilePath,
|
|
8578
|
+
error
|
|
8579
|
+
}, "Failed to read story file (absent from working tree AND branch HEAD)");
|
|
8580
|
+
return defaultFailResult(`story-file-missing: ${storyFilePath} absent from working tree and branch HEAD (${error})`, {
|
|
8581
|
+
input: 0,
|
|
8582
|
+
output: 0
|
|
8583
|
+
});
|
|
8584
|
+
}
|
|
8536
8585
|
}
|
|
8537
8586
|
const archConstraintsContent = await getArchConstraints$2(deps);
|
|
8538
8587
|
const templateTokens = countTokens(template);
|
|
@@ -12041,8 +12090,10 @@ function assembleVerificationContext(opts) {
|
|
|
12041
12090
|
} catch {
|
|
12042
12091
|
commitSha = "unknown";
|
|
12043
12092
|
}
|
|
12044
|
-
const
|
|
12045
|
-
const
|
|
12093
|
+
const trustedDir = opts.trustedProfileDir ?? opts.workingDir;
|
|
12094
|
+
const profileBuildCommand = readProfileKey(trustedDir, "buildCommand");
|
|
12095
|
+
const profileTestCommand = readProfileKey(trustedDir, "testCommand");
|
|
12096
|
+
const trustedLanguages = readProfileLanguagesLocal(trustedDir);
|
|
12046
12097
|
return {
|
|
12047
12098
|
storyKey: opts.storyKey,
|
|
12048
12099
|
workingDir: opts.workingDir,
|
|
@@ -12057,13 +12108,26 @@ function assembleVerificationContext(opts) {
|
|
|
12057
12108
|
...opts.changedFiles !== void 0 ? { changedFiles: opts.changedFiles } : {},
|
|
12058
12109
|
...opts.modifiedTrackedFiles !== void 0 ? { modifiedTrackedFiles: opts.modifiedTrackedFiles } : {},
|
|
12059
12110
|
...profileBuildCommand !== void 0 ? { buildCommand: profileBuildCommand } : {},
|
|
12060
|
-
...profileTestCommand !== void 0 ? { testCommand: profileTestCommand } : {}
|
|
12111
|
+
...profileTestCommand !== void 0 ? { testCommand: profileTestCommand } : {},
|
|
12112
|
+
...trustedLanguages.length > 0 ? { trustedLanguages } : {}
|
|
12061
12113
|
};
|
|
12062
12114
|
}
|
|
12063
12115
|
/**
|
|
12064
12116
|
* Read a single `<key>: value` line from `.substrate/project-profile.yaml`
|
|
12065
12117
|
* under `workingDir` (H1.2). Line-based parse — no yaml dependency.
|
|
12066
12118
|
*/
|
|
12119
|
+
function readProfileLanguagesLocal(dir) {
|
|
12120
|
+
const profilePath = join$1(dir, ".substrate", "project-profile.yaml");
|
|
12121
|
+
if (!existsSync(profilePath)) return [];
|
|
12122
|
+
try {
|
|
12123
|
+
const content = readFileSync(profilePath, "utf-8");
|
|
12124
|
+
const langs = new Set();
|
|
12125
|
+
for (const m of content.matchAll(/^\s*(?:-\s+)?language:\s*['"]?([a-z]+)['"]?\s*$/gm)) if (m[1] !== void 0) langs.add(m[1]);
|
|
12126
|
+
return [...langs];
|
|
12127
|
+
} catch {
|
|
12128
|
+
return [];
|
|
12129
|
+
}
|
|
12130
|
+
}
|
|
12067
12131
|
function readProfileKey(workingDir, key) {
|
|
12068
12132
|
const profilePath = join$1(workingDir, ".substrate", "project-profile.yaml");
|
|
12069
12133
|
if (!existsSync(profilePath)) return void 0;
|
|
@@ -15591,6 +15655,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15591
15655
|
const verifContext = assembleVerificationContext({
|
|
15592
15656
|
storyKey,
|
|
15593
15657
|
workingDir: effectiveProjectRoot ?? process.cwd(),
|
|
15658
|
+
...projectRoot !== void 0 ? { trustedProfileDir: projectRoot } : {},
|
|
15594
15659
|
reviewResult: latestReviewSignals,
|
|
15595
15660
|
storyContent: storyContentForVerification,
|
|
15596
15661
|
devStoryResult: devStorySignals,
|
|
@@ -15681,6 +15746,7 @@ function createImplementationOrchestrator(deps) {
|
|
|
15681
15746
|
const retryVerifContext = assembleVerificationContext({
|
|
15682
15747
|
storyKey,
|
|
15683
15748
|
workingDir: effectiveProjectRoot ?? process.cwd(),
|
|
15749
|
+
...projectRoot !== void 0 ? { trustedProfileDir: projectRoot } : {},
|
|
15684
15750
|
reviewResult: latestReviewSignals,
|
|
15685
15751
|
storyContent: storyContentForVerification,
|
|
15686
15752
|
devStoryResult: devStorySignals,
|
|
@@ -16449,23 +16515,26 @@ function createImplementationOrchestrator(deps) {
|
|
|
16449
16515
|
continue;
|
|
16450
16516
|
}
|
|
16451
16517
|
if (isPhantomReview && timeoutRetried) {
|
|
16518
|
+
const isStoryFileMissing = (reviewResult.error ?? "").includes("story-file-missing");
|
|
16519
|
+
const escalationReason = isStoryFileMissing ? "story-file-missing" : "consecutive-review-timeouts";
|
|
16452
16520
|
logger$27.warn({
|
|
16453
16521
|
storyKey,
|
|
16454
16522
|
reviewCycles,
|
|
16455
|
-
error: reviewResult.error
|
|
16456
|
-
|
|
16523
|
+
error: reviewResult.error,
|
|
16524
|
+
reason: escalationReason
|
|
16525
|
+
}, "Consecutive review failures (original + retry) — escalating immediately");
|
|
16457
16526
|
endPhase(storyKey, "code-review");
|
|
16458
16527
|
updateStory(storyKey, {
|
|
16459
16528
|
phase: "ESCALATED",
|
|
16460
|
-
error:
|
|
16529
|
+
error: escalationReason,
|
|
16461
16530
|
completedAt: new Date().toISOString()
|
|
16462
16531
|
});
|
|
16463
16532
|
await writeStoryMetricsBestEffort(storyKey, "escalated", reviewCycles + 1);
|
|
16464
16533
|
await emitEscalation({
|
|
16465
16534
|
storyKey,
|
|
16466
|
-
lastVerdict:
|
|
16535
|
+
lastVerdict: escalationReason,
|
|
16467
16536
|
reviewCycles: reviewCycles + 1,
|
|
16468
|
-
issues: ["Review dispatch failed twice consecutively (original + phantom-retry). Likely resource-constrained or diff too large for reviewer."]
|
|
16537
|
+
issues: [isStoryFileMissing ? `Story artifact is missing from BOTH the working tree and the branch HEAD (${reviewResult.error ?? ""}). An agent deleted it and it was never committed — check the wip/feat commits on the story branch for the last good copy.` : "Review dispatch failed twice consecutively (original + phantom-retry). Likely resource-constrained or diff too large for reviewer."]
|
|
16469
16538
|
});
|
|
16470
16539
|
await persistState();
|
|
16471
16540
|
return;
|
|
@@ -47727,7 +47796,7 @@ async function runFullPipeline(options) {
|
|
|
47727
47796
|
*/
|
|
47728
47797
|
async function emitPreDispatchVersionAdvisory(currentVersion) {
|
|
47729
47798
|
if (process.env["SUBSTRATE_NO_UPDATE_CHECK"] === "1") return;
|
|
47730
|
-
const { createVersionManager } = await import("./version-manager-impl
|
|
47799
|
+
const { createVersionManager } = await import("./version-manager-impl--XXnwjMd.js");
|
|
47731
47800
|
const vm = createVersionManager();
|
|
47732
47801
|
const result = await vm.checkForUpdates(true);
|
|
47733
47802
|
const gap = classifyVersionGap(currentVersion, result.latestVersion);
|
|
@@ -47834,4 +47903,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
|
|
|
47834
47903
|
|
|
47835
47904
|
//#endregion
|
|
47836
47905
|
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, 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 };
|
|
47837
|
-
//# sourceMappingURL=run-
|
|
47906
|
+
//# sourceMappingURL=run-DbT2-Wzg.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createVersionManager } from "./dist-
|
|
1
|
+
import { createVersionManager } from "./dist-90byyGPp.js";
|
|
2
2
|
import { execSync, spawn } from "child_process";
|
|
3
3
|
import * as readline from "readline";
|
|
4
4
|
|
|
@@ -123,4 +123,4 @@ function registerUpgradeCommand(program) {
|
|
|
123
123
|
|
|
124
124
|
//#endregion
|
|
125
125
|
export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
|
|
126
|
-
//# sourceMappingURL=upgrade-
|
|
126
|
+
//# sourceMappingURL=upgrade-Dw6jKkH3.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./dist-
|
|
1
|
+
import "./dist-90byyGPp.js";
|
|
2
2
|
import "./version-manager-impl-qFBiO4Eh.js";
|
|
3
|
-
import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-
|
|
3
|
+
import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-Dw6jKkH3.js";
|
|
4
4
|
|
|
5
5
|
export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
|
package/package.json
CHANGED