valent-pipeline 0.19.35 → 0.19.37
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/package.json
CHANGED
|
@@ -1875,6 +1875,21 @@ async function runStory(story) {
|
|
|
1875
1875
|
await runGitStep(storyId, [
|
|
1876
1876
|
`node .valent-pipeline/bin/cli.js git start-story --story ${storyId}${gitFlags}`,
|
|
1877
1877
|
], 'start', 'QA')
|
|
1878
|
+
// Cross-lane pin coherence on the inline-fix revalidation path (2026-06-19, M-28): the blocking
|
|
1879
|
+
// bug's fix already merged INTO this story branch (ship-story --into) and was CRITIC-approved in
|
|
1880
|
+
// its OWN lane — but that merge advanced the story tip PAST the story's last critic pin. The
|
|
1881
|
+
// revalidation runs no CRITIC (by design — the fix was already reviewed) and `commitAndRepin`
|
|
1882
|
+
// no-ops here (no devTasks), so the STALE story critic pin would trip `pins:critic`
|
|
1883
|
+
// (evidence assert --require-pins critic) against the merged tip and FALSE-VOID a genuine SHIP —
|
|
1884
|
+
// exactly the 2.11 reject. Re-pin critic so the pin records the cross-lane coverage that
|
|
1885
|
+
// genuinely exists (story code @ the old pin + the bug fix @ its lane's own approving pin); the
|
|
1886
|
+
// bug only merged here because it SHIPPED through its own CRITIC+JUDGE gates, and this no-rebuild
|
|
1887
|
+
// path introduces no new source, so the coverage is real. The v3 source-delta check still
|
|
1888
|
+
// fails-closed on any genuine un-reviewed change after this point. This is the "revalidation
|
|
1889
|
+
// legitimately re-pins" case the pin-coherence doctrine already anticipates (evidence.js).
|
|
1890
|
+
await runGitStep(storyId, [
|
|
1891
|
+
`node .valent-pipeline/bin/cli.js evidence pin --story ${storyId} --gate critic`,
|
|
1892
|
+
], 'reval-repin-critic', 'QA')
|
|
1878
1893
|
}
|
|
1879
1894
|
await spawn('QA-B', 'qa-b.md',
|
|
1880
1895
|
'This is a RE-VALIDATION of a previously-rejected story whose blocking bug has since been fixed and ' +
|
package/src/lib/sprint.js
CHANGED
|
@@ -226,22 +226,27 @@ export function packSprint(stories, velocity, opts = {}) {
|
|
|
226
226
|
// groomed story alone — pulling in its groomed prerequisites first so order stays dependency-safe
|
|
227
227
|
// — accepting an over-budget sprint. `over_budget` is flagged so the planner can surface
|
|
228
228
|
// "this story exceeds velocity; planned alone — consider splitting it."
|
|
229
|
+
// forceAdd: include a story over-budget, pulling in its unsatisfied blocking bugs + groomed deps
|
|
230
|
+
// FIRST so execution order stays dependency-safe. Shared by both over-budget guards below.
|
|
231
|
+
const forceAdd = (story) => {
|
|
232
|
+
if (inSprint.has(story.id)) return;
|
|
233
|
+
for (const bugId of bugsOf(story)) {
|
|
234
|
+
const bug = byId.get(bugId);
|
|
235
|
+
if (bug && !satisfied.has(bug.status) && !inSprint.has(bugId)) forceAdd(bug);
|
|
236
|
+
}
|
|
237
|
+
for (const depId of depsOf(story)) {
|
|
238
|
+
const dep = byId.get(depId);
|
|
239
|
+
if (dep && dep.status === 'groomed' && !inSprint.has(depId)) forceAdd(dep);
|
|
240
|
+
}
|
|
241
|
+
add(story);
|
|
242
|
+
};
|
|
243
|
+
|
|
229
244
|
let overBudget = false;
|
|
245
|
+
// Anti-stall (empty sprint): nothing fit the budget but groomed work exists — the smallest eligible
|
|
246
|
+
// story exceeds the whole velocity. Plan the highest-priority groomed story alone, over budget, so the
|
|
247
|
+
// project can never stall on a story that can never be packed. Same out-of-batch guard as the main
|
|
248
|
+
// loop (review #20): never force-plan a story whose unpacked prerequisite never shipped.
|
|
230
249
|
if (sprintStories.length === 0 && byPriority.length > 0) {
|
|
231
|
-
const forceAdd = (story) => {
|
|
232
|
-
if (inSprint.has(story.id)) return;
|
|
233
|
-
for (const bugId of bugsOf(story)) {
|
|
234
|
-
const bug = byId.get(bugId);
|
|
235
|
-
if (bug && !satisfied.has(bug.status) && !inSprint.has(bugId)) forceAdd(bug);
|
|
236
|
-
}
|
|
237
|
-
for (const depId of depsOf(story)) {
|
|
238
|
-
const dep = byId.get(depId);
|
|
239
|
-
if (dep && dep.status === 'groomed' && !inSprint.has(depId)) forceAdd(dep);
|
|
240
|
-
}
|
|
241
|
-
add(story);
|
|
242
|
-
};
|
|
243
|
-
// Same out-of-batch guard as the main loop (review #20): the anti-stall must not force-plan
|
|
244
|
-
// a story whose unpacked prerequisite never shipped.
|
|
245
250
|
const candidate = byPriority.find((s) => outOfBatchDepsSatisfied(s));
|
|
246
251
|
if (candidate) {
|
|
247
252
|
forceAdd(candidate);
|
|
@@ -249,6 +254,20 @@ export function packSprint(stories, velocity, opts = {}) {
|
|
|
249
254
|
}
|
|
250
255
|
}
|
|
251
256
|
|
|
257
|
+
// Feature-starvation guard (HARNESS-GAPS 2026-06-18, M-19 Issue 2 / orchestrator-confirmed): the
|
|
258
|
+
// empty-sprint anti-stall above does NOT fire when a small bug/spike fits — so a 1-pt bug packed while
|
|
259
|
+
// every groomed FEATURE exceeds velocity strands all feature work indefinitely (a bug-only sprint makes
|
|
260
|
+
// no product progress). If the packed set has NO feature story yet a deps-satisfied groomed feature
|
|
261
|
+
// exists, force the highest-priority one in over budget (same dependency-safe forceAdd).
|
|
262
|
+
const isFeature = (s) => s && s.type !== 'bug' && s.type !== 'spike';
|
|
263
|
+
if (sprintStories.length > 0 && !sprintStories.some((id) => isFeature(byId.get(id)))) {
|
|
264
|
+
const topFeature = byPriority.find((s) => isFeature(s) && !inSprint.has(s.id) && outOfBatchDepsSatisfied(s));
|
|
265
|
+
if (topFeature) {
|
|
266
|
+
forceAdd(topFeature);
|
|
267
|
+
overBudget = true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
252
271
|
const buffer = groomed.filter((s) => !inSprint.has(s.id)).map((s) => s.id);
|
|
253
272
|
const pointsPlanned = sprintStories.reduce((sum, id) => sum + pointsOf(byId.get(id)), 0);
|
|
254
273
|
|