substrate-ai 0.2.25 → 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-CKvf6LgL.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-bigUnNya.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
@@ -172,6 +172,87 @@ interface StoryEscalationEvent {
172
172
  /** Issues list from the final review (may be empty) */
173
173
  issues: EscalationIssue[];
174
174
  }
175
+ /**
176
+ * Emitted when a dev-story agent reported COMPLETE but git diff shows no
177
+ * file changes in the working tree (phantom completion — Story 24-1).
178
+ */
179
+ interface StoryZeroDiffEscalationEvent {
180
+ type: 'story:zero-diff-escalation';
181
+ /** ISO-8601 timestamp generated at emit time */
182
+ ts: string;
183
+ /** Story key (e.g., "10-1") */
184
+ storyKey: string;
185
+ /** Always "zero-diff-on-complete" */
186
+ reason: string;
187
+ }
188
+ /**
189
+ * Emitted when the build verification command exits with a non-zero code
190
+ * or times out, before code-review is dispatched (Story 24-2).
191
+ */
192
+ interface StoryBuildVerificationFailedEvent {
193
+ type: 'story:build-verification-failed';
194
+ /** ISO-8601 timestamp generated at emit time */
195
+ ts: string;
196
+ /** Story key (e.g., "24-2") */
197
+ storyKey: string;
198
+ /** Exit code from the build command (-1 for timeout) */
199
+ exitCode: number;
200
+ /** Combined stdout+stderr output, truncated to 2000 chars */
201
+ output: string;
202
+ }
203
+ /**
204
+ * Emitted when the build verification command exits with code 0 (Story 24-2).
205
+ */
206
+ interface StoryBuildVerificationPassedEvent {
207
+ type: 'story:build-verification-passed';
208
+ /** ISO-8601 timestamp generated at emit time */
209
+ ts: string;
210
+ /** Story key (e.g., "24-2") */
211
+ storyKey: string;
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
+ }
175
256
  /**
176
257
  * Emitted for non-fatal warnings during pipeline execution
177
258
  * (e.g., token ceiling truncation, partial batch failures).
@@ -432,7 +513,7 @@ interface SupervisorExperimentErrorEvent {
432
513
  * }
433
514
  * ```
434
515
  */
435
- type PipelineEvent = PipelineStartEvent | PipelineCompleteEvent | StoryPhaseEvent | StoryDoneEvent | StoryEscalationEvent | StoryWarnEvent | StoryLogEvent | PipelineHeartbeatEvent | StoryStallEvent | 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
436
517
  //#region src/core/errors.d.ts
437
518
 
438
519
  /**
@@ -1018,6 +1099,11 @@ interface OrchestratorEvents {
1018
1099
  storyKey: string;
1019
1100
  msg: string;
1020
1101
  };
1102
+ /** Zero-diff detection gate: dev-story reported COMPLETE but git diff is empty (Story 24-1) */
1103
+ 'orchestrator:zero-diff-escalation': {
1104
+ storyKey: string;
1105
+ reason: string;
1106
+ };
1021
1107
  /** Implementation orchestrator has finished all stories */
1022
1108
  'orchestrator:complete': {
1023
1109
  totalStories: number;
@@ -1067,6 +1153,35 @@ interface OrchestratorEvents {
1067
1153
  affected_items: string[];
1068
1154
  }>;
1069
1155
  };
1156
+ /** Build verification command failed with non-zero exit or timeout */
1157
+ 'story:build-verification-failed': {
1158
+ storyKey: string;
1159
+ exitCode: number;
1160
+ /** Build output (stdout+stderr), truncated to 2000 chars */
1161
+ output: string;
1162
+ };
1163
+ /** Build verification command exited with code 0 */
1164
+ 'story:build-verification-passed': {
1165
+ storyKey: string;
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
+ };
1070
1185
  }
1071
1186
 
1072
1187
  //#endregion