substrate-ai 0.20.55 → 0.20.57

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 { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-VcMmfo2w.js";
1
+ import { addTokenUsage, createDecision, createPipelineRun, createRequirement, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunningPipelineRuns, getTokenUsageSummary, listRequirements, registerArtifact, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision } from "./dist-W2emvN3F.js";
2
2
  import "./decisions-C0pz9Clx.js";
3
3
 
4
4
  export { getLatestRun };
@@ -861,6 +861,7 @@ function extractJsonAsYaml(text) {
861
861
  const SHUTDOWN_GRACE_MS = 1e4;
862
862
  const SHUTDOWN_MAX_WAIT_MS = 3e4;
863
863
  const CHARS_PER_TOKEN$3 = 4;
864
+ const MAX_TAIL_BUFFER = 64 * 1024;
864
865
  /**
865
866
  * Extract top-level field names from a Zod schema for prompt injection.
866
867
  * Returns field names with type hints (e.g., "result: <string>", "files_modified: <list>").
@@ -1132,7 +1133,7 @@ var DispatcherImpl = class {
1132
1133
  this._logger.info("Dispatcher shutdown complete");
1133
1134
  }
1134
1135
  async _startDispatch(id, request, resolve$2) {
1135
- const { prompt, agent, taskType, timeout, outputSchema, workingDirectory, model, maxTurns, maxContextTokens, otlpEndpoint, storyKey, optimizationDirectives } = request;
1136
+ const { prompt, agent, taskType, timeout, outputSchema, workingDirectory, model, maxTurns, maxContextTokens, otlpEndpoint, storyKey, optimizationDirectives, attemptNumber } = request;
1136
1137
  let effectiveModel = model;
1137
1138
  if (effectiveModel === void 0 && this._config.routingResolver !== void 0) {
1138
1139
  const resolution = this._config.routingResolver.resolveModel(taskType);
@@ -1235,8 +1236,15 @@ var DispatcherImpl = class {
1235
1236
  }
1236
1237
  const stdoutChunks = [];
1237
1238
  const stderrChunks = [];
1239
+ let stdoutSize = 0;
1240
+ let stderrSize = 0;
1238
1241
  if (proc.stdout !== null) proc.stdout.on("data", (chunk) => {
1239
1242
  stdoutChunks.push(chunk);
1243
+ stdoutSize += chunk.length;
1244
+ while (stdoutSize > MAX_TAIL_BUFFER && stdoutChunks.length > 1) {
1245
+ const dropped = stdoutChunks.shift();
1246
+ stdoutSize -= dropped.length;
1247
+ }
1240
1248
  const dataStr = chunk.toString("utf-8");
1241
1249
  this._eventBus.emit("agent:output", {
1242
1250
  dispatchId: id,
@@ -1245,6 +1253,11 @@ var DispatcherImpl = class {
1245
1253
  });
1246
1254
  if (proc.stderr !== null) proc.stderr.on("data", (chunk) => {
1247
1255
  stderrChunks.push(chunk);
1256
+ stderrSize += chunk.length;
1257
+ while (stderrSize > MAX_TAIL_BUFFER && stderrChunks.length > 1) {
1258
+ const dropped = stderrChunks.shift();
1259
+ stderrSize -= dropped.length;
1260
+ }
1248
1261
  });
1249
1262
  const activeDispatch = {
1250
1263
  id,
@@ -1273,8 +1286,9 @@ var DispatcherImpl = class {
1273
1286
  }, "Agent dispatched");
1274
1287
  activeDispatch.timeoutHandle = setTimeout(() => {
1275
1288
  activeDispatch.timedOut = true;
1289
+ const elapsedAtKill = Date.now() - startedAt;
1276
1290
  proc.kill("SIGTERM");
1277
- const durationMs = Date.now() - startedAt;
1291
+ const durationMs = elapsedAtKill;
1278
1292
  const output = Buffer.concat(stdoutChunks).toString("utf-8");
1279
1293
  const inputTokens = Math.ceil(prompt.length / CHARS_PER_TOKEN$3);
1280
1294
  const outputTokens = Math.ceil(output.length / CHARS_PER_TOKEN$3);
@@ -1282,6 +1296,20 @@ var DispatcherImpl = class {
1282
1296
  dispatchId: id,
1283
1297
  timeoutMs
1284
1298
  });
1299
+ const stderrTail = Buffer.concat(stderrChunks).toString("utf8");
1300
+ const stdoutTail = Buffer.concat(stdoutChunks).toString("utf8");
1301
+ this._eventBus.emit("dispatch:spawnsync-timeout", {
1302
+ type: "dispatch:spawnsync-timeout",
1303
+ storyKey: storyKey ?? "unknown",
1304
+ taskType,
1305
+ attemptNumber: attemptNumber ?? 1,
1306
+ timeoutMs,
1307
+ elapsedAtKill,
1308
+ ...proc.pid != null && proc.pid > 0 ? { pid: proc.pid } : {},
1309
+ occurredAt: new Date().toISOString(),
1310
+ stderrTail,
1311
+ stdoutTail
1312
+ });
1285
1313
  this._logger.warn({
1286
1314
  id,
1287
1315
  agent,
@@ -9301,7 +9329,6 @@ var ClaudeCodeAdapter = class {
9301
9329
  "--dangerously-skip-permissions"
9302
9330
  ];
9303
9331
  if (options.maxTurns !== void 0) args.push("--max-turns", String(options.maxTurns));
9304
- if (options.maxContextTokens !== void 0) args.push("--max-context-tokens", String(options.maxContextTokens));
9305
9332
  if (options.additionalFlags && options.additionalFlags.length > 0) args.push(...options.additionalFlags);
9306
9333
  const systemPromptParts = [BASE_SYSTEM_PROMPT];
9307
9334
  if (options.optimizationDirectives) systemPromptParts.push(`\n\n## Optimization Directives\n${options.optimizationDirectives}`);
@@ -11015,4 +11042,4 @@ async function callLLM(params) {
11015
11042
 
11016
11043
  //#endregion
11017
11044
  export { ADVISORY_NOTES, AdapterRegistry, AdtError, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, Categorizer, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, ConsumerAnalyzer, CostTrackerConfigSchema, DEFAULT_CONFIG, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, DoltNotInstalled, DoltQueryError, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, GeminiCLIAdapter, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, LEARNING_FINDING, LogTurnAnalyzer, ModelRoutingConfigSchema, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProviderPolicySchema, ProvidersSchema, Recommender, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TASK_TYPE_PHASE_MAP, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryConfigSchema, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, VersionManagerImpl, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, callLLM, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDatabaseAdapter as createDatabaseAdapter$1, createDecision, createDoltClient, createExperimenter, createPipelineRun, createRequirement, createVersionManager, detectInterfaceChanges, determineVerdict, getActiveDecisions, getAllCostEntriesFiltered, getArtifactByTypeForRun, getArtifactsByRun, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getModelTier, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRequirements, listRunMetrics, loadModelRoutingConfig, loadParentRunDecisions, registerArtifact, resolvePromptFile, supersedeDecision, tagRunAsBaseline, updateDecision, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics };
11018
- //# sourceMappingURL=dist-VcMmfo2w.js.map
11045
+ //# sourceMappingURL=dist-W2emvN3F.js.map
@@ -1,4 +1,4 @@
1
- import { AdtError } from "./dist-VcMmfo2w.js";
1
+ import { AdtError } from "./dist-W2emvN3F.js";
2
2
 
3
3
  //#region src/core/errors.ts
4
4
  /** Error thrown when task configuration is invalid */
@@ -71,4 +71,4 @@ var TaskGraphIncompatibleFormatError = class extends AdtError {
71
71
 
72
72
  //#endregion
73
73
  export { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError };
74
- //# sourceMappingURL=errors-CogpxBUg.js.map
74
+ //# sourceMappingURL=errors-CKFu8YI9.js.map
@@ -1,3 +1,3 @@
1
- import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-VcMmfo2w.js";
1
+ import { buildAuditLogEntry, buildBranchName, buildModificationDirective, buildPRBody, buildWorktreePath, createExperimenter, determineVerdict, resolvePromptFile } from "./dist-W2emvN3F.js";
2
2
 
3
3
  export { createExperimenter };
@@ -1,6 +1,6 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-PSnpYDAa.js";
1
+ import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-PdI4-96I.js";
2
2
  import "./logger-KeHncl-f.js";
3
- import "./dist-VcMmfo2w.js";
3
+ import "./dist-W2emvN3F.js";
4
4
  import "./decisions-C0pz9Clx.js";
5
5
 
6
6
  export { inspectProcessTree };
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from "./logger-KeHncl-f.js";
2
- import { DoltClient, DoltQueryError, LEARNING_FINDING, createDatabaseAdapter$1 as createDatabaseAdapter, createDecision, getDecisionsByCategory, getLatestRun, getPipelineRunById, initSchema } from "./dist-VcMmfo2w.js";
2
+ import { DoltClient, DoltQueryError, LEARNING_FINDING, createDatabaseAdapter$1 as createDatabaseAdapter, createDecision, getDecisionsByCategory, getLatestRun, getPipelineRunById, initSchema } from "./dist-W2emvN3F.js";
3
3
  import { createRequire } from "module";
4
4
  import { dirname, join } from "path";
5
5
  import { readFile } from "fs/promises";
@@ -3819,6 +3819,30 @@ function tail(text, bytes = PROBE_TAIL_BYTES) {
3819
3819
  return text.length <= bytes ? text : text.slice(text.length - bytes);
3820
3820
  }
3821
3821
  /**
3822
+ * Story 66-6 / obs_2026-05-04_024 fix #1:
3823
+ * Substitute `<REPO_ROOT>` and `$REPO_ROOT` placeholder tokens in a probe
3824
+ * command string with the actual project root path before shell invocation.
3825
+ *
3826
+ * Rules:
3827
+ * - Every literal `<REPO_ROOT>` substring is replaced with `projectRoot`.
3828
+ * - Every `$REPO_ROOT` token that is NOT immediately followed by an
3829
+ * alphanumeric character or underscore is replaced with `projectRoot`
3830
+ * (so `$REPO_ROOT_EXTRA` is left untouched).
3831
+ * - All other `<...>` placeholders (e.g. `<UNKNOWN_PLACEHOLDER>`) are
3832
+ * passed through unchanged — Story 66-7 handles the unknown-placeholder
3833
+ * finding category separately.
3834
+ * - Probes without any placeholder are returned byte-for-byte identical.
3835
+ *
3836
+ * Backward-compat note: any existing probe command that contained the
3837
+ * literal text `<REPO_ROOT>` (none expected in practice) will now have that
3838
+ * text replaced with the project root path. This is the intended behavior.
3839
+ */
3840
+ function substituteRuntimePlaceholders(command, projectRoot) {
3841
+ let result = command.replaceAll("<REPO_ROOT>", projectRoot);
3842
+ result = result.replace(/\$REPO_ROOT(?=[^A-Za-z0-9_]|$)/g, projectRoot);
3843
+ return result;
3844
+ }
3845
+ /**
3822
3846
  * Story 60-4: evaluate `expect_stdout_no_regex` and `expect_stdout_regex`
3823
3847
  * patterns against the captured stdout. Runs against the full (un-tailed)
3824
3848
  * stdout so authors can match payload shape even when the response is
@@ -3913,11 +3937,12 @@ function executeProbeOnHost(probe, options = {}) {
3913
3937
  const cwd = options.cwd ?? process.cwd();
3914
3938
  const env = options.env ?? process.env;
3915
3939
  const start = Date.now();
3940
+ const resolvedCommand = substituteRuntimePlaceholders(probe.command, cwd);
3916
3941
  return new Promise((resolve$2) => {
3917
3942
  let stdout = "";
3918
3943
  let stderr = "";
3919
3944
  let settled = false;
3920
- const child = spawn(probe.command, [], {
3945
+ const child = spawn(resolvedCommand, [], {
3921
3946
  cwd,
3922
3947
  env,
3923
3948
  detached: true,
@@ -4090,6 +4115,16 @@ const CATEGORY_MISSING_TRIGGER = "runtime-probe-missing-production-trigger";
4090
4115
  */
4091
4116
  const CATEGORY_MISSING_PROBES_DECLARED = "runtime-probe-missing-declared-probes";
4092
4117
  /**
4118
+ * Story 66-7: probe exited non-zero AND stderr/stdout contained a placeholder
4119
+ * token that was never substituted before execution (e.g. `<REPO_ROOT>`,
4120
+ * `<CONFIG_DIR>`, `<UNKNOWN_VAR>`). Distinct from `runtime-probe-fail`
4121
+ * (genuine runtime failure) so operators and probe-author quality dashboards
4122
+ * can carve placeholder substitution failures out for cleaner triage and
4123
+ * metrics. Severity: `error` (matches `runtime-probe-fail` baseline).
4124
+ * Closes obs_2026-05-04_024 fix #3.
4125
+ */
4126
+ const CATEGORY_PLACEHOLDER_NOT_SUBSTITUTED = "runtime-probe-placeholder-not-substituted";
4127
+ /**
4093
4128
  * Source-AC keywords that signal an event-driven implementation. Word-boundary
4094
4129
  * matched, case-insensitive. When any of these appears in source AC text AND
4095
4130
  * no probe's command invokes a known production trigger, the check emits a
@@ -4230,6 +4265,37 @@ function detectsStateIntegratingAC(sourceContent) {
4230
4265
  return false;
4231
4266
  }
4232
4267
  /**
4268
+ * Detects whether a probe's combined output (stderr + stdout) contains an
4269
+ * unrecognized placeholder token that was not substituted before execution.
4270
+ *
4271
+ * Two shapes are handled:
4272
+ *
4273
+ * Shape 1 — command-line tool "no such file" with placeholder argument:
4274
+ * `grep: <REPO_ROOT>: No such file or directory`
4275
+ * `bash: <CONFIG_DIR>: command not found`
4276
+ * Regex (multiline): `/^[\w]*:\s*(<[A-Z_]+>):?/m`
4277
+ *
4278
+ * Shape 2 — shell syntax error adjacent to a placeholder token:
4279
+ * Combined output contains `Syntax error: "&&" unexpected` AND a `<TOKEN>`.
4280
+ *
4281
+ * Returns the captured `<TOKEN>` string if the placeholder leakage pattern
4282
+ * fires, or `null` if no placeholder is detected (allowing the existing
4283
+ * `CATEGORY_FAIL` path to proceed unmodified).
4284
+ *
4285
+ * Exported (mirrors the export pattern of `detectNegationContextLines`,
4286
+ * `detectDependencyContextLines`, `detectsEventDrivenAC`) so tests and
4287
+ * downstream consumers can call it directly.
4288
+ */
4289
+ function detectPlaceholderLeakage(output) {
4290
+ const shape1Match = /^[\w]*:\s*(<[A-Z_]+>):?/m.exec(output);
4291
+ if (shape1Match !== null) return shape1Match[1] ?? null;
4292
+ if (output.includes("Syntax error: \"&&\" unexpected")) {
4293
+ const tokenMatch = /(<[A-Z_]+>)/.exec(output);
4294
+ if (tokenMatch !== null) return tokenMatch[1] ?? null;
4295
+ }
4296
+ return null;
4297
+ }
4298
+ /**
4233
4299
  * Returns true if any probe's command line invokes a known production trigger.
4234
4300
  */
4235
4301
  function probesInvokeProductionTrigger(probes) {
@@ -4323,17 +4389,69 @@ var RuntimeProbeCheck = class {
4323
4389
  }
4324
4390
  const result = await this._executors.host(probe);
4325
4391
  if (result.outcome === "pass") continue;
4326
- const category = result.outcome === "timeout" ? CATEGORY_TIMEOUT : result.assertionFailures !== void 0 ? CATEGORY_ASSERTION_FAIL : result.errorShapeIndicators !== void 0 ? CATEGORY_ERROR_RESPONSE : CATEGORY_FAIL;
4327
4392
  const descriptor = probe.description ? ` (${probe.description})` : "";
4328
- let message;
4329
- if (result.outcome === "timeout") message = `probe "${probe.name}"${descriptor} timed out after ${result.durationMs}ms`;
4330
- else if (result.assertionFailures !== void 0) message = `probe "${probe.name}"${descriptor} exit 0 but stdout assertion failed: ` + result.assertionFailures.join("; ");
4331
- else if (result.errorShapeIndicators !== void 0) message = `probe "${probe.name}"${descriptor} exit 0 but response contained error envelope: ` + result.errorShapeIndicators.join("; ") + " — the tool returned an error-shaped JSON response despite a clean exit code. This is structural evidence the implementation didn't actually work; add an explicit `expect_stdout_no_regex` assertion to make the failure surface earlier in author-controlled form.";
4332
- else message = `probe "${probe.name}"${descriptor} failed with exit ${result.exitCode ?? "unknown"}`;
4393
+ if (result.outcome === "timeout") {
4394
+ findings.push({
4395
+ category: CATEGORY_TIMEOUT,
4396
+ severity: "error",
4397
+ message: `probe "${probe.name}"${descriptor} timed out after ${result.durationMs}ms`,
4398
+ command: result.command,
4399
+ stdoutTail: result.stdoutTail,
4400
+ stderrTail: result.stderrTail,
4401
+ durationMs: result.durationMs,
4402
+ _authoredBy: probe._authoredBy ?? "create-story-ac-transfer"
4403
+ });
4404
+ continue;
4405
+ }
4406
+ if (result.assertionFailures !== void 0) {
4407
+ findings.push({
4408
+ category: CATEGORY_ASSERTION_FAIL,
4409
+ severity: "error",
4410
+ message: `probe "${probe.name}"${descriptor} exit 0 but stdout assertion failed: ` + result.assertionFailures.join("; "),
4411
+ command: result.command,
4412
+ ...result.exitCode !== void 0 ? { exitCode: result.exitCode } : {},
4413
+ stdoutTail: result.stdoutTail,
4414
+ stderrTail: result.stderrTail,
4415
+ durationMs: result.durationMs,
4416
+ _authoredBy: probe._authoredBy ?? "create-story-ac-transfer"
4417
+ });
4418
+ continue;
4419
+ }
4420
+ if (result.errorShapeIndicators !== void 0) {
4421
+ findings.push({
4422
+ category: CATEGORY_ERROR_RESPONSE,
4423
+ severity: "error",
4424
+ message: `probe "${probe.name}"${descriptor} exit 0 but response contained error envelope: ` + result.errorShapeIndicators.join("; ") + " — the tool returned an error-shaped JSON response despite a clean exit code. This is structural evidence the implementation didn't actually work; add an explicit `expect_stdout_no_regex` assertion to make the failure surface earlier in author-controlled form.",
4425
+ command: result.command,
4426
+ ...result.exitCode !== void 0 ? { exitCode: result.exitCode } : {},
4427
+ stdoutTail: result.stdoutTail,
4428
+ stderrTail: result.stderrTail,
4429
+ durationMs: result.durationMs,
4430
+ _authoredBy: probe._authoredBy ?? "create-story-ac-transfer"
4431
+ });
4432
+ continue;
4433
+ }
4434
+ const outputForDetection = `${result.stderrTail ?? ""}\n${result.stdoutTail ?? ""}`;
4435
+ const placeholderToken = detectPlaceholderLeakage(outputForDetection);
4436
+ if (placeholderToken !== null) {
4437
+ findings.push({
4438
+ category: CATEGORY_PLACEHOLDER_NOT_SUBSTITUTED,
4439
+ severity: "error",
4440
+ message: `Probe failed: unrecognized placeholder token "${placeholderToken}" was not substituted before execution`,
4441
+ command: result.command,
4442
+ ...result.exitCode !== void 0 ? { exitCode: result.exitCode } : {},
4443
+ stdoutTail: result.stdoutTail,
4444
+ stderrTail: result.stderrTail,
4445
+ durationMs: result.durationMs,
4446
+ unrecognizedPlaceholder: placeholderToken,
4447
+ _authoredBy: probe._authoredBy ?? "create-story-ac-transfer"
4448
+ });
4449
+ continue;
4450
+ }
4333
4451
  findings.push({
4334
- category,
4452
+ category: CATEGORY_FAIL,
4335
4453
  severity: "error",
4336
- message,
4454
+ message: `probe "${probe.name}"${descriptor} failed with exit ${result.exitCode ?? "unknown"}`,
4337
4455
  command: result.command,
4338
4456
  ...result.exitCode !== void 0 ? { exitCode: result.exitCode } : {},
4339
4457
  stdoutTail: result.stdoutTail,
@@ -6912,4 +7030,4 @@ function registerHealthCommand(program, _version = "0.0.0", projectRoot = proces
6912
7030
 
6913
7031
  //#endregion
6914
7032
  export { BMAD_BASELINE_TOKENS_FULL, DEFAULT_STALL_THRESHOLD_SECONDS, DoltMergeConflict, FileStateStore, FindingsInjector, RunManifest, RuntimeProbeListSchema, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN$1 as STORY_KEY_PATTERN, SUBSTRATE_OWNED_SETTINGS_KEYS, SupervisorLock, VALID_PHASES, WorkGraphRepository, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, __commonJS, __require, __toESM, aggregateProbeAuthorMetrics, applyConfigToGraph, buildPipelineStatusOutput, createDatabaseAdapter$1 as createDatabaseAdapter, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, createStateStore, detectCycles, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, findPackageRoot, formatOutput, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, inspectProcessTree, isOrchestratorProcessLine, parseDbTimestampAsUtc, parseRuntimeProbes, registerHealthCommand, renderFindings, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveGraphPath, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runHealthAction, validateStoryKey };
6915
- //# sourceMappingURL=health-PSnpYDAa.js.map
7033
+ //# sourceMappingURL=health-PdI4-96I.js.map
package/dist/index.d.ts CHANGED
@@ -317,9 +317,25 @@ interface StoryLogEvent {
317
317
  /** Log message */
318
318
  msg: string;
319
319
  }
320
+ /**
321
+ * Snapshot entry for a single story within a heartbeat event.
322
+ * Both fields are strings so the event schema stays language-agnostic.
323
+ *
324
+ * - `phase` — raw orchestrator StoryPhase value (e.g. 'IN_DEV', 'COMPLETE').
325
+ * - `status` — consumer-facing status derived from phase (e.g. 'dispatched', 'complete').
326
+ *
327
+ * Story 66-2: obs_2026-05-03_022 fix #2.
328
+ */
329
+ type HeartbeatStorySnapshot = {
330
+ phase: string;
331
+ status: string;
332
+ };
320
333
  /**
321
334
  * Emitted periodically (every 30s) when no other progress events have fired.
322
335
  * Allows parent agents to distinguish "working silently" from "stuck".
336
+ *
337
+ * Story 66-2: gains optional `per_story_state` field for real-time drift detection
338
+ * between in-memory orchestrator state and the persisted manifest (obs_2026-05-03_022 fix #2).
323
339
  */
324
340
  interface PipelineHeartbeatEvent {
325
341
  type: 'pipeline:heartbeat';
@@ -333,6 +349,13 @@ interface PipelineHeartbeatEvent {
333
349
  completed_dispatches: number;
334
350
  /** Number of dispatches waiting to start */
335
351
  queued_dispatches: number;
352
+ /**
353
+ * Snapshot of in-memory phase and derived status for each story.
354
+ * Omitted (or empty object) when no stories are dispatched.
355
+ * Additive and optional — existing heartbeat consumers require no changes.
356
+ * Story 66-2: obs_2026-05-03_022 fix #2.
357
+ */
358
+ per_story_state?: Record<string, HeartbeatStorySnapshot>;
336
359
  }
337
360
  /**
338
361
  * Emitted when the watchdog timer detects no progress for an extended period.
@@ -903,10 +926,11 @@ interface AdapterOptions$1 {
903
926
  */
904
927
  storyKey?: string;
905
928
  /**
906
- * Optional maximum context tokens (passed as --max-context-tokens to Claude CLI).
907
- * When set, constrains the context window to prevent runaway token usage.
908
- * Used by efficiency-gated retry logic (Story 30-8) to cap context for stories
909
- * that previously exhibited context spike patterns.
929
+ * Optional maximum context tokens. Historically passed as --max-context-tokens to
930
+ * Claude CLI; that flag was removed in Claude Code v2.x and is now silently ignored
931
+ * by the claude-adapter. The field remains on the options shape for backward compat
932
+ * with callers (Story 30-8 efficiency-gated retry logic) but no longer constrains
933
+ * dispatch behavior. --max-turns continues to bound dispatch length.
910
934
  */
911
935
  maxContextTokens?: number;
912
936
  /**
@@ -2210,6 +2234,34 @@ interface OrchestratorEvents {
2210
2234
  activeDispatches: number;
2211
2235
  completedDispatches: number;
2212
2236
  queuedDispatches: number;
2237
+ /**
2238
+ * Per-story phase and derived status snapshot from in-memory orchestrator state.
2239
+ * Omitted when no stories are dispatched. Story 66-2: obs_2026-05-03_022 fix #2.
2240
+ */
2241
+ perStoryState?: Record<string, {
2242
+ phase: string;
2243
+ status: string;
2244
+ }>;
2245
+ };
2246
+ /**
2247
+ * Story 66-4 / obs_2026-05-04_023 fix #3: dispatcher subprocess hit ETIMEDOUT.
2248
+ * Emitted for both the initial attempt (attemptNumber: 1) and retry (attemptNumber: 2).
2249
+ * Story 66-5 adds optional stderrTail/stdoutTail forensic capture.
2250
+ * Mirror of CoreEvents['dispatch:spawnsync-timeout']; both must stay in sync.
2251
+ */
2252
+ 'dispatch:spawnsync-timeout': {
2253
+ type: 'dispatch:spawnsync-timeout';
2254
+ storyKey: string;
2255
+ taskType: string;
2256
+ attemptNumber: 1 | 2;
2257
+ timeoutMs: number;
2258
+ elapsedAtKill: number;
2259
+ pid?: number;
2260
+ occurredAt: string;
2261
+ /** Tail of subprocess stderr captured at kill time (~64KB max, UTF-8) */
2262
+ stderrTail?: string;
2263
+ /** Tail of subprocess stdout captured at kill time (~64KB max, UTF-8) */
2264
+ stdoutTail?: string;
2213
2265
  };
2214
2266
  /** Watchdog detected no progress for an extended period */
2215
2267
  'orchestrator:stall': {
@@ -2560,10 +2612,11 @@ interface AdapterOptions {
2560
2612
  */
2561
2613
  storyKey?: string;
2562
2614
  /**
2563
- * Optional maximum context tokens (passed as --max-context-tokens to Claude CLI).
2564
- * When set, constrains the context window to prevent runaway token usage.
2565
- * Used by efficiency-gated retry logic (Story 30-8) to cap context for stories
2566
- * that previously exhibited context spike patterns.
2615
+ * Optional maximum context tokens. Historically passed as --max-context-tokens to
2616
+ * Claude CLI; that flag was removed in Claude Code v2.x and is now silently ignored
2617
+ * by the claude-adapter. The field remains on the options shape for backward compat
2618
+ * with callers (Story 30-8 efficiency-gated retry logic) but no longer constrains
2619
+ * dispatch behavior. --max-turns continues to bound dispatch length.
2567
2620
  */
2568
2621
  maxContextTokens?: number;
2569
2622
  /**
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { childLogger, createLogger, logger } from "./logger-KeHncl-f.js";
2
2
  import { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-CElYrONe.js";
3
- import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-VcMmfo2w.js";
3
+ import { AdapterRegistry, AdtError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter } from "./dist-W2emvN3F.js";
4
4
  import "./adapter-registry-DXLMTmfD.js";
5
- import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-CogpxBUg.js";
5
+ import { BudgetExceededError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError } from "./errors-CKFu8YI9.js";
6
6
 
7
7
  //#region src/core/di.ts
8
8
  /**
@@ -1,4 +1,4 @@
1
- import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-VcMmfo2w.js";
1
+ import { ModelRoutingConfigSchema, ProviderPolicySchema, RoutingConfigError, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, TASK_TYPE_PHASE_MAP, getModelTier, loadModelRoutingConfig } from "./dist-W2emvN3F.js";
2
2
  import "./routing-CcBOCuC9.js";
3
3
 
4
4
  export { loadModelRoutingConfig };
@@ -1,8 +1,8 @@
1
- import "./health-PSnpYDAa.js";
1
+ import "./health-PdI4-96I.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
- import "./dist-VcMmfo2w.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-CeaNSnD6.js";
4
+ import "./dist-W2emvN3F.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-DcDoaG12.js";
6
6
  import "./routing-CcBOCuC9.js";
7
7
  import "./decisions-C0pz9Clx.js";
8
8