valent-pipeline 0.19.32 → 0.19.34
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
|
@@ -2833,8 +2833,9 @@ async function runStory(story) {
|
|
|
2833
2833
|
const evidenceNote = hasMachineEvidence
|
|
2834
2834
|
? `\n\nMACHINE EVIDENCE (authoritative): the deterministic Evidence gate already ran ` +
|
|
2835
2835
|
`\`evidence assert\` + \`trace check\` (gate verdict: ${evGate.verdict}${evGate.escalated ? ', escalated after the rework cap' : ''}${evGate.advisory ? ', advisory' : ''}). ` +
|
|
2836
|
-
|
|
2837
|
-
|
|
2836
|
+
(evGate.verdictPath
|
|
2837
|
+
? `Read the assert JSON the Evidence gate VERIFIED — \`${evGate.verdictPath}\` — NOT merely the newest file under \`stories/${sid}/evidence/asserts/\` (a transient or mislabeled-label run can be newer and carry the wrong counts) — and TRANSCRIBE testsPassed/testsFailed/openP1toP3 `
|
|
2838
|
+
: `Read the NEWEST green qa-b JSON under \`stories/${sid}/evidence/asserts/\` and TRANSCRIBE testsPassed/testsFailed/openP1toP3 `) +
|
|
2838
2839
|
`from its counts (openP1toP3 = bugs in the \`valent:bugs\` block of bugs.md with status open/fix-in-progress AND priority P1/P2/P3, EXCLUDING any with \`preExisting: true\` or \`category: pre-existing\` — baselined pre-existing bugs are non-blocking and the cross-check counts them separately, so including them here produces a verdict-integrity mismatch and refuses the ship) — do NOT count from execution-report.md prose. ` +
|
|
2839
2840
|
`Set evidenceVerdict to the assert verdict and gitSha to the evidence run's SHA. Your job on numbers is ANOMALY ` +
|
|
2840
2841
|
`DETECTION: FLAG as a discrepancy any claim in execution-report.md / traceability-matrix.md / bugs.md that the ` +
|
package/src/lib/crosscheck.js
CHANGED
|
@@ -62,17 +62,31 @@ export function crosscheckVerdict({ reported = null, bugsBlock = null, assertVer
|
|
|
62
62
|
// ship is claimed < actual — and refusing it stranded genuinely shippable stories. So an
|
|
63
63
|
// over-report on these fields reconciles to the authoritative recount with a warning; an
|
|
64
64
|
// under-report stays a hard mismatch. (Prompt tightening alone did not hold — the LLM still
|
|
65
|
-
// over-counts; this is the mechanical backstop.)
|
|
66
|
-
//
|
|
65
|
+
// over-counts; this is the mechanical backstop.)
|
|
66
|
+
//
|
|
67
|
+
// GOOD-thing counts (testsPassed) are the MIRROR IMAGE: the unsafe, ship-sneaking direction is
|
|
68
|
+
// OVER-claiming (padding green to look more passing than reality), so an over-claim stays a hard
|
|
69
|
+
// mismatch; an UNDER-report (claimed FEWER passes than the recount) is the safe direction — you
|
|
70
|
+
// cannot sneak a ship by under-stating passes, because the ship gates on the authoritative recount,
|
|
71
|
+
// not on this transcribed number — so it reconciles to the recount with a warning. This closes the
|
|
72
|
+
// JUDGE-verdict-path analogue of Gap 2 (label-multiplexing, 2026-06-18): a transcribed testsPassed
|
|
73
|
+
// bound to a transient/mislabeled qa-b run under-counts passes, which is harmless and must not
|
|
74
|
+
// refuse a ship the green assert already proved. Exact-match fields (verdict, reviewedSha) keep
|
|
75
|
+
// strict equality in both directions.
|
|
67
76
|
const SAFE_IF_OVER_REPORTED = new Set(['testsFailed', 'openP1toP3']);
|
|
77
|
+
const SAFE_IF_UNDER_REPORTED = new Set(['testsPassed']);
|
|
68
78
|
const compare = (field, actual) => {
|
|
69
79
|
recounted[field] = actual;
|
|
70
80
|
if (!claim(field) || reported[field] === actual) return;
|
|
71
|
-
|
|
72
|
-
|
|
81
|
+
const numeric = typeof reported[field] === 'number' && typeof actual === 'number';
|
|
82
|
+
if (numeric && SAFE_IF_OVER_REPORTED.has(field) && reported[field] > actual) {
|
|
73
83
|
warnings.push(`${field}: self-reported ${reported[field]} but artifacts show ${actual} — over-report (safe, conservative direction), reconciled to the recount`);
|
|
74
84
|
return;
|
|
75
85
|
}
|
|
86
|
+
if (numeric && SAFE_IF_UNDER_REPORTED.has(field) && reported[field] < actual) {
|
|
87
|
+
warnings.push(`${field}: self-reported ${reported[field]} but artifacts show ${actual} — under-report (safe direction: under-stating passes cannot sneak a ship), reconciled to the recount`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
76
90
|
mismatches.push({ field, claimed: reported[field], actual });
|
|
77
91
|
};
|
|
78
92
|
|
|
@@ -66,10 +66,38 @@ export function isGatableToken(token) {
|
|
|
66
66
|
return true;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Blank out JS/TS comments — both line and block comments — so a skip marker that appears only inside
|
|
71
|
+
* a comment (a commented-out `// it.skip(...)`, or an `it.skip` mentioned inside a JSDoc/block comment)
|
|
72
|
+
* is not mistaken for a real skip (HARNESS-GAPS 2026-06-18). Comment bytes become spaces; newlines and
|
|
73
|
+
* tabs are preserved so line numbers and the waiver line-window stay exact. String / template literals
|
|
74
|
+
* are tracked, so a comment-looking substring INSIDE a string is left intact — a real marker is never
|
|
75
|
+
* hidden (no false-negatives).
|
|
76
|
+
*/
|
|
77
|
+
export function stripComments(content) {
|
|
78
|
+
const s = String(content || '');
|
|
79
|
+
let out = '';
|
|
80
|
+
let state = 'code'; // code | line | block | sq | dq | tpl
|
|
81
|
+
const ws = (ch) => (ch === '\n' || ch === '\t' ? ch : ' ');
|
|
82
|
+
for (let i = 0; i < s.length; i++) {
|
|
83
|
+
const c = s[i];
|
|
84
|
+
const d = s[i + 1];
|
|
85
|
+
if (state === 'code') {
|
|
86
|
+
if (c === '/' && d === '/') { state = 'line'; out += ' '; i++; continue; }
|
|
87
|
+
if (c === '/' && d === '*') { state = 'block'; out += ' '; i++; continue; }
|
|
88
|
+
if (c === "'") { state = 'sq'; out += c; continue; }
|
|
89
|
+
if (c === '"') { state = 'dq'; out += c; continue; }
|
|
90
|
+
if (c === '`') { state = 'tpl'; out += c; continue; }
|
|
91
|
+
out += c; continue;
|
|
92
|
+
}
|
|
93
|
+
if (state === 'line') { if (c === '\n') { state = 'code'; out += c; } else out += ws(c); continue; }
|
|
94
|
+
if (state === 'block') { if (c === '*' && d === '/') { state = 'code'; out += ' '; i++; } else out += ws(c); continue; }
|
|
95
|
+
// inside a string/template literal: copy verbatim, honor backslash escapes, close on the quote
|
|
96
|
+
out += c;
|
|
97
|
+
if (c === '\\') { out += (s[i + 1] ?? ''); i++; continue; }
|
|
98
|
+
if ((state === 'sq' && c === "'") || (state === 'dq' && c === '"') || (state === 'tpl' && c === '`')) state = 'code';
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
73
101
|
}
|
|
74
102
|
|
|
75
103
|
/**
|
|
@@ -81,14 +109,16 @@ function stripLineComment(line) {
|
|
|
81
109
|
*/
|
|
82
110
|
function scanSkips(file) {
|
|
83
111
|
const out = [];
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
112
|
+
const raw = (file.content || '').split(/\r?\n/);
|
|
113
|
+
// Match skip markers in CODE only — comments (line `//` and block `/* */`) are blanked so a marker
|
|
114
|
+
// that merely appears inside a comment is not flagged. The waiver check still reads the RAW line,
|
|
115
|
+
// since the `valent-waiver:` token lives in a comment / the it.skip() title.
|
|
116
|
+
const code = stripComments(file.content || '').split(/\r?\n/);
|
|
117
|
+
for (let i = 0; i < raw.length; i++) {
|
|
88
118
|
SKIP_MARKER.lastIndex = 0;
|
|
89
|
-
const m = code.match(SKIP_MARKER);
|
|
119
|
+
const m = (code[i] || '').match(SKIP_MARKER);
|
|
90
120
|
if (!m) continue;
|
|
91
|
-
const waived = WAIVER_RE.test(raw) ||
|
|
121
|
+
const waived = WAIVER_RE.test(raw[i]) || raw.slice(Math.max(0, i - 3), i).some((l) => WAIVER_RE.test(l));
|
|
92
122
|
if (waived) continue;
|
|
93
123
|
out.push({
|
|
94
124
|
kind: 'unwaived-skip',
|