@substrate-ai/sdlc 0.20.61 → 0.20.63
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/run-model/per-story-state.d.ts +3 -2
- package/dist/run-model/per-story-state.d.ts.map +1 -1
- package/dist/run-model/per-story-state.js +17 -0
- package/dist/run-model/per-story-state.js.map +1 -1
- package/dist/run-model/schemas.d.ts +2 -1
- package/dist/run-model/schemas.d.ts.map +1 -1
- package/dist/verification/cross-story-race-recovery.d.ts +160 -0
- package/dist/verification/cross-story-race-recovery.d.ts.map +1 -0
- package/dist/verification/cross-story-race-recovery.js +312 -0
- package/dist/verification/cross-story-race-recovery.js.map +1 -0
- package/dist/verification/index.d.ts +2 -0
- package/dist/verification/index.d.ts.map +1 -1
- package/dist/verification/index.js +2 -0
- package/dist/verification/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -14,7 +14,7 @@ import { z } from 'zod';
|
|
|
14
14
|
* later stories (`gated` from 53-9, `skipped` from 53-3, `recovered` from 54-1)
|
|
15
15
|
* and any future extensions without breaking deserialization.
|
|
16
16
|
*/
|
|
17
|
-
export declare const PerStoryStatusSchema: 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]>;
|
|
17
|
+
export declare const PerStoryStatusSchema: 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.ZodLiteral<"verification-stale">, z.ZodString]>;
|
|
18
18
|
export type PerStoryStatus = z.infer<typeof PerStoryStatusSchema>;
|
|
19
19
|
/**
|
|
20
20
|
* Schema for a single per-story state entry in the run manifest.
|
|
@@ -30,7 +30,7 @@ export type PerStoryStatus = z.infer<typeof PerStoryStatusSchema>;
|
|
|
30
30
|
* - `cost_usd`: Accumulated cost in USD (populated at terminal transition).
|
|
31
31
|
*/
|
|
32
32
|
export declare const PerStoryStateSchema: z.ZodObject<{
|
|
33
|
-
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]>;
|
|
33
|
+
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.ZodLiteral<"verification-stale">, z.ZodString]>;
|
|
34
34
|
phase: z.ZodString;
|
|
35
35
|
started_at: z.ZodString;
|
|
36
36
|
completed_at: z.ZodOptional<z.ZodString>;
|
|
@@ -94,6 +94,7 @@ export declare const PerStoryStateSchema: z.ZodObject<{
|
|
|
94
94
|
tests: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"pass">, z.ZodLiteral<"fail">, z.ZodLiteral<"unknown">, z.ZodString]>>;
|
|
95
95
|
}, z.core.$strip>>;
|
|
96
96
|
probe_author_triggered_by: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"event-driven">, z.ZodLiteral<"state-integrating">, z.ZodLiteral<"both">, z.ZodString]>>;
|
|
97
|
+
verification_re_run: z.ZodOptional<z.ZodBoolean>;
|
|
97
98
|
}, z.core.$strip>;
|
|
98
99
|
export type PerStoryState = z.infer<typeof PerStoryStateSchema>;
|
|
99
100
|
//# sourceMappingURL=per-story-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"per-story-state.d.ts","sourceRoot":"","sources":["../../src/run-model/per-story-state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"per-story-state.d.ts","sourceRoot":"","sources":["../../src/run-model/per-story-state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,qVAmB/B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAMjE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoD9B,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA"}
|
|
@@ -30,6 +30,13 @@ export const PerStoryStatusSchema = z.union([
|
|
|
30
30
|
z.literal('verification-failed'),
|
|
31
31
|
z.literal('gated'),
|
|
32
32
|
z.literal('skipped'),
|
|
33
|
+
/**
|
|
34
|
+
* Transient state during cross-story-race recovery (Story 70-1). Story is
|
|
35
|
+
* re-verification pending; not a terminal failure. Once recovery completes
|
|
36
|
+
* the status transitions to 'complete' (pipeline:cross-story-race-recovered)
|
|
37
|
+
* or 'failed' (pipeline:cross-story-race-still-failed).
|
|
38
|
+
*/
|
|
39
|
+
z.literal('verification-stale'),
|
|
33
40
|
z.string(), // extensible fallback — must be last
|
|
34
41
|
]);
|
|
35
42
|
// ---------------------------------------------------------------------------
|
|
@@ -90,5 +97,15 @@ export const PerStoryStateSchema = z.object({
|
|
|
90
97
|
z.literal('both'),
|
|
91
98
|
z.string(),
|
|
92
99
|
]).optional(),
|
|
100
|
+
/**
|
|
101
|
+
* Story 70-1: set to `true` when the story's verification was re-run as part
|
|
102
|
+
* of cross-story-race recovery and the fresh result still failed. Allows
|
|
103
|
+
* downstream consumers (e.g. supervisor, post-mortem tooling) to distinguish
|
|
104
|
+
* genuine race-confirmed failures from original first-pass failures.
|
|
105
|
+
*
|
|
106
|
+
* Absent on stories that were not re-verified via recovery — do NOT interpret
|
|
107
|
+
* absence as `false`; use `?? false` at call sites that need a boolean.
|
|
108
|
+
*/
|
|
109
|
+
verification_re_run: z.boolean().optional(),
|
|
93
110
|
});
|
|
94
111
|
//# sourceMappingURL=per-story-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"per-story-state.js","sourceRoot":"","sources":["../../src/run-model/per-story-state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAA;AAEpE,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC;IAC1C,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACpB,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACvB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;IAChC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAClB,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACpB,CAAC,CAAC,MAAM,EAAE,EAAE,qCAAqC;CAClD,CAAC,CAAA;AAIF,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,oBAAoB;IAC5B,yEAAyE;IACzE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,iEAAiE;IACjE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,kEAAkE;IAClE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,6EAA6E;IAC7E,mBAAmB,EAAE,+BAA+B,CAAC,QAAQ,EAAE;IAC/D,iFAAiF;IACjF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IAC7C,4DAA4D;IAC5D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACxD,iDAAiD;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACrD,gIAAgI;IAChI,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACtD;;;;;;OAMG;IACH,iBAAiB,EAAE,2BAA2B,CAAC,QAAQ,EAAE;IACzD;;;;;;;;OAQG;IACH,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;QACzB,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC;QAC9B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACjB,CAAC,CAAC,MAAM,EAAE;KACX,CAAC,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"per-story-state.js","sourceRoot":"","sources":["../../src/run-model/per-story-state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAA;AAEpE,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC;IAC1C,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACpB,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACvB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtB,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;IAChC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAClB,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACpB;;;;;OAKG;IACH,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;IAC/B,CAAC,CAAC,MAAM,EAAE,EAAE,qCAAqC;CAClD,CAAC,CAAA;AAIF,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,oBAAoB;IAC5B,yEAAyE;IACzE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,iEAAiE;IACjE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,kEAAkE;IAClE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,6EAA6E;IAC7E,mBAAmB,EAAE,+BAA+B,CAAC,QAAQ,EAAE;IAC/D,iFAAiF;IACjF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IAC7C,4DAA4D;IAC5D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACxD,iDAAiD;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACrD,gIAAgI;IAChI,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACtD;;;;;;OAMG;IACH,iBAAiB,EAAE,2BAA2B,CAAC,QAAQ,EAAE;IACzD;;;;;;;;OAQG;IACH,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;QACzB,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC;QAC9B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACjB,CAAC,CAAC,MAAM,EAAE;KACX,CAAC,CAAC,QAAQ,EAAE;IACb;;;;;;;;OAQG;IACH,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAA"}
|
|
@@ -56,7 +56,7 @@ export declare const RunManifestSchema: z.ZodObject<{
|
|
|
56
56
|
supervisor_pid: z.ZodNullable<z.ZodNumber>;
|
|
57
57
|
supervisor_session_id: z.ZodNullable<z.ZodString>;
|
|
58
58
|
per_story_state: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
59
|
-
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]>;
|
|
59
|
+
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.ZodLiteral<"verification-stale">, z.ZodString]>;
|
|
60
60
|
phase: z.ZodString;
|
|
61
61
|
started_at: z.ZodString;
|
|
62
62
|
completed_at: z.ZodOptional<z.ZodString>;
|
|
@@ -120,6 +120,7 @@ export declare const RunManifestSchema: z.ZodObject<{
|
|
|
120
120
|
tests: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"pass">, z.ZodLiteral<"fail">, z.ZodLiteral<"unknown">, z.ZodString]>>;
|
|
121
121
|
}, z.core.$strip>>;
|
|
122
122
|
probe_author_triggered_by: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"event-driven">, z.ZodLiteral<"state-integrating">, z.ZodLiteral<"both">, z.ZodString]>>;
|
|
123
|
+
verification_re_run: z.ZodOptional<z.ZodBoolean>;
|
|
123
124
|
}, z.core.$strip>>;
|
|
124
125
|
recovery_history: z.ZodArray<z.ZodObject<{
|
|
125
126
|
story_key: z.ZodString;
|
|
@@ -1 +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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyB5B,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"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-story race recovery — Story 70-1.
|
|
3
|
+
*
|
|
4
|
+
* Provides `detectStaleVerifications` (pure, no I/O) and
|
|
5
|
+
* `runStaleVerificationRecovery` (action handler) for detecting and resolving
|
|
6
|
+
* verification races that occur when concurrent story commits land after the
|
|
7
|
+
* earlier story's verification already ran.
|
|
8
|
+
*
|
|
9
|
+
* Motivating incidents:
|
|
10
|
+
* - Epic 66 run a832487a: 66-1+66-2+66-7 concurrent dispatch — concurrent
|
|
11
|
+
* stories modifying shared test files caused transient verification failures
|
|
12
|
+
* when the later-committing story's changes affected the earlier story's
|
|
13
|
+
* already-recorded verification verdict.
|
|
14
|
+
* - Epic 67 run a59e4c96: 67-1+67-2 concurrent dispatch — the
|
|
15
|
+
* methodology-pack.test.ts BUDGET_LIMIT constant (30000 vs 32000) was
|
|
16
|
+
* updated by story 67-1 AFTER 67-2's verification ran on the un-bumped
|
|
17
|
+
* tree, causing a false pipeline failure verdict despite fully coherent
|
|
18
|
+
* on-disk state. Budget-bump pattern documented in:
|
|
19
|
+
* packages/sdlc/src/__tests__/methodology-pack.test.ts
|
|
20
|
+
*
|
|
21
|
+
* This primitive eliminates manual Path A recovery on the cross-story-race
|
|
22
|
+
* class going forward.
|
|
23
|
+
*/
|
|
24
|
+
import type { TypedEventBus } from '@substrate-ai/core';
|
|
25
|
+
import type { DatabaseAdapter } from '@substrate-ai/core';
|
|
26
|
+
import type { SdlcEvents } from '../events.js';
|
|
27
|
+
import type { RunManifest } from '../run-model/run-manifest.js';
|
|
28
|
+
/**
|
|
29
|
+
* Pre-resolved per-story entry for stale-verification detection.
|
|
30
|
+
*
|
|
31
|
+
* All fields are pre-resolved by the caller so `detectStaleVerifications`
|
|
32
|
+
* remains a pure function with no I/O. `runStaleVerificationRecovery`
|
|
33
|
+
* populates these fields from the run manifest and git log.
|
|
34
|
+
*/
|
|
35
|
+
export interface BatchEntry {
|
|
36
|
+
/** Story key (e.g. "70-1"). */
|
|
37
|
+
storyKey: string;
|
|
38
|
+
/**
|
|
39
|
+
* ISO timestamp of when this story's verification result was recorded.
|
|
40
|
+
* Falls back to `completed_at` from PerStoryState when absent from
|
|
41
|
+
* verification_result metadata (Risk: Assumption 2).
|
|
42
|
+
*/
|
|
43
|
+
verifiedAt?: string;
|
|
44
|
+
/**
|
|
45
|
+
* ISO timestamp of when this story's implementation commit landed.
|
|
46
|
+
* Resolved from `git log --format=%cI --grep="feat(story-<storyKey>):" -1`.
|
|
47
|
+
*/
|
|
48
|
+
committedAt?: string;
|
|
49
|
+
/** Files modified by this story's implementation (from dev_story_signals). */
|
|
50
|
+
modifiedFiles?: string[];
|
|
51
|
+
/** Test files associated with this story (subset of modifiedFiles). */
|
|
52
|
+
testFiles?: string[];
|
|
53
|
+
/**
|
|
54
|
+
* Fallback file list when `modifiedFiles` is absent (AC9-f).
|
|
55
|
+
* Populated from verification_result or dev_story_signals when the primary
|
|
56
|
+
* modifiedFiles field is not available in the manifest.
|
|
57
|
+
*/
|
|
58
|
+
verificationResultFiles?: string[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Detect stories whose verification results were recorded before concurrent
|
|
62
|
+
* story commits landed.
|
|
63
|
+
*
|
|
64
|
+
* Stale-verification boundary condition:
|
|
65
|
+
* t.committedAt > s.verifiedAt
|
|
66
|
+
* AND
|
|
67
|
+
* t.modifiedFiles ∩ (s.modifiedFiles ∪ s.testFiles) ≠ ∅
|
|
68
|
+
*
|
|
69
|
+
* Where:
|
|
70
|
+
* s = the story we're checking for staleness
|
|
71
|
+
* t = another story in the batch that may have committed after s verified
|
|
72
|
+
*
|
|
73
|
+
* Pure function — all data must be pre-resolved in the `batch` entries.
|
|
74
|
+
* Returns empty array when no stale stories are detected (idempotent, no-op).
|
|
75
|
+
*
|
|
76
|
+
* @param batch Pre-resolved story data for all stories in the concurrent batch.
|
|
77
|
+
* @param _manifest Manifest instance (accepted for API symmetry; not used in pure logic).
|
|
78
|
+
* @returns Array of story keys that have stale verification results.
|
|
79
|
+
*/
|
|
80
|
+
export declare function detectStaleVerifications(batch: BatchEntry[], _manifest: RunManifest | Record<string, unknown>): string[];
|
|
81
|
+
/**
|
|
82
|
+
* Resolves the commit timestamp for a story's implementation commit.
|
|
83
|
+
*
|
|
84
|
+
* Uses the canonical `feat(story-<storyKey>):` commit message pattern to
|
|
85
|
+
* locate the story's auto-commit in git history.
|
|
86
|
+
*
|
|
87
|
+
* @param storyKey Story key (e.g. "70-1")
|
|
88
|
+
* @param workingDir Absolute path to the git repo root
|
|
89
|
+
* @returns ISO-8601 commit timestamp string, or `undefined` if not found
|
|
90
|
+
*/
|
|
91
|
+
export declare function CommittedAtResolver(storyKey: string, workingDir: string): string | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Input for `runStaleVerificationRecovery`.
|
|
94
|
+
*/
|
|
95
|
+
export interface StaleVerificationRecoveryInput {
|
|
96
|
+
/** Run ID for event emission and manifest access. */
|
|
97
|
+
runId: string;
|
|
98
|
+
/**
|
|
99
|
+
* Batch entries with pre-resolved story data. `committedAt` values are
|
|
100
|
+
* resolved internally from git log; do NOT pre-populate them.
|
|
101
|
+
* Other fields (verifiedAt, modifiedFiles, testFiles) are populated from
|
|
102
|
+
* the manifest's per_story_state when absent from the caller's batch.
|
|
103
|
+
*/
|
|
104
|
+
batch: BatchEntry[];
|
|
105
|
+
/** Absolute path to the project working directory. */
|
|
106
|
+
workingDir: string;
|
|
107
|
+
/** Typed event bus for emitting recovery lifecycle events. */
|
|
108
|
+
bus: TypedEventBus<SdlcEvents>;
|
|
109
|
+
/** RunManifest instance for state reads and writes. */
|
|
110
|
+
manifest: RunManifest;
|
|
111
|
+
/**
|
|
112
|
+
* Database adapter for Dolt persistence (canonical helper per AC3).
|
|
113
|
+
*
|
|
114
|
+
* Reserved for future Dolt writes (e.g. storing recovery audit records).
|
|
115
|
+
* `RunManifest.patchStoryState` currently handles all necessary persistence
|
|
116
|
+
* for this recovery handler, so `adapter` is wired through at the interface
|
|
117
|
+
* boundary to preserve the canonical-helper contract without forcing callers
|
|
118
|
+
* to update their call sites when a Dolt write is added later.
|
|
119
|
+
*
|
|
120
|
+
* Do NOT remove this parameter — it is part of the public AC3-mandated
|
|
121
|
+
* interface shape. Add a leading underscore if a linter flags it as unused.
|
|
122
|
+
*/
|
|
123
|
+
adapter: DatabaseAdapter;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Result of a `runStaleVerificationRecovery` invocation.
|
|
127
|
+
*/
|
|
128
|
+
export interface StaleVerificationRecoveryResult {
|
|
129
|
+
/** Story keys whose fresh verification passed → transitioned to 'complete'. */
|
|
130
|
+
recovered: string[];
|
|
131
|
+
/** Story keys whose fresh verification still failed → transitioned to 'failed'. */
|
|
132
|
+
stillFailed: string[];
|
|
133
|
+
/** True when no stale verifications were detected (idempotent no-op exit). */
|
|
134
|
+
noStale: boolean;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Cross-story race recovery action handler.
|
|
138
|
+
*
|
|
139
|
+
* Orchestrates the full recovery arc for stories with stale verification
|
|
140
|
+
* results caused by concurrent story commits landing after verification ran:
|
|
141
|
+
*
|
|
142
|
+
* 1. Resolves `committedAt` for each batch story via git log.
|
|
143
|
+
* 2. Enriches BatchEntry[] from manifest per_story_state when fields absent.
|
|
144
|
+
* 3. Calls `detectStaleVerifications` to identify stale story keys.
|
|
145
|
+
* 4. Returns `{ noStale: true }` immediately when none are stale (idempotent).
|
|
146
|
+
* 5. For each stale story:
|
|
147
|
+
* a. Transitions status to `verification-stale` in manifest.
|
|
148
|
+
* b. Re-runs `createDefaultVerificationPipeline` against current tree.
|
|
149
|
+
* c. On pass: transitions to `complete`, emits `pipeline:cross-story-race-recovered`.
|
|
150
|
+
* d. On fail: transitions to `failed` with `verification_re_run: true`,
|
|
151
|
+
* emits `pipeline:cross-story-race-still-failed`.
|
|
152
|
+
*
|
|
153
|
+
* Implements AC3 canonical-helper discipline: all state reads use RunManifest,
|
|
154
|
+
* all persistence uses the injected adapter. No direct file reads of manifest.json.
|
|
155
|
+
*
|
|
156
|
+
* @param input Recovery input (see StaleVerificationRecoveryInput)
|
|
157
|
+
* @returns Recovery summary
|
|
158
|
+
*/
|
|
159
|
+
export declare function runStaleVerificationRecovery(input: StaleVerificationRecoveryInput): Promise<StaleVerificationRecoveryResult>;
|
|
160
|
+
//# sourceMappingURL=cross-story-race-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-story-race-recovery.d.ts","sourceRoot":"","sources":["../../src/verification/cross-story-race-recovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAQ/D;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAA;CACnC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/C,MAAM,EAAE,CAwDV;AAMD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,SAAS,CAcpB;AAMD;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,GAAG,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IAC9B,uDAAuD;IACvD,QAAQ,EAAE,WAAW,CAAA;IACrB;;;;;;;;;;;OAWG;IACH,OAAO,EAAE,eAAe,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,+EAA+E;IAC/E,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,mFAAmF;IACnF,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,+BAA+B,CAAC,CAqL1C"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-story race recovery — Story 70-1.
|
|
3
|
+
*
|
|
4
|
+
* Provides `detectStaleVerifications` (pure, no I/O) and
|
|
5
|
+
* `runStaleVerificationRecovery` (action handler) for detecting and resolving
|
|
6
|
+
* verification races that occur when concurrent story commits land after the
|
|
7
|
+
* earlier story's verification already ran.
|
|
8
|
+
*
|
|
9
|
+
* Motivating incidents:
|
|
10
|
+
* - Epic 66 run a832487a: 66-1+66-2+66-7 concurrent dispatch — concurrent
|
|
11
|
+
* stories modifying shared test files caused transient verification failures
|
|
12
|
+
* when the later-committing story's changes affected the earlier story's
|
|
13
|
+
* already-recorded verification verdict.
|
|
14
|
+
* - Epic 67 run a59e4c96: 67-1+67-2 concurrent dispatch — the
|
|
15
|
+
* methodology-pack.test.ts BUDGET_LIMIT constant (30000 vs 32000) was
|
|
16
|
+
* updated by story 67-1 AFTER 67-2's verification ran on the un-bumped
|
|
17
|
+
* tree, causing a false pipeline failure verdict despite fully coherent
|
|
18
|
+
* on-disk state. Budget-bump pattern documented in:
|
|
19
|
+
* packages/sdlc/src/__tests__/methodology-pack.test.ts
|
|
20
|
+
*
|
|
21
|
+
* This primitive eliminates manual Path A recovery on the cross-story-race
|
|
22
|
+
* class going forward.
|
|
23
|
+
*/
|
|
24
|
+
import { execSync } from 'node:child_process';
|
|
25
|
+
import { readdirSync, readFileSync, existsSync } from 'node:fs';
|
|
26
|
+
import { createDefaultVerificationPipeline } from './verification-pipeline.js';
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// detectStaleVerifications — pure function, no I/O
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
/**
|
|
31
|
+
* Detect stories whose verification results were recorded before concurrent
|
|
32
|
+
* story commits landed.
|
|
33
|
+
*
|
|
34
|
+
* Stale-verification boundary condition:
|
|
35
|
+
* t.committedAt > s.verifiedAt
|
|
36
|
+
* AND
|
|
37
|
+
* t.modifiedFiles ∩ (s.modifiedFiles ∪ s.testFiles) ≠ ∅
|
|
38
|
+
*
|
|
39
|
+
* Where:
|
|
40
|
+
* s = the story we're checking for staleness
|
|
41
|
+
* t = another story in the batch that may have committed after s verified
|
|
42
|
+
*
|
|
43
|
+
* Pure function — all data must be pre-resolved in the `batch` entries.
|
|
44
|
+
* Returns empty array when no stale stories are detected (idempotent, no-op).
|
|
45
|
+
*
|
|
46
|
+
* @param batch Pre-resolved story data for all stories in the concurrent batch.
|
|
47
|
+
* @param _manifest Manifest instance (accepted for API symmetry; not used in pure logic).
|
|
48
|
+
* @returns Array of story keys that have stale verification results.
|
|
49
|
+
*/
|
|
50
|
+
export function detectStaleVerifications(batch, _manifest) {
|
|
51
|
+
if (batch.length < 2) {
|
|
52
|
+
// Cannot have a race with fewer than 2 stories
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const staleKeys = [];
|
|
56
|
+
for (const s of batch) {
|
|
57
|
+
const sVerifiedAt = s.verifiedAt;
|
|
58
|
+
if (sVerifiedAt === undefined) {
|
|
59
|
+
// Story was never verified — not a staleness case
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// Effective file set for story s: modifiedFiles ∪ testFiles, with fallback
|
|
63
|
+
const sPrimaryFiles = s.modifiedFiles ?? s.verificationResultFiles ?? [];
|
|
64
|
+
const sTestFiles = s.testFiles ?? [];
|
|
65
|
+
const sAllFiles = new Set([...sPrimaryFiles, ...sTestFiles]);
|
|
66
|
+
if (sAllFiles.size === 0) {
|
|
67
|
+
// No files tracked for story s — cannot detect overlap
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
for (const t of batch) {
|
|
71
|
+
if (t.storyKey === s.storyKey)
|
|
72
|
+
continue;
|
|
73
|
+
const tCommittedAt = t.committedAt;
|
|
74
|
+
if (tCommittedAt === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
// Race condition: t committed AFTER s had already verified.
|
|
77
|
+
// Use Date objects for comparison to handle timezone-offset strings
|
|
78
|
+
// (git log may emit local-timezone format while manifest timestamps are UTC).
|
|
79
|
+
let tTime, sTime;
|
|
80
|
+
try {
|
|
81
|
+
tTime = new Date(tCommittedAt).getTime();
|
|
82
|
+
sTime = new Date(sVerifiedAt).getTime();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
continue; // unparseable timestamp — skip
|
|
86
|
+
}
|
|
87
|
+
if (isNaN(tTime) || isNaN(sTime))
|
|
88
|
+
continue;
|
|
89
|
+
if (tTime <= sTime)
|
|
90
|
+
continue;
|
|
91
|
+
// Check file overlap: t modified files that s also worked on
|
|
92
|
+
const tFiles = t.modifiedFiles ?? [];
|
|
93
|
+
const hasOverlap = tFiles.some((f) => sAllFiles.has(f));
|
|
94
|
+
if (hasOverlap) {
|
|
95
|
+
staleKeys.push(s.storyKey);
|
|
96
|
+
break; // found at least one race partner — no need to check more
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return staleKeys;
|
|
101
|
+
}
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// CommittedAtResolver — git log helper
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
/**
|
|
106
|
+
* Resolves the commit timestamp for a story's implementation commit.
|
|
107
|
+
*
|
|
108
|
+
* Uses the canonical `feat(story-<storyKey>):` commit message pattern to
|
|
109
|
+
* locate the story's auto-commit in git history.
|
|
110
|
+
*
|
|
111
|
+
* @param storyKey Story key (e.g. "70-1")
|
|
112
|
+
* @param workingDir Absolute path to the git repo root
|
|
113
|
+
* @returns ISO-8601 commit timestamp string, or `undefined` if not found
|
|
114
|
+
*/
|
|
115
|
+
export function CommittedAtResolver(storyKey, workingDir) {
|
|
116
|
+
try {
|
|
117
|
+
const result = execSync(`git log --format=%cI --grep="feat(story-${storyKey}):" -1`, {
|
|
118
|
+
cwd: workingDir,
|
|
119
|
+
encoding: 'utf-8',
|
|
120
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
121
|
+
}).trim();
|
|
122
|
+
return result.length > 0 ? result : undefined;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Cross-story race recovery action handler.
|
|
130
|
+
*
|
|
131
|
+
* Orchestrates the full recovery arc for stories with stale verification
|
|
132
|
+
* results caused by concurrent story commits landing after verification ran:
|
|
133
|
+
*
|
|
134
|
+
* 1. Resolves `committedAt` for each batch story via git log.
|
|
135
|
+
* 2. Enriches BatchEntry[] from manifest per_story_state when fields absent.
|
|
136
|
+
* 3. Calls `detectStaleVerifications` to identify stale story keys.
|
|
137
|
+
* 4. Returns `{ noStale: true }` immediately when none are stale (idempotent).
|
|
138
|
+
* 5. For each stale story:
|
|
139
|
+
* a. Transitions status to `verification-stale` in manifest.
|
|
140
|
+
* b. Re-runs `createDefaultVerificationPipeline` against current tree.
|
|
141
|
+
* c. On pass: transitions to `complete`, emits `pipeline:cross-story-race-recovered`.
|
|
142
|
+
* d. On fail: transitions to `failed` with `verification_re_run: true`,
|
|
143
|
+
* emits `pipeline:cross-story-race-still-failed`.
|
|
144
|
+
*
|
|
145
|
+
* Implements AC3 canonical-helper discipline: all state reads use RunManifest,
|
|
146
|
+
* all persistence uses the injected adapter. No direct file reads of manifest.json.
|
|
147
|
+
*
|
|
148
|
+
* @param input Recovery input (see StaleVerificationRecoveryInput)
|
|
149
|
+
* @returns Recovery summary
|
|
150
|
+
*/
|
|
151
|
+
export async function runStaleVerificationRecovery(input) {
|
|
152
|
+
const { runId, batch, workingDir, bus, manifest } = input;
|
|
153
|
+
// --- Step 1: Resolve committedAt for each story via git log ---
|
|
154
|
+
const enrichedBatch = [];
|
|
155
|
+
let manifestData = null;
|
|
156
|
+
try {
|
|
157
|
+
manifestData = await manifest.read();
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// manifest unreadable — proceed with batch data as-is
|
|
161
|
+
}
|
|
162
|
+
for (const entry of batch) {
|
|
163
|
+
const committedAt = CommittedAtResolver(entry.storyKey, workingDir);
|
|
164
|
+
// Enrich verifiedAt and modifiedFiles from manifest when absent in batch entry
|
|
165
|
+
let verifiedAt = entry.verifiedAt;
|
|
166
|
+
let modifiedFiles = entry.modifiedFiles;
|
|
167
|
+
let testFiles = entry.testFiles;
|
|
168
|
+
let verificationResultFiles = entry.verificationResultFiles;
|
|
169
|
+
if (manifestData !== null) {
|
|
170
|
+
const perStory = manifestData.per_story_state[entry.storyKey];
|
|
171
|
+
if (perStory !== undefined) {
|
|
172
|
+
// Fall back to completed_at as verifiedAt when absent (Risk: Assumption 2)
|
|
173
|
+
if (verifiedAt === undefined) {
|
|
174
|
+
verifiedAt = perStory.completed_at;
|
|
175
|
+
}
|
|
176
|
+
// Fall back to dev_story_signals.files_modified when modifiedFiles absent
|
|
177
|
+
if (modifiedFiles === undefined && perStory.dev_story_signals?.files_modified !== undefined) {
|
|
178
|
+
modifiedFiles = perStory.dev_story_signals.files_modified;
|
|
179
|
+
}
|
|
180
|
+
// Populate verificationResultFiles from dev_story_signals as the AC9-f fallback
|
|
181
|
+
if (verificationResultFiles === undefined && perStory.dev_story_signals?.files_modified !== undefined) {
|
|
182
|
+
verificationResultFiles = perStory.dev_story_signals.files_modified;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Build enriched entry using exactOptionalPropertyTypes-safe spread:
|
|
187
|
+
// only include optional fields when they have a concrete value.
|
|
188
|
+
const enriched = { storyKey: entry.storyKey };
|
|
189
|
+
if (committedAt !== undefined)
|
|
190
|
+
enriched.committedAt = committedAt;
|
|
191
|
+
if (verifiedAt !== undefined)
|
|
192
|
+
enriched.verifiedAt = verifiedAt;
|
|
193
|
+
if (modifiedFiles !== undefined)
|
|
194
|
+
enriched.modifiedFiles = modifiedFiles;
|
|
195
|
+
if (testFiles !== undefined)
|
|
196
|
+
enriched.testFiles = testFiles;
|
|
197
|
+
if (verificationResultFiles !== undefined)
|
|
198
|
+
enriched.verificationResultFiles = verificationResultFiles;
|
|
199
|
+
enrichedBatch.push(enriched);
|
|
200
|
+
}
|
|
201
|
+
// --- Step 2: Detect stale verifications (pure) ---
|
|
202
|
+
const staleKeys = detectStaleVerifications(enrichedBatch, manifest);
|
|
203
|
+
if (staleKeys.length === 0) {
|
|
204
|
+
// Idempotent no-op: no stale verifications detected
|
|
205
|
+
return { recovered: [], stillFailed: [], noStale: true };
|
|
206
|
+
}
|
|
207
|
+
// --- Step 3: Recovery loop — re-verify each stale story ---
|
|
208
|
+
const recovered = [];
|
|
209
|
+
const stillFailed = [];
|
|
210
|
+
// Build a fresh verification pipeline bound to this bus
|
|
211
|
+
const verificationPipeline = createDefaultVerificationPipeline(bus);
|
|
212
|
+
for (const storyKey of staleKeys) {
|
|
213
|
+
const recoveryStart = Date.now();
|
|
214
|
+
// Collect original findings from manifest
|
|
215
|
+
let originalFindings = [];
|
|
216
|
+
if (manifestData !== null) {
|
|
217
|
+
const perStory = manifestData.per_story_state[storyKey];
|
|
218
|
+
if (perStory?.verification_result !== undefined) {
|
|
219
|
+
originalFindings = (perStory.verification_result.checks ?? []).flatMap((c) => c.findings ?? []);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Transition to verification-stale
|
|
223
|
+
await manifest
|
|
224
|
+
.patchStoryState(storyKey, { status: 'verification-stale' })
|
|
225
|
+
.catch(() => {
|
|
226
|
+
// Non-fatal — continue recovery even if manifest patch fails
|
|
227
|
+
});
|
|
228
|
+
// Build a minimal verification context against current HEAD
|
|
229
|
+
let commitSha;
|
|
230
|
+
try {
|
|
231
|
+
commitSha = execSync('git rev-parse HEAD', {
|
|
232
|
+
cwd: workingDir,
|
|
233
|
+
encoding: 'utf-8',
|
|
234
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
235
|
+
}).trim();
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
commitSha = 'unknown';
|
|
239
|
+
}
|
|
240
|
+
// Read story content if available (best-effort)
|
|
241
|
+
let storyContent;
|
|
242
|
+
try {
|
|
243
|
+
const artifactsDir = `${workingDir}/_bmad-output/implementation-artifacts`;
|
|
244
|
+
if (existsSync(artifactsDir)) {
|
|
245
|
+
const STALE_SUFFIX = /\.stale-\d+\.md$/;
|
|
246
|
+
const files = readdirSync(artifactsDir);
|
|
247
|
+
const match = files.find((f) => f.startsWith(`${storyKey}-`) && f.endsWith('.md') && !STALE_SUFFIX.test(f));
|
|
248
|
+
if (match !== undefined) {
|
|
249
|
+
storyContent = readFileSync(`${artifactsDir}/${match}`, 'utf-8');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Story content is optional — proceed without it
|
|
255
|
+
}
|
|
256
|
+
// exactOptionalPropertyTypes-safe construction: only include optional
|
|
257
|
+
// fields when they have a concrete non-undefined value.
|
|
258
|
+
const verifContext = {
|
|
259
|
+
storyKey,
|
|
260
|
+
workingDir,
|
|
261
|
+
commitSha,
|
|
262
|
+
timeout: 60_000,
|
|
263
|
+
...(storyContent !== undefined ? { storyContent } : {}),
|
|
264
|
+
};
|
|
265
|
+
// Re-run verification pipeline against fresh tree
|
|
266
|
+
const freshSummary = await verificationPipeline.run(verifContext, 'A');
|
|
267
|
+
const freshFindings = (freshSummary.checks ?? []).flatMap((c) => c.findings ?? []);
|
|
268
|
+
const recoveryDurationMs = Date.now() - recoveryStart;
|
|
269
|
+
if (freshSummary.status === 'pass' || freshSummary.status === 'warn') {
|
|
270
|
+
// Fresh verification passed — story is genuinely complete
|
|
271
|
+
await manifest
|
|
272
|
+
.patchStoryState(storyKey, {
|
|
273
|
+
status: 'complete',
|
|
274
|
+
verification_result: freshSummary,
|
|
275
|
+
completed_at: new Date().toISOString(),
|
|
276
|
+
})
|
|
277
|
+
.catch(() => {
|
|
278
|
+
// Non-fatal
|
|
279
|
+
});
|
|
280
|
+
bus.emit('pipeline:cross-story-race-recovered', {
|
|
281
|
+
runId,
|
|
282
|
+
storyKey,
|
|
283
|
+
originalFindings,
|
|
284
|
+
freshFindings,
|
|
285
|
+
recoveryDurationMs,
|
|
286
|
+
});
|
|
287
|
+
recovered.push(storyKey);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
// Fresh verification still failed — genuine failure, not a race artefact
|
|
291
|
+
await manifest
|
|
292
|
+
.patchStoryState(storyKey, {
|
|
293
|
+
status: 'failed',
|
|
294
|
+
verification_result: freshSummary,
|
|
295
|
+
verification_re_run: true,
|
|
296
|
+
completed_at: new Date().toISOString(),
|
|
297
|
+
})
|
|
298
|
+
.catch(() => {
|
|
299
|
+
// Non-fatal
|
|
300
|
+
});
|
|
301
|
+
bus.emit('pipeline:cross-story-race-still-failed', {
|
|
302
|
+
runId,
|
|
303
|
+
storyKey,
|
|
304
|
+
freshFindings,
|
|
305
|
+
recoveryDurationMs,
|
|
306
|
+
});
|
|
307
|
+
stillFailed.push(storyKey);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return { recovered, stillFailed, noStale: false };
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=cross-story-race-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-story-race-recovery.js","sourceRoot":"","sources":["../../src/verification/cross-story-race-recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,4 +22,6 @@ export { SourceAcShelloutCheck, runShelloutCheck } from './checks/index.js';
|
|
|
22
22
|
export { CATEGORY_SHELLOUT_NPX_FALLBACK } from './findings.js';
|
|
23
23
|
export { CrossStoryConsistencyCheck, runCrossStoryConsistencyCheck, } from './checks/index.js';
|
|
24
24
|
export { CATEGORY_CROSS_STORY_CONCURRENT_MODIFICATION } from './findings.js';
|
|
25
|
+
export { detectStaleVerifications, CommittedAtResolver, runStaleVerificationRecovery, } from './cross-story-race-recovery.js';
|
|
26
|
+
export type { BatchEntry, StaleVerificationRecoveryInput, StaleVerificationRecoveryResult, } from './cross-story-race-recovery.js';
|
|
25
27
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AACpG,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAE5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAEtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAA;AACxF,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAErE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAA;AAE9D,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,4CAA4C,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AACpG,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAE5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAEtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAA;AACxF,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAErE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAA;AAE9D,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,4CAA4C,EAAE,MAAM,eAAe,CAAA;AAE5E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,4BAA4B,GAC7B,MAAM,gCAAgC,CAAA;AACvC,YAAY,EACV,UAAU,EACV,8BAA8B,EAC9B,+BAA+B,GAChC,MAAM,gCAAgC,CAAA"}
|
|
@@ -26,4 +26,6 @@ export { CATEGORY_SHELLOUT_NPX_FALLBACK } from './findings.js';
|
|
|
26
26
|
// Story 68-1: cross-story consistency check + finding category
|
|
27
27
|
export { CrossStoryConsistencyCheck, runCrossStoryConsistencyCheck, } from './checks/index.js';
|
|
28
28
|
export { CATEGORY_CROSS_STORY_CONCURRENT_MODIFICATION } from './findings.js';
|
|
29
|
+
// Story 70-1: cross-story race recovery
|
|
30
|
+
export { detectStaleVerifications, CommittedAtResolver, runStaleVerificationRecovery, } from './cross-story-race-recovery.js';
|
|
29
31
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AAYpG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,2CAA2C;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAEnE,0DAA0D;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,iFAAiF;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAQ1B,+CAA+C;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAA;AACxF,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC1F,uCAAuC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,qDAAqD;AACrD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAA;AAC9D,+DAA+D;AAC/D,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,4CAA4C,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AAYpG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,2CAA2C;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAEnE,0DAA0D;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,iFAAiF;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAQ1B,+CAA+C;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAA;AACxF,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC1F,uCAAuC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,qDAAqD;AACrD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAA;AAC9D,+DAA+D;AAC/D,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,4CAA4C,EAAE,MAAM,eAAe,CAAA;AAC5E,wCAAwC;AACxC,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,4BAA4B,GAC7B,MAAM,gCAAgC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrate-ai/sdlc",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.63",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node": ">=22.0.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@substrate-ai/core": "0.20.
|
|
27
|
+
"@substrate-ai/core": "0.20.63",
|
|
28
28
|
"js-yaml": "^4.1.1",
|
|
29
29
|
"zod": "^4.3.6"
|
|
30
30
|
},
|