substrate-ai 0.20.104 → 0.20.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -3,7 +3,7 @@ import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipel
3
3
  import { createLogger } from "../logger-KeHncl-f.js";
4
4
  import { createEventBus } from "../helpers-CElYrONe.js";
5
5
  import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initWorkGraphSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-CiMN31df.js";
6
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-DBGt1IJy.js";
6
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-BaEjWFS6.js";
7
7
  import "../adapter-registry-DIcrxjH8.js";
8
8
  import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-6GF2dThG.js";
9
9
  import "../errors-BaUaJmz9.js";
@@ -8420,7 +8420,7 @@ async function runSupervisorAction(options, deps = {}) {
8420
8420
  await initSchema(expAdapter);
8421
8421
  const { runRunAction: runPipeline } = await import(
8422
8422
  /* @vite-ignore */
8423
- "../run-Bga9OHjj.js"
8423
+ "../run-BPqjp1vn.js"
8424
8424
  );
8425
8425
  const runStoryFn = async (opts) => {
8426
8426
  const exitCode = await runPipeline({
@@ -96,10 +96,12 @@ Each dispatched story runs in `.substrate-worktrees/story-<key>` on its own bran
96
96
 
97
97
  ### Recommended `.gitignore` entries
98
98
 
99
- Substrate writes ephemeral per-process and per-run state under `.substrate/`. Only `.substrate/config.yaml` is intended to be tracked everything else (Dolt repo, kv-metrics, run manifests, heartbeats, halt notifications, current-run-id, .pid files) regenerates each run. Ignore everything under `.substrate/` and re-include only the config:
99
+ Substrate writes per-project state under `.substrate/` in a few flavors: per-process scratch (`.pid`, `current-run-id`, `latest-heartbeat-per-story-state.json` regenerated each run); per-run artifacts (`runs/<run-id>.json`, `notifications/`); local telemetry (`kv-metrics.json` — per-run phase token breakdown, accumulates into a local corpus used by `substrate metrics` and optional auto-tuner); the Dolt repository (`state/`); and the operator config (`config.yaml`, the only file intended for cross-machine sharing).
100
+
101
+ Defensible default: ignore everything under `.substrate/` except the operator config. Local telemetry stays per-developer; operators see their own corpus locally regardless of git.
100
102
 
101
103
  ```gitignore
102
- # Substrate ephemeral state — track only the operator config
104
+ # Substrate state — track only the operator config
103
105
  .substrate/*
104
106
  !.substrate/config.yaml
105
107
  ```
@@ -111,15 +111,23 @@ Each dispatched story runs in `.substrate-worktrees/story-<key>` on its own bran
111
111
 
112
112
  ### Recommended `.gitignore` entries
113
113
 
114
- Substrate writes ephemeral per-process and per-run state under `.substrate/`. Only `.substrate/config.yaml` is intended to be tracked — everything else (the Dolt repo, kv-metrics, run manifests, heartbeats, halt notifications, current-run-id, .pid files) is regenerated each run and should be ignored. The simplest pattern is to ignore everything under `.substrate/` and re-include only the config:
114
+ Substrate writes per-project state under `.substrate/` in a few flavors:
115
+ - **Per-process scratch** (`.pid`, `current-run-id`, `latest-heartbeat-per-story-state.json`) — regenerated each run.
116
+ - **Per-run artifacts** (`runs/<run-id>.json`, `notifications/<run-id>-*.json`) — accumulate across runs; substrate report consumes and cleans notifications.
117
+ - **Local telemetry** (`kv-metrics.json` — per-run phase token breakdown used by `substrate metrics --output-format json` and, when enabled, the routing auto-tuner) — accumulates across runs into a local corpus.
118
+ - **The Dolt repository** (`state/`) — versioned pipeline state, large + binary.
119
+ - **Operator config** (`config.yaml`) — the only file intended for cross-machine sharing.
120
+
121
+ The defensible default for most projects is to ignore everything under `.substrate/` except the operator config. Local telemetry stays on each developer's machine — operators see their own corpus locally via `substrate metrics`; cross-machine sharing of routing telemetry is a future feature, not currently supported.
115
122
 
116
123
  ```gitignore
117
- # Substrate ephemeral state — track only the operator config
124
+ # Substrate state — track only the operator config; everything else is
125
+ # per-process, per-run, or local-machine accumulation
118
126
  .substrate/*
119
127
  !.substrate/config.yaml
120
128
  ```
121
129
 
122
- This is future-proof against new ephemeral files substrate may introduce. If you'd rather enumerate the specific patterns, the equivalent explicit form is:
130
+ This is future-proof against new files substrate may introduce. If you want to enumerate explicitly instead:
123
131
 
124
132
  ```gitignore
125
133
  .substrate/state/
@@ -133,6 +141,8 @@ This is future-proof against new ephemeral files substrate may introduce. If you
133
141
  .substrate/routing-policy.yaml
134
142
  ```
135
143
 
144
+ **Tradeoff to consider:** if your team wants to share a routing auto-tune corpus across machines (e.g., to seed `config.auto_tune` decisions with combined data), you could remove `kv-metrics.json` from the ignore set — at the cost of one git-mutation per substrate run. Most teams don't need this; the file is operator-visible locally regardless of git.
145
+
136
146
  ### State Backend
137
147
 
138
148
  Substrate uses Dolt for versioned pipeline state by default. Run `substrate init` to set it up automatically if Dolt is on PATH. Features that require Dolt: `substrate history`, OTEL observability persistence, and context engineering repo-map storage.
@@ -96,10 +96,12 @@ Each dispatched story runs in `.substrate-worktrees/story-<key>` on its own bran
96
96
 
97
97
  ### Recommended `.gitignore` entries
98
98
 
99
- Substrate writes ephemeral per-process and per-run state under `.substrate/`. Only `.substrate/config.yaml` is intended to be tracked everything else (Dolt repo, kv-metrics, run manifests, heartbeats, halt notifications, current-run-id, .pid files) regenerates each run. Ignore everything under `.substrate/` and re-include only the config:
99
+ Substrate writes per-project state under `.substrate/` in a few flavors: per-process scratch (`.pid`, `current-run-id`, `latest-heartbeat-per-story-state.json` regenerated each run); per-run artifacts (`runs/<run-id>.json`, `notifications/`); local telemetry (`kv-metrics.json` — per-run phase token breakdown, accumulates into a local corpus used by `substrate metrics` and optional auto-tuner); the Dolt repository (`state/`); and the operator config (`config.yaml`, the only file intended for cross-machine sharing).
100
+
101
+ Defensible default: ignore everything under `.substrate/` except the operator config. Local telemetry stays per-developer; operators see their own corpus locally regardless of git.
100
102
 
101
103
  ```gitignore
102
- # Substrate ephemeral state — track only the operator config
104
+ # Substrate state — track only the operator config
103
105
  .substrate/*
104
106
  !.substrate/config.yaml
105
107
  ```
@@ -2,7 +2,7 @@ import "./health-C5ASRMDX.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
4
  import "./dist-CiMN31df.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-DBGt1IJy.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-BaEjWFS6.js";
6
6
  import "./manifest-read-6GF2dThG.js";
7
7
  import "./routing-DFxoKHDt.js";
8
8
  import "./work-graph-repository-DZyJv5pV.js";
@@ -13275,7 +13275,7 @@ function checkProfileStaleness(projectRoot) {
13275
13275
  * @returns A fully-configured ImplementationOrchestrator ready to call run()
13276
13276
  */
13277
13277
  function createImplementationOrchestrator(deps) {
13278
- const { db, pack, contextCompiler, dispatcher, eventBus, config, projectRoot, tokenCeilings, stateStore, telemetryPersistence, ingestionServer, repoMapInjector, maxRepoMapTokens, agentId, runManifest = null, worktreeManager } = deps;
13278
+ const { db, pack, contextCompiler, dispatcher, eventBus, config, projectRoot, tokenCeilings, telemetryPersistence, ingestionServer, repoMapInjector, maxRepoMapTokens, agentId, runManifest = null, worktreeManager } = deps;
13279
13279
  const noWorktree = config.noWorktree ?? false;
13280
13280
  const _worktreeManager = worktreeManager ?? (projectRoot !== void 0 && !noWorktree ? createGitWorktreeManager({
13281
13281
  eventBus: toCoreEventBus(eventBus),
@@ -13322,7 +13322,6 @@ function createImplementationOrchestrator(deps) {
13322
13322
  let _probeAuthorEffectiveMode = "enabled";
13323
13323
  const verificationStore = new VerificationStore();
13324
13324
  const verificationPipeline = createDefaultVerificationPipeline(toSdlcEventBus(eventBus), void 0);
13325
- const _stateStoreCache = new Map();
13326
13325
  const _checkpoints = new Map();
13327
13326
  const enqueueMerge = createMergeQueue();
13328
13327
  const MEMORY_PRESSURE_BACKOFF_MS = [
@@ -13432,26 +13431,6 @@ function createImplementationOrchestrator(deps) {
13432
13431
  primary_agent_id: storyAgentId ?? agentId ?? "claude-code",
13433
13432
  dispatch_agents_json: _storyAgents.has(storyKey) ? JSON.stringify(_storyAgents.get(storyKey)) : void 0
13434
13433
  });
13435
- if (stateStore !== void 0) stateStore.recordMetric({
13436
- storyKey,
13437
- taskType: "dev-story",
13438
- model: void 0,
13439
- tokensIn: tokenAgg.input,
13440
- tokensOut: tokenAgg.output,
13441
- cacheReadTokens: void 0,
13442
- costUsd: tokenAgg.cost,
13443
- wallClockMs,
13444
- reviewCycles,
13445
- stallCount: _storiesWithStall.has(storyKey) ? 1 : 0,
13446
- result,
13447
- recordedAt: completedAt,
13448
- timestamp: completedAt
13449
- }).catch((storeErr) => {
13450
- logger$27.warn({
13451
- err: storeErr,
13452
- storyKey
13453
- }, "Failed to record metric to StateStore (best-effort)");
13454
- });
13455
13434
  try {
13456
13435
  const runId = config.pipelineRunId ?? "unknown";
13457
13436
  await createDecision(db, {
@@ -13667,15 +13646,6 @@ function createImplementationOrchestrator(deps) {
13667
13646
  }
13668
13647
  function getStatus() {
13669
13648
  const stories = {};
13670
- for (const [key, record] of _stateStoreCache) if (!_stories.has(key)) stories[key] = {
13671
- phase: record.phase,
13672
- reviewCycles: record.reviewCycles,
13673
- lastVerdict: record.lastVerdict,
13674
- error: record.error,
13675
- startedAt: record.startedAt,
13676
- completedAt: record.completedAt,
13677
- checkpointFilesCount: record.checkpointFilesCount
13678
- };
13679
13649
  for (const [key, s$1] of _stories) stories[key] = { ...s$1 };
13680
13650
  const status = {
13681
13651
  state: _state,
@@ -13695,10 +13665,6 @@ function createImplementationOrchestrator(deps) {
13695
13665
  const existing = _stories.get(storyKey);
13696
13666
  if (existing !== void 0) {
13697
13667
  Object.assign(existing, updates);
13698
- persistStoryState(storyKey, existing).catch((err) => logger$27.warn({
13699
- err,
13700
- storyKey
13701
- }, "StateStore write failed after updateStory"));
13702
13668
  if (updates.phase !== void 0) {
13703
13669
  const targetStatus = wgStatusForPhase(updates.phase);
13704
13670
  if (targetStatus !== null) if (targetStatus === "in_progress" && _wgInProgressWritten.has(storyKey)) {} else {
@@ -13750,34 +13716,6 @@ function createImplementationOrchestrator(deps) {
13750
13716
  }
13751
13717
  }
13752
13718
  }
13753
- /**
13754
- * Persist a single story's state to the StateStore (Story 26-4, AC2).
13755
- *
13756
- * Best-effort: callers should `.catch()` on the returned promise.
13757
- * Never throws — errors are swallowed so the pipeline is never blocked.
13758
- */
13759
- async function persistStoryState(storyKey, state) {
13760
- if (stateStore === void 0) return;
13761
- try {
13762
- const record = {
13763
- storyKey,
13764
- phase: state.phase,
13765
- reviewCycles: state.reviewCycles,
13766
- lastVerdict: state.lastVerdict,
13767
- error: state.error,
13768
- startedAt: state.startedAt,
13769
- completedAt: state.completedAt,
13770
- sprint: config.sprint,
13771
- checkpointFilesCount: state.checkpointFilesCount
13772
- };
13773
- await stateStore.setStoryState(storyKey, record);
13774
- } catch (err) {
13775
- logger$27.warn({
13776
- err,
13777
- storyKey
13778
- }, "StateStore.setStoryState failed (best-effort)");
13779
- }
13780
- }
13781
13719
  async function persistState() {
13782
13720
  if (config.pipelineRunId === void 0) return;
13783
13721
  recordProgress();
@@ -13946,10 +13884,6 @@ function createImplementationOrchestrator(deps) {
13946
13884
  completedAt: new Date().toISOString()
13947
13885
  };
13948
13886
  _stories.set(storyKey, memPressureState);
13949
- persistStoryState(storyKey, memPressureState).catch((err) => logger$27.warn({
13950
- err,
13951
- storyKey
13952
- }, "StateStore write failed after memory-pressure escalation"));
13953
13887
  await writeStoryMetricsBestEffort(storyKey, "escalated", 0);
13954
13888
  await emitEscalation({
13955
13889
  storyKey,
@@ -14452,15 +14386,7 @@ function createImplementationOrchestrator(deps) {
14452
14386
  const storyContent = await readFile$1(storyFilePath, "utf-8");
14453
14387
  const contracts = parseInterfaceContracts(storyContent, storyKey);
14454
14388
  if (contracts.length > 0) {
14455
- const contractRecords = contracts.map((d) => ({
14456
- storyKey: d.storyKey,
14457
- contractName: d.contractName,
14458
- direction: d.direction,
14459
- schemaPath: d.filePath,
14460
- ...d.transport !== void 0 ? { transport: d.transport } : {}
14461
- }));
14462
- if (stateStore !== void 0) await stateStore.setContracts(storyKey, contractRecords);
14463
- else for (const contract of contracts) await createDecision(db, {
14389
+ for (const contract of contracts) await createDecision(db, {
14464
14390
  pipeline_run_id: config.pipelineRunId ?? null,
14465
14391
  phase: "implementation",
14466
14392
  category: "interface-contract",
@@ -14882,18 +14808,6 @@ function createImplementationOrchestrator(deps) {
14882
14808
  filesCount: timeoutFiles.length,
14883
14809
  diffSizeBytes
14884
14810
  });
14885
- if (stateStore !== void 0) stateStore.recordMetric({
14886
- storyKey,
14887
- taskType: "dev-story",
14888
- result: "timeout",
14889
- recordedAt: new Date().toISOString(),
14890
- sprint: config.sprint
14891
- }).catch((storeErr) => {
14892
- logger$27.warn({
14893
- err: storeErr,
14894
- storyKey
14895
- }, "Failed to record timeout metric to StateStore (best-effort)");
14896
- });
14897
14811
  await persistState();
14898
14812
  eventBus.emit("story:checkpoint-retry", {
14899
14813
  storyKey,
@@ -15517,10 +15431,6 @@ function createImplementationOrchestrator(deps) {
15517
15431
  completedAt: new Date().toISOString(),
15518
15432
  error: "recovery-engine-propose"
15519
15433
  });
15520
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$27.warn({
15521
- err,
15522
- storyKey
15523
- }, "StateStore write failed after recovery-propose"));
15524
15434
  await emitEscalation({
15525
15435
  storyKey,
15526
15436
  lastVerdict: "recovery-propose",
@@ -15558,10 +15468,6 @@ function createImplementationOrchestrator(deps) {
15558
15468
  completedAt: new Date().toISOString(),
15559
15469
  error: "recovery-engine-halt"
15560
15470
  });
15561
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$27.warn({
15562
- err,
15563
- storyKey
15564
- }, "StateStore write failed after recovery-halt"));
15565
15471
  await emitEscalation({
15566
15472
  storyKey,
15567
15473
  lastVerdict: "recovery-halt",
@@ -15578,10 +15484,6 @@ function createImplementationOrchestrator(deps) {
15578
15484
  phase: "VERIFICATION_FAILED",
15579
15485
  completedAt: new Date().toISOString()
15580
15486
  });
15581
- persistStoryState(storyKey, _stories.get(storyKey)).catch((err) => logger$27.warn({
15582
- err,
15583
- storyKey
15584
- }, "StateStore write failed after verification-failed"));
15585
15487
  await writeStoryMetricsBestEffort(storyKey, "verification-failed", finalReviewCycles);
15586
15488
  await persistState();
15587
15489
  return "verification-failed";
@@ -17008,26 +16910,6 @@ function createImplementationOrchestrator(deps) {
17008
16910
  process.on("SIGTERM", sigtermHandler);
17009
16911
  process.on("SIGINT", sigintHandler);
17010
16912
  try {
17011
- if (stateStore !== void 0) {
17012
- const stateStoreInitStart = Date.now();
17013
- await stateStore.initialize();
17014
- _startupTimings.stateStoreInitMs = Date.now() - stateStoreInitStart;
17015
- for (const key of storyKeys) {
17016
- const pendingState = _stories.get(key);
17017
- if (pendingState !== void 0) persistStoryState(key, pendingState).catch((err) => logger$27.warn({
17018
- err,
17019
- storyKey: key
17020
- }, "StateStore write failed during PENDING init"));
17021
- }
17022
- try {
17023
- const queryStoriesStart = Date.now();
17024
- const existingRecords = await stateStore.queryStories({});
17025
- _startupTimings.queryStoriesMs = Date.now() - queryStoriesStart;
17026
- for (const record of existingRecords) _stateStoreCache.set(record.storyKey, record);
17027
- } catch (err) {
17028
- logger$27.warn({ err }, "StateStore.queryStories() failed during init — status merge will be empty (best-effort)");
17029
- }
17030
- }
17031
16913
  if (ingestionServer !== void 0) {
17032
16914
  if (telemetryPersistence !== void 0) try {
17033
16915
  const pipelineLogger = logger$27;
@@ -17052,40 +16934,26 @@ function createImplementationOrchestrator(deps) {
17052
16934
  logger$27.info({ otlpEndpoint: _otlpEndpoint }, "OTLP telemetry ingestion active");
17053
16935
  } catch {}
17054
16936
  }
17055
- let contractDeclarations = [];
17056
- if (stateStore !== void 0) {
17057
- const queryContractsStart = Date.now();
17058
- const allContractRecords = await stateStore.queryContracts();
17059
- _startupTimings.queryContractsMs = Date.now() - queryContractsStart;
17060
- contractDeclarations = allContractRecords.map((r) => ({
17061
- storyKey: r.storyKey,
17062
- contractName: r.contractName,
17063
- direction: r.direction,
17064
- filePath: r.schemaPath,
17065
- ...r.transport !== void 0 ? { transport: r.transport } : {}
17066
- }));
17067
- } else {
17068
- const interfaceContractDecisions = await getDecisionsByCategory(db, "interface-contract");
17069
- contractDeclarations = interfaceContractDecisions.map((d) => {
17070
- try {
17071
- const parsed = JSON.parse(d.value);
17072
- const storyKey = typeof parsed.storyKey === "string" ? parsed.storyKey : "";
17073
- const contractName = typeof parsed.schemaName === "string" ? parsed.schemaName : "";
17074
- const direction = parsed.direction === "export" ? "export" : "import";
17075
- const filePath = typeof parsed.filePath === "string" ? parsed.filePath : "";
17076
- if (!storyKey || !contractName) return null;
17077
- return {
17078
- storyKey,
17079
- contractName,
17080
- direction,
17081
- filePath,
17082
- ...typeof parsed.transport === "string" ? { transport: parsed.transport } : {}
17083
- };
17084
- } catch {
17085
- return null;
17086
- }
17087
- }).filter((d) => d !== null);
17088
- }
16937
+ const interfaceContractDecisions = await getDecisionsByCategory(db, "interface-contract");
16938
+ const contractDeclarations = interfaceContractDecisions.map((d) => {
16939
+ try {
16940
+ const parsed = JSON.parse(d.value);
16941
+ const storyKey = typeof parsed.storyKey === "string" ? parsed.storyKey : "";
16942
+ const contractName = typeof parsed.schemaName === "string" ? parsed.schemaName : "";
16943
+ const direction = parsed.direction === "export" ? "export" : "import";
16944
+ const filePath = typeof parsed.filePath === "string" ? parsed.filePath : "";
16945
+ if (!storyKey || !contractName) return null;
16946
+ return {
16947
+ storyKey,
16948
+ contractName,
16949
+ direction,
16950
+ filePath,
16951
+ ...typeof parsed.transport === "string" ? { transport: parsed.transport } : {}
16952
+ };
16953
+ } catch {
16954
+ return null;
16955
+ }
16956
+ }).filter((d) => d !== null);
17089
16957
  const conflictDetectStart = Date.now();
17090
16958
  const { batches, edges: contractEdges } = detectConflictGroupsWithContracts(storyKeys, { moduleMap: pack.manifest.conflictGroups }, contractDeclarations);
17091
16959
  _startupTimings.conflictDetectMs = Date.now() - conflictDetectStart;
@@ -17222,38 +17090,6 @@ function createImplementationOrchestrator(deps) {
17222
17090
  mismatches: mismatches.length,
17223
17091
  verdict: mismatches.length === 0 ? "pass" : "fail"
17224
17092
  });
17225
- if (stateStore !== void 0) try {
17226
- const currentSprintContracts = (await stateStore.queryContracts()).filter((cr) => storyKeys.includes(cr.storyKey));
17227
- const verifiedAt = new Date().toISOString();
17228
- const contractsByStory = new Map();
17229
- for (const cr of currentSprintContracts) {
17230
- const existing = contractsByStory.get(cr.storyKey) ?? [];
17231
- existing.push(cr);
17232
- contractsByStory.set(cr.storyKey, existing);
17233
- }
17234
- for (const [sk, contracts] of contractsByStory) {
17235
- const records = contracts.map((cr) => {
17236
- const contractMismatches = (_contractMismatches ?? []).filter((m) => (m.exporter === sk || m.importer === sk) && m.contractName === cr.contractName);
17237
- if (contractMismatches.length > 0) return {
17238
- storyKey: sk,
17239
- contractName: cr.contractName,
17240
- verdict: "fail",
17241
- mismatchDescription: contractMismatches[0].mismatchDescription,
17242
- verifiedAt
17243
- };
17244
- return {
17245
- storyKey: sk,
17246
- contractName: cr.contractName,
17247
- verdict: "pass",
17248
- verifiedAt
17249
- };
17250
- });
17251
- await stateStore.setContractVerification(sk, records);
17252
- }
17253
- logger$27.info({ storyCount: contractsByStory.size }, "Contract verification results persisted to StateStore");
17254
- } catch (persistErr) {
17255
- logger$27.warn({ err: persistErr }, "Failed to persist contract verification results to StateStore");
17256
- }
17257
17093
  } catch (err) {
17258
17094
  logger$27.error({ err }, "Post-sprint contract verification threw an error — skipping");
17259
17095
  }
@@ -17287,7 +17123,6 @@ function createImplementationOrchestrator(deps) {
17287
17123
  } finally {
17288
17124
  process.off("SIGTERM", sigtermHandler);
17289
17125
  process.off("SIGINT", sigintHandler);
17290
- if (stateStore !== void 0) await stateStore.close().catch((err) => logger$27.warn({ err }, "StateStore.close() failed (best-effort)"));
17291
17126
  if (ingestionServer !== void 0) await ingestionServer.stop().catch((err) => logger$27.warn({ err }, "IngestionServer.stop() failed (best-effort)"));
17292
17127
  }
17293
17128
  }
@@ -47216,4 +47051,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
47216
47051
 
47217
47052
  //#endregion
47218
47053
  export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
47219
- //# sourceMappingURL=run-DBGt1IJy.js.map
47054
+ //# sourceMappingURL=run-BaEjWFS6.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.104",
3
+ "version": "0.20.106",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",