@substrate-ai/sdlc 0.19.54

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 (166) hide show
  1. package/dist/events.d.ts +336 -0
  2. package/dist/events.d.ts.map +1 -0
  3. package/dist/events.js +11 -0
  4. package/dist/events.js.map +1 -0
  5. package/dist/gating/conflict-detector.d.ts +59 -0
  6. package/dist/gating/conflict-detector.d.ts.map +1 -0
  7. package/dist/gating/conflict-detector.js +101 -0
  8. package/dist/gating/conflict-detector.js.map +1 -0
  9. package/dist/gating/dispatch-gate.d.ts +42 -0
  10. package/dist/gating/dispatch-gate.d.ts.map +1 -0
  11. package/dist/gating/dispatch-gate.js +197 -0
  12. package/dist/gating/dispatch-gate.js.map +1 -0
  13. package/dist/gating/index.d.ts +9 -0
  14. package/dist/gating/index.d.ts.map +1 -0
  15. package/dist/gating/index.js +8 -0
  16. package/dist/gating/index.js.map +1 -0
  17. package/dist/gating/types.d.ts +98 -0
  18. package/dist/gating/types.d.ts.map +1 -0
  19. package/dist/gating/types.js +8 -0
  20. package/dist/gating/types.js.map +1 -0
  21. package/dist/handlers/event-bridge.d.ts +56 -0
  22. package/dist/handlers/event-bridge.d.ts.map +1 -0
  23. package/dist/handlers/event-bridge.js +140 -0
  24. package/dist/handlers/event-bridge.js.map +1 -0
  25. package/dist/handlers/index.d.ts +15 -0
  26. package/dist/handlers/index.d.ts.map +1 -0
  27. package/dist/handlers/index.js +14 -0
  28. package/dist/handlers/index.js.map +1 -0
  29. package/dist/handlers/sdlc-code-review-handler.d.ts +119 -0
  30. package/dist/handlers/sdlc-code-review-handler.d.ts.map +1 -0
  31. package/dist/handlers/sdlc-code-review-handler.js +131 -0
  32. package/dist/handlers/sdlc-code-review-handler.js.map +1 -0
  33. package/dist/handlers/sdlc-create-story-handler.d.ts +97 -0
  34. package/dist/handlers/sdlc-create-story-handler.d.ts.map +1 -0
  35. package/dist/handlers/sdlc-create-story-handler.js +91 -0
  36. package/dist/handlers/sdlc-create-story-handler.js.map +1 -0
  37. package/dist/handlers/sdlc-dev-story-handler.d.ts +121 -0
  38. package/dist/handlers/sdlc-dev-story-handler.d.ts.map +1 -0
  39. package/dist/handlers/sdlc-dev-story-handler.js +288 -0
  40. package/dist/handlers/sdlc-dev-story-handler.js.map +1 -0
  41. package/dist/handlers/sdlc-phase-handler.d.ts +32 -0
  42. package/dist/handlers/sdlc-phase-handler.d.ts.map +1 -0
  43. package/dist/handlers/sdlc-phase-handler.js +166 -0
  44. package/dist/handlers/sdlc-phase-handler.js.map +1 -0
  45. package/dist/handlers/types.d.ts +132 -0
  46. package/dist/handlers/types.d.ts.map +1 -0
  47. package/dist/handlers/types.js +10 -0
  48. package/dist/handlers/types.js.map +1 -0
  49. package/dist/index.d.ts +8 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +14 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/learning/failure-classifier.d.ts +23 -0
  54. package/dist/learning/failure-classifier.d.ts.map +1 -0
  55. package/dist/learning/failure-classifier.js +75 -0
  56. package/dist/learning/failure-classifier.js.map +1 -0
  57. package/dist/learning/finding-classifier.d.ts +25 -0
  58. package/dist/learning/finding-classifier.d.ts.map +1 -0
  59. package/dist/learning/finding-classifier.js +37 -0
  60. package/dist/learning/finding-classifier.js.map +1 -0
  61. package/dist/learning/finding-lifecycle.d.ts +69 -0
  62. package/dist/learning/finding-lifecycle.d.ts.map +1 -0
  63. package/dist/learning/finding-lifecycle.js +162 -0
  64. package/dist/learning/finding-lifecycle.js.map +1 -0
  65. package/dist/learning/finding-store.d.ts +16 -0
  66. package/dist/learning/finding-store.d.ts.map +1 -0
  67. package/dist/learning/finding-store.js +26 -0
  68. package/dist/learning/finding-store.js.map +1 -0
  69. package/dist/learning/findings-injector.d.ts +34 -0
  70. package/dist/learning/findings-injector.d.ts.map +1 -0
  71. package/dist/learning/findings-injector.js +140 -0
  72. package/dist/learning/findings-injector.js.map +1 -0
  73. package/dist/learning/index.d.ts +8 -0
  74. package/dist/learning/index.d.ts.map +1 -0
  75. package/dist/learning/index.js +10 -0
  76. package/dist/learning/index.js.map +1 -0
  77. package/dist/learning/relevance-scorer.d.ts +25 -0
  78. package/dist/learning/relevance-scorer.d.ts.map +1 -0
  79. package/dist/learning/relevance-scorer.js +49 -0
  80. package/dist/learning/relevance-scorer.js.map +1 -0
  81. package/dist/learning/types.d.ts +55 -0
  82. package/dist/learning/types.d.ts.map +1 -0
  83. package/dist/learning/types.js +36 -0
  84. package/dist/learning/types.js.map +1 -0
  85. package/dist/orchestrator/graph-orchestrator.d.ts +208 -0
  86. package/dist/orchestrator/graph-orchestrator.d.ts.map +1 -0
  87. package/dist/orchestrator/graph-orchestrator.js +213 -0
  88. package/dist/orchestrator/graph-orchestrator.js.map +1 -0
  89. package/dist/run-manifest/cli-flags.d.ts +11 -0
  90. package/dist/run-manifest/cli-flags.d.ts.map +1 -0
  91. package/dist/run-manifest/cli-flags.js +10 -0
  92. package/dist/run-manifest/cli-flags.js.map +1 -0
  93. package/dist/run-manifest/index.d.ts +10 -0
  94. package/dist/run-manifest/index.d.ts.map +1 -0
  95. package/dist/run-manifest/index.js +10 -0
  96. package/dist/run-manifest/index.js.map +1 -0
  97. package/dist/run-model/cli-flags.d.ts +27 -0
  98. package/dist/run-model/cli-flags.d.ts.map +1 -0
  99. package/dist/run-model/cli-flags.js +31 -0
  100. package/dist/run-model/cli-flags.js.map +1 -0
  101. package/dist/run-model/index.d.ts +21 -0
  102. package/dist/run-model/index.d.ts.map +1 -0
  103. package/dist/run-model/index.js +19 -0
  104. package/dist/run-model/index.js.map +1 -0
  105. package/dist/run-model/per-story-state.d.ts +62 -0
  106. package/dist/run-model/per-story-state.d.ts.map +1 -0
  107. package/dist/run-model/per-story-state.js +70 -0
  108. package/dist/run-model/per-story-state.js.map +1 -0
  109. package/dist/run-model/recovery-history.d.ts +56 -0
  110. package/dist/run-model/recovery-history.d.ts.map +1 -0
  111. package/dist/run-model/recovery-history.js +83 -0
  112. package/dist/run-model/recovery-history.js.map +1 -0
  113. package/dist/run-model/run-manifest.d.ts +146 -0
  114. package/dist/run-model/run-manifest.d.ts.map +1 -0
  115. package/dist/run-model/run-manifest.js +481 -0
  116. package/dist/run-model/run-manifest.js.map +1 -0
  117. package/dist/run-model/schemas.d.ts +117 -0
  118. package/dist/run-model/schemas.d.ts.map +1 -0
  119. package/dist/run-model/schemas.js +83 -0
  120. package/dist/run-model/schemas.js.map +1 -0
  121. package/dist/run-model/supervisor-lock.d.ts +104 -0
  122. package/dist/run-model/supervisor-lock.d.ts.map +1 -0
  123. package/dist/run-model/supervisor-lock.js +284 -0
  124. package/dist/run-model/supervisor-lock.js.map +1 -0
  125. package/dist/run-model/types.d.ts +74 -0
  126. package/dist/run-model/types.d.ts.map +1 -0
  127. package/dist/run-model/types.js +8 -0
  128. package/dist/run-model/types.js.map +1 -0
  129. package/dist/run-model/verification-result.d.ts +60 -0
  130. package/dist/run-model/verification-result.d.ts.map +1 -0
  131. package/dist/run-model/verification-result.js +55 -0
  132. package/dist/run-model/verification-result.js.map +1 -0
  133. package/dist/verification/checks/acceptance-criteria-evidence-check.d.ts +21 -0
  134. package/dist/verification/checks/acceptance-criteria-evidence-check.d.ts.map +1 -0
  135. package/dist/verification/checks/acceptance-criteria-evidence-check.js +159 -0
  136. package/dist/verification/checks/acceptance-criteria-evidence-check.js.map +1 -0
  137. package/dist/verification/checks/build-check.d.ts +52 -0
  138. package/dist/verification/checks/build-check.d.ts.map +1 -0
  139. package/dist/verification/checks/build-check.js +160 -0
  140. package/dist/verification/checks/build-check.js.map +1 -0
  141. package/dist/verification/checks/index.d.ts +15 -0
  142. package/dist/verification/checks/index.d.ts.map +1 -0
  143. package/dist/verification/checks/index.js +15 -0
  144. package/dist/verification/checks/index.js.map +1 -0
  145. package/dist/verification/checks/phantom-review-check.d.ts +29 -0
  146. package/dist/verification/checks/phantom-review-check.d.ts.map +1 -0
  147. package/dist/verification/checks/phantom-review-check.js +70 -0
  148. package/dist/verification/checks/phantom-review-check.js.map +1 -0
  149. package/dist/verification/checks/trivial-output-check.d.ts +47 -0
  150. package/dist/verification/checks/trivial-output-check.d.ts.map +1 -0
  151. package/dist/verification/checks/trivial-output-check.js +72 -0
  152. package/dist/verification/checks/trivial-output-check.js.map +1 -0
  153. package/dist/verification/index.d.ts +13 -0
  154. package/dist/verification/index.d.ts.map +1 -0
  155. package/dist/verification/index.js +13 -0
  156. package/dist/verification/index.js.map +1 -0
  157. package/dist/verification/types.d.ts +149 -0
  158. package/dist/verification/types.d.ts.map +1 -0
  159. package/dist/verification/types.js +12 -0
  160. package/dist/verification/types.js.map +1 -0
  161. package/dist/verification/verification-pipeline.d.ts +65 -0
  162. package/dist/verification/verification-pipeline.d.ts.map +1 -0
  163. package/dist/verification/verification-pipeline.js +149 -0
  164. package/dist/verification/verification-pipeline.js.map +1 -0
  165. package/graphs/sdlc-pipeline.dot +42 -0
  166. package/package.json +22 -0
@@ -0,0 +1,481 @@
1
+ /**
2
+ * RunManifest — atomic file-backed run state — Story 52-1.
3
+ *
4
+ * Provides typed read/write operations with atomic file replacement
5
+ * so run state survives process crashes without corruption.
6
+ *
7
+ * File layout (relative to baseDir):
8
+ * {run-id}.json — primary manifest
9
+ * {run-id}.json.bak — backup written before rename
10
+ * {run-id}.json.tmp — temporary write target (fsync'd before rename)
11
+ */
12
+ import { promises as fs } from 'node:fs';
13
+ import { join } from 'node:path';
14
+ import { RunManifestSchema, ManifestReadError } from './schemas.js';
15
+ // ---------------------------------------------------------------------------
16
+ // Helpers
17
+ // ---------------------------------------------------------------------------
18
+ /** Default base directory for run manifests. */
19
+ function defaultBaseDir() {
20
+ return join(process.cwd(), '.substrate', 'runs');
21
+ }
22
+ /** Build the primary manifest path for a given run ID. */
23
+ function primaryPath(baseDir, runId) {
24
+ return join(baseDir, `${runId}.json`);
25
+ }
26
+ /** Build the backup path. */
27
+ function bakPath(baseDir, runId) {
28
+ return join(baseDir, `${runId}.json.bak`);
29
+ }
30
+ /** Build the temporary write path. */
31
+ function tmpPath(baseDir, runId) {
32
+ return join(baseDir, `${runId}.json.tmp`);
33
+ }
34
+ /**
35
+ * Attempt to read and parse a manifest file.
36
+ * Returns the parsed data, or null if the file is missing or fails Zod validation.
37
+ */
38
+ async function tryReadFile(filePath) {
39
+ try {
40
+ const raw = await fs.readFile(filePath, 'utf-8');
41
+ let parsed;
42
+ try {
43
+ parsed = JSON.parse(raw);
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ const result = RunManifestSchema.safeParse(parsed);
49
+ if (!result.success) {
50
+ return null;
51
+ }
52
+ return result.data;
53
+ }
54
+ catch {
55
+ // File missing or unreadable
56
+ return null;
57
+ }
58
+ }
59
+ /**
60
+ * Build a minimal RunManifestData from Dolt pipeline_runs table.
61
+ * Used in degraded-mode when all file sources fail.
62
+ */
63
+ async function reconstructFromDolt(runId, adapter) {
64
+ try {
65
+ const rows = await adapter.query('SELECT id, config_json, created_at, updated_at FROM pipeline_runs WHERE id = ?', [runId]);
66
+ if (rows.length === 0) {
67
+ return null;
68
+ }
69
+ const row = rows[0];
70
+ let cliFlags = {};
71
+ if (row.config_json) {
72
+ try {
73
+ const parsed = JSON.parse(row.config_json);
74
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
75
+ cliFlags = parsed;
76
+ }
77
+ }
78
+ catch {
79
+ // ignore parse failure
80
+ }
81
+ }
82
+ const now = new Date().toISOString();
83
+ const data = {
84
+ run_id: runId,
85
+ cli_flags: cliFlags,
86
+ story_scope: [],
87
+ supervisor_pid: null,
88
+ supervisor_session_id: null,
89
+ per_story_state: {},
90
+ recovery_history: [],
91
+ cost_accumulation: { per_story: {}, run_total: 0 },
92
+ pending_proposals: [],
93
+ generation: 0,
94
+ created_at: row.created_at ?? now,
95
+ updated_at: row.updated_at ?? now,
96
+ };
97
+ return data;
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // RunManifest class
105
+ // ---------------------------------------------------------------------------
106
+ /**
107
+ * Typed, atomic file-backed run manifest.
108
+ *
109
+ * Each instance is bound to a specific run ID and base directory.
110
+ * Use `RunManifest.create()` to initialize a new manifest,
111
+ * or `RunManifest.read()` to load an existing one.
112
+ */
113
+ export class RunManifest {
114
+ runId;
115
+ baseDir;
116
+ /** Optional Dolt adapter for degraded-mode fallback on read. */
117
+ doltAdapter;
118
+ constructor(runId, baseDir = defaultBaseDir(), doltAdapter = null) {
119
+ this.runId = runId;
120
+ this.baseDir = baseDir;
121
+ this.doltAdapter = doltAdapter;
122
+ }
123
+ // -------------------------------------------------------------------------
124
+ // Path helpers (instance methods for convenience)
125
+ // -------------------------------------------------------------------------
126
+ get primaryPath() {
127
+ return primaryPath(this.baseDir, this.runId);
128
+ }
129
+ get bakPath() {
130
+ return bakPath(this.baseDir, this.runId);
131
+ }
132
+ get tmpPath() {
133
+ return tmpPath(this.baseDir, this.runId);
134
+ }
135
+ // -------------------------------------------------------------------------
136
+ // read() — instance convenience wrapper
137
+ // -------------------------------------------------------------------------
138
+ /**
139
+ * Read this manifest from disk (multi-tier fallback).
140
+ *
141
+ * Delegates to `RunManifest.read()` with this instance's runId, baseDir,
142
+ * and doltAdapter. Primarily used by `SupervisorLock` (and tests that mock it).
143
+ *
144
+ * @throws ManifestReadError if all sources fail
145
+ */
146
+ async read() {
147
+ return RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
148
+ }
149
+ // -------------------------------------------------------------------------
150
+ // update() — partial atomic update
151
+ // -------------------------------------------------------------------------
152
+ /**
153
+ * Atomically update specific fields in the manifest.
154
+ *
155
+ * Reads the current manifest, merges in the provided partial data (shallow
156
+ * merge), then writes the result atomically. Generation is incremented and
157
+ * `updated_at` is refreshed by `write()`.
158
+ *
159
+ * Callers should pass only the fields they intend to change. Do NOT use this
160
+ * to change `run_id` or `created_at` — those are immutable after creation.
161
+ *
162
+ * @throws ManifestReadError if the current manifest cannot be read
163
+ */
164
+ async update(partial) {
165
+ const current = await this.read();
166
+ const merged = {
167
+ ...current,
168
+ ...partial,
169
+ };
170
+ await this.write(merged);
171
+ }
172
+ // -------------------------------------------------------------------------
173
+ // write()
174
+ // -------------------------------------------------------------------------
175
+ /**
176
+ * Atomically write the manifest to disk.
177
+ *
178
+ * Sequence:
179
+ * 1. Auto-increment `generation`, set `updated_at`
180
+ * 2. Serialize to JSON and validate round-trip
181
+ * 3. Ensure baseDir exists (mkdir -p)
182
+ * 4. Write to `.tmp` via open → write → datasync → close (fsync)
183
+ * 5. If primary exists, copy to `.bak`
184
+ * 6. Rename `.tmp` → primary path
185
+ */
186
+ async write(data) {
187
+ // Read current generation from disk to increment correctly
188
+ let currentGeneration = 0;
189
+ const existing = await tryReadFile(this.primaryPath);
190
+ if (existing !== null) {
191
+ currentGeneration = existing.generation;
192
+ }
193
+ const fullData = {
194
+ ...data,
195
+ generation: currentGeneration + 1,
196
+ updated_at: new Date().toISOString(),
197
+ };
198
+ // Serialize and validate round-trip
199
+ const json = JSON.stringify(fullData, null, 2);
200
+ // Validate parse round-trip — if this throws, do not proceed
201
+ JSON.parse(json);
202
+ // Ensure base directory exists
203
+ await fs.mkdir(this.baseDir, { recursive: true });
204
+ // Write to .tmp using open → write → datasync → close (NOT writeFile — no fsync)
205
+ const tmp = this.tmpPath;
206
+ const fileHandle = await fs.open(tmp, 'w');
207
+ try {
208
+ await fileHandle.write(json, 0, 'utf-8');
209
+ await fileHandle.datasync();
210
+ }
211
+ finally {
212
+ await fileHandle.close();
213
+ }
214
+ // Backup current primary to .bak (if primary exists)
215
+ try {
216
+ await fs.copyFile(this.primaryPath, this.bakPath);
217
+ }
218
+ catch {
219
+ // Primary does not exist yet — no backup needed
220
+ }
221
+ // Atomic rename: .tmp → primary
222
+ await fs.rename(tmp, this.primaryPath);
223
+ }
224
+ // -------------------------------------------------------------------------
225
+ // Static factory: open()
226
+ // -------------------------------------------------------------------------
227
+ /**
228
+ * Return a bound `RunManifest` instance without performing any file I/O.
229
+ *
230
+ * Use `open()` when you want to call instance methods (`read()`, `patchCLIFlags()`)
231
+ * on an existing run without reading the manifest upfront.
232
+ *
233
+ * ```typescript
234
+ * await RunManifest.open(runId, runsDir).patchCLIFlags(cliFlags)
235
+ * ```
236
+ */
237
+ static open(runId, baseDir = defaultBaseDir(), doltAdapter = null) {
238
+ return new RunManifest(runId, baseDir, doltAdapter);
239
+ }
240
+ // -------------------------------------------------------------------------
241
+ // Instance: patchCLIFlags()
242
+ // -------------------------------------------------------------------------
243
+ /**
244
+ * Read the current manifest (or create a minimal default), merge the provided
245
+ * CLI flags into `cli_flags`, and write the result atomically.
246
+ *
247
+ * Non-fatal: callers should wrap in try/catch and log a warning on failure.
248
+ * The pipeline must not abort if manifest write fails.
249
+ */
250
+ async patchCLIFlags(flags) {
251
+ let existingData;
252
+ try {
253
+ const read = await RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
254
+ // Strip generation and updated_at — write() re-computes them
255
+ const { generation: _gen, updated_at: _ts, ...rest } = read;
256
+ existingData = rest;
257
+ }
258
+ catch {
259
+ // No existing manifest — bootstrap a minimal default
260
+ const now = new Date().toISOString();
261
+ existingData = {
262
+ run_id: this.runId,
263
+ cli_flags: {},
264
+ story_scope: [],
265
+ supervisor_pid: null,
266
+ supervisor_session_id: null,
267
+ per_story_state: {},
268
+ recovery_history: [],
269
+ cost_accumulation: { per_story: {}, run_total: 0 },
270
+ pending_proposals: [],
271
+ created_at: now,
272
+ };
273
+ }
274
+ await this.write({
275
+ ...existingData,
276
+ cli_flags: { ...existingData.cli_flags, ...flags },
277
+ });
278
+ }
279
+ // -------------------------------------------------------------------------
280
+ // Instance: patchStoryState() — atomic upsert for per-story lifecycle state
281
+ // -------------------------------------------------------------------------
282
+ /**
283
+ * Atomically upsert the per-story lifecycle state for a single story key.
284
+ *
285
+ * Reads the current manifest (or creates a minimal default if absent),
286
+ * shallowly merges `updates` into `per_story_state[storyKey]`, and writes
287
+ * the result atomically via a single `write()` call.
288
+ *
289
+ * Fields not included in `updates` on an existing entry are preserved unchanged.
290
+ *
291
+ * Non-fatal: callers MUST wrap in `.catch((err) => logger.warn(...))`.
292
+ * The pipeline must never abort due to a manifest write failure.
293
+ *
294
+ * @param storyKey - Story key (e.g. '52-4')
295
+ * @param updates - Partial PerStoryState fields to merge
296
+ */
297
+ async patchStoryState(storyKey, updates) {
298
+ let existingData;
299
+ try {
300
+ const read = await RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
301
+ // Strip generation and updated_at — write() re-computes them
302
+ const { generation: _gen, updated_at: _ts, ...rest } = read;
303
+ existingData = rest;
304
+ }
305
+ catch {
306
+ // No existing manifest — bootstrap a minimal default so we can write the entry
307
+ const now = new Date().toISOString();
308
+ existingData = {
309
+ run_id: this.runId,
310
+ cli_flags: {},
311
+ story_scope: [],
312
+ supervisor_pid: null,
313
+ supervisor_session_id: null,
314
+ per_story_state: {},
315
+ recovery_history: [],
316
+ cost_accumulation: { per_story: {}, run_total: 0 },
317
+ pending_proposals: [],
318
+ created_at: now,
319
+ };
320
+ }
321
+ // Shallow-merge updates into the existing entry (or create if absent).
322
+ // When no existing entry is present, provide sensible defaults for the three
323
+ // required fields (status, phase, started_at) so the merged result passes
324
+ // PerStoryStateSchema validation on read. In normal pipeline operation the
325
+ // orchestrator always creates the entry via the 'dispatched' transition before
326
+ // calling persistVerificationResult or any other partial-patch helper, so
327
+ // `existing` is defined in the vast majority of cases. This guard handles
328
+ // callers that patch verification_result or cost_usd in isolation (e.g. tests).
329
+ const existing = existingData.per_story_state[storyKey];
330
+ const merged = {
331
+ status: 'pending',
332
+ phase: '',
333
+ started_at: new Date().toISOString(),
334
+ ...existing,
335
+ ...updates,
336
+ };
337
+ await this.write({
338
+ ...existingData,
339
+ per_story_state: {
340
+ ...existingData.per_story_state,
341
+ [storyKey]: merged,
342
+ },
343
+ });
344
+ }
345
+ // -------------------------------------------------------------------------
346
+ // Instance: appendRecoveryEntry() — atomic append and cost update
347
+ // -------------------------------------------------------------------------
348
+ /**
349
+ * Atomically append a recovery entry and update cost accumulation.
350
+ *
351
+ * Reads the current manifest, appends `entry` to `recovery_history[]`,
352
+ * increments `cost_accumulation.per_story[entry.story_key]` by `entry.cost_usd`,
353
+ * increments `cost_accumulation.run_total` by `entry.cost_usd`, then writes
354
+ * atomically via a single `write()` call.
355
+ *
356
+ * Non-fatal: callers MUST wrap in `.catch((err) => logger.warn(...))`.
357
+ * The pipeline must never abort due to a manifest write failure.
358
+ *
359
+ * `entry.cost_usd` is the cost of this single retry attempt only (NOT cumulative).
360
+ * Cumulative per-story retry cost is tracked in `cost_accumulation.per_story`.
361
+ *
362
+ * @param entry - Recovery entry to append (attempt_number is 1-indexed)
363
+ */
364
+ async appendRecoveryEntry(entry) {
365
+ let existingData;
366
+ try {
367
+ const read = await RunManifest.read(this.runId, this.baseDir, this.doltAdapter);
368
+ const { generation: _gen, updated_at: _ts, ...rest } = read;
369
+ existingData = rest;
370
+ }
371
+ catch {
372
+ // No existing manifest — bootstrap a minimal default so we can write the entry
373
+ const now = new Date().toISOString();
374
+ existingData = {
375
+ run_id: this.runId,
376
+ cli_flags: {},
377
+ story_scope: [],
378
+ supervisor_pid: null,
379
+ supervisor_session_id: null,
380
+ per_story_state: {},
381
+ recovery_history: [],
382
+ cost_accumulation: { per_story: {}, run_total: 0 },
383
+ pending_proposals: [],
384
+ created_at: now,
385
+ };
386
+ }
387
+ const prevStoryCost = existingData.cost_accumulation.per_story[entry.story_key] ?? 0;
388
+ const updated = {
389
+ ...existingData,
390
+ recovery_history: [...existingData.recovery_history, entry],
391
+ cost_accumulation: {
392
+ per_story: {
393
+ ...existingData.cost_accumulation.per_story,
394
+ [entry.story_key]: prevStoryCost + entry.cost_usd,
395
+ },
396
+ run_total: existingData.cost_accumulation.run_total + entry.cost_usd,
397
+ },
398
+ };
399
+ await this.write(updated);
400
+ }
401
+ // -------------------------------------------------------------------------
402
+ // Static factory: create()
403
+ // -------------------------------------------------------------------------
404
+ /**
405
+ * Create a new manifest with `generation: 0` and write it.
406
+ * Returns a bound `RunManifest` instance.
407
+ */
408
+ static async create(runId, initialData, baseDir = defaultBaseDir(), doltAdapter = null) {
409
+ const instance = new RunManifest(runId, baseDir, doltAdapter);
410
+ const now = new Date().toISOString();
411
+ const data = {
412
+ ...initialData,
413
+ created_at: now,
414
+ };
415
+ await instance.write(data);
416
+ return instance;
417
+ }
418
+ // -------------------------------------------------------------------------
419
+ // Static: read()
420
+ // -------------------------------------------------------------------------
421
+ /**
422
+ * Read a manifest from disk with multi-tier fallback.
423
+ *
424
+ * Attempts sources in order:
425
+ * 1. Primary `.json`
426
+ * 2. Backup `.json.bak` (preferred over primary if generation is higher)
427
+ * 3. Temporary `.json.tmp`
428
+ * 4. Dolt degraded reconstruction (if doltAdapter is provided)
429
+ *
430
+ * Generation tiebreak: if `.bak` has a higher `generation` than primary,
431
+ * `.bak` is preferred (indicates primary was overwritten mid-rename).
432
+ *
433
+ * @throws ManifestReadError if all sources fail
434
+ */
435
+ static async read(runId, baseDir = defaultBaseDir(), doltAdapter = null) {
436
+ const attempted = [];
437
+ const primary = primaryPath(baseDir, runId);
438
+ const bak = bakPath(baseDir, runId);
439
+ const tmp = tmpPath(baseDir, runId);
440
+ // Attempt primary and bak, then apply generation tiebreak
441
+ attempted.push(primary);
442
+ const primaryData = await tryReadFile(primary);
443
+ attempted.push(bak);
444
+ const bakData = await tryReadFile(bak);
445
+ // Generation tiebreak: prefer bak if it has a higher generation (newer write)
446
+ if (primaryData !== null && bakData !== null) {
447
+ if (bakData.generation > primaryData.generation) {
448
+ // .bak is newer — use it
449
+ return bakData;
450
+ }
451
+ // primary is fine
452
+ return primaryData;
453
+ }
454
+ if (primaryData !== null) {
455
+ return primaryData;
456
+ }
457
+ if (bakData !== null) {
458
+ return bakData;
459
+ }
460
+ // Try .tmp
461
+ attempted.push(tmp);
462
+ const tmpData = await tryReadFile(tmp);
463
+ if (tmpData !== null) {
464
+ return tmpData;
465
+ }
466
+ // Dolt degraded reconstruction
467
+ if (doltAdapter !== null) {
468
+ const doltSource = 'dolt:pipeline_runs';
469
+ attempted.push(doltSource);
470
+ const doltData = await reconstructFromDolt(runId, doltAdapter);
471
+ if (doltData !== null) {
472
+ // Log degraded mode warning
473
+ console.warn(`[RunManifest] Degraded mode: reconstructed run ${runId} from Dolt pipeline_runs. ` +
474
+ `per_story_state and recovery_history are empty.`);
475
+ return doltData;
476
+ }
477
+ }
478
+ throw new ManifestReadError(`Failed to read manifest for run ${runId}: all sources exhausted`, attempted);
479
+ }
480
+ }
481
+ //# sourceMappingURL=run-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-manifest.js","sourceRoot":"","sources":["../../src/run-model/run-manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * RunManifest Zod schemas — Story 52-1 / Story 52-8.
3
+ *
4
+ * Provides runtime validation for the run manifest file.
5
+ * All schemas mirror the TypeScript interfaces in `types.ts`.
6
+ */
7
+ import { z } from 'zod';
8
+ export { RecoveryEntrySchema, CostAccumulationSchema } from './recovery-history.js';
9
+ /**
10
+ * Schema for a pending supervisor proposal.
11
+ * Uses z.union for extensible type field (follows v0.19.6 ReadinessFindingCategory pattern).
12
+ */
13
+ export declare const ProposalSchema: z.ZodObject<{
14
+ id: z.ZodString;
15
+ created_at: z.ZodString;
16
+ description: z.ZodString;
17
+ type: z.ZodUnion<readonly [z.ZodLiteral<"retry">, z.ZodLiteral<"fix">, z.ZodLiteral<"escalate">, z.ZodLiteral<"skip">, z.ZodString]>;
18
+ story_key: z.ZodOptional<z.ZodString>;
19
+ payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
+ }, z.core.$strip>;
21
+ /**
22
+ * Zod schema for the full run manifest data.
23
+ * Validated on every read; write validates via JSON round-trip.
24
+ *
25
+ * `cost_accumulation` uses `.default({ per_story: {}, run_total: 0 })` so
26
+ * pre-Phase-D manifests that omit this field parse without error (AC7).
27
+ */
28
+ export declare const RunManifestSchema: z.ZodObject<{
29
+ run_id: z.ZodString;
30
+ cli_flags: z.ZodPipe<z.ZodObject<{
31
+ stories: z.ZodOptional<z.ZodArray<z.ZodString>>;
32
+ halt_on: z.ZodOptional<z.ZodEnum<{
33
+ all: "all";
34
+ critical: "critical";
35
+ none: "none";
36
+ }>>;
37
+ cost_ceiling: z.ZodOptional<z.ZodNumber>;
38
+ agent: z.ZodOptional<z.ZodString>;
39
+ skip_verification: z.ZodOptional<z.ZodBoolean>;
40
+ events: z.ZodOptional<z.ZodBoolean>;
41
+ }, z.core.$strip>, z.ZodTransform<Record<string, unknown>, {
42
+ stories?: string[] | undefined;
43
+ halt_on?: "all" | "critical" | "none" | undefined;
44
+ cost_ceiling?: number | undefined;
45
+ agent?: string | undefined;
46
+ skip_verification?: boolean | undefined;
47
+ events?: boolean | undefined;
48
+ }>>;
49
+ story_scope: z.ZodArray<z.ZodString>;
50
+ supervisor_pid: z.ZodNullable<z.ZodNumber>;
51
+ supervisor_session_id: z.ZodNullable<z.ZodString>;
52
+ per_story_state: z.ZodRecord<z.ZodString, z.ZodObject<{
53
+ status: z.ZodUnion<readonly [z.ZodLiteral<"pending">, z.ZodLiteral<"dispatched">, z.ZodLiteral<"in-review">, z.ZodLiteral<"complete">, z.ZodLiteral<"failed">, z.ZodLiteral<"escalated">, z.ZodLiteral<"recovered">, z.ZodLiteral<"verification-failed">, z.ZodLiteral<"gated">, z.ZodLiteral<"skipped">, z.ZodString]>;
54
+ phase: z.ZodString;
55
+ started_at: z.ZodString;
56
+ completed_at: z.ZodOptional<z.ZodString>;
57
+ verification_result: z.ZodOptional<z.ZodObject<{
58
+ storyKey: z.ZodString;
59
+ checks: z.ZodArray<z.ZodObject<{
60
+ checkName: z.ZodString;
61
+ status: z.ZodEnum<{
62
+ pass: "pass";
63
+ warn: "warn";
64
+ fail: "fail";
65
+ }>;
66
+ details: z.ZodString;
67
+ duration_ms: z.ZodNumber;
68
+ }, z.core.$strip>>;
69
+ status: z.ZodEnum<{
70
+ pass: "pass";
71
+ warn: "warn";
72
+ fail: "fail";
73
+ }>;
74
+ duration_ms: z.ZodNumber;
75
+ }, z.core.$strip>>;
76
+ cost_usd: z.ZodOptional<z.ZodNumber>;
77
+ review_cycles: z.ZodOptional<z.ZodNumber>;
78
+ dispatches: z.ZodOptional<z.ZodNumber>;
79
+ retry_count: z.ZodOptional<z.ZodNumber>;
80
+ }, z.core.$strip>>;
81
+ recovery_history: z.ZodArray<z.ZodObject<{
82
+ story_key: z.ZodString;
83
+ attempt_number: z.ZodNumber;
84
+ strategy: z.ZodString;
85
+ root_cause: z.ZodString;
86
+ outcome: z.ZodUnion<readonly [z.ZodLiteral<"retried">, z.ZodLiteral<"escalated">, z.ZodLiteral<"skipped">, z.ZodString]>;
87
+ cost_usd: z.ZodNumber;
88
+ timestamp: z.ZodString;
89
+ }, z.core.$strip>>;
90
+ cost_accumulation: z.ZodDefault<z.ZodObject<{
91
+ per_story: z.ZodRecord<z.ZodString, z.ZodNumber>;
92
+ run_total: z.ZodNumber;
93
+ }, z.core.$strip>>;
94
+ pending_proposals: z.ZodArray<z.ZodObject<{
95
+ id: z.ZodString;
96
+ created_at: z.ZodString;
97
+ description: z.ZodString;
98
+ type: z.ZodUnion<readonly [z.ZodLiteral<"retry">, z.ZodLiteral<"fix">, z.ZodLiteral<"escalate">, z.ZodLiteral<"skip">, z.ZodString]>;
99
+ story_key: z.ZodOptional<z.ZodString>;
100
+ payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
101
+ }, z.core.$strip>>;
102
+ generation: z.ZodNumber;
103
+ created_at: z.ZodString;
104
+ updated_at: z.ZodString;
105
+ }, z.core.$strip>;
106
+ /**
107
+ * Error thrown when all read sources for a manifest fail.
108
+ *
109
+ * Includes `attempted_sources` listing each path/source tried,
110
+ * so callers can diagnose which files were corrupt or missing.
111
+ */
112
+ export declare class ManifestReadError extends Error {
113
+ /** List of sources (file paths or source names) that were attempted. */
114
+ readonly attempted_sources: string[];
115
+ constructor(message: string, attempted_sources: string[]);
116
+ }
117
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/run-model/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAMnF;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;iBAazB,CAAA;AAMF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoB5B,CAAA;AAMF;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;gBAExB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE;CAKzD"}