substrate-ai 0.9.0 → 0.11.0

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.
Files changed (35) hide show
  1. package/dist/adapter-registry-DXLMTmfD.js +0 -0
  2. package/dist/adapter-registry-neBZrkr3.js +4 -0
  3. package/dist/cli/index.js +5594 -5951
  4. package/dist/decisions-C0pz9Clx.js +0 -0
  5. package/dist/{decisions-BDLp3tJB.js → decisions-DQZW0h9X.js} +2 -1
  6. package/dist/dist-eNB_v7Iy.js +10205 -0
  7. package/dist/errors-BvyMlvCX.js +74 -0
  8. package/dist/experimenter-Dos3NsCg.js +3 -0
  9. package/dist/health-BvYILeQQ.js +6 -0
  10. package/dist/{health-C-VRJruD.js → health-CiDi90gC.js} +57 -1850
  11. package/dist/{helpers-CpMs8VZX.js → helpers-DTp3VJ2-.js} +31 -121
  12. package/dist/index.d.ts +709 -266
  13. package/dist/index.js +5 -3
  14. package/dist/{logger-D2fS2ccL.js → logger-KeHncl-f.js} +2 -42
  15. package/dist/routing-CcBOCuC9.js +0 -0
  16. package/dist/{routing-CD8bIci_.js → routing-HaYsjEIS.js} +2 -2
  17. package/dist/{run-ClxNDHbr.js → run-CAUhTR7Y.js} +594 -4249
  18. package/dist/run-DPZOQOvB.js +9 -0
  19. package/dist/{upgrade-B1S61VXJ.js → upgrade-DFGrqjGI.js} +3 -3
  20. package/dist/{upgrade-BK0HrKA6.js → upgrade-DYdYuuJK.js} +3 -3
  21. package/dist/version-manager-impl-BmOWu8ml.js +0 -0
  22. package/dist/version-manager-impl-CKv6I1S0.js +4 -0
  23. package/package.json +5 -2
  24. package/dist/adapter-registry-D2zdMwVu.js +0 -840
  25. package/dist/adapter-registry-WAyFydN5.js +0 -4
  26. package/dist/config-migrator-CtGelIsG.js +0 -250
  27. package/dist/decisions-DhAA2HG2.js +0 -397
  28. package/dist/experimenter-D_N_7ZF3.js +0 -503
  29. package/dist/git-utils-DxPx6erV.js +0 -365
  30. package/dist/health-DMbNP9bw.js +0 -5
  31. package/dist/operational-BdcdmDqS.js +0 -374
  32. package/dist/routing-BVrxrM6v.js +0 -832
  33. package/dist/run-MAQ3Wuju.js +0 -10
  34. package/dist/version-manager-impl-BIxOe7gZ.js +0 -372
  35. package/dist/version-manager-impl-RrWs-CI6.js +0 -4
@@ -1,374 +0,0 @@
1
- //#region src/persistence/queries/metrics.ts
2
- /**
3
- * Write or update run-level metrics.
4
- *
5
- * Uses a portable delete-then-insert pattern inside a transaction to work on
6
- * both SQLite/WASM and Dolt/MySQL. When a row already exists, the `restarts`
7
- * and `is_baseline` values are preserved from the existing row (so any
8
- * `incrementRunRestarts()` calls made by the supervisor between the caller's
9
- * read and this write are not silently overwritten).
10
- */
11
- async function writeRunMetrics(adapter, input) {
12
- await adapter.transaction(async (tx) => {
13
- const existing = await tx.query("SELECT restarts, is_baseline FROM run_metrics WHERE run_id = ?", [input.run_id]);
14
- if (existing.length > 0) await tx.query("DELETE FROM run_metrics WHERE run_id = ?", [input.run_id]);
15
- const restarts = existing[0]?.restarts ?? input.restarts ?? 0;
16
- const isBaseline = existing[0]?.is_baseline ?? input.is_baseline ?? 0;
17
- await tx.query(`INSERT INTO run_metrics (
18
- run_id, methodology, status, started_at, completed_at,
19
- wall_clock_seconds, total_input_tokens, total_output_tokens, total_cost_usd,
20
- stories_attempted, stories_succeeded, stories_failed, stories_escalated,
21
- total_review_cycles, total_dispatches, concurrency_setting, max_concurrent_actual, restarts,
22
- is_baseline
23
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
24
- input.run_id,
25
- input.methodology,
26
- input.status,
27
- input.started_at,
28
- input.completed_at ?? null,
29
- input.wall_clock_seconds ?? 0,
30
- input.total_input_tokens ?? 0,
31
- input.total_output_tokens ?? 0,
32
- input.total_cost_usd ?? 0,
33
- input.stories_attempted ?? 0,
34
- input.stories_succeeded ?? 0,
35
- input.stories_failed ?? 0,
36
- input.stories_escalated ?? 0,
37
- input.total_review_cycles ?? 0,
38
- input.total_dispatches ?? 0,
39
- input.concurrency_setting ?? 1,
40
- input.max_concurrent_actual ?? 1,
41
- restarts,
42
- isBaseline
43
- ]);
44
- });
45
- }
46
- /**
47
- * Get run metrics for a specific run.
48
- */
49
- async function getRunMetrics(adapter, runId) {
50
- const rows = await adapter.query("SELECT * FROM run_metrics WHERE run_id = ?", [runId]);
51
- return rows[0];
52
- }
53
- /**
54
- * List the most recent N run metrics rows, newest first.
55
- */
56
- async function listRunMetrics(adapter, limit = 10) {
57
- return adapter.query("SELECT * FROM run_metrics ORDER BY started_at DESC LIMIT ?", [limit]);
58
- }
59
- /**
60
- * Tag a run as the baseline (clears any existing baseline first).
61
- */
62
- async function tagRunAsBaseline(adapter, runId) {
63
- await adapter.transaction(async (tx) => {
64
- await tx.query("UPDATE run_metrics SET is_baseline = 0");
65
- await tx.query("UPDATE run_metrics SET is_baseline = 1 WHERE run_id = ?", [runId]);
66
- });
67
- }
68
- /**
69
- * Get the current baseline run metrics (if any).
70
- */
71
- async function getBaselineRunMetrics(adapter) {
72
- const rows = await adapter.query("SELECT * FROM run_metrics WHERE is_baseline = 1 LIMIT 1");
73
- return rows[0];
74
- }
75
- /**
76
- * Increment the restart count for a run by 1.
77
- * Called by the supervisor each time it successfully restarts the pipeline.
78
- * If the run_id does not yet exist in run_metrics, a placeholder row is
79
- * inserted so the restart count is not lost — writeRunMetrics will overwrite
80
- * all other fields when the run reaches a terminal state.
81
- *
82
- * Uses a portable select-then-update/insert pattern inside a transaction to
83
- * work on both SQLite/WASM and Dolt/MySQL.
84
- */
85
- async function incrementRunRestarts(adapter, runId) {
86
- await adapter.transaction(async (tx) => {
87
- const existing = await tx.query("SELECT restarts FROM run_metrics WHERE run_id = ?", [runId]);
88
- if (existing.length > 0) await tx.query("UPDATE run_metrics SET restarts = ? WHERE run_id = ?", [existing[0].restarts + 1, runId]);
89
- else await tx.query(`INSERT INTO run_metrics (run_id, methodology, status, started_at, restarts)
90
- VALUES (?, 'unknown', 'running', ?, 1)`, [runId, new Date().toISOString()]);
91
- });
92
- }
93
- /**
94
- * Write or update story-level metrics.
95
- *
96
- * Uses a portable delete-then-insert pattern inside a transaction to work on
97
- * both SQLite/WASM and Dolt/MySQL. When a row already exists, the `started_at`
98
- * value is preserved from the existing row if the new value is null.
99
- */
100
- async function writeStoryMetrics(adapter, input) {
101
- await adapter.transaction(async (tx) => {
102
- const existing = await tx.query("SELECT started_at FROM story_metrics WHERE run_id = ? AND story_key = ?", [input.run_id, input.story_key]);
103
- if (existing.length > 0) await tx.query("DELETE FROM story_metrics WHERE run_id = ? AND story_key = ?", [input.run_id, input.story_key]);
104
- const startedAt = input.started_at ?? existing[0]?.started_at ?? null;
105
- await tx.query(`INSERT INTO story_metrics (
106
- run_id, story_key, result, phase_durations_json, started_at, completed_at,
107
- wall_clock_seconds, input_tokens, output_tokens, cost_usd,
108
- review_cycles, dispatches
109
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
110
- input.run_id,
111
- input.story_key,
112
- input.result,
113
- input.phase_durations_json ?? null,
114
- startedAt,
115
- input.completed_at ?? null,
116
- input.wall_clock_seconds ?? 0,
117
- input.input_tokens ?? 0,
118
- input.output_tokens ?? 0,
119
- input.cost_usd ?? 0,
120
- input.review_cycles ?? 0,
121
- input.dispatches ?? 0
122
- ]);
123
- });
124
- }
125
- /**
126
- * Get all story metrics for a given run.
127
- */
128
- async function getStoryMetricsForRun(adapter, runId) {
129
- return adapter.query("SELECT * FROM story_metrics WHERE run_id = ? ORDER BY id ASC", [runId]);
130
- }
131
- /**
132
- * Compare two runs and return percentage deltas for key numeric fields.
133
- * Positive deltas mean run B is larger/longer than run A.
134
- * Returns null if either run does not exist.
135
- */
136
- async function compareRunMetrics(adapter, runIdA, runIdB) {
137
- const a = await getRunMetrics(adapter, runIdA);
138
- const b = await getRunMetrics(adapter, runIdB);
139
- if (!a || !b) return null;
140
- const pct = (base, diff) => base === 0 ? null : Math.round(diff / base * 100 * 10) / 10;
141
- const inputDelta = b.total_input_tokens - a.total_input_tokens;
142
- const outputDelta = b.total_output_tokens - a.total_output_tokens;
143
- const clockDelta = (b.wall_clock_seconds ?? 0) - (a.wall_clock_seconds ?? 0);
144
- const cycleDelta = b.total_review_cycles - a.total_review_cycles;
145
- const costDelta = (b.total_cost_usd ?? 0) - (a.total_cost_usd ?? 0);
146
- return {
147
- run_id_a: runIdA,
148
- run_id_b: runIdB,
149
- token_input_delta: inputDelta,
150
- token_output_delta: outputDelta,
151
- token_input_pct: pct(a.total_input_tokens, inputDelta),
152
- token_output_pct: pct(a.total_output_tokens, outputDelta),
153
- wall_clock_delta_seconds: clockDelta,
154
- wall_clock_pct: pct(a.wall_clock_seconds ?? 0, clockDelta),
155
- review_cycles_delta: cycleDelta,
156
- review_cycles_pct: pct(a.total_review_cycles, cycleDelta),
157
- cost_delta: costDelta,
158
- cost_pct: pct(a.total_cost_usd ?? 0, costDelta)
159
- };
160
- }
161
- /**
162
- * Aggregate token usage from the token_usage table for a pipeline run.
163
- */
164
- async function aggregateTokenUsageForRun(adapter, runId) {
165
- const rows = await adapter.query(`SELECT
166
- COALESCE(SUM(input_tokens), 0) as input,
167
- COALESCE(SUM(output_tokens), 0) as output,
168
- COALESCE(SUM(cost_usd), 0) as cost
169
- FROM token_usage
170
- WHERE pipeline_run_id = ?`, [runId]);
171
- return rows[0] ?? {
172
- input: 0,
173
- output: 0,
174
- cost: 0
175
- };
176
- }
177
- /**
178
- * Aggregate token usage for a specific story within a pipeline run.
179
- * Matches rows where the metadata JSON contains the given storyKey.
180
- */
181
- async function aggregateTokenUsageForStory(adapter, runId, storyKey) {
182
- const rows = await adapter.query(`SELECT
183
- COALESCE(SUM(input_tokens), 0) as input,
184
- COALESCE(SUM(output_tokens), 0) as output,
185
- COALESCE(SUM(cost_usd), 0) as cost
186
- FROM token_usage
187
- WHERE pipeline_run_id = ?
188
- AND metadata IS NOT NULL
189
- AND metadata LIKE ?`, [runId, `%"storyKey":"${storyKey}"%`]);
190
- return rows[0] ?? {
191
- input: 0,
192
- output: 0,
193
- cost: 0
194
- };
195
- }
196
-
197
- //#endregion
198
- //#region src/persistence/schemas/operational.ts
199
- /**
200
- * Category and key-schema constants for operational findings in the decision store.
201
- *
202
- * These constants avoid string literals scattered across supervisor, orchestrator,
203
- * and experimenter code. Import them wherever you need to insert or query
204
- * operational decisions.
205
- */
206
- /**
207
- * Category for supervisor stall events and run-level summaries.
208
- *
209
- * Key schemas:
210
- * - Stall finding: "stall:{storyKey}:{timestamp}"
211
- * - Run summary: "run-summary:{runId}"
212
- *
213
- * Value shapes:
214
- *
215
- * Stall finding:
216
- * ```json
217
- * {
218
- * "phase": "string", // story phase at stall time, e.g. "code-review"
219
- * "staleness_secs": 700,
220
- * "attempt": 1, // restart attempt number (1-based)
221
- * "outcome": "recovered" // "recovered" | "failed" | "max-restarts-escalated"
222
- * }
223
- * ```
224
- *
225
- * Run summary:
226
- * ```json
227
- * {
228
- * "succeeded": ["1-1", "1-2"],
229
- * "failed": ["1-3"],
230
- * "escalated": [],
231
- * "total_restarts": 0,
232
- * "elapsed_seconds": 1234,
233
- * "total_input_tokens": 50000,
234
- * "total_output_tokens": 10000
235
- * }
236
- * ```
237
- */
238
- const OPERATIONAL_FINDING = "operational-finding";
239
- /**
240
- * Category for supervisor experiment results.
241
- *
242
- * Key schema: "experiment:{runId}:{timestamp}"
243
- *
244
- * Value shape:
245
- * ```json
246
- * {
247
- * "target_metric": "token_regression",
248
- * "before": 12000,
249
- * "after": 9500,
250
- * "verdict": "IMPROVED", // "IMPROVED" | "MIXED" | "REGRESSED"
251
- * "branch_name": "supervisor/experiment/abc12345-dev-story-token-regression"
252
- * }
253
- * ```
254
- */
255
- const EXPERIMENT_RESULT = "experiment-result";
256
- /**
257
- * Category for per-story wall-clock and efficiency metrics.
258
- *
259
- * Key schema: "{storyKey}:{runId}"
260
- *
261
- * Value shape:
262
- * ```json
263
- * {
264
- * "wall_clock_seconds": 180,
265
- * "input_tokens": 8000,
266
- * "output_tokens": 2000,
267
- * "review_cycles": 2,
268
- * "stalled": false
269
- * }
270
- * ```
271
- */
272
- const STORY_METRICS = "story-metrics";
273
- /**
274
- * Category for structured escalation diagnoses.
275
- *
276
- * Key schema: "{storyKey}:{runId}"
277
- *
278
- * Value shape:
279
- * ```json
280
- * {
281
- * "issueDistribution": "concentrated",
282
- * "severityProfile": "major-only",
283
- * "totalIssues": 3,
284
- * "blockerCount": 0,
285
- * "majorCount": 3,
286
- * "minorCount": 0,
287
- * "affectedFiles": ["src/foo.ts"],
288
- * "reviewCycles": 3,
289
- * "recommendedAction": "retry-targeted",
290
- * "rationale": "3 major issues concentrated in few files."
291
- * }
292
- * ```
293
- */
294
- const ESCALATION_DIAGNOSIS = "escalation-diagnosis";
295
- /**
296
- * Category for per-story outcome findings (learning loop).
297
- *
298
- * Key schema: "{storyKey}:{runId}"
299
- *
300
- * Value shape:
301
- * ```json
302
- * {
303
- * "storyKey": "22-1",
304
- * "outcome": "complete",
305
- * "reviewCycles": 2,
306
- * "verdictHistory": ["NEEDS_MINOR_FIXES", "SHIP_IT"],
307
- * "recurringPatterns": ["missing error handling"]
308
- * }
309
- * ```
310
- */
311
- const STORY_OUTCOME = "story-outcome";
312
- /**
313
- * Category for post-implementation test expansion findings generated per-story.
314
- *
315
- * Key schema: "{storyKey}:{runId}"
316
- *
317
- * Value shape:
318
- * ```json
319
- * {
320
- * "expansion_priority": "medium", // "low" | "medium" | "high"
321
- * "coverage_gaps": [
322
- * {
323
- * "ac_ref": "AC1",
324
- * "description": "Happy path not exercised at module boundary",
325
- * "gap_type": "missing-integration" // "missing-e2e" | "missing-integration" | "unit-only"
326
- * }
327
- * ],
328
- * "suggested_tests": [
329
- * {
330
- * "test_name": "runFoo integration happy path",
331
- * "test_type": "integration", // "e2e" | "integration" | "unit"
332
- * "description": "Test runFoo with real DB instance",
333
- * "target_ac": "AC1" // optional
334
- * }
335
- * ],
336
- * "notes": "Optional free-text notes", // optional
337
- * "error": "Error message if fallback" // optional — present only on graceful fallback
338
- * }
339
- * ```
340
- */
341
- const TEST_EXPANSION_FINDING = "test-expansion-finding";
342
- /**
343
- * Category for pre-implementation test plans generated per-story.
344
- *
345
- * Key schema: "{storyKey}"
346
- *
347
- * Value shape:
348
- * ```json
349
- * {
350
- * "test_files": ["src/modules/foo/__tests__/foo.test.ts"],
351
- * "test_categories": ["unit", "integration"],
352
- * "coverage_notes": "AC1 covered by foo.test.ts"
353
- * }
354
- * ```
355
- */
356
- const TEST_PLAN = "test-plan";
357
- /**
358
- * Category for advisory notes persisted when a code review returns LGTM_WITH_NOTES.
359
- *
360
- * Key schema: "{storyKey}:{runId}"
361
- *
362
- * Value shape:
363
- * ```json
364
- * {
365
- * "storyKey": "25-3",
366
- * "notes": "Consider extracting the helper into a shared module for reuse."
367
- * }
368
- * ```
369
- */
370
- const ADVISORY_NOTES = "advisory-notes";
371
-
372
- //#endregion
373
- export { ADVISORY_NOTES, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, OPERATIONAL_FINDING, STORY_METRICS, STORY_OUTCOME, TEST_EXPANSION_FINDING, TEST_PLAN, aggregateTokenUsageForRun, aggregateTokenUsageForStory, compareRunMetrics, getBaselineRunMetrics, getRunMetrics, getStoryMetricsForRun, incrementRunRestarts, listRunMetrics, tagRunAsBaseline, writeRunMetrics, writeStoryMetrics };
374
- //# sourceMappingURL=operational-BdcdmDqS.js.map