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.
Files changed (28) hide show
  1. package/README.md +32 -3
  2. package/dist/adapter-registry-BSig1zpx.js +4 -0
  3. package/dist/cli/index.js +114 -19
  4. package/dist/cli/templates/agents-md-substrate-section.md +12 -1
  5. package/dist/cli/templates/claude-md-substrate-section.md +6 -0
  6. package/dist/cli/templates/gemini-md-substrate-section.md +12 -1
  7. package/dist/{decisions-BPwrDCTx.js → decisions-lxU14pNh.js} +1 -1
  8. package/dist/{dist-BkhYgJWo.js → dist-CpnLJuVw.js} +13 -3
  9. package/dist/{errors-C7pY6_yQ.js → errors-8tVEwG6v.js} +2 -2
  10. package/dist/{experimenter-BYqALeaE.js → experimenter-C7swe92R.js} +1 -1
  11. package/dist/{health-Cfkv6XoQ.js → health-Dnzblihr.js} +3 -3
  12. package/dist/{health-Coh3BG8W.js → health-bhMCTYDO.js} +3 -3
  13. package/dist/{index-CnV5PcSR.d.ts → index-C31XtSMn.d.ts} +8 -1
  14. package/dist/index.d.ts +45 -2
  15. package/dist/index.js +2 -2
  16. package/dist/{interactive-prompt-BBfPSxyJ.js → interactive-prompt-BM5RaXYG.js} +2 -2
  17. package/dist/{manifest-read-BhNRIiqm.js → manifest-read-B3gE46DX.js} +369 -4
  18. package/dist/modules/interactive-prompt/index.js +3 -3
  19. package/dist/{routing-BS-Q8_2L.js → routing-CGO2UZyA.js} +1 -1
  20. package/dist/{run-CKM-5T34.js → run-ChZFveqv.js} +5 -5
  21. package/dist/{run-JrEnvaB0.js → run-ZxFHQyE_.js} +219 -8
  22. package/dist/src/modules/recovery-engine/index.d.ts +16 -2
  23. package/dist/{upgrade-S1oUMH5P.js → upgrade-BUSzXgnd.js} +2 -2
  24. package/dist/{upgrade-BOWLlLbD.js → upgrade-M0UkDCeg.js} +2 -2
  25. package/dist/{version-manager-impl-BVcsgUtN.js → version-manager-impl-DeEPhQlA.js} +1 -1
  26. package/package.json +1 -1
  27. package/packs/bmad/prompts/create-story.md +22 -0
  28. 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 at `.substrate-worktrees/story-<key>` on branch `substrate/story-<key>`. After verification produces a SHIP_IT verdict, **substrate auto-commits the dispatched agent's output** to the story branch with a `feat(story-N-M): <title>` message (v0.20.86+substrate does NOT rely on the agent running `git commit` itself, since empirical audit found agents don't reliably do so). Pre-commit hooks run on the substrate commit. The branch then merges to the base branch (typically main) and the worktree is removed. If the commit fails (e.g., a pre-commit hook rejects) or the agent's run produced no committable changes, the story escalates with `dev-story-commit-failed` or `dev-story-no-commit` instead of merging an empty branch. After a verification failure, the worktree and branch are preserved so you can inspect the partial implementation via `substrate reconcile-from-disk`. Use `--no-worktree` if your project does not support worktrees (e.g., submodules, bare repos).
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
- Six gates run after code review. Each can pass, warn, or fail; failures block SHIP_IT.
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 worktrees under `.substrate-worktrees/story-<key>/`. Successful stories are merged to main and their worktrees removed. Failed or escalated stories preserve their worktrees for operator inspection via `substrate reconcile-from-disk`.
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 |
@@ -0,0 +1,4 @@
1
+ import { AdapterRegistry } from "./dist-CpnLJuVw.js";
2
+ import "./adapter-registry-DXLMTmfD.js";
3
+
4
+ export { AdapterRegistry };
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-Cfkv6XoQ.js";
2
+ import { FileKvStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createDatabaseAdapter, createDoltOperatorReader, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, parseDbTimestampAsUtc, registerHealthCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion } from "../health-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-BkhYgJWo.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-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-BhNRIiqm.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-JrEnvaB0.js";
9
- import "../errors-C7pY6_yQ.js";
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-BBfPSxyJ.js";
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-S1oUMH5P.js";
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-Coh3BG8W.js");
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-CZn__637.js"
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-BYqALeaE.js"
8648
+ "../experimenter-C7swe92R.js"
8645
8649
  );
8646
8650
  const { getLatestRun: getLatest } = await import(
8647
8651
  /* @vite-ignore */
8648
- "../decisions-BPwrDCTx.js"
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-CKM-5T34.js"
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-BS-Q8_2L.js");
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-BOWLlLbD.js").then(async () => {
13512
- const { createVersionManager } = await import("../version-manager-impl-BVcsgUtN.js");
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 `.substrate-worktrees/story-<key>` on its own branch (`substrate/story-<key>`). The agent's auto-commit (e.g., `feat(story-N-M): ...`) lands on the branch, not main. Merge to main happens after verification SHIP_IT; the worktree is then removed. 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).
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 `.substrate-worktrees/story-<key>` on its own branch (`substrate/story-<key>`). The agent's auto-commit (e.g., `feat(story-N-M): ...`) lands on the branch, not main. Merge to main happens after verification SHIP_IT; the worktree is then removed. 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).
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-BkhYgJWo.js";
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-BkhYgJWo.js.map
12641
+ //# sourceMappingURL=dist-CpnLJuVw.js.map
@@ -1,4 +1,4 @@
1
- import { AdtError } from "./dist-BkhYgJWo.js";
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-C7pY6_yQ.js.map
74
+ //# sourceMappingURL=errors-8tVEwG6v.js.map
@@ -1,3 +1,3 @@
1
- import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-BkhYgJWo.js";
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-BkhYgJWo.js";
3
- import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-BhNRIiqm.js";
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-Cfkv6XoQ.js.map
1003
+ //# sourceMappingURL=health-Dnzblihr.js.map
@@ -1,7 +1,7 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-Cfkv6XoQ.js";
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-BkhYgJWo.js";
4
- import "./manifest-read-BhNRIiqm.js";
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-CnV5PcSR.d.ts.map
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-CnV5PcSR.js";
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-BkhYgJWo.js";
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-C7pY6_yQ.js";
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
  /**