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 +49 -3
- package/dist/index.d.ts +116 -1
- package/dist/{run-CKvf6LgL.js → run-DG5j6vJI.js} +703 -196
- package/dist/{run-bigUnNya.js → run-jLeEo8FW.js} +1 -1
- package/package.json +1 -1
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-
|
|
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
|
-
|
|
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-
|
|
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
|