fix(review): the coordinator gets the brief's choices and writes the brief-conflict mark

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

View file

@ -461,6 +461,22 @@ Since 1.1 (ordre 5):
- `## Declined to Judge` — required at `review_version` ≥ 1.1 (strict error, soft warning; 1.0 reviews exempt): every finding set aside without a ruling, with its reason (including engine findings outside the review scope, `engine:out-of-scope`), plus `Trimmed: N`. **No finding is struck for length**: only MINOR/SUGGESTION text is trimmed, and counted (`trimmed` in the JSON block); a long BLOCKER/MAJOR keeps every character.
- Findings from Claude Code's own `/code-review` and `/security-review` enter under the catalogue keys `CODE_REVIEW_DEFECT` (MAJOR), `CODE_REVIEW_IMPROVEMENT` (MINOR: a `/code-review` finding whose category is simplification, efficiency, reuse, style or readability) and `SECURITY_REVIEW_VULNERABILITY` (BLOCKER), or a narrower key, with `reviewer` `claude-code-review` / `claude-security-review`.
**The brief-conflict mark (fields `engine`, `contradicts_brief`, `brief_lowered_from`).**
Each finding may carry three more fields, in its body field list and in the trailing JSON block:
`engine` (`code-review` | `security-review`, on a finding that came from an engine),
`contradicts_brief` (the brief's Non-Goal or stated choice the finding's recommended action contradicts, verbatim)
and `brief_lowered_from` (`MAJOR`, written only by the one lowering).
The mark is a field on a kept finding, never a `suppressed_reason`.
Only an engine finding is ever marked; a reviewer-agent finding (no `engine`) and a finding whose `rule_key` is not in the catalogue never are.
The one legal lowering: a `/code-review` MAJOR-tier finding at severity MAJOR drops to MINOR, with `brief_lowered_from: MAJOR`;
a BLOCKER-tier, a MINOR-tier and any `/security-review` finding keep their severity and only carry the mark.
On an ALLOW or WARN review the verdict gate exits 2 on every finding `illegalBriefLowering` (`lib/review/coordinator-contract.mjs`) names:
any other `brief_lowered_from`, a mark on a reviewer-agent finding, a marked finding below its tier, a marked finding with an unknown key,
and an engine finding below its tier, marked or not (a BLOCK review exits 1 as before).
The gate cannot check an `engine` label on the prose path: there the coordinator writes the label, so a finding wrongly labelled `engine` is judged as an engine finding;
the workflow path (`--workflow`) takes `engine` from the payload source and writes it into the returned finding.
A plan made from the review skips a lowered finding: it is MINOR, and `/trekplan` takes BLOCKER and MAJOR findings only.
**Validation strategy:**
| Layer | When | What |