Phase 3.3 of the generalization arc. Estimation (ADR-0175), deduction serving (ADR-0256) and curriculum serving (ADR-0262) had each written the same seal -> ratify -> SHA-verify -> serve-gate machinery. core/ratified_ledger.py now owns it and states the four rules once: only sealed practice writes; tamper-evidence is structural (a load that cannot reproduce content_sha256 REFUSES); ceilings are not negotiable at the call site; absent evidence is never a license. Each capability keeps a thin adapter that names its artifact and preserves its public API. One real difference is now declared rather than implied: missing_ok distinguishes a ledger a capability SHIPS with (absence = broken deployment, refuse) from one whose practice volume is still being built (absence = nothing earned yet, serve disclosed) — curriculum serving is the second kind today. Safety property is byte-identity, asserted not assumed: re-sealing the committed 25-band deduction ledger through the bridge reproduces it byte-for-byte, so no artifact and no lane pin moves. Effect: a new subject arena now needs a gold corpus and a band key, not a re-implementation of ratification — which is what §3 meant by sequencing the bridge ahead of the second subject. [Verification]: tests/test_ratified_ledger_bridge.py 8 passed; core test --suite deductive 252 passed; estimation/license test set 355 passed; committed deduction ledger byte-identical after reseal.
68 lines
2.7 KiB
Python
68 lines
2.7 KiB
Python
"""Serving-side SERVE license for curriculum-grounded answers (ADR-0262).
|
||
|
||
Reads the **ratified, committed** curriculum-serve ledger
|
||
(``chat/data/curriculum_serve_ledger.json``) and exposes, per *(subject ×
|
||
relation family)* band, whether the FULL serving pipeline (curriculum
|
||
compiler → argument reader → ROBDD engine) has earned ``Action.SERVE`` under
|
||
the safe default ceilings (θ_SERVE=0.99). The engine READS this artifact; it
|
||
never writes it — the sealed-practice output of
|
||
``evals.curriculum_serve.practice.runner.seal_ledger`` is the only writer, and
|
||
its ``content_sha256`` is verified on load so a hand-edited ledger is rejected
|
||
rather than silently trusted.
|
||
|
||
The third instance of the seal → ratify → SHA-verify → serve-gate pattern, and
|
||
the one that made the shared bridge worth extracting: this module is now an
|
||
ADAPTER over ``core.ratified_ledger`` (ADR-0263). It names the artifact, keeps
|
||
the memoization, and declares the one thing that genuinely differs — this
|
||
ledger is legitimately ABSENT, because no curriculum band has earned anything
|
||
yet (ADR-0262 §5.1: the binding constraint is ratified curriculum volume). An
|
||
absent ledger reads as an empty table, so every answer is served DISCLOSED.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from functools import lru_cache
|
||
from pathlib import Path
|
||
|
||
from core.ratified_ledger import (
|
||
RatifiedLedgerError as RatifiedCurriculumLedgerError,
|
||
load_sealed_ledger,
|
||
serve_license,
|
||
)
|
||
from core.reliability_gate import Ceilings, ClassTally, LicenseDecision
|
||
|
||
_LEDGER_PATH = Path(__file__).resolve().parent / "data" / "curriculum_serve_ledger.json"
|
||
|
||
|
||
@lru_cache(maxsize=1)
|
||
def load_ratified_ledger() -> dict[str, ClassTally]:
|
||
"""Load + verify the ratified curriculum-serve ledger → per-band tallies.
|
||
|
||
An ABSENT ledger is not an error here: no curriculum band has earned
|
||
anything yet, and the honest reading of "no file" is "no committed
|
||
evidence", which the gate turns into a disclosed answer rather than a
|
||
withheld one.
|
||
"""
|
||
return load_sealed_ledger(_LEDGER_PATH, missing_ok=True)
|
||
|
||
|
||
def curriculum_serve_license(
|
||
band: str,
|
||
*,
|
||
ledger: dict[str, ClassTally] | None = None,
|
||
ceilings: Ceilings | None = None,
|
||
) -> LicenseDecision | None:
|
||
"""The ``Action.SERVE`` license for a curriculum band, or ``None``.
|
||
|
||
``None`` means the band has no committed evidence → never licensed; the
|
||
caller serves a disclosed (hedged) surface, the safe default.
|
||
"""
|
||
ledger = ledger if ledger is not None else load_ratified_ledger()
|
||
return serve_license(band, ledger, ceilings=ceilings)
|
||
|
||
|
||
__all__ = [
|
||
"RatifiedCurriculumLedgerError",
|
||
"curriculum_serve_license",
|
||
"load_ratified_ledger",
|
||
]
|