ADR-115: Principle-aware PR reviewers
Status: Proposed Date: 2026-04-26 Related: ADR-083 (defense-in-depth-rule-promotion), ADR-090 (ai-as-scaffold-pipelines-as-runtime), ADR-104 (dry-run-on-history-adaptive-gate), ADR-110 (observe-and-file-dominant-pattern), ADR-112 (principles tier — sibling PR), ADR-117 (module guidelines — sibling)
Context
The 2026-04-26 PR cycle produced two --admin overrides on the same wrong-premise pattern: Marcus blocked devtools#126 citing the "docs/shared/ propagation rule" against a repo-root README, where the rule plainly does not apply (the README is authoritative source, not generated artifact); Priya blocked dark-factory#465 citing input-validation principles against ansible -e on an operator-controlled controller, where the trust boundary is shell access, not network. In both cases the operator authorised the --admin with an audit reason naming why the reviewer was wrong, per the feedback_admin_override_with_audit.md memory rule.
The root cause is structural: each persona reviews from training priors, re-deriving judgement per PR with no shared context about the project's structural decisions. The same wrong-premise pattern recurs whenever a similar diff shape lands, because the personas have no memory and the project has no canonical priors for them to consult. This is the recurring --admin loop the operator named in warp #341 ("PR reviews that can consistently and stay on course with an idea").
The principles tier (warp #339, ADR-112 sibling) creates the data layer. This ADR is the operational counterpart: reviewers consume that data layer before judging.
Decision
Each persona's CLAUDE.md prompt (gyrum-priya, gyrum-marcus, gyrum-lin, gyrum-dana) opens with a load-bearing "Principles applicable to this PR" section that fetches relevant principles from the warp API before reviewing:
curl -sH "Authorization: Bearer $WARP_TOKEN" \
"$WARP_URL/api/v1/principles?applies_to_pattern=<file-path-glob>"
The personas filter by per-persona principles_scope (Priya → security/scope-creep/trust-boundaries; Marcus → architecture/abstractions/layering; Lin → testing/idioms/contracts; Dana → docs/UX) plus cross-area principles ("structural beats prose") visible to all. Every blocking objection MUST cite a principle id with a one-line summary; concerns without an applicable principle surface as ADVISORY, not BLOCKING. If the reviewer believes a structural principle should exist but cannot find one, they file a kind: principle, status: proposed ticket and surface the concern as advisory this round.
Anti-examples — the cases where a principle looks like it applies but does not — are first-class on the principle record. Today's two false positives become the seed corpus: the docs/shared/ rule gains an anti-example for repo-root READMEs; the input-validation principle gains one for operator-controlled ansible -e. When a future --admin override fires with audit reason naming "false positive on premise X", the system auto-files a principle anti-example proposal so the next PR with the same diff shape does not hit the same wall.
The operator override path is unchanged: --admin remains available for the case where the operator disagrees with reviewer + principles together. Override frequency is telemetry — the r7 sub-ticket alerts when overrides cluster on a missing principle, signalling a gap to fill rather than a reviewer to scold.
Consequences
What becomes easier.
- Reviewers are consistent across PRs of the same shape. The "what does Marcus think today" variance collapses to "what do these principles say about this change".
- Recurring
--adminoverrides become signal, not noise. A cluster of overrides on the same audit reason means a missing or wrong principle, and the anti-example auto-file path closes the loop without operator effort beyond writing the audit reason once. - Reviewer reasoning becomes auditable. Every block cites a principle id; later we can ask "which principles are most cited on blocks?" and "which are most overridden?" and tune accordingly.
- The persona-PAT rubber-stamp risk drops. Today a persona with no priors and a vague prompt can produce reviewer-themed prose; with cited-principle-or-advisory-only as a hard rule, the prose has to land on a real anchor.
What becomes harder.
- Each persona pays a
+2-3sprinciple fetch per review. Acceptable: review wall-clock is dominated by the model call already, and the principles endpoint is small and indexed. - Stale or wrong principles cascade into wrong reviews. Mitigation: the principle-revision workflow (warp #339 r7) gives a clear path to amend, and the
status: supersededfield withsuperseded_bykeeps reviewers off retired rules. - Over-citation risk: reviewers might cite principles for everything, drowning the real concerns. Mitigation: the
applies_topattern on each principle is checked against the diff before citation is allowed; principles without a matchingapplies_toglob cannot be cited as blocking. - Bypass-via-blindness is replaced by bypass-via-worship as the failure mode to watch. Mitigation: ADVISORY surface for non-principle concerns (genuine reviewer judgement still gets a voice) and the operator override path always available.
What we sign up to maintain.
- The
GET /api/v1/principles?applies_to_pattern=endpoint and its index for sub-second lookups. - Per-persona
principles_scopedefaults and the cross-area "visible to all" tag set. - The auto-file-on-override pipeline that turns audit reasons into principle anti-example proposals.
- The override-rate telemetry per persona, with the alert threshold on weekly clustering.
Alternatives considered
- Embed principles in the persona prompt at build time. Rejected: every principle change requires a persona-prompt redeploy; the data layer (warp #339) exists exactly so the rules can evolve without coordinated releases.
- Single shared "review checklist" instead of per-persona principles_scope. Rejected: collapses the four-persona signal into one. The whole point of the four personas is that security, architecture, testing, and docs are different lenses; the principle set has the same shape.
- Make principle citation advisory, not required, for blocks. Rejected: that is today, with extra ceremony. The bug being fixed is "blocks without principle backing"; making the backing optional re-introduces the bug.
- Skip personas, run a single principle-checker bot. Rejected: principles cover structural concerns, but reviewers also catch concerns no principle predicts (subtle bugs, naming, test gaps). The personas remain; the principles constrain their blocking criteria, not their advisory voice.
Supersedes: none Superseded by: none yet
Amendment — 2026-04-29 (warp#698 / ADR-124)
Marcus's principles_scope (architecture/abstractions/layering) gains the block-composition principle from ADR-124. PRs introducing a new monolithic step under cmd/server/pipeline/**, pkg/pipeline/**, or pkg/block/** — or any new directory importing gyrum-pipelines/pkg/block — must be blocked with a citation to ADR-124. Concerns raised against legacy pipelines pre-dating ADR-124 surface as ADVISORY (the graduation campaign in warp#707 owns the migration), not BLOCKING.