valent-pipeline 0.19.21 → 0.19.22
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 +1 -1
- package/src/lib/crosscheck.js +16 -2
- package/src/lib/git-flow.js +13 -1
package/package.json
CHANGED
package/src/lib/crosscheck.js
CHANGED
|
@@ -55,11 +55,25 @@ export function crosscheckVerdict({ reported = null, bugsBlock = null, assertVer
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const claim = (field) => reported && reported[field] !== undefined && reported[field] !== null;
|
|
58
|
+
// Counts of BAD things (failures, open blocking bugs): a self-report HIGHER than the machine
|
|
59
|
+
// recount is the SAFE, conservative direction — the gate was harder on itself than reality (e.g. a
|
|
60
|
+
// JUDGE that counted a pre-existing, baseline-excluded failure as testsFailed/openP1toP3). That is
|
|
61
|
+
// NOT the integrity breach this module exists to catch — a gate HIDING failures/bugs to sneak a
|
|
62
|
+
// ship is claimed < actual — and refusing it stranded genuinely shippable stories. So an
|
|
63
|
+
// over-report on these fields reconciles to the authoritative recount with a warning; an
|
|
64
|
+
// under-report stays a hard mismatch. (Prompt tightening alone did not hold — the LLM still
|
|
65
|
+
// over-counts; this is the mechanical backstop.) Good-thing counts (testsPassed) and exact-match
|
|
66
|
+
// fields keep strict equality, where over-claiming IS the unsafe direction.
|
|
67
|
+
const SAFE_IF_OVER_REPORTED = new Set(['testsFailed', 'openP1toP3']);
|
|
58
68
|
const compare = (field, actual) => {
|
|
59
69
|
recounted[field] = actual;
|
|
60
|
-
if (claim(field)
|
|
61
|
-
|
|
70
|
+
if (!claim(field) || reported[field] === actual) return;
|
|
71
|
+
if (SAFE_IF_OVER_REPORTED.has(field) && typeof reported[field] === 'number'
|
|
72
|
+
&& typeof actual === 'number' && reported[field] > actual) {
|
|
73
|
+
warnings.push(`${field}: self-reported ${reported[field]} but artifacts show ${actual} — over-report (safe, conservative direction), reconciled to the recount`);
|
|
74
|
+
return;
|
|
62
75
|
}
|
|
76
|
+
mismatches.push({ field, claimed: reported[field], actual });
|
|
63
77
|
};
|
|
64
78
|
|
|
65
79
|
// Test counts — from the assert verdict (machine-derived twice over).
|
package/src/lib/git-flow.js
CHANGED
|
@@ -402,7 +402,19 @@ export function startStory({ root, story, targetBranch = '', prefix = 'story/',
|
|
|
402
402
|
snapshotSha = snap.sha || null;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
|
|
405
|
+
// An inline fix (--from-story) inherits its SOURCE story's recorded target — NOT the
|
|
406
|
+
// currently-checked-out branch. Running several fixes for one story back-to-back leaves HEAD on the
|
|
407
|
+
// previous fix's branch; defaulting `target` to onBranch made each later fix target (and, via the
|
|
408
|
+
// base check below, base on) its SIBLING fix branch — so the fixes silently chained onto the first
|
|
409
|
+
// fix's branch instead of the story, stranded off the real target (2026-06-14). An explicit
|
|
410
|
+
// --target still wins; onBranch stays the fallback for a plain story or a fix whose source has no
|
|
411
|
+
// flow record yet. With the right target, the base check (`!isMergedInto(source, target)`) also
|
|
412
|
+
// resolves correctly — the source story is unmerged into the REAL target, so the fix bases on it.
|
|
413
|
+
let inheritedTarget = null;
|
|
414
|
+
if (fromStory && !targetBranch) {
|
|
415
|
+
inheritedTarget = readFlowRecord(root, fromStory)?.target || null;
|
|
416
|
+
}
|
|
417
|
+
const target = targetBranch || inheritedTarget || onBranch;
|
|
406
418
|
let base = target;
|
|
407
419
|
let basedOnStory = false;
|
|
408
420
|
if (fromStory) {
|