Skip to content

feat(eval): C3 cross-family EVAL panel — close same-family generator↔evaluator - #479

Merged
ProtocolWarden merged 2 commits into
mainfrom
feat/c3-eval-panel
Jul 15, 2026
Merged

feat(eval): C3 cross-family EVAL panel — close same-family generator↔evaluator#479
ProtocolWarden merged 2 commits into
mainfrom
feat/c3-eval-panel

Conversation

@ProtocolWarden

Copy link
Copy Markdown
Owner

What

Council spec (docs/design/COUNCIL_VERDICT.md) Phase 3 / C3 — the last council phase. Closes the guide-gap audit's HIGH finding: same-family generator↔evaluator.

The EVAL drift monitor is supposed to grade the production reviewer (claude family) with a different family — but that requirement was only a code comment, and the task shipped wired extractor=None (permanently inert). C3 turns cross-family from a comment into a control.

How

  • eval/panel_critic.run_panel_drift_monitor (pure, 100% unit-tested): grades each configured family independently — a per-family majority vote that is never pooled across families for the drift decision — and flags drifted = any family's own majority ≠ the signed answer. This is what stops a dominant/larger family from masking its own drift by outvoting a smaller one. (C1's aggregate_council doesn't fit — its unanimous-LGTM/merge shape is a decision, not a drift-vs-answer grade — so C3 has its own aggregator.)
  • eval/panel_invoker.LiveFamilyExtractor: runs each family via the shared build_member_argv + a codex stdout-JSON fallback (verdict.last_json_object).
  • member_runner.py: build_member_argv extracted verbatim from pr_review_watcher/main.py (a pure move) so the EVAL invoker never imports the merge-critical reviewer module. C1's 166 reviewer tests stay green.
  • EvalPanelSettings: panel=[] / enabled=FalseOFF by default, mirroring C1's empty-guardrail-paths rollout.
  • Degraded panel refuses to collapse: if a configured family's CLI is unavailable, the monitor skippeds with a loud reason — it never silently grades with a single (same) family, which would re-open the finding.

Status / prerequisites

Fully wired and unit-tested with injected fakes, but inert in production until an extraction-kind corpus exists (the seed corpus is verdict-kind) — same inert-until-seeded posture BackendCheckExtractor already had. The deterministic Lane-1 replay gate (model-free) is unchanged and remains the only blocking control.

Tests

tests/unit full suite 8531 pass at 86.03% (gate 85%); reviewer suite 166 pass (C1 intact after the extraction); ruff clean. New modules 100% covered (impure subprocess glue pragma: no cover). Per-family domination cases (claude drifts / codex agrees, and reverse) and degraded-family-skip are explicitly tested.

Council spec Phase 3 (C3). Completes the C1 (#469) + C2 (ContextLifecycle #43) + C3 council trilogy.

🤖 Generated with Claude Code

ProtocolWarden and others added 2 commits July 15, 2026 12:22
…evaluator

The EVAL drift monitor is meant to grade the claude reviewer with a different
family, but that was only a comment and the task was wired extractor=None
(inert). C3 makes cross-family a control: run_panel_drift_monitor grades each
family independently (per-family majority, never pooled) and flags drift when
ANY family's own majority disagrees with the signed answer — a dominant family
can't mask its own drift. LiveFamilyExtractor runs each family via a shared
build_member_argv (extracted verbatim from pr_review_watcher/main.py into
member_runner.py — a pure move; C1 reviewer tests stay green) + codex stdout
fallback. EvalPanelSettings ships OFF (panel=[]/enabled=False). Degraded panel
=> skipped loud, never a same-family collapse. Inert until an extraction corpus
exists; wired + unit-tested with fakes. tests/unit 86.03%; reviewer 166 green.

Council spec COUNCIL_VERDICT.md Phase 3 (C3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ty flagged self._extractor (CheckExtractor | None) at the run_drift_monitor
call; the elif guard above already returns when it is None, so cast it (ruff
bans assert). No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ProtocolWarden
ProtocolWarden merged commit d351534 into main Jul 15, 2026
25 checks passed
@ProtocolWarden
ProtocolWarden deleted the feat/c3-eval-panel branch July 15, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant