ADR-0175 Phase 1 — standalone, deterministic, zero serving change. Nothing in
the serving/eval path imports it.
core/reliability_gate/:
- floor.py: conservative_floor(s,k) — pinned one-sided Wilson lower bound over
COMMITTED trials. z=2.576, N_MIN=10; range [0,1) (never exactly 1.0); float64
rounded half-to-even to 1e-9 for cross-backend replay. Perfect record reduces
to k/(k+z²) (earned by volume).
- ledger.py: ClassTally — immutable per-class counts; reliability = commitment
precision (refusals excluded so coverage never penalizes reliability);
t2_precision over the anchor set; coverage tracked separately.
- ceilings.py: Action{PRACTICE,PROPOSE,SERVE} + Ceilings — human-set θ
(practice=0, propose=.85, serve=.99). Frozen; with_override returns a NEW
instance (no in-place self-authorization).
- gate.py: license_for() — deterministic gate, measured/required≥1 (≡ measured≥
required; required=0 ⟹ always). Pure; never mutates/emits ceilings.
34 tests, each ADR invariant exercised by a test that fails under its violation:
#3 determinism/replay (idempotent, pre-rounded, deterministic decisions),
#4 no self-authorization (frozen ceilings; gate never emits/mutates them),
#1 proxy (zero serving coupling). Plus the §4a worked examples (38 clean
commitments clear propose; one wrong in 40 drops below; serve needs ~657).
Verified: 34/34 pass; architectural invariants 40/40; smoke 67/67; ruff clean;
no serving/eval import of the package.
66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
"""ADR-0175 §3 — human-set required-reliability ceilings (θ).
|
|
|
|
``θ`` is the per-class, per-action reliability an action *demands* before it is
|
|
licensed. These are the **human autonomy dial**, distinct from the global
|
|
estimator skepticism :data:`core.reliability_gate.floor.WILSON_Z`.
|
|
|
|
Invariant #4 — the engine never raises its own ceiling. Enforced structurally:
|
|
:class:`Ceilings` is frozen (no in-place mutation), and "raising a ceiling" via
|
|
:meth:`with_override` returns a NEW instance — an explicit reconstruction that
|
|
models a human editing config, never engine self-authorization.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
from typing import Final, Mapping
|
|
|
|
|
|
class Action(Enum):
|
|
"""The blast-radius of what a passed gate licenses (ADR-0175 §3)."""
|
|
|
|
PRACTICE = "practice" # sealed; θ = 0 -> always attempt
|
|
PROPOSE = "propose" # emit a ratifiable proposal
|
|
SERVE = "serve" # touch a served answer
|
|
|
|
|
|
# Global default ceilings. PRACTICE = 0.0 (sealed practice always attempts).
|
|
_DEFAULTS: Final[Mapping[Action, float]] = {
|
|
Action.PRACTICE: 0.0,
|
|
Action.PROPOSE: 0.85,
|
|
Action.SERVE: 0.99,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class Ceilings:
|
|
"""Immutable θ table: global defaults + explicit per-(class, action) overrides."""
|
|
|
|
overrides: tuple[tuple[str, Action, float], ...] = ()
|
|
|
|
def required(self, class_name: str, action: Action) -> float:
|
|
"""θ for this class+action — an override if present, else the global default."""
|
|
for cls, act, theta in self.overrides:
|
|
if cls == class_name and act == action:
|
|
return theta
|
|
return _DEFAULTS[action]
|
|
|
|
def with_override(self, class_name: str, action: Action, theta: float) -> "Ceilings":
|
|
"""Return a NEW Ceilings with this ceiling set (immutable; not in-place).
|
|
|
|
θ must be in ``[0.0, 1.0)`` — a ceiling of 1.0 is unreachable by the
|
|
floor (no finite record proves perfection), so it is rejected as a
|
|
configuration error rather than silently making an action impossible.
|
|
"""
|
|
if not (0.0 <= theta < 1.0):
|
|
raise ValueError("θ must be in [0.0, 1.0)")
|
|
kept = tuple(
|
|
o for o in self.overrides if not (o[0] == class_name and o[1] == action)
|
|
)
|
|
return Ceilings(kept + ((class_name, action, theta),))
|
|
|
|
@classmethod
|
|
def default(cls) -> "Ceilings":
|
|
"""The global-default ceilings with no per-class overrides."""
|
|
return cls()
|