substrate-ai 0.20.108 → 0.20.110

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.
@@ -0,0 +1,4 @@
1
+ import { AdapterRegistry } from "./dist-CQ9ZuL2a.js";
2
+ import "./adapter-registry-DIcrxjH8.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-D1xKwyaI.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-CJyzYsfu.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, createPipelineRun, 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-Dm37IPMW.js";
6
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-CIMNjDBH.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, createPipelineRun, 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-CQ9ZuL2a.js";
6
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-DdTN1lge.js";
7
7
  import "../adapter-registry-DIcrxjH8.js";
8
- import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-927qGezm.js";
9
- import "../errors-BaHE73L3.js";
8
+ import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-B3HU_Awn.js";
9
+ import "../errors-Szein5Rn.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-DblHY8se.js";
14
- import "../interactive-prompt-nDNiofTX.js";
14
+ import "../interactive-prompt-CoX8AYbn.js";
15
15
  import "../recovery-engine-BKGBeBnW.js";
16
16
  import "../version-manager-impl-qFBiO4Eh.js";
17
- import { registerUpgradeCommand } from "../upgrade-7KujpKbf.js";
17
+ import { registerUpgradeCommand } from "../upgrade-Bpd6pUrr.js";
18
18
  import { Command } from "commander";
19
19
  import { fileURLToPath } from "url";
20
20
  import { dirname, join, resolve } from "path";
@@ -6515,6 +6515,7 @@ async function runFullPipelineFromPhase(options) {
6515
6515
  } else if (currentPhase === "implementation") {
6516
6516
  let telemetryEnabled = false;
6517
6517
  let telemetryPort = 4318;
6518
+ let resumeWorktreeCopyFiles;
6518
6519
  try {
6519
6520
  const configSystem = createConfigSystem({ projectConfigDir: dbDir });
6520
6521
  await configSystem.load();
@@ -6523,6 +6524,7 @@ async function runFullPipelineFromPhase(options) {
6523
6524
  telemetryEnabled = true;
6524
6525
  telemetryPort = cfg.telemetry.port ?? 4318;
6525
6526
  }
6527
+ if (Array.isArray(cfg.worktree?.copy_files) && cfg.worktree.copy_files.length > 0) resumeWorktreeCopyFiles = [...cfg.worktree.copy_files];
6526
6528
  } catch {}
6527
6529
  const ingestionServer = telemetryEnabled ? new IngestionServer({ port: telemetryPort }) : void 0;
6528
6530
  const telemetryPersistence = telemetryEnabled ? new AdapterTelemetryPersistence(adapter) : void 0;
@@ -6536,7 +6538,8 @@ async function runFullPipelineFromPhase(options) {
6536
6538
  maxConcurrency: concurrency,
6537
6539
  maxReviewCycles: effectiveMaxReviewCycles,
6538
6540
  pipelineRunId: runId,
6539
- enableHeartbeat: eventsFlag === true
6541
+ enableHeartbeat: eventsFlag === true,
6542
+ ...resumeWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: resumeWorktreeCopyFiles } : {}
6540
6543
  },
6541
6544
  projectRoot,
6542
6545
  agentId,
@@ -6891,7 +6894,7 @@ async function runStatusAction(options) {
6891
6894
  logger$15.debug({ err }, "Work graph query failed, continuing without work graph data");
6892
6895
  }
6893
6896
  if (run === void 0) {
6894
- const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-CxU-1KLv.js");
6897
+ const { inspectProcessTree: inspectProcessTree$1 } = await import("../health-BX4kfRaJ.js");
6895
6898
  const substrateDirPath = join(projectRoot, ".substrate");
6896
6899
  const processInfo = inspectProcessTree$1({
6897
6900
  projectRoot,
@@ -7839,7 +7842,7 @@ function defaultSupervisorDeps() {
7839
7842
  if (cached === null) {
7840
7843
  const { AdapterRegistry: AR } = await import(
7841
7844
  /* @vite-ignore */
7842
- "../adapter-registry-5zXxdGZq.js"
7845
+ "../adapter-registry-jUH7TLH4.js"
7843
7846
  );
7844
7847
  cached = new AR();
7845
7848
  await cached.discoverAndRegister();
@@ -8406,11 +8409,11 @@ async function runSupervisorAction(options, deps = {}) {
8406
8409
  try {
8407
8410
  const { createExperimenter } = await import(
8408
8411
  /* @vite-ignore */
8409
- "../experimenter-BW8Bab4C.js"
8412
+ "../experimenter-COjr78xQ.js"
8410
8413
  );
8411
8414
  const { getLatestRun: getLatest } = await import(
8412
8415
  /* @vite-ignore */
8413
- "../decisions-BF76Y5h7.js"
8416
+ "../decisions-BYa6S26_.js"
8414
8417
  );
8415
8418
  const expAdapter = createDatabaseAdapter({
8416
8419
  backend: "auto",
@@ -8420,7 +8423,7 @@ async function runSupervisorAction(options, deps = {}) {
8420
8423
  await initSchema(expAdapter);
8421
8424
  const { runRunAction: runPipeline } = await import(
8422
8425
  /* @vite-ignore */
8423
- "../run-CtdP1-q9.js"
8426
+ "../run--ncQ9inj.js"
8424
8427
  );
8425
8428
  const runStoryFn = async (opts) => {
8426
8429
  const exitCode = await runPipeline({
@@ -8945,7 +8948,7 @@ async function runMetricsAction(options) {
8945
8948
  const routingConfigPath = join(dbDir, "routing.yml");
8946
8949
  let routingConfig = null;
8947
8950
  if (existsSync$1(routingConfigPath)) try {
8948
- const { loadModelRoutingConfig } = await import("../routing-CkUTlM3M.js");
8951
+ const { loadModelRoutingConfig } = await import("../routing-C_KbC9on.js");
8949
8952
  routingConfig = loadModelRoutingConfig(routingConfigPath);
8950
8953
  } catch {}
8951
8954
  if (routingConfig === null) routingConfig = {
@@ -10350,6 +10353,54 @@ async function listWorktreesAction(options) {
10350
10353
  }
10351
10354
  }
10352
10355
  /**
10356
+ * Cleanup action — removes one or all substrate-managed worktrees + their
10357
+ * branches. Wraps the existing GitWorktreeManager.cleanupWorktree /
10358
+ * cleanupAllWorktrees backend; v0.20.109 closes the gap where the
10359
+ * "already registered" error message advertised a `--cleanup` flag that
10360
+ * didn't exist.
10361
+ *
10362
+ * @param options - Action options
10363
+ * @returns - Exit code (0 = success, 1 = error)
10364
+ */
10365
+ async function cleanupWorktreesAction(options) {
10366
+ const { taskId, projectRoot } = options;
10367
+ try {
10368
+ const eventBus = createEventBus();
10369
+ const manager = createGitWorktreeManager({
10370
+ eventBus,
10371
+ projectRoot
10372
+ });
10373
+ if (taskId !== void 0) try {
10374
+ await manager.cleanupWorktree(taskId);
10375
+ process.stdout.write(`Cleaned up worktree for task "${taskId}"\n`);
10376
+ return WORKTREES_EXIT_SUCCESS;
10377
+ } catch (err) {
10378
+ const message = err instanceof Error ? err.message : String(err);
10379
+ process.stderr.write(`Error cleaning up worktree for task "${taskId}": ${message}\n`);
10380
+ logger$9.error({
10381
+ err,
10382
+ taskId
10383
+ }, "cleanupWorktreesAction (single) failed");
10384
+ return WORKTREES_EXIT_ERROR;
10385
+ }
10386
+ try {
10387
+ const cleaned = await manager.cleanupAllWorktrees();
10388
+ process.stdout.write(`Cleaned up ${cleaned} worktree${cleaned === 1 ? "" : "s"}\n`);
10389
+ return WORKTREES_EXIT_SUCCESS;
10390
+ } catch (err) {
10391
+ const message = err instanceof Error ? err.message : String(err);
10392
+ process.stderr.write(`Error during bulk cleanup: ${message}\n`);
10393
+ logger$9.error({ err }, "cleanupWorktreesAction (bulk) failed");
10394
+ return WORKTREES_EXIT_ERROR;
10395
+ }
10396
+ } catch (err) {
10397
+ const message = err instanceof Error ? err.message : String(err);
10398
+ process.stderr.write(`Error: ${message}\n`);
10399
+ logger$9.error({ err }, "cleanupWorktreesAction failed");
10400
+ return WORKTREES_EXIT_ERROR;
10401
+ }
10402
+ }
10403
+ /**
10353
10404
  * Register the `substrate worktrees` command with the CLI program.
10354
10405
  *
10355
10406
  * @param program - Commander program instance
@@ -10357,7 +10408,16 @@ async function listWorktreesAction(options) {
10357
10408
  * @param projectRoot - Project root directory (defaults to process.cwd())
10358
10409
  */
10359
10410
  function registerWorktreesCommand(program, version = "0.0.0", projectRoot = process.cwd()) {
10360
- program.command("worktrees").description("List all active git worktrees and their associated tasks").option("--output-format <format>", "Output format: table (default) or json", "table").option("--json", "Output JSON (shorthand for --output-format json)", false).option("--status <status>", `Filter by task status: ${VALID_STATUSES.join(", ")}`).option("--sort <key>", `Sort by: ${VALID_SORT_KEYS.join(", ")} (default: created)`, "created").action(async (opts) => {
10411
+ program.command("worktrees").description("List or clean up substrate git worktrees and their task branches").option("--output-format <format>", "Output format: table (default) or json", "table").option("--json", "Output JSON (shorthand for --output-format json)", false).option("--status <status>", `Filter by task status: ${VALID_STATUSES.join(", ")}`).option("--sort <key>", `Sort by: ${VALID_SORT_KEYS.join(", ")} (default: created)`, "created").option("--cleanup [task-id]", "Remove substrate worktree(s) and branches. Pass a task id to remove just one; omit the arg to remove all.").action(async (opts) => {
10412
+ if (opts.cleanup !== void 0 && opts.cleanup !== false) {
10413
+ const taskId = typeof opts.cleanup === "string" && opts.cleanup.trim().length > 0 ? opts.cleanup.trim() : void 0;
10414
+ const cleanupExitCode = await cleanupWorktreesAction({
10415
+ ...taskId !== void 0 ? { taskId } : {},
10416
+ projectRoot
10417
+ });
10418
+ process.exitCode = cleanupExitCode;
10419
+ return;
10420
+ }
10361
10421
  const outputFormat = opts.json ? "json" : opts.outputFormat === "json" ? "json" : "table";
10362
10422
  let statusFilter;
10363
10423
  if (opts.status !== void 0) {
@@ -10953,6 +11013,13 @@ async function runRetryEscalatedAction(options) {
10953
11013
  const agentAdapter = agentId != null ? injectedRegistry.get(agentId) : void 0;
10954
11014
  const adapterDefaultCycles = agentAdapter?.getCapabilities?.()?.defaultMaxReviewCycles;
10955
11015
  const effectiveMaxReviewCycles = adapterDefaultCycles != null ? Math.max(2, adapterDefaultCycles) : 2;
11016
+ let retryWorktreeCopyFiles;
11017
+ try {
11018
+ const configSystem = createConfigSystem({ projectConfigDir: join(dbRoot, ".substrate") });
11019
+ await configSystem.load();
11020
+ const cfg = configSystem.getConfig();
11021
+ if (Array.isArray(cfg.worktree?.copy_files) && cfg.worktree.copy_files.length > 0) retryWorktreeCopyFiles = [...cfg.worktree.copy_files];
11022
+ } catch {}
10956
11023
  const orchestrator = createImplementationOrchestrator({
10957
11024
  db: adapter,
10958
11025
  pack,
@@ -10963,7 +11030,8 @@ async function runRetryEscalatedAction(options) {
10963
11030
  maxConcurrency: concurrency,
10964
11031
  maxReviewCycles: effectiveMaxReviewCycles,
10965
11032
  pipelineRunId: pipelineRun.id,
10966
- ...Object.keys(perStoryContextCeilings).length > 0 ? { perStoryContextCeilings } : {}
11033
+ ...Object.keys(perStoryContextCeilings).length > 0 ? { perStoryContextCeilings } : {},
11034
+ ...retryWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: retryWorktreeCopyFiles } : {}
10967
11035
  },
10968
11036
  projectRoot,
10969
11037
  agentId
@@ -12468,6 +12536,13 @@ function registerReconcileFromDiskCommand(program, _version = "0.0.0", projectRo
12468
12536
  //#region src/cli/commands/report.ts
12469
12537
  const logger$1 = createLogger("report");
12470
12538
  /**
12539
+ * v0.20.110: Minimum output_tokens for a verified/recovered story to be
12540
+ * trusted as having actually produced work. Below this, the story is flagged
12541
+ * with `low_output_warning: true` so operators don't trust misleading metrics.
12542
+ * Boardgame backlog Item 3.
12543
+ */
12544
+ const LOW_OUTPUT_TOKEN_THRESHOLD = 100;
12545
+ /**
12471
12546
  * Determine whether verification ran for a story.
12472
12547
  *
12473
12548
  * Handles both real manifest format (checks array) and probe fixture format
@@ -12694,7 +12769,7 @@ function renderHuman(output, manifest) {
12694
12769
  const costCell = s.cost_usd != null ? `$${s.cost_usd.toFixed(4)}` : "-";
12695
12770
  const f = s.verification_findings;
12696
12771
  const findingsCell = `E:${f.error} W:${f.warn} I:${f.info}`;
12697
- const verifiedTag = s.outcome === "verified" ? "✓" : "";
12772
+ const verifiedTag = s.outcome === "verified" ? s.low_output_warning === true ? "⚠ low-out" : "✓" : s.low_output_warning === true ? "⚠ low-out" : "";
12698
12773
  const key = s.story_key.length > 50 ? s.story_key.slice(0, 49) + "…" : s.story_key;
12699
12774
  lines.push(formatRow([
12700
12775
  key,
@@ -12707,6 +12782,12 @@ function renderHuman(output, manifest) {
12707
12782
  ], COL_WIDTHS));
12708
12783
  }
12709
12784
  lines.push("");
12785
+ const lowOutputStories = stories.filter((s) => s.low_output_warning === true);
12786
+ if (lowOutputStories.length > 0) {
12787
+ lines.push(`⚠ ${lowOutputStories.length} story/stories produced fewer than ${LOW_OUTPUT_TOKEN_THRESHOLD} output tokens —`);
12788
+ lines.push(` the "verified" verdict may be misleading. Inspect dispatch artifacts before trusting.`);
12789
+ lines.push("");
12790
+ }
12710
12791
  if (escalations.length > 0) {
12711
12792
  lines.push("──── Escalation Details ────");
12712
12793
  for (const esc of escalations) {
@@ -12780,7 +12861,7 @@ function renderJson(output) {
12780
12861
  * @param manifest - Raw manifest data.
12781
12862
  * @param halts - Optional operator halt notifications (Story 73-2, AC12).
12782
12863
  */
12783
- function assembleReport(runId, manifest, halts) {
12864
+ function assembleReport(runId, manifest, halts, storyOutputTokens) {
12784
12865
  const perStoryState = manifest.per_story_state ?? {};
12785
12866
  const storyKeys = Object.keys(perStoryState);
12786
12867
  const startedAt = manifest.created_at ?? "";
@@ -12821,6 +12902,9 @@ function assembleReport(runId, manifest, halts) {
12821
12902
  const findings = extractVerificationFindings(state);
12822
12903
  const verificationRan = didVerificationRun(state);
12823
12904
  const wc = wallClockMs(state);
12905
+ const outputTokens = storyOutputTokens?.get(key);
12906
+ const trustworthyOutcome = outcome === "verified" || outcome === "recovered";
12907
+ const lowOutputWarning = outputTokens !== void 0 && trustworthyOutcome && outputTokens < LOW_OUTPUT_TOKEN_THRESHOLD;
12824
12908
  const storySummary = {
12825
12909
  story_key: key,
12826
12910
  outcome,
@@ -12828,7 +12912,9 @@ function assembleReport(runId, manifest, halts) {
12828
12912
  review_cycles: state.review_cycles ?? 0,
12829
12913
  cost_usd: state.cost_usd,
12830
12914
  verification_findings: findings,
12831
- verification_ran: verificationRan
12915
+ verification_ran: verificationRan,
12916
+ ...outputTokens !== void 0 ? { output_tokens: outputTokens } : {},
12917
+ ...lowOutputWarning ? { low_output_warning: true } : {}
12832
12918
  };
12833
12919
  stories.push(storySummary);
12834
12920
  summary[outcome]++;
@@ -12992,7 +13078,21 @@ async function runReportAction(options) {
12992
13078
  logger$1.debug({ err }, "notification read failed — continuing without halt data");
12993
13079
  return [];
12994
13080
  });
12995
- const output = assembleReport(resolvedRunId, manifest, halts);
13081
+ const storyOutputTokens = new Map();
13082
+ const metricsAdapter = createDatabaseAdapter({
13083
+ backend: "auto",
13084
+ basePath: dbRoot
13085
+ });
13086
+ try {
13087
+ await initSchema(metricsAdapter);
13088
+ const storyMetricsRows = await getStoryMetricsForRun(metricsAdapter, resolvedRunId);
13089
+ for (const row of storyMetricsRows) if (typeof row.output_tokens === "number") storyOutputTokens.set(row.story_key, row.output_tokens);
13090
+ } catch (err) {
13091
+ logger$1.debug({ err }, "story_metrics read failed — low-output flagging unavailable");
13092
+ } finally {
13093
+ await metricsAdapter.close().catch(swallowDebug("report-metrics-close"));
13094
+ }
13095
+ const output = assembleReport(resolvedRunId, manifest, halts, storyOutputTokens);
12996
13096
  if (verifyAc === true) {
12997
13097
  const artifactsDir = join(dbRoot, "_bmad-output", "implementation-artifacts");
12998
13098
  const acTraceability = {};
@@ -13130,8 +13230,8 @@ async function createProgram() {
13130
13230
  /** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
13131
13231
  function checkForUpdatesInBackground(currentVersion) {
13132
13232
  if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
13133
- import("../upgrade-fViYOn8u.js").then(async () => {
13134
- const { createVersionManager } = await import("../version-manager-impl-brvj1EYW.js");
13233
+ import("../upgrade-DoWjPygF.js").then(async () => {
13234
+ const { createVersionManager } = await import("../version-manager-impl-DyE9bMVG.js");
13135
13235
  const vm = createVersionManager();
13136
13236
  const result = await vm.checkForUpdates();
13137
13237
  if (result.updateAvailable) {
@@ -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-Dm37IPMW.js";
1
+ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-CQ9ZuL2a.js";
2
2
  import "./decisions-CzSIEeGP.js";
3
3
 
4
4
  export { getLatestRun };
@@ -2544,27 +2544,30 @@ function isDoltAvailable(basePath) {
2544
2544
  console.warn("[persistence:adapter] Dolt still unavailable after retry — falling back to InMemoryDatabaseAdapter. Telemetry and cost data will NOT persist.");
2545
2545
  return false;
2546
2546
  }
2547
+ function adapterDiag(message) {
2548
+ process.stderr.write("[persistence:adapter] " + message + "\n");
2549
+ }
2547
2550
  function createDatabaseAdapter(config = { backend: "auto" }, doltClientFactory) {
2548
2551
  const backend = config.backend ?? "auto";
2549
2552
  const basePath = config.basePath ?? process.cwd();
2550
2553
  const doltRepoPath = join$1(basePath, ".substrate", "state");
2551
2554
  if (backend === "dolt") {
2552
2555
  if (!doltClientFactory) {
2553
- console.debug("[persistence:adapter] dolt backend requested but no doltClientFactory provided; falling back to memory");
2556
+ adapterDiag("dolt backend requested but no doltClientFactory provided; falling back to memory");
2554
2557
  return new InMemoryDatabaseAdapter();
2555
2558
  }
2556
- console.debug("[persistence:adapter] Using DoltDatabaseAdapter (explicit config)");
2559
+ adapterDiag("Using DoltDatabaseAdapter (explicit config)");
2557
2560
  return new DoltDatabaseAdapter(doltClientFactory(doltRepoPath));
2558
2561
  }
2559
2562
  if (backend === "memory") {
2560
- console.debug("[persistence:adapter] Using InMemoryDatabaseAdapter (explicit config)");
2563
+ adapterDiag("Using InMemoryDatabaseAdapter (explicit config)");
2561
2564
  return new InMemoryDatabaseAdapter();
2562
2565
  }
2563
2566
  if (doltClientFactory && isDoltAvailable(basePath)) {
2564
- console.debug("[persistence:adapter] Dolt detected, using DoltDatabaseAdapter");
2567
+ adapterDiag("Dolt detected, using DoltDatabaseAdapter");
2565
2568
  return new DoltDatabaseAdapter(doltClientFactory(doltRepoPath));
2566
2569
  }
2567
- console.debug("[persistence:adapter] Dolt not available or no factory, using InMemoryDatabaseAdapter");
2570
+ adapterDiag("Dolt not available or no factory, using InMemoryDatabaseAdapter");
2568
2571
  return new InMemoryDatabaseAdapter();
2569
2572
  }
2570
2573
 
@@ -6109,6 +6112,7 @@ const TelemetryConfigSchema = z.object({
6109
6112
  meshUrl: z.string().url().optional(),
6110
6113
  projectId: z.string().optional()
6111
6114
  }).strict();
6115
+ const WorktreeConfigSchema = z.object({ copy_files: z.array(z.string()).default([]) }).strict();
6112
6116
  /** Current supported config format version */
6113
6117
  const CURRENT_CONFIG_FORMAT_VERSION = "1";
6114
6118
  /** Current supported task graph version */
@@ -6125,6 +6129,7 @@ const SubstrateConfigSchema = z.object({
6125
6129
  cost_tracker: CostTrackerConfigSchema.optional(),
6126
6130
  budget: BudgetConfigSchema.optional(),
6127
6131
  telemetry: TelemetryConfigSchema.optional(),
6132
+ worktree: WorktreeConfigSchema.optional(),
6128
6133
  trivialOutputThreshold: z.number().int().nonnegative().optional()
6129
6134
  }).passthrough();
6130
6135
  const PartialProviderConfigSchema = ProviderConfigSchema.partial();
@@ -6141,6 +6146,7 @@ const PartialSubstrateConfigSchema = z.object({
6141
6146
  cost_tracker: CostTrackerConfigSchema.partial().optional(),
6142
6147
  budget: BudgetConfigSchema.partial().optional(),
6143
6148
  telemetry: TelemetryConfigSchema.partial().optional(),
6149
+ worktree: WorktreeConfigSchema.partial().optional(),
6144
6150
  trivialOutputThreshold: z.number().int().nonnegative().optional()
6145
6151
  }).passthrough();
6146
6152
 
@@ -11251,4 +11257,4 @@ async function callLLM(params) {
11251
11257
 
11252
11258
  //#endregion
11253
11259
  export { ADVISORY_NOTES, AdapterRegistry, AdtError, BudgetConfigSchema, 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, createPipelineRun, createRequirement, createVersionManager, 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 };
11254
- //# sourceMappingURL=dist-Dm37IPMW.js.map
11260
+ //# sourceMappingURL=dist-CQ9ZuL2a.js.map
@@ -1,4 +1,4 @@
1
- import { AdtError } from "./dist-Dm37IPMW.js";
1
+ import { AdtError } from "./dist-CQ9ZuL2a.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-BaHE73L3.js.map
74
+ //# sourceMappingURL=errors-Szein5Rn.js.map
@@ -1,3 +1,3 @@
1
- import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-Dm37IPMW.js";
1
+ import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-CQ9ZuL2a.js";
2
2
 
3
3
  export { createExperimenter };
@@ -1,7 +1,7 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-D1xKwyaI.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-CJyzYsfu.js";
2
2
  import "./logger-KeHncl-f.js";
3
- import "./dist-Dm37IPMW.js";
4
- import "./manifest-read-927qGezm.js";
3
+ import "./dist-CQ9ZuL2a.js";
4
+ import "./manifest-read-B3HU_Awn.js";
5
5
  import "./work-graph-repository-DZyJv5pV.js";
6
6
  import "./decisions-CzSIEeGP.js";
7
7
 
@@ -1,6 +1,6 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-Dm37IPMW.js";
3
- import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-927qGezm.js";
2
+ import { DoltClient, DoltQueryError, createDatabaseAdapter$1 as createDatabaseAdapter, getLatestRun, getPipelineRunById, initSchema } from "./dist-CQ9ZuL2a.js";
3
+ import { resolveMainRepoRoot, resolveRunManifest } from "./manifest-read-B3HU_Awn.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-D1xKwyaI.js.map
1003
+ //# sourceMappingURL=health-CJyzYsfu.js.map
@@ -288,6 +288,9 @@ declare const SubstrateConfigSchema: z.ZodObject<{
288
288
  meshUrl: z.ZodOptional<z.ZodString>;
289
289
  projectId: z.ZodOptional<z.ZodString>;
290
290
  }, z.core.$strict>>;
291
+ worktree: z.ZodOptional<z.ZodObject<{
292
+ copy_files: z.ZodDefault<z.ZodArray<z.ZodString>>;
293
+ }, z.core.$strict>>;
291
294
  trivialOutputThreshold: z.ZodOptional<z.ZodNumber>;
292
295
  }, z.core.$loose>;
293
296
  type SubstrateConfig = z.infer<typeof SubstrateConfigSchema>; //#endregion
@@ -1429,4 +1432,4 @@ interface Recommendation {
1429
1432
 
1430
1433
  //#endregion
1431
1434
  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 };
1432
- //# sourceMappingURL=index-C8F4ACfC.d.ts.map
1435
+ //# sourceMappingURL=index-DYzIw89v.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-C8F4ACfC.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-DYzIw89v.js";
2
2
  import pino from "pino";
3
3
  import { z } from "zod";
4
4
  import { Readable, Writable } from "node:stream";
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-Dm37IPMW.js";
3
+ import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-CQ9ZuL2a.js";
4
4
  import "./adapter-registry-DIcrxjH8.js";
5
- import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-BaHE73L3.js";
5
+ import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-Szein5Rn.js";
6
6
 
7
7
  //#region src/core/di.ts
8
8
  /**
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { readCurrentRunId, resolveMainRepoRoot } from "./manifest-read-927qGezm.js";
2
+ import { readCurrentRunId, resolveMainRepoRoot } from "./manifest-read-B3HU_Awn.js";
3
3
  import { join } from "node:path";
4
4
  import { mkdir, readFile, writeFile } from "node:fs/promises";
5
5
  import * as readline from "node:readline";
@@ -180,4 +180,4 @@ async function runInteractivePrompt(decisionContext) {
180
180
 
181
181
  //#endregion
182
182
  export { runInteractivePrompt };
183
- //# sourceMappingURL=interactive-prompt-nDNiofTX.js.map
183
+ //# sourceMappingURL=interactive-prompt-CoX8AYbn.js.map
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { LEARNING_FINDING, createDecision, getDecisionsByCategory } from "./dist-Dm37IPMW.js";
2
+ import { LEARNING_FINDING, createDecision, getDecisionsByCategory } from "./dist-CQ9ZuL2a.js";
3
3
  import * as path$1 from "path";
4
4
  import { join } from "path";
5
5
  import { readFile } from "fs/promises";
@@ -5845,4 +5845,4 @@ async function resolveRunManifest(dbRoot, runId) {
5845
5845
 
5846
5846
  //#endregion
5847
5847
  export { FindingsInjector, RunManifest, RuntimeProbeListSchema, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, readCurrentRunId, renderFindings, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck, runStaleVerificationRecovery };
5848
- //# sourceMappingURL=manifest-read-927qGezm.js.map
5848
+ //# sourceMappingURL=manifest-read-B3HU_Awn.js.map
@@ -1,6 +1,6 @@
1
1
  import "../../logger-KeHncl-f.js";
2
- import "../../dist-Dm37IPMW.js";
3
- import "../../manifest-read-927qGezm.js";
4
- import { runInteractivePrompt } from "../../interactive-prompt-nDNiofTX.js";
2
+ import "../../dist-CQ9ZuL2a.js";
3
+ import "../../manifest-read-B3HU_Awn.js";
4
+ import { runInteractivePrompt } from "../../interactive-prompt-CoX8AYbn.js";
5
5
 
6
6
  export { runInteractivePrompt };
@@ -1,4 +1,4 @@
1
- import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-Dm37IPMW.js";
1
+ import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-CQ9ZuL2a.js";
2
2
  import "./routing-DFxoKHDt.js";
3
3
 
4
4
  export { loadModelRoutingConfig };
@@ -1,14 +1,14 @@
1
- import "./health-D1xKwyaI.js";
1
+ import "./health-CJyzYsfu.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
- import "./dist-Dm37IPMW.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-CIMNjDBH.js";
6
- import "./manifest-read-927qGezm.js";
4
+ import "./dist-CQ9ZuL2a.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-DdTN1lge.js";
6
+ import "./manifest-read-B3HU_Awn.js";
7
7
  import "./routing-DFxoKHDt.js";
8
8
  import "./work-graph-repository-DZyJv5pV.js";
9
9
  import "./decisions-CzSIEeGP.js";
10
10
  import "./decision-router-DblHY8se.js";
11
- import "./interactive-prompt-nDNiofTX.js";
11
+ import "./interactive-prompt-CoX8AYbn.js";
12
12
  import "./recovery-engine-BKGBeBnW.js";
13
13
 
14
14
  export { runRunAction };
@@ -1,11 +1,11 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-D1xKwyaI.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-CJyzYsfu.js";
2
2
  import { createLogger } from "./logger-KeHncl-f.js";
3
3
  import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
4
- import { ADVISORY_NOTES, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-Dm37IPMW.js";
5
- import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-927qGezm.js";
4
+ import { ADVISORY_NOTES, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-CQ9ZuL2a.js";
5
+ import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-B3HU_Awn.js";
6
6
  import { WorkGraphRepository, detectCycles } from "./work-graph-repository-DZyJv5pV.js";
7
7
  import { deriveExitCode, routeDecision } from "./decision-router-DblHY8se.js";
8
- import { runInteractivePrompt } from "./interactive-prompt-nDNiofTX.js";
8
+ import { runInteractivePrompt } from "./interactive-prompt-CoX8AYbn.js";
9
9
  import { runRecoveryEngine } from "./recovery-engine-BKGBeBnW.js";
10
10
  import { basename, dirname, extname, join } from "path";
11
11
  import { access, readFile, readdir, stat } from "fs/promises";
@@ -21,7 +21,7 @@ import path, { basename as basename$1, dirname as dirname$1, extname as extname$
21
21
  import { tmpdir } from "node:os";
22
22
  import { createHash, randomUUID } from "node:crypto";
23
23
  import { z } from "zod";
24
- import { access as access$1, lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, rename, rm, stat as stat$1, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
24
+ import { access as access$1, copyFile, lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, rename, rm, stat as stat$1, unlink as unlink$1, writeFile as writeFile$1 } from "node:fs/promises";
25
25
  import { 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, unlinkSync as unlinkSync$1, writeFileSync as writeFileSync$1 } from "fs";
26
26
  import { promisify } from "node:util";
27
27
  import { fileURLToPath } from "node:url";
@@ -144,10 +144,15 @@ async function verifyGitVersion() {
144
144
  * @param taskId - Task identifier (used in path derivation)
145
145
  * @param branchName - Branch name to create (e.g., "substrate/story-abc123")
146
146
  * @param baseBranch - Branch to base the worktree on (e.g., "main")
147
+ * @param copyFiles - v0.20.109: Optional list of files to copy from the
148
+ * project root into the new worktree after creation
149
+ * (e.g., `[".env", ".env.local"]`). Missing files are
150
+ * skipped silently. Useful for gitignored files that
151
+ * build tooling needs but `git worktree add` won't carry.
147
152
  * @returns - Object with the worktreePath
148
153
  * @throws - Error if git command fails
149
154
  */
150
- async function createWorktree(projectRoot, taskId, branchName, baseBranch) {
155
+ async function createWorktree(projectRoot, taskId, branchName, baseBranch, copyFiles = []) {
151
156
  const worktreePath = path$5.join(projectRoot, ".substrate-worktrees", taskId);
152
157
  const worktreeExists = await access$1(worktreePath).then(() => true).catch((err) => {
153
158
  if (err.code === "ENOENT") return false;
@@ -165,7 +170,7 @@ async function createWorktree(projectRoot, taskId, branchName, baseBranch) {
165
170
  recursive: true,
166
171
  force: true
167
172
  });
168
- else throw new Error(`Worktree at ${worktreePath} is already registered. Run \`substrate worktrees --cleanup\` to remove it.`);
173
+ else throw new Error(`Worktree at ${worktreePath} is already registered (branch: ${branchName}).\nThis usually means a prior dispatch escalated and the worktree was preserved for inspection.\nIt may contain uncommitted changes that are NOT on the branch — inspect before removing.\n\nTo remove and re-dispatch:\n substrate worktrees --cleanup ${taskId}\n\nTo remove all substrate worktrees:\n substrate worktrees --cleanup`);
169
174
  }
170
175
  const addResult = await spawnGit([
171
176
  "worktree",
@@ -176,9 +181,35 @@ async function createWorktree(projectRoot, taskId, branchName, baseBranch) {
176
181
  baseBranch
177
182
  ], { cwd: projectRoot });
178
183
  if (addResult.code !== 0) throw new Error(`git worktree add failed for task "${taskId}": ${addResult.stderr || addResult.stdout}`);
184
+ await copyFilesToWorktree(projectRoot, worktreePath, copyFiles);
179
185
  return { worktreePath };
180
186
  }
181
187
  /**
188
+ * Copy files from a source directory into a target worktree.
189
+ *
190
+ * Skips missing files silently (intentional — config like `[".env",
191
+ * ".env.local"]` should not blow up if `.env.local` doesn't exist in the
192
+ * parent checkout). Creates parent directories for nested paths.
193
+ *
194
+ * Exported for testability; not part of the public worktree API.
195
+ */
196
+ async function copyFilesToWorktree(sourceRoot, worktreePath, files) {
197
+ if (files.length === 0) return;
198
+ for (const relativePath of files) {
199
+ if (path$5.isAbsolute(relativePath) || relativePath.split(path$5.sep).includes("..")) continue;
200
+ const sourcePath = path$5.join(sourceRoot, relativePath);
201
+ const destPath = path$5.join(worktreePath, relativePath);
202
+ try {
203
+ await access$1(sourcePath);
204
+ } catch {
205
+ continue;
206
+ }
207
+ const destDir = path$5.dirname(destPath);
208
+ if (destDir !== worktreePath) await mkdir$1(destDir, { recursive: true });
209
+ await copyFile(sourcePath, destPath);
210
+ }
211
+ }
212
+ /**
182
213
  * Remove a git worktree by path.
183
214
  *
184
215
  * Uses `git worktree remove --force` to handle unclean worktrees.
@@ -358,16 +389,19 @@ var GitWorktreeManagerImpl = class {
358
389
  _baseDirectory;
359
390
  _db;
360
391
  _logger;
392
+ /** v0.20.109: files to copy from project root into each new worktree (e.g. `.env`). */
393
+ _copyFiles;
361
394
  /** Bound listener references for cleanup in shutdown() */
362
395
  _onTaskReady;
363
396
  _onTaskComplete;
364
397
  _onTaskFailed;
365
- constructor(eventBus, projectRoot, baseDirectory = DEFAULT_WORKTREE_BASE, db = null, logger$27) {
398
+ constructor(eventBus, projectRoot, baseDirectory = DEFAULT_WORKTREE_BASE, db = null, logger$27, copyFiles = []) {
366
399
  this._eventBus = eventBus;
367
400
  this._projectRoot = projectRoot;
368
401
  this._baseDirectory = baseDirectory;
369
402
  this._db = db;
370
403
  this._logger = logger$27 ?? console;
404
+ this._copyFiles = copyFiles;
371
405
  this._onTaskReady = ({ taskId }) => {
372
406
  this._handleTaskReady(taskId).catch((err) => {
373
407
  this._logger.error({
@@ -431,9 +465,10 @@ var GitWorktreeManagerImpl = class {
431
465
  taskId,
432
466
  branchName,
433
467
  worktreePath,
434
- baseBranch
468
+ baseBranch,
469
+ copyFiles: this._copyFiles
435
470
  }, "createWorktree");
436
- await createWorktree(this._projectRoot, taskId, branchName, baseBranch);
471
+ await createWorktree(this._projectRoot, taskId, branchName, baseBranch, this._copyFiles);
437
472
  const createdAt = new Date();
438
473
  this._eventBus.emit("worktree:created", {
439
474
  taskId,
@@ -657,7 +692,7 @@ var GitWorktreeManagerImpl = class {
657
692
  }
658
693
  };
659
694
  function createGitWorktreeManager(options) {
660
- return new GitWorktreeManagerImpl(options.eventBus, options.projectRoot, options.baseDirectory, options.db ?? null, options.logger);
695
+ return new GitWorktreeManagerImpl(options.eventBus, options.projectRoot, options.baseDirectory, options.db ?? null, options.logger, options.copyFiles);
661
696
  }
662
697
 
663
698
  //#endregion
@@ -13279,7 +13314,8 @@ function createImplementationOrchestrator(deps) {
13279
13314
  const noWorktree = config.noWorktree ?? false;
13280
13315
  const _worktreeManager = worktreeManager ?? (projectRoot !== void 0 && !noWorktree ? createGitWorktreeManager({
13281
13316
  eventBus: toCoreEventBus(eventBus),
13282
- projectRoot
13317
+ projectRoot,
13318
+ ...config.worktreeCopyFiles !== void 0 ? { copyFiles: config.worktreeCopyFiles } : {}
13283
13319
  }) : void 0);
13284
13320
  const logger$27 = createLogger("implementation-orchestrator");
13285
13321
  const telemetryAdvisor = db !== void 0 ? createTelemetryAdvisor({ db }) : void 0;
@@ -45599,6 +45635,7 @@ async function runRunAction(options) {
45599
45635
  let meshUrl;
45600
45636
  let meshProjectId;
45601
45637
  let configRetryBudget;
45638
+ let configWorktreeCopyFiles;
45602
45639
  try {
45603
45640
  const configSystem = createConfigSystem({ projectConfigDir: dbDir });
45604
45641
  await configSystem.load();
@@ -45617,6 +45654,10 @@ async function runRunAction(options) {
45617
45654
  meshProjectId = cfg.telemetry.projectId;
45618
45655
  }
45619
45656
  if (typeof cfg.retry_budget === "number") configRetryBudget = cfg.retry_budget;
45657
+ if (Array.isArray(cfg.worktree?.copy_files) && cfg.worktree.copy_files.length > 0) {
45658
+ configWorktreeCopyFiles = [...cfg.worktree.copy_files];
45659
+ logger.info({ copyFiles: configWorktreeCopyFiles }, "Loaded worktree.copy_files from config");
45660
+ }
45620
45661
  } catch {
45621
45662
  logger.debug("Config loading skipped — using default token ceilings and telemetry settings");
45622
45663
  }
@@ -45705,7 +45746,8 @@ async function runRunAction(options) {
45705
45746
  maxReviewCycles: effectiveMaxReviewCycles,
45706
45747
  retryBudget: configRetryBudget ?? 2,
45707
45748
  agentId,
45708
- ...noWorktree === true ? { noWorktree: true } : {}
45749
+ ...noWorktree === true ? { noWorktree: true } : {},
45750
+ ...configWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: configWorktreeCopyFiles } : {}
45709
45751
  });
45710
45752
  let storyKeys = [...parsedStoryKeys];
45711
45753
  if (!existsSync$1(dbDir)) mkdirSync$1(dbDir, { recursive: true });
@@ -46257,7 +46299,8 @@ async function runRunAction(options) {
46257
46299
  ...skipVerification === true ? { skipVerification: true } : {},
46258
46300
  ...probeAuthor !== void 0 ? { probeAuthorMode: probeAuthor } : {},
46259
46301
  probeAuthorStateIntegrating: resolvedProbeAuthorStateIntegrating,
46260
- ...noWorktree === true ? { noWorktree: true } : {}
46302
+ ...noWorktree === true ? { noWorktree: true } : {},
46303
+ ...configWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: configWorktreeCopyFiles } : {}
46261
46304
  },
46262
46305
  projectRoot,
46263
46306
  tokenCeilings,
@@ -46475,7 +46518,7 @@ async function runRunAction(options) {
46475
46518
  }
46476
46519
  }
46477
46520
  async function runFullPipeline(options) {
46478
- const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, skipVerification, maxReviewCycles = 2, retryBudget, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort, agentId, meshUrl: fpMeshUrl, meshProjectId: fpMeshProjectId, engineType: fpEngineType, probeAuthor, probeAuthorStateIntegrating: fpProbeAuthorStateIntegrating, noWorktree } = options;
46521
+ const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, skipVerification, maxReviewCycles = 2, retryBudget, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort, agentId, meshUrl: fpMeshUrl, meshProjectId: fpMeshProjectId, engineType: fpEngineType, probeAuthor, probeAuthorStateIntegrating: fpProbeAuthorStateIntegrating, noWorktree, worktreeCopyFiles: fpWorktreeCopyFiles } = options;
46479
46522
  if (!existsSync$1(dbDir)) mkdirSync$1(dbDir, { recursive: true });
46480
46523
  let doltServerFull = null;
46481
46524
  try {
@@ -46784,7 +46827,8 @@ async function runFullPipeline(options) {
46784
46827
  ...skipVerification === true ? { skipVerification: true } : {},
46785
46828
  ...probeAuthor !== void 0 ? { probeAuthorMode: probeAuthor } : {},
46786
46829
  ...fpProbeAuthorStateIntegrating !== void 0 ? { probeAuthorStateIntegrating: fpProbeAuthorStateIntegrating } : {},
46787
- ...noWorktree === true ? { noWorktree: true } : {}
46830
+ ...noWorktree === true ? { noWorktree: true } : {},
46831
+ ...fpWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: fpWorktreeCopyFiles } : {}
46788
46832
  },
46789
46833
  projectRoot,
46790
46834
  tokenCeilings,
@@ -46954,7 +46998,7 @@ async function runFullPipeline(options) {
46954
46998
  */
46955
46999
  async function emitPreDispatchVersionAdvisory(currentVersion) {
46956
47000
  if (process.env["SUBSTRATE_NO_UPDATE_CHECK"] === "1") return;
46957
- const { createVersionManager } = await import("./version-manager-impl-brvj1EYW.js");
47001
+ const { createVersionManager } = await import("./version-manager-impl-DyE9bMVG.js");
46958
47002
  const vm = createVersionManager();
46959
47003
  const result = await vm.checkForUpdates(true);
46960
47004
  const gap = classifyVersionGap(currentVersion, result.latestVersion);
@@ -47051,4 +47095,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
47051
47095
 
47052
47096
  //#endregion
47053
47097
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
47054
- //# sourceMappingURL=run-CIMNjDBH.js.map
47098
+ //# sourceMappingURL=run-DdTN1lge.js.map
@@ -1,4 +1,4 @@
1
- import { CoreEvents, DatabaseAdapter, TypedEventBus } from "../../../index-C8F4ACfC.js";
1
+ import { CoreEvents, DatabaseAdapter, TypedEventBus } from "../../../index-DYzIw89v.js";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region packages/sdlc/dist/verification/findings.d.ts
@@ -1,4 +1,4 @@
1
- import { createVersionManager } from "./dist-Dm37IPMW.js";
1
+ import { createVersionManager } from "./dist-CQ9ZuL2a.js";
2
2
  import { execSync, spawn } from "child_process";
3
3
  import * as readline from "readline";
4
4
 
@@ -123,4 +123,4 @@ function registerUpgradeCommand(program) {
123
123
 
124
124
  //#endregion
125
125
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
126
- //# sourceMappingURL=upgrade-7KujpKbf.js.map
126
+ //# sourceMappingURL=upgrade-Bpd6pUrr.js.map
@@ -1,5 +1,5 @@
1
- import "./dist-Dm37IPMW.js";
1
+ import "./dist-CQ9ZuL2a.js";
2
2
  import "./version-manager-impl-qFBiO4Eh.js";
3
- import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-7KujpKbf.js";
3
+ import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-Bpd6pUrr.js";
4
4
 
5
5
  export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
@@ -1,4 +1,4 @@
1
- import { VersionManagerImpl, createVersionManager } from "./dist-Dm37IPMW.js";
1
+ import { VersionManagerImpl, createVersionManager } from "./dist-CQ9ZuL2a.js";
2
2
  import "./version-manager-impl-qFBiO4Eh.js";
3
3
 
4
4
  export { createVersionManager };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.108",
3
+ "version": "0.20.110",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,4 +0,0 @@
1
- import { AdapterRegistry } from "./dist-Dm37IPMW.js";
2
- import "./adapter-registry-DIcrxjH8.js";
3
-
4
- export { AdapterRegistry };