substrate-ai 0.20.31 → 0.20.32

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.
@@ -1,4 +1,4 @@
1
- import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-B0cPyaYJ.js";
1
+ import { BMAD_BASELINE_TOKENS_FULL, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, WorkGraphRepository, __commonJS, __require, __toESM, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectCycles, detectsEventDrivenAC, extractTargetFilesFromStoryContent, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, renderFindings, resolveGraphPath, resolveMainRepoRoot, validateStoryKey } from "./health-DJ4z2uWN.js";
2
2
  import { createLogger } from "./logger-KeHncl-f.js";
3
3
  import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
4
4
  import { ADVISORY_NOTES, 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, createConfigSystem, createDatabaseAdapter$1, createDecision, createPipelineRun, createRequirement, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-CqtWS9wF.js";
@@ -9,11 +9,12 @@ import yaml from "js-yaml";
9
9
  import * as actualFS from "node:fs";
10
10
  import { accessSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
11
11
  import { exec, execFile, execFileSync, execSync, spawn } from "node:child_process";
12
+ import * as path$2 from "node:path";
12
13
  import path, { basename as basename$1, dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, posix, resolve as resolve$1, win32 } from "node:path";
13
14
  import { tmpdir } from "node:os";
14
15
  import { createHash, randomUUID } from "node:crypto";
15
16
  import { z } from "zod";
16
- import { access as access$1, lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, stat as stat$1, unlink, writeFile as writeFile$1 } from "node:fs/promises";
17
+ import { access as access$1, lstat, mkdir as mkdir$1, readFile as readFile$1, readdir as readdir$1, readlink, realpath, rename, stat as stat$1, unlink, writeFile as writeFile$1 } from "node:fs/promises";
17
18
  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";
18
19
  import { promisify } from "node:util";
19
20
  import { fileURLToPath } from "node:url";
@@ -2122,7 +2123,7 @@ async function runHelpAgent() {
2122
2123
 
2123
2124
  //#endregion
2124
2125
  //#region src/persistence/dolt-server.ts
2125
- const logger$23 = createLogger("dolt-server");
2126
+ const logger$25 = createLogger("dolt-server");
2126
2127
  /**
2127
2128
  * Start a dolt sql-server for the given project, if Dolt is available and no
2128
2129
  * server is already running (socket already exists).
@@ -2139,7 +2140,7 @@ async function startDoltServer(projectRoot) {
2139
2140
  if (!existsSync(join$1(stateDir, ".dolt"))) return null;
2140
2141
  try {
2141
2142
  await access$1(socketPath);
2142
- logger$23.debug("Dolt socket already exists at %s — using existing server", socketPath);
2143
+ logger$25.debug("Dolt socket already exists at %s — using existing server", socketPath);
2143
2144
  return null;
2144
2145
  } catch {}
2145
2146
  try {
@@ -2148,10 +2149,10 @@ async function startDoltServer(projectRoot) {
2148
2149
  stdio: "pipe"
2149
2150
  });
2150
2151
  } catch {
2151
- logger$23.debug("dolt binary not on PATH — cannot start server");
2152
+ logger$25.debug("dolt binary not on PATH — cannot start server");
2152
2153
  return null;
2153
2154
  }
2154
- logger$23.debug("Starting dolt sql-server at %s", socketPath);
2155
+ logger$25.debug("Starting dolt sql-server at %s", socketPath);
2155
2156
  let proc$1;
2156
2157
  try {
2157
2158
  proc$1 = spawn("dolt", [
@@ -2172,26 +2173,26 @@ async function startDoltServer(projectRoot) {
2172
2173
  detached: false
2173
2174
  });
2174
2175
  } catch (err) {
2175
- logger$23.debug("Failed to spawn dolt sql-server: %s", err instanceof Error ? err.message : String(err));
2176
+ logger$25.debug("Failed to spawn dolt sql-server: %s", err instanceof Error ? err.message : String(err));
2176
2177
  return null;
2177
2178
  }
2178
2179
  let failed = false;
2179
2180
  proc$1.on("error", (err) => {
2180
- logger$23.debug("dolt sql-server error: %s", err.message);
2181
+ logger$25.debug("dolt sql-server error: %s", err.message);
2181
2182
  failed = true;
2182
2183
  });
2183
2184
  proc$1.on("exit", (code) => {
2184
- if (code !== null && code !== 0) logger$23.debug("dolt sql-server exited with code %d", code);
2185
+ if (code !== null && code !== 0) logger$25.debug("dolt sql-server exited with code %d", code);
2185
2186
  });
2186
2187
  proc$1.stderr?.on("data", (chunk) => {
2187
2188
  const line = chunk.toString().trim();
2188
- if (line) logger$23.debug("dolt-server: %s", line);
2189
+ if (line) logger$25.debug("dolt-server: %s", line);
2189
2190
  });
2190
2191
  const deadline = Date.now() + 5e3;
2191
2192
  while (Date.now() < deadline && !failed) try {
2192
2193
  await access$1(socketPath);
2193
2194
  const pid = proc$1.pid ?? 0;
2194
- logger$23.info("Auto-started dolt sql-server (pid=%d, socket=%s)", pid, socketPath);
2195
+ logger$25.info("Auto-started dolt sql-server (pid=%d, socket=%s)", pid, socketPath);
2195
2196
  let stopped = false;
2196
2197
  return {
2197
2198
  pid,
@@ -2199,14 +2200,14 @@ async function startDoltServer(projectRoot) {
2199
2200
  stop: () => {
2200
2201
  if (stopped) return;
2201
2202
  stopped = true;
2202
- logger$23.debug("Stopping dolt sql-server (pid=%d)", pid);
2203
+ logger$25.debug("Stopping dolt sql-server (pid=%d)", pid);
2203
2204
  proc$1.kill("SIGTERM");
2204
2205
  }
2205
2206
  };
2206
2207
  } catch {
2207
2208
  await new Promise((resolve$6) => setTimeout(resolve$6, 100));
2208
2209
  }
2209
- logger$23.debug("dolt sql-server did not start within 5s — killing");
2210
+ logger$25.debug("dolt sql-server did not start within 5s — killing");
2210
2211
  proc$1.kill("SIGTERM");
2211
2212
  return null;
2212
2213
  }
@@ -2276,7 +2277,7 @@ function truncateToTokens(text, maxTokens) {
2276
2277
 
2277
2278
  //#endregion
2278
2279
  //#region src/modules/context-compiler/context-compiler-impl.ts
2279
- const logger$22 = createLogger("context-compiler");
2280
+ const logger$24 = createLogger("context-compiler");
2280
2281
  /**
2281
2282
  * Fraction of the original token budget that must remain (after required +
2282
2283
  * important sections) before an optional section is included.
@@ -2337,7 +2338,7 @@ var ContextCompilerImpl = class {
2337
2338
  }
2338
2339
  _applyExclusionFilter(text, sectionName) {
2339
2340
  for (const excludedPath of this._excludedPaths) if (text.includes(excludedPath)) {
2340
- logger$22.warn({
2341
+ logger$24.warn({
2341
2342
  sectionName,
2342
2343
  excludedPath
2343
2344
  }, "ContextCompiler: section excluded — contains path from exclusion list");
@@ -2395,7 +2396,7 @@ var ContextCompilerImpl = class {
2395
2396
  includedParts.push(truncated);
2396
2397
  remainingBudget -= truncatedTokens;
2397
2398
  anyTruncated = true;
2398
- logger$22.warn({
2399
+ logger$24.warn({
2399
2400
  section: section.name,
2400
2401
  originalTokens: tokens,
2401
2402
  budgetTokens: truncatedTokens
@@ -2409,7 +2410,7 @@ var ContextCompilerImpl = class {
2409
2410
  });
2410
2411
  } else {
2411
2412
  anyTruncated = true;
2412
- logger$22.warn({
2413
+ logger$24.warn({
2413
2414
  section: section.name,
2414
2415
  tokens
2415
2416
  }, "Context compiler: omitted \"important\" section — no budget remaining");
@@ -2436,7 +2437,7 @@ var ContextCompilerImpl = class {
2436
2437
  } else {
2437
2438
  if (tokens > 0) {
2438
2439
  anyTruncated = true;
2439
- logger$22.warn({
2440
+ logger$24.warn({
2440
2441
  section: section.name,
2441
2442
  tokens,
2442
2443
  budgetFractionRemaining: budgetFractionRemaining.toFixed(2)
@@ -2530,8 +2531,8 @@ var GrammarLoader = class {
2530
2531
  _extensionMap;
2531
2532
  _cache = new Map();
2532
2533
  _unavailable = false;
2533
- constructor(logger$24) {
2534
- this._logger = logger$24;
2534
+ constructor(logger$26) {
2535
+ this._logger = logger$26;
2535
2536
  this._extensionMap = new Map([
2536
2537
  [".ts", "tree-sitter-typescript/typescript"],
2537
2538
  [".tsx", "tree-sitter-typescript/tsx"],
@@ -2568,8 +2569,8 @@ var GrammarLoader = class {
2568
2569
  throw err;
2569
2570
  }
2570
2571
  }
2571
- _loadModule(path$3) {
2572
- return __require(path$3);
2572
+ _loadModule(path$4) {
2573
+ return __require(path$4);
2573
2574
  }
2574
2575
  };
2575
2576
 
@@ -2617,9 +2618,9 @@ const ERR_REPO_MAP_GIT_FAILED = "ERR_REPO_MAP_GIT_FAILED";
2617
2618
  var SymbolParser = class {
2618
2619
  _grammarLoader;
2619
2620
  _logger;
2620
- constructor(grammarLoader, logger$24) {
2621
+ constructor(grammarLoader, logger$26) {
2621
2622
  this._grammarLoader = grammarLoader;
2622
- this._logger = logger$24;
2623
+ this._logger = logger$26;
2623
2624
  }
2624
2625
  async parseFile(filePath) {
2625
2626
  const ext$2 = extname$1(filePath);
@@ -2764,9 +2765,9 @@ async function computeFileHash(filePath) {
2764
2765
  var DoltSymbolRepository = class {
2765
2766
  _client;
2766
2767
  _logger;
2767
- constructor(client, logger$24) {
2768
+ constructor(client, logger$26) {
2768
2769
  this._client = client;
2769
- this._logger = logger$24;
2770
+ this._logger = logger$26;
2770
2771
  }
2771
2772
  /**
2772
2773
  * Atomically replace all symbols for filePath.
@@ -2972,11 +2973,11 @@ var RepoMapStorage = class {
2972
2973
  _metaRepo;
2973
2974
  _gitClient;
2974
2975
  _logger;
2975
- constructor(symbolRepo, metaRepo, gitClient, logger$24) {
2976
+ constructor(symbolRepo, metaRepo, gitClient, logger$26) {
2976
2977
  this._symbolRepo = symbolRepo;
2977
2978
  this._metaRepo = metaRepo;
2978
2979
  this._gitClient = gitClient;
2979
- this._logger = logger$24;
2980
+ this._logger = logger$26;
2980
2981
  }
2981
2982
  /**
2982
2983
  * Returns true if the file's current content hash differs from the stored hash.
@@ -3093,8 +3094,8 @@ function runGit(args, cwd) {
3093
3094
  */
3094
3095
  var GitClient = class {
3095
3096
  _logger;
3096
- constructor(logger$24) {
3097
- this._logger = logger$24;
3097
+ constructor(logger$26) {
3098
+ this._logger = logger$26;
3098
3099
  }
3099
3100
  /**
3100
3101
  * Returns the current HEAD commit SHA.
@@ -3926,12 +3927,12 @@ const qmarksTestNoExtDot$1 = ([$0]) => {
3926
3927
  };
3927
3928
  /* c8 ignore start */
3928
3929
  const defaultPlatform$3 = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
3929
- const path$2 = {
3930
+ const path$3 = {
3930
3931
  win32: { sep: "\\" },
3931
3932
  posix: { sep: "/" }
3932
3933
  };
3933
3934
  /* c8 ignore stop */
3934
- const sep$1 = defaultPlatform$3 === "win32" ? path$2.win32.sep : path$2.posix.sep;
3935
+ const sep$1 = defaultPlatform$3 === "win32" ? path$3.win32.sep : path$3.posix.sep;
3935
3936
  minimatch$1.sep = sep$1;
3936
3937
  const GLOBSTAR$1 = Symbol("globstar **");
3937
3938
  minimatch$1.GLOBSTAR = GLOBSTAR$1;
@@ -4450,9 +4451,9 @@ var RepoMapQueryEngine = class {
4450
4451
  repo;
4451
4452
  logger;
4452
4453
  telemetry;
4453
- constructor(repo, logger$24, telemetry) {
4454
+ constructor(repo, logger$26, telemetry) {
4454
4455
  this.repo = repo;
4455
- this.logger = logger$24;
4456
+ this.logger = logger$26;
4456
4457
  this.telemetry = telemetry;
4457
4458
  }
4458
4459
  async query(q) {
@@ -4672,9 +4673,9 @@ var RepoMapFormatter = class {
4672
4673
  var RepoMapTelemetry = class {
4673
4674
  _telemetry;
4674
4675
  _logger;
4675
- constructor(telemetry, logger$24) {
4676
+ constructor(telemetry, logger$26) {
4676
4677
  this._telemetry = telemetry;
4677
- this._logger = logger$24;
4678
+ this._logger = logger$26;
4678
4679
  }
4679
4680
  /**
4680
4681
  * Emit a `repo_map.query` span.
@@ -4699,9 +4700,9 @@ var RepoMapTelemetry = class {
4699
4700
  var RepoMapModule = class {
4700
4701
  _metaRepo;
4701
4702
  _logger;
4702
- constructor(metaRepo, logger$24) {
4703
+ constructor(metaRepo, logger$26) {
4703
4704
  this._metaRepo = metaRepo;
4704
- this._logger = logger$24;
4705
+ this._logger = logger$26;
4705
4706
  }
4706
4707
  /**
4707
4708
  * Check whether the stored repo-map is stale relative to the current HEAD commit.
@@ -4745,9 +4746,9 @@ var RepoMapModule = class {
4745
4746
  var RepoMapInjector = class {
4746
4747
  _queryEngine;
4747
4748
  _logger;
4748
- constructor(queryEngine, logger$24) {
4749
+ constructor(queryEngine, logger$26) {
4749
4750
  this._queryEngine = queryEngine;
4750
- this._logger = logger$24;
4751
+ this._logger = logger$26;
4751
4752
  }
4752
4753
  /**
4753
4754
  * Build repo-map context by extracting file references from the story content,
@@ -4823,12 +4824,13 @@ const DEFAULT_TIMEOUTS = {
4823
4824
  "arch-decisions": 24e4,
4824
4825
  "arch-patterns": 24e4,
4825
4826
  "story-epics": 24e4,
4826
- "story-stories": 6e5
4827
+ "story-stories": 6e5,
4828
+ "probe-author": 3e5
4827
4829
  };
4828
4830
 
4829
4831
  //#endregion
4830
4832
  //#region src/modules/agent-dispatch/dispatcher-impl.ts
4831
- const logger$21 = createLogger("agent-dispatch");
4833
+ const logger$23 = createLogger("agent-dispatch");
4832
4834
  /**
4833
4835
  * Create a new Dispatcher instance.
4834
4836
  *
@@ -4972,7 +4974,7 @@ function runBuildVerification(options) {
4972
4974
  let cmd;
4973
4975
  if (verifyCommand === void 0) {
4974
4976
  const detection = detectPackageManager(projectRoot);
4975
- logger$21.info({
4977
+ logger$23.info({
4976
4978
  packageManager: detection.packageManager,
4977
4979
  lockfile: detection.lockfile,
4978
4980
  resolvedCommand: detection.command
@@ -4984,7 +4986,7 @@ function runBuildVerification(options) {
4984
4986
  const filters = deriveTurboFilters(changedFiles, projectRoot);
4985
4987
  if (filters.length > 0) {
4986
4988
  cmd = `${cmd} ${filters.join(" ")}`;
4987
- logger$21.info({
4989
+ logger$23.info({
4988
4990
  filters,
4989
4991
  originalCmd: options.verifyCommand ?? "(auto-detected)"
4990
4992
  }, "Build verification: scoped turbo build to affected packages");
@@ -5027,7 +5029,7 @@ function runBuildVerification(options) {
5027
5029
  };
5028
5030
  const missingScriptPattern = /Missing script[:\s]|No script found|Command "build" not found/i;
5029
5031
  if (missingScriptPattern.test(combinedOutput)) {
5030
- logger$21.warn("Build script not found — skipping pre-flight (greenfield repo)");
5032
+ logger$23.warn("Build script not found — skipping pre-flight (greenfield repo)");
5031
5033
  return {
5032
5034
  status: "skipped",
5033
5035
  exitCode,
@@ -5037,7 +5039,7 @@ function runBuildVerification(options) {
5037
5039
  }
5038
5040
  const pep668Pattern = /externally-managed-environment|This environment is externally managed/i;
5039
5041
  if (pep668Pattern.test(combinedOutput)) {
5040
- logger$21.warn("PEP 668: pip blocked by externally-managed-environment — skipping pre-flight. Create a .venv to resolve.");
5042
+ logger$23.warn("PEP 668: pip blocked by externally-managed-environment — skipping pre-flight. Create a .venv to resolve.");
5041
5043
  return {
5042
5044
  status: "skipped",
5043
5045
  exitCode,
@@ -5221,7 +5223,7 @@ function pickRecommendation(distribution, profile, totalIssues, reviewCycles, la
5221
5223
 
5222
5224
  //#endregion
5223
5225
  //#region src/modules/implementation-orchestrator/project-findings.ts
5224
- const logger$20 = createLogger("project-findings");
5226
+ const logger$22 = createLogger("project-findings");
5225
5227
  /** Maximum character length for the findings summary */
5226
5228
  const MAX_CHARS = 2e3;
5227
5229
  /**
@@ -5294,7 +5296,7 @@ async function getProjectFindings(db) {
5294
5296
  if (summary.length > MAX_CHARS) summary = summary.slice(0, MAX_CHARS - 3) + "...";
5295
5297
  return summary;
5296
5298
  } catch (err) {
5297
- logger$20.warn({ err }, "Failed to query project findings (graceful fallback)");
5299
+ logger$22.warn({ err }, "Failed to query project findings (graceful fallback)");
5298
5300
  return "";
5299
5301
  }
5300
5302
  }
@@ -5317,7 +5319,7 @@ function extractRecurringPatterns(outcomes) {
5317
5319
 
5318
5320
  //#endregion
5319
5321
  //#region src/modules/compiled-workflows/prompt-assembler.ts
5320
- const logger$19 = createLogger("compiled-workflows:prompt-assembler");
5322
+ const logger$21 = createLogger("compiled-workflows:prompt-assembler");
5321
5323
  /**
5322
5324
  * Assemble a final prompt from a template and sections map.
5323
5325
  *
@@ -5342,7 +5344,7 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
5342
5344
  tokenCount,
5343
5345
  truncated: false
5344
5346
  };
5345
- logger$19.warn({
5347
+ logger$21.warn({
5346
5348
  tokenCount,
5347
5349
  ceiling: tokenCeiling
5348
5350
  }, "Prompt exceeds token ceiling — truncating optional sections");
@@ -5358,10 +5360,10 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
5358
5360
  const targetSectionTokens = Math.max(0, currentSectionTokens - overBy);
5359
5361
  if (targetSectionTokens === 0) {
5360
5362
  contentMap[section.name] = "";
5361
- logger$19.warn({ sectionName: section.name }, "Section eliminated to fit token budget");
5363
+ logger$21.warn({ sectionName: section.name }, "Section eliminated to fit token budget");
5362
5364
  } else {
5363
5365
  contentMap[section.name] = truncateToTokens(section.content, targetSectionTokens);
5364
- logger$19.warn({
5366
+ logger$21.warn({
5365
5367
  sectionName: section.name,
5366
5368
  targetSectionTokens
5367
5369
  }, "Section truncated to fit token budget");
@@ -5372,7 +5374,7 @@ function assemblePrompt(template, sections, tokenCeiling = 2200) {
5372
5374
  }
5373
5375
  if (tokenCount <= tokenCeiling) break;
5374
5376
  }
5375
- if (tokenCount > tokenCeiling) logger$19.warn({
5377
+ if (tokenCount > tokenCeiling) logger$21.warn({
5376
5378
  tokenCount,
5377
5379
  ceiling: tokenCeiling
5378
5380
  }, "Required sections alone exceed token ceiling — returning over-budget prompt");
@@ -5633,6 +5635,43 @@ const TestExpansionResultSchema = z.object({
5633
5635
  suggested_tests: z.array(SuggestedTestSchema).default([]),
5634
5636
  notes: z.string().optional()
5635
5637
  });
5638
+ /**
5639
+ * Inline mirror of RuntimeProbeSchema from @substrate-ai/sdlc.
5640
+ *
5641
+ * Inlined here instead of imported to avoid triggering Vitest's mock validation
5642
+ * error in orchestrator tests that mock @substrate-ai/sdlc without including
5643
+ * RuntimeProbeListSchema. The canonical definition lives in
5644
+ * packages/sdlc/src/verification/probes/types.ts — keep in sync when that
5645
+ * schema changes.
5646
+ */
5647
+ const InlineRuntimeProbeSchema = z.object({
5648
+ name: z.string().min(1, "probe name is required"),
5649
+ sandbox: z.enum(["host", "twin"]),
5650
+ command: z.string().min(1, "probe command is required"),
5651
+ timeout_ms: z.number().int().positive().optional(),
5652
+ description: z.string().optional(),
5653
+ expect_stdout_no_regex: z.array(z.string().min(1)).optional(),
5654
+ expect_stdout_regex: z.array(z.string().min(1)).optional()
5655
+ });
5656
+ const InlineRuntimeProbeListSchema = z.array(InlineRuntimeProbeSchema);
5657
+ /**
5658
+ * Schema for the YAML output contract of the probe-author sub-agent.
5659
+ *
5660
+ * The agent emits a yaml block containing result and probes list.
5661
+ * The probes field is validated against the RuntimeProbe shape from @substrate-ai/sdlc
5662
+ * (inlined to avoid module mock conflicts in orchestrator unit tests).
5663
+ *
5664
+ * Example:
5665
+ * result: success
5666
+ * probes:
5667
+ * - name: my-probe
5668
+ * sandbox: host
5669
+ * command: echo "hello"
5670
+ */
5671
+ const ProbeAuthorResultSchema = z.object({
5672
+ result: z.preprocess((val) => val === "failure" ? "failed" : val, z.enum(["success", "failed"])),
5673
+ probes: InlineRuntimeProbeListSchema
5674
+ });
5636
5675
 
5637
5676
  //#endregion
5638
5677
  //#region src/modules/compiled-workflows/token-ceiling.ts
@@ -5645,7 +5684,8 @@ const TOKEN_CEILING_DEFAULTS = {
5645
5684
  "dev-story": 4e5,
5646
5685
  "code-review": 5e5,
5647
5686
  "test-plan": 1e5,
5648
- "test-expansion": 2e5
5687
+ "test-expansion": 2e5,
5688
+ "probe-author": 5e4
5649
5689
  };
5650
5690
  /**
5651
5691
  * Resolve the effective token ceiling for a workflow type.
@@ -5674,7 +5714,7 @@ function getTokenCeiling(workflowType, tokenCeilings) {
5674
5714
 
5675
5715
  //#endregion
5676
5716
  //#region src/modules/compiled-workflows/create-story.ts
5677
- const logger$18 = createLogger("compiled-workflows:create-story");
5717
+ const logger$20 = createLogger("compiled-workflows:create-story");
5678
5718
  /**
5679
5719
  * Compute a hex SHA-256 of the normalized source AC section text.
5680
5720
  *
@@ -5709,13 +5749,13 @@ function hashSourceAcSection(section) {
5709
5749
  */
5710
5750
  async function runCreateStory(deps, params) {
5711
5751
  const { epicId, storyKey, pipelineRunId, source_ac_hash, priorDriftFeedback } = params;
5712
- logger$18.debug({
5752
+ logger$20.debug({
5713
5753
  epicId,
5714
5754
  storyKey,
5715
5755
  pipelineRunId
5716
5756
  }, "Starting create-story workflow");
5717
5757
  const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("create-story", deps.tokenCeilings);
5718
- logger$18.info({
5758
+ logger$20.info({
5719
5759
  workflow: "create-story",
5720
5760
  ceiling: TOKEN_CEILING,
5721
5761
  source: tokenCeilingSource
@@ -5725,7 +5765,7 @@ async function runCreateStory(deps, params) {
5725
5765
  template = await deps.pack.getPrompt("create-story");
5726
5766
  } catch (err) {
5727
5767
  const error = err instanceof Error ? err.message : String(err);
5728
- logger$18.error({ error }, "Failed to retrieve create-story prompt template");
5768
+ logger$20.error({ error }, "Failed to retrieve create-story prompt template");
5729
5769
  return {
5730
5770
  result: "failed",
5731
5771
  error: `Failed to retrieve prompt template: ${error}`,
@@ -5742,7 +5782,7 @@ async function runCreateStory(deps, params) {
5742
5782
  const storySection = extractStorySection(epicShardContent, storyKey);
5743
5783
  if (storySection !== null) {
5744
5784
  const computedHash = hashSourceAcSection(storySection);
5745
- if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$18.debug({
5785
+ if (source_ac_hash !== void 0 && source_ac_hash !== computedHash) logger$20.debug({
5746
5786
  storyKey,
5747
5787
  suppliedHash: source_ac_hash,
5748
5788
  computedHash
@@ -5757,7 +5797,7 @@ async function runCreateStory(deps, params) {
5757
5797
  const storyDef = storyDecisions.find((d) => d.category === "stories" && d.key === storyKey);
5758
5798
  if (storyDef) {
5759
5799
  storyDefinitionContent = storyDef.value;
5760
- logger$18.debug({ storyKey }, "Injected story definition from solutioning decisions");
5800
+ logger$20.debug({ storyKey }, "Injected story definition from solutioning decisions");
5761
5801
  }
5762
5802
  } catch {}
5763
5803
  const archConstraintsContent = await getArchConstraints$3(deps);
@@ -5808,7 +5848,7 @@ async function runCreateStory(deps, params) {
5808
5848
  priority: "optional"
5809
5849
  }]
5810
5850
  ], TOKEN_CEILING);
5811
- logger$18.debug({
5851
+ logger$20.debug({
5812
5852
  tokenCount,
5813
5853
  truncated,
5814
5854
  tokenCeiling: TOKEN_CEILING
@@ -5828,7 +5868,7 @@ async function runCreateStory(deps, params) {
5828
5868
  dispatchResult = await handle.result;
5829
5869
  } catch (err) {
5830
5870
  const error = err instanceof Error ? err.message : String(err);
5831
- logger$18.error({
5871
+ logger$20.error({
5832
5872
  epicId,
5833
5873
  storyKey,
5834
5874
  error
@@ -5849,7 +5889,7 @@ async function runCreateStory(deps, params) {
5849
5889
  if (dispatchResult.status === "failed") {
5850
5890
  const errorMsg = dispatchResult.parseError ?? `Dispatch failed with exit code ${dispatchResult.exitCode}`;
5851
5891
  const stderrDetail = dispatchResult.output ? ` Output: ${dispatchResult.output}` : "";
5852
- logger$18.warn({
5892
+ logger$20.warn({
5853
5893
  epicId,
5854
5894
  storyKey,
5855
5895
  exitCode: dispatchResult.exitCode,
@@ -5862,7 +5902,7 @@ async function runCreateStory(deps, params) {
5862
5902
  };
5863
5903
  }
5864
5904
  if (dispatchResult.status === "timeout") {
5865
- logger$18.warn({
5905
+ logger$20.warn({
5866
5906
  epicId,
5867
5907
  storyKey
5868
5908
  }, "Create-story dispatch timed out");
@@ -5875,7 +5915,7 @@ async function runCreateStory(deps, params) {
5875
5915
  if (dispatchResult.parsed === null) {
5876
5916
  const details = dispatchResult.parseError ?? "No YAML block found in output";
5877
5917
  const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
5878
- logger$18.warn({
5918
+ logger$20.warn({
5879
5919
  epicId,
5880
5920
  storyKey,
5881
5921
  details,
@@ -5891,7 +5931,7 @@ async function runCreateStory(deps, params) {
5891
5931
  const parseResult = CreateStoryResultSchema.safeParse(dispatchResult.parsed);
5892
5932
  if (!parseResult.success) {
5893
5933
  const details = parseResult.error.message;
5894
- logger$18.warn({
5934
+ logger$20.warn({
5895
5935
  epicId,
5896
5936
  storyKey,
5897
5937
  details
@@ -5904,7 +5944,7 @@ async function runCreateStory(deps, params) {
5904
5944
  };
5905
5945
  }
5906
5946
  const parsed = parseResult.data;
5907
- logger$18.info({
5947
+ logger$20.info({
5908
5948
  epicId,
5909
5949
  storyKey,
5910
5950
  storyFile: parsed.story_file,
@@ -5932,7 +5972,7 @@ async function getImplementationDecisions(deps, pipelineRunId) {
5932
5972
  }
5933
5973
  return await getDecisionsByPhase(deps.db, "implementation");
5934
5974
  } catch (err) {
5935
- logger$18.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve implementation decisions");
5975
+ logger$20.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve implementation decisions");
5936
5976
  return [];
5937
5977
  }
5938
5978
  }
@@ -6019,10 +6059,10 @@ function computeStoryFileFidelity(storyFileContent, namedPaths) {
6019
6059
  };
6020
6060
  const missing = [];
6021
6061
  const present = [];
6022
- for (const path$3 of namedPaths) {
6023
- const basename$2 = path$3.includes("/") ? path$3.slice(path$3.lastIndexOf("/") + 1) : path$3;
6024
- if (storyFileContent.includes(path$3) || storyFileContent.includes(basename$2)) present.push(path$3);
6025
- else missing.push(path$3);
6062
+ for (const path$4 of namedPaths) {
6063
+ const basename$2 = path$4.includes("/") ? path$4.slice(path$4.lastIndexOf("/") + 1) : path$4;
6064
+ if (storyFileContent.includes(path$4) || storyFileContent.includes(basename$2)) present.push(path$4);
6065
+ else missing.push(path$4);
6026
6066
  }
6027
6067
  return {
6028
6068
  missing,
@@ -6134,7 +6174,7 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
6134
6174
  if (storyKey) {
6135
6175
  const perStoryShard = decisions.find((d) => d.category === "epic-shard" && d.key === storyKey);
6136
6176
  if (perStoryShard?.value) {
6137
- logger$18.debug({
6177
+ logger$20.debug({
6138
6178
  epicId,
6139
6179
  storyKey
6140
6180
  }, "Found per-story epic shard (direct lookup)");
@@ -6146,13 +6186,13 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
6146
6186
  if (shardContent && storyKey) {
6147
6187
  const storySection = extractStorySection(shardContent, storyKey);
6148
6188
  if (storySection) {
6149
- logger$18.debug({
6189
+ logger$20.debug({
6150
6190
  epicId,
6151
6191
  storyKey
6152
6192
  }, "Extracted per-story section from epic shard (pre-37-0 fallback)");
6153
6193
  return storySection;
6154
6194
  }
6155
- logger$18.info({
6195
+ logger$20.info({
6156
6196
  epicId,
6157
6197
  storyKey
6158
6198
  }, "Story section absent in decisions-store shard — attempting file-based fallback before returning stale shard");
@@ -6160,11 +6200,11 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
6160
6200
  if (projectRoot) {
6161
6201
  const fallback = readEpicShardFromFile(projectRoot, epicId);
6162
6202
  if (fallback) {
6163
- logger$18.info({ epicId }, "Using file-based fallback for epic shard");
6203
+ logger$20.info({ epicId }, "Using file-based fallback for epic shard");
6164
6204
  if (storyKey) {
6165
6205
  const storySection = extractStorySection(fallback, storyKey);
6166
6206
  if (storySection) {
6167
- logger$18.debug({
6207
+ logger$20.debug({
6168
6208
  epicId,
6169
6209
  storyKey
6170
6210
  }, "Extracted per-story section from file-based epic shard");
@@ -6177,7 +6217,7 @@ function getEpicShard(decisions, epicId, projectRoot, storyKey) {
6177
6217
  if (shardContent) return shardContent;
6178
6218
  return "";
6179
6219
  } catch (err) {
6180
- logger$18.warn({
6220
+ logger$20.warn({
6181
6221
  epicId,
6182
6222
  error: err instanceof Error ? err.message : String(err)
6183
6223
  }, "Failed to retrieve epic shard");
@@ -6194,7 +6234,7 @@ function getPrevDevNotes(decisions, epicId) {
6194
6234
  if (devNotes.length === 0) return "";
6195
6235
  return devNotes[devNotes.length - 1].value;
6196
6236
  } catch (err) {
6197
- logger$18.warn({
6237
+ logger$20.warn({
6198
6238
  epicId,
6199
6239
  error: err instanceof Error ? err.message : String(err)
6200
6240
  }, "Failed to retrieve prev dev notes");
@@ -6227,7 +6267,7 @@ async function getArchConstraints$3(deps) {
6227
6267
  const truncatedBody = body.length > 300 ? body.slice(0, 297) + "..." : body;
6228
6268
  return `${header}\n${truncatedBody}`;
6229
6269
  }).join("\n\n");
6230
- logger$18.info({
6270
+ logger$20.info({
6231
6271
  fullLength: full.length,
6232
6272
  summarizedLength: summarized.length,
6233
6273
  decisions: constraints.length
@@ -6237,13 +6277,13 @@ async function getArchConstraints$3(deps) {
6237
6277
  if (deps.projectRoot) {
6238
6278
  const fallback = readArchConstraintsFromFile(deps.projectRoot);
6239
6279
  if (fallback) {
6240
- logger$18.info("Using file-based fallback for architecture constraints (decisions table empty)");
6280
+ logger$20.info("Using file-based fallback for architecture constraints (decisions table empty)");
6241
6281
  return fallback.length > ARCH_CONSTRAINT_MAX_CHARS ? fallback.slice(0, ARCH_CONSTRAINT_MAX_CHARS) + "\n\n[truncated for token budget]" : fallback;
6242
6282
  }
6243
6283
  }
6244
6284
  return "";
6245
6285
  } catch (err) {
6246
- logger$18.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
6286
+ logger$20.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
6247
6287
  return "";
6248
6288
  }
6249
6289
  }
@@ -6296,7 +6336,7 @@ function readEpicShardFromFile(projectRoot, epicId) {
6296
6336
  } catch {}
6297
6337
  return "";
6298
6338
  } catch (err) {
6299
- logger$18.warn({
6339
+ logger$20.warn({
6300
6340
  epicId,
6301
6341
  error: err instanceof Error ? err.message : String(err)
6302
6342
  }, "File-based epic shard fallback failed");
@@ -6319,7 +6359,7 @@ function readArchConstraintsFromFile(projectRoot) {
6319
6359
  const content = readFileSync(archPath, "utf-8");
6320
6360
  return content.slice(0, 1500);
6321
6361
  } catch (err) {
6322
- logger$18.warn({ error: err instanceof Error ? err.message : String(err) }, "File-based architecture fallback failed");
6362
+ logger$20.warn({ error: err instanceof Error ? err.message : String(err) }, "File-based architecture fallback failed");
6323
6363
  return "";
6324
6364
  }
6325
6365
  }
@@ -6332,7 +6372,7 @@ async function getStoryTemplate(deps) {
6332
6372
  try {
6333
6373
  return await deps.pack.getTemplate("story");
6334
6374
  } catch (err) {
6335
- logger$18.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve story template from pack");
6375
+ logger$20.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve story template from pack");
6336
6376
  return "";
6337
6377
  }
6338
6378
  }
@@ -6369,7 +6409,7 @@ async function isValidStoryFile(filePath) {
6369
6409
 
6370
6410
  //#endregion
6371
6411
  //#region src/modules/compiled-workflows/git-helpers.ts
6372
- const logger$17 = createLogger("compiled-workflows:git-helpers");
6412
+ const logger$19 = createLogger("compiled-workflows:git-helpers");
6373
6413
  /**
6374
6414
  * Check whether the repo at `cwd` has at least one commit (HEAD resolves).
6375
6415
  * Returns false for fresh repos with no commits, avoiding `fatal: bad revision 'HEAD'`.
@@ -6406,7 +6446,7 @@ function hasCommits(cwd) {
6406
6446
  */
6407
6447
  async function getGitDiffSummary(workingDirectory = process.cwd()) {
6408
6448
  if (!hasCommits(workingDirectory)) {
6409
- logger$17.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff");
6449
+ logger$19.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff");
6410
6450
  return "";
6411
6451
  }
6412
6452
  return runGitCommand(["diff", "HEAD"], workingDirectory, "git-diff-summary");
@@ -6423,7 +6463,7 @@ async function getGitDiffSummary(workingDirectory = process.cwd()) {
6423
6463
  */
6424
6464
  async function getGitDiffStatSummary(workingDirectory = process.cwd()) {
6425
6465
  if (!hasCommits(workingDirectory)) {
6426
- logger$17.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat");
6466
+ logger$19.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat");
6427
6467
  return "";
6428
6468
  }
6429
6469
  return runGitCommand([
@@ -6472,7 +6512,7 @@ async function getGitDiffStatBetweenCommits(baseCommit, endCommit = "HEAD", work
6472
6512
  async function getGitDiffForFiles(files, workingDirectory = process.cwd()) {
6473
6513
  if (files.length === 0) return "";
6474
6514
  if (!hasCommits(workingDirectory)) {
6475
- logger$17.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff for files");
6515
+ logger$19.debug({ cwd: workingDirectory }, "No commits in repo — returning empty diff for files");
6476
6516
  return "";
6477
6517
  }
6478
6518
  await stageIntentToAdd(files, workingDirectory);
@@ -6499,7 +6539,7 @@ async function getGitDiffForFiles(files, workingDirectory = process.cwd()) {
6499
6539
  async function getGitDiffStatForFiles(files, workingDirectory = process.cwd()) {
6500
6540
  if (files.length === 0) return "";
6501
6541
  if (!hasCommits(workingDirectory)) {
6502
- logger$17.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat for files");
6542
+ logger$19.debug({ cwd: workingDirectory }, "No commits in repo — returning empty stat for files");
6503
6543
  return "";
6504
6544
  }
6505
6545
  return runGitCommand([
@@ -6548,7 +6588,7 @@ async function stageIntentToAdd(files, workingDirectory) {
6548
6588
  if (files.length === 0) return;
6549
6589
  const existing = files.filter((f$1) => {
6550
6590
  const exists = existsSync(f$1);
6551
- if (!exists) logger$17.debug({ file: f$1 }, "Skipping nonexistent file in stageIntentToAdd");
6591
+ if (!exists) logger$19.debug({ file: f$1 }, "Skipping nonexistent file in stageIntentToAdd");
6552
6592
  return exists;
6553
6593
  });
6554
6594
  if (existing.length === 0) return;
@@ -6582,7 +6622,7 @@ async function runGitCommand(args, cwd, logLabel) {
6582
6622
  stderr += chunk.toString("utf-8");
6583
6623
  });
6584
6624
  proc$1.on("error", (err) => {
6585
- logger$17.warn({
6625
+ logger$19.warn({
6586
6626
  label: logLabel,
6587
6627
  cwd,
6588
6628
  error: err.message
@@ -6591,7 +6631,7 @@ async function runGitCommand(args, cwd, logLabel) {
6591
6631
  });
6592
6632
  proc$1.on("close", (code) => {
6593
6633
  if (code !== 0) {
6594
- logger$17.warn({
6634
+ logger$19.warn({
6595
6635
  label: logLabel,
6596
6636
  cwd,
6597
6637
  code,
@@ -6607,7 +6647,7 @@ async function runGitCommand(args, cwd, logLabel) {
6607
6647
 
6608
6648
  //#endregion
6609
6649
  //#region src/modules/compiled-workflows/story-complexity.ts
6610
- const logger$16 = createLogger("compiled-workflows:story-complexity");
6650
+ const logger$18 = createLogger("compiled-workflows:story-complexity");
6611
6651
  /**
6612
6652
  * Compute a complexity score from story markdown content.
6613
6653
  *
@@ -6659,7 +6699,7 @@ function resolveFixStoryMaxTurns(complexityScore) {
6659
6699
  * @param resolvedMaxTurns - Turn limit resolved for this dispatch
6660
6700
  */
6661
6701
  function logComplexityResult(storyKey, complexity, resolvedMaxTurns) {
6662
- logger$16.info({
6702
+ logger$18.info({
6663
6703
  storyKey,
6664
6704
  taskCount: complexity.taskCount,
6665
6705
  subtaskCount: complexity.subtaskCount,
@@ -6915,9 +6955,9 @@ function resolveInstallCommand(projectRoot) {
6915
6955
 
6916
6956
  //#endregion
6917
6957
  //#region src/modules/compiled-workflows/dev-story.ts
6918
- const logger$15 = createLogger("compiled-workflows:dev-story");
6958
+ const logger$17 = createLogger("compiled-workflows:dev-story");
6919
6959
  /** Default timeout for dev-story dispatches in milliseconds (30 min) */
6920
- const DEFAULT_TIMEOUT_MS$1 = 18e5;
6960
+ const DEFAULT_TIMEOUT_MS$2 = 18e5;
6921
6961
  /**
6922
6962
  * Execute the compiled dev-story workflow.
6923
6963
  *
@@ -6927,12 +6967,12 @@ const DEFAULT_TIMEOUT_MS$1 = 18e5;
6927
6967
  */
6928
6968
  async function runDevStory(deps, params) {
6929
6969
  const { storyKey, storyFilePath, taskScope, priorFiles, findingsPrompt: handlerFindingsPrompt } = params;
6930
- logger$15.info({
6970
+ logger$17.info({
6931
6971
  storyKey,
6932
6972
  storyFilePath
6933
6973
  }, "Starting compiled dev-story workflow");
6934
6974
  const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("dev-story", deps.tokenCeilings);
6935
- logger$15.info({
6975
+ logger$17.info({
6936
6976
  workflow: "dev-story",
6937
6977
  ceiling: TOKEN_CEILING,
6938
6978
  source: tokenCeilingSource
@@ -6975,10 +7015,10 @@ async function runDevStory(deps, params) {
6975
7015
  let template;
6976
7016
  try {
6977
7017
  template = await deps.pack.getPrompt("dev-story");
6978
- logger$15.debug({ storyKey }, "Retrieved dev-story prompt template from pack");
7018
+ logger$17.debug({ storyKey }, "Retrieved dev-story prompt template from pack");
6979
7019
  } catch (err) {
6980
7020
  const error = err instanceof Error ? err.message : String(err);
6981
- logger$15.error({
7021
+ logger$17.error({
6982
7022
  storyKey,
6983
7023
  error
6984
7024
  }, "Failed to retrieve dev-story prompt template");
@@ -6989,14 +7029,14 @@ async function runDevStory(deps, params) {
6989
7029
  storyContent = await readFile$1(storyFilePath, "utf-8");
6990
7030
  } catch (err) {
6991
7031
  if (err.code === "ENOENT") {
6992
- logger$15.error({
7032
+ logger$17.error({
6993
7033
  storyKey,
6994
7034
  storyFilePath
6995
7035
  }, "Story file not found");
6996
7036
  return makeFailureResult("story_file_not_found");
6997
7037
  }
6998
7038
  const error = err instanceof Error ? err.message : String(err);
6999
- logger$15.error({
7039
+ logger$17.error({
7000
7040
  storyKey,
7001
7041
  storyFilePath,
7002
7042
  error
@@ -7004,7 +7044,7 @@ async function runDevStory(deps, params) {
7004
7044
  return makeFailureResult(`story_file_read_error: ${error}`);
7005
7045
  }
7006
7046
  if (storyContent.trim().length === 0) {
7007
- logger$15.error({
7047
+ logger$17.error({
7008
7048
  storyKey,
7009
7049
  storyFilePath
7010
7050
  }, "Story file is empty");
@@ -7012,7 +7052,7 @@ async function runDevStory(deps, params) {
7012
7052
  }
7013
7053
  const staleStatus = detectDeprecatedStatusField(storyContent);
7014
7054
  if (staleStatus !== null) {
7015
- logger$15.warn({
7055
+ logger$17.warn({
7016
7056
  storyFilePath,
7017
7057
  staleStatus
7018
7058
  }, "Story spec contains deprecated Status field — stripped before dispatch (status is managed by Dolt work graph)");
@@ -7027,17 +7067,17 @@ async function runDevStory(deps, params) {
7027
7067
  const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
7028
7068
  if (testPatternDecisions.length > 0) {
7029
7069
  testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
7030
- logger$15.debug({
7070
+ logger$17.debug({
7031
7071
  storyKey,
7032
7072
  count: testPatternDecisions.length
7033
7073
  }, "Loaded test patterns from decision store");
7034
7074
  } else {
7035
7075
  testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
7036
- logger$15.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
7076
+ logger$17.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
7037
7077
  }
7038
7078
  } catch (err) {
7039
7079
  const error = err instanceof Error ? err.message : String(err);
7040
- logger$15.warn({
7080
+ logger$17.warn({
7041
7081
  storyKey,
7042
7082
  error
7043
7083
  }, "Failed to load test patterns — using defaults");
@@ -7051,7 +7091,7 @@ async function runDevStory(deps, params) {
7051
7091
  if (deps.repoMapInjector !== void 0) {
7052
7092
  const injection = await deps.repoMapInjector.buildContext(storyContent, deps.maxRepoMapTokens ?? 2e3);
7053
7093
  repoContextContent = injection.text;
7054
- logger$15.info({
7094
+ logger$17.info({
7055
7095
  storyKey,
7056
7096
  repoMapTokens: Math.ceil(injection.text.length / 4),
7057
7097
  symbolCount: injection.symbolCount,
@@ -7061,7 +7101,7 @@ async function runDevStory(deps, params) {
7061
7101
  let priorFindingsContent = "";
7062
7102
  if (handlerFindingsPrompt !== void 0 && handlerFindingsPrompt.length > 0) {
7063
7103
  priorFindingsContent = handlerFindingsPrompt;
7064
- logger$15.debug({
7104
+ logger$17.debug({
7065
7105
  storyKey,
7066
7106
  findingsLen: handlerFindingsPrompt.length
7067
7107
  }, "Using pre-computed findings from handler (Story 53-8 AC2)");
@@ -7073,7 +7113,7 @@ async function runDevStory(deps, params) {
7073
7113
  });
7074
7114
  if (findings.length > 0) {
7075
7115
  priorFindingsContent = findings;
7076
- logger$15.debug({
7116
+ logger$17.debug({
7077
7117
  storyKey,
7078
7118
  findingsLen: findings.length
7079
7119
  }, "Injecting relevance-scored findings into dev-story prompt");
@@ -7093,7 +7133,7 @@ async function runDevStory(deps, params) {
7093
7133
  if (plan.test_categories && plan.test_categories.length > 0) parts.push(`\n### Categories: ${plan.test_categories.join(", ")}`);
7094
7134
  if (plan.coverage_notes) parts.push(`\n### Coverage Notes\n${plan.coverage_notes}`);
7095
7135
  testPlanContent = parts.join("\n");
7096
- logger$15.debug({ storyKey }, "Injecting test plan into dev-story prompt");
7136
+ logger$17.debug({ storyKey }, "Injecting test plan into dev-story prompt");
7097
7137
  }
7098
7138
  } catch {}
7099
7139
  const sections = [
@@ -7154,7 +7194,7 @@ async function runDevStory(deps, params) {
7154
7194
  }
7155
7195
  ];
7156
7196
  const { prompt, tokenCount, truncated } = assemblePrompt(template, sections, TOKEN_CEILING);
7157
- logger$15.info({
7197
+ logger$17.info({
7158
7198
  storyKey,
7159
7199
  tokenCount,
7160
7200
  ceiling: TOKEN_CEILING,
@@ -7166,7 +7206,7 @@ async function runDevStory(deps, params) {
7166
7206
  prompt,
7167
7207
  agent: deps.agentId ?? "claude-code",
7168
7208
  taskType: "dev-story",
7169
- timeout: DEFAULT_TIMEOUT_MS$1,
7209
+ timeout: DEFAULT_TIMEOUT_MS$2,
7170
7210
  outputSchema: DevStoryResultSchema,
7171
7211
  maxTurns: resolvedMaxTurns,
7172
7212
  ...deps.projectRoot !== void 0 ? { workingDirectory: deps.projectRoot } : {},
@@ -7178,7 +7218,7 @@ async function runDevStory(deps, params) {
7178
7218
  dispatchResult = await handle.result;
7179
7219
  } catch (err) {
7180
7220
  const error = err instanceof Error ? err.message : String(err);
7181
- logger$15.error({
7221
+ logger$17.error({
7182
7222
  storyKey,
7183
7223
  error
7184
7224
  }, "Dispatch threw an unexpected error");
@@ -7189,11 +7229,11 @@ async function runDevStory(deps, params) {
7189
7229
  output: dispatchResult.tokenEstimate.output
7190
7230
  };
7191
7231
  if (dispatchResult.status === "timeout") {
7192
- logger$15.error({
7232
+ logger$17.error({
7193
7233
  storyKey,
7194
7234
  durationMs: dispatchResult.durationMs
7195
7235
  }, "Dev-story dispatch timed out");
7196
- if (dispatchResult.output.length > 0) logger$15.info({
7236
+ if (dispatchResult.output.length > 0) logger$17.info({
7197
7237
  storyKey,
7198
7238
  partialOutput: dispatchResult.output.slice(0, 500)
7199
7239
  }, "Partial output before timeout");
@@ -7203,12 +7243,12 @@ async function runDevStory(deps, params) {
7203
7243
  };
7204
7244
  }
7205
7245
  if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
7206
- logger$15.error({
7246
+ logger$17.error({
7207
7247
  storyKey,
7208
7248
  exitCode: dispatchResult.exitCode,
7209
7249
  status: dispatchResult.status
7210
7250
  }, "Dev-story dispatch failed");
7211
- if (dispatchResult.output.length > 0) logger$15.info({
7251
+ if (dispatchResult.output.length > 0) logger$17.info({
7212
7252
  storyKey,
7213
7253
  partialOutput: dispatchResult.output.slice(0, 500)
7214
7254
  }, "Partial output from failed dispatch");
@@ -7220,7 +7260,7 @@ async function runDevStory(deps, params) {
7220
7260
  if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
7221
7261
  const details = dispatchResult.parseError ?? "parsed result was null";
7222
7262
  const rawSnippet = dispatchResult.output ? dispatchResult.output.slice(0, 1e3) : "(empty)";
7223
- logger$15.error({
7263
+ logger$17.error({
7224
7264
  storyKey,
7225
7265
  parseError: details,
7226
7266
  rawOutputSnippet: rawSnippet
@@ -7228,12 +7268,12 @@ async function runDevStory(deps, params) {
7228
7268
  let filesModified = [];
7229
7269
  try {
7230
7270
  filesModified = await getGitChangedFiles(deps.projectRoot ?? process.cwd());
7231
- if (filesModified.length > 0) logger$15.info({
7271
+ if (filesModified.length > 0) logger$17.info({
7232
7272
  storyKey,
7233
7273
  fileCount: filesModified.length
7234
7274
  }, "Recovered files_modified from git status (YAML fallback)");
7235
7275
  } catch (err) {
7236
- logger$15.warn({
7276
+ logger$17.warn({
7237
7277
  storyKey,
7238
7278
  error: err instanceof Error ? err.message : String(err)
7239
7279
  }, "Failed to recover files_modified from git");
@@ -7250,7 +7290,7 @@ async function runDevStory(deps, params) {
7250
7290
  };
7251
7291
  }
7252
7292
  const parsed = dispatchResult.parsed;
7253
- logger$15.info({
7293
+ logger$17.info({
7254
7294
  storyKey,
7255
7295
  result: parsed.result,
7256
7296
  acMet: parsed.ac_met.length
@@ -7366,7 +7406,7 @@ function extractReferencedFiles(storyContent) {
7366
7406
  const matches = storyContent.match(filePathRegex) ?? [];
7367
7407
  const freq = new Map();
7368
7408
  for (const m of matches) freq.set(m, (freq.get(m) ?? 0) + 1);
7369
- const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([path$3]) => path$3);
7409
+ const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([path$4]) => path$4);
7370
7410
  return sorted.filter((p) => !p.includes(".test."));
7371
7411
  }
7372
7412
  function extractFilesInScope(storyContent) {
@@ -7390,19 +7430,6 @@ function extractFilesInScope(storyContent) {
7390
7430
  //#endregion
7391
7431
  //#region src/modules/compiled-workflows/scope-guardrail.ts
7392
7432
  /**
7393
- * ScopeGuardrail — utility for detecting out-of-scope file modifications in code review.
7394
- *
7395
- * Parses the expected file set from a story spec and compares it against the
7396
- * actual files modified by the dev agent. Returns a pre-computed scope analysis
7397
- * markdown string that can be injected into the code-review prompt so the LLM
7398
- * reviewer does not need to re-parse the spec sections manually.
7399
- *
7400
- * Architecture constraints:
7401
- * - Pure utility: no imports from packages/sdlc/, packages/core/, or persistence layer
7402
- * - Takes plain strings in, returns plain strings out
7403
- * - Test-file exemption patterns must match countTestMetrics() in code-review.ts
7404
- */
7405
- /**
7406
7433
  * File extensions that qualify a token as a "path-like" string in task bullets.
7407
7434
  * Any token containing `/` and one of these extensions is treated as a file path.
7408
7435
  */
@@ -7495,13 +7522,17 @@ var ScopeGuardrail = class ScopeGuardrail {
7495
7522
  *
7496
7523
  * @param storyContent - Raw story spec markdown text
7497
7524
  * @param filesModified - List of file paths from the git diff
7525
+ * @param fileDiffs - Optional per-file diff map. When provided, transitive
7526
+ * re-exports (Story 61-5) whose `from` source IS in
7527
+ * expectedFiles are excluded from the out-of-scope set.
7498
7528
  * @returns Markdown string listing expected/actual/delta file sets,
7499
7529
  * or empty string if no violations found
7500
7530
  */
7501
- static buildAnalysis(storyContent, filesModified) {
7531
+ static buildAnalysis(storyContent, filesModified, fileDiffs) {
7502
7532
  const expectedFiles = ScopeGuardrail.parseExpectedFiles(storyContent);
7503
7533
  const nonTestFiles = filesModified.filter((f$1) => !isTestFile(f$1));
7504
- const outOfScope = nonTestFiles.filter((f$1) => !expectedFiles.has(f$1));
7534
+ let outOfScope = nonTestFiles.filter((f$1) => !expectedFiles.has(f$1));
7535
+ if (fileDiffs !== void 0) outOfScope = outOfScope.filter((filePath) => !isPureTransitiveReExport(filePath, fileDiffs.get(filePath), expectedFiles));
7505
7536
  if (outOfScope.length === 0) return "";
7506
7537
  const expectedList = expectedFiles.size > 0 ? Array.from(expectedFiles).map((f$1) => ` - ${f$1}`).join("\n") : " (none specified)";
7507
7538
  const actualList = nonTestFiles.length > 0 ? nonTestFiles.map((f$1) => ` - ${f$1}`).join("\n") : " (none)";
@@ -7571,10 +7602,108 @@ function isFilePath(candidate) {
7571
7602
  if (/\s/.test(candidate)) return false;
7572
7603
  return RECOGNIZED_EXTENSIONS.some((ext$2) => candidate.endsWith(ext$2));
7573
7604
  }
7605
+ /**
7606
+ * Split a combined `git diff` output into per-file diff sections, keyed by
7607
+ * the post-image (`b/`) path. Returns an empty map if the input is empty.
7608
+ *
7609
+ * Used by callers that need to feed per-file diffs into
7610
+ * `ScopeGuardrail.buildAnalysis` for transitive re-export detection.
7611
+ */
7612
+ function parseDiffByFile(combinedDiff) {
7613
+ const result = new Map();
7614
+ if (combinedDiff.trim() === "") return result;
7615
+ let currentPath = null;
7616
+ let currentLines = [];
7617
+ for (const line of combinedDiff.split("\n")) {
7618
+ const headerMatch = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
7619
+ if (headerMatch !== null) {
7620
+ if (currentPath !== null) result.set(currentPath, currentLines.join("\n"));
7621
+ currentPath = headerMatch[2] ?? null;
7622
+ currentLines = [line];
7623
+ continue;
7624
+ }
7625
+ if (currentPath !== null) currentLines.push(line);
7626
+ }
7627
+ if (currentPath !== null) result.set(currentPath, currentLines.join("\n"));
7628
+ return result;
7629
+ }
7630
+ /**
7631
+ * Single-line re-export pattern. Matches:
7632
+ * export { Foo } from './bar.js'
7633
+ * export { Foo, Bar as Baz } from './bar'
7634
+ * export type { Foo } from './bar.js'
7635
+ * export { type Foo, Bar } from './bar.js'
7636
+ *
7637
+ * Captures the relative `from` path (group 1). Path must start with `./`
7638
+ * (downward re-exports only — the canonical pattern is package barrel files
7639
+ * re-exporting submodule symbols). `../` paths are not tolerated; those
7640
+ * suggest cross-package coupling that warrants real review.
7641
+ */
7642
+ const REEXPORT_LINE_RE = /^\s*export\s+(?:type\s+)?\{[^}]+\}\s+from\s+['"](\.\/[^'"]+)['"]\s*;?\s*$/;
7643
+ /**
7644
+ * Returns true if `diffContent` represents a pure transitive re-export
7645
+ * change for `modifiedFilePath` — meaning every added/removed line is a
7646
+ * re-export whose `from` source resolves to a file in `expectedFiles`.
7647
+ *
7648
+ * Story 61-5: surfaced by 60-13 dispatch where dev added a 2-line re-export
7649
+ * of `detectsEventDrivenAC` to `verification/index.ts` (an `index.ts`
7650
+ * re-export hop required for cross-package access via `@substrate-ai/sdlc`).
7651
+ * scope-guardrail flagged it as out-of-scope, reviewer admitted "the change
7652
+ * is clearly required" but flagged anyway, story timed out → escalated.
7653
+ *
7654
+ * Returns false when:
7655
+ * - diff content unavailable
7656
+ * - any non-re-export, non-comment, non-blank change exists
7657
+ * - any re-export's resolved `from` source is NOT in expectedFiles
7658
+ * - diff is empty (no changes — preserve existing behavior)
7659
+ */
7660
+ function isPureTransitiveReExport(modifiedFilePath, diffContent, expectedFiles) {
7661
+ if (diffContent === void 0 || diffContent.trim() === "") return false;
7662
+ let sawChange = false;
7663
+ for (const line of diffContent.split("\n")) {
7664
+ if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@") || line.startsWith("diff ") || line.startsWith("index ") || line.startsWith("similarity ") || line.startsWith("rename ") || line.startsWith("new file ") || line.startsWith("deleted file ") || line.startsWith("Binary ") || line.startsWith("\\ No newline")) continue;
7665
+ if (!line.startsWith("+") && !line.startsWith("-")) continue;
7666
+ const content = line.slice(1);
7667
+ const trimmed = content.trim();
7668
+ if (trimmed === "") continue;
7669
+ if (trimmed.startsWith("//")) continue;
7670
+ sawChange = true;
7671
+ const match$2 = trimmed.match(REEXPORT_LINE_RE);
7672
+ if (match$2 === null) return false;
7673
+ const fromPath = match$2[1] ?? "";
7674
+ if (!resolvesIntoExpected(modifiedFilePath, fromPath, expectedFiles)) return false;
7675
+ }
7676
+ return sawChange;
7677
+ }
7678
+ /**
7679
+ * Resolve a `from './x.js'` path relative to `modifiedFilePath`'s directory
7680
+ * and check if the resolved path (or its `.ts` sibling) is in `expectedFiles`.
7681
+ *
7682
+ * ESM convention: source files are `.ts`, but imports use `.js` extensions.
7683
+ * We accept either extension when matching against expectedFiles.
7684
+ */
7685
+ function resolvesIntoExpected(modifiedFilePath, relativePath, expectedFiles) {
7686
+ const dir = path$2.posix.dirname(modifiedFilePath);
7687
+ const resolved = path$2.posix.normalize(path$2.posix.join(dir, relativePath));
7688
+ const candidates = new Set([resolved]);
7689
+ if (resolved.endsWith(".js")) {
7690
+ candidates.add(resolved.slice(0, -3) + ".ts");
7691
+ candidates.add(resolved.slice(0, -3) + ".tsx");
7692
+ }
7693
+ if (resolved.endsWith(".ts")) candidates.add(resolved.slice(0, -3) + ".js");
7694
+ if (!/\.(t|j)sx?$/.test(resolved)) {
7695
+ candidates.add(resolved + ".ts");
7696
+ candidates.add(resolved + ".tsx");
7697
+ candidates.add(resolved + ".js");
7698
+ candidates.add(resolved + "/index.ts");
7699
+ }
7700
+ for (const candidate of candidates) if (expectedFiles.has(candidate)) return true;
7701
+ return false;
7702
+ }
7574
7703
 
7575
7704
  //#endregion
7576
7705
  //#region src/modules/compiled-workflows/code-review.ts
7577
- const logger$14 = createLogger("compiled-workflows:code-review");
7706
+ const logger$16 = createLogger("compiled-workflows:code-review");
7578
7707
  /**
7579
7708
  * Default fallback result when dispatch fails or times out.
7580
7709
  * Uses NEEDS_MINOR_FIXES (not NEEDS_MAJOR_REWORK) so a parse/schema failure
@@ -7649,14 +7778,14 @@ async function countTestMetrics(filesModified, cwd) {
7649
7778
  async function runCodeReview(deps, params) {
7650
7779
  const { storyKey, storyFilePath, workingDirectory, pipelineRunId, filesModified, previousIssues, buildPassed, baselineCommit } = params;
7651
7780
  const cwd = workingDirectory ?? process.cwd();
7652
- logger$14.debug({
7781
+ logger$16.debug({
7653
7782
  storyKey,
7654
7783
  storyFilePath,
7655
7784
  cwd,
7656
7785
  pipelineRunId
7657
7786
  }, "Starting code-review workflow");
7658
7787
  const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("code-review", deps.tokenCeilings);
7659
- logger$14.info({
7788
+ logger$16.info({
7660
7789
  workflow: "code-review",
7661
7790
  ceiling: TOKEN_CEILING,
7662
7791
  source: tokenCeilingSource
@@ -7666,7 +7795,7 @@ async function runCodeReview(deps, params) {
7666
7795
  template = await deps.pack.getPrompt("code-review");
7667
7796
  } catch (err) {
7668
7797
  const error = err instanceof Error ? err.message : String(err);
7669
- logger$14.error({ error }, "Failed to retrieve code-review prompt template");
7798
+ logger$16.error({ error }, "Failed to retrieve code-review prompt template");
7670
7799
  return defaultFailResult(`Failed to retrieve prompt template: ${error}`, {
7671
7800
  input: 0,
7672
7801
  output: 0
@@ -7677,7 +7806,7 @@ async function runCodeReview(deps, params) {
7677
7806
  storyContent = await readFile$1(storyFilePath, "utf-8");
7678
7807
  } catch (err) {
7679
7808
  const error = err instanceof Error ? err.message : String(err);
7680
- logger$14.error({
7809
+ logger$16.error({
7681
7810
  storyFilePath,
7682
7811
  error
7683
7812
  }, "Failed to read story file");
@@ -7697,12 +7826,12 @@ async function runCodeReview(deps, params) {
7697
7826
  const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
7698
7827
  if (scopedTotal <= TOKEN_CEILING) {
7699
7828
  gitDiffContent = scopedDiff;
7700
- logger$14.debug({
7829
+ logger$16.debug({
7701
7830
  fileCount: filesModified.length,
7702
7831
  tokenCount: scopedTotal
7703
7832
  }, "Using scoped file diff");
7704
7833
  } else {
7705
- logger$14.warn({
7834
+ logger$16.warn({
7706
7835
  estimatedTotal: scopedTotal,
7707
7836
  ceiling: TOKEN_CEILING,
7708
7837
  fileCount: filesModified.length
@@ -7716,7 +7845,7 @@ async function runCodeReview(deps, params) {
7716
7845
  const fullTotal = nonDiffTokens + countTokens(fullDiff);
7717
7846
  if (fullTotal <= TOKEN_CEILING) gitDiffContent = fullDiff;
7718
7847
  else {
7719
- logger$14.warn({
7848
+ logger$16.warn({
7720
7849
  estimatedTotal: fullTotal,
7721
7850
  ceiling: TOKEN_CEILING
7722
7851
  }, "Full git diff would exceed token ceiling — using stat-only summary");
@@ -7724,7 +7853,7 @@ async function runCodeReview(deps, params) {
7724
7853
  }
7725
7854
  }
7726
7855
  if (gitDiffContent.trim().length === 0 && baselineCommit) {
7727
- logger$14.info({
7856
+ logger$16.info({
7728
7857
  storyKey,
7729
7858
  baselineCommit
7730
7859
  }, "Working tree diff empty — diffing against baseline commit");
@@ -7732,7 +7861,7 @@ async function runCodeReview(deps, params) {
7732
7861
  const commitTotal = nonDiffTokens + countTokens(commitDiff);
7733
7862
  if (commitDiff.trim().length > 0) if (commitTotal <= TOKEN_CEILING) gitDiffContent = commitDiff;
7734
7863
  else {
7735
- logger$14.warn({
7864
+ logger$16.warn({
7736
7865
  estimatedTotal: commitTotal,
7737
7866
  ceiling: TOKEN_CEILING
7738
7867
  }, "Baseline..HEAD diff exceeds token ceiling — using stat-only summary");
@@ -7740,7 +7869,7 @@ async function runCodeReview(deps, params) {
7740
7869
  }
7741
7870
  }
7742
7871
  if (gitDiffContent.trim().length === 0) {
7743
- logger$14.info({ storyKey }, "Empty git diff — skipping review with SHIP_IT");
7872
+ logger$16.info({ storyKey }, "Empty git diff — skipping review with SHIP_IT");
7744
7873
  return {
7745
7874
  verdict: "SHIP_IT",
7746
7875
  issues: 0,
@@ -7756,7 +7885,7 @@ async function runCodeReview(deps, params) {
7756
7885
  if (deps.repoMapInjector !== void 0) {
7757
7886
  const injection = await deps.repoMapInjector.buildContext(storyContent, deps.maxRepoMapTokens ?? 2e3);
7758
7887
  repoContextContent = injection.text;
7759
- logger$14.info({
7888
+ logger$16.info({
7760
7889
  storyKey,
7761
7890
  repoMapTokens: Math.ceil(injection.text.length / 4),
7762
7891
  symbolCount: injection.symbolCount,
@@ -7776,16 +7905,17 @@ async function runCodeReview(deps, params) {
7776
7905
  const findings = await getProjectFindings(deps.db);
7777
7906
  if (findings.length > 0) {
7778
7907
  priorFindingsContent = "Previous reviews found these recurring patterns — pay special attention:\n\n" + findings;
7779
- logger$14.debug({
7908
+ logger$16.debug({
7780
7909
  storyKey,
7781
7910
  findingsLen: findings.length
7782
7911
  }, "Injecting prior findings into code-review prompt");
7783
7912
  }
7784
7913
  } catch {}
7785
7914
  const testMetricsContent = await countTestMetrics(filesModified, cwd);
7786
- if (testMetricsContent) logger$14.debug({ storyKey }, "Injecting verified test-count metrics into code-review context");
7787
- const scopeAnalysisContent = storyContent && filesModified ? ScopeGuardrail.buildAnalysis(storyContent, filesModified) : "";
7788
- if (scopeAnalysisContent) logger$14.debug({ storyKey }, "Scope analysis detected out-of-scope files");
7915
+ if (testMetricsContent) logger$16.debug({ storyKey }, "Injecting verified test-count metrics into code-review context");
7916
+ const fileDiffs = gitDiffContent ? parseDiffByFile(gitDiffContent) : void 0;
7917
+ const scopeAnalysisContent = storyContent && filesModified ? ScopeGuardrail.buildAnalysis(storyContent, filesModified, fileDiffs) : "";
7918
+ if (scopeAnalysisContent) logger$16.debug({ storyKey }, "Scope analysis detected out-of-scope files");
7789
7919
  const buildStatusPrefix = buildPassed === true ? "BUILD STATUS: PASSED — code compiles and passes build verification. Focus on logic correctness, style, and acceptance criteria rather than compilation errors.\n\n" : "";
7790
7920
  const sections = [
7791
7921
  {
@@ -7830,11 +7960,11 @@ async function runCodeReview(deps, params) {
7830
7960
  }
7831
7961
  ];
7832
7962
  const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
7833
- if (assembleResult.truncated) logger$14.warn({
7963
+ if (assembleResult.truncated) logger$16.warn({
7834
7964
  storyKey,
7835
7965
  tokenCount: assembleResult.tokenCount
7836
7966
  }, "Code-review prompt truncated to fit token ceiling");
7837
- logger$14.debug({
7967
+ logger$16.debug({
7838
7968
  storyKey,
7839
7969
  tokenCount: assembleResult.tokenCount,
7840
7970
  truncated: assembleResult.truncated
@@ -7855,7 +7985,7 @@ async function runCodeReview(deps, params) {
7855
7985
  dispatchResult = await handle.result;
7856
7986
  } catch (err) {
7857
7987
  const error = err instanceof Error ? err.message : String(err);
7858
- logger$14.error({
7988
+ logger$16.error({
7859
7989
  storyKey,
7860
7990
  error
7861
7991
  }, "Code-review dispatch threw unexpected error");
@@ -7871,7 +8001,7 @@ async function runCodeReview(deps, params) {
7871
8001
  const rawOutput = dispatchResult.output ?? void 0;
7872
8002
  if (dispatchResult.status === "failed") {
7873
8003
  const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""} ${dispatchResult.output ? `Stderr: ${dispatchResult.output}` : ""}`.trim();
7874
- logger$14.warn({
8004
+ logger$16.warn({
7875
8005
  storyKey,
7876
8006
  exitCode: dispatchResult.exitCode
7877
8007
  }, "Code-review dispatch failed");
@@ -7881,7 +8011,7 @@ async function runCodeReview(deps, params) {
7881
8011
  };
7882
8012
  }
7883
8013
  if (dispatchResult.status === "timeout") {
7884
- logger$14.warn({ storyKey }, "Code-review dispatch timed out");
8014
+ logger$16.warn({ storyKey }, "Code-review dispatch timed out");
7885
8015
  return {
7886
8016
  ...defaultFailResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage),
7887
8017
  rawOutput
@@ -7889,7 +8019,7 @@ async function runCodeReview(deps, params) {
7889
8019
  }
7890
8020
  if (dispatchResult.parsed === null) {
7891
8021
  const details = dispatchResult.parseError ?? "No YAML block found in output";
7892
- logger$14.warn({
8022
+ logger$16.warn({
7893
8023
  storyKey,
7894
8024
  details
7895
8025
  }, "Code-review output schema validation failed");
@@ -7907,7 +8037,7 @@ async function runCodeReview(deps, params) {
7907
8037
  const parseResult = CodeReviewResultSchema.safeParse(dispatchResult.parsed);
7908
8038
  if (!parseResult.success) {
7909
8039
  const details = parseResult.error.message;
7910
- logger$14.warn({
8040
+ logger$16.warn({
7911
8041
  storyKey,
7912
8042
  details
7913
8043
  }, "Code-review output failed schema validation");
@@ -7923,13 +8053,13 @@ async function runCodeReview(deps, params) {
7923
8053
  };
7924
8054
  }
7925
8055
  const parsed = parseResult.data;
7926
- if (parsed.agentVerdict !== parsed.verdict) logger$14.info({
8056
+ if (parsed.agentVerdict !== parsed.verdict) logger$16.info({
7927
8057
  storyKey,
7928
8058
  agentVerdict: parsed.agentVerdict,
7929
8059
  pipelineVerdict: parsed.verdict,
7930
8060
  issues: parsed.issues
7931
8061
  }, "Pipeline overrode agent verdict based on issue severities");
7932
- logger$14.info({
8062
+ logger$16.info({
7933
8063
  storyKey,
7934
8064
  verdict: parsed.verdict,
7935
8065
  issues: parsed.issues
@@ -7954,16 +8084,16 @@ async function getArchConstraints$2(deps) {
7954
8084
  if (constraints.length === 0) return "";
7955
8085
  return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
7956
8086
  } catch (err) {
7957
- logger$14.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
8087
+ logger$16.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
7958
8088
  return "";
7959
8089
  }
7960
8090
  }
7961
8091
 
7962
8092
  //#endregion
7963
8093
  //#region src/modules/compiled-workflows/test-plan.ts
7964
- const logger$13 = createLogger("compiled-workflows:test-plan");
8094
+ const logger$15 = createLogger("compiled-workflows:test-plan");
7965
8095
  /** Default timeout for test-plan dispatches in milliseconds (5 min — lightweight call) */
7966
- const DEFAULT_TIMEOUT_MS = 3e5;
8096
+ const DEFAULT_TIMEOUT_MS$1 = 3e5;
7967
8097
  /**
7968
8098
  * Execute the compiled test-plan workflow.
7969
8099
  *
@@ -7973,12 +8103,12 @@ const DEFAULT_TIMEOUT_MS = 3e5;
7973
8103
  */
7974
8104
  async function runTestPlan(deps, params) {
7975
8105
  const { storyKey, storyFilePath, pipelineRunId } = params;
7976
- logger$13.info({
8106
+ logger$15.info({
7977
8107
  storyKey,
7978
8108
  storyFilePath
7979
8109
  }, "Starting compiled test-plan workflow");
7980
8110
  const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("test-plan", deps.tokenCeilings);
7981
- logger$13.info({
8111
+ logger$15.info({
7982
8112
  workflow: "test-plan",
7983
8113
  ceiling: TOKEN_CEILING,
7984
8114
  source: tokenCeilingSource
@@ -7986,10 +8116,10 @@ async function runTestPlan(deps, params) {
7986
8116
  let template;
7987
8117
  try {
7988
8118
  template = await deps.pack.getPrompt("test-plan");
7989
- logger$13.debug({ storyKey }, "Retrieved test-plan prompt template from pack");
8119
+ logger$15.debug({ storyKey }, "Retrieved test-plan prompt template from pack");
7990
8120
  } catch (err) {
7991
8121
  const error = err instanceof Error ? err.message : String(err);
7992
- logger$13.warn({
8122
+ logger$15.warn({
7993
8123
  storyKey,
7994
8124
  error
7995
8125
  }, "Failed to retrieve test-plan prompt template");
@@ -8000,14 +8130,14 @@ async function runTestPlan(deps, params) {
8000
8130
  storyContent = await readFile$1(storyFilePath, "utf-8");
8001
8131
  } catch (err) {
8002
8132
  if (err.code === "ENOENT") {
8003
- logger$13.warn({
8133
+ logger$15.warn({
8004
8134
  storyKey,
8005
8135
  storyFilePath
8006
8136
  }, "Story file not found for test planning");
8007
8137
  return makeTestPlanFailureResult("story_file_not_found");
8008
8138
  }
8009
8139
  const error = err instanceof Error ? err.message : String(err);
8010
- logger$13.warn({
8140
+ logger$15.warn({
8011
8141
  storyKey,
8012
8142
  storyFilePath,
8013
8143
  error
@@ -8021,13 +8151,13 @@ async function runTestPlan(deps, params) {
8021
8151
  const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
8022
8152
  if (testPatternDecisions.length > 0) {
8023
8153
  testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
8024
- logger$13.debug({
8154
+ logger$15.debug({
8025
8155
  storyKey,
8026
8156
  count: testPatternDecisions.length
8027
8157
  }, "Loaded test patterns from decision store");
8028
8158
  } else {
8029
8159
  testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
8030
- logger$13.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
8160
+ logger$15.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
8031
8161
  }
8032
8162
  } catch {
8033
8163
  testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
@@ -8049,7 +8179,7 @@ async function runTestPlan(deps, params) {
8049
8179
  priority: "optional"
8050
8180
  }
8051
8181
  ], TOKEN_CEILING);
8052
- logger$13.info({
8182
+ logger$15.info({
8053
8183
  storyKey,
8054
8184
  tokenCount,
8055
8185
  ceiling: TOKEN_CEILING,
@@ -8061,7 +8191,7 @@ async function runTestPlan(deps, params) {
8061
8191
  prompt,
8062
8192
  agent: deps.agentId ?? "claude-code",
8063
8193
  taskType: "test-plan",
8064
- timeout: DEFAULT_TIMEOUT_MS,
8194
+ timeout: DEFAULT_TIMEOUT_MS$1,
8065
8195
  outputSchema: TestPlanResultSchema,
8066
8196
  ...deps.projectRoot !== void 0 ? { workingDirectory: deps.projectRoot } : {},
8067
8197
  ...deps.otlpEndpoint !== void 0 ? { otlpEndpoint: deps.otlpEndpoint } : {},
@@ -8070,7 +8200,7 @@ async function runTestPlan(deps, params) {
8070
8200
  dispatchResult = await handle.result;
8071
8201
  } catch (err) {
8072
8202
  const error = err instanceof Error ? err.message : String(err);
8073
- logger$13.warn({
8203
+ logger$15.warn({
8074
8204
  storyKey,
8075
8205
  error
8076
8206
  }, "Test-plan dispatch threw an unexpected error");
@@ -8081,7 +8211,7 @@ async function runTestPlan(deps, params) {
8081
8211
  output: dispatchResult.tokenEstimate.output
8082
8212
  };
8083
8213
  if (dispatchResult.status === "timeout") {
8084
- logger$13.warn({
8214
+ logger$15.warn({
8085
8215
  storyKey,
8086
8216
  durationMs: dispatchResult.durationMs
8087
8217
  }, "Test-plan dispatch timed out");
@@ -8091,7 +8221,7 @@ async function runTestPlan(deps, params) {
8091
8221
  };
8092
8222
  }
8093
8223
  if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
8094
- logger$13.warn({
8224
+ logger$15.warn({
8095
8225
  storyKey,
8096
8226
  exitCode: dispatchResult.exitCode,
8097
8227
  status: dispatchResult.status
@@ -8103,7 +8233,7 @@ async function runTestPlan(deps, params) {
8103
8233
  }
8104
8234
  if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
8105
8235
  const details = dispatchResult.parseError ?? "parsed result was null";
8106
- logger$13.warn({
8236
+ logger$15.warn({
8107
8237
  storyKey,
8108
8238
  parseError: details
8109
8239
  }, "Test-plan YAML schema validation failed");
@@ -8126,19 +8256,19 @@ async function runTestPlan(deps, params) {
8126
8256
  }),
8127
8257
  rationale: `Test plan for ${storyKey}: ${parsed.test_files.length} test files, categories: ${parsed.test_categories.join(", ")}`
8128
8258
  });
8129
- logger$13.info({
8259
+ logger$15.info({
8130
8260
  storyKey,
8131
8261
  fileCount: parsed.test_files.length,
8132
8262
  categories: parsed.test_categories
8133
8263
  }, "Test plan stored in decision store");
8134
8264
  } catch (err) {
8135
8265
  const error = err instanceof Error ? err.message : String(err);
8136
- logger$13.warn({
8266
+ logger$15.warn({
8137
8267
  storyKey,
8138
8268
  error
8139
8269
  }, "Failed to store test plan in decision store — proceeding anyway");
8140
8270
  }
8141
- logger$13.info({
8271
+ logger$15.info({
8142
8272
  storyKey,
8143
8273
  result: parsed.result
8144
8274
  }, "Test-plan workflow completed");
@@ -8178,14 +8308,312 @@ async function getArchConstraints$1(deps) {
8178
8308
  if (constraints.length === 0) return "";
8179
8309
  return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
8180
8310
  } catch (err) {
8181
- logger$13.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints for test-plan — proceeding without them");
8311
+ logger$15.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints for test-plan — proceeding without them");
8182
8312
  return "";
8183
8313
  }
8184
8314
  }
8185
8315
 
8316
+ //#endregion
8317
+ //#region src/modules/implementation-orchestrator/probe-author-integration.ts
8318
+ const logger$14 = createLogger("implementation-orchestrator:probe-author");
8319
+ /** Default timeout for probe-author dispatches (5 min) */
8320
+ const DEFAULT_TIMEOUT_MS = 3e5;
8321
+ /** Timeout multiplier for the single retry after a timeout failure */
8322
+ const TIMEOUT_RETRY_MULTIPLIER = 1.5;
8323
+ /**
8324
+ * Execute the probe-author integration phase.
8325
+ *
8326
+ * Gate 1 — Event-driven AC check: calls `detectsEventDrivenAC(epicContent)`.
8327
+ * Skip if the source AC does not describe a hook, timer, signal, or webhook.
8328
+ *
8329
+ * Gate 2 — Idempotency check: reads storyFilePath and checks for an existing
8330
+ * `## Runtime Probes` section. Skip if present (probes already authored).
8331
+ *
8332
+ * Dispatch: assembles the probe-author prompt and dispatches via WorkflowDeps.
8333
+ * Uses ProbeAuthorResultSchema (result + probes) as outputSchema so the
8334
+ * existing YAML-parser anchor-key detection works correctly.
8335
+ *
8336
+ * Retry policy:
8337
+ * - Timeout → single retry at TIMEOUT_RETRY_MULTIPLIER × DEFAULT_TIMEOUT_MS.
8338
+ * Fall through if second attempt also times out.
8339
+ * - Invalid YAML → single retry with augmented prompt that includes the parse
8340
+ * error and the first 500 chars of bad output. Fall through if retry fails.
8341
+ * - Dispatch error (process crash, network failure) → fall through immediately.
8342
+ * - Empty probes list → emit `probe-author:no-probes-authored`, fall through.
8343
+ *
8344
+ * All failure paths are non-fatal — returns result: 'failed' instead of
8345
+ * throwing so the caller can unconditionally fall through to dev-story.
8346
+ */
8347
+ async function runProbeAuthor(deps, params) {
8348
+ const start = Date.now();
8349
+ const { storyKey, storyFilePath, pipelineRunId, sourceAcContent, epicContent, emitEvent } = params;
8350
+ const tokenUsage = {
8351
+ input: 0,
8352
+ output: 0
8353
+ };
8354
+ if (!detectsEventDrivenAC(epicContent)) {
8355
+ logger$14.debug({ storyKey }, "probe-author: source AC not event-driven — skipping");
8356
+ return makeSkippedResult(tokenUsage, start);
8357
+ }
8358
+ let storyContent;
8359
+ try {
8360
+ storyContent = await readFile$1(storyFilePath, "utf-8");
8361
+ if (/^## Runtime Probes/m.test(storyContent)) {
8362
+ logger$14.info({ storyKey }, "probe-author: story artifact already has ## Runtime Probes — skipping");
8363
+ return makeSkippedResult(tokenUsage, start);
8364
+ }
8365
+ } catch (err) {
8366
+ const error = err instanceof Error ? err.message : String(err);
8367
+ logger$14.warn({
8368
+ storyKey,
8369
+ error
8370
+ }, "probe-author: failed to read story file — falling through");
8371
+ emitEvent?.("probe-author:dispatch-error", {
8372
+ storyKey,
8373
+ runId: pipelineRunId,
8374
+ error
8375
+ });
8376
+ return makeFailedResult(`story_file_read_error: ${error}`, tokenUsage, start);
8377
+ }
8378
+ const { ceiling: TOKEN_CEILING } = getTokenCeiling("probe-author", deps.tokenCeilings);
8379
+ let template;
8380
+ try {
8381
+ template = await deps.pack.getPrompt("probe-author");
8382
+ logger$14.debug({ storyKey }, "probe-author: retrieved prompt template");
8383
+ } catch (err) {
8384
+ const error = err instanceof Error ? err.message : String(err);
8385
+ logger$14.warn({
8386
+ storyKey,
8387
+ error
8388
+ }, "probe-author: failed to get prompt template — falling through");
8389
+ emitEvent?.("probe-author:dispatch-error", {
8390
+ storyKey,
8391
+ runId: pipelineRunId,
8392
+ error
8393
+ });
8394
+ return makeFailedResult(`template_load_failed: ${error}`, tokenUsage, start);
8395
+ }
8396
+ const { prompt: basePrompt } = assemblePrompt(template, [{
8397
+ name: "rendered_ac_section",
8398
+ content: storyContent,
8399
+ priority: "required"
8400
+ }, {
8401
+ name: "source_epic_ac_section",
8402
+ content: sourceAcContent,
8403
+ priority: "required"
8404
+ }], TOKEN_CEILING);
8405
+ const doDispatch = async (promptText, timeoutMs) => {
8406
+ const handle = deps.dispatcher.dispatch({
8407
+ prompt: promptText,
8408
+ agent: deps.agentId ?? "claude-code",
8409
+ taskType: "probe-author",
8410
+ timeout: timeoutMs,
8411
+ outputSchema: ProbeAuthorResultSchema,
8412
+ ...deps.projectRoot !== void 0 ? { workingDirectory: deps.projectRoot } : {},
8413
+ ...deps.otlpEndpoint !== void 0 ? { otlpEndpoint: deps.otlpEndpoint } : {},
8414
+ storyKey
8415
+ });
8416
+ return await handle.result;
8417
+ };
8418
+ let dispatchResult;
8419
+ try {
8420
+ logger$14.info({ storyKey }, "probe-author: dispatching probe-author agent");
8421
+ dispatchResult = await doDispatch(basePrompt, DEFAULT_TIMEOUT_MS);
8422
+ tokenUsage.input += dispatchResult.tokenEstimate.input;
8423
+ tokenUsage.output += dispatchResult.tokenEstimate.output;
8424
+ } catch (err) {
8425
+ const error = err instanceof Error ? err.message : String(err);
8426
+ logger$14.warn({
8427
+ storyKey,
8428
+ error
8429
+ }, "probe-author: dispatch error — falling through to dev-story");
8430
+ emitEvent?.("probe-author:dispatch-error", {
8431
+ storyKey,
8432
+ runId: pipelineRunId,
8433
+ error
8434
+ });
8435
+ return makeFailedResult(`dispatch_error: ${error}`, tokenUsage, start);
8436
+ }
8437
+ if (dispatchResult.status === "timeout") {
8438
+ const elapsedMs = Date.now() - start;
8439
+ logger$14.warn({
8440
+ storyKey,
8441
+ elapsedMs
8442
+ }, "probe-author: dispatch timed out — retrying with 1.5× timeout");
8443
+ emitEvent?.("probe-author:timeout", {
8444
+ storyKey,
8445
+ runId: pipelineRunId,
8446
+ elapsedMs
8447
+ });
8448
+ try {
8449
+ const retryResult = await doDispatch(basePrompt, Math.round(DEFAULT_TIMEOUT_MS * TIMEOUT_RETRY_MULTIPLIER));
8450
+ tokenUsage.input += retryResult.tokenEstimate.input;
8451
+ tokenUsage.output += retryResult.tokenEstimate.output;
8452
+ if (retryResult.status === "timeout") {
8453
+ logger$14.warn({ storyKey }, "probe-author: retry also timed out — falling through to dev-story");
8454
+ return makeFailedResult("dispatch_timeout", tokenUsage, start);
8455
+ }
8456
+ dispatchResult = retryResult;
8457
+ } catch (retryErr) {
8458
+ const error = retryErr instanceof Error ? retryErr.message : String(retryErr);
8459
+ logger$14.warn({
8460
+ storyKey,
8461
+ error
8462
+ }, "probe-author: retry dispatch error — falling through to dev-story");
8463
+ return makeFailedResult(`retry_dispatch_error: ${error}`, tokenUsage, start);
8464
+ }
8465
+ }
8466
+ if (dispatchResult.status === "failed" || dispatchResult.exitCode !== 0) {
8467
+ const error = `dispatch_failed with exit_code=${dispatchResult.exitCode}`;
8468
+ logger$14.warn({ storyKey }, `probe-author: ${error} — falling through to dev-story`);
8469
+ emitEvent?.("probe-author:dispatch-error", {
8470
+ storyKey,
8471
+ runId: pipelineRunId,
8472
+ error
8473
+ });
8474
+ return makeFailedResult(error, tokenUsage, start);
8475
+ }
8476
+ if (dispatchResult.parseError !== null || dispatchResult.parsed === null) {
8477
+ const parseError = dispatchResult.parseError ?? "parsed result was null";
8478
+ const rawOutputSnippet = dispatchResult.output.slice(0, 500);
8479
+ logger$14.warn({
8480
+ storyKey,
8481
+ parseError,
8482
+ rawOutputSnippet
8483
+ }, "probe-author: YAML parse failure — retrying with augmented prompt");
8484
+ emitEvent?.("probe-author:invalid-output", {
8485
+ storyKey,
8486
+ runId: pipelineRunId,
8487
+ parseError,
8488
+ rawOutputSnippet
8489
+ });
8490
+ const augmentedPrompt = `${basePrompt}\n\n---\n\nPrevious output failed parsing with: ${parseError}; produce a single yaml block conforming to RuntimeProbeListSchema`;
8491
+ try {
8492
+ const retryResult = await doDispatch(augmentedPrompt, DEFAULT_TIMEOUT_MS);
8493
+ tokenUsage.input += retryResult.tokenEstimate.input;
8494
+ tokenUsage.output += retryResult.tokenEstimate.output;
8495
+ if (retryResult.parseError !== null || retryResult.parsed === null) {
8496
+ logger$14.warn({ storyKey }, "probe-author: retry still produced invalid YAML — falling through");
8497
+ return makeFailedResult("invalid_yaml_after_retry", tokenUsage, start);
8498
+ }
8499
+ dispatchResult = retryResult;
8500
+ } catch (retryErr) {
8501
+ const error = retryErr instanceof Error ? retryErr.message : String(retryErr);
8502
+ logger$14.warn({
8503
+ storyKey,
8504
+ error
8505
+ }, "probe-author: retry error after invalid YAML — falling through");
8506
+ return makeFailedResult(`retry_error_after_invalid_yaml: ${error}`, tokenUsage, start);
8507
+ }
8508
+ }
8509
+ const parsedOutput = dispatchResult.parsed;
8510
+ const probeValidation = RuntimeProbeListSchema.safeParse(parsedOutput.probes);
8511
+ if (!probeValidation.success) {
8512
+ const validationError = probeValidation.error.message;
8513
+ logger$14.warn({
8514
+ storyKey,
8515
+ validationError
8516
+ }, "probe-author: probes failed RuntimeProbeListSchema — falling through");
8517
+ return makeFailedResult(`schema_validation_failed: ${validationError}`, tokenUsage, start);
8518
+ }
8519
+ const probes = probeValidation.data;
8520
+ if (probes.length === 0) {
8521
+ logger$14.info({ storyKey }, "probe-author: authored empty probes list — no probes needed");
8522
+ emitEvent?.("probe-author:no-probes-authored", {
8523
+ storyKey,
8524
+ runId: pipelineRunId
8525
+ });
8526
+ return {
8527
+ result: "success",
8528
+ probesAuthoredCount: 0,
8529
+ tokenUsage,
8530
+ durationMs: Date.now() - start
8531
+ };
8532
+ }
8533
+ try {
8534
+ const refreshedContent = await readFile$1(storyFilePath, "utf-8");
8535
+ if (/^## Runtime Probes/m.test(refreshedContent)) {
8536
+ logger$14.info({ storyKey }, "probe-author: ## Runtime Probes section appeared after dispatch — skipping append (idempotent)");
8537
+ const dispatchDurationMs$1 = Date.now() - start;
8538
+ emitEvent?.("probe-author:dispatched", {
8539
+ storyKey,
8540
+ runId: pipelineRunId,
8541
+ probesAuthoredCount: 0,
8542
+ dispatchDurationMs: dispatchDurationMs$1,
8543
+ costUsd: estimateDispatchCost$1(tokenUsage.input, tokenUsage.output)
8544
+ });
8545
+ return makeSkippedResult(tokenUsage, start);
8546
+ }
8547
+ const probesYaml = yaml.dump(probes, { lineWidth: 120 }).trimEnd();
8548
+ const probesSection = `\n## Runtime Probes\n\n\`\`\`yaml\n${probesYaml}\n\`\`\`\n`;
8549
+ const newContent = refreshedContent + probesSection;
8550
+ const targetDir = dirname$1(storyFilePath);
8551
+ const tmpPath = join$1(targetDir, `.probe-author-${Date.now()}.tmp.md`);
8552
+ await writeFile$1(tmpPath, newContent, "utf-8");
8553
+ await rename(tmpPath, storyFilePath);
8554
+ logger$14.info({
8555
+ storyKey,
8556
+ probesCount: probes.length
8557
+ }, "probe-author: appended ## Runtime Probes section");
8558
+ } catch (err) {
8559
+ const error = err instanceof Error ? err.message : String(err);
8560
+ logger$14.warn({
8561
+ storyKey,
8562
+ error
8563
+ }, "probe-author: failed to append probes — falling through to dev-story");
8564
+ return {
8565
+ result: "failed",
8566
+ probesAuthoredCount: probes.length,
8567
+ error: `append_error: ${error}`,
8568
+ tokenUsage,
8569
+ durationMs: Date.now() - start
8570
+ };
8571
+ }
8572
+ const dispatchDurationMs = Date.now() - start;
8573
+ const costUsd = estimateDispatchCost$1(tokenUsage.input, tokenUsage.output);
8574
+ emitEvent?.("probe-author:dispatched", {
8575
+ storyKey,
8576
+ runId: pipelineRunId,
8577
+ probesAuthoredCount: probes.length,
8578
+ dispatchDurationMs,
8579
+ costUsd
8580
+ });
8581
+ logger$14.info({
8582
+ storyKey,
8583
+ probesAuthoredCount: probes.length
8584
+ }, "probe-author: phase complete");
8585
+ return {
8586
+ result: "success",
8587
+ probesAuthoredCount: probes.length,
8588
+ tokenUsage,
8589
+ durationMs: Date.now() - start
8590
+ };
8591
+ }
8592
+ function makeSkippedResult(tokenUsage, start) {
8593
+ return {
8594
+ result: "skipped",
8595
+ probesAuthoredCount: 0,
8596
+ tokenUsage,
8597
+ durationMs: Date.now() - start
8598
+ };
8599
+ }
8600
+ function makeFailedResult(error, tokenUsage, start) {
8601
+ return {
8602
+ result: "failed",
8603
+ probesAuthoredCount: 0,
8604
+ error,
8605
+ tokenUsage,
8606
+ durationMs: Date.now() - start
8607
+ };
8608
+ }
8609
+ /** Claude pricing: $3/1M input, $15/1M output */
8610
+ function estimateDispatchCost$1(input, output) {
8611
+ return (input * 3 + output * 15) / 1e6;
8612
+ }
8613
+
8186
8614
  //#endregion
8187
8615
  //#region src/modules/compiled-workflows/test-expansion.ts
8188
- const logger$12 = createLogger("compiled-workflows:test-expansion");
8616
+ const logger$13 = createLogger("compiled-workflows:test-expansion");
8189
8617
  function defaultFallbackResult(error, tokenUsage) {
8190
8618
  return {
8191
8619
  expansion_priority: "low",
@@ -8215,14 +8643,14 @@ function defaultFallbackResult(error, tokenUsage) {
8215
8643
  async function runTestExpansion(deps, params) {
8216
8644
  const { storyKey, storyFilePath, pipelineRunId, filesModified, workingDirectory } = params;
8217
8645
  const cwd = workingDirectory ?? process.cwd();
8218
- logger$12.debug({
8646
+ logger$13.debug({
8219
8647
  storyKey,
8220
8648
  storyFilePath,
8221
8649
  cwd,
8222
8650
  pipelineRunId
8223
8651
  }, "Starting test-expansion workflow");
8224
8652
  const { ceiling: TOKEN_CEILING, source: tokenCeilingSource } = getTokenCeiling("test-expansion", deps.tokenCeilings);
8225
- logger$12.info({
8653
+ logger$13.info({
8226
8654
  workflow: "test-expansion",
8227
8655
  ceiling: TOKEN_CEILING,
8228
8656
  source: tokenCeilingSource
@@ -8232,7 +8660,7 @@ async function runTestExpansion(deps, params) {
8232
8660
  template = await deps.pack.getPrompt("test-expansion");
8233
8661
  } catch (err) {
8234
8662
  const error = err instanceof Error ? err.message : String(err);
8235
- logger$12.warn({ error }, "Failed to retrieve test-expansion prompt template");
8663
+ logger$13.warn({ error }, "Failed to retrieve test-expansion prompt template");
8236
8664
  return defaultFallbackResult(`Failed to retrieve prompt template: ${error}`, {
8237
8665
  input: 0,
8238
8666
  output: 0
@@ -8243,7 +8671,7 @@ async function runTestExpansion(deps, params) {
8243
8671
  storyContent = await readFile$1(storyFilePath, "utf-8");
8244
8672
  } catch (err) {
8245
8673
  const error = err instanceof Error ? err.message : String(err);
8246
- logger$12.warn({
8674
+ logger$13.warn({
8247
8675
  storyFilePath,
8248
8676
  error
8249
8677
  }, "Failed to read story file");
@@ -8259,13 +8687,13 @@ async function runTestExpansion(deps, params) {
8259
8687
  const testPatternDecisions = solutioningDecisions.filter((d) => d.category === "test-patterns");
8260
8688
  if (testPatternDecisions.length > 0) {
8261
8689
  testPatternsContent = "## Test Patterns\n" + testPatternDecisions.map((d) => `- ${d.key}: ${d.value}`).join("\n");
8262
- logger$12.debug({
8690
+ logger$13.debug({
8263
8691
  storyKey,
8264
8692
  count: testPatternDecisions.length
8265
8693
  }, "Loaded test patterns from decision store");
8266
8694
  } else {
8267
8695
  testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
8268
- logger$12.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
8696
+ logger$13.debug({ storyKey }, "No test-pattern decisions — using stack-aware defaults");
8269
8697
  }
8270
8698
  } catch {
8271
8699
  testPatternsContent = resolveDefaultTestPatterns(deps.projectRoot);
@@ -8280,12 +8708,12 @@ async function runTestExpansion(deps, params) {
8280
8708
  const scopedTotal = nonDiffTokens + countTokens(scopedDiff);
8281
8709
  if (scopedTotal <= TOKEN_CEILING) {
8282
8710
  gitDiffContent = scopedDiff;
8283
- logger$12.debug({
8711
+ logger$13.debug({
8284
8712
  fileCount: filesModified.length,
8285
8713
  tokenCount: scopedTotal
8286
8714
  }, "Using scoped file diff");
8287
8715
  } else {
8288
- logger$12.warn({
8716
+ logger$13.warn({
8289
8717
  estimatedTotal: scopedTotal,
8290
8718
  ceiling: TOKEN_CEILING,
8291
8719
  fileCount: filesModified.length
@@ -8293,7 +8721,7 @@ async function runTestExpansion(deps, params) {
8293
8721
  gitDiffContent = await getGitDiffStatForFiles(filesModified, cwd);
8294
8722
  }
8295
8723
  } catch (err) {
8296
- logger$12.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to get git diff — proceeding with empty diff");
8724
+ logger$13.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to get git diff — proceeding with empty diff");
8297
8725
  }
8298
8726
  const sections = [
8299
8727
  {
@@ -8318,11 +8746,11 @@ async function runTestExpansion(deps, params) {
8318
8746
  }
8319
8747
  ];
8320
8748
  const assembleResult = assemblePrompt(template, sections, TOKEN_CEILING);
8321
- if (assembleResult.truncated) logger$12.warn({
8749
+ if (assembleResult.truncated) logger$13.warn({
8322
8750
  storyKey,
8323
8751
  tokenCount: assembleResult.tokenCount
8324
8752
  }, "Test-expansion prompt truncated to fit token ceiling");
8325
- logger$12.debug({
8753
+ logger$13.debug({
8326
8754
  storyKey,
8327
8755
  tokenCount: assembleResult.tokenCount,
8328
8756
  truncated: assembleResult.truncated
@@ -8342,7 +8770,7 @@ async function runTestExpansion(deps, params) {
8342
8770
  dispatchResult = await handle.result;
8343
8771
  } catch (err) {
8344
8772
  const error = err instanceof Error ? err.message : String(err);
8345
- logger$12.warn({
8773
+ logger$13.warn({
8346
8774
  storyKey,
8347
8775
  error
8348
8776
  }, "Test-expansion dispatch threw unexpected error");
@@ -8357,19 +8785,19 @@ async function runTestExpansion(deps, params) {
8357
8785
  };
8358
8786
  if (dispatchResult.status === "failed") {
8359
8787
  const errorMsg = `Dispatch status: failed. Exit code: ${dispatchResult.exitCode}. ${dispatchResult.parseError ?? ""}`.trim();
8360
- logger$12.warn({
8788
+ logger$13.warn({
8361
8789
  storyKey,
8362
8790
  exitCode: dispatchResult.exitCode
8363
8791
  }, "Test-expansion dispatch failed");
8364
8792
  return defaultFallbackResult(errorMsg, tokenUsage);
8365
8793
  }
8366
8794
  if (dispatchResult.status === "timeout") {
8367
- logger$12.warn({ storyKey }, "Test-expansion dispatch timed out");
8795
+ logger$13.warn({ storyKey }, "Test-expansion dispatch timed out");
8368
8796
  return defaultFallbackResult("Dispatch status: timeout. The agent did not complete within the allowed time.", tokenUsage);
8369
8797
  }
8370
8798
  if (dispatchResult.parsed === null) {
8371
8799
  const details = dispatchResult.parseError ?? "No YAML block found in output";
8372
- logger$12.warn({
8800
+ logger$13.warn({
8373
8801
  storyKey,
8374
8802
  details
8375
8803
  }, "Test-expansion output has no parseable YAML");
@@ -8378,14 +8806,14 @@ async function runTestExpansion(deps, params) {
8378
8806
  const parseResult = TestExpansionResultSchema.safeParse(dispatchResult.parsed);
8379
8807
  if (!parseResult.success) {
8380
8808
  const details = parseResult.error.message;
8381
- logger$12.warn({
8809
+ logger$13.warn({
8382
8810
  storyKey,
8383
8811
  details
8384
8812
  }, "Test-expansion output failed schema validation");
8385
8813
  return defaultFallbackResult(`schema_validation_failed: ${details}`, tokenUsage);
8386
8814
  }
8387
8815
  const parsed = parseResult.data;
8388
- logger$12.info({
8816
+ logger$13.info({
8389
8817
  storyKey,
8390
8818
  expansion_priority: parsed.expansion_priority,
8391
8819
  coverage_gaps: parsed.coverage_gaps.length,
@@ -8410,11 +8838,15 @@ async function getArchConstraints(deps) {
8410
8838
  if (constraints.length === 0) return "";
8411
8839
  return constraints.map((d) => `${d.key}: ${d.value}`).join("\n");
8412
8840
  } catch (err) {
8413
- logger$12.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
8841
+ logger$13.warn({ error: err instanceof Error ? err.message : String(err) }, "Failed to retrieve architecture constraints");
8414
8842
  return "";
8415
8843
  }
8416
8844
  }
8417
8845
 
8846
+ //#endregion
8847
+ //#region src/modules/compiled-workflows/probe-author.ts
8848
+ const logger$12 = createLogger("compiled-workflows:probe-author");
8849
+
8418
8850
  //#endregion
8419
8851
  //#region src/modules/compiled-workflows/story-analyzer.ts
8420
8852
  /**
@@ -11707,7 +12139,7 @@ function checkProfileStaleness(projectRoot) {
11707
12139
  */
11708
12140
  function createImplementationOrchestrator(deps) {
11709
12141
  const { db, pack, contextCompiler, dispatcher, eventBus, config, projectRoot, tokenCeilings, stateStore, telemetryPersistence, ingestionServer, repoMapInjector, maxRepoMapTokens, agentId, runManifest = null } = deps;
11710
- const logger$24 = createLogger("implementation-orchestrator");
12142
+ const logger$26 = createLogger("implementation-orchestrator");
11711
12143
  const telemetryAdvisor = db !== void 0 ? createTelemetryAdvisor({ db }) : void 0;
11712
12144
  const wgRepo = new WorkGraphRepository(db);
11713
12145
  const _wgInProgressWritten = new Set();
@@ -11790,7 +12222,7 @@ function createImplementationOrchestrator(deps) {
11790
12222
  const existingCount = storyState?.retry_count ?? 0;
11791
12223
  _storyRetryCount.set(storyKey, existingCount);
11792
12224
  } catch (err) {
11793
- logger$24.warn({
12225
+ logger$26.warn({
11794
12226
  err,
11795
12227
  storyKey
11796
12228
  }, "initRetryCount: failed to read manifest — starting at 0");
@@ -11804,7 +12236,7 @@ function createImplementationOrchestrator(deps) {
11804
12236
  const current = _storyRetryCount.get(storyKey) ?? 0;
11805
12237
  const next = current + 1;
11806
12238
  _storyRetryCount.set(storyKey, next);
11807
- if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { retry_count: next }).catch((err) => logger$24.warn({
12239
+ if (runManifest !== null && runManifest !== void 0) runManifest.patchStoryState(storyKey, { retry_count: next }).catch((err) => logger$26.warn({
11808
12240
  err,
11809
12241
  storyKey
11810
12242
  }, "patchStoryState(retry_count) failed — pipeline continues"));
@@ -11817,7 +12249,7 @@ function createImplementationOrchestrator(deps) {
11817
12249
  const nowMs = Date.now();
11818
12250
  for (const [phase, startMs] of starts) {
11819
12251
  const endMs = ends?.get(phase);
11820
- if (endMs === void 0) logger$24.warn({
12252
+ if (endMs === void 0) logger$26.warn({
11821
12253
  storyKey,
11822
12254
  phase
11823
12255
  }, "Phase has no end time — story may have errored mid-phase. Duration capped to now() and may be inflated.");
@@ -11834,7 +12266,7 @@ function createImplementationOrchestrator(deps) {
11834
12266
  const wallClockSeconds = startedAt ? Math.round((new Date(completedAt).getTime() - new Date(startedAt).getTime()) / 1e3) : 0;
11835
12267
  const wallClockMs = startedAt ? new Date(completedAt).getTime() - new Date(startedAt).getTime() : 0;
11836
12268
  const tokenAgg = await aggregateTokenUsageForStory(db, config.pipelineRunId, storyKey);
11837
- if (runManifest !== null) runManifest.patchStoryState(storyKey, { cost_usd: tokenAgg.cost }).catch((err) => logger$24.warn({
12269
+ if (runManifest !== null) runManifest.patchStoryState(storyKey, { cost_usd: tokenAgg.cost }).catch((err) => logger$26.warn({
11838
12270
  err,
11839
12271
  storyKey
11840
12272
  }, "patchStoryState(cost_usd) failed — pipeline continues"));
@@ -11870,7 +12302,7 @@ function createImplementationOrchestrator(deps) {
11870
12302
  recordedAt: completedAt,
11871
12303
  timestamp: completedAt
11872
12304
  }).catch((storeErr) => {
11873
- logger$24.warn({
12305
+ logger$26.warn({
11874
12306
  err: storeErr,
11875
12307
  storyKey
11876
12308
  }, "Failed to record metric to StateStore (best-effort)");
@@ -11892,7 +12324,7 @@ function createImplementationOrchestrator(deps) {
11892
12324
  rationale: `Story ${storyKey} completed with result=${result} in ${wallClockSeconds}s. Tokens: ${tokenAgg.input}+${tokenAgg.output}. Review cycles: ${reviewCycles}.`
11893
12325
  });
11894
12326
  } catch (decisionErr) {
11895
- logger$24.warn({
12327
+ logger$26.warn({
11896
12328
  err: decisionErr,
11897
12329
  storyKey
11898
12330
  }, "Failed to write story-metrics decision (best-effort)");
@@ -11971,7 +12403,7 @@ function createImplementationOrchestrator(deps) {
11971
12403
  const LOW_OUTPUT_TOKEN_THRESHOLD = 100;
11972
12404
  const unverified = tokenAgg.output < LOW_OUTPUT_TOKEN_THRESHOLD;
11973
12405
  if (unverified) {
11974
- logger$24.warn({
12406
+ logger$26.warn({
11975
12407
  storyKey,
11976
12408
  outputTokens: tokenAgg.output,
11977
12409
  threshold: LOW_OUTPUT_TOKEN_THRESHOLD
@@ -11995,13 +12427,13 @@ function createImplementationOrchestrator(deps) {
11995
12427
  ...unverified ? { unverified: true } : {}
11996
12428
  });
11997
12429
  } catch (emitErr) {
11998
- logger$24.warn({
12430
+ logger$26.warn({
11999
12431
  err: emitErr,
12000
12432
  storyKey
12001
12433
  }, "Failed to emit story:metrics event (best-effort)");
12002
12434
  }
12003
12435
  } catch (err) {
12004
- logger$24.warn({
12436
+ logger$26.warn({
12005
12437
  err,
12006
12438
  storyKey
12007
12439
  }, "Failed to write story metrics (best-effort)");
@@ -12030,7 +12462,7 @@ function createImplementationOrchestrator(deps) {
12030
12462
  rationale: `Story ${storyKey} ${outcome} after ${reviewCycles} review cycle(s).`
12031
12463
  });
12032
12464
  } catch (err) {
12033
- logger$24.warn({
12465
+ logger$26.warn({
12034
12466
  err,
12035
12467
  storyKey
12036
12468
  }, "Failed to write story-outcome decision (best-effort)");
@@ -12068,7 +12500,7 @@ function createImplementationOrchestrator(deps) {
12068
12500
  rationale: `Escalation diagnosis for ${payload.storyKey}: ${diagnosis.recommendedAction} — ${diagnosis.rationale}`
12069
12501
  });
12070
12502
  } catch (err) {
12071
- logger$24.warn({
12503
+ logger$26.warn({
12072
12504
  err,
12073
12505
  storyKey: payload.storyKey
12074
12506
  }, "Failed to persist escalation diagnosis (best-effort)");
@@ -12118,7 +12550,7 @@ function createImplementationOrchestrator(deps) {
12118
12550
  const existing = _stories.get(storyKey);
12119
12551
  if (existing !== void 0) {
12120
12552
  Object.assign(existing, updates);
12121
- persistStoryState(storyKey, existing).catch((err) => logger$24.warn({
12553
+ persistStoryState(storyKey, existing).catch((err) => logger$26.warn({
12122
12554
  err,
12123
12555
  storyKey
12124
12556
  }, "StateStore write failed after updateStory"));
@@ -12127,12 +12559,12 @@ function createImplementationOrchestrator(deps) {
12127
12559
  storyKey,
12128
12560
  conflict: err
12129
12561
  });
12130
- else logger$24.warn({
12562
+ else logger$26.warn({
12131
12563
  err,
12132
12564
  storyKey
12133
12565
  }, "mergeStory failed");
12134
12566
  });
12135
- else if (updates.phase === "ESCALATED" || updates.phase === "VERIFICATION_FAILED") stateStore?.rollbackStory(storyKey).catch((err) => logger$24.warn({
12567
+ else if (updates.phase === "ESCALATED" || updates.phase === "VERIFICATION_FAILED") stateStore?.rollbackStory(storyKey).catch((err) => logger$26.warn({
12136
12568
  err,
12137
12569
  storyKey
12138
12570
  }, "rollbackStory failed — branch may persist"));
@@ -12144,7 +12576,7 @@ function createImplementationOrchestrator(deps) {
12144
12576
  ...updates
12145
12577
  };
12146
12578
  const opts = targetStatus === "complete" || targetStatus === "escalated" ? { completedAt: fullUpdated.completedAt } : void 0;
12147
- wgRepo.updateStoryStatus(storyKey, targetStatus, opts).catch((err) => logger$24.warn({
12579
+ wgRepo.updateStoryStatus(storyKey, targetStatus, opts).catch((err) => logger$26.warn({
12148
12580
  err,
12149
12581
  storyKey
12150
12582
  }, "wg_stories status update failed (best-effort)"));
@@ -12160,7 +12592,7 @@ function createImplementationOrchestrator(deps) {
12160
12592
  status: "dispatched",
12161
12593
  phase: String(updates.phase),
12162
12594
  started_at: fullUpdated.startedAt ?? new Date().toISOString()
12163
- }).catch((err) => logger$24.warn({
12595
+ }).catch((err) => logger$26.warn({
12164
12596
  err,
12165
12597
  storyKey
12166
12598
  }, "patchStoryState(dispatched) failed — pipeline continues"));
@@ -12172,7 +12604,7 @@ function createImplementationOrchestrator(deps) {
12172
12604
  completed_at: fullUpdated.completedAt ?? new Date().toISOString(),
12173
12605
  review_cycles: fullUpdated.reviewCycles ?? 0,
12174
12606
  dispatches: _storyDispatches.get(storyKey) ?? 0
12175
- }).catch((err) => logger$24.warn({
12607
+ }).catch((err) => logger$26.warn({
12176
12608
  err,
12177
12609
  storyKey
12178
12610
  }, `patchStoryState(${manifestStatus}) failed — pipeline continues`));
@@ -12202,7 +12634,7 @@ function createImplementationOrchestrator(deps) {
12202
12634
  };
12203
12635
  await stateStore.setStoryState(storyKey, record);
12204
12636
  } catch (err) {
12205
- logger$24.warn({
12637
+ logger$26.warn({
12206
12638
  err,
12207
12639
  storyKey
12208
12640
  }, "StateStore.setStoryState failed (best-effort)");
@@ -12218,7 +12650,7 @@ function createImplementationOrchestrator(deps) {
12218
12650
  token_usage_json: serialized
12219
12651
  });
12220
12652
  } catch (err) {
12221
- logger$24.warn({ err }, "Failed to persist orchestrator state");
12653
+ logger$26.warn({ err }, "Failed to persist orchestrator state");
12222
12654
  }
12223
12655
  }
12224
12656
  function recordProgress() {
@@ -12244,7 +12676,7 @@ function createImplementationOrchestrator(deps) {
12244
12676
  queuedDispatches: queued
12245
12677
  });
12246
12678
  if (config.pipelineRunId !== void 0) updatePipelineRun(db, config.pipelineRunId, { current_phase: "implementation" }).catch((err) => {
12247
- logger$24.debug({ err }, "Heartbeat: failed to touch updated_at (non-fatal)");
12679
+ logger$26.debug({ err }, "Heartbeat: failed to touch updated_at (non-fatal)");
12248
12680
  });
12249
12681
  const elapsed = Date.now() - _lastProgressTs;
12250
12682
  let childPids = [];
@@ -12266,7 +12698,7 @@ function createImplementationOrchestrator(deps) {
12266
12698
  }
12267
12699
  if (childActive) {
12268
12700
  _lastProgressTs = Date.now();
12269
- logger$24.debug({
12701
+ logger$26.debug({
12270
12702
  storyKey: key,
12271
12703
  phase: s$1.phase,
12272
12704
  childPids
@@ -12275,7 +12707,7 @@ function createImplementationOrchestrator(deps) {
12275
12707
  }
12276
12708
  _stalledStories.add(key);
12277
12709
  _storiesWithStall.add(key);
12278
- logger$24.warn({
12710
+ logger$26.warn({
12279
12711
  storyKey: key,
12280
12712
  phase: s$1.phase,
12281
12713
  elapsedMs: elapsed,
@@ -12320,7 +12752,7 @@ function createImplementationOrchestrator(deps) {
12320
12752
  for (let attempt = 0; attempt < MEMORY_PRESSURE_BACKOFF_MS.length; attempt++) {
12321
12753
  const memState = dispatcher.getMemoryState();
12322
12754
  if (!memState.isPressured) return true;
12323
- logger$24.warn({
12755
+ logger$26.warn({
12324
12756
  storyKey,
12325
12757
  freeMB: memState.freeMB,
12326
12758
  thresholdMB: memState.thresholdMB,
@@ -12340,12 +12772,12 @@ function createImplementationOrchestrator(deps) {
12340
12772
  * exhausted retries the story is ESCALATED.
12341
12773
  */
12342
12774
  async function processStory(storyKey, storyOptions) {
12343
- logger$24.info({ storyKey }, "Processing story");
12775
+ logger$26.info({ storyKey }, "Processing story");
12344
12776
  await initRetryCount(storyKey);
12345
12777
  {
12346
12778
  const memoryOk = await checkMemoryPressure(storyKey);
12347
12779
  if (!memoryOk) {
12348
- logger$24.warn({ storyKey }, "Memory pressure exhausted — escalating story without dispatch");
12780
+ logger$26.warn({ storyKey }, "Memory pressure exhausted — escalating story without dispatch");
12349
12781
  const memPressureState = {
12350
12782
  phase: "ESCALATED",
12351
12783
  reviewCycles: 0,
@@ -12354,7 +12786,7 @@ function createImplementationOrchestrator(deps) {
12354
12786
  completedAt: new Date().toISOString()
12355
12787
  };
12356
12788
  _stories.set(storyKey, memPressureState);
12357
- persistStoryState(storyKey, memPressureState).catch((err) => logger$24.warn({
12789
+ persistStoryState(storyKey, memPressureState).catch((err) => logger$26.warn({
12358
12790
  err,
12359
12791
  storyKey
12360
12792
  }, "StateStore write failed after memory-pressure escalation"));
@@ -12371,7 +12803,7 @@ function createImplementationOrchestrator(deps) {
12371
12803
  }
12372
12804
  await waitIfPaused();
12373
12805
  if (_state !== "RUNNING") return;
12374
- stateStore?.branchForStory(storyKey).catch((err) => logger$24.warn({
12806
+ stateStore?.branchForStory(storyKey).catch((err) => logger$26.warn({
12375
12807
  err,
12376
12808
  storyKey
12377
12809
  }, "branchForStory failed — continuing without branch isolation"));
@@ -12390,7 +12822,7 @@ function createImplementationOrchestrator(deps) {
12390
12822
  if (match$2) {
12391
12823
  const candidatePath = join$1(artifactsDir, match$2);
12392
12824
  const validation = await isValidStoryFile(candidatePath);
12393
- if (!validation.valid) logger$24.warn({
12825
+ if (!validation.valid) logger$26.warn({
12394
12826
  storyKey,
12395
12827
  storyFilePath: candidatePath,
12396
12828
  reason: validation.reason
@@ -12415,7 +12847,7 @@ function createImplementationOrchestrator(deps) {
12415
12847
  storedHash,
12416
12848
  currentHash
12417
12849
  });
12418
- logger$24.info({
12850
+ logger$26.info({
12419
12851
  storyKey,
12420
12852
  storedHash,
12421
12853
  currentHash
@@ -12426,7 +12858,7 @@ function createImplementationOrchestrator(deps) {
12426
12858
  } catch {}
12427
12859
  if (!isDrift) {
12428
12860
  storyFilePath = candidatePath;
12429
- logger$24.info({
12861
+ logger$26.info({
12430
12862
  storyKey,
12431
12863
  storyFilePath
12432
12864
  }, "Found existing story file — skipping create-story");
@@ -12446,12 +12878,12 @@ function createImplementationOrchestrator(deps) {
12446
12878
  const staleName = match$2.replace(/\.md$/, `.stale-${ts}.md`);
12447
12879
  const stalePath = join$1(artifactsDir, staleName);
12448
12880
  renameSync(candidatePath, stalePath);
12449
- logger$24.info({
12881
+ logger$26.info({
12450
12882
  storyKey,
12451
12883
  staleName
12452
12884
  }, `[orchestrator] story ${storyKey}: renamed drifted artifact to ${staleName} before re-dispatch`);
12453
12885
  } catch (renameErr) {
12454
- logger$24.warn({
12886
+ logger$26.warn({
12455
12887
  storyKey,
12456
12888
  err: renameErr
12457
12889
  }, "Failed to rename stale artifact before create-story re-dispatch; relying on 58-9d fraud-guard");
@@ -12460,7 +12892,7 @@ function createImplementationOrchestrator(deps) {
12460
12892
  }
12461
12893
  } catch {}
12462
12894
  if (storyFilePath === void 0 && projectRoot && isImplicitlyCovered(storyKey, projectRoot)) {
12463
- logger$24.info({ storyKey }, `Story ${storyKey} appears implicitly covered — all expected new files already exist. Skipping create-story.`);
12895
+ logger$26.info({ storyKey }, `Story ${storyKey} appears implicitly covered — all expected new files already exist. Skipping create-story.`);
12464
12896
  endPhase(storyKey, "create-story");
12465
12897
  eventBus.emit("orchestrator:story-phase-complete", {
12466
12898
  storyKey,
@@ -12513,7 +12945,7 @@ function createImplementationOrchestrator(deps) {
12513
12945
  output_tokens: createResult.tokenUsage.output,
12514
12946
  cost_usd: estimateDispatchCost(createResult.tokenUsage.input, createResult.tokenUsage.output),
12515
12947
  metadata: JSON.stringify({ storyKey })
12516
- })).catch((tokenErr) => logger$24.warn({
12948
+ })).catch((tokenErr) => logger$26.warn({
12517
12949
  storyKey,
12518
12950
  err: tokenErr
12519
12951
  }, "Failed to record create-story token usage"));
@@ -12521,7 +12953,7 @@ function createImplementationOrchestrator(deps) {
12521
12953
  if (createResult.result === "failed") {
12522
12954
  const errMsg = createResult.error ?? "create-story failed";
12523
12955
  const stderrSnippet = errMsg.includes("--- stderr ---") ? errMsg.slice(errMsg.indexOf("--- stderr ---") + 15, errMsg.indexOf("--- stderr ---") + 515) : errMsg.slice(0, 500);
12524
- logger$24.error({
12956
+ logger$26.error({
12525
12957
  storyKey,
12526
12958
  stderrSnippet
12527
12959
  }, `Create-story failed: ${stderrSnippet.split("\n")[0]}`);
@@ -12563,7 +12995,7 @@ function createImplementationOrchestrator(deps) {
12563
12995
  let claimedPath = createResult.story_file;
12564
12996
  if (claimedPath.startsWith(escapedExpectedDir)) {
12565
12997
  claimedPath = claimedPath.replace("/\\_bmad-output/", "/_bmad-output/");
12566
- logger$24.warn({
12998
+ logger$26.warn({
12567
12999
  storyKey,
12568
13000
  originalClaim: createResult.story_file,
12569
13001
  normalizedClaim: claimedPath
@@ -12581,7 +13013,7 @@ function createImplementationOrchestrator(deps) {
12581
13013
  if (escapedVariant !== claimedPath && existsSync(escapedVariant)) try {
12582
13014
  renameSync(escapedVariant, claimedPath);
12583
13015
  actualPath = claimedPath;
12584
- logger$24.warn({
13016
+ logger$26.warn({
12585
13017
  storyKey,
12586
13018
  escapedVariant,
12587
13019
  canonicalPath: claimedPath
@@ -12592,7 +13024,7 @@ function createImplementationOrchestrator(deps) {
12592
13024
  });
12593
13025
  } catch (renameErr) {
12594
13026
  actualPath = escapedVariant;
12595
- logger$24.warn({
13027
+ logger$26.warn({
12596
13028
  storyKey,
12597
13029
  escapedVariant,
12598
13030
  canonicalPath: claimedPath,
@@ -12607,7 +13039,7 @@ function createImplementationOrchestrator(deps) {
12607
13039
  if (actualPath === null) {
12608
13040
  const outputTokens = createResult.tokenUsage?.output ?? 0;
12609
13041
  const errMsg = `create-story claimed success (story_file: ${createResult.story_file}) but the file does not exist on disk (output tokens: ${outputTokens})`;
12610
- logger$24.error({
13042
+ logger$26.error({
12611
13043
  storyKey,
12612
13044
  claimedPath: createResult.story_file,
12613
13045
  outputTokens
@@ -12634,7 +13066,7 @@ function createImplementationOrchestrator(deps) {
12634
13066
  const mtimeISO = new Date(claimedStat.mtimeMs).toISOString();
12635
13067
  const dispatchStartISO = new Date(dispatchStartMs).toISOString();
12636
13068
  const errMsg = `create-story claimed success but did not rewrite ${actualPath} during this dispatch (file mtime ${mtimeISO} predates dispatch start ${dispatchStartISO}; output tokens: ${outputTokens})`;
12637
- logger$24.error({
13069
+ logger$26.error({
12638
13070
  storyKey,
12639
13071
  claimedPath: actualPath,
12640
13072
  mtimeISO,
@@ -12657,7 +13089,7 @@ function createImplementationOrchestrator(deps) {
12657
13089
  return;
12658
13090
  }
12659
13091
  } catch (verifyErr) {
12660
- logger$24.warn({
13092
+ logger$26.warn({
12661
13093
  storyKey,
12662
13094
  err: verifyErr
12663
13095
  }, "create-story post-dispatch file verification threw; proceeding with claimed path");
@@ -12680,7 +13112,7 @@ function createImplementationOrchestrator(deps) {
12680
13112
  const overlap = computeTitleOverlap(expectedTitle, createResult.story_title);
12681
13113
  if (overlap < TITLE_OVERLAP_WARNING_THRESHOLD) {
12682
13114
  const msg = `Story title mismatch: expected "${expectedTitle}" but got "${createResult.story_title}" (word overlap: ${Math.round(overlap * 100)}%). This may indicate the create-story agent received truncated context.`;
12683
- logger$24.warn({
13115
+ logger$26.warn({
12684
13116
  storyKey,
12685
13117
  expectedTitle,
12686
13118
  generatedTitle: createResult.story_title,
@@ -12690,7 +13122,7 @@ function createImplementationOrchestrator(deps) {
12690
13122
  storyKey,
12691
13123
  msg
12692
13124
  });
12693
- } else logger$24.debug({
13125
+ } else logger$26.debug({
12694
13126
  storyKey,
12695
13127
  expectedTitle,
12696
13128
  generatedTitle: createResult.story_title,
@@ -12699,7 +13131,7 @@ function createImplementationOrchestrator(deps) {
12699
13131
  }
12700
13132
  }
12701
13133
  } catch (titleValidationErr) {
12702
- logger$24.debug({
13134
+ logger$26.debug({
12703
13135
  storyKey,
12704
13136
  err: titleValidationErr
12705
13137
  }, "Story title validation skipped due to error");
@@ -12740,7 +13172,7 @@ function createImplementationOrchestrator(deps) {
12740
13172
  const pathDrift = pathFidelity?.drift ?? 0;
12741
13173
  const clauseDrift = clauseFidelity.drift;
12742
13174
  const overallDrift = Math.max(pathDrift, clauseDrift);
12743
- logger$24.debug({
13175
+ logger$26.debug({
12744
13176
  storyKey,
12745
13177
  pathDrift,
12746
13178
  clauseDrift,
@@ -12762,7 +13194,7 @@ function createImplementationOrchestrator(deps) {
12762
13194
  if (pathMissing.length > 0) reasons.push(`${pathMissing.length} named path(s) missing`);
12763
13195
  if (numericMismatches.length > 0) reasons.push(`${numericMismatches.length} numeric quantifier mismatch(es) (e.g., "${numericMismatches[0].noun}" source=${numericMismatches[0].sourceCount} rendered=${numericMismatches[0].renderedCount})`);
12764
13196
  if (clauseFidelity.clauseRatio < .7) reasons.push(`clause shortfall (rendered ${clauseFidelity.renderedClauseCount}/${clauseFidelity.sourceClauseCount} = ${Math.round(clauseFidelity.clauseRatio * 100)}%)`);
12765
- logger$24.warn({
13197
+ logger$26.warn({
12766
13198
  storyKey,
12767
13199
  pathDrift,
12768
13200
  clauseDrift,
@@ -12805,7 +13237,7 @@ function createImplementationOrchestrator(deps) {
12805
13237
  storyFilePath = void 0;
12806
13238
  continue;
12807
13239
  } catch (renameErr) {
12808
- logger$24.warn({
13240
+ logger$26.warn({
12809
13241
  storyKey,
12810
13242
  err: renameErr,
12811
13243
  stalePath
@@ -12819,7 +13251,7 @@ function createImplementationOrchestrator(deps) {
12819
13251
  if (numericMismatches.length > 0) reasons.push(`numeric mismatches: ${numericMismatches.map((m) => `${m.noun} (source=${m.sourceCount}, rendered=${m.renderedCount})`).join("; ")}`);
12820
13252
  if (clauseFidelity.clauseRatio < .7) reasons.push(`clause shortfall: source=${clauseFidelity.sourceClauseCount}, rendered=${clauseFidelity.renderedClauseCount}`);
12821
13253
  const errMsg = `create-story output drifted from source AC after ${MAX_FIDELITY_RETRIES} retries; ` + reasons.join("; ");
12822
- logger$24.error({
13254
+ logger$26.error({
12823
13255
  storyKey,
12824
13256
  pathDrift,
12825
13257
  clauseDrift,
@@ -12846,7 +13278,7 @@ function createImplementationOrchestrator(deps) {
12846
13278
  }
12847
13279
  }
12848
13280
  } catch (fidelityErr) {
12849
- logger$24.warn({
13281
+ logger$26.warn({
12850
13282
  storyKey,
12851
13283
  err: fidelityErr
12852
13284
  }, "fidelity gate threw; proceeding without retry");
@@ -12877,18 +13309,79 @@ function createImplementationOrchestrator(deps) {
12877
13309
  ...contract.transport !== void 0 ? { transport: contract.transport } : {}
12878
13310
  })
12879
13311
  });
12880
- logger$24.info({
13312
+ logger$26.info({
12881
13313
  storyKey,
12882
13314
  contractCount: contracts.length,
12883
13315
  contracts
12884
13316
  }, "Stored interface contract declarations");
12885
13317
  }
12886
13318
  } catch (err) {
12887
- logger$24.warn({
13319
+ logger$26.warn({
12888
13320
  storyKey,
12889
13321
  error: err instanceof Error ? err.message : String(err)
12890
13322
  }, "Failed to parse interface contracts — continuing without contract declarations");
12891
13323
  }
13324
+ if (storyFilePath) try {
13325
+ let probeAuthorEpicContent = "";
13326
+ const probeAuthorEpicsPath = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
13327
+ if (probeAuthorEpicsPath) try {
13328
+ const epicFull = readFileSync(probeAuthorEpicsPath, "utf-8");
13329
+ const section = extractStorySection(epicFull, storyKey);
13330
+ probeAuthorEpicContent = section ?? epicFull;
13331
+ } catch {}
13332
+ if (detectsEventDrivenAC(probeAuthorEpicContent)) {
13333
+ let artifactHasProbes = false;
13334
+ try {
13335
+ const artifactContent = readFileSync(storyFilePath, "utf-8");
13336
+ artifactHasProbes = /^## Runtime Probes/m.test(artifactContent);
13337
+ } catch {}
13338
+ if (!artifactHasProbes) {
13339
+ const probeAuthorResult = await runProbeAuthor({
13340
+ db,
13341
+ pack,
13342
+ contextCompiler,
13343
+ dispatcher,
13344
+ projectRoot,
13345
+ tokenCeilings,
13346
+ otlpEndpoint: _otlpEndpoint,
13347
+ agentId
13348
+ }, {
13349
+ storyKey,
13350
+ storyFilePath,
13351
+ pipelineRunId: config.pipelineRunId ?? "",
13352
+ sourceAcContent: probeAuthorEpicContent,
13353
+ epicContent: probeAuthorEpicContent,
13354
+ emitEvent: (name, payload) => {
13355
+ eventBus.emit("orchestrator:story-warn", {
13356
+ storyKey,
13357
+ msg: `probe-author:${name.replace("probe-author:", "")} ${JSON.stringify(payload)}`
13358
+ });
13359
+ }
13360
+ });
13361
+ logger$26.info({
13362
+ storyKey,
13363
+ result: probeAuthorResult.result,
13364
+ probesAuthoredCount: probeAuthorResult.probesAuthoredCount
13365
+ }, "probe-author phase complete");
13366
+ if (config.pipelineRunId !== void 0 && probeAuthorResult.tokenUsage.input + probeAuthorResult.tokenUsage.output > 0) Promise.resolve().then(() => addTokenUsage(db, config.pipelineRunId, {
13367
+ phase: "probe-author",
13368
+ agent: "probe-author",
13369
+ input_tokens: probeAuthorResult.tokenUsage.input,
13370
+ output_tokens: probeAuthorResult.tokenUsage.output,
13371
+ cost_usd: estimateDispatchCost(probeAuthorResult.tokenUsage.input, probeAuthorResult.tokenUsage.output),
13372
+ metadata: JSON.stringify({ storyKey })
13373
+ })).catch((tokenErr) => logger$26.warn({
13374
+ storyKey,
13375
+ err: tokenErr
13376
+ }, "Failed to record probe-author token usage"));
13377
+ } else logger$26.debug({ storyKey }, "probe-author: story artifact already has ## Runtime Probes — skipping gate");
13378
+ } else logger$26.debug({ storyKey }, "probe-author: source AC not event-driven — skipping gate");
13379
+ } catch (probeAuthorErr) {
13380
+ logger$26.warn({
13381
+ storyKey,
13382
+ err: probeAuthorErr
13383
+ }, "probe-author gate threw unexpectedly; proceeding to test-plan without authored probes");
13384
+ }
12892
13385
  await waitIfPaused();
12893
13386
  if (_state !== "RUNNING") return;
12894
13387
  startPhase(storyKey, "test-plan");
@@ -12913,10 +13406,10 @@ function createImplementationOrchestrator(deps) {
12913
13406
  });
12914
13407
  testPlanPhaseResult = testPlanResult.result;
12915
13408
  testPlanTokenUsage = testPlanResult.tokenUsage;
12916
- if (testPlanResult.result === "success") logger$24.info({ storyKey }, "Test plan generated successfully");
12917
- else logger$24.warn({ storyKey }, "Test planning returned failed result — proceeding to dev-story without test plan");
13409
+ if (testPlanResult.result === "success") logger$26.info({ storyKey }, "Test plan generated successfully");
13410
+ else logger$26.warn({ storyKey }, "Test planning returned failed result — proceeding to dev-story without test plan");
12918
13411
  } catch (err) {
12919
- logger$24.warn({
13412
+ logger$26.warn({
12920
13413
  storyKey,
12921
13414
  err
12922
13415
  }, "Test planning failed — proceeding to dev-story without test plan");
@@ -12929,7 +13422,7 @@ function createImplementationOrchestrator(deps) {
12929
13422
  output_tokens: testPlanTokenUsage.output,
12930
13423
  cost_usd: estimateDispatchCost(testPlanTokenUsage.input, testPlanTokenUsage.output),
12931
13424
  metadata: JSON.stringify({ storyKey })
12932
- })).catch((tokenErr) => logger$24.warn({
13425
+ })).catch((tokenErr) => logger$26.warn({
12933
13426
  storyKey,
12934
13427
  err: tokenErr
12935
13428
  }, "Failed to record test-plan token usage"));
@@ -12997,7 +13490,7 @@ function createImplementationOrchestrator(deps) {
12997
13490
  storyContentForAnalysis = await readFile$1(storyFilePath ?? "", "utf-8");
12998
13491
  storyContentForVerification = storyContentForAnalysis;
12999
13492
  } catch (err) {
13000
- logger$24.error({
13493
+ logger$26.error({
13001
13494
  storyKey,
13002
13495
  storyFilePath,
13003
13496
  error: err instanceof Error ? err.message : String(err)
@@ -13005,7 +13498,7 @@ function createImplementationOrchestrator(deps) {
13005
13498
  }
13006
13499
  const analysis = analyzeStoryComplexity(storyContentForAnalysis);
13007
13500
  const batches = planTaskBatches(analysis);
13008
- logger$24.info({
13501
+ logger$26.info({
13009
13502
  storyKey,
13010
13503
  estimatedScope: analysis.estimatedScope,
13011
13504
  batchCount: batches.length,
@@ -13023,7 +13516,7 @@ function createImplementationOrchestrator(deps) {
13023
13516
  if (_state !== "RUNNING") break;
13024
13517
  const taskScope = batch.taskIds.map((id, i) => `T${id}: ${batch.taskTitles[i] ?? ""}`).join("\n");
13025
13518
  const priorFiles = allFilesModified.size > 0 ? Array.from(allFilesModified) : void 0;
13026
- logger$24.info({
13519
+ logger$26.info({
13027
13520
  storyKey,
13028
13521
  batchIndex: batch.batchIndex,
13029
13522
  taskCount: batch.taskIds.length
@@ -13054,7 +13547,7 @@ function createImplementationOrchestrator(deps) {
13054
13547
  });
13055
13548
  } catch (batchErr) {
13056
13549
  const errMsg = batchErr instanceof Error ? batchErr.message : String(batchErr);
13057
- logger$24.warn({
13550
+ logger$26.warn({
13058
13551
  storyKey,
13059
13552
  batchIndex: batch.batchIndex,
13060
13553
  error: errMsg
@@ -13075,7 +13568,7 @@ function createImplementationOrchestrator(deps) {
13075
13568
  filesModified: batchFilesModified,
13076
13569
  result: batchResult.result === "success" ? "success" : "failed"
13077
13570
  };
13078
- logger$24.info(batchMetrics, "Batch dev-story metrics");
13571
+ logger$26.info(batchMetrics, "Batch dev-story metrics");
13079
13572
  for (const f$1 of batchFilesModified) allFilesModified.add(f$1);
13080
13573
  if (batchFilesModified.length > 0) batchFileGroups.push({
13081
13574
  batchIndex: batch.batchIndex,
@@ -13094,13 +13587,13 @@ function createImplementationOrchestrator(deps) {
13094
13587
  durationMs: batchDurationMs,
13095
13588
  result: batchMetrics.result
13096
13589
  })
13097
- })).catch((tokenErr) => logger$24.warn({
13590
+ })).catch((tokenErr) => logger$26.warn({
13098
13591
  storyKey,
13099
13592
  batchIndex: batch.batchIndex,
13100
13593
  err: tokenErr
13101
13594
  }, "Failed to record batch token usage"));
13102
13595
  if (batchResult.tokenUsage?.output !== void 0) devOutputTokenCount = (devOutputTokenCount ?? 0) + batchResult.tokenUsage.output;
13103
- if (batchResult.result === "failed") logger$24.warn({
13596
+ if (batchResult.result === "failed") logger$26.warn({
13104
13597
  storyKey,
13105
13598
  batchIndex: batch.batchIndex,
13106
13599
  error: batchResult.error
@@ -13143,7 +13636,7 @@ function createImplementationOrchestrator(deps) {
13143
13636
  output_tokens: devResult.tokenUsage.output,
13144
13637
  cost_usd: estimateDispatchCost(devResult.tokenUsage.input, devResult.tokenUsage.output),
13145
13638
  metadata: JSON.stringify({ storyKey })
13146
- })).catch((tokenErr) => logger$24.warn({
13639
+ })).catch((tokenErr) => logger$26.warn({
13147
13640
  storyKey,
13148
13641
  err: tokenErr
13149
13642
  }, "Failed to record dev-story token usage"));
@@ -13158,7 +13651,7 @@ function createImplementationOrchestrator(deps) {
13158
13651
  endPhase(storyKey, "dev-story");
13159
13652
  const timeoutFiles = checkGitDiffFiles(projectRoot ?? process.cwd());
13160
13653
  if (timeoutFiles.length === 0) {
13161
- logger$24.warn({ storyKey }, "Dev-story timeout with zero modified files — escalating immediately (no checkpoint)");
13654
+ logger$26.warn({ storyKey }, "Dev-story timeout with zero modified files — escalating immediately (no checkpoint)");
13162
13655
  updateStory(storyKey, {
13163
13656
  phase: "ESCALATED",
13164
13657
  error: "timeout-no-files",
@@ -13174,7 +13667,7 @@ function createImplementationOrchestrator(deps) {
13174
13667
  await persistState();
13175
13668
  return;
13176
13669
  }
13177
- logger$24.info({
13670
+ logger$26.info({
13178
13671
  storyKey,
13179
13672
  filesCount: timeoutFiles.length
13180
13673
  }, "Dev-story timeout with partial files — capturing checkpoint");
@@ -13191,7 +13684,7 @@ function createImplementationOrchestrator(deps) {
13191
13684
  ]
13192
13685
  }).trim();
13193
13686
  } catch (diffErr) {
13194
- logger$24.warn({
13687
+ logger$26.warn({
13195
13688
  storyKey,
13196
13689
  error: diffErr instanceof Error ? diffErr.message : String(diffErr)
13197
13690
  }, "Failed to capture git diff for checkpoint — proceeding with empty diff");
@@ -13218,7 +13711,7 @@ function createImplementationOrchestrator(deps) {
13218
13711
  recordedAt: new Date().toISOString(),
13219
13712
  sprint: config.sprint
13220
13713
  }).catch((storeErr) => {
13221
- logger$24.warn({
13714
+ logger$26.warn({
13222
13715
  err: storeErr,
13223
13716
  storyKey
13224
13717
  }, "Failed to record timeout metric to StateStore (best-effort)");
@@ -13277,9 +13770,9 @@ function createImplementationOrchestrator(deps) {
13277
13770
  checkpointRetryPrompt = assembled.prompt;
13278
13771
  } catch {
13279
13772
  checkpointRetryPrompt = `Continue story ${storyKey} from checkpoint. Your prior attempt timed out. Do not redo completed work.`;
13280
- logger$24.warn({ storyKey }, "Failed to assemble checkpoint retry prompt — using fallback");
13773
+ logger$26.warn({ storyKey }, "Failed to assemble checkpoint retry prompt — using fallback");
13281
13774
  }
13282
- logger$24.info({
13775
+ logger$26.info({
13283
13776
  storyKey,
13284
13777
  filesCount: checkpointData.filesModified.length
13285
13778
  }, "Dispatching checkpoint retry for timed-out story");
@@ -13308,7 +13801,7 @@ function createImplementationOrchestrator(deps) {
13308
13801
  } : void 0 }
13309
13802
  });
13310
13803
  if (checkpointRetryResult.status === "timeout") {
13311
- logger$24.warn({ storyKey }, "Checkpoint retry dispatch timed out — escalating story");
13804
+ logger$26.warn({ storyKey }, "Checkpoint retry dispatch timed out — escalating story");
13312
13805
  updateStory(storyKey, {
13313
13806
  phase: "ESCALATED",
13314
13807
  error: "checkpoint-retry-timeout",
@@ -13328,7 +13821,7 @@ function createImplementationOrchestrator(deps) {
13328
13821
  replaceDevStorySignals(retryParsed);
13329
13822
  devFilesModified = retryParsed?.files_modified ?? checkGitDiffFiles(projectRoot ?? process.cwd());
13330
13823
  if (checkpointRetryResult.status === "completed" && retryParsed?.result === "success") devStoryWasSuccess = true;
13331
- else logger$24.warn({
13824
+ else logger$26.warn({
13332
13825
  storyKey,
13333
13826
  status: checkpointRetryResult.status
13334
13827
  }, "Checkpoint retry completed with failure — proceeding to code review");
@@ -13338,13 +13831,13 @@ function createImplementationOrchestrator(deps) {
13338
13831
  replaceDevStorySignals(devResult);
13339
13832
  if (devResult.result === "success") devStoryWasSuccess = true;
13340
13833
  else {
13341
- logger$24.warn({
13834
+ logger$26.warn({
13342
13835
  storyKey,
13343
13836
  error: devResult.error,
13344
13837
  filesModified: devFilesModified.length
13345
13838
  }, "Dev-story reported failure, proceeding to code review");
13346
13839
  if (!devResult.error?.startsWith("dispatch_timeout")) {
13347
- logger$24.warn({
13840
+ logger$26.warn({
13348
13841
  storyKey,
13349
13842
  error: devResult.error
13350
13843
  }, "Agent process failure (non-timeout) — story will proceed to code review with partial work");
@@ -13406,13 +13899,13 @@ function createImplementationOrchestrator(deps) {
13406
13899
  }).trim();
13407
13900
  if (committedFiles.length > 0) gitDiffFiles = committedFiles.split("\n").filter(Boolean);
13408
13901
  } catch {}
13409
- logger$24.info({
13902
+ logger$26.info({
13410
13903
  storyKey,
13411
13904
  baselineHeadSha,
13412
13905
  committedFileCount: gitDiffFiles?.length ?? 0
13413
13906
  }, "Working tree clean but new commits detected since dispatch — skipping zero-diff escalation");
13414
13907
  } else {
13415
- logger$24.warn({ storyKey }, "Zero-diff detected after COMPLETE dev-story — no file changes and no new commits");
13908
+ logger$26.warn({ storyKey }, "Zero-diff detected after COMPLETE dev-story — no file changes and no new commits");
13416
13909
  eventBus.emit("orchestrator:zero-diff-escalation", {
13417
13910
  storyKey,
13418
13911
  reason: "zero-diff-on-complete"
@@ -13462,10 +13955,10 @@ function createImplementationOrchestrator(deps) {
13462
13955
  "pipe"
13463
13956
  ]
13464
13957
  });
13465
- logger$24.info({ storyKey }, "Secondary typecheck (tsc --noEmit) passed");
13958
+ logger$26.info({ storyKey }, "Secondary typecheck (tsc --noEmit) passed");
13466
13959
  } catch (tscErr) {
13467
13960
  const tscOutput = tscErr instanceof Error && "stdout" in tscErr ? String(tscErr.stdout ?? "").slice(0, 2e3) : "";
13468
- logger$24.warn({
13961
+ logger$26.warn({
13469
13962
  storyKey,
13470
13963
  tscOutput
13471
13964
  }, "Secondary typecheck (tsc --noEmit) failed — treating as build failure");
@@ -13480,7 +13973,7 @@ function createImplementationOrchestrator(deps) {
13480
13973
  if (buildVerifyResult.status === "passed") {
13481
13974
  _buildPassed = true;
13482
13975
  eventBus.emit("story:build-verification-passed", { storyKey });
13483
- logger$24.info({ storyKey }, "Build verification passed");
13976
+ logger$26.info({ storyKey }, "Build verification passed");
13484
13977
  } else if (buildVerifyResult.status === "failed" || buildVerifyResult.status === "timeout") {
13485
13978
  const truncatedOutput = (buildVerifyResult.output ?? "").slice(0, 2e3);
13486
13979
  const reason = buildVerifyResult.reason ?? "build-verification-failed";
@@ -13489,7 +13982,7 @@ function createImplementationOrchestrator(deps) {
13489
13982
  const resolvedRoot = projectRoot ?? process.cwd();
13490
13983
  const hasChanges = detectPackageChanges(_packageSnapshot, resolvedRoot);
13491
13984
  if (hasChanges) {
13492
- logger$24.warn({ storyKey }, "Package files changed since snapshot — restoring to prevent cascade");
13985
+ logger$26.warn({ storyKey }, "Package files changed since snapshot — restoring to prevent cascade");
13493
13986
  const restoreResult = restorePackageSnapshot(_packageSnapshot, { projectRoot: resolvedRoot });
13494
13987
  if (restoreResult.restored) {
13495
13988
  const retryAfterRestore = runBuildVerification({
@@ -13502,11 +13995,11 @@ function createImplementationOrchestrator(deps) {
13502
13995
  retryPassed = true;
13503
13996
  _buildPassed = true;
13504
13997
  eventBus.emit("story:build-verification-passed", { storyKey });
13505
- logger$24.warn({
13998
+ logger$26.warn({
13506
13999
  storyKey,
13507
14000
  filesRestored: restoreResult.filesRestored
13508
14001
  }, "Build passed after package snapshot restore — cross-story pollution detected and cleaned");
13509
- } else logger$24.warn({
14002
+ } else logger$26.warn({
13510
14003
  storyKey,
13511
14004
  filesRestored: restoreResult.filesRestored
13512
14005
  }, "Build still fails after snapshot restore — story has its own build errors");
@@ -13518,7 +14011,7 @@ function createImplementationOrchestrator(deps) {
13518
14011
  if (missingPkgMatch && buildVerifyResult.status !== "timeout") {
13519
14012
  const missingPkg = missingPkgMatch[1].replace(/^(@[^/]+\/[^/]+)\/.*$/, "$1").replace(/^([^@][^/]*)\/.*$/, "$1");
13520
14013
  const resolvedRoot = projectRoot ?? process.cwd();
13521
- logger$24.warn({
14014
+ logger$26.warn({
13522
14015
  storyKey,
13523
14016
  missingPkg
13524
14017
  }, "Build-fix retry: detected missing npm package — attempting npm install");
@@ -13529,7 +14022,7 @@ function createImplementationOrchestrator(deps) {
13529
14022
  encoding: "utf-8",
13530
14023
  stdio: "pipe"
13531
14024
  });
13532
- logger$24.warn({
14025
+ logger$26.warn({
13533
14026
  storyKey,
13534
14027
  missingPkg
13535
14028
  }, "Build-fix retry: npm install succeeded — retrying build verification");
@@ -13543,18 +14036,18 @@ function createImplementationOrchestrator(deps) {
13543
14036
  retryPassed = true;
13544
14037
  _buildPassed = true;
13545
14038
  eventBus.emit("story:build-verification-passed", { storyKey });
13546
- logger$24.warn({
14039
+ logger$26.warn({
13547
14040
  storyKey,
13548
14041
  missingPkg
13549
14042
  }, "Build-fix retry: build verification passed after installing missing package");
13550
- } else logger$24.warn({
14043
+ } else logger$26.warn({
13551
14044
  storyKey,
13552
14045
  missingPkg,
13553
14046
  retryStatus: retryResult.status
13554
14047
  }, "Build-fix retry: build still fails after installing missing package — escalating");
13555
14048
  } catch (installErr) {
13556
14049
  const installMsg = installErr instanceof Error ? installErr.message : String(installErr);
13557
- logger$24.warn({
14050
+ logger$26.warn({
13558
14051
  storyKey,
13559
14052
  missingPkg,
13560
14053
  error: installMsg
@@ -13564,7 +14057,7 @@ function createImplementationOrchestrator(deps) {
13564
14057
  if (!retryPassed) {
13565
14058
  let buildFixPassed = false;
13566
14059
  if (buildVerifyResult.status === "failed" && storyFilePath !== void 0) try {
13567
- logger$24.info({ storyKey }, "Dispatching build-fix agent");
14060
+ logger$26.info({ storyKey }, "Dispatching build-fix agent");
13568
14061
  startPhase(storyKey, "build-fix");
13569
14062
  const storyContent = await readFile$1(storyFilePath, "utf-8");
13570
14063
  let buildFixTemplate;
@@ -13601,11 +14094,11 @@ function createImplementationOrchestrator(deps) {
13601
14094
  buildFixPassed = true;
13602
14095
  _buildPassed = true;
13603
14096
  eventBus.emit("story:build-verification-passed", { storyKey });
13604
- logger$24.info({ storyKey }, "Build passed after build-fix dispatch");
13605
- } else logger$24.warn({ storyKey }, "Build still fails after build-fix dispatch — escalating");
14097
+ logger$26.info({ storyKey }, "Build passed after build-fix dispatch");
14098
+ } else logger$26.warn({ storyKey }, "Build still fails after build-fix dispatch — escalating");
13606
14099
  } catch (fixErr) {
13607
14100
  const fixMsg = fixErr instanceof Error ? fixErr.message : String(fixErr);
13608
- logger$24.warn({
14101
+ logger$26.warn({
13609
14102
  storyKey,
13610
14103
  error: fixMsg
13611
14104
  }, "Build-fix dispatch failed — escalating");
@@ -13616,7 +14109,7 @@ function createImplementationOrchestrator(deps) {
13616
14109
  exitCode: buildVerifyResult.exitCode ?? 1,
13617
14110
  output: truncatedOutput
13618
14111
  });
13619
- logger$24.warn({
14112
+ logger$26.warn({
13620
14113
  storyKey,
13621
14114
  reason,
13622
14115
  exitCode: buildVerifyResult.exitCode
@@ -13648,7 +14141,7 @@ function createImplementationOrchestrator(deps) {
13648
14141
  storyKey
13649
14142
  });
13650
14143
  if (icResult.potentiallyAffectedTests.length > 0) {
13651
- logger$24.warn({
14144
+ logger$26.warn({
13652
14145
  storyKey,
13653
14146
  modifiedInterfaces: icResult.modifiedInterfaces,
13654
14147
  potentiallyAffectedTests: icResult.potentiallyAffectedTests
@@ -13729,7 +14222,7 @@ function createImplementationOrchestrator(deps) {
13729
14222
  "NEEDS_MAJOR_REWORK": 2
13730
14223
  };
13731
14224
  for (const group of batchFileGroups) {
13732
- logger$24.info({
14225
+ logger$26.info({
13733
14226
  storyKey,
13734
14227
  batchIndex: group.batchIndex,
13735
14228
  fileCount: group.files.length
@@ -13774,7 +14267,7 @@ function createImplementationOrchestrator(deps) {
13774
14267
  rawOutput: lastRawOutput,
13775
14268
  tokenUsage: aggregateTokens
13776
14269
  };
13777
- logger$24.info({
14270
+ logger$26.info({
13778
14271
  storyKey,
13779
14272
  batchCount: batchFileGroups.length,
13780
14273
  verdict: worstVerdict,
@@ -13817,7 +14310,7 @@ function createImplementationOrchestrator(deps) {
13817
14310
  storyKey,
13818
14311
  reviewCycle: reviewCycles
13819
14312
  })
13820
- })).catch((tokenErr) => logger$24.warn({
14313
+ })).catch((tokenErr) => logger$26.warn({
13821
14314
  storyKey,
13822
14315
  err: tokenErr
13823
14316
  }, "Failed to record code-review token usage"));
@@ -13825,7 +14318,7 @@ function createImplementationOrchestrator(deps) {
13825
14318
  const isPhantomReview = reviewResult.dispatchFailed === true || reviewResult.verdict !== "SHIP_IT" && reviewResult.verdict !== "LGTM_WITH_NOTES" && (reviewResult.issue_list === void 0 || reviewResult.issue_list.length === 0) && reviewResult.error !== void 0;
13826
14319
  if (isPhantomReview && !timeoutRetried) {
13827
14320
  timeoutRetried = true;
13828
- logger$24.warn({
14321
+ logger$26.warn({
13829
14322
  storyKey,
13830
14323
  reviewCycles,
13831
14324
  error: reviewResult.error
@@ -13833,7 +14326,7 @@ function createImplementationOrchestrator(deps) {
13833
14326
  continue;
13834
14327
  }
13835
14328
  if (isPhantomReview && timeoutRetried) {
13836
- logger$24.warn({
14329
+ logger$26.warn({
13837
14330
  storyKey,
13838
14331
  reviewCycles,
13839
14332
  error: reviewResult.error
@@ -13857,7 +14350,7 @@ function createImplementationOrchestrator(deps) {
13857
14350
  verdict = reviewResult.verdict;
13858
14351
  issueList = reviewResult.issue_list ?? [];
13859
14352
  if (verdict === "NEEDS_MAJOR_REWORK" && reviewCycles > 0 && previousIssueList.length > 0 && issueList.length < previousIssueList.length) {
13860
- logger$24.info({
14353
+ logger$26.info({
13861
14354
  storyKey,
13862
14355
  originalVerdict: verdict,
13863
14356
  issuesBefore: previousIssueList.length,
@@ -13893,7 +14386,7 @@ function createImplementationOrchestrator(deps) {
13893
14386
  if (_decomposition !== void 0) parts.push(`decomposed: ${_decomposition.batchCount} batches`);
13894
14387
  parts.push(`${fileCount} files`);
13895
14388
  parts.push(`${totalTokensK} tokens`);
13896
- logger$24.info({
14389
+ logger$26.info({
13897
14390
  storyKey,
13898
14391
  verdict,
13899
14392
  agentVerdict: reviewResult.agentVerdict
@@ -13950,7 +14443,7 @@ function createImplementationOrchestrator(deps) {
13950
14443
  phase: "VERIFICATION_FAILED",
13951
14444
  completedAt: new Date().toISOString()
13952
14445
  });
13953
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$24.warn({
14446
+ persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
13954
14447
  err,
13955
14448
  storyKey
13956
14449
  }, "StateStore write failed after verification-failed"));
@@ -13964,7 +14457,7 @@ function createImplementationOrchestrator(deps) {
13964
14457
  completedAt: new Date().toISOString()
13965
14458
  });
13966
14459
  if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
13967
- if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$24.warn({
14460
+ if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
13968
14461
  storyKey,
13969
14462
  category: "verification-result-missing"
13970
14463
  }, "post-COMPLETE invariant: verification_result absent in manifest");
@@ -13989,9 +14482,9 @@ function createImplementationOrchestrator(deps) {
13989
14482
  }),
13990
14483
  rationale: `Advisory notes from LGTM_WITH_NOTES review of ${storyKey}`
13991
14484
  });
13992
- logger$24.info({ storyKey }, "Advisory notes persisted to decision store");
14485
+ logger$26.info({ storyKey }, "Advisory notes persisted to decision store");
13993
14486
  } catch (advisoryErr) {
13994
- logger$24.warn({
14487
+ logger$26.warn({
13995
14488
  storyKey,
13996
14489
  error: advisoryErr instanceof Error ? advisoryErr.message : String(advisoryErr)
13997
14490
  }, "Failed to persist advisory notes (best-effort)");
@@ -13999,27 +14492,27 @@ function createImplementationOrchestrator(deps) {
13999
14492
  if (telemetryPersistence !== void 0) try {
14000
14493
  const turns = await telemetryPersistence.getTurnAnalysis(storyKey);
14001
14494
  if (turns.length > 0) {
14002
- const scorer = new EfficiencyScorer(logger$24);
14495
+ const scorer = new EfficiencyScorer(logger$26);
14003
14496
  const effScore = scorer.score(storyKey, turns);
14004
14497
  await telemetryPersistence.storeEfficiencyScore(effScore);
14005
- logger$24.info({
14498
+ logger$26.info({
14006
14499
  storyKey,
14007
14500
  compositeScore: effScore.compositeScore,
14008
14501
  modelCount: effScore.perModelBreakdown.length
14009
14502
  }, "Efficiency score computed and persisted");
14010
- } else logger$24.debug({ storyKey }, "No turn analysis data available — skipping efficiency scoring");
14503
+ } else logger$26.debug({ storyKey }, "No turn analysis data available — skipping efficiency scoring");
14011
14504
  } catch (effErr) {
14012
- logger$24.warn({
14505
+ logger$26.warn({
14013
14506
  storyKey,
14014
14507
  error: effErr instanceof Error ? effErr.message : String(effErr)
14015
14508
  }, "Efficiency scoring failed — story verdict unchanged");
14016
14509
  }
14017
14510
  if (telemetryPersistence !== void 0) try {
14018
14511
  const turns = await telemetryPersistence.getTurnAnalysis(storyKey);
14019
- if (turns.length === 0) logger$24.debug({ storyKey }, "No turn analysis data for telemetry categorization — skipping");
14512
+ if (turns.length === 0) logger$26.debug({ storyKey }, "No turn analysis data for telemetry categorization — skipping");
14020
14513
  else {
14021
- const categorizer = new Categorizer(logger$24);
14022
- const consumerAnalyzer = new ConsumerAnalyzer(categorizer, logger$24);
14514
+ const categorizer = new Categorizer(logger$26);
14515
+ const consumerAnalyzer = new ConsumerAnalyzer(categorizer, logger$26);
14023
14516
  const categoryStats = categorizer.computeCategoryStatsFromTurns(turns);
14024
14517
  const consumerStats = consumerAnalyzer.analyzeFromTurns(turns);
14025
14518
  await telemetryPersistence.storeCategoryStats(storyKey, categoryStats);
@@ -14027,7 +14520,7 @@ function createImplementationOrchestrator(deps) {
14027
14520
  const growingCount = categoryStats.filter((c) => c.trend === "growing").length;
14028
14521
  const topCategory = categoryStats[0]?.category ?? "none";
14029
14522
  const topConsumer = consumerStats[0]?.consumerKey ?? "none";
14030
- logger$24.info({
14523
+ logger$26.info({
14031
14524
  storyKey,
14032
14525
  topCategory,
14033
14526
  topConsumer,
@@ -14035,7 +14528,7 @@ function createImplementationOrchestrator(deps) {
14035
14528
  }, "Semantic categorization and consumer analysis complete");
14036
14529
  }
14037
14530
  } catch (catErr) {
14038
- logger$24.warn({
14531
+ logger$26.warn({
14039
14532
  storyKey,
14040
14533
  error: catErr instanceof Error ? catErr.message : String(catErr)
14041
14534
  }, "Semantic categorization failed — story verdict unchanged");
@@ -14057,7 +14550,7 @@ function createImplementationOrchestrator(deps) {
14057
14550
  filesModified: devFilesModified,
14058
14551
  workingDirectory: projectRoot
14059
14552
  });
14060
- logger$24.debug({
14553
+ logger$26.debug({
14061
14554
  storyKey,
14062
14555
  expansion_priority: expansionResult.expansion_priority,
14063
14556
  coverage_gaps: expansionResult.coverage_gaps.length
@@ -14070,7 +14563,7 @@ function createImplementationOrchestrator(deps) {
14070
14563
  value: JSON.stringify(expansionResult)
14071
14564
  });
14072
14565
  } catch (expansionErr) {
14073
- logger$24.warn({
14566
+ logger$26.warn({
14074
14567
  storyKey,
14075
14568
  error: expansionErr instanceof Error ? expansionErr.message : String(expansionErr)
14076
14569
  }, "Test expansion failed — story verdict unchanged");
@@ -14097,7 +14590,7 @@ function createImplementationOrchestrator(deps) {
14097
14590
  await persistState();
14098
14591
  return;
14099
14592
  }
14100
- logger$24.info({
14593
+ logger$26.info({
14101
14594
  storyKey,
14102
14595
  reviewCycles: finalReviewCycles,
14103
14596
  issueCount: issueList.length
@@ -14163,7 +14656,7 @@ function createImplementationOrchestrator(deps) {
14163
14656
  fixPrompt = assembled.prompt;
14164
14657
  } catch {
14165
14658
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, minor fixes needed`;
14166
- logger$24.warn({ storyKey }, "Failed to assemble auto-approve fix prompt, using fallback");
14659
+ logger$26.warn({ storyKey }, "Failed to assemble auto-approve fix prompt, using fallback");
14167
14660
  }
14168
14661
  const handle = dispatcher.dispatch({
14169
14662
  prompt: fixPrompt,
@@ -14184,9 +14677,9 @@ function createImplementationOrchestrator(deps) {
14184
14677
  output: fixResult.tokenEstimate.output
14185
14678
  } : void 0 }
14186
14679
  });
14187
- if (fixResult.status === "timeout") logger$24.warn({ storyKey }, "Auto-approve fix timed out — approving anyway (issues were minor)");
14680
+ if (fixResult.status === "timeout") logger$26.warn({ storyKey }, "Auto-approve fix timed out — approving anyway (issues were minor)");
14188
14681
  } catch (err) {
14189
- logger$24.warn({
14682
+ logger$26.warn({
14190
14683
  storyKey,
14191
14684
  err
14192
14685
  }, "Auto-approve fix dispatch failed — approving anyway (issues were minor)");
@@ -14223,7 +14716,7 @@ function createImplementationOrchestrator(deps) {
14223
14716
  phase: "VERIFICATION_FAILED",
14224
14717
  completedAt: new Date().toISOString()
14225
14718
  });
14226
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$24.warn({
14719
+ persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
14227
14720
  err,
14228
14721
  storyKey
14229
14722
  }, "StateStore write failed after verification-failed"));
@@ -14246,7 +14739,7 @@ function createImplementationOrchestrator(deps) {
14246
14739
  completedAt: new Date().toISOString()
14247
14740
  });
14248
14741
  if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
14249
- if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$24.warn({
14742
+ if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
14250
14743
  storyKey,
14251
14744
  category: "verification-result-missing"
14252
14745
  }, "post-COMPLETE invariant: verification_result absent in manifest");
@@ -14271,7 +14764,7 @@ function createImplementationOrchestrator(deps) {
14271
14764
  outcome: "retried",
14272
14765
  cost_usd: 0,
14273
14766
  timestamp: new Date().toISOString()
14274
- }).catch((err) => logger$24.warn({
14767
+ }).catch((err) => logger$26.warn({
14275
14768
  err,
14276
14769
  storyKey
14277
14770
  }, "appendRecoveryEntry failed — pipeline continues"));
@@ -14411,7 +14904,7 @@ function createImplementationOrchestrator(deps) {
14411
14904
  fixPrompt = assembled.prompt;
14412
14905
  } catch {
14413
14906
  fixPrompt = `Fix story ${storyKey}: verdict=${verdict}, taskType=${taskType}`;
14414
- logger$24.warn({
14907
+ logger$26.warn({
14415
14908
  storyKey,
14416
14909
  taskType
14417
14910
  }, "Failed to assemble fix prompt, using fallback");
@@ -14448,7 +14941,86 @@ function createImplementationOrchestrator(deps) {
14448
14941
  } : void 0 }
14449
14942
  });
14450
14943
  if (fixResult.status === "timeout") {
14451
- logger$24.warn({
14944
+ if (taskType === "minor-fixes") {
14945
+ const finalReviewCycles = reviewCycles + 1;
14946
+ const downgradedVerdict = "LGTM_WITH_NOTES";
14947
+ logger$26.warn({
14948
+ storyKey,
14949
+ reviewCycles: finalReviewCycles,
14950
+ issueCount: issueList.length
14951
+ }, "Minor-fixes dispatch timed out — auto-approving as LGTM_WITH_NOTES (original findings retained as warnings)");
14952
+ endPhase(storyKey, "code-review");
14953
+ if (config.skipVerification !== true) {
14954
+ const latestReviewSignals = reviewResult != null ? {
14955
+ dispatchFailed: reviewResult.dispatchFailed,
14956
+ error: reviewResult.error,
14957
+ rawOutput: reviewResult.rawOutput
14958
+ } : void 0;
14959
+ let sourceEpicContent3;
14960
+ const epicsPath3 = findEpicFileForStory(projectRoot ?? process.cwd(), storyKey);
14961
+ if (epicsPath3) try {
14962
+ const epicFull3 = readFileSync(epicsPath3, "utf-8");
14963
+ const section3 = extractStorySection(epicFull3, storyKey);
14964
+ if (section3) sourceEpicContent3 = section3;
14965
+ } catch {}
14966
+ await persistDevStorySignals(storyKey, devStorySignals, runManifest);
14967
+ const verifContext = assembleVerificationContext({
14968
+ storyKey,
14969
+ workingDir: projectRoot ?? process.cwd(),
14970
+ reviewResult: latestReviewSignals,
14971
+ storyContent: storyContentForVerification,
14972
+ devStoryResult: devStorySignals,
14973
+ outputTokenCount: devOutputTokenCount,
14974
+ sourceEpicContent: sourceEpicContent3
14975
+ });
14976
+ const verifSummary = await verificationPipeline.run(verifContext, "A");
14977
+ verificationStore.set(storyKey, verifSummary);
14978
+ await persistVerificationResult(storyKey, verifSummary, runManifest);
14979
+ if (verifSummary.status === "fail") {
14980
+ updateStory(storyKey, {
14981
+ phase: "VERIFICATION_FAILED",
14982
+ completedAt: new Date().toISOString()
14983
+ });
14984
+ persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$26.warn({
14985
+ err,
14986
+ storyKey
14987
+ }, "StateStore write failed after verification-failed"));
14988
+ await writeStoryMetricsBestEffort(storyKey, "verification-failed", finalReviewCycles);
14989
+ await persistState();
14990
+ return;
14991
+ }
14992
+ }
14993
+ eventBus.emit("story:auto-approved", {
14994
+ storyKey,
14995
+ verdict: downgradedVerdict,
14996
+ reviewCycles: finalReviewCycles,
14997
+ maxReviewCycles: config.maxReviewCycles,
14998
+ issueCount: issueList.length,
14999
+ reason: `Minor-fixes dispatch timed out (cycle ${finalReviewCycles}) — auto-approving as LGTM_WITH_NOTES with original findings retained as warnings`
15000
+ });
15001
+ updateStory(storyKey, {
15002
+ phase: "COMPLETE",
15003
+ reviewCycles: finalReviewCycles,
15004
+ lastVerdict: downgradedVerdict,
15005
+ completedAt: new Date().toISOString()
15006
+ });
15007
+ if (config.skipVerification !== true && runManifest != null) Promise.resolve().then(() => runManifest.read()).then((manifest) => {
15008
+ if (manifest?.per_story_state?.[storyKey]?.verification_result == null) logger$26.warn({
15009
+ storyKey,
15010
+ category: "verification-result-missing"
15011
+ }, "post-COMPLETE invariant: verification_result absent in manifest");
15012
+ }).catch(() => {});
15013
+ await writeStoryMetricsBestEffort(storyKey, downgradedVerdict, finalReviewCycles);
15014
+ await writeStoryOutcomeBestEffort(storyKey, "complete", finalReviewCycles);
15015
+ eventBus.emit("orchestrator:story-complete", {
15016
+ storyKey,
15017
+ reviewCycles: finalReviewCycles
15018
+ });
15019
+ await persistState();
15020
+ keepReviewing = false;
15021
+ return;
15022
+ }
15023
+ logger$26.warn({
14452
15024
  storyKey,
14453
15025
  taskType
14454
15026
  }, "Fix dispatch timed out — escalating story");
@@ -14470,7 +15042,7 @@ function createImplementationOrchestrator(deps) {
14470
15042
  }
14471
15043
  if (fixResult.status === "failed") {
14472
15044
  if (isMajorRework) {
14473
- logger$24.warn({
15045
+ logger$26.warn({
14474
15046
  storyKey,
14475
15047
  exitCode: fixResult.exitCode
14476
15048
  }, "Major rework dispatch failed — escalating story");
@@ -14490,7 +15062,7 @@ function createImplementationOrchestrator(deps) {
14490
15062
  await persistState();
14491
15063
  return;
14492
15064
  }
14493
- logger$24.warn({
15065
+ logger$26.warn({
14494
15066
  storyKey,
14495
15067
  taskType,
14496
15068
  exitCode: fixResult.exitCode
@@ -14498,7 +15070,7 @@ function createImplementationOrchestrator(deps) {
14498
15070
  }
14499
15071
  if (isMajorRework) replaceDevStorySignals(fixResult.parsed);
14500
15072
  } catch (err) {
14501
- logger$24.warn({
15073
+ logger$26.warn({
14502
15074
  storyKey,
14503
15075
  taskType,
14504
15076
  err
@@ -14549,7 +15121,7 @@ function createImplementationOrchestrator(deps) {
14549
15121
  ...haltOn !== "none" ? { severity: "critical" } : {}
14550
15122
  });
14551
15123
  _budgetExhausted = true;
14552
- logger$24.warn({
15124
+ logger$26.warn({
14553
15125
  skipped: allSkipped.length,
14554
15126
  cumulative: result.cumulative,
14555
15127
  ceiling: result.ceiling
@@ -14566,7 +15138,7 @@ function createImplementationOrchestrator(deps) {
14566
15138
  const completedStoryKeys = [];
14567
15139
  for (const storyKey of group) {
14568
15140
  if (_shutdownRequested) {
14569
- logger$24.info({ storyKey }, "shutdown requested — skipping dispatch");
15141
+ logger$26.info({ storyKey }, "shutdown requested — skipping dispatch");
14570
15142
  return;
14571
15143
  }
14572
15144
  if (runManifest !== null && runManifest !== void 0) try {
@@ -14589,7 +15161,7 @@ function createImplementationOrchestrator(deps) {
14589
15161
  }
14590
15162
  }
14591
15163
  } catch (err) {
14592
- logger$24.debug({ err }, "Cost ceiling check failed — proceeding without enforcement");
15164
+ logger$26.debug({ err }, "Cost ceiling check failed — proceeding without enforcement");
14593
15165
  }
14594
15166
  let optimizationDirectives;
14595
15167
  if (telemetryAdvisor !== void 0 && completedStoryKeys.length > 0) try {
@@ -14597,13 +15169,13 @@ function createImplementationOrchestrator(deps) {
14597
15169
  const directives = telemetryAdvisor.formatOptimizationDirectives(recs);
14598
15170
  if (directives.length > 0) {
14599
15171
  optimizationDirectives = directives;
14600
- logger$24.debug({
15172
+ logger$26.debug({
14601
15173
  storyKey,
14602
15174
  directiveCount: recs.filter((r) => r.severity !== "info").length
14603
15175
  }, "Optimization directives ready for dispatch");
14604
15176
  }
14605
15177
  } catch (err) {
14606
- logger$24.debug({
15178
+ logger$26.debug({
14607
15179
  err,
14608
15180
  storyKey
14609
15181
  }, "Failed to fetch optimization directives — proceeding without");
@@ -14658,7 +15230,7 @@ function createImplementationOrchestrator(deps) {
14658
15230
  async function shutdownGracefully(reason, signal) {
14659
15231
  if (_shutdownRequested) return;
14660
15232
  _shutdownRequested = true;
14661
- logger$24.info({
15233
+ logger$26.info({
14662
15234
  reason,
14663
15235
  signal
14664
15236
  }, "Graceful shutdown initiated — stopping new dispatches");
@@ -14668,8 +15240,8 @@ function createImplementationOrchestrator(deps) {
14668
15240
  run_status: "stopped",
14669
15241
  stopped_reason: reason,
14670
15242
  stopped_at: new Date().toISOString()
14671
- }).catch((err) => logger$24.warn({ err }, "patchRunStatus failed during shutdown (best-effort)"));
14672
- if (config.pipelineRunId !== void 0) await updatePipelineRun(db, config.pipelineRunId, { status: "stopped" }).catch((err) => logger$24.warn({ err }, "updatePipelineRun(stopped) failed during shutdown (best-effort)"));
15243
+ }).catch((err) => logger$26.warn({ err }, "patchRunStatus failed during shutdown (best-effort)"));
15244
+ if (config.pipelineRunId !== void 0) await updatePipelineRun(db, config.pipelineRunId, { status: "stopped" }).catch((err) => logger$26.warn({ err }, "updatePipelineRun(stopped) failed during shutdown (best-effort)"));
14673
15245
  const activePhases = [
14674
15246
  "PENDING",
14675
15247
  "IN_STORY_CREATION",
@@ -14680,7 +15252,7 @@ function createImplementationOrchestrator(deps) {
14680
15252
  "CHECKPOINT"
14681
15253
  ];
14682
15254
  const cancellations = [];
14683
- for (const [storyKey, state] of _stories.entries()) if (activePhases.includes(state.phase)) cancellations.push(wgRepo.updateStoryStatus(storyKey, "cancelled").catch((err) => logger$24.warn({
15255
+ for (const [storyKey, state] of _stories.entries()) if (activePhases.includes(state.phase)) cancellations.push(wgRepo.updateStoryStatus(storyKey, "cancelled").catch((err) => logger$26.warn({
14684
15256
  err,
14685
15257
  storyKey
14686
15258
  }, "wg_stories → cancelled failed during shutdown (best-effort)")));
@@ -14689,11 +15261,11 @@ function createImplementationOrchestrator(deps) {
14689
15261
  }
14690
15262
  async function run(storyKeys) {
14691
15263
  if (_state === "RUNNING" || _state === "PAUSED") {
14692
- logger$24.warn({ state: _state }, "run() called while orchestrator is already running or paused — ignoring");
15264
+ logger$26.warn({ state: _state }, "run() called while orchestrator is already running or paused — ignoring");
14693
15265
  return getStatus();
14694
15266
  }
14695
15267
  if (_state === "COMPLETE") {
14696
- logger$24.warn({ state: _state }, "run() called on a COMPLETE orchestrator — ignoring");
15268
+ logger$26.warn({ state: _state }, "run() called on a COMPLETE orchestrator — ignoring");
14697
15269
  return getStatus();
14698
15270
  }
14699
15271
  _state = "RUNNING";
@@ -14717,7 +15289,7 @@ function createImplementationOrchestrator(deps) {
14717
15289
  const seedStart = Date.now();
14718
15290
  const seedResult = await seedMethodologyContext(db, projectRoot);
14719
15291
  _startupTimings.seedMethodologyMs = Date.now() - seedStart;
14720
- if (seedResult.decisionsCreated > 0) logger$24.info({
15292
+ if (seedResult.decisionsCreated > 0) logger$26.info({
14721
15293
  decisionsCreated: seedResult.decisionsCreated,
14722
15294
  skippedCategories: seedResult.skippedCategories,
14723
15295
  durationMs: _startupTimings.seedMethodologyMs
@@ -14727,12 +15299,12 @@ function createImplementationOrchestrator(deps) {
14727
15299
  const ingestStart = Date.now();
14728
15300
  try {
14729
15301
  const ingestResult = await autoIngestEpicsDependencies(db, projectRoot);
14730
- if (ingestResult.storiesIngested > 0 || ingestResult.dependenciesIngested > 0) logger$24.info({
15302
+ if (ingestResult.storiesIngested > 0 || ingestResult.dependenciesIngested > 0) logger$26.info({
14731
15303
  ...ingestResult,
14732
15304
  durationMs: Date.now() - ingestStart
14733
15305
  }, "Auto-ingested stories and dependencies from epics document");
14734
15306
  } catch (err) {
14735
- logger$24.debug({ err }, "Auto-ingest from epics document skipped — work graph may be unavailable");
15307
+ logger$26.debug({ err }, "Auto-ingest from epics document skipped — work graph may be unavailable");
14736
15308
  }
14737
15309
  }
14738
15310
  const sigtermHandler = () => {
@@ -14750,7 +15322,7 @@ function createImplementationOrchestrator(deps) {
14750
15322
  _startupTimings.stateStoreInitMs = Date.now() - stateStoreInitStart;
14751
15323
  for (const key of storyKeys) {
14752
15324
  const pendingState = _stories.get(key);
14753
- if (pendingState !== void 0) persistStoryState(key, pendingState).catch((err) => logger$24.warn({
15325
+ if (pendingState !== void 0) persistStoryState(key, pendingState).catch((err) => logger$26.warn({
14754
15326
  err,
14755
15327
  storyKey: key
14756
15328
  }, "StateStore write failed during PENDING init"));
@@ -14761,12 +15333,12 @@ function createImplementationOrchestrator(deps) {
14761
15333
  _startupTimings.queryStoriesMs = Date.now() - queryStoriesStart;
14762
15334
  for (const record of existingRecords) _stateStoreCache.set(record.storyKey, record);
14763
15335
  } catch (err) {
14764
- logger$24.warn({ err }, "StateStore.queryStories() failed during init — status merge will be empty (best-effort)");
15336
+ logger$26.warn({ err }, "StateStore.queryStories() failed during init — status merge will be empty (best-effort)");
14765
15337
  }
14766
15338
  }
14767
15339
  if (ingestionServer !== void 0) {
14768
15340
  if (telemetryPersistence !== void 0) try {
14769
- const pipelineLogger = logger$24;
15341
+ const pipelineLogger = logger$26;
14770
15342
  const telemetryPipeline = new TelemetryPipeline({
14771
15343
  normalizer: new TelemetryNormalizer(pipelineLogger),
14772
15344
  turnAnalyzer: new TurnAnalyzer(pipelineLogger),
@@ -14778,14 +15350,14 @@ function createImplementationOrchestrator(deps) {
14778
15350
  persistence: telemetryPersistence
14779
15351
  });
14780
15352
  ingestionServer.setPipeline(telemetryPipeline);
14781
- logger$24.info("TelemetryPipeline wired to IngestionServer");
15353
+ logger$26.info("TelemetryPipeline wired to IngestionServer");
14782
15354
  } catch (pipelineErr) {
14783
- logger$24.warn({ err: pipelineErr }, "Failed to create TelemetryPipeline — continuing without analysis pipeline");
15355
+ logger$26.warn({ err: pipelineErr }, "Failed to create TelemetryPipeline — continuing without analysis pipeline");
14784
15356
  }
14785
- await ingestionServer.start().catch((err) => logger$24.warn({ err }, "IngestionServer.start() failed — continuing without telemetry (best-effort)"));
15357
+ await ingestionServer.start().catch((err) => logger$26.warn({ err }, "IngestionServer.start() failed — continuing without telemetry (best-effort)"));
14786
15358
  try {
14787
15359
  _otlpEndpoint = ingestionServer.getOtlpEnvVars().OTEL_EXPORTER_OTLP_ENDPOINT;
14788
- logger$24.info({ otlpEndpoint: _otlpEndpoint }, "OTLP telemetry ingestion active");
15360
+ logger$26.info({ otlpEndpoint: _otlpEndpoint }, "OTLP telemetry ingestion active");
14789
15361
  } catch {}
14790
15362
  }
14791
15363
  let contractDeclarations = [];
@@ -14825,12 +15397,12 @@ function createImplementationOrchestrator(deps) {
14825
15397
  const conflictDetectStart = Date.now();
14826
15398
  const { batches, edges: contractEdges } = detectConflictGroupsWithContracts(storyKeys, { moduleMap: pack.manifest.conflictGroups }, contractDeclarations);
14827
15399
  _startupTimings.conflictDetectMs = Date.now() - conflictDetectStart;
14828
- if (contractEdges.length > 0) logger$24.info({
15400
+ if (contractEdges.length > 0) logger$26.info({
14829
15401
  contractEdges,
14830
15402
  edgeCount: contractEdges.length
14831
15403
  }, "Contract dependency edges detected — applying contract-aware dispatch ordering");
14832
- wgRepo.addContractDependencies(contractEdges).catch((err) => logger$24.warn({ err }, "contract dep persistence failed (best-effort)"));
14833
- logger$24.info({
15404
+ wgRepo.addContractDependencies(contractEdges).catch((err) => logger$26.warn({ err }, "contract dep persistence failed (best-effort)"));
15405
+ logger$26.info({
14834
15406
  storyCount: storyKeys.length,
14835
15407
  groupCount: batches.reduce((sum, b) => sum + b.length, 0),
14836
15408
  batchCount: batches.length,
@@ -14840,7 +15412,7 @@ function createImplementationOrchestrator(deps) {
14840
15412
  groups: batch.map((g) => g.join(","))
14841
15413
  }))
14842
15414
  }, "Orchestrator starting");
14843
- logger$24.info({
15415
+ logger$26.info({
14844
15416
  storyCount: storyKeys.length,
14845
15417
  conflictGroups: batches.length,
14846
15418
  maxConcurrency: config.maxConcurrency
@@ -14861,7 +15433,7 @@ function createImplementationOrchestrator(deps) {
14861
15433
  exitCode,
14862
15434
  output: truncatedOutput
14863
15435
  });
14864
- logger$24.error({
15436
+ logger$26.error({
14865
15437
  exitCode,
14866
15438
  reason: preFlightResult.reason
14867
15439
  }, "Pre-flight build check failed — aborting pipeline before any story dispatch");
@@ -14870,19 +15442,19 @@ function createImplementationOrchestrator(deps) {
14870
15442
  await persistState();
14871
15443
  return getStatus();
14872
15444
  }
14873
- if (preFlightResult.status !== "skipped") logger$24.info("Pre-flight build check passed");
15445
+ if (preFlightResult.status !== "skipped") logger$26.info("Pre-flight build check passed");
14874
15446
  }
14875
- logger$24.info(_startupTimings, "Orchestrator startup timings (ms)");
15447
+ logger$26.info(_startupTimings, "Orchestrator startup timings (ms)");
14876
15448
  const totalGroups = batches.reduce((sum, b) => sum + b.length, 0);
14877
15449
  const actualConcurrency = Math.min(config.maxConcurrency, totalGroups);
14878
15450
  if (actualConcurrency > 1 && projectRoot !== void 0) try {
14879
15451
  _packageSnapshot = capturePackageSnapshot({ projectRoot });
14880
- logger$24.info({
15452
+ logger$26.info({
14881
15453
  fileCount: _packageSnapshot.files.size,
14882
15454
  installCommand: _packageSnapshot.installCommand
14883
15455
  }, "Package snapshot captured for concurrent story protection");
14884
15456
  } catch (snapErr) {
14885
- logger$24.warn({ err: snapErr }, "Failed to capture package snapshot — continuing without protection");
15457
+ logger$26.warn({ err: snapErr }, "Failed to capture package snapshot — continuing without protection");
14886
15458
  }
14887
15459
  try {
14888
15460
  for (const batchGroups of batches) await runWithConcurrency(batchGroups, config.maxConcurrency);
@@ -14891,7 +15463,7 @@ function createImplementationOrchestrator(deps) {
14891
15463
  _state = "FAILED";
14892
15464
  _completedAt = new Date().toISOString();
14893
15465
  await persistState();
14894
- logger$24.error({ err }, "Orchestrator failed with unhandled error");
15466
+ logger$26.error({ err }, "Orchestrator failed with unhandled error");
14895
15467
  return getStatus();
14896
15468
  }
14897
15469
  stopHeartbeat();
@@ -14901,7 +15473,7 @@ function createImplementationOrchestrator(deps) {
14901
15473
  const totalDeclarations = contractDeclarations.length;
14902
15474
  const currentSprintDeclarations = contractDeclarations.filter((d) => storyKeys.includes(d.storyKey));
14903
15475
  const stalePruned = totalDeclarations - currentSprintDeclarations.length;
14904
- if (stalePruned > 0) logger$24.info({
15476
+ if (stalePruned > 0) logger$26.info({
14905
15477
  stalePruned,
14906
15478
  remaining: currentSprintDeclarations.length
14907
15479
  }, "Pruned stale contract declarations from previous epics");
@@ -14915,11 +15487,11 @@ function createImplementationOrchestrator(deps) {
14915
15487
  contractName: mismatch.contractName,
14916
15488
  mismatchDescription: mismatch.mismatchDescription
14917
15489
  });
14918
- logger$24.warn({
15490
+ logger$26.warn({
14919
15491
  mismatchCount: mismatches.length,
14920
15492
  mismatches
14921
15493
  }, "Post-sprint contract verification found mismatches — manual review required");
14922
- } else if (currentSprintDeclarations.length > 0) logger$24.info("Post-sprint contract verification passed — all declared contracts satisfied");
15494
+ } else if (currentSprintDeclarations.length > 0) logger$26.info("Post-sprint contract verification passed — all declared contracts satisfied");
14923
15495
  eventBus.emit("pipeline:contract-verification-summary", {
14924
15496
  verified: currentSprintDeclarations.length,
14925
15497
  stalePruned,
@@ -14954,12 +15526,12 @@ function createImplementationOrchestrator(deps) {
14954
15526
  });
14955
15527
  await stateStore.setContractVerification(sk, records);
14956
15528
  }
14957
- logger$24.info({ storyCount: contractsByStory.size }, "Contract verification results persisted to StateStore");
15529
+ logger$26.info({ storyCount: contractsByStory.size }, "Contract verification results persisted to StateStore");
14958
15530
  } catch (persistErr) {
14959
- logger$24.warn({ err: persistErr }, "Failed to persist contract verification results to StateStore");
15531
+ logger$26.warn({ err: persistErr }, "Failed to persist contract verification results to StateStore");
14960
15532
  }
14961
15533
  } catch (err) {
14962
- logger$24.error({ err }, "Post-sprint contract verification threw an error — skipping");
15534
+ logger$26.error({ err }, "Post-sprint contract verification threw an error — skipping");
14963
15535
  }
14964
15536
  if (projectRoot !== void 0) try {
14965
15537
  const indicators = checkProfileStaleness(projectRoot);
@@ -14969,10 +15541,10 @@ function createImplementationOrchestrator(deps) {
14969
15541
  message,
14970
15542
  indicators
14971
15543
  });
14972
- logger$24.warn({ indicators }, message);
15544
+ logger$26.warn({ indicators }, message);
14973
15545
  }
14974
15546
  } catch (err) {
14975
- logger$24.debug({ err }, "Profile staleness check failed (best-effort)");
15547
+ logger$26.debug({ err }, "Profile staleness check failed (best-effort)");
14976
15548
  }
14977
15549
  let completed = 0;
14978
15550
  let escalated = 0;
@@ -14991,8 +15563,8 @@ function createImplementationOrchestrator(deps) {
14991
15563
  } finally {
14992
15564
  process.off("SIGTERM", sigtermHandler);
14993
15565
  process.off("SIGINT", sigintHandler);
14994
- if (stateStore !== void 0) await stateStore.close().catch((err) => logger$24.warn({ err }, "StateStore.close() failed (best-effort)"));
14995
- if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$24.warn({ err }, "IngestionServer.stop() failed (best-effort)"));
15566
+ if (stateStore !== void 0) await stateStore.close().catch((err) => logger$26.warn({ err }, "StateStore.close() failed (best-effort)"));
15567
+ if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$26.warn({ err }, "IngestionServer.stop() failed (best-effort)"));
14996
15568
  }
14997
15569
  }
14998
15570
  function pause() {
@@ -15001,7 +15573,7 @@ function createImplementationOrchestrator(deps) {
15001
15573
  _pauseGate = createPauseGate();
15002
15574
  _state = "PAUSED";
15003
15575
  eventBus.emit("orchestrator:paused", {});
15004
- logger$24.info("Orchestrator paused");
15576
+ logger$26.info("Orchestrator paused");
15005
15577
  }
15006
15578
  function resume() {
15007
15579
  if (_state !== "PAUSED") return;
@@ -15012,7 +15584,7 @@ function createImplementationOrchestrator(deps) {
15012
15584
  }
15013
15585
  _state = "RUNNING";
15014
15586
  eventBus.emit("orchestrator:resumed", {});
15015
- logger$24.info("Orchestrator resumed");
15587
+ logger$26.info("Orchestrator resumed");
15016
15588
  }
15017
15589
  return {
15018
15590
  run,
@@ -16428,8 +17000,8 @@ async function resolveContext(ref, deps, runId, params, stepOutputs) {
16428
17000
  return params[key] ?? "";
16429
17001
  }
16430
17002
  if (source.startsWith("decision:")) {
16431
- const path$3 = source.slice(9);
16432
- const [phase, category] = path$3.split(".");
17003
+ const path$4 = source.slice(9);
17004
+ const [phase, category] = path$4.split(".");
16433
17005
  if (!phase || !category) return "";
16434
17006
  const decisions = await getDecisionsByPhaseForRun(deps.db, runId, phase);
16435
17007
  const filtered = decisions.filter((d) => d.category === category);
@@ -16500,8 +17072,8 @@ async function runSteps(steps, deps, runId, phase, params) {
16500
17072
  for (const ref of step.context) {
16501
17073
  let value;
16502
17074
  if (ref.source.startsWith("decision:")) {
16503
- const path$3 = ref.source.slice(9);
16504
- const [decPhase, decCategory] = path$3.split(".");
17075
+ const path$4 = ref.source.slice(9);
17076
+ const [decPhase, decCategory] = path$4.split(".");
16505
17077
  if (decPhase && decCategory) {
16506
17078
  const decisions = await getDecisionsByPhaseForRun(deps.db, runId, decPhase);
16507
17079
  const filtered = decisions.filter((d) => d.category === decCategory);
@@ -27548,8 +28120,8 @@ var require_uri_all = __commonJS({ "node_modules/uri-js/dist/es5/uri.all.js"(exp
27548
28120
  wsComponents.secure = void 0;
27549
28121
  }
27550
28122
  if (wsComponents.resourceName) {
27551
- var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path$3 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
27552
- wsComponents.path = path$3 && path$3 !== "/" ? path$3 : void 0;
28123
+ var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path$4 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
28124
+ wsComponents.path = path$4 && path$4 !== "/" ? path$4 : void 0;
27553
28125
  wsComponents.query = query;
27554
28126
  wsComponents.resourceName = void 0;
27555
28127
  }
@@ -27890,12 +28462,12 @@ var require_util = __commonJS({ "node_modules/ajv/lib/compile/util.js"(exports,
27890
28462
  return "'" + escapeQuotes(str) + "'";
27891
28463
  }
27892
28464
  function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
27893
- var path$3 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
27894
- return joinPaths(currentPath, path$3);
28465
+ var path$4 = jsonPointers ? "'/' + " + expr + (isNumber ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
28466
+ return joinPaths(currentPath, path$4);
27895
28467
  }
27896
28468
  function getPath(currentPath, prop, jsonPointers) {
27897
- var path$3 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
27898
- return joinPaths(currentPath, path$3);
28469
+ var path$4 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
28470
+ return joinPaths(currentPath, path$4);
27899
28471
  }
27900
28472
  var JSON_POINTER$1 = /^\/(?:[^~]|~0|~1)*$/;
27901
28473
  var RELATIVE_JSON_POINTER$1 = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
@@ -32063,16 +32635,16 @@ var require_ajv = __commonJS({ "node_modules/ajv/lib/ajv.js"(exports, module) {
32063
32635
  return metaOpts;
32064
32636
  }
32065
32637
  function setLogger(self) {
32066
- var logger$24 = self._opts.logger;
32067
- if (logger$24 === false) self.logger = {
32638
+ var logger$26 = self._opts.logger;
32639
+ if (logger$26 === false) self.logger = {
32068
32640
  log: noop,
32069
32641
  warn: noop,
32070
32642
  error: noop
32071
32643
  };
32072
32644
  else {
32073
- if (logger$24 === void 0) logger$24 = console;
32074
- if (!(typeof logger$24 == "object" && logger$24.log && logger$24.warn && logger$24.error)) throw new Error("logger must implement log, warn and error methods");
32075
- self.logger = logger$24;
32645
+ if (logger$26 === void 0) logger$26 = console;
32646
+ if (!(typeof logger$26 == "object" && logger$26.log && logger$26.warn && logger$26.error)) throw new Error("logger must implement log, warn and error methods");
32647
+ self.logger = logger$26;
32076
32648
  }
32077
32649
  }
32078
32650
  function noop() {}
@@ -32104,8 +32676,8 @@ var ToolRegistry = class {
32104
32676
  if (!valid) {
32105
32677
  const errors = validate$1.errors ?? [];
32106
32678
  const messages = errors.map((e) => {
32107
- const path$3 = e.instancePath ?? e.dataPath ?? "";
32108
- return `${path$3} ${e.message ?? ""}`.trim();
32679
+ const path$4 = e.instancePath ?? e.dataPath ?? "";
32680
+ return `${path$4} ${e.message ?? ""}`.trim();
32109
32681
  }).join(", ");
32110
32682
  return {
32111
32683
  content: `Validation failed for tool '${name}': ${messages}`,
@@ -38709,10 +39281,10 @@ var PathBase = class {
38709
39281
  /**
38710
39282
  * Get the Path object referenced by the string path, resolved from this Path
38711
39283
  */
38712
- resolve(path$3) {
38713
- if (!path$3) return this;
38714
- const rootPath = this.getRootString(path$3);
38715
- const dir = path$3.substring(rootPath.length);
39284
+ resolve(path$4) {
39285
+ if (!path$4) return this;
39286
+ const rootPath = this.getRootString(path$4);
39287
+ const dir = path$4.substring(rootPath.length);
38716
39288
  const dirParts = dir.split(this.splitSep);
38717
39289
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
38718
39290
  return result;
@@ -39367,8 +39939,8 @@ var PathWin32 = class PathWin32 extends PathBase {
39367
39939
  /**
39368
39940
  * @internal
39369
39941
  */
39370
- getRootString(path$3) {
39371
- return win32.parse(path$3).root;
39942
+ getRootString(path$4) {
39943
+ return win32.parse(path$4).root;
39372
39944
  }
39373
39945
  /**
39374
39946
  * @internal
@@ -39413,8 +39985,8 @@ var PathPosix = class PathPosix extends PathBase {
39413
39985
  /**
39414
39986
  * @internal
39415
39987
  */
39416
- getRootString(path$3) {
39417
- return path$3.startsWith("/") ? "/" : "";
39988
+ getRootString(path$4) {
39989
+ return path$4.startsWith("/") ? "/" : "";
39418
39990
  }
39419
39991
  /**
39420
39992
  * @internal
@@ -39507,9 +40079,9 @@ var PathScurryBase = class {
39507
40079
  /**
39508
40080
  * Get the depth of a provided path, string, or the cwd
39509
40081
  */
39510
- depth(path$3 = this.cwd) {
39511
- if (typeof path$3 === "string") path$3 = this.cwd.resolve(path$3);
39512
- return path$3.depth();
40082
+ depth(path$4 = this.cwd) {
40083
+ if (typeof path$4 === "string") path$4 = this.cwd.resolve(path$4);
40084
+ return path$4.depth();
39513
40085
  }
39514
40086
  /**
39515
40087
  * Return the cache of child entries. Exposed so subclasses can create
@@ -39890,9 +40462,9 @@ var PathScurryBase = class {
39890
40462
  process$1();
39891
40463
  return results;
39892
40464
  }
39893
- chdir(path$3 = this.cwd) {
40465
+ chdir(path$4 = this.cwd) {
39894
40466
  const oldCwd = this.cwd;
39895
- this.cwd = typeof path$3 === "string" ? this.cwd.resolve(path$3) : path$3;
40467
+ this.cwd = typeof path$4 === "string" ? this.cwd.resolve(path$4) : path$4;
39896
40468
  this.cwd[setAsCwd](oldCwd);
39897
40469
  }
39898
40470
  };
@@ -40276,8 +40848,8 @@ var MatchRecord = class {
40276
40848
  this.store.set(target, current === void 0 ? n$1 : n$1 & current);
40277
40849
  }
40278
40850
  entries() {
40279
- return [...this.store.entries()].map(([path$3, n$1]) => [
40280
- path$3,
40851
+ return [...this.store.entries()].map(([path$4, n$1]) => [
40852
+ path$4,
40281
40853
  !!(n$1 & 2),
40282
40854
  !!(n$1 & 1)
40283
40855
  ]);
@@ -40453,9 +41025,9 @@ var GlobUtil = class {
40453
41025
  signal;
40454
41026
  maxDepth;
40455
41027
  includeChildMatches;
40456
- constructor(patterns, path$3, opts) {
41028
+ constructor(patterns, path$4, opts) {
40457
41029
  this.patterns = patterns;
40458
- this.path = path$3;
41030
+ this.path = path$4;
40459
41031
  this.opts = opts;
40460
41032
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
40461
41033
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -40476,11 +41048,11 @@ var GlobUtil = class {
40476
41048
  });
40477
41049
  }
40478
41050
  }
40479
- #ignored(path$3) {
40480
- return this.seen.has(path$3) || !!this.#ignore?.ignored?.(path$3);
41051
+ #ignored(path$4) {
41052
+ return this.seen.has(path$4) || !!this.#ignore?.ignored?.(path$4);
40481
41053
  }
40482
- #childrenIgnored(path$3) {
40483
- return !!this.#ignore?.childrenIgnored?.(path$3);
41054
+ #childrenIgnored(path$4) {
41055
+ return !!this.#ignore?.childrenIgnored?.(path$4);
40484
41056
  }
40485
41057
  pause() {
40486
41058
  this.paused = true;
@@ -40662,8 +41234,8 @@ var GlobUtil = class {
40662
41234
  };
40663
41235
  var GlobWalker = class extends GlobUtil {
40664
41236
  matches = new Set();
40665
- constructor(patterns, path$3, opts) {
40666
- super(patterns, path$3, opts);
41237
+ constructor(patterns, path$4, opts) {
41238
+ super(patterns, path$4, opts);
40667
41239
  }
40668
41240
  matchEmit(e) {
40669
41241
  this.matches.add(e);
@@ -40690,8 +41262,8 @@ var GlobWalker = class extends GlobUtil {
40690
41262
  };
40691
41263
  var GlobStream = class extends GlobUtil {
40692
41264
  results;
40693
- constructor(patterns, path$3, opts) {
40694
- super(patterns, path$3, opts);
41265
+ constructor(patterns, path$4, opts) {
41266
+ super(patterns, path$4, opts);
40695
41267
  this.results = new Minipass({
40696
41268
  signal: this.signal,
40697
41269
  objectMode: true
@@ -44583,4 +45155,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
44583
45155
 
44584
45156
  //#endregion
44585
45157
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict, wireNdjsonEmitter };
44586
- //# sourceMappingURL=run-C8IJQ5i5.js.map
45158
+ //# sourceMappingURL=run-DGyWCmcu.js.map