/** * v5.6 C added the OST (Output-Style Validation) scanner — a 14th orchestrated * scanner. The frozen v5.0.0 byte-equal baselines predate it (13 scanners), so * this strips the additive OST scanner entry before comparison, the same way * strip-hotspot-load-pattern.mjs handles B2's additive hotspot fields. Stripping * (rather than re-seeding the frozen snapshots) keeps the strongest invariant: * the ORIGINAL 13 scanners still emit byte-identical output, and the frozen * snapshots stay free of post-v5.0.0 drift (the hotspot triple, ancestor token * counts) that re-seeding would bake in. * * Removing a zero-finding scanner entry only moves `aggregate.scanners_ok` * (OST is always status 'ok' and emits nothing on the deterministic fixture, so * total_findings / counts / risk_score / verdict are unchanged). The strip * decrements scanners_ok to match. * * Mutates in place and returns the payload for chaining inside a normalizer: * return stripAddedScanners(stripHotspotLoadPattern(out)); */ const ADDED_SCANNERS = new Set(['OST', 'OPT']); function stripFromEnvelope(env) { if (!env || typeof env !== 'object' || !Array.isArray(env.scanners)) return; let removedOk = 0; const kept = []; for (const s of env.scanners) { if (ADDED_SCANNERS.has(s.scanner)) { if (s.status === 'ok') removedOk++; continue; } kept.push(s); } env.scanners = kept; if (env.aggregate && typeof env.aggregate.scanners_ok === 'number') { env.aggregate.scanners_ok -= removedOk; } } /** * Strip added (post-v5.0.0) scanner entries from a CLI payload / envelope — * both top-level (`scanners`) and nested (`scannerEnvelope.scanners`). * @template T * @param {T} payload * @returns {T} */ export function stripAddedScanners(payload) { if (!payload || typeof payload !== 'object') return payload; stripFromEnvelope(payload); if (payload.scannerEnvelope) stripFromEnvelope(payload.scannerEnvelope); return payload; } /** * Remove `[OST] …` per-scanner progress lines from a captured stderr scorecard, * so a 14-scanner live run matches the frozen 13-scanner stderr snapshot. * @param {string} text * @returns {string} */ export function stripAddedScannerStderr(text) { if (typeof text !== 'string') return text; return text.replace(/^[ \t]*\[(OST|OPT)\][^\n]*\n/gm, ''); }