# ADR-0131.4 — Composite Math-Expert Promotion Gate (wired) **Status:** Accepted **Date:** 2026-05-23 **Author:** CORE main agent (Opus 4.7) **Depends on:** ADR-0131 (composite gate framing), ADR-0131.1 (B1 substrate), ADR-0131.1.S (B1 sealed holdout), ADR-0131.2 (B2 substrate), ADR-0131.3 (B3 substrate), ADR-0131.G.0 (probe substrate) **Parent:** ADR-0131 **Reserved follow-up:** the full ADR-0120 contract (9 ADR-0114a obligations not implemented yet for `mathematics_logic`). --- ## Context ADR-0131 introduced the composite math-expert promotion contract: > The `mathematics_logic` domain `expert` promotion contract is > revised. The ADR-0120 single-benchmark check > (`correct_rate ≥ 0.60` on GSM8K) is replaced by a composite > requirement: B1 ≥ 0.95 AND B2 ≥ 0.95 AND B3 ≥ 0.95, each with > `wrong == 0`. GSM8K is retained as a stress-test lane that the > math expert runs but is not gated on — reported as honest > disclosure. ADR-0131's implementation plan (sub-phase `0131.4`) named `formation/ratify.py` + `formation/promote.py` as the wire-up points. That was a misidentification: those modules govern the SPECULATIVE → COHERENT bridge for individual teaching examples (ADR-0021), not domain-tier expert promotion. The correct site is `core/capability/`, where `expert_demo.py` (the audit-passed gate) already lives and where ADR-0120 reserves `expert_promotion.py`. A full ADR-0120 implementation requires substrate for 10 ADR-0114a obligations (sealed holdout, OOD ratio, replay determinism, typed refusal + `wrong == 0`, perturbation, depth curve, frontier comparison, adversarial, byte-equal lane runner, operation provenance via pack). For `mathematics_logic`, only **5 of those 10 obligations** have substrate landed today: - #1 sealed holdout (ADR-0131.1.S — B1 sealed) - #3 replay-equal trace (B1/B2/B3 runners emit `trace_hash`) - #4 typed refusal + `wrong == 0` (the load-bearing invariant every G. and B-lane has been preserving) - #7 frontier-baseline comparison (ADR-0131.1.F) - #9 determinism (every B-lane report is byte-equal across runs) The other 5 (#2 OOD ratio, #5 perturbation, #6 depth curve, #8 adversarial, #10 operation-provenance-via-pack) need domain-specific substrate that isn't built yet. Implementing those is sequencing-wise *after* ADR-0131.4, not bundled with it. ## Decision Implement only the **ADR-0131-specific revision** as a focused module: the composite B1+B2+B3 evaluator. Structure it so a future `core/capability/expert_promotion.py` implementing the full ADR-0120 contract can consume it as the math-specific substitute for the single-lane coverage check. ### What this ADR wires `core/capability/composite_math_gate.py`: ```python def evaluate_composite_math_gate( *, b1_public_path, b1_sealed_path, b2_path, b3_path, gsm8k_probe_path, ) -> CompositeMathGateVerdict ``` - Reads each benchmark's already-committed `report.json` (no I/O beyond that; no recomputation of lane verdicts). - Handles the heterogeneous report shapes (B1/B2 use `counts: {correct, wrong, refused}`; B3 uses `metrics: {correct, wrong, cases_total, correct_rate}`). Refuses cleanly if the shape is neither. - Applies the pinned thresholds: `correct_rate ≥ 0.95` AND `wrong == 0` per benchmark. - Composes per-benchmark verdicts → composite verdict. - Computes a reproducible SHA-256 claim digest over the canonical evidence bundle (per ADR-0120 "Signed `expert_claims` entry with reproducible digest" requirement). - Emits GSM8K honest-disclosure (admission, wrong, refused, substrate) but does NOT use it in the gate. CLI wiring at `core capability math-expert-gate` (added to `core/cli.py`). Writes `evals/math_expert_claims/v1/expert_claims_math_v1.json` (unsigned). Reviewer signature via ADR-0092 reviewer-registry is reserved for the broader ADR-0120 wire-up. ### Empirical verdict Run against current `main` (post-PR #182/#183/#184/#185, pre-G.1): ``` composite_gate_passed: True claim_digest: 2bfc7f6c5b06a4c5befef3a9a2629a023518ae97490f6ddf092c1852c966c275 B1_public passed=True correct=185/185 wrong=0 rate=1.0000 B1_sealed passed=True correct=14/14 wrong=0 rate=1.0000 B2_teaching_corpus passed=True correct=40/40 wrong=0 rate=1.0000 B3_bounded_grammar passed=True correct=50/50 wrong=0 rate=1.0000 GSM8K honest disclosure: admission=0/50, wrong=0, substrate=candidate_graph ``` **The math expert is gate-passing under ADR-0131's revised composite contract.** The bet ADR-0131 placed — that the architecture's structural strengths align with three benchmarks that measure those strengths — has paid off on first evaluation. This does NOT mean the full ADR-0120 contract passes (5 of 10 obligations still need substrate). It means the *math-specific revision portion* of the contract passes today, and the architecturally-aligned bet was correct. ## What this does NOT do - Does NOT implement the broader ADR-0120 10-obligation contract. That requires substrate for 5 missing obligations (OOD ratio, perturbation, depth curve, adversarial, operation-provenance). - Does NOT promote `mathematics_logic` to `expert` ledger status. Ledger promotion is a separate ADR that consumes this gate's output AND the broader ADR-0120 obligations. - Does NOT sign the `expert_claims` artifact. Reviewer signature via ADR-0092 registry is reserved for the full wire-up. - Does NOT touch `formation/ratify.py` or `formation/promote.py` (the teaching-example-tier modules ADR-0131's plan misidentified). - Does NOT recompute the lane verdicts. The committed B-lane reports are the gate's input contract; the lane runners own their verdicts and the gate trusts them. If a reviewer suspects a lane report is stale, re-run the lane. ## Trust boundary - Reads only: - `evals/math_symbolic_equivalence/v1/report.json` + `sealed_report.json` - `evals/math_teaching_corpus/v1/report.json` - `evals/math_bounded_grammar/v1/report.json` - `evals/gsm8k_math/train_sample/v1/train_sample_coverage_report.json` (disclosure-only) - Writes only: the path passed to `emit_expert_claims_artifact` (default: `evals/math_expert_claims/v1/expert_claims_math_v1.json`). - No dynamic imports, no shell passthrough, no network. - Pure function over already-committed JSON; deterministic (verified by `test_claim_digest_reproducible` and `test_artifact_emission_byte_equal`). ## Tests `tests/test_adr_0131_4_composite_math_gate.py` — 12 tests: - Threshold values are pinned (changing requires a new ADR) - Both lane-report shapes parse correctly - Gate passes iff all 4 benchmarks pass - Gate refuses cleanly on threshold miss, on wrong-count > 0, on missing report - GSM8K disclosure handled (present, missing, never gates) - Claim digest reproducible (deterministic) - Artifact emission byte-equal across calls - Snapshot test: committed main state satisfies the composite gate 12/12 pass in 0.22s. ## CLAUDE.md PR-checklist - **Capability added:** wires the ADR-0131-specific composite benchmark evaluator at the right architectural layer (`core/capability/`); makes the math-expert promotion verdict computable, reproducible, and CLI-callable. - **Invariant proving field validity:** every B-lane's `wrong == 0` is preserved (the gate gates on it); GSM8K probe `admitted_wrong == 0` preserved. - **CLI/eval proving the lane:** `python3 -m core.cli capability math-expert-gate` + `pytest tests/test_adr_0131_4_composite_math_gate.py`. - **Avoided hidden normalization / stochastic / approximate / unreviewed mutation:** Yes. Pure function over committed JSON. - **Trust boundary:** read-only inputs, single deterministic write to a documented artifact path.