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

@ -457,3 +457,80 @@ test('Handover 6 — names the fields, engine findings only, the one lowering an
assert.match(h6, /cannot check an `engine` label on the prose path/);
assert.match(h6, /skips a lowered finding/, 'a plan made from the review skips a lowered (MINOR) finding');
});
// ---- Decision 13 (operator 12.10): the source decides, a tie keeps the reviewer --
//
// "Came from an engine" is read from the payload a finding arrived in, never
// from an `engine` field a reviewer wrote on its own finding; and on a severity
// tie a reviewer-agent finding survives over an engine finding, so an engine's
// mark can never lower what a reviewer agent asserted, whatever the order.
function reviewerCopy(extra = {}) {
const { engine: _e, ...rest } = codeReviewDefect({ title: 'Reviewer: no retry', ...extra });
return rest;
}
test('decision 13 — a reviewer payload whose finding labels itself engine code-review is not lowered', () => {
const f = codeReviewDefect({ contradicts_brief: NON_GOAL });
const result = m.runContract(payload('code-correctness-reviewer', [f]));
const out = result.findings[0];
assert.equal(out.severity, 'MAJOR', 'a reviewer MAJOR is never lowered by the brief rule');
assert.equal('brief_lowered_from' in out, false);
assert.equal('engine' in out, false, 'engine comes from the payload source, not the field');
assert.equal('contradicts_brief' in out, false, 'only an engine finding is ever marked');
assert.equal(result.verdict, 'WARN');
assertAllOutputLegal(result);
});
test('decision 13 — an engine payload decides the engine: a /security-review payload finding labelled code-review keeps its severity', () => {
const f = codeReviewDefect({ contradicts_brief: NON_GOAL });
const result = m.runContract(payload('claude-security-review', [f]));
const out = result.findings[0];
assert.equal(out.engine, 'security-review');
assert.equal(out.severity, 'MAJOR');
assert.equal('brief_lowered_from' in out, false);
assert.equal(out.contradicts_brief, NON_GOAL, 'the mark is kept on an engine finding');
assertAllOutputLegal(result);
});
for (const order of ['reviewer first', 'engine first']) {
test(`decision 13 — a tie between a marked /code-review MAJOR and a reviewer MAJOR keeps the reviewer (${order}) → WARN`, () => {
const reviewerPayload = { reviewer: 'code-correctness-reviewer', findings: [reviewerCopy({ rule_key: 'MISSING_TEST' })] };
const enginePayload = { reviewer: 'claude-code-review', findings: [codeReviewDefect({ rule_key: 'MISSING_TEST', contradicts_brief: NON_GOAL })] };
const payloads = order === 'reviewer first' ? [reviewerPayload, enginePayload] : [enginePayload, reviewerPayload];
const result = m.runContract(payloads);
assert.equal(result.findings.length, 1);
const out = result.findings[0];
assert.equal(out.severity, 'MAJOR', 'the reviewer agent asserted MAJOR; the engine mark cannot lower it');
assert.equal('brief_lowered_from' in out, false);
assert.equal('engine' in out, false, 'the survivor is the reviewer finding');
assert.equal('contradicts_brief' in out, false);
assert.deepEqual([...out.raised_by].sort(), ['claude-code-review', 'code-correctness-reviewer']);
assert.equal(result.verdict, 'WARN');
assertAllOutputLegal(result);
});
}
test('decision 13 — an engine MAJOR over a reviewer MINOR on the same triplet still drops to MINOR (the engine wins on severity)', () => {
const result = m.runContract([
{ reviewer: 'code-correctness-reviewer', findings: [reviewerCopy({ rule_key: 'MISSING_TEST', severity: 'MINOR' })] },
{ reviewer: 'claude-code-review', findings: [codeReviewDefect({ rule_key: 'MISSING_TEST', contradicts_brief: NON_GOAL })] },
]);
const out = result.findings[0];
assert.equal(out.engine, 'code-review');
assert.equal(out.severity, 'MINOR');
assert.equal(out.brief_lowered_from, 'MAJOR');
assert.equal(result.verdict, 'ALLOW');
assertAllOutputLegal(result);
});
test('decision 13 — the prose states the tie rule (coordinator Pass 1, Handover 6)', () => {
const coordinator = readDoc('agents', 'review-coordinator.md');
const pass1 = cut(coordinator, '### Pass 1', '### Pass 2', 'coordinator Pass 1');
assert.match(pass1, /prefer\s+a\s+reviewer-agent\s+finding\s+over\s+an\s+engine\s+finding/,
'Pass 1: a tie keeps the reviewer-agent finding');
assert.match(pass1, /never\s+lowers\s+what\s+a\s+reviewer\s+agent\s+asserted/);
const h6 = cut(readDoc('docs', 'HANDOVER-CONTRACTS.md'), '## Handover 6 — `review.md` → plan', '\n## Handover 7', 'Handover 6');
assert.match(h6, /takes? `engine` from the payload a finding arrived in/);
assert.match(h6, /on a severity tie[^.]*a reviewer-agent finding survives[^.]*over an engine finding/i);
});

View file

@ -321,3 +321,22 @@ test('armB brief rule — VERDICT_SCHEMA declares engine, contradicts_brief and
assert.ok(/only an engine finding/i.test(prompt), 'engine findings only');
assert.ok(/kept and marked, never removed/i.test(prompt));
});
// Decision 13 (operator 12.10): on a severity tie a reviewer-agent finding
// survives dedup over an engine finding, so the engine's mark can never lower
// what a reviewer agent asserted (the same rule as coordinator-contract Pass 1).
test('armB brief rule (15) — a tie between a reviewer MAJOR and a /code-review MAJOR keeps the reviewer: the legal shape returned with ALLOW → WARN, no engine', async () => {
const c = await floorCase({
reviewerFindings: [F('CODE_REVIEW_DEFECT', 'MAJOR')],
codeFindings: [F('CODE_REVIEW_DEFECT', 'MAJOR')],
returned: [F('CODE_REVIEW_DEFECT', 'MINOR', { contradicts_brief: MARK, brief_lowered_from: 'MAJOR', engine: 'code-review' })],
verdict: 'ALLOW',
});
assert.equal(c.merged.length, 1);
assert.equal(c.merged[0].severity, 'MAJOR');
assert.equal('engine' in c.merged[0], false, 'the tie keeps the reviewer finding');
assert.equal(c.r.verdict, 'WARN');
assert.equal(c.r.findings[0].severity, 'MAJOR');
assert.equal('engine' in c.r.findings[0], false);
checkRaise(c, true);
});