fix(review): the payload decides the engine, and a tie keeps the reviewer finding

An engine's brief-conflict mark could lower a reviewer agent's MAJOR: ingest kept an engine field a reviewer wrote on its own finding, and on a severity tie the survivor depended on payload order (engine first gave ALLOW, reviewer first WARN). ingest now takes engine from the payload source; Pass 1 and the workflow dedup keep the reviewer-agent finding on a tie. Prose (coordinator Pass 1, Handover 6) follows. Decision 13, operator 12.10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-12 18:50:56 +02:00
commit 305ac9284f
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
6 changed files with 140 additions and 12 deletions

View file

@ -120,8 +120,10 @@ const VERDICT_SCHEMA = {
// Inlined dedup by (file,line,rule_key) — the JS-side replacement for the
// coordinator's pass-1 triplet dedup (T2 §5 / lib/review/plan-review-dedup.mjs
// pattern; scripts cannot import, so the triplet key is inlined). On a
// repeated triplet the higher severity stays; at equal severity the finding
// with an `engine` stays; otherwise the first-seen one stays.
// repeated triplet the higher severity stays; at equal severity a reviewer
// finding (no `engine`) stays over an engine finding, so an engine's mark never
// lowers what a reviewer agent asserted (decision 13, operator 12.10, as
// coordinator-contract Pass 1); otherwise the first-seen one stays.
function dedupByTriplet(findings) {
const seen = new Map();
for (const f of findings) {
@ -129,8 +131,8 @@ function dedupByTriplet(findings) {
if (!seen.has(key)) { seen.set(key, f); continue; }
const kept = seen.get(key);
const higher = sevRank(f.severity) < sevRank(kept.severity);
const tieToEngine = sevRank(f.severity) === sevRank(kept.severity) && Boolean(f.engine) && !kept.engine;
if (higher || tieToEngine) seen.set(key, f);
const tieToReviewer = sevRank(f.severity) === sevRank(kept.severity) && !f.engine && Boolean(kept.engine);
if (higher || tieToReviewer) seen.set(key, f);
}
return [...seen.values()];
}