substrate-ai 0.2.26 → 0.2.27

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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-CEtHPG4I.js";
2
+ import { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-DG5j6vJI.js";
3
3
  import { createLogger, deepMask } from "../logger-D2fS2ccL.js";
4
4
  import { AdapterRegistry, ConfigError, ConfigIncompatibleFormatError } from "../errors-CswS7Mzg.js";
5
5
  import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator } from "../version-manager-impl-CZ6KF1Ds.js";
@@ -1615,7 +1615,53 @@ async function runStatusAction(options) {
1615
1615
  const storiesCount = db.prepare(`SELECT COUNT(*) as cnt FROM requirements WHERE pipeline_run_id = ? AND source = 'solutioning-phase'`).get(run.id)?.cnt ?? 0;
1616
1616
  if (outputFormat === "json") {
1617
1617
  const statusOutput = buildPipelineStatusOutput(run, tokenSummary, decisionsCount, storiesCount);
1618
- process.stdout.write(formatOutput(statusOutput, "json", true) + "\n");
1618
+ const storyMetricsRows = getStoryMetricsForRun(db, run.id);
1619
+ const storyMetricsV2 = storyMetricsRows.map((row) => {
1620
+ const phaseBreakdown = {};
1621
+ try {
1622
+ if (row.phase_durations_json) {
1623
+ const parsed = JSON.parse(row.phase_durations_json);
1624
+ for (const [phase, secs] of Object.entries(parsed)) phaseBreakdown[phase] = Math.round(secs * 1e3);
1625
+ }
1626
+ } catch {}
1627
+ return {
1628
+ story_key: row.story_key,
1629
+ result: row.result,
1630
+ wall_clock_ms: Math.round((row.wall_clock_seconds ?? 0) * 1e3),
1631
+ phase_breakdown: phaseBreakdown,
1632
+ tokens: {
1633
+ input: row.input_tokens ?? 0,
1634
+ output: row.output_tokens ?? 0
1635
+ },
1636
+ review_cycles: row.review_cycles ?? 0,
1637
+ dispatches: row.dispatches ?? 0
1638
+ };
1639
+ });
1640
+ let pipelineWallClockMs = 0;
1641
+ try {
1642
+ const createdAt = parseDbTimestampAsUtc(run.created_at);
1643
+ const endTimestamp = run.status === "running" ? new Date() : parseDbTimestampAsUtc(run.updated_at);
1644
+ pipelineWallClockMs = Math.max(0, endTimestamp.getTime() - createdAt.getTime());
1645
+ } catch {}
1646
+ const totalReviewCycles = storyMetricsRows.reduce((sum, r) => sum + (r.review_cycles ?? 0), 0);
1647
+ const totalInputTokens = storyMetricsRows.reduce((sum, r) => sum + (r.input_tokens ?? 0), 0);
1648
+ const totalOutputTokens = storyMetricsRows.reduce((sum, r) => sum + (r.output_tokens ?? 0), 0);
1649
+ const completedCount = storyMetricsRows.filter((r) => r.result === "success").length;
1650
+ const storiesPerHour = pipelineWallClockMs > 0 ? Math.round(completedCount / (pipelineWallClockMs / 36e5) * 100) / 100 : 0;
1651
+ const totalCostUsd = storyMetricsRows.reduce((sum, r) => sum + (r.cost_usd ?? 0), 0);
1652
+ const enhancedOutput = {
1653
+ ...statusOutput,
1654
+ story_metrics: storyMetricsV2,
1655
+ pipeline_metrics: {
1656
+ total_wall_clock_ms: pipelineWallClockMs,
1657
+ total_review_cycles: totalReviewCycles,
1658
+ total_input_tokens: totalInputTokens,
1659
+ total_output_tokens: totalOutputTokens,
1660
+ stories_per_hour: storiesPerHour,
1661
+ cost_usd: totalCostUsd
1662
+ }
1663
+ };
1664
+ process.stdout.write(formatOutput(enhancedOutput, "json", true) + "\n");
1619
1665
  } else {
1620
1666
  let hasPhaseHistory = false;
1621
1667
  try {
@@ -2842,7 +2888,7 @@ async function runSupervisorAction(options, deps = {}) {
2842
2888
  const expDb = expDbWrapper.db;
2843
2889
  const { runRunAction: runPipeline } = await import(
2844
2890
  /* @vite-ignore */
2845
- "../run-BXKRGSeL.js"
2891
+ "../run-jLeEo8FW.js"
2846
2892
  );
2847
2893
  const runStoryFn = async (opts) => {
2848
2894
  const exitCode = await runPipeline({
package/dist/index.d.ts CHANGED
@@ -210,6 +210,49 @@ interface StoryBuildVerificationPassedEvent {
210
210
  /** Story key (e.g., "24-2") */
211
211
  storyKey: string;
212
212
  }
213
+ /**
214
+ * Emitted (non-blocking) when a dev-story modifies .ts files that export
215
+ * shared TypeScript interfaces or types, and those names are referenced by
216
+ * test files outside the same module.
217
+ *
218
+ * Signals potential stale-mock risk. The story still proceeds to code-review.
219
+ * (Story 24-3)
220
+ */
221
+ interface StoryInterfaceChangeWarningEvent {
222
+ type: 'story:interface-change-warning';
223
+ /** ISO-8601 timestamp generated at emit time */
224
+ ts: string;
225
+ /** Story key (e.g., "24-3") */
226
+ storyKey: string;
227
+ /** Exported interface/type names found in modified files */
228
+ modifiedInterfaces: string[];
229
+ /** Test file paths (relative to project root) that reference the modified interface names */
230
+ potentiallyAffectedTests: string[];
231
+ }
232
+ /**
233
+ * Emitted when a story reaches a terminal state (COMPLETE, ESCALATED, or
234
+ * max retries), providing a metrics snapshot for observability (Story 24-4).
235
+ */
236
+ interface StoryMetricsEvent {
237
+ type: 'story:metrics';
238
+ /** ISO-8601 timestamp generated at emit time */
239
+ ts: string;
240
+ /** Story key (e.g., "24-4") */
241
+ storyKey: string;
242
+ /** Total wall-clock duration in milliseconds */
243
+ wallClockMs: number;
244
+ /** Per-phase duration in milliseconds: phase name → ms */
245
+ phaseBreakdown: Record<string, number>;
246
+ /** Token counts from the adapter (accumulated across all dispatches) */
247
+ tokens: {
248
+ input: number;
249
+ output: number;
250
+ };
251
+ /** Number of code-review cycles completed */
252
+ reviewCycles: number;
253
+ /** Total number of agent dispatches for this story */
254
+ dispatches: number;
255
+ }
213
256
  /**
214
257
  * Emitted for non-fatal warnings during pipeline execution
215
258
  * (e.g., token ceiling truncation, partial batch failures).
@@ -470,7 +513,7 @@ interface SupervisorExperimentErrorEvent {
470
513
  * }
471
514
  * ```
472
515
  */
473
- type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | StoryPhaseEvent | StoryDoneEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | StoryZeroDiffEscalationEvent | StoryBuildVerificationFailedEvent | StoryBuildVerificationPassedEvent | SupervisorPollEvent | SupervisorKillEvent | SupervisorRestartEvent | SupervisorAbortEvent | SupervisorSummaryEvent | SupervisorAnalysisCompleteEvent | SupervisorAnalysisErrorEvent | SupervisorExperimentStartEvent | SupervisorExperimentSkipEvent | SupervisorExperimentRecommendationsEvent | SupervisorExperimentCompleteEvent | SupervisorExperimentErrorEvent; //#endregion
516
+ type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | StoryPhaseEvent | StoryDoneEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | StoryZeroDiffEscalationEvent | StoryBuildVerificationFailedEvent | StoryBuildVerificationPassedEvent | StoryInterfaceChangeWarningEvent | StoryMetricsEvent | SupervisorPollEvent | SupervisorKillEvent | SupervisorRestartEvent | SupervisorAbortEvent | SupervisorSummaryEvent | SupervisorAnalysisCompleteEvent | SupervisorAnalysisErrorEvent | SupervisorExperimentStartEvent | SupervisorExperimentSkipEvent | SupervisorExperimentRecommendationsEvent | SupervisorExperimentCompleteEvent | SupervisorExperimentErrorEvent; //#endregion
474
517
  //#region src/core/errors.d.ts
475
518
 
476
519
  /**
@@ -1121,6 +1164,24 @@ interface OrchestratorEvents {
1121
1164
  'story:build-verification-passed': {
1122
1165
  storyKey: string;
1123
1166
  };
1167
+ /** Non-blocking warning: modified .ts files export shared interfaces referenced by cross-module tests */
1168
+ 'story:interface-change-warning': {
1169
+ storyKey: string;
1170
+ modifiedInterfaces: string[];
1171
+ potentiallyAffectedTests: string[];
1172
+ };
1173
+ /** Per-story metrics snapshot emitted when a story reaches a terminal state (Story 24-4) */
1174
+ 'story:metrics': {
1175
+ storyKey: string;
1176
+ wallClockMs: number;
1177
+ phaseBreakdown: Record<string, number>;
1178
+ tokens: {
1179
+ input: number;
1180
+ output: number;
1181
+ };
1182
+ reviewCycles: number;
1183
+ dispatches: number;
1184
+ };
1124
1185
  }
1125
1186
 
1126
1187
  //#endregion