substrate-ai 0.21.1 → 0.21.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -3
- package/dist/adapter-registry-BSig1zpx.js +4 -0
- package/dist/cli/index.js +114 -19
- package/dist/cli/templates/agents-md-substrate-section.md +12 -1
- package/dist/cli/templates/claude-md-substrate-section.md +6 -0
- package/dist/cli/templates/gemini-md-substrate-section.md +12 -1
- package/dist/{decisions-BPwrDCTx.js → decisions-lxU14pNh.js} +1 -1
- package/dist/{dist-BkhYgJWo.js → dist-CpnLJuVw.js} +13 -3
- package/dist/{errors-C7pY6_yQ.js → errors-8tVEwG6v.js} +2 -2
- package/dist/{experimenter-BYqALeaE.js → experimenter-C7swe92R.js} +1 -1
- package/dist/{health-Cfkv6XoQ.js → health-Dnzblihr.js} +3 -3
- package/dist/{health-Coh3BG8W.js → health-bhMCTYDO.js} +3 -3
- package/dist/{index-CnV5PcSR.d.ts → index-C31XtSMn.d.ts} +8 -1
- package/dist/index.d.ts +45 -2
- package/dist/index.js +2 -2
- package/dist/{interactive-prompt-BBfPSxyJ.js → interactive-prompt-BM5RaXYG.js} +2 -2
- package/dist/{manifest-read-BhNRIiqm.js → manifest-read-B3gE46DX.js} +369 -4
- package/dist/modules/interactive-prompt/index.js +3 -3
- package/dist/{routing-BS-Q8_2L.js → routing-CGO2UZyA.js} +1 -1
- package/dist/{run-CKM-5T34.js → run-ChZFveqv.js} +5 -5
- package/dist/{run-JrEnvaB0.js → run-ZxFHQyE_.js} +219 -8
- package/dist/src/modules/recovery-engine/index.d.ts +16 -2
- package/dist/{upgrade-S1oUMH5P.js → upgrade-BUSzXgnd.js} +2 -2
- package/dist/{upgrade-BOWLlLbD.js → upgrade-M0UkDCeg.js} +2 -2
- package/dist/{version-manager-impl-BVcsgUtN.js → version-manager-impl-DeEPhQlA.js} +1 -1
- package/package.json +1 -1
- package/packs/bmad/prompts/create-story.md +22 -0
- package/dist/adapter-registry-CZn__637.js +0 -4
package/README.md
CHANGED
|
@@ -157,11 +157,21 @@ Stories run in parallel across your available agents, each in its own git worktr
|
|
|
157
157
|
|
|
158
158
|
#### Per-Story Worktree Lifecycle
|
|
159
159
|
|
|
160
|
-
Each dispatched story runs in a dedicated git worktree
|
|
160
|
+
Each dispatched story runs in a dedicated git worktree on branch `substrate/story-<key>`. **Since v0.20.149 the worktree base is external by default** — `~/.substrate/worktrees/<projectname>-<hash8>/<key>/`, outside your repo; set `worktree.base: in-repo` in `.substrate/config.yaml` to restore the legacy `.substrate-worktrees/<key>/` path. **Commit-first (v0.20.139+):** substrate auto-commits the agent's output to the story branch (`feat(story-N-M): <title>`) at **dev-story completion — before review** — so the branch is always the durable copy of the work; failure paths add `wip(story-<key>)` checkpoints. Pre-commit hooks run on the substrate commit. If the commit fails (a hook rejects) or the run produced no committable changes, the story escalates `dev-story-commit-failed` / `dev-story-no-commit`. How the verified branch integrates is controlled by [finalization mode](#finalization). After a verification failure, the worktree and branch are preserved for inspection via `substrate reconcile-from-disk`. Use `--no-worktree` for projects that don't support worktrees (submodules, bare repos).
|
|
161
|
+
|
|
162
|
+
#### Finalization
|
|
163
|
+
|
|
164
|
+
`finalization.mode` in `.substrate/config.yaml` (or `--finalization <mode>` per run) decides how a verified story's branch integrates:
|
|
165
|
+
|
|
166
|
+
- **`merge`** (default) — local merge into the run's start branch, **fast-forward-only by default** (a base that moved during the run escalates `ff-only-merge-not-possible` rather than fabricating a merge commit). `finalization.merge_strategy: three-way` enables merge commits and is **required for concurrent multi-story runs**.
|
|
167
|
+
- **`branch`** — nothing self-merges; the `substrate/story-<key>` branch is the deliverable (safe for brownfield repos).
|
|
168
|
+
- **`pr`** — branch + push + `gh pr create` (one PR per story); degrades to `branch` on push/gh failure, never blocks.
|
|
169
|
+
|
|
170
|
+
NDJSON lifecycle events `story:committed` → (`story:merged`) → `story:finalized` report the outcome, and `substrate report` lists any unmerged deliverable branches.
|
|
161
171
|
|
|
162
172
|
### Verification Pipeline
|
|
163
173
|
|
|
164
|
-
|
|
174
|
+
A Tier-A gate sequence runs after code review. Each gate can pass, warn, or fail; failures block SHIP_IT.
|
|
165
175
|
|
|
166
176
|
| Gate | What it catches |
|
|
167
177
|
|---|---|
|
|
@@ -169,6 +179,10 @@ Six gates run after code review. Each can pass, warn, or fail; failures block SH
|
|
|
169
179
|
| **trivial-output** | Output token count below threshold — likely no real work done |
|
|
170
180
|
| **acceptance-criteria-evidence** | Each AC has demonstrable evidence in dev-story signals (files modified, tests added) |
|
|
171
181
|
| **build** | Project build succeeds against the dev's worktree |
|
|
182
|
+
| **test-suite** | Runs the project's real test command (from the trusted main-tree profile) and fails on a red suite; rejects exit-code-laundering wrappers (`… \|\| true`) |
|
|
183
|
+
| **scope-contamination** | Foreign-language sources / foreign toolchain manifests / build-output droppings vs the project's declared languages |
|
|
184
|
+
| **test-mutation** | Warns when a story modifies or deletes pre-existing tracked test files (reward-hack tripwire), including committed and renamed test files |
|
|
185
|
+
| **net-new-implementation** | A "success" story whose diff is artifact-only, an empty stub, or a whitespace-only edit escalates `no-implementation` |
|
|
172
186
|
| **runtime-probes** | Each declared `## Runtime Probes` section probe runs successfully against real or sandboxed state. Includes auto-detection for error-shape envelopes (`{"isError": true}`, `{"status": "error"}`) and production-trigger requirements for event-driven ACs. Frontmatter `external_state_dependencies` declarations hard-gate when probes section is missing. |
|
|
173
187
|
| **source-ac-fidelity** | AC text in source epic appears verbatim in story artifact (paths, MUST clauses, hard contracts). Includes 4 context-aware heuristics: negation (paths the AC says NOT to deliver), dependency-context (peer packages the implementation imports), operational-path (system install destinations like `.git/hooks/`), and alternative-option groups. |
|
|
174
188
|
|
|
@@ -501,6 +515,20 @@ token_ceilings:
|
|
|
501
515
|
# Optional: dispatch timeout overrides (ms)
|
|
502
516
|
dispatch_timeouts:
|
|
503
517
|
dev-story: 1800000 # 30 min
|
|
518
|
+
|
|
519
|
+
# Optional: how verified stories integrate (v0.20.147+)
|
|
520
|
+
finalization:
|
|
521
|
+
mode: merge # merge (default) | branch | pr
|
|
522
|
+
merge_strategy: ff-only # ff-only (default) | three-way (needed for concurrent multi-story)
|
|
523
|
+
# epic_gate_command: "uv run pytest" # must pass before the last story of an epic integrates
|
|
524
|
+
|
|
525
|
+
# Optional: per-story worktree location (v0.20.149+)
|
|
526
|
+
worktree:
|
|
527
|
+
base: external # external (default: ~/.substrate/worktrees/...) | in-repo
|
|
528
|
+
|
|
529
|
+
# Optional: spawned-agent permission profile (v0.20.152+)
|
|
530
|
+
dispatch:
|
|
531
|
+
permission_profile: skip # skip (default) | scoped (per-worktree settings; accident-mitigation, not a security boundary)
|
|
504
532
|
```
|
|
505
533
|
|
|
506
534
|
### Configuration Files
|
|
@@ -527,7 +555,7 @@ substrate init
|
|
|
527
555
|
|
|
528
556
|
Without Dolt, all functionality works except for: `substrate diff`, `substrate history`, persistent OTEL observability tables, and context engineering repo-map storage.
|
|
529
557
|
|
|
530
|
-
**On-disk operator surface:** Each pipeline run creates per-story
|
|
558
|
+
**On-disk operator surface:** Each pipeline run creates a per-story worktree — by default under `~/.substrate/worktrees/<project>-<hash>/<key>/` (external base; `worktree.base: in-repo` restores `.substrate-worktrees/<key>/`). Verified stories integrate per the [finalization mode](#finalization) and their worktrees are removed; failed or escalated stories preserve their worktree and branch for operator inspection via `substrate reconcile-from-disk`.
|
|
531
559
|
|
|
532
560
|
## CLI Command Reference
|
|
533
561
|
|
|
@@ -551,6 +579,7 @@ These commands are typically invoked by your AI assistant during pipeline operat
|
|
|
551
579
|
| `substrate run --max-review-cycles <n>` | Cycles per story (default 2; use 3 for migrations / interface extraction) |
|
|
552
580
|
| `substrate run --skip-verification` | Skip post-dispatch verification (use sparingly) |
|
|
553
581
|
| `substrate run --no-worktree` | Disable per-story git worktrees (use for submodule repos or bare repos that don't support worktrees) |
|
|
582
|
+
| `substrate run --finalization <mode>` | How verified work integrates: `merge` (default) / `branch` / `pr` — see [Finalization](#finalization) |
|
|
554
583
|
| `substrate run --help-agent` | Print agent instruction prompt fragment |
|
|
555
584
|
| `substrate resume` | Resume an interrupted run |
|
|
556
585
|
| `substrate cancel` | Cancel a running pipeline |
|
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-Dnzblihr.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-CpnLJuVw.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 { JOURNEY_DEFERRALS_PATH, JOURNEY_REGISTRY_PATH, RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, loadJourneyRegistryFromFile, loadJourneyRegistryFromTrustedTree, parseJourneyDeferrals, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-B3gE46DX.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-ZxFHQyE_.js";
|
|
9
|
+
import "../errors-8tVEwG6v.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-BM5RaXYG.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-BUSzXgnd.js";
|
|
18
18
|
import { Command } from "commander";
|
|
19
19
|
import { fileURLToPath } from "url";
|
|
20
20
|
import { dirname, join, resolve } from "path";
|
|
@@ -25,11 +25,11 @@ import * as actualFS from "node:fs";
|
|
|
25
25
|
import { existsSync, promises, readFileSync, writeFileSync } from "node:fs";
|
|
26
26
|
import { execFile, spawnSync } from "node:child_process";
|
|
27
27
|
import * as path$1 from "node:path";
|
|
28
|
-
import { basename as basename$1, join as join$1, posix, relative, resolve as resolve$1, win32 } from "node:path";
|
|
28
|
+
import { basename as basename$1, dirname as dirname$1, join as join$1, posix, relative, resolve as resolve$1, win32 } from "node:path";
|
|
29
29
|
import { randomUUID } from "node:crypto";
|
|
30
30
|
import { z } from "zod";
|
|
31
31
|
import * as fs from "node:fs/promises";
|
|
32
|
-
import { lstat, readFile as readFile$1, readdir as readdir$1, readlink, realpath } from "node:fs/promises";
|
|
32
|
+
import { lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, writeFile as writeFile$1 } from "node:fs/promises";
|
|
33
33
|
import { chmodSync, cpSync, existsSync as existsSync$1, lstatSync, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdir as readdir$2, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1, rmSync as rmSync$1, statSync as statSync$1, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
34
34
|
import { homedir } from "os";
|
|
35
35
|
import { createRequire } from "node:module";
|
|
@@ -699,6 +699,7 @@ const WHOLESALE_SUBSTRATE_IGNORES = new Set([
|
|
|
699
699
|
const STAR = ".substrate/*";
|
|
700
700
|
const CONFIG_NEGATION = "!.substrate/config.yaml";
|
|
701
701
|
const PROFILE_NEGATION = "!.substrate/project-profile.yaml";
|
|
702
|
+
const ACCEPTANCE_NEGATION = "!.substrate/acceptance/";
|
|
702
703
|
const CODEX_PROMPTS = ".codex/prompts/";
|
|
703
704
|
const CODEX_SKILLS = ".codex/skills/";
|
|
704
705
|
/**
|
|
@@ -717,6 +718,9 @@ function computeSubstrateGitignore(existing) {
|
|
|
717
718
|
const profileNegIdx = trimmed.lastIndexOf(PROFILE_NEGATION);
|
|
718
719
|
const profileNegationEffective = profileNegIdx !== -1 && profileNegIdx > starIdx;
|
|
719
720
|
if (!profileNegationEffective) append.push(PROFILE_NEGATION);
|
|
721
|
+
const acceptanceNegIdx = trimmed.lastIndexOf(ACCEPTANCE_NEGATION);
|
|
722
|
+
const acceptanceNegationEffective = acceptanceNegIdx !== -1 && acceptanceNegIdx > starIdx;
|
|
723
|
+
if (!acceptanceNegationEffective) append.push(ACCEPTANCE_NEGATION);
|
|
720
724
|
if (!trimmed.includes(CODEX_PROMPTS)) append.push(CODEX_PROMPTS);
|
|
721
725
|
if (!trimmed.includes(CODEX_SKILLS)) append.push(CODEX_SKILLS);
|
|
722
726
|
let content = lines.join("\n");
|
|
@@ -7126,7 +7130,7 @@ async function runStatusAction(options) {
|
|
|
7126
7130
|
logger$15.debug({ err }, "Work graph query failed, continuing without work graph data");
|
|
7127
7131
|
}
|
|
7128
7132
|
if (run === void 0) {
|
|
7129
|
-
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-
|
|
7133
|
+
const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-bhMCTYDO.js");
|
|
7130
7134
|
const substrateDirPath = join(projectRoot, ".substrate");
|
|
7131
7135
|
const processInfo = inspectProcessTree$1({
|
|
7132
7136
|
projectRoot,
|
|
@@ -8074,7 +8078,7 @@ function defaultSupervisorDeps() {
|
|
|
8074
8078
|
if (cached === null) {
|
|
8075
8079
|
const { AdapterRegistry: AR } = await import(
|
|
8076
8080
|
/* @vite-ignore */
|
|
8077
|
-
"../adapter-registry-
|
|
8081
|
+
"../adapter-registry-BSig1zpx.js"
|
|
8078
8082
|
);
|
|
8079
8083
|
cached = new AR();
|
|
8080
8084
|
await cached.discoverAndRegister();
|
|
@@ -8641,11 +8645,11 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
8641
8645
|
try {
|
|
8642
8646
|
const { createExperimenter } = await import(
|
|
8643
8647
|
/* @vite-ignore */
|
|
8644
|
-
"../experimenter-
|
|
8648
|
+
"../experimenter-C7swe92R.js"
|
|
8645
8649
|
);
|
|
8646
8650
|
const { getLatestRun: getLatest } = await import(
|
|
8647
8651
|
/* @vite-ignore */
|
|
8648
|
-
"../decisions-
|
|
8652
|
+
"../decisions-lxU14pNh.js"
|
|
8649
8653
|
);
|
|
8650
8654
|
const expAdapter = createDatabaseAdapter({
|
|
8651
8655
|
backend: "auto",
|
|
@@ -8655,7 +8659,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
8655
8659
|
await initSchema(expAdapter);
|
|
8656
8660
|
const { runRunAction: runPipeline } = await import(
|
|
8657
8661
|
/* @vite-ignore */
|
|
8658
|
-
"../run-
|
|
8662
|
+
"../run-ChZFveqv.js"
|
|
8659
8663
|
);
|
|
8660
8664
|
const runStoryFn = async (opts) => {
|
|
8661
8665
|
const exitCode = await runPipeline({
|
|
@@ -9180,7 +9184,7 @@ async function runMetricsAction(options) {
|
|
|
9180
9184
|
const routingConfigPath = join(dbDir, "routing.yml");
|
|
9181
9185
|
let routingConfig = null;
|
|
9182
9186
|
if (existsSync$1(routingConfigPath)) try {
|
|
9183
|
-
const { loadModelRoutingConfig } = await import("../routing-
|
|
9187
|
+
const { loadModelRoutingConfig } = await import("../routing-CGO2UZyA.js");
|
|
9184
9188
|
routingConfig = loadModelRoutingConfig(routingConfigPath);
|
|
9185
9189
|
} catch {}
|
|
9186
9190
|
if (routingConfig === null) routingConfig = {
|
|
@@ -12988,7 +12992,7 @@ function computeReportVerdict(summary, runStatus) {
|
|
|
12988
12992
|
if (summary.total === 0) return "NO STORIES RUN";
|
|
12989
12993
|
return "ALL PASSED";
|
|
12990
12994
|
}
|
|
12991
|
-
function renderHuman(output, manifest) {
|
|
12995
|
+
function renderHuman$1(output, manifest) {
|
|
12992
12996
|
const lines = [];
|
|
12993
12997
|
const { runId, summary, stories, escalations, cost, duration, halts } = output;
|
|
12994
12998
|
const durationStr = duration.wall_clock_ms != null ? formatDurationMs(duration.wall_clock_ms) : "unknown";
|
|
@@ -13411,7 +13415,7 @@ async function runReportAction(options) {
|
|
|
13411
13415
|
output.ac_traceability = acTraceability;
|
|
13412
13416
|
}
|
|
13413
13417
|
if (outputFormat === "json") process.stdout.write(renderJson(output) + "\n");
|
|
13414
|
-
else process.stdout.write(renderHuman(output, manifest));
|
|
13418
|
+
else process.stdout.write(renderHuman$1(output, manifest));
|
|
13415
13419
|
return 0;
|
|
13416
13420
|
}
|
|
13417
13421
|
/**
|
|
@@ -13435,6 +13439,96 @@ function registerReportCommand(program, _version = "0.0.0", projectRoot = proces
|
|
|
13435
13439
|
});
|
|
13436
13440
|
}
|
|
13437
13441
|
|
|
13442
|
+
//#endregion
|
|
13443
|
+
//#region src/cli/commands/acceptance.ts
|
|
13444
|
+
const ACCEPTANCE_EXIT_SUCCESS = 0;
|
|
13445
|
+
const ACCEPTANCE_EXIT_ERROR = 1;
|
|
13446
|
+
function summarizeRegistry(registry) {
|
|
13447
|
+
const journeyCount = registry.journeys.length;
|
|
13448
|
+
const endStateCount = registry.journeys.reduce((n, j) => n + j.end_states.length, 0);
|
|
13449
|
+
const criticalCount = registry.journeys.filter((j) => j.criticality === "critical").length;
|
|
13450
|
+
return `journey registry v${String(registry.version)}: ${String(journeyCount)} journeys (${String(criticalCount)} critical), ${String(endStateCount)} end-states`;
|
|
13451
|
+
}
|
|
13452
|
+
/** Render a load result for humans. Returns the exit code. */
|
|
13453
|
+
function renderHuman(result, source) {
|
|
13454
|
+
switch (result.status) {
|
|
13455
|
+
case "ok":
|
|
13456
|
+
process.stdout.write(`OK — ${summarizeRegistry(result.registry)} (${source})\n`);
|
|
13457
|
+
for (const journey of result.registry.journeys) process.stdout.write(` ${journey.id} [${journey.criticality}] ${journey.title} — ${String(journey.end_states.length)} end-state(s), surfaces: ${journey.surfaces.join(", ")}\n`);
|
|
13458
|
+
return ACCEPTANCE_EXIT_SUCCESS;
|
|
13459
|
+
case "absent":
|
|
13460
|
+
process.stdout.write(`NO REGISTRY — ${JOURNEY_REGISTRY_PATH} not found (${source}).\nAuthor it at planning time; see the acceptance-gate design brief for the schema.\n`);
|
|
13461
|
+
return ACCEPTANCE_EXIT_ERROR;
|
|
13462
|
+
case "invalid":
|
|
13463
|
+
process.stdout.write(`INVALID — ${JOURNEY_REGISTRY_PATH} failed validation (${source}):\n`);
|
|
13464
|
+
for (const issue of result.issues) process.stdout.write(` ${issue.path}: ${issue.message}\n`);
|
|
13465
|
+
return ACCEPTANCE_EXIT_ERROR;
|
|
13466
|
+
case "error":
|
|
13467
|
+
process.stdout.write(`ERROR — could not read the registry (${source}): ${result.message}\n`);
|
|
13468
|
+
return ACCEPTANCE_EXIT_ERROR;
|
|
13469
|
+
}
|
|
13470
|
+
}
|
|
13471
|
+
function registerAcceptanceCommand(program, version) {
|
|
13472
|
+
const acceptanceCmd = program.command("acceptance").description("Acceptance Gate — journey registry tools (the missing sprint demo)");
|
|
13473
|
+
acceptanceCmd.command("validate").description(`Lint ${JOURNEY_REGISTRY_PATH} with actionable, pathed errors`).option("--ref <ref>", "validate the COMMITTED registry at a git ref (trusted-tree read) instead of the working tree").option("--output-format <format>", "Output format: text (default) or json", "text").action(async (opts) => {
|
|
13474
|
+
const projectRoot = process.cwd();
|
|
13475
|
+
const source = opts.ref !== void 0 ? `committed @ ${opts.ref}` : "working tree";
|
|
13476
|
+
const result = opts.ref !== void 0 ? await loadJourneyRegistryFromTrustedTree(projectRoot, opts.ref) : await loadJourneyRegistryFromFile(projectRoot);
|
|
13477
|
+
if (opts.outputFormat === "json") {
|
|
13478
|
+
const output = buildJsonOutput("substrate acceptance validate", {
|
|
13479
|
+
source,
|
|
13480
|
+
...result
|
|
13481
|
+
}, version);
|
|
13482
|
+
process.stdout.write(JSON.stringify(output, null, 2) + "\n");
|
|
13483
|
+
process.exit(result.status === "ok" ? ACCEPTANCE_EXIT_SUCCESS : ACCEPTANCE_EXIT_ERROR);
|
|
13484
|
+
}
|
|
13485
|
+
process.exit(renderHuman(result, source));
|
|
13486
|
+
});
|
|
13487
|
+
acceptanceCmd.command("defer <journeyId>").description("Record an operator deferral for a journey — the coverage audit reports it `deferred` instead of unclaimed/unwalked. Writes to the working tree; COMMIT the file for the audit (trusted tree) to honor it.").requiredOption("--reason <text>", "why this journey is deferred (the operator ack is the point)").action(async (journeyId, opts) => {
|
|
13488
|
+
const projectRoot = process.cwd();
|
|
13489
|
+
const registry = await loadJourneyRegistryFromFile(projectRoot);
|
|
13490
|
+
if (registry.status !== "ok") {
|
|
13491
|
+
process.stdout.write(`cannot defer: journey registry is ${registry.status} at ${JOURNEY_REGISTRY_PATH} — fix it first (substrate acceptance validate)\n`);
|
|
13492
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13493
|
+
}
|
|
13494
|
+
if (!registry.registry.journeys.some((j) => j.id === journeyId)) {
|
|
13495
|
+
process.stdout.write(`cannot defer: journey "${journeyId}" is not in the registry. Known ids: ${registry.registry.journeys.map((j) => j.id).join(", ")}\n`);
|
|
13496
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13497
|
+
}
|
|
13498
|
+
const deferralsPath = join$1(projectRoot, JOURNEY_DEFERRALS_PATH);
|
|
13499
|
+
let existingContent = "";
|
|
13500
|
+
try {
|
|
13501
|
+
existingContent = await readFile$1(deferralsPath, "utf-8");
|
|
13502
|
+
} catch {}
|
|
13503
|
+
const existing = parseJourneyDeferrals(existingContent);
|
|
13504
|
+
if (!existing.ok) {
|
|
13505
|
+
process.stdout.write(`cannot defer: ${JOURNEY_DEFERRALS_PATH} is invalid:\n`);
|
|
13506
|
+
for (const issue of existing.issues) process.stdout.write(` ${issue.path}: ${issue.message}\n`);
|
|
13507
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13508
|
+
}
|
|
13509
|
+
if (existing.deferrals.some((d) => d.journey === journeyId)) {
|
|
13510
|
+
process.stdout.write(`journey ${journeyId} is already deferred — no change\n`);
|
|
13511
|
+
process.exit(ACCEPTANCE_EXIT_SUCCESS);
|
|
13512
|
+
}
|
|
13513
|
+
const deferrals = [...existing.deferrals, {
|
|
13514
|
+
journey: journeyId,
|
|
13515
|
+
reason: opts.reason,
|
|
13516
|
+
deferred_at: new Date().toISOString()
|
|
13517
|
+
}];
|
|
13518
|
+
const rendered = "deferrals:\n" + deferrals.map((d) => ` - journey: ${d.journey}\n reason: ${JSON.stringify(d.reason)}\n` + (d.deferred_at !== void 0 ? ` deferred_at: ${JSON.stringify(d.deferred_at)}\n` : "")).join("");
|
|
13519
|
+
try {
|
|
13520
|
+
await mkdir$1(dirname$1(deferralsPath), { recursive: true });
|
|
13521
|
+
await writeFile$1(deferralsPath, rendered, "utf-8");
|
|
13522
|
+
} catch (err) {
|
|
13523
|
+
process.stdout.write(`failed to write ${JOURNEY_DEFERRALS_PATH}: ${String(err)}\n`);
|
|
13524
|
+
process.exit(ACCEPTANCE_EXIT_ERROR);
|
|
13525
|
+
}
|
|
13526
|
+
process.stdout.write(`deferred ${journeyId} ("${opts.reason}") → ${JOURNEY_DEFERRALS_PATH}\nCOMMIT this file — the coverage audit reads the trusted (committed) tree.
|
|
13527
|
+
`);
|
|
13528
|
+
process.exit(ACCEPTANCE_EXIT_SUCCESS);
|
|
13529
|
+
});
|
|
13530
|
+
}
|
|
13531
|
+
|
|
13438
13532
|
//#endregion
|
|
13439
13533
|
//#region src/cli/index.ts
|
|
13440
13534
|
process.setMaxListeners(20);
|
|
@@ -13494,6 +13588,7 @@ async function createProgram() {
|
|
|
13494
13588
|
registerMonitorCommand(program, version);
|
|
13495
13589
|
registerMergeCommand(program);
|
|
13496
13590
|
registerWorktreesCommand(program, version);
|
|
13591
|
+
registerAcceptanceCommand(program, version);
|
|
13497
13592
|
registerBrainstormCommand(program, version);
|
|
13498
13593
|
registerExportCommand(program, version);
|
|
13499
13594
|
registerIngestEpicCommand(program);
|
|
@@ -13508,8 +13603,8 @@ async function createProgram() {
|
|
|
13508
13603
|
/** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
|
|
13509
13604
|
function checkForUpdatesInBackground(currentVersion) {
|
|
13510
13605
|
if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
|
|
13511
|
-
import("../upgrade-
|
|
13512
|
-
const { createVersionManager } = await import("../version-manager-impl-
|
|
13606
|
+
import("../upgrade-M0UkDCeg.js").then(async () => {
|
|
13607
|
+
const { createVersionManager } = await import("../version-manager-impl-DeEPhQlA.js");
|
|
13513
13608
|
const vm = createVersionManager();
|
|
13514
13609
|
const result = await vm.checkForUpdates();
|
|
13515
13610
|
if (result.updateAvailable) {
|
|
@@ -69,7 +69,17 @@ The Recovery Engine runs a 3-tier auto-fix ladder before any halt — Tier A ret
|
|
|
69
69
|
|
|
70
70
|
### Per-Story Worktree Behavior
|
|
71
71
|
|
|
72
|
-
Each dispatched story runs in
|
|
72
|
+
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).
|
|
73
|
+
|
|
74
|
+
### Finalization — how verified work integrates
|
|
75
|
+
|
|
76
|
+
`finalization.mode` in `.substrate/config.yaml` (or `--finalization <mode>` per run):
|
|
77
|
+
|
|
78
|
+
- **`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.
|
|
79
|
+
- **`branch`**: verified work stays on `substrate/story-<key>` — nothing self-merges; the branch is the deliverable. The safe brownfield mode.
|
|
80
|
+
- **`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.
|
|
81
|
+
|
|
82
|
+
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).
|
|
73
83
|
|
|
74
84
|
### Key Commands
|
|
75
85
|
|
|
@@ -79,6 +89,7 @@ Each dispatched story runs in `.substrate-worktrees/story-<key>` on its own bran
|
|
|
79
89
|
| `substrate run --halt-on <severity>` | Halt policy: `all` / `critical` (default) / `none` |
|
|
80
90
|
| `substrate run --non-interactive` | Suppress stdin prompts |
|
|
81
91
|
| `substrate run --no-worktree` | Disable per-story git worktrees (use for submodules or bare repos) |
|
|
92
|
+
| `substrate run --finalization <mode>` | Integration mode: `merge` (default) / `branch` (never self-merge) / `pr` |
|
|
82
93
|
| `substrate report [--run <id\|latest>]` | Per-run completion report |
|
|
83
94
|
| `substrate report --verify-ac` | Append AC-to-Test traceability matrix |
|
|
84
95
|
| `substrate reconcile-from-disk [--dry-run] [--yes]` | Path A reconciliation when tree is coherent |
|
|
@@ -93,6 +93,12 @@ Each dispatched story runs in an isolated git worktree on its own branch (`subst
|
|
|
93
93
|
|
|
94
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).
|
|
95
95
|
|
|
96
|
+
### Acceptance Gate — journey coverage (optional)
|
|
97
|
+
|
|
98
|
+
If the project declares a journey registry at `.substrate/acceptance/journeys.yaml` (PRD user journeys with concrete end-states — COMMIT the file; substrate reads the committed copy, never an agent-writable worktree copy), the pipeline audits journey coverage at each epic close and at run end: every registered journey lands in exactly one state — `walked-pass`, `walked-fail`, `deferred`, `unclaimed` (NO story claims it — the never-wired-journey class), or `unwalked`. Results stream as `acceptance:coverage` events and land on the run manifest.
|
|
99
|
+
|
|
100
|
+
`acceptance.mode` in `.substrate/config.yaml`: `advisory` (default — warns, never blocks), `blocking` (an unclaimed/unwalked journey escalates `journey-unclaimed`/`journey-unwalked` on the LAST story of the epic before it integrates), or `off`. Create-story tags stories with the journeys they deliver (`journeys:` frontmatter). To explicitly skip a journey: `substrate acceptance defer <id> --reason "<why>"` and commit the deferral file. Lint the registry with `substrate acceptance validate`.
|
|
101
|
+
|
|
96
102
|
### Key Commands Reference
|
|
97
103
|
|
|
98
104
|
| Command | Purpose |
|
|
@@ -69,7 +69,17 @@ The Recovery Engine runs a 3-tier auto-fix ladder before any halt — Tier A ret
|
|
|
69
69
|
|
|
70
70
|
### Per-Story Worktree Behavior
|
|
71
71
|
|
|
72
|
-
Each dispatched story runs in
|
|
72
|
+
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).
|
|
73
|
+
|
|
74
|
+
### Finalization — how verified work integrates
|
|
75
|
+
|
|
76
|
+
`finalization.mode` in `.substrate/config.yaml` (or `--finalization <mode>` per run):
|
|
77
|
+
|
|
78
|
+
- **`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.
|
|
79
|
+
- **`branch`**: verified work stays on `substrate/story-<key>` — nothing self-merges; the branch is the deliverable. The safe brownfield mode.
|
|
80
|
+
- **`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.
|
|
81
|
+
|
|
82
|
+
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).
|
|
73
83
|
|
|
74
84
|
### Key Commands
|
|
75
85
|
|
|
@@ -79,6 +89,7 @@ Each dispatched story runs in `.substrate-worktrees/story-<key>` on its own bran
|
|
|
79
89
|
| `substrate run --halt-on <severity>` | Halt policy: `all` / `critical` (default) / `none` |
|
|
80
90
|
| `substrate run --non-interactive` | Suppress stdin prompts |
|
|
81
91
|
| `substrate run --no-worktree` | Disable per-story git worktrees (use for submodules or bare repos) |
|
|
92
|
+
| `substrate run --finalization <mode>` | Integration mode: `merge` (default) / `branch` (never self-merge) / `pr` |
|
|
82
93
|
| `substrate report [--run <id\|latest>]` | Per-run completion report |
|
|
83
94
|
| `substrate report --verify-ac` | Append AC-to-Test traceability matrix |
|
|
84
95
|
| `substrate reconcile-from-disk [--dry-run] [--yes]` | Path A reconciliation when tree is coherent |
|
|
@@ -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-CpnLJuVw.js";
|
|
2
2
|
import "./decisions-CzSIEeGP.js";
|
|
3
3
|
|
|
4
4
|
export { getLatestRun };
|
|
@@ -6341,7 +6341,12 @@ const SubstrateConfigSchema = z.object({
|
|
|
6341
6341
|
]).optional(),
|
|
6342
6342
|
merge_strategy: z.enum(["ff-only", "three-way"]).optional(),
|
|
6343
6343
|
epic_gate_command: z.string().optional()
|
|
6344
|
-
}).strict().optional()
|
|
6344
|
+
}).strict().optional(),
|
|
6345
|
+
acceptance: z.object({ mode: z.enum([
|
|
6346
|
+
"off",
|
|
6347
|
+
"advisory",
|
|
6348
|
+
"blocking"
|
|
6349
|
+
]).optional() }).strict().optional()
|
|
6345
6350
|
}).passthrough();
|
|
6346
6351
|
const PartialProviderConfigSchema = ProviderConfigSchema.partial();
|
|
6347
6352
|
const PartialGlobalSettingsSchema = GlobalSettingsSchema.partial();
|
|
@@ -6368,7 +6373,12 @@ const PartialSubstrateConfigSchema = z.object({
|
|
|
6368
6373
|
]).optional(),
|
|
6369
6374
|
merge_strategy: z.enum(["ff-only", "three-way"]).optional(),
|
|
6370
6375
|
epic_gate_command: z.string().optional()
|
|
6371
|
-
}).strict().optional()
|
|
6376
|
+
}).strict().optional(),
|
|
6377
|
+
acceptance: z.object({ mode: z.enum([
|
|
6378
|
+
"off",
|
|
6379
|
+
"advisory",
|
|
6380
|
+
"blocking"
|
|
6381
|
+
]).optional() }).strict().optional()
|
|
6372
6382
|
}).passthrough();
|
|
6373
6383
|
|
|
6374
6384
|
//#endregion
|
|
@@ -12628,4 +12638,4 @@ async function callLLM(params) {
|
|
|
12628
12638
|
|
|
12629
12639
|
//#endregion
|
|
12630
12640
|
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 };
|
|
12631
|
-
//# sourceMappingURL=dist-
|
|
12641
|
+
//# sourceMappingURL=dist-CpnLJuVw.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdtError } from "./dist-
|
|
1
|
+
import { AdtError } from "./dist-CpnLJuVw.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-8tVEwG6v.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-CpnLJuVw.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-CpnLJuVw.js";
|
|
3
|
+
import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-B3gE46DX.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-Dnzblihr.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-Dnzblihr.js";
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
|
-
import "./dist-
|
|
4
|
-
import "./manifest-read-
|
|
3
|
+
import "./dist-CpnLJuVw.js";
|
|
4
|
+
import "./manifest-read-B3gE46DX.js";
|
|
5
5
|
import "./work-graph-repository-DZyJv5pV.js";
|
|
6
6
|
import "./decisions-CzSIEeGP.js";
|
|
7
7
|
|
|
@@ -314,6 +314,13 @@ declare const SubstrateConfigSchema: z.ZodObject<{
|
|
|
314
314
|
}>>;
|
|
315
315
|
epic_gate_command: z.ZodOptional<z.ZodString>;
|
|
316
316
|
}, z.core.$strict>>;
|
|
317
|
+
acceptance: z.ZodOptional<z.ZodObject<{
|
|
318
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
319
|
+
off: "off";
|
|
320
|
+
advisory: "advisory";
|
|
321
|
+
blocking: "blocking";
|
|
322
|
+
}>>;
|
|
323
|
+
}, z.core.$strict>>;
|
|
317
324
|
}, z.core.$loose>;
|
|
318
325
|
type SubstrateConfig = z.infer<typeof SubstrateConfigSchema>; //#endregion
|
|
319
326
|
//#region packages/core/dist/events/core-events.d.ts
|
|
@@ -1622,4 +1629,4 @@ interface Recommendation {
|
|
|
1622
1629
|
|
|
1623
1630
|
//#endregion
|
|
1624
1631
|
export { AdapterDiscoveryResult, AdapterRegistry as AdapterRegistry$1, AdtError as AdtError$1, ClaudeCodeAdapter as ClaudeCodeAdapter$1, CodexCLIAdapter as CodexCLIAdapter$1, ConfigError as ConfigError$1, ConfigIncompatibleFormatError as ConfigIncompatibleFormatError$1, CoreEvents, DatabaseAdapter, DiscoveryReport, GeminiCLIAdapter as GeminiCLIAdapter$1, Recommendation, TypedEventBus };
|
|
1625
|
-
//# sourceMappingURL=index-
|
|
1632
|
+
//# sourceMappingURL=index-C31XtSMn.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdapterDiscoveryResult, AdapterRegistry$1 as AdapterRegistry, AdtError$1 as AdtError, ClaudeCodeAdapter$1 as ClaudeCodeAdapter, CodexCLIAdapter$1 as CodexCLIAdapter, ConfigError$1 as ConfigError, ConfigIncompatibleFormatError$1 as ConfigIncompatibleFormatError, DiscoveryReport, GeminiCLIAdapter$1 as GeminiCLIAdapter, Recommendation, TypedEventBus } from "./index-
|
|
1
|
+
import { AdapterDiscoveryResult, AdapterRegistry$1 as AdapterRegistry, AdtError$1 as AdtError, ClaudeCodeAdapter$1 as ClaudeCodeAdapter, CodexCLIAdapter$1 as CodexCLIAdapter, ConfigError$1 as ConfigError, ConfigIncompatibleFormatError$1 as ConfigIncompatibleFormatError, DiscoveryReport, GeminiCLIAdapter$1 as GeminiCLIAdapter, Recommendation, TypedEventBus } from "./index-C31XtSMn.js";
|
|
2
2
|
import pino from "pino";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Readable, Writable } from "node:stream";
|
|
@@ -203,6 +203,32 @@ interface StoryFinalizedEvent {
|
|
|
203
203
|
/** PR URL (pr mode, only when gh pr create succeeded) */
|
|
204
204
|
pr_url?: string;
|
|
205
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* A0.3 (acceptance-gate): journey coverage audit result, emitted at each
|
|
208
|
+
* epic close and at run end (`scope: "final"`). Every registered journey in
|
|
209
|
+
* scope lands in exactly one state; `unclaimed` is the never-wired-journey
|
|
210
|
+
* class (UJ-2) caught structurally. In `blocking` mode an unclaimed/unwalked
|
|
211
|
+
* journey escalates the LAST story of the epic before it integrates; in
|
|
212
|
+
* `advisory` mode (the default) this event and a warning are the signal.
|
|
213
|
+
*/
|
|
214
|
+
interface AcceptanceCoverageEvent {
|
|
215
|
+
type: 'acceptance:coverage';
|
|
216
|
+
/** ISO-8601 timestamp generated at emit time */
|
|
217
|
+
ts: string;
|
|
218
|
+
/** Audited boundary: `epic-<n>` or `final` */
|
|
219
|
+
scope: string;
|
|
220
|
+
/** Audit posture the run is under */
|
|
221
|
+
mode: 'advisory' | 'blocking';
|
|
222
|
+
/** Per-journey coverage states */
|
|
223
|
+
entries: {
|
|
224
|
+
journeyId: string;
|
|
225
|
+
criticality: 'critical' | 'standard';
|
|
226
|
+
state: 'walked-pass' | 'walked-fail' | 'deferred' | 'unclaimed' | 'unwalked';
|
|
227
|
+
ownerStories: string[];
|
|
228
|
+
}[];
|
|
229
|
+
/** State counts across `entries` */
|
|
230
|
+
summary: Record<string, number>;
|
|
231
|
+
}
|
|
206
232
|
/**
|
|
207
233
|
* Emitted when the orchestrator auto-approves a story after exhausting
|
|
208
234
|
* review cycles with only minor issues remaining. Provides transparency
|
|
@@ -836,7 +862,7 @@ interface PipelineMergeConflictDetectedEvent {
|
|
|
836
862
|
* }
|
|
837
863
|
* ```
|
|
838
864
|
*/
|
|
839
|
-
type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | PipelinePreFlightFailureEvent | PipelineProfileStaleEvent | PipelineContractMismatchEvent | PipelineContractVerificationSummaryEvent | StoryPhaseEvent | StoryDoneEvent | StoryCommittedEvent | StoryMergedEvent | StoryFinalizedEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | StoryZeroDiffEscalationEvent | StoryBuildVerificationFailedEvent | StoryBuildVerificationPassedEvent | StoryInterfaceChangeWarningEvent | StoryMetricsEvent | SupervisorPollEvent | SupervisorKillEvent | SupervisorRestartEvent | SupervisorAbortEvent | SupervisorSummaryEvent | SupervisorAnalysisCompleteEvent | SupervisorAnalysisErrorEvent | SupervisorExperimentStartEvent | SupervisorExperimentSkipEvent | SupervisorExperimentRecommendationsEvent | SupervisorExperimentCompleteEvent | SupervisorExperimentErrorEvent | RoutingModelSelectedEvent | PipelinePhaseStartEvent | PipelinePhaseCompleteEvent | StoryAutoApprovedEvent | VerificationCheckCompleteEvent | VerificationStoryCompleteEvent | CostWarningEvent | CostCeilingReachedEvent | DecisionHaltSkippedNonInteractiveEvent | PipelineMergeConflictDetectedEvent; //#endregion
|
|
865
|
+
type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | PipelinePreFlightFailureEvent | PipelineProfileStaleEvent | PipelineContractMismatchEvent | PipelineContractVerificationSummaryEvent | StoryPhaseEvent | StoryDoneEvent | StoryCommittedEvent | StoryMergedEvent | StoryFinalizedEvent | AcceptanceCoverageEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | StoryZeroDiffEscalationEvent | StoryBuildVerificationFailedEvent | StoryBuildVerificationPassedEvent | StoryInterfaceChangeWarningEvent | StoryMetricsEvent | SupervisorPollEvent | SupervisorKillEvent | SupervisorRestartEvent | SupervisorAbortEvent | SupervisorSummaryEvent | SupervisorAnalysisCompleteEvent | SupervisorAnalysisErrorEvent | SupervisorExperimentStartEvent | SupervisorExperimentSkipEvent | SupervisorExperimentRecommendationsEvent | SupervisorExperimentCompleteEvent | SupervisorExperimentErrorEvent | RoutingModelSelectedEvent | PipelinePhaseStartEvent | PipelinePhaseCompleteEvent | StoryAutoApprovedEvent | VerificationCheckCompleteEvent | VerificationStoryCompleteEvent | CostWarningEvent | CostCeilingReachedEvent | DecisionHaltSkippedNonInteractiveEvent | PipelineMergeConflictDetectedEvent; //#endregion
|
|
840
866
|
//#region src/core/errors.d.ts
|
|
841
867
|
|
|
842
868
|
/**
|
|
@@ -1497,6 +1523,23 @@ interface OrchestratorEvents {
|
|
|
1497
1523
|
sha: string;
|
|
1498
1524
|
prUrl?: string;
|
|
1499
1525
|
};
|
|
1526
|
+
/**
|
|
1527
|
+
* A0.3 (acceptance-gate): journey coverage audit result — emitted at epic
|
|
1528
|
+
* close and at run end. Mapped to the NDJSON `acceptance:coverage` event.
|
|
1529
|
+
*/
|
|
1530
|
+
'orchestrator:acceptance-coverage': {
|
|
1531
|
+
scope: string;
|
|
1532
|
+
mode: 'advisory' | 'blocking';
|
|
1533
|
+
entries: {
|
|
1534
|
+
journeyId: string;
|
|
1535
|
+
title: string;
|
|
1536
|
+
criticality: 'critical' | 'standard';
|
|
1537
|
+
epic?: number;
|
|
1538
|
+
state: 'walked-pass' | 'walked-fail' | 'deferred' | 'unclaimed' | 'unwalked';
|
|
1539
|
+
ownerStories: string[];
|
|
1540
|
+
}[];
|
|
1541
|
+
summary: Record<string, number>;
|
|
1542
|
+
};
|
|
1500
1543
|
/** A story has been escalated after exceeding max review cycles */
|
|
1501
1544
|
'orchestrator:story-escalated': {
|
|
1502
1545
|
storyKey: string;
|
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-CpnLJuVw.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-8tVEwG6v.js";
|
|
6
6
|
|
|
7
7
|
//#region src/core/di.ts
|
|
8
8
|
/**
|