feat(adr-0244): Phase 4 — governed f64→f32 serving-boundary cast (§2.5 / 0245 §2.2)
The single explicit, fail-closed f64→f32 down-cast at the certified lifecycle egress. serving_cast(psi_steady, certificate, verdict) -> ServingState in core/physics/cognitive_lifecycle.py: - Casts ONLY a state that validates as a finite 32-vector, matches its certificate psi_digest, and was verdict.admitted — an uncertified, refused, or digest-mismatched state is never served. - Precision-checks the f32 result (cast_error = max|f64-f32|, unit norm) and fails closed on an f32 precision cliff (f32_precision_insufficient) rather than serving a silently-degraded state. - Keeps f64 as the source of truth: psi_steady and the psi_digest content-address chain are untouched; ServingState carries provenance back (source_psi_digest, certificate_id, measured cast_error) for audit. f64 stays inside relaxation/eigendecomp — this is the one place f32 appears (ADR-0245 §2.2 mechanical sympathy). Satisfies both ADR-0244 §2.5 and ADR-0245 §2.2 (one contract, two ADRs). Measured on a real certified outcome: cast_error ~1.2e-8, unit_norm_f32 ~0.99999998. Off-serving (A-04 guard: chat.runtime never imports it). ADR-0245 status map + plan doc updated. [Verification]: smoke 176 passed; fast lane 11907 passed / 109 skipped (-n auto, not quarantine/slow); 10 targeted serving-cast tests passed.
This commit is contained in:
parent
33bbfa0b06
commit
918aa843b1
4 changed files with 245 additions and 8 deletions
|
|
@ -892,6 +892,104 @@ def egress_gate(
|
|||
)
|
||||
|
||||
|
||||
# --- Serving-boundary f64 -> f32 cast (ADR-0244 §2.5 / ADR-0245 §2.2) -----------------
|
||||
#
|
||||
# The lifecycle relaxes and certifies entirely in float64 (relaxation,
|
||||
# eigendecomposition, the psi_digest content-address chain — all f64). f32 is a
|
||||
# *serving* representation only: the down-cast happens once, at the certified
|
||||
# egress hand-off, for consumers on the f32 fast path (the Rust f32
|
||||
# geometric_product, SIMD, GPU). This is the single governed cast — explicit,
|
||||
# gated on certification, precision-checked, and auditable — not an implicit
|
||||
# dtype coercion sprinkled through the hot path.
|
||||
_F32_CAST_TOL = 1e-6 # float32 has ~1.19e-7 machine eps; a unit versor's
|
||||
# components are O(1), so a faithful down-cast keeps
|
||||
# max|f64 - f32| ~6e-8 and unit-norm within a few ulp. The
|
||||
# tolerance fails closed on a state whose dynamic range
|
||||
# exceeds what f32 can represent (a genuine precision
|
||||
# cliff) rather than serving a silently-degraded state.
|
||||
|
||||
|
||||
class ServingCastError(CognitiveLifecycleError):
|
||||
"""Refused to serve a state as f32: uncertified, digest-mismatched, or f32
|
||||
precision-insufficient. f64 stays the source of truth; the cast never
|
||||
silently degrades a state."""
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ServingState:
|
||||
"""f32 serving projection of a certified ψ_steady (ADR-0244 §2.5 / ADR-0245 §2.2).
|
||||
|
||||
The f64 state and its ``psi_digest`` remain authoritative; this is the
|
||||
down-cast handed to f32 serving consumers, carrying provenance back to the
|
||||
f64 certificate and the measured round-trip error so the cast is auditable.
|
||||
"""
|
||||
|
||||
psi_f32: np.ndarray
|
||||
source_psi_digest: str
|
||||
certificate_id: str
|
||||
cast_error: float
|
||||
unit_norm_f32: float
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
"source_psi_digest": self.source_psi_digest,
|
||||
"certificate_id": self.certificate_id,
|
||||
"cast_error": float(self.cast_error),
|
||||
"unit_norm_f32": float(self.unit_norm_f32),
|
||||
"dtype": str(self.psi_f32.dtype),
|
||||
}
|
||||
|
||||
|
||||
def serving_cast(
|
||||
psi_steady: np.ndarray,
|
||||
certificate: RelaxationCertificate,
|
||||
verdict: EgressVerdict,
|
||||
*,
|
||||
tol: float = _F32_CAST_TOL,
|
||||
) -> ServingState:
|
||||
"""Governed f64→f32 down-cast at the certified serving boundary.
|
||||
|
||||
Fail-closed. The state is cast **only** if it (a) validates as a finite
|
||||
32-vector, (b) matches its certificate's ``psi_digest`` (the state served is
|
||||
provably the certified one), and (c) was admitted by the egress gate — an
|
||||
uncertified or refused state is never handed to a serving consumer. The f32
|
||||
representation is then precision-checked: if the down-cast perturbs any
|
||||
component or the unit norm beyond ``tol``, the state sits on an f32 precision
|
||||
cliff and the cast fails closed rather than serving a degraded state.
|
||||
|
||||
f64 remains the source of truth: neither ``psi_steady`` nor the certificate /
|
||||
digest chain is mutated. This is the single explicit cast the ADR-0245 §2.2
|
||||
mechanical-sympathy contract permits — f64 everywhere inside, f32 only here.
|
||||
"""
|
||||
arr = _as_psi(psi_steady, "ψ_steady", error=ServingCastError) # f64 validate
|
||||
if _psi_digest(arr) != certificate.psi_digest:
|
||||
raise ServingCastError(
|
||||
"certificate_state_mismatch", certificate_id=certificate.certificate_id
|
||||
)
|
||||
if not verdict.admitted:
|
||||
raise ServingCastError("uncertified_state_not_served", verdict_reason=verdict.reason)
|
||||
|
||||
f32 = np.ascontiguousarray(arr, dtype=np.dtype("<f4"))
|
||||
roundtrip = f32.astype(np.float64)
|
||||
cast_error = float(np.max(np.abs(arr - roundtrip))) if arr.size else 0.0
|
||||
unit_norm_f32 = float(np.linalg.norm(roundtrip))
|
||||
if cast_error > float(tol) or abs(unit_norm_f32 - 1.0) > float(tol) + _EPSILON_DRIFT:
|
||||
raise ServingCastError(
|
||||
"f32_precision_insufficient",
|
||||
cast_error=cast_error,
|
||||
unit_norm_f32=unit_norm_f32,
|
||||
tol=float(tol),
|
||||
)
|
||||
f32.setflags(write=False)
|
||||
return ServingState(
|
||||
psi_f32=f32,
|
||||
source_psi_digest=certificate.psi_digest,
|
||||
certificate_id=certificate.certificate_id,
|
||||
cast_error=cast_error,
|
||||
unit_norm_f32=unit_norm_f32,
|
||||
)
|
||||
|
||||
|
||||
# --- Composed lifecycle ---------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -991,6 +1089,8 @@ __all__ = [
|
|||
"RelaxationNotConverged",
|
||||
"RelaxationNumericalFailure",
|
||||
"RelaxationResult",
|
||||
"ServingCastError",
|
||||
"ServingState",
|
||||
"assignment_component_index",
|
||||
"compile_propositional",
|
||||
"compile_quadratic_well",
|
||||
|
|
@ -998,5 +1098,6 @@ __all__ = [
|
|||
"ingest_context",
|
||||
"propositional_entails",
|
||||
"relax_to_ground",
|
||||
"serving_cast",
|
||||
"uniform_assignment_state",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
> | § | Decision | Status |
|
||||
> |---|---|---|
|
||||
> | 2.1 | PyO3 Rust `geometric_product` f32 fast-path | ✅ **Done** — `algebra/backend.py`, pre-existing before this arc. |
|
||||
> | 2.2 | Gated f64→f32 serving boundary | ❌ **Open** — the one genuinely-unbuilt decision. Identical in substance to ADR-0244 §2.5 (same cast, same boundary); tracked as **one contract, two ADRs** — D4 Phase 4. |
|
||||
> | 2.2 | Gated f64→f32 serving boundary | ✅ **Built (D4 Phase 4)** — `serving_cast(psi_steady, certificate, verdict) → ServingState` in `cognitive_lifecycle.py`. A single explicit, fail-closed down-cast at the certified egress: casts only a certified/admitted/digest-matched state, precision-checks the f32 result (fails closed on a cliff), and keeps f64 as the source of truth (the digest chain is untouched). Same contract as ADR-0244 §2.5. Pinned by `tests/test_adr_0244_serving_cast.py` (10 tests). |
|
||||
> | 2.3 | Semantic rigor in content addressing (full 256-bit digest, no `default=str`, byte-order guard) | ◐ **Hot-path done, residual open** — `cognitive_lifecycle.py` / `biography_wiring.py` / `self_authorship.py` fixed (cohesion-directive D1). Three contemplation-module content-id sites (`core/contemplation/schema.py`, `plan_preflight.py`, `miners/articulation_quality.py`) still truncate to 16 hex chars and/or use `default=str` — D4 Phase 5. |
|
||||
> | 2.4 | `_cached_eigh` memoization (`functools.lru_cache`, keyed on `hamiltonian_id` + `matrix.tobytes()`) | ✅ **Done** — `core/physics/cognitive_lifecycle.py::_cached_eigh` (cohesion-directive D2), exactly as specified including the canonical two-part cache key. |
|
||||
>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ ADR-0244 is the **identity-layer consumer**; ADR-0245 is the **mechanical-sympat
|
|||
| 2.2 | Spectral-leakage **fail-closed** gate + `C_id` + `IdentityGateRefusal` | ❌ unbuilt as gate (call site exists at `chat/runtime.py:2679`, but **advisory** only) |
|
||||
| 2.3 | `Q_top` topological charge | ✅ resolved → **retire from egress** (proven vacuous, `evals/adr_0244_qtop_vacuity`) |
|
||||
| 2.4 | Bracketed-local Fibonacci search + `γ_id` calibration | ◐ search-honesty done (D3); calibration half unbuilt |
|
||||
| 2.5 | Serving-boundary f64→f32 cast contract | ❌ unbuilt (== ADR-0245 §2.2; the one genuinely-absent seam) |
|
||||
| 2.5 | Serving-boundary f64→f32 cast contract | ✅ done (Phase 4 — `serving_cast`→`ServingState`, `cognitive_lifecycle.py`) |
|
||||
| 2.6 | Rust GP fast-path + parity gate | ✅ done (f32 pre-existing + f64 D2, bit-identical) |
|
||||
| 2.7 | Full digests / no `default=str` / byte-order guard | ◐ hot-path done (D1); contemplation content-ids residual |
|
||||
| 2.8 | `eigh` memoization | ✅ done (`_cached_eigh`, D2) |
|
||||
|
|
@ -42,12 +42,12 @@ ADR-0244 is the **identity-layer consumer**; ADR-0245 is the **mechanical-sympat
|
|||
| ADR-0245 § | Mechanism | Status entering D4 |
|
||||
|---|---|---|
|
||||
| 2.1 | PyO3 Rust `geometric_product` f32 fast-path | ✅ done (`algebra/backend.py`) |
|
||||
| 2.2 | Gated f64→f32 serving boundary | ❌ unbuilt (== 0244 §2.5) |
|
||||
| 2.2 | Gated f64→f32 serving boundary | ✅ done (Phase 4 — `serving_cast`, == 0244 §2.5) |
|
||||
| 2.3 | Semantic rigor in content addressing | ◐ hot-path done (D1); residual |
|
||||
| 2.4 | `_cached_eigh` memoization | ✅ done |
|
||||
| 3 | Acceptance gate (parity, ≥10× f32 speedup, 0-LAPACK-on-repeat, collision-resistance) | ◐ parity ✓, 0-LAPACK partial (`test_adr_0244_mechanical_sympathy.py`); f32-speedup + collision proofs **missing** |
|
||||
|
||||
**Net remaining build = ADR-0244 §2.1 + §2.2 (the identity gate rebuild), §2.4 calibration, §2.5/0245§2.2 cast, §2.7 residual, §2.9 wiring, + the ADR-0245 §3 gaps.**
|
||||
**Net remaining build (entering Phase 5) = §2.7 residual (3 contemplation content-id sites), §2.9 allocator wiring, §2.10 audit-confirm, + the ADR-0245 §3 acceptance gaps (f32 ≥10× speedup benchmark + collision-resistance proof).** (§2.1/§2.2 identity gate, §2.4 calibration, §2.5/0245§2.2 cast all landed Phases 1–4.)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -161,8 +161,8 @@ Dependencies: `0 → {1, 4}` · `1 → 2 → 3` · `5 after 0` · `6 last`. Each
|
|||
**Steps:** add the typed cast contract at the egress hand-off; precision-sufficiency + parity test; keep f64 inside relaxation/eigendecomp.
|
||||
**Acceptance:** f32 cast only after certification; parity within documented f32 tolerance; f64 preserved upstream; determinism intact. Satisfies **both** 0244 §2.5 and 0245 §2.2.
|
||||
**Gate:** smoke + fast lane + cast tests.
|
||||
**Status:** ⬜ NOT STARTED (may run parallel to 1–3; sequence after 0)
|
||||
**Resume notes:** —
|
||||
**Status:** ✅ DONE — landed `17ec6eee`.
|
||||
**Resume notes:** Shipped `serving_cast(psi_steady, certificate, verdict, *, tol=1e-6) → ServingState` + `ServingCastError` in `core/physics/cognitive_lifecycle.py` (+ `__all__`), pinned by `tests/test_adr_0244_serving_cast.py` (10 tests). The **single explicit** f64→f32 down-cast at the certified egress hand-off: fail-closed — casts only a state that validates as a finite 32-vector, matches its certificate `psi_digest`, and was `verdict.admitted`; then precision-checks the f32 result (`cast_error = max|f64−f32|`, unit-norm) and fails closed on an f32 cliff (`f32_precision_insufficient`). **f64 stays source of truth** — `psi_steady` + the digest chain are untouched; `ServingState` carries provenance back (`source_psi_digest`, `certificate_id`, measured `cast_error`) for audit. Measured on a real certified outcome: `cast_error ≈ 1.2e-8`, `unit_norm_f32 ≈ 0.99999998` (well within tol). Off-serve (A-04 guard test: `chat.runtime` never imports it); f64 kept inside relaxation/eigendecomp. Independent of 1–3.
|
||||
|
||||
### Phase 5 — §2.7 residual + §2.9 adoption + §2.10 audit + ADR-0245 §3 gate
|
||||
**Objective:** finish semantic-rigor residuals, wire the allocator, close the 0245 acceptance gate.
|
||||
|
|
@ -231,6 +231,7 @@ Forward-looking mechanical-sympathy items from the critique — a separate optim
|
|||
- **2026-07-17** — **Phase 2b landed `c7e2b3b6`.** Runtime wiring: `identity_wave_gate` flag (`core/config.py`), two flag-gated touches in `chat/runtime.py` (`wave_field=final_state.F` at the identity check; post-verdict boundary supplement + geometric refusal fold), wave telemetry in `chat/telemetry.py` (emitted only when `wave_mode_active`). **Integration bug caught + fixed:** the live versor carries boost (e5) components → `F aᵢ F̃` is NOT Euclidean-norm-preserving → un-normalized leakage/self-align ran to 5.16 / −4.75. Fixed with per-axis normalization in `identity_manifold.py` (leakage fraction ∈ [0,1], signed cosine ∈ [−1,1]; Phase-1 unit-rotor results unchanged; boost test added; §4a updated). Gate: 74 targeted + smoke 176 + fast lane **11883 passed, 109 skipped** (8:26) — flag-off byte-identity confirmed. **Open reality for Phase 3:** value axes are placeholders (e1/e2/e3), so whether the geometric gate DISCRIMINATES adversarial vs benign is an empirical question — 2c measures it. Next: 2c (ablation eval).
|
||||
- **2026-07-17** — **Phase 2c landed `c0ff4720` → Phase 2 COMPLETE.** `evals/adr_0244_identity_gate/` (detection-value ablation) + `tests/test_adr_0244_identity_gate_eval.py` (6 tests) + CLI. Measured: the wave gate separates a geometric-attack panel (2 inversions caught by orientation, 4 tilts/boosts caught by subspace leakage) from an aligned in-subspace panel — all attacks flagged, all aligned admitted, `min_attack_signal 0.35 > max_aligned_leakage 0.0`; wave adds detection value 6-vs-0 over the geometry-blind legacy path. Honest caveat baked in: separation is on the *designed* geometric signal; real-encoder separation is empirical (Phase 3). Additive-only (evals/ + test), off-serving (quarantine green). Gate: smoke 176 + fast lane. Next: Phase 3 (γ_id calibration).
|
||||
- **2026-07-17** — **Phase 3 landed `f3702ad4` → calibration built + certified; live flag flip BLOCKED by empirical non-separation.** `evals/adr_0244_gamma_calibration/` + `tests/test_adr_0244_gamma_calibration.py` (9 tests). The bracketed-local Fibonacci search certifies `γ* = 0.2126624458513829` (cert `0079b5f201fbf616…`) separating the geometric attack signal; pinned as `identity._WAVE_LEAKAGE_BOUND` and **decoupled the wave path from `alignment_threshold`**. **Then measured the crux the whole arc deferred:** real benign live turns do NOT preserve `span(e1,e2,e3)` — leakage 0.14–0.81 (mean 0.55), self-align to −0.52, **12/13 benign false-refused at γ***, best-achievable balanced error **0.346**. So the calibration certifies `flag_flip_authorized=False`; **`identity_wave_gate` stays OFF**. Root cause: the shipped value axes are *nominal basis vectors, not dynamically-preserved eigenmodes* — no dynamical anchoring in the current field evolution; the fix is the **ADR-0246 induced-action programme** (brief already merged). The wave gate is validated, correctly-off scaffolding. A slow drift-guard test canaries any future change that starts preserving identity. Gate: smoke 176 + fast lane + 59 targeted (incl. wave/ablation/runtime unchanged). Next: Phase 4 (§2.5 cast) — independent of 1–3.
|
||||
- **2026-07-17** — **Phase 4 landed `17ec6eee` → §2.5 / 0245 §2.2 serving cast COMPLETE.** `serving_cast(psi_steady, certificate, verdict) → ServingState` + `ServingCastError` in `core/physics/cognitive_lifecycle.py`; `tests/test_adr_0244_serving_cast.py` (10 tests). The single explicit, fail-closed f64→f32 down-cast at the certified egress: casts only a validated / digest-matched / admitted state; precision-checks the f32 result and fails closed on a cliff (`f32_precision_insufficient`); keeps f64 as source of truth (digest chain untouched) and carries audit provenance. Measured `cast_error ≈ 1.2e-8`. Off-serve (A-04 guard green). Gate: smoke 176 + fast lane + 10 targeted. Next: Phase 5 (§2.7 residual + §2.9 allocator + §2.10 audit + 0245 §3 gate).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -242,10 +243,10 @@ Forward-looking mechanical-sympathy items from the critique — a separate optim
|
|||
| 1 | §2.1 identity manifold primitive (operator-preservation) | ✅ DONE | `3c3d2c29` |
|
||||
| 2 | §2.2 fail-closed gate + boundary_ids + C_id + telemetry + eval | ✅ DONE | `1c7ea26e`+`c7e2b3b6`+`c0ff4720` |
|
||||
| 3 | §2.4 γ_id calibration (certified; **live flip BLOCKED — flag stays OFF**) | ✅ DONE | `f3702ad4` |
|
||||
| 4 | §2.5 / 0245 §2.2 serving-boundary cast | ⬜ NOT STARTED | — |
|
||||
| 4 | §2.5 / 0245 §2.2 serving-boundary cast | ✅ DONE | `17ec6eee` |
|
||||
| 5 | §2.7 residual + §2.9 wiring + §2.10 audit + 0245 §3 gate | ⬜ NOT STARTED | — |
|
||||
| 6 | Close-out (2 acceptance packets + 2 ratified flips) | ⬜ NOT STARTED | — |
|
||||
|
||||
**▶ NEXT: Phase 4 — §2.5 / ADR-0245 §2.2 serving-boundary f64→f32 cast** (lifecycle-internal, `core/physics/cognitive_lifecycle.py`; independent of 1–3, depends only on Phase 0). Then Phase 5 (residuals + allocator + 0245 §3 gate), then Phase 6 (close-out).
|
||||
**▶ NEXT: Phase 5 — §2.7 residual (3 contemplation content-id sites) + §2.9 allocator wiring + §2.10 audit-confirm + ADR-0245 §3 acceptance gate** (f32 ≥10× speedup benchmark + `_content_id` collision-resistance proof). Then Phase 6 (close-out: 2 acceptance packets + user-ratified status flips + cleanup).
|
||||
|
||||
**Phase 3 headline for resumers:** the γ_id calibration machinery is built + certified, but the empirical finding is that **the live serving flag cannot honestly be flipped on** — real benign traffic doesn't preserve the nominal identity subspace (best balanced error 0.346), so the gate would mass-refuse. `identity_wave_gate` stays OFF; the live gate awaits the ADR-0246 induced-action work. This is a **true architectural-gap discovery**, faithfully honoring the plan's conditional ("flip *once evidenced*"), not a deviation.
|
||||
|
|
|
|||
135
tests/test_adr_0244_serving_cast.py
Normal file
135
tests/test_adr_0244_serving_cast.py
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
"""ADR-0244 §2.5 / ADR-0245 §2.2 — governed f64→f32 serving-boundary cast.
|
||||
|
||||
Pins the single explicit down-cast at the certified lifecycle egress: it casts
|
||||
only a certified, admitted, digest-matched state; keeps f64 as the source of
|
||||
truth (the digest chain is untouched); is precision-checked (fails closed on an
|
||||
f32 cliff) and deterministic.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS
|
||||
from core.physics.cognitive_lifecycle import (
|
||||
RelaxationResult,
|
||||
ServingCastError,
|
||||
ServingState,
|
||||
compile_quadratic_well,
|
||||
egress_gate,
|
||||
relax_to_ground,
|
||||
serving_cast,
|
||||
)
|
||||
|
||||
|
||||
def _unit(v: np.ndarray) -> np.ndarray:
|
||||
return v / np.linalg.norm(v)
|
||||
|
||||
|
||||
def _onehot(i: int) -> np.ndarray:
|
||||
v = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
v[i] = 1.0
|
||||
return v
|
||||
|
||||
|
||||
def _certified_outcome():
|
||||
target = _unit(_onehot(1) + _onehot(6))
|
||||
ham = compile_quadratic_well(target, curvature=1.0)
|
||||
result = relax_to_ground(_unit(_onehot(1) + 0.3 * _onehot(6)), ham)
|
||||
verdict = egress_gate(result.psi_steady, result.certificate)
|
||||
assert verdict.admitted is True
|
||||
return result, verdict
|
||||
|
||||
|
||||
def test_cast_of_certified_state_is_f32_and_within_tolerance():
|
||||
result, verdict = _certified_outcome()
|
||||
state = serving_cast(result.psi_steady, result.certificate, verdict)
|
||||
assert isinstance(state, ServingState)
|
||||
assert state.psi_f32.dtype == np.dtype("<f4")
|
||||
assert state.psi_f32.shape == (N_COMPONENTS,)
|
||||
assert state.cast_error < 1e-6 # documented f32 parity tolerance
|
||||
assert abs(state.unit_norm_f32 - 1.0) < 1e-6
|
||||
# provenance links back to the f64 certificate
|
||||
assert state.source_psi_digest == result.certificate.psi_digest
|
||||
assert state.certificate_id == result.certificate.certificate_id
|
||||
|
||||
|
||||
def test_f64_remains_the_source_of_truth():
|
||||
result, verdict = _certified_outcome()
|
||||
digest_before = result.certificate.psi_digest
|
||||
serving_cast(result.psi_steady, result.certificate, verdict)
|
||||
# neither the state nor its certificate/digest is mutated by the cast
|
||||
assert result.psi_steady.dtype == np.float64
|
||||
assert result.certificate.psi_digest == digest_before
|
||||
|
||||
|
||||
def test_cast_is_deterministic():
|
||||
result, verdict = _certified_outcome()
|
||||
a = serving_cast(result.psi_steady, result.certificate, verdict)
|
||||
b = serving_cast(result.psi_steady, result.certificate, verdict)
|
||||
assert np.array_equal(a.psi_f32, b.psi_f32)
|
||||
assert a.cast_error == b.cast_error and a.unit_norm_f32 == b.unit_norm_f32
|
||||
|
||||
|
||||
def test_uncertified_verdict_is_never_served():
|
||||
result, _ = _certified_outcome()
|
||||
|
||||
class _Refused:
|
||||
admitted = False
|
||||
reason = "relaxation_not_certified"
|
||||
|
||||
with pytest.raises(ServingCastError, match="uncertified_state_not_served"):
|
||||
serving_cast(result.psi_steady, result.certificate, _Refused())
|
||||
|
||||
|
||||
def test_digest_mismatch_refuses():
|
||||
result, verdict = _certified_outcome()
|
||||
ham = compile_quadratic_well(_unit(_onehot(2) + _onehot(6)), curvature=1.0)
|
||||
other = relax_to_ground(_unit(_onehot(2) + 0.2 * _onehot(6)), ham)
|
||||
# a state that is not the one the certificate addresses must not be served
|
||||
with pytest.raises(ServingCastError, match="certificate_state_mismatch"):
|
||||
serving_cast(other.psi_steady, result.certificate, verdict)
|
||||
|
||||
|
||||
def test_malformed_state_refuses_before_casting():
|
||||
result, verdict = _certified_outcome()
|
||||
with pytest.raises(ServingCastError, match="bad_shape"):
|
||||
serving_cast(np.zeros(16, dtype=np.float64), result.certificate, verdict)
|
||||
bad = np.array(result.psi_steady, dtype=np.float64, copy=True)
|
||||
bad[0] = np.nan
|
||||
with pytest.raises(ServingCastError, match="non_finite"):
|
||||
serving_cast(bad, result.certificate, verdict)
|
||||
|
||||
|
||||
def test_precision_sufficiency_guard_is_enforced():
|
||||
# For a unit versor f32 is sufficient, so the guard passes in normal use.
|
||||
# Tightening tol below f32's own rounding proves the guard is live (fails
|
||||
# closed on a precision cliff) rather than decorative.
|
||||
result, verdict = _certified_outcome()
|
||||
with pytest.raises(ServingCastError, match="f32_precision_insufficient"):
|
||||
serving_cast(result.psi_steady, result.certificate, verdict, tol=0.0)
|
||||
|
||||
|
||||
def test_serving_state_as_dict_is_audit_ready():
|
||||
result, verdict = _certified_outcome()
|
||||
d = serving_cast(result.psi_steady, result.certificate, verdict).as_dict()
|
||||
assert d["certificate_id"] == result.certificate.certificate_id
|
||||
assert d["source_psi_digest"] == result.certificate.psi_digest
|
||||
assert d["dtype"] == "float32"
|
||||
assert d["cast_error"] < 1e-6
|
||||
|
||||
|
||||
def test_cast_never_imported_into_serve_hot_path():
|
||||
# A-04: cognitive_lifecycle stays off the chat serve path.
|
||||
import inspect
|
||||
|
||||
import chat.runtime
|
||||
|
||||
assert "serving_cast" not in inspect.getsource(chat.runtime)
|
||||
|
||||
|
||||
def test_relaxation_result_type_is_unchanged():
|
||||
result, _ = _certified_outcome()
|
||||
assert isinstance(result, RelaxationResult)
|
||||
assert result.psi_steady.flags.writeable is False
|
||||
Loading…
Reference in a new issue