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.
60 lines
2.7 KiB
Python
60 lines
2.7 KiB
Python
"""E — the serving-side SERVE license for the converse-guess.
|
|
|
|
Reads the **ratified, committed** estimation ledger (``data/estimation_ledger.json``)
|
|
and exposes, per predicate, whether the converse-guess has earned ``Action.SERVE``
|
|
under the safe default ceilings (θ_SERVE=0.99). The engine READS this artifact; it
|
|
never writes it. The artifact is the sealed-practice output of
|
|
``evals.determination_estimation.build_ledger`` — its ``content_sha256`` is verified on
|
|
load, so a hand-edited (un-ratified) ledger is rejected rather than silently trusted.
|
|
|
|
Determinism: the ledger is immutable ratified data, parsed once and cached; the gate
|
|
is pure. No engine self-authorization — ceilings stay at the safe defaults (raising
|
|
one's own bar is structurally impossible, ADR-0175 invariant #4).
|
|
|
|
The load/verify/gate mechanics live in ``core.ratified_ledger`` (ADR-0263), the
|
|
bridge extracted from this module and its two successors; this is the estimation
|
|
ADAPTER over it, preserving its own public API (including the predicate →
|
|
converse-class naming, which is the one thing genuinely local to estimation).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from functools import lru_cache
|
|
from pathlib import Path
|
|
|
|
from core.ratified_ledger import RatifiedLedgerError, load_sealed_ledger
|
|
from core.ratified_ledger import serve_license as _serve_license
|
|
from core.reliability_gate import Ceilings, ClassTally, LicenseDecision
|
|
from generate.determine.estimate import converse_class_name
|
|
|
|
_LEDGER_PATH = Path(__file__).resolve().parent / "data" / "estimation_ledger.json"
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def load_ratified_ledger() -> dict[str, ClassTally]:
|
|
"""Load + verify the ratified estimation ledger → per-class ``ClassTally``.
|
|
|
|
Raises :class:`RatifiedLedgerError` if the file is absent/malformed or its
|
|
recomputed ``content_sha256`` does not match the committed one (tamper-evidence:
|
|
only the sealed-practice output is trusted, never a hand-edited ledger).
|
|
"""
|
|
return load_sealed_ledger(_LEDGER_PATH)
|
|
|
|
|
|
def serve_license(
|
|
predicate: str,
|
|
*,
|
|
ledger: dict[str, ClassTally] | None = None,
|
|
ceilings: Ceilings | None = None,
|
|
) -> LicenseDecision | None:
|
|
"""The ``Action.SERVE`` license for ``predicate``'s converse-guess, or ``None``.
|
|
|
|
``None`` means the predicate-class is absent from the ratified ledger (no committed
|
|
evidence → never licensed; the caller refuses, the safe default). Otherwise the
|
|
deterministic ``license_for`` verdict under the safe default ceilings.
|
|
"""
|
|
ledger = ledger if ledger is not None else load_ratified_ledger()
|
|
return _serve_license(converse_class_name(predicate), ledger, ceilings=ceilings)
|
|
|
|
|
|
__all__ = ["RatifiedLedgerError", "load_ratified_ledger", "serve_license"]
|