Merge ADR-0246 Ring-1 implementation into main — flag-off, ADR Proposed

Merges the complete five-unit ADR-0246 stack (authorized by Shay 2026-07-17:
"make sure all CI checks pass green then commit and push to remote main, no PR
necessary"), executed Fable 5 (scaffold + completion) -> Opus 4.8 (adversarial
audit PASS + hardening) -> Sonnet 5/Fable 5 (telemetry + serve integration +
§11 feasibility):

  4941cf18 §3 primitives         A(F), d_orth, d_stab vs locked H_id={I}, typed channels
  6efe4ad8 §3.4/3.5 path ledger  lawful-only composition + hard breaks
  ed54ddda §6.1/6.2 eval suite   every preflight case pinned; malformed-F fail-closed
  47e7eb4e Opus audit+hardening  bit-exact math verify; §3.7 admit surface + serve
                                 wiring (default-off identity_action_surface);
                                 §6.3 discrimination report (honest numbers)
  (tip)    completion            §4.1/§4.2 telemetry records; §3.4-step-2 admitted
                                 gate; observe-only path serve integration; §11
                                 grounding-feasibility (honest NULL, method
                                 validated); ADR body Proposed + packet §8 PENDING

GOVERNANCE SCOPE OF THIS MERGE: code lands flag-gated DEFAULT-OFF with flag-off
byte-identity proven (all D4 gate surfaces green unchanged; smoke green at every
unit). The ADR document is **Proposed** — this merge is NOT a status flip and
NOT live activation. identity_wave_gate AND identity_action_surface remain
default-off / live activation NOT authorized (D4 ratified limitation + §6.3
evidence: benign/adversarial AUC 0.375, benign false-refusal 1.00; §11: no
held-out-stable generator subspace, cross-cohort cosine 0.52 = 87th pctile of
chance). Ratification of the ADR (and its requested rulings: F1 composition
semantics, ||.||_G convention, hard-break turn ownership, refusal_reason
widening) is Shay's, via the acceptance packet.

[Verification]: smoke 176 passed (final tree); full targeted battery 228 passed
(9 ADR-0246 suites + D4 identity + gamma calibration + identity_gate +
telemetry); §6.1/6.2 eval 14/14; artifacts + run logs under docs/audit/.
This commit is contained in:
Shay 2026-07-17 23:37:26 -07:00
commit f49b391d37
31 changed files with 4621 additions and 76 deletions

View file

@ -80,6 +80,8 @@ from core.physics.identity import (
IdentityScore,
TurnEvent,
)
from core.physics.identity import advance_session_identity_path
from core.physics.identity_action import AdmissionPolicy
from packs.ethics.check import EthicsCheck, EthicsContext
from packs.ethics.loader import (
DEFAULT_ETHICS_PACK as _DEFAULT_ETHICS_PACK,
@ -705,6 +707,11 @@ class ChatRuntime:
self.identity_manifold,
)
self._last_refusal_was_typed: bool = True
# ADR-0246 §3.4/§3.5 — lawful-only session identity-path ledger
# (observe-only; advanced per-turn only when identity_action_surface +
# identity_wave_gate are both on). Instance lifetime IS the §3.5
# session boundary: a fresh runtime starts from None → hard break.
self._identity_path_ledger = None
self.turn_log: List[TurnEvent] = []
from chat.thread_context import ThreadContext
self.thread_context = ThreadContext()
@ -2683,13 +2690,38 @@ class ChatRuntime:
# path (byte-identical). The boundary_ids intersection needs the
# safety/ethics verdicts, which are computed below — it is supplemented
# after those run.
# ADR-0246 §3.7 — fuller admit surface, flag-gated + default-off. The
# policy is placeholder/uncalibrated (calibrated=False); it only acts
# when identity_wave_gate is also on (a wave_field exists).
_admission_policy = (
AdmissionPolicy.placeholder_default()
if self.config.identity_action_surface
else None
)
identity_score = self._identity_check.check(
reasoning_trajectory,
self.identity_manifold,
wave_field=(
result.final_state.F if self.config.identity_wave_gate else None
),
admission_policy=_admission_policy,
turn_id=self._context.turn,
pack_id=self.identity_pack_id,
)
# ADR-0246 §3.4/§3.5 — lawful-only session identity path (OBSERVE-ONLY,
# same flags). Refused turns break; scope changes hard-break; the
# ledger's session_admit is telemetry, never an egress decision
# (epsilon_session is an uncertified placeholder; live activation
# remains unauthorized).
identity_path_ledger = None
if _admission_policy is not None and identity_score.wave_mode_active:
self._identity_path_ledger, _path_turn = advance_session_identity_path(
self._identity_path_ledger,
self.identity_manifold,
result.final_state.F,
_admission_policy,
)
identity_path_ledger = self._identity_path_ledger
flagged = identity_score.flagged
cycle_cost = CycleCost(
cycle_index=self._context.turn,
@ -3013,6 +3045,7 @@ class ChatRuntime:
normative_clearance=main_normative_clearance,
normative_detail=main_normative_detail,
reach_level=main_reach_level,
identity_path=identity_path_ledger,
)
self.turn_log.append(turn_event)
self._emit_turn_event(turn_event)

View file

@ -151,6 +151,33 @@ def serialize_turn_event(
out["identity_boundary_violations"] = sorted(
getattr(identity_score, "boundary_violations", ()) or ()
)
# ADR-0246 §3.7/§4.1 — induced-action admit-surface telemetry.
# Emitted only when the surface ran this turn (behind the separate
# default-off ``identity_action_surface`` flag); absent otherwise, so
# the D4-only wire format above stays byte-identical.
if getattr(identity_score, "action_surface_active", False):
out["identity_d_orth"] = float(getattr(identity_score, "d_orth", 0.0))
out["identity_d_stab"] = float(getattr(identity_score, "d_stab", 0.0))
record = getattr(identity_score, "action_record", None)
if record is not None:
out["identity_action_admitted"] = bool(record.admitted)
out["identity_action_lawful"] = str(record.lawful_action)
out["identity_action_refusal_reason"] = record.refusal_reason
out["identity_action_record_digest"] = record.record_digest()
# ADR-0246 §3.4/§3.5/§4.2 — session identity-path ledger telemetry
# (observe-only). Emitted only when the path ran this turn; absent
# otherwise, so the flag-off wire format stays byte-identical.
ledger = getattr(event, "identity_path", None)
if ledger is not None:
out["identity_path_chain_id"] = str(getattr(ledger, "chain_id", ""))
out["identity_path_d_stab"] = float(getattr(ledger, "d_stab_path", 0.0))
out["identity_path_composed_turns"] = int(
getattr(ledger, "composed_turn_count", 0)
)
out["identity_path_breaks"] = int(getattr(ledger, "break_count", 0))
out["identity_path_session_admit"] = bool(
getattr(ledger, "session_admit", True)
)
if include_content:
out["input_tokens"] = list(getattr(event, "input_tokens", ()))
out["surface"] = str(getattr(event, "surface", ""))

View file

@ -303,6 +303,15 @@ class RuntimeConfig:
# (legacy scalar-L2 identity score, no geometric refusal).
identity_wave_gate: bool = False
# ADR-0246 §3.7 — the fuller induced-action admit surface (d_orth, d_stab vs
# locked H_id={I}, typed residual channels) layered on the wave gate. OFF by
# default and NOT authorized for live activation: its thresholds are
# UNCERTIFIED placeholders (only γ_id is certified) and the §6.3 discrimination
# report shows it refuses benign and adversarial traffic alike on the declared
# placeholder frame. Requires identity_wave_gate to also be on (it acts on the
# live versor F). Flag-off is byte-identical to the D4 wave path.
identity_action_surface: bool = False
# Step B (inline realization) — when on, each turn ACCRUES knowledge into the
# held self: a comprehensible declarative turn is realized into the session vault
# (SPECULATIVE, as-told), and a comprehensible question turn is determined over

View file

@ -13,15 +13,28 @@ CORE's identity is not a description of CORE. It is CORE, expressed geometricall
from __future__ import annotations
import functools
import hashlib
import json
import math
import warnings
from dataclasses import dataclass
from typing import Dict, FrozenSet, List, Optional, Tuple
from typing import Any, Dict, FrozenSet, List, Optional, Tuple
import numpy as np
from algebra.cl41 import N_COMPONENTS
from core.physics.identity_manifold import IdentityManifoldGeometry
from core.physics.identity_action import (
AdmissionPolicy,
IdentityActionRecord,
IdentityChainScope,
IdentityPathLedger,
PathBudget,
PLACEHOLDER_EPSILON_SESSION,
advance_identity_path,
build_identity_action_record,
evaluate_admission,
)
# ADR-0244 §2.2 / §4a / §2.4 — wave-gate thresholds.
#
@ -84,6 +97,94 @@ def _geometry_for_manifold(manifold: "IdentityManifold") -> IdentityManifoldGeom
return _geometry_for_axis_directions(directions)
# ADR-0246 §3.5/§4.1 — version identifiers for the hard-break ledger scope and
# the per-turn IdentityActionRecord. ``geometry_version`` identifies the
# ``IdentityManifoldGeometry`` construction contract (Gram/lift semantics);
# ``gate_version`` identifies the §3.7 admit-surface DECISION LOGIC in
# ``evaluate_admission`` (as opposed to its threshold VALUES, which are
# ``AdmissionPolicy.version_id()``). Bump either only on a genuine contract
# change — these are code-identity tags, not calibration numbers.
GEOMETRY_VERSION: str = "identity_manifold_geometry_v1"
GATE_VERSION: str = "adr_0246_admit_surface_v1"
def manifold_content_digest(manifold: "IdentityManifold") -> str:
"""Full-SHA-256 content digest of the declared value-axis frame.
ADR-0246 §3.5 a new identity-action chain must start whenever the
identity pack content changes. ``IdentityManifold`` carries no digest of
its own (the pack loader doesn't compute one), so this hashes the exact
content that defines the frame: each axis's id/name/direction/weight, the
boundary ids, and the alignment threshold canonical JSON (sorted keys, no
``default=str``), full 64-hex digest (ADR-0245 §2.3, no truncation).
"""
payload = {
"value_axes": [
{
"axis_id": str(getattr(axis, "axis_id", getattr(axis, "name", ""))),
"name": str(getattr(axis, "name", "")),
"direction": [float(x) for x in getattr(axis, "direction", ()) or ()],
"weight": float(getattr(axis, "weight", 1.0)),
}
for axis in manifold.value_axes
],
"boundary_ids": sorted(manifold.boundary_ids),
"alignment_threshold": float(manifold.alignment_threshold),
}
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
# §3.5 session scoping note: the live ledger object is held BY the runtime
# instance, so the session boundary is enforced by object lifetime (a new
# runtime/session starts from ``ledger=None`` → hard break). The constant
# session_id below therefore only needs to be stable WITHIN an instance;
# pack/geometry/policy changes mid-instance still hard-break via the scope
# comparison in ``advance_identity_path``.
_LIVE_SESSION_SCOPE_ID: str = "live_runtime_session"
def advance_session_identity_path(
ledger: "IdentityPathLedger | None",
manifold: "IdentityManifold",
wave_field,
policy: "AdmissionPolicy",
*,
boundary_breach: bool = False,
) -> tuple["IdentityPathLedger", dict]:
"""Advance the live session's lawful-only identity path by one turn
(ADR-0246 §3.4/§3.5 serve integration OBSERVE-ONLY).
Builds the §3.5 chain scope from the manifold's content digest + the
geometry/gate/policy version ids, evaluates the §3.7 admit surface for the
§3.4-step-2 ``admitted`` gate, and folds the turn's induced action into the
ledger (lawful-only composition; refused turns are break markers).
OBSERVE-ONLY: the returned ledger's ``session_admit`` is telemetry, not an
egress decision ``epsilon_session`` is an UNCERTIFIED placeholder and
live activation of any identity gate remains unauthorized (D4 ratification
+ the §6.3 discrimination evidence). No refusal is derived from the path
here; that requires calibrated budgets + explicit human ratification.
"""
geometry = _geometry_for_manifold(manifold)
F = np.asarray(wave_field, dtype=np.float64)
result = evaluate_admission(geometry, F, policy, boundary_breach=boundary_breach)
action = geometry.induced_action(F)
scope = IdentityChainScope(
pack_content_digest=manifold_content_digest(manifold),
geometry_version=GEOMETRY_VERSION,
policy_version=f"{GATE_VERSION}:{policy.version_id()}",
session_id=_LIVE_SESSION_SCOPE_ID,
)
budget = PathBudget(
epsilon_turn=policy.epsilon_turn,
epsilon_session=PLACEHOLDER_EPSILON_SESSION,
)
return advance_identity_path(
ledger, scope, action, geometry.gram, budget, admitted=result.admitted
)
@dataclass(frozen=True)
class ValueAxis:
"""Compatibility value-axis shape for identity-gate tests and fixtures.
@ -123,6 +224,16 @@ class IdentityScore:
# Committed boundary_ids the turn violated (intersection with the manifold's
# boundary set); a non-empty set is a hard identity-boundary breach.
boundary_violations: FrozenSet[str] = frozenset()
# ADR-0246 §3.7 induced-action admit-surface measures. Populated only when the
# ``identity_action_surface`` policy runs (``action_surface_active=True``);
# legacy defaults keep the flag-off wave/legacy IdentityScore byte-identical.
action_surface_active: bool = False
d_orth: float = 0.0
d_stab: float = 0.0
# ADR-0246 §4.1 — the full per-turn IdentityActionRecord (typed residual
# channels, digests, admit verdict). ``None`` unless the §3.7 surface ran
# (``action_surface_active=True``); legacy/flag-off callers are unaffected.
action_record: "IdentityActionRecord | None" = None
@property
def value(self) -> float:
@ -275,6 +386,9 @@ class IdentityCheck:
manifold: IdentityManifold,
trajectory_id: str,
boundary_violations: FrozenSet[str],
admission_policy: "AdmissionPolicy | None" = None,
turn_id: int = 0,
pack_id: str = "",
) -> IdentityScore:
"""Operator-preservation identity score for a live versor (ADR-0244 §2.2/§4a).
@ -282,6 +396,16 @@ class IdentityCheck:
the value subspace via its action on the axes ``F aᵢ F̃`` subspace
leakage (tilt toward alien dimensions) plus signed self-alignment
(in-subspace inversion). See :mod:`core.physics.identity_manifold`.
When ``admission_policy`` is supplied (ADR-0246 §3.7, flag-gated behind
``identity_action_surface``), the fuller induced-action admit surface
(``d_orth``, ``d_stab`` vs locked ``H_id={I}``, typed residual channels)
is additionally applied: a versor failing it folds into ``flagged`` (the
existing ``would_violate`` refusal path abstains admit-or-abstain, no
corrector). When ``None`` (default) the result is byte-identical to the D4
wave path. ``turn_id``/``pack_id`` (ADR-0246 §4.1) are forwarded into the
per-turn ``IdentityActionRecord`` when the surface is active; both default
to empty/zero so omitting them never affects behavior.
"""
F = self._validate_wave_field(wave_field)
geometry = _geometry_for_manifold(manifold)
@ -305,6 +429,42 @@ class IdentityCheck:
or bool(deviations)
or bool(boundary_violations)
)
# ADR-0246 §3.7 (flag-gated). When a policy is supplied, additionally apply
# the induced-action admit surface; a refusal folds into ``flagged`` so the
# existing ``would_violate`` egress abstains (admit-or-abstain, no
# corrector). When absent, the fields keep legacy defaults ⇒ byte-identical.
action_surface_active = False
d_orth = 0.0
d_stab = 0.0
action_record: "IdentityActionRecord | None" = None
if admission_policy is not None:
result = evaluate_admission(
geometry,
F.astype(np.float64),
admission_policy,
boundary_breach=bool(boundary_violations),
)
action_surface_active = True
d_orth = result.d_orth
d_stab = result.d_stab
flagged = flagged or not result.admitted
# ADR-0246 §4.1 per-turn telemetry record. Re-evaluates the (cheap,
# pure) admit surface rather than threading ``result`` through, so
# the already-audited ``evaluate_admission`` call above stays
# untouched — see docs/audit/adr-0246-slice1-opus-audit-and-hardening.md.
action_record = build_identity_action_record(
geometry,
F.astype(np.float64),
admission_policy,
turn_id=turn_id,
trajectory_id=trajectory_id,
pack_id=pack_id,
pack_content_digest=manifold_content_digest(manifold),
geometry_version=GEOMETRY_VERSION,
gate_version=GATE_VERSION,
wave_mode_active=True,
boundary_breach=bool(boundary_violations),
)
return IdentityScore(
score=score,
flagged=flagged,
@ -314,6 +474,10 @@ class IdentityCheck:
leakage_norm=leakage_rms,
min_self_alignment=min_align,
boundary_violations=boundary_violations,
action_surface_active=action_surface_active,
d_orth=d_orth,
d_stab=d_stab,
action_record=action_record,
)
def check(
@ -323,6 +487,9 @@ class IdentityCheck:
*,
wave_field=None,
violated_boundary_ids: FrozenSet[str] = frozenset(),
admission_policy: "AdmissionPolicy | None" = None,
turn_id: int = 0,
pack_id: str = "",
) -> IdentityScore:
"""Check a trajectory against the IdentityManifold (ADR-0010 / ADR-0244).
@ -331,6 +498,12 @@ class IdentityCheck:
gate; otherwise fall back to the legacy scalar-L2 heuristic. A *malformed*
wave field raises (fail-closed) only an ABSENT one falls back.
``admission_policy`` (ADR-0246 §3.7, flag-gated behind
``identity_action_surface``) is forwarded to the wave path only; ``None``
(default) keeps every caller byte-identical to the D4 gate. ``turn_id``/
``pack_id`` (ADR-0246 §4.1) are cosmetic identifiers for the per-turn
record and default to ``0``/``""`` omitting them changes nothing.
``violated_boundary_ids`` (the turn's safety/ethics violated boundaries)
is intersected with the manifold's committed ``boundary_ids``; a non-empty
intersection is a hard identity-boundary breach (governance annotation
@ -353,7 +526,8 @@ class IdentityCheck:
)
if wave_field is not None:
return self._wave_field_score(
wave_field, resolved_manifold, trajectory_id, boundary_violations
wave_field, resolved_manifold, trajectory_id, boundary_violations,
admission_policy=admission_policy, turn_id=turn_id, pack_id=pack_id,
)
confidence = float(getattr(trajectory, "total_coherence_delta", 0.0))
confidence += self._mean_frame_coherence(trajectory)
@ -571,3 +745,9 @@ class TurnEvent:
composer_atom_set_hash: str = ""
graph_atom_set_hash: str = ""
composer_graph_atom_overlap_count: int = 0
# ADR-0246 §3.4/§3.5/§4.2 — the session identity-path ledger snapshot after
# this turn (an ``IdentityPathLedger``), populated only when the
# identity_action_surface path ran. ``None`` (default) on legacy/flag-off
# turns keeps the wire format byte-identical. Typed as ``object`` to
# preserve identity.py's low-coupling value-type role in TurnEvent.
identity_path: object = None

View file

@ -0,0 +1,677 @@
"""core.physics.identity_action — lawful identity action policy (ADR-0246 §3.2§3.3).
Where :mod:`core.physics.identity_manifold` measures *what a versor does* to the
value frame (the induced action ``A(F)``, its orthogonality defect ``d_orth``, and
typed leakage), this module measures *whether that action is lawful* how far the
induced action sits from the explicitly permitted identity actions ``H_id``.
The two diagnostics are deliberately never collapsed (ADR-0246 §3.2):
* ``d_orth`` (in identity_manifold) detects non-isometric / numerically
corrupt action on the subspace. A conditioning check, NOT an authorization.
* ``d_stab`` (here) ``min_{H H_id} A(F) H_G`` detects departure from
the explicitly *permitted* identity action. This is the lawfulness measure.
**Locked stabilizer (ADR-0246 §3.3).** For the default identity pack
H_id = { I }
the singleton containing only the identity matrix in the axis basis. Algebraic
cleanliness identity lawfulness, so ``-I`` (global inversion), axis
permutations, continuous rotations, and arbitrary reweightings are **excluded**.
Under a singleton stabilizer there is no continuous projection that "invents" a
lawful action: ``d_stab`` is a pass/fail distance, and callers must NOT soft-project
``A`` onto ``I`` and then compose the projection as if the turn were lawful.
Enlarging ``H_id`` is a future, explicit, reviewed pack/policy change never an
implicit convenience here.
Pure (numpy + identity_manifold only), deterministic, float64, off-serving. This
module owns both the per-turn stabilizer defect (``d_stab``) and the lawful-only
path ledger (§3.4/§3.5): the identity path composes ONLY the induced actions of
turns certified lawful, refused turns insert break markers (never a soft-projected
``I``), and a scope change forces a hard break onto a new chain.
"""
from __future__ import annotations
import hashlib
import json
from dataclasses import dataclass
from typing import Any, Sequence
import numpy as np
from core.physics.identity_manifold import (
IdentityManifoldGeometry,
orthogonality_defect_of_action,
)
# Below this the axis Gram is treated as the identity matrix and the G-weighted
# norm collapses to the plain Frobenius norm (exact for the default pack).
_IDENTITY_GRAM_TOL: float = 1e-9
@dataclass(frozen=True)
class IdentityStabilizer:
"""The permitted identity actions ``H_id`` in the axis basis.
``members`` are the allowed action matrices. The default (and only ratified)
policy is the singleton ``{ I }`` see module docstring / ADR-0246 §3.3.
Constructing a non-singleton stabilizer is possible for research/analysis but
is NOT a ratified live policy; enlarging ``H_id`` for serving requires an
explicit reviewed change.
"""
members: tuple[np.ndarray, ...]
@classmethod
def singleton(cls, dimension: int) -> "IdentityStabilizer":
"""The locked default ``H_id = { I_dimension }``."""
return cls(members=(np.eye(int(dimension), dtype=np.float64),))
@property
def is_singleton_identity(self) -> bool:
"""True iff this is exactly the locked default ``{ I }``."""
return len(self.members) == 1 and bool(
np.allclose(self.members[0], np.eye(self.members[0].shape[0]))
)
def _matrix_sqrt_spd(gram: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
"""``(G^{1/2}, G^{-1/2})`` for a symmetric positive-definite Gram via eigh."""
eigvals, eigvecs = np.linalg.eigh(gram)
if float(eigvals.min()) <= 0.0:
raise ValueError("stabilizer defect requires a positive-definite Gram")
root = eigvecs @ np.diag(np.sqrt(eigvals)) @ eigvecs.T
inv_root = eigvecs @ np.diag(1.0 / np.sqrt(eigvals)) @ eigvecs.T
return root, inv_root
def _g_weighted_frobenius(matrix: np.ndarray, gram: np.ndarray) -> float:
"""Metric-consistent matrix norm ``‖M‖_G`` (ADR-0246 §3.2).
Measured in a ``G``-orthonormal frame: ``M_G = G^{1/2} M G^{-1/2}_F``.
Reduces exactly to the plain Frobenius norm when ``G = I`` (the default pack),
and is invariant to the metric-preserving change of axis coordinates. The
convention is fixed here for the value packs in use; a broader-pack review may
revisit it (ADR-0246 §3.2 leaves general-pack ``·_G`` to ADR-0246 proper).
"""
if np.allclose(gram, np.eye(gram.shape[0]), atol=_IDENTITY_GRAM_TOL):
return float(np.linalg.norm(matrix, ord="fro"))
root, inv_root = _matrix_sqrt_spd(gram)
return float(np.linalg.norm(root @ matrix @ inv_root, ord="fro"))
def stabilizer_defect(
action: np.ndarray,
gram: np.ndarray,
stabilizer: IdentityStabilizer,
) -> float:
"""``d_stab = min_{H ∈ H_id} ‖A H‖_G`` (ADR-0246 §3.2§3.3).
The lawfulness distance of an induced action ``A`` from the permitted identity
actions. Zero iff ``A`` equals a permitted action. Under the locked singleton
``H_id = { I }`` this is exactly ``A I_G`` a pass/fail distance, not a
corrector.
"""
action = np.asarray(action, dtype=np.float64)
gram = np.asarray(gram, dtype=np.float64)
if not stabilizer.members:
raise ValueError("stabilizer must contain at least one permitted action")
return min(
_g_weighted_frobenius(action - np.asarray(H, dtype=np.float64), gram)
for H in stabilizer.members
)
def stabilizer_defect_for_versor(
geometry: IdentityManifoldGeometry,
versor: np.ndarray,
stabilizer: IdentityStabilizer | None = None,
) -> float:
"""``d_stab`` for a versor's induced action against ``geometry``.
Defaults to the locked singleton ``H_id = { I }`` sized to the value frame.
"""
action = geometry.induced_action(versor)
if stabilizer is None:
stabilizer = IdentityStabilizer.singleton(action.shape[0])
return stabilizer_defect(action, geometry.gram, stabilizer)
# -- ADR-0246 §3.4/§3.5 lawful-only identity-path ledger -----------------------
@dataclass(frozen=True)
class PathBudget:
"""Two-level lawfulness budget (ADR-0246 §3.4).
``epsilon_turn`` bounds a single turn's ``d_stab`` (a large one-turn departure
refuses immediately); ``epsilon_session`` bounds the composed lawful path's
``d_stab`` (slow accumulation of individually-lawful turns eventually refuses).
"""
epsilon_turn: float
epsilon_session: float
@dataclass(frozen=True)
class IdentityChainScope:
"""The scope that keys an identity-action chain (ADR-0246 §3.5).
Any change to these forces a **hard break** a new chain that does NOT
continue the previous composed path. The frame, its geometry, the lawfulness
policy, the session, and (when explicit) the biography epoch each redefine
what "the path" means, so a path may only compose within a single scope.
"""
pack_content_digest: str
geometry_version: str
policy_version: str
session_id: str
biography_epoch: str | None = None
def as_dict(self) -> dict[str, Any]:
return {
"pack_content_digest": self.pack_content_digest,
"geometry_version": self.geometry_version,
"policy_version": self.policy_version,
"session_id": self.session_id,
"biography_epoch": self.biography_epoch,
}
def _chain_id(scope: IdentityChainScope, chain_index: int) -> str:
"""Deterministic full-SHA-256 chain id (ADR-0245 §2.3 — no truncation).
Includes ``chain_index`` so a scope that recurs later in a session (e.g. a
pack A B A cycle) still yields a distinct chain id.
"""
payload = json.dumps(
{**scope.as_dict(), "chain_index": int(chain_index)},
sort_keys=True,
separators=(",", ":"),
)
return hashlib.sha256(payload.encode("utf-8")).hexdigest()
@dataclass(frozen=True)
class IdentityPathLedger:
"""Immutable snapshot of the lawful-only identity path (ADR-0246 §4.2).
``a_path_lawful`` is the time-forward product of the induced actions of the
turns certified lawful within this chain (``I`` for an empty chain). Refused
turns are counted in ``break_count`` and excluded from the product never
composed as ``I`` (that would be the soft-projection §3.4 forbids).
"""
chain_id: str
scope: IdentityChainScope
chain_index: int
dimension: int
a_path_lawful: np.ndarray
d_stab_path: float
composed_turn_count: int
break_count: int
session_admit: bool
def ledger_digest(self) -> str:
"""Full-SHA-256 content id over the path state (LE f64 byte-order)."""
digest = hashlib.sha256()
digest.update(self.chain_id.encode("utf-8"))
digest.update(
np.ascontiguousarray(self.a_path_lawful, dtype=np.dtype("<f8")).tobytes()
)
digest.update(
json.dumps(
[self.chain_index, self.composed_turn_count, self.break_count],
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
)
return digest.hexdigest()
def as_dict(self) -> dict[str, Any]:
return {
"schema_version": "identity_path_v1",
"chain_id": self.chain_id,
"scope": self.scope.as_dict(),
"chain_index": self.chain_index,
"dimension": self.dimension,
"a_path_lawful": [
[float(x) for x in row] for row in self.a_path_lawful
],
"d_stab_path": float(self.d_stab_path),
"composed_turn_count": self.composed_turn_count,
"break_count": self.break_count,
"session_admit": self.session_admit,
"ledger_digest": self.ledger_digest(),
}
def advance_identity_path(
ledger: IdentityPathLedger | None,
scope: IdentityChainScope,
action: np.ndarray,
gram: np.ndarray,
budget: PathBudget,
*,
admitted: bool = True,
) -> tuple[IdentityPathLedger, dict[str, Any]]:
"""Fold one turn's raw induced action into the lawful-only path (§3.4/§3.5).
Returns ``(new_ledger, turn_record)``. ``turn_record`` reports this turn's
``lawful`` / ``d_stab_turn`` / ``path_break`` / ``hard_break``. A turn is
lawful iff it was ``admitted`` by the caller's per-turn policy (§3.4 step 2;
default ``True`` for pure geometric callers) AND ``d_stab(action)
epsilon_turn`` under the locked singleton ``H_id={I}``; only lawful turns
compose. A scope change (or an absent prior ledger) is a hard break that
starts a fresh chain the previous path is NOT continued. Immutable:
``ledger`` is never mutated.
**Composition semantics (ratification-relevant ADR-0246 §3.4).** A lawful
turn composes its *actual certified* induced action ``A_t`` (``a_path = A_t @
a_path``), NOT a literal ``I`` element of ``H_id``. This is required, not a
shortcut: the ledger exists to catch slow multi-turn drift (§2 gap "slow
drift evades per-turn thresholds"), and many individually-lawful near-``I``
turns must be allowed to *accumulate* until ``d_stab(A_path) > ε_session``.
Composing literal ``I`` elements would make ``A_path I`` and detect nothing.
So "compose lawful ``H_t``" (§3.4 step 4) means "compose the per-turn actions
that were *certified lawful*", and only those — a refused turn is a break
marker, excluded from the product, never a soft-projected ``I`` masquerading
as a pass. The ADR body should state this reading explicitly.
"""
action = np.asarray(action, dtype=np.float64)
if action.ndim != 2 or action.shape[0] != action.shape[1]:
raise ValueError(
f"induced action must be a square matrix, got shape {action.shape}"
)
dimension = action.shape[0]
stabilizer = IdentityStabilizer.singleton(dimension)
d_stab_turn = stabilizer_defect(action, gram, stabilizer)
# §3.4 step 2 then step 3: a turn must be ADMITTED by the per-turn policy
# (/d_orth/per-axis — the caller's §3.7 verdict, default True for pure
# geometric callers) BEFORE the stabilizer criterion can certify it lawful.
# A refused turn is a break marker even when its d_stab happens to be small
# (e.g. refused on leakage alone) — otherwise a policy-refused action would
# compose into "identity holonomy", the §3.4 category error.
lawful = admitted and d_stab_turn <= budget.epsilon_turn
hard_break = ledger is None or ledger.scope != scope
if hard_break:
chain_index = 0 if ledger is None else ledger.chain_index + 1
a_path = np.eye(dimension, dtype=np.float64)
composed = 0
breaks = 0
else:
assert ledger is not None # not a hard break ⇒ prior ledger exists
chain_index = ledger.chain_index
a_path = ledger.a_path_lawful
composed = ledger.composed_turn_count
breaks = ledger.break_count
if lawful:
# time-forward: later turns act on the left of the accumulated frame action
a_path = action @ a_path
composed += 1
path_break = False
else:
# break marker — excluded from the product; NOT composed as identity
breaks += 1
path_break = True
d_stab_path = stabilizer_defect(a_path, gram, stabilizer)
new_ledger = IdentityPathLedger(
chain_id=_chain_id(scope, chain_index),
scope=scope,
chain_index=chain_index,
dimension=dimension,
a_path_lawful=a_path,
d_stab_path=d_stab_path,
composed_turn_count=composed,
break_count=breaks,
session_admit=(d_stab_path <= budget.epsilon_session),
)
turn_record = {
"lawful": lawful,
"d_stab_turn": d_stab_turn,
"path_break": path_break,
"hard_break": hard_break,
}
return new_ledger, turn_record
def raw_path_product(actions: Sequence[np.ndarray]) -> np.ndarray:
"""Time-forward product of ALL actions, lawful or not — **forensic only**.
This is the category error §3.4 forbids for the live path (it mixes refused,
ill-conditioned, and leaked actions into a fake "holonomy"). It exists solely
so tests and forensics can demonstrate that the lawful-only product differs
from the naive raw product. Never use it to admit a turn.
"""
if not actions:
raise ValueError("raw_path_product requires at least one action")
result = np.eye(np.asarray(actions[0]).shape[0], dtype=np.float64)
for action in actions:
result = np.asarray(action, dtype=np.float64) @ result
return result
# -- ADR-0246 §3.7 per-turn admission surface (pure; admit-or-abstain only) -----
# The one CERTIFIED threshold: γ_id from D4 Phase 3 (Fibonacci-search certificate
# `0079b5f2…`), the same value pinned as ``identity._WAVE_LEAKAGE_BOUND``. A test
# asserts the two stay equal so they cannot drift.
CERTIFIED_GAMMA_ID: float = 0.2126624458513829
# UNCERTIFIED PLACEHOLDERS. D4 Phase 3 certified ONLY γ_id. These bounds are NOT
# calibrated — they exist so the §3.7 admit surface is *expressible and testable*,
# and so the discrimination report can measure what such a gate WOULD do. They are
# never a live default: `AdmissionPolicy.placeholder_default()` sets `calibrated=
# False`, and no serve path may admit on them until they are certified.
PLACEHOLDER_ORTH_TOL: float = 1e-6
PLACEHOLDER_EPSILON_TURN: float = 0.1
PLACEHOLDER_EPSILON_SESSION: float = 0.3 # §3.4 path budget — UNCERTIFIED
PLACEHOLDER_TAU_MAX: float = 0.2126624458513829 # per-axis leakage cap (= γ_id placeholder)
PLACEHOLDER_S_MIN: float = 0.0 # self-alignment floor (matches D4 _WAVE_SELF_ALIGNMENT_FLOOR)
PLACEHOLDER_UNCLASSIFIED_TOL: float = 1e-6
@dataclass(frozen=True)
class AdmissionPolicy:
"""Thresholds for the ADR-0246 §3.7 per-turn admit surface.
``calibrated`` is ``False`` for any policy built from placeholders. A serve
gate MUST refuse to *activate* (admit live traffic) on an uncalibrated policy;
the policy is usable off-serving (discrimination reports, tests) regardless.
Only ``gamma_id`` is certified (D4 Phase 3); the rest are placeholders.
"""
orth_tol: float
epsilon_turn: float
gamma_id: float
tau_max: float
s_min: float
unclassified_tol: float
calibrated: bool = False
@classmethod
def placeholder_default(cls) -> "AdmissionPolicy":
"""Certified γ_id + clearly-uncalibrated placeholders (``calibrated=False``)."""
return cls(
orth_tol=PLACEHOLDER_ORTH_TOL,
epsilon_turn=PLACEHOLDER_EPSILON_TURN,
gamma_id=CERTIFIED_GAMMA_ID,
tau_max=PLACEHOLDER_TAU_MAX,
s_min=PLACEHOLDER_S_MIN,
unclassified_tol=PLACEHOLDER_UNCLASSIFIED_TOL,
calibrated=False,
)
def version_id(self) -> str:
"""Full-SHA-256 identifier of this exact threshold set (ADR-0246 §4.1
``policy_version`` / §3.5 "gate/policy version changed" hard-break key).
Changes iff any threshold or the ``calibrated`` flag changes canonical
JSON, no ``default=str`` (ADR-0245 §2.3).
"""
payload = {
"orth_tol": self.orth_tol,
"epsilon_turn": self.epsilon_turn,
"gamma_id": self.gamma_id,
"tau_max": self.tau_max,
"s_min": self.s_min,
"unclassified_tol": self.unclassified_tol,
"calibrated": self.calibrated,
}
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
@dataclass(frozen=True)
class AdmissionResult:
"""Outcome of the §3.7 admit surface for one versor — admit-or-abstain only.
``admitted`` is the AND of every condition; ``refusal_reasons`` names each
failed condition (empty iff admitted). All raw measurements are retained for
telemetry / the discrimination report. No corrector: this never rewrites the
versor or the action it only decides admit vs refuse.
"""
admitted: bool
refusal_reasons: tuple[str, ...]
d_orth: float
d_stab: float
leakage_rms: float
max_leakage: float
min_self_alignment: float
typed_channels: dict[str, float]
def as_dict(self) -> dict[str, Any]:
return {
"admitted": self.admitted,
"refusal_reasons": list(self.refusal_reasons),
"d_orth": float(self.d_orth),
"d_stab": float(self.d_stab),
"leakage_rms": float(self.leakage_rms),
"max_leakage": float(self.max_leakage),
"min_self_alignment": float(self.min_self_alignment),
"typed_channels": {k: float(v) for k, v in self.typed_channels.items()},
}
def evaluate_admission(
geometry: IdentityManifoldGeometry,
versor: np.ndarray,
policy: AdmissionPolicy,
*,
boundary_breach: bool = False,
) -> AdmissionResult:
"""Evaluate the ADR-0246 §3.7 per-turn admit surface for ``versor``.
Admit iff ALL of: ``d_orth orth_tol``, ``d_stab epsilon_turn``,
``leakage_rms gamma_id``, ``max_i leakage_i tau_max``,
``min_i self_align_i s_min``, no ``boundary_breach``, and no unclassified
residual channel firing (``> unclassified_tol``). Otherwise refuse (naming
every failed condition). Pure and admit-or-abstain never a corrector.
A malformed versor raises :class:`MalformedVersorError` from the primitives;
the serve caller is expected to translate that into a fail-closed refusal.
"""
leakage, self_align = geometry.axis_response(versor)
leakage_rms = float((sum(v * v for v in leakage) / len(leakage)) ** 0.5)
max_leakage = float(max(leakage))
min_self_alignment = float(min(self_align))
action = geometry.induced_action(versor)
d_orth = orthogonality_defect_of_action(action, geometry.gram)
d_stab = stabilizer_defect(action, geometry.gram, IdentityStabilizer.singleton(action.shape[0]))
channels = geometry.typed_residual_energy(versor)
reasons: list[str] = []
if d_orth > policy.orth_tol:
reasons.append("d_orth>orth_tol")
if d_stab > policy.epsilon_turn:
reasons.append("d_stab>epsilon_turn")
if leakage_rms > policy.gamma_id:
reasons.append("leakage_rms>gamma_id")
if max_leakage > policy.tau_max:
reasons.append("max_leakage>tau_max")
if min_self_alignment < policy.s_min:
reasons.append("min_self_alignment<s_min")
if boundary_breach:
reasons.append("boundary_id_breach")
if channels["unclassified"] > policy.unclassified_tol:
reasons.append("unclassified_channel_firing")
return AdmissionResult(
admitted=not reasons,
refusal_reasons=tuple(reasons),
d_orth=d_orth,
d_stab=d_stab,
leakage_rms=leakage_rms,
max_leakage=max_leakage,
min_self_alignment=min_self_alignment,
typed_channels=channels,
)
# -- ADR-0246 §4.1/§4.3 per-turn identity-action telemetry record --------------
def _field_digest(versor: np.ndarray) -> str:
"""Full-SHA-256 digest of the versor's bytes (LE float64, ADR-0245 §2.3).
Same convention as :func:`core.physics.holographic_vault._default_mode_id`:
explicit little-endian coercion (platform-stable, not implicit host
endianness) and no truncation.
"""
le_bytes = np.ascontiguousarray(versor, dtype=np.dtype("<f8")).tobytes()
return hashlib.sha256(le_bytes).hexdigest()
@dataclass(frozen=True)
class IdentityActionRecord:
"""Per-turn identity-action telemetry record (ADR-0246 §4.1).
Built only when the §3.7 admit surface actually ran (mirrors
``IdentityScore.action_surface_active``) there is no "empty" record; its
mere existence signals the surface was active this turn. Immutable; every
array/measure is the RAW value (never a soft-projected stand-in).
**Deviation from the brief's literal singular ``refusal_reason``:**
:func:`evaluate_admission` can name MULTIPLE failed conditions
(``AdmissionResult.refusal_reasons``, a tuple); this record joins them with
``";"`` into one string (``None`` when admitted) so no information from a
multi-condition refusal is silently dropped.
**``lawful_action``** reflects the §3.4 path-ledger's own narrower
criterion ``d_stab epsilon_turn`` under the locked ``H_id={I}`` which
is a STRICT SUBSET of the fuller §3.7 ``admitted`` verdict (which also
checks leakage/orth/self-align/boundary/unclassified). A turn can be
"admitted" but still ``lawful_action="none"`` if only the stabilizer
criterion fails to also hold within budget though in practice the two
move together since ``d_stab>epsilon_turn`` is itself one of the admission
reasons. Never a soft projection: exactly ``"I"`` or ``"none"``.
"""
schema_version: str
turn_id: int
trajectory_id: str
pack_id: str
pack_content_digest: str
geometry_version: str
gate_version: str
policy_version: str
wave_mode_active: bool
a_raw: np.ndarray
d_orth: float
d_stab: float
leakage: tuple[float, ...]
leakage_rms: float
max_leakage: float
self_align: tuple[float, ...]
min_self_alignment: float
typed_residual_energy: dict[str, float]
admitted: bool
refusal_reason: str | None
lawful_action: str
path_break: bool
field_digest: str
def _identity_payload(self) -> dict[str, Any]:
"""Everything except ``record_digest`` itself (avoids self-reference)."""
return {
"schema_version": self.schema_version,
"turn_id": self.turn_id,
"trajectory_id": self.trajectory_id,
"pack_id": self.pack_id,
"pack_content_digest": self.pack_content_digest,
"geometry_version": self.geometry_version,
"gate_version": self.gate_version,
"policy_version": self.policy_version,
"wave_mode_active": self.wave_mode_active,
"A_raw": [[float(x) for x in row] for row in self.a_raw],
"d_orth": float(self.d_orth),
"d_stab": float(self.d_stab),
"leakage": [float(x) for x in self.leakage],
"leakage_rms": float(self.leakage_rms),
"max_leakage": float(self.max_leakage),
"self_align": [float(x) for x in self.self_align],
"min_self_alignment": float(self.min_self_alignment),
"typed_residual_energy": {
k: float(v) for k, v in self.typed_residual_energy.items()
},
"admitted": self.admitted,
"refusal_reason": self.refusal_reason,
"lawful_action": self.lawful_action,
"path_break": self.path_break,
"field_digest": self.field_digest,
}
def record_digest(self) -> str:
"""Full-SHA-256 content id over the record (ADR-0245 §2.3 — no
truncation, canonical JSON, no ``default=str``)."""
canonical = json.dumps(
self._identity_payload(), sort_keys=True, separators=(",", ":")
)
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
def as_dict(self) -> dict[str, Any]:
out = self._identity_payload()
out["record_digest"] = self.record_digest()
return out
def build_identity_action_record(
geometry: IdentityManifoldGeometry,
versor: np.ndarray,
policy: AdmissionPolicy,
*,
turn_id: int = 0,
trajectory_id: str = "",
pack_id: str = "",
pack_content_digest: str = "",
geometry_version: str = "",
gate_version: str = "",
wave_mode_active: bool = True,
path_break: bool = False,
boundary_breach: bool = False,
) -> IdentityActionRecord:
"""Build the full ADR-0246 §4.1 per-turn record for one versor.
Runs :func:`evaluate_admission` (the single source of truth for the admit
verdict) plus :meth:`IdentityManifoldGeometry.induced_action` /
``axis_response`` for the raw per-axis vectors the aggregate result doesn't
expose. ``path_break`` defaults to ``False`` a caller not integrated with
the §3.4/§3.5 path ledger has no path to report a break against; a
path-integrated caller should pass the ledger's own ``turn_record["path_break"]``.
"""
result = evaluate_admission(geometry, versor, policy, boundary_breach=boundary_breach)
leakage, self_align = geometry.axis_response(versor)
lawful_action = "I" if result.d_stab <= policy.epsilon_turn else "none"
refusal_reason = ";".join(result.refusal_reasons) if result.refusal_reasons else None
return IdentityActionRecord(
schema_version="identity_action_v1",
turn_id=turn_id,
trajectory_id=trajectory_id,
pack_id=pack_id,
pack_content_digest=pack_content_digest,
geometry_version=geometry_version,
gate_version=gate_version,
policy_version=policy.version_id(),
wave_mode_active=wave_mode_active,
a_raw=geometry.induced_action(versor),
d_orth=result.d_orth,
d_stab=result.d_stab,
leakage=tuple(leakage),
leakage_rms=result.leakage_rms,
max_leakage=result.max_leakage,
self_align=tuple(self_align),
min_self_alignment=result.min_self_alignment,
typed_residual_energy=result.typed_channels,
admitted=result.admitted,
refusal_reason=refusal_reason,
lawful_action=lawful_action,
path_break=path_break,
field_digest=_field_digest(versor),
)

View file

@ -56,6 +56,15 @@ from algebra.cl41 import (
# to resolve without mode-aliasing (ADR-0244 §2.1).
CONDITION_BOUND: float = 1e5
# Grade-1 basis-vector slots in the 32-component Cl(4,1) layout. The spatial block
# is e1/e2/e3 (indices 1/2/3) — the default value-axis support; e4/e5 (indices 4/5)
# are the extra grade-1 directions a versor tilts (e4, null/conformal) or boosts
# (e5) a value axis toward. Pinned against ``algebra.cl41.basis_vector`` in tests
# (ADR-0246 §3.6 fixed blade map).
SPATIAL_GRADE1_INDICES: tuple[int, int, int] = (1, 2, 3)
E4_GRADE1_INDEX: int = 4
E5_GRADE1_INDEX: int = 5
class ManifoldConditioningError(ValueError):
"""Raised when the value-axis Gram matrix is too ill-conditioned.
@ -151,6 +160,40 @@ def euclidean_norm(s: np.ndarray) -> float:
return float(np.linalg.norm(np.asarray(s, dtype=np.float64), ord=2))
class MalformedVersorError(ValueError):
"""Raised when a versor handed to an ADR-0246 primitive is not a well-formed
``N_COMPONENTS``-vector of finite floats.
Fail-closed at the primitive boundary (ADR-0246 §6.1 "Malformed F → typed
error"): a NaN/inf or wrong-shape field must raise, never propagate a silent
NaN into an induced action or a residual-channel split.
"""
def _validate_versor(versor: np.ndarray) -> np.ndarray:
"""Coerce to a finite float64 ``(N_COMPONENTS,)`` array or fail closed."""
array = np.asarray(versor, dtype=np.float64)
if array.shape != (N_COMPONENTS,):
raise MalformedVersorError(
f"versor must have shape ({N_COMPONENTS},), got {array.shape}"
)
if not np.all(np.isfinite(array)):
raise MalformedVersorError("versor has non-finite (NaN/inf) components")
return array
def orthogonality_defect_of_action(action: np.ndarray, gram: np.ndarray) -> float:
"""``‖AᵀGA G‖_F`` for a precomputed induced action ``A`` (ADR-0246 §3.2).
Zero iff ``A`` is a ``G``-isometry of the value subspace. The single home for
the d_orth definition, shared by :meth:`IdentityManifoldGeometry.orthogonality_defect`
and the off-serving diagnostics.
"""
action = np.asarray(action, dtype=np.float64)
gram = np.asarray(gram, dtype=np.float64)
return float(np.linalg.norm(action.T @ gram @ action - gram, ord="fro"))
@dataclass(frozen=True)
class IdentityManifoldGeometry:
"""Frozen operator-preservation geometry for a set of value axes.
@ -232,3 +275,100 @@ class IdentityManifoldGeometry:
"""
leakage, _ = self.axis_response(versor)
return float((sum(value * value for value in leakage) / len(leakage)) ** 0.5)
# -- ADR-0246 §3 induced-action primitives (pure, off-serving) --------------
def induced_action(self, versor: np.ndarray) -> np.ndarray:
"""The induced action matrix ``A(F)`` of a versor on the value frame.
``A_kj = (G¹)_{km} a_m, F a_j F̃`` (ADR-0246 §3.1). Column ``j`` is the
image of axis ``j`` (``F a_j F̃``) re-expressed in the axis basis. This
captures ALL in-subspace action including the permutations and rotations
that per-axis leakage is blind to (a rotor rotating e1e2 has zero leakage
but a non-identity ``A``). It is RAW (unnormalized): a boost that stretches
an axis shows up as a column norm > 1 and hence in :meth:`orthogonality_defect`,
deliberately not hidden by normalization.
When ``F`` preserves the subspace isometrically, ``A`` is ``G``-orthogonal
(``AᵀGA = G``). Built only from existing primitives (Gram, signed inner
product, sandwich); no new algebra.
Raises :class:`MalformedVersorError` on a non-finite or wrong-shape versor
(ADR-0246 §6.1 fail-closed on malformed F).
"""
versor = _validate_versor(versor)
n = len(self.axes_psi)
overlaps = np.empty((n, n), dtype=np.float64)
for j, axis_j in enumerate(self.axes_psi):
image = sandwich(versor, axis_j)
for k, axis_k in enumerate(self.axes_psi):
overlaps[k, j] = _inner0(axis_k, image)
return self.gram_inv @ overlaps
def orthogonality_defect(self, versor: np.ndarray) -> float:
"""``d_orth(F) = ‖A(F)ᵀ G A(F) G‖_F`` (ADR-0246 §3.2).
Zero iff the induced action is a ``G``-isometry of the value subspace.
Non-zero flags numerical failure or genuinely non-isometric action (a
boost stretches the frame). It detects a DIFFERENT failure than
:func:`~core.physics.identity_action.stabilizer_defect` and must never be
read as a semantic authorization policy it is a conditioning / isometry
check only.
"""
return orthogonality_defect_of_action(self.induced_action(versor), self.gram)
def typed_residual_energy(self, versor: np.ndarray) -> dict[str, float]:
"""Typed decomposition of the out-of-subspace leakage (ADR-0246 §3.6).
For each axis the rejection ``r = F a F̃ P_I(F a F̃)`` is split by which
grade-1 direction it leaks into, summed over axes, and returned as
fractions of the total rotated-axis energy:
* ``null_or_conformal`` energy on e4 (index 4): conformal/null tilt.
* ``boost_like`` energy on e5 (index 5): noncompact/boost class.
* ``spatial_foreign`` energy on spatial grade-1 slots (e1/e2/e3) not
in the value-axis span; structurally 0 for the default full-span pack.
* ``unclassified`` the remainder (higher-grade contamination after
the sandwich, numerical junk). Fail-closed: no correction policy ever
attaches to this channel. For a clean versor (grade-preserving sandwich)
it is ~0.
Retains the positive-definite Euclidean coefficient norm (never the
indefinite ``·,·``) so a boost/e5 component cannot silently vanish.
Raises :class:`MalformedVersorError` on a non-finite or wrong-shape versor
(ADR-0246 §6.1 fail-closed on malformed F).
"""
versor = _validate_versor(versor)
e4_energy = e5_energy = spatial_foreign = unclassified = total = 0.0
for axis in self.axes_psi:
rotated = sandwich(versor, axis)
rejection = rotated - self.project(rotated)
total += euclidean_norm(rotated) ** 2
e4_energy += float(rejection[E4_GRADE1_INDEX] ** 2)
e5_energy += float(rejection[E5_GRADE1_INDEX] ** 2)
spatial_foreign += float(
sum(rejection[i] ** 2 for i in SPATIAL_GRADE1_INDICES)
)
rejection_energy = euclidean_norm(rejection) ** 2
unclassified += max(
0.0,
rejection_energy
- float(rejection[E4_GRADE1_INDEX] ** 2)
- float(rejection[E5_GRADE1_INDEX] ** 2)
- float(sum(rejection[i] ** 2 for i in SPATIAL_GRADE1_INDICES)),
)
if total <= 0.0:
# Versor annihilated every axis — fail-closed as fully unaccounted.
return {
"null_or_conformal": 0.0,
"boost_like": 0.0,
"spatial_foreign": 0.0,
"unclassified": 1.0,
}
return {
"null_or_conformal": e4_energy / total,
"boost_like": e5_energy / total,
"spatial_foreign": spatial_foreign / total,
"unclassified": unclassified / total,
}

View file

@ -0,0 +1,282 @@
# ADR-0246: Induced Identity Action and Path Integrity
**Status**: **Proposed** — pending explicit human ratification (provenance guard: no self-Accept; ruling record in the acceptance packet is PENDING)
**Date**: 2026-07-17
**Authors**: Joshua Shay + multi-model R&D (Fable 5 scaffold → Opus 4.8 adversarial audit + hardening → Sonnet 5/Fable 5 completion; per-model provenance in §9)
**Preflight**: `docs/briefs/ADR-0246-induced-identity-action-and-path-integrity-preflight.md` (locked decisions §3, non-goals §7 — all honored; execution log §0a)
**Depends on**: ADR-0244 (operator-preservation identity gate, Accepted), ADR-0245 (mechanical sympathy + semantic rigor, Accepted)
**Related**: slice-0 evidence `docs/audit/adr-0246-slice0-mismatch-diagnostic-2026-07-17.md` (merged, quarantined diagnostic); Opus audit `docs/audit/adr-0246-slice1-opus-audit-and-hardening.md`
---
## 1. Context and problem
D4 (ADR-0244) built the per-turn operator-preservation floor: does the live
cognitive versor `F` preserve the frozen identity frame `I = span(a₁…aₙ)`,
measured by per-axis subspace leakage `ℓᵢ` and signed self-alignment `sᵢ`? Two
gaps were deliberately left open (preflight §2):
1. **Lawfulness inside the span** — leakage is blind to in-span reshuffles: a
rotor permuting `e1→e2` or inverting `e1→e1` has `≈0` yet is not the
identity-preserving action.
2. **Accumulation across turns** — per-turn thresholds cannot see slow drift:
many individually-admissible small rotations compose into a large one.
This ADR closes both with the **induced action** `A(F)` on the frame, two
never-collapsed diagnostics (`d_orth`, `d_stab`), a locked lawful-stabilizer
policy `H_id={I}`, typed residual channels, a lawful-only path ledger with hard
breaks, a per-turn admit surface, and full per-turn/per-session telemetry — all
flag-gated default-off at serve.
**Claims language (binding, §10 #9 of the preflight):** everything this ADR
instruments is **lawfulness relative to the declared frozen frame**. It does
NOT establish, and must never be quoted as establishing, any semantic
inalienability of the value labels themselves — the shipped axes
(`truthfulness=e1`, `coherence=e2`, `reverence=e3`) remain placeholder
orthonormal directions with no demonstrated dynamical or semantic grounding
(see §6, §7).
## 2. Decisions (as implemented; preflight §3 locked decisions honored)
### 2.1 Induced action matrix `A(F)`
`A_kj(F) = (G⁻¹)_km ⟨a_m, F a_j F̃⟩₀` — the full in-subspace action of the
versor on the frame (`core/physics/identity_manifold.py::IdentityManifoldGeometry.induced_action`).
Raw/unnormalized: a boost's cosh-stretch shows in column norms and in `d_orth`,
never hidden. Bit-exactness against an independent re-derivation was verified
in the Opus audit (max discrepancy 0.00e+00).
### 2.2 Two diagnostics, never collapsed
- `d_orth(F) = ‖A(F)ᵀ G A(F) G‖_F` (`orthogonality_defect`) — G-isometry /
numerical-integrity check. **Not** an authorization policy.
- `d_stab(F) = min_{H∈H_id} ‖A(F) H‖_G` (`identity_action.py::stabilizer_defect`)
— the lawfulness distance from the permitted identity actions.
**Norm convention (ruling requested — §7 item 1):** `‖M‖_G ≡ ‖G^{1/2} M G^{-1/2}‖_F`,
computed via `eigh` of the SPD Gram; reduces exactly to Frobenius at `G=I`
(the only shipped pack). This is the metric-consistent choice (invariant under
G-orthogonal reparameterization of the axes); ratifying this ADR ratifies the
convention.
### 2.3 Lawful stabilizer — locked singleton
`H_id = {I}` (`IdentityStabilizer.singleton`), hardcoded in the path-advance
(no enlargement parameter exists). `I`, permutations, `O(n)`/`SO(n)`
rotations, and reweightings are excluded; enlarging `H_id` is a future explicit
reviewed pack/policy change. No soft-projection of an unlawful `A` onto `I`
exists anywhere (grep-audited; pinned by tests).
### 2.4 Path integrity — lawful-only composition (F1 semantics, ratification-relevant)
`advance_identity_path` (§3.4/§3.5) composes the session path
`A_path = A_T ⋯ A_1` from **only** the turns certified lawful, where lawful ≡
**admitted by the per-turn policy (§3.4 step 2)** AND `d_stab(A_t) ≤ ε_turn`.
Refused or ill-conditioned turns insert a **break marker** and are excluded —
never a soft-projected `I` masquerading as a pass; the raw product is exposed
only as `raw_path_product` (forensic; a test fails if it ever equals the lawful
path in a mixed sequence).
**F1 composition semantics (audit finding, hereby put to ratification):** a
lawful turn composes its *actual certified action* `A_t`, not a literal element
of `H_id`. This is required, not convenience — composing literal `I`s would
make `A_path ≡ I` and blind the ledger to exactly the slow drift it exists to
catch. "Compose lawful `H_t`" in preflight §3.4-step-4 is READ as "compose the
per-turn actions that were certified lawful."
**Hard breaks (§3.5):** a new chain (fresh `chain_id`, path not continued)
starts on any change of pack content digest / geometry version / gate+policy
version / session — each dimension is pinned by a test. **Turn ownership at a
hard break (ruling requested — §7 item 3):** the boundary turn belongs to the
NEW chain (it composes into the fresh path if lawful). Biography holonomy stays
a separate process; nothing here rewrites identity axes.
**Budgets:** `d_stab(A_t) ≤ ε_turn` per turn and `d_stab(A_path) ≤ ε_session`
per session — both ε are **UNCERTIFIED placeholders** (§5), so the session
verdict (`session_admit`) is telemetry only.
### 2.5 Typed residual channels — pinned blade map
On each axis rejection `r = F a F̃ P_I(F a F̃)` (`typed_residual_energy`),
energy splits into: `null_or_conformal` (e4 = grade-1 index **4**),
`boost_like` (e5 = grade-1 index **5**), `spatial_foreign` (grade-1 spatial
slots **1/2/3** outside the pack's axis support), `unclassified` (everything
else — fail-closed, **no correction policy ever attaches to it**). Blade
indices are pinned against `algebra.cl41.basis_vector` in tests
(`test_blade_index_constants_match_algebra`). For the default full-span pack,
`spatial_foreign` is **tautologically zero** (the rejection is orthogonal to
the whole spatial block); it fires correctly for reduced-support packs —
resolved and pinned (§7 item 2).
### 2.6 Per-turn admit surface (§3.7) — admit-or-abstain only
`evaluate_admission(geometry, F, policy)` admits iff `d_orth ≤ orth_tol` AND
`d_stab ≤ ε_turn` AND `leakage_rms ≤ γ_id` AND `max ℓᵢ ≤ τ_max` AND
`min sᵢ ≥ s_min` AND no boundary breach AND no unclassified-channel firing;
otherwise refuses naming every failed condition. **No geometric `C_id`
corrector exists** — the egress model remains D4's
`conjugate_correct(refuse=True)` abstention. A malformed versor raises
`MalformedVersorError` (fail-closed; never a silent legacy fallback when a
wave field was supplied).
### 2.7 Serve wiring — flag-gated, default-off, byte-identical off
- New `RuntimeConfig.identity_action_surface: bool = False` (separate from
`identity_wave_gate`; acts only when the wave gate is also on).
- `chat/runtime.py → IdentityCheck.check(admission_policy=…) → _wave_field_score`:
a §3.7 refusal folds into `flagged`, so the existing `would_violate` egress
abstains. `IdentityScore` gains `action_surface_active`/`d_orth`/`d_stab`/
`action_record` with legacy defaults — flag-off is byte-identical (all D4
gate surfaces green unchanged; smoke green post-wiring).
- The session path ledger is advanced per wave-path turn under the same flags,
**observe-only** (`advance_session_identity_path`): `session_admit` is
telemetry, never an egress decision, because `ε_session` is uncertified and
live activation remains unauthorized.
### 2.8 Telemetry (§4.1/§4.2/§4.3)
- `IdentityActionRecord` (schema `identity_action_v1`): turn/trajectory/pack
ids, **full-SHA-256** pack-content digest + `field_digest` (LE f64 bytes) +
`record_digest` (canonical JSON, no `default=str`), geometry/gate/policy
versions (`policy_version = AdmissionPolicy.version_id()`, full SHA-256 of
the exact threshold set), `A_raw`, `d_orth`, `d_stab`, leakage/self-align
vectors, typed channels, `admitted`, `refusal_reason` (all failed conditions
joined with `;` — a deliberate widening of the preflight's singular field so
multi-condition refusals lose nothing), `lawful_action ∈ {"I","none"}`
(never a matrix), `path_break`.
- `IdentityPathLedger` (schema `identity_path_v1`): `chain_id` (full SHA-256
of scope + chain index), lawful path, `d_stab_path`, composed/break counts,
`session_admit`, `ledger_digest`.
- The JSONL turn serializer emits `identity_d_*`/`identity_action_*`/
`identity_path_*` keys **only when the respective path ran** — the flag-off
wire format is byte-identical (pinned by tests).
## 3. Evidence — §6 eval matrix (all green) and the honest discrimination result
- **§6.1 synthetic geometric suite** (9 cases) + **§6.2 path/holonomy suite**
(5 cases): `evals/adr_0246_geometric_suite` — 14/14; every construction in
the preflight tables pinned individually (identity versor, π-inversion
`s=1`, 90° permutation `s=0`, mild drift, e14 tilt, e15 boost,
near-singular Gram → `ManifoldConditioningError`, malformed F → typed error;
lawful sequence, accumulation-to-session-refusal, interleaved breaks,
pack-change hard break, raw≠lawful forensic).
- **§6.3 discrimination report** (`evals/adr_0246_discrimination`;
live benign n=13, adversarial n=8, synthetic-near-identity control n=5;
artifact `docs/audit/artifacts/adr-0246-slice1-discrimination-report.json`):
| benign pass | false refusal | adversarial detect | control pass | d_stab AUC (95% CI) |
|---|---|---|---|---|
| **0.00** | **1.00** | 1.00 | **1.00** | **0.375** [0.15, 0.62] |
**Honest finding:** on the declared placeholder frame the admit surface
refuses benign and adversarial versors **alike** — benign cognition sits
~18× farther from the frame (mean `d_stab` 27.8) than the crafted attacks
(1.55), so `d_stab` discriminates *below chance*. The near-identity control
passing 100% proves the mechanism is sound; the failure is entirely that
benign cognition does not live near the declared frame. A refuse-everything
gate trivially "detects" attacks but is **not a discriminator**.
- **§11 grounding-feasibility study** (`evals/adr_0246_grounding_feasibility`;
artifact `docs/audit/artifacts/adr-0246-grounding-feasibility-report.json`):
fixed TRAIN (live benign, n=13) / HELD-OUT (independent paraphrase cohort,
n=12) / ADVERSARIAL (n=8) splits; bivector-block generator proxy (numpy-only;
exact for simple rotors/boosts, first-order otherwise); sample-size-calibrated
null distribution (200 trials of independent pure-noise cohort pairs at the
real n) with a shared-basis positive recovery control; precision pairs
(f64↔f32) and per-plane generator-energy analysis.
**Result: NULL, with the method itself validated.** The positive control
(two independent cohorts sharing one true rank-2 subspace) recovers at
cosine 0.9995 — the 100th percentile of the same-sample-size null (p95 =
0.60) — so the instrument can find real structure at n=12. The real cohorts
do not show it: TRAIN→HELD-OUT top-2 cosine 0.52 sits at only the **87th
percentile of pure chance** (need ≥ 95th); residual-based discrimination is
AUC **0.49** (chance; CI [0.21, 0.77]); generator energy is spread across
all 10 bivector planes in both cohorts; precision transport is immaterial
(max bivector delta 6.9e-7). Benign cognition has no small, stable,
cohort-independent generator subspace detectable at this sample size — the
D4/slice-0/§6.3 finding now holds at the GENERATOR level too. Threshold
tuning cannot produce a discriminating gate; a revised implementation
contract is not justified on this evidence. The full `honest_finding` text
in the artifact is binding for any downstream claim; a much larger,
pre-registered cohort would be needed to rule out a subtle real effect.
## 4. Operational status (machine-readable)
```yaml
identity_action_surface:
implementation: proposed # this ADR; code merged flag-off
live_activation: not_authorized # D4 ratified limitation carries over
default: off
blocker: >
§6.3 shows no benign/adversarial separation on the declared frame
(AUC 0.375, benign false-refusal 1.00); thresholds beyond gamma_id
are uncertified placeholders.
activation_requires:
- held-out-stable, safety-relevant grounding result (§11 programme)
- calibrated epsilon_turn/epsilon_session/tau_max/s_min certificates
- renewed discrimination evidence with acceptable benign refusal rate
- explicit human ratification
identity_wave_gate:
unchanged: true # ADR-0244 Accepted-with-limitation posture untouched
```
## 5. Uncertified placeholders (enumerated; never live defaults)
| Constant | Value | Status |
|---|---|---|
| `gamma_id` | 0.2126624458513829 | **CERTIFIED** (D4 Phase 3 Fibonacci certificate `0079b5f2…`); pinned equal to `identity._WAVE_LEAKAGE_BOUND` by test |
| `epsilon_turn` | 0.1 | placeholder |
| `epsilon_session` | 0.3 | placeholder |
| `tau_max` | = γ_id | placeholder |
| `s_min` | 0.0 | matches D4's fixed orientation floor (geometric invariant, not tuned) |
| `orth_tol` | 1e-6 | placeholder |
| `unclassified_tol` | 1e-6 | placeholder |
`AdmissionPolicy.placeholder_default()` carries `calibrated=False`; a serve
gate must never treat an uncalibrated policy as license to activate.
## 6. What this ADR does NOT do (preflight §7 non-goals — all honored)
No geometric `C_id`/corrector; no Ring-2 residual protocol; no semantic axis
grounding or pack redesign; no biography-holonomy merge; no atlas/VSWR work;
no analytic cast reactance; no grade-1 versor projection (proven vacuous); no
indefinite-norm leakage; no `H_id` enlargement; no soft-projection; no
default-on serve gate; no Smith-chart algebra; no status flip of ADR-0244/0245.
## 7. Resolved and open questions
1. **`‖·‖_G` convention** — implemented as `‖G^{1/2}MG^{-1/2}‖_F`; **ratify
with this ADR** (§2.2).
2. **`spatial_foreign` channel** — RESOLVED: tautologically zero for the
default full-span pack; fires correctly for reduced-support packs (pinned:
`test_spatial_foreign_channel_fires_for_reduced_support_pack`).
3. **Hard-break turn ownership** — implemented as new-chain; **ratify with
this ADR** (§2.4).
4. **Malformed-F/gate routing** — the D4 wave-path validator raises before the
admission surface runs; `MalformedVersorError` from the pure primitives
propagates fail-closed. No silent legacy fallback exists when a wave field
was supplied. Unifying the two typed errors is left to a future cleanup.
5. **OPEN (future ADR):** semantic axis grounding — blocked on a positive §11
result at adequate sample size; `ε` calibration; `H_id` policy products.
## 8. Consequences
- The identity organ now measures *everything* the preflight demanded —
in-span lawfulness, isometry integrity, typed foreign leakage, and
path accumulation — with serve byte-identity preserved and zero live policy
change. What it measures says, honestly: the declared frame is not the
structure live cognition preserves, so the gate stays off and the next
investment belongs to grounding, not thresholds.
- All future identity work inherits content-addressed, full-digest telemetry
(records + ledger) and a single pure source of truth for the §3 primitives.
## 9. Provenance
Fable 5: slice-0 diagnostic; §3 primitives + §3.4/3.5 ledger + §6.1/6.2 suites
(RED-first); this completion pass. Opus 4.8: adversarial audit (bit-exact math
re-derivation; H_id/soft-projection/scope-creep verification), F1 finding,
§3.7 surface + serve wiring, §6.3 discrimination report. Sonnet 5: §4.1/§4.2
telemetry records, `admitted` gate on the ledger (F1-adjacent §3.4-step-2
compliance), path serve integration (observe-only), §11 feasibility study
design. Every stage: local-first CI (smoke + targeted suites) before commit;
no self-Accept at any point.

View file

@ -0,0 +1,105 @@
# ADR-0246 Acceptance Packet — Induced Identity Action and Path Integrity
**Date:** 2026-07-17
**ADR:** `docs/adr/ADR-0246-induced-identity-action-and-path-integrity.md` (**Proposed**)
**Preflight:** `docs/briefs/ADR-0246-induced-identity-action-and-path-integrity-preflight.md`
**Provenance chain:** Fable 5 (slice-0 diagnostic; §3 primitives; §3.4/3.5 ledger; §6.1/6.2 suites; completion pass) → Opus 4.8 (adversarial audit VERDICT PASS — bit-exact math re-derivation; F1 finding; §3.7 surface + serve wiring; §6.3 discrimination) → Sonnet 5/Fable 5 (§4.1/§4.2 telemetry; §3.4-step-2 `admitted` gate; path serve integration; §11 feasibility study). No self-Accept at any stage.
---
## 1. Scope of what is being put to ruling
Accepting this ADR accepts: the §3 primitives and their pinned blade map; the
locked `H_id={I}` stabilizer; the **`‖·‖_G = ‖G^{1/2}MG^{-1/2}‖_F` norm
convention**; the **F1 composition semantics** (lawful turns compose their raw
*certified* action, never a literal `I`); the **admitted-gate** on composition
(§3.4 step 2); **hard-break turn ownership = new chain**; the §3.7
admit-or-abstain surface; the flag-gated serve wiring (default-off,
byte-identical off); and the §4.1/§4.2 telemetry contracts.
It does **NOT** accept or authorize: live activation of `identity_wave_gate`
or `identity_action_surface` (both stay default-off; the D4 ratified
limitation carries over); any calibration of the placeholder thresholds; any
semantic claim about the value labels ("lawfulness relative to the declared
frozen frame" only); any `H_id` enlargement or geometric corrector.
## 2. §10 acceptance criteria — status
| # | Criterion | Status |
|---|---|---|
| 1 | §6 synthetic + path suites green; discrimination report attached | ✅ 14/14 eval cases; §6.3 + §11 artifacts under `docs/audit/artifacts/` |
| 2 | `H_id={I}` enforced, no silent enlargement | ✅ singleton hardcoded; no enlargement path; grep-audited + pinned |
| 3 | Lawful-only composition proven by tests that fail if raw product used | ✅ `test_lawful_path_equals_lawful_subproduct_not_raw`, `test_raw_product_differs_from_lawful`, §3.4-step-2 pin |
| 4 | Ledger hard-breaks on pack/geometry/policy/session change | ✅ parametrized over every scope dimension |
| 5 | Flag-off serve path byte-identical | ✅ egress/action-record/path tests + all D4 gate surfaces green unchanged + smoke |
| 6 | No geometric `C_id`; admit-or-abstain only | ✅ no corrector exists; refusal folds into the existing `would_violate` egress |
| 7 | Typed residual channels pinned to explicit blade indices | ✅ e4=idx 4, e5=idx 5, spatial=idx 1/2/3; pinned vs `algebra.cl41` |
| 8 | Smoke + relevant lanes local-first; `[Verification]` on commits | ✅ every commit in the stack; final run log `docs/audit/artifacts/adr-0246-slice1-complete-runlog.txt` |
| 9 | Claims language: lawfulness-relative-to-frame, never semantic inalienability | ✅ binding in ADR §1; enforced in report code + tests |
| 10 | Explicit human ratification for status flip | ⏳ THIS PACKET — §8 below |
## 3. Verification summary (see run log for actual output)
- §6.1/§6.2 eval harness: **14/14** `all_passed=True`.
- ADR-0246 test suites (induced-action incl. spatial-foreign resolution,
path-ledger incl. raw-sneak + admitted-gate, geometric suite, admission +
honest-verdict pins, egress wiring, action-record §4.1, path serve
integration, grounding feasibility, mismatch diagnostic): **all green**.
- Adjacent D4 identity surfaces + telemetry suites: **green unchanged**
(serve byte-identity).
- `uv run core test --suite smoke -q`: **green** (appended to run log).
## 4. The honest §6.3 discrimination numbers (binding)
Benign pass **0.00** · false refusal **1.00** · adversarial detect 1.00 ·
near-identity control pass **1.00** · `d_stab` AUC **0.375** [0.15, 0.62] —
benign cognition sits ~18× farther from the declared frame than crafted
attacks. The gate mechanism is sound; the frame is not what live cognition
preserves. A refuse-everything gate is not a discriminator; activation stays
unauthorized.
## 5. The §11 grounding-feasibility verdict (binding, verbatim from the artifact)
> NULL (n_train=13, n_held_out=12): the top-2 generator-proxy subspace found
> on TRAIN does NOT reliably reproduce on the independently-collected HELD-OUT
> cohort — cosine similarity 0.52 sits at only the 87th percentile of what two
> INDEPENDENT pure-noise cohorts of the same size produce by chance (need >=
> 95th) and/or does not clear the discrimination bar (AUC 0.49, 95% CI [0.21,
> 0.77]). This is consistent with — and sharpens — the D4/slice-0/§6.3 finding
> at the GENERATOR level (not just the induced-action level): benign cognition
> does not have a small, stable, cohort-independent generator subspace
> detectable at this sample size. Threshold tuning on the current pack cannot
> produce a discriminating gate; this feasibility study does not find grounds
> to draft a revised ADR-0246 implementation contract. A much larger cohort
> (this study used n<=13 per real cohort) would be needed to rule out a real
> but subtle effect, rather than to overturn this null.
Method validated by sample-size-calibrated controls: shared-basis positive
pair recovers at cosine 0.9995 (100th percentile of the null; null p95 0.60 at
n=12). Precision transport immaterial (6.9e-7).
## 6. Rulings requested alongside Proposed→Accepted
1. `‖·‖_G` convention (ADR §2.2).
2. F1 composition semantics + admitted-gate reading of §3.4 (ADR §2.4).
3. Hard-break turn ownership = new chain (ADR §2.4).
4. The refusal_reason multi-condition widening (ADR §2.8).
## 7. Operational limitation carried forward
`identity_wave_gate` AND `identity_action_surface` remain **default-off / live
activation NOT authorized**. Activation prerequisites (all required): a
positive, held-out-stable, safety-relevant grounding result at adequate sample
size; calibrated ε/τ/s certificates; renewed discrimination evidence with
acceptable benign refusal; explicit human ratification.
## 8. RULING RECORD
**PENDING** — awaiting explicit ruling by Joshua Shay.
| Field | Value |
|---|---|
| Ruling | _(pending)_ |
| By | _(pending)_ |
| Date | _(pending)_ |
| Notes | _(pending)_ |

View file

@ -0,0 +1,150 @@
# ADR-0246 Slice-1 — Opus 4.8 Audit, Hardening & Discrimination Report
**Reviewer:** Opus 4.8. **Branch:** `feat/adr-0246-slice1-hardened` (stacked on
`feat/adr-0246-slice1-scaffold`, unmerged). **Not a PR, not merged, no status
flip.** Review gate only — ratification is human (Shay).
**Audited artifact:** Fable 5's `feat/adr-0246-slice1-scaffold`.
---
## 1. Step-1 adversarial audit — VERDICT: PASS (one documentation finding)
Nothing was trusted from Fable's run log; every claim was reproduced.
| Check | Method | Result |
|-------|--------|--------|
| D4 closed (hard gate) | independent `git cat-file`/status on `main` | ✅ both acceptance packets on `main`; ADR-0244 Accepted/ratified; `main @ 04d67ca5` |
| `A(F)`, `d_orth`, `d_stab`, typed channels correct | **re-derived from §3.1/3.2/3.6 from scratch** (independent sandwich/Gram/projection) and diffed vs impl | ✅ **bit-exact, max discrepancy 0.00e+00** |
| `H_id={I}` genuinely locked in code | read `IdentityStabilizer`, `advance_identity_path` | ✅ singleton hardcoded in the path; **no enlargement parameter or path**; grep found no enlargement/permutation/soft-projection code |
| Path composes lawful only, never raw, no soft-`I` | read composition; grep | ✅ lawful turns compose; refused turns → `path_break`, excluded; `a_path` untouched on refuse |
| Placeholders logged, not baked | read policy/eval | ✅ `PLACEHOLDER_*` marked; `PathBudget` always caller-supplied |
| §7 scope creep / serve byte-identity | full `git diff main..scaffold`; per-function diff | ✅ **no `chat/runtime.py`, `identity.py`, or flag change**; serve-called geometry functions untouched (additions only) |
| §6.1/§6.2 matrix reproduced | ran from clean tree | ✅ 14/14 eval cases; 64 tests |
### Finding F1 (documentation, NOT a code bug)
`advance_identity_path` composes the **raw certified action** `A_t`
(`a_path = A_t @ a_path`), not a literal `I`. This is **required and correct**
composing `I`s would make `A_path ≡ I` and defeat the slow-drift detection that is
the ledger's whole purpose (§2 gap). But it departs from a literal reading of
§3.4-step-4's `H_t ∈ H_id` notation and was undocumented. **Correction applied:**
an explicit "Composition semantics (ratification-relevant)" paragraph now states
the reading in the docstring; the ADR body should ratify it (see §4 handoff).
No locked decision (§3) or non-goal (§7) was violated to make anything pass.
---
## 2. Hardening & additions (this branch) — diff-style note
Every change vs Fable's scaffold, and why:
| File | Change | Why |
|------|--------|-----|
| `identity_action.py` | **F1 docstring** on `advance_identity_path` | ratify the raw-certified-action composition (audit finding) |
| `identity_action.py` | **§3.7 admit surface**: `CERTIFIED_GAMMA_ID`, `PLACEHOLDER_*`, `AdmissionPolicy` (`calibrated=False`), `AdmissionResult`, `evaluate_admission` | pure, testable admit-or-abstain surface (§3.7) — the reusable core for the discrimination report and the future serve wiring. No corrector. |
| `evals/adr_0246_discrimination/` | **§6.3 discrimination report** (new) | honest benign-vs-adversarial numbers with bootstrap-CI AUC (§6.3/§10) |
| `tests/test_adr_0246_admission.py` | pins for `evaluate_admission` + the honest verdict + γ_id-drift guard | fail loudly if the surface or the honesty claim regresses |
| `tests/test_adr_0246_path_ledger.py` | **raw-sneak hardening test** | fails if a raw product ever enters `A_path_lawful` (Step 2.3) |
Nothing here touches serve, flags, `H_id`, or adds a corrector. `evaluate_admission`
lives in the pure `identity_action.py`; γ_id is pinned equal to
`identity._WAVE_LEAKAGE_BOUND` by a test so it cannot drift.
---
## 3. §6.3 Discrimination report — HONEST numbers (no inflation)
Full artifact: `docs/audit/artifacts/adr-0246-slice1-discrimination-report.json`
(live benign cohort n=13, adversarial n=8, synthetic-near-identity control n=5;
policy = placeholder, `calibrated=False`).
| Metric | Value |
|--------|-------|
| benign pass rate | **0.00** |
| false refusal rate | **1.00** |
| adversarial detection rate | 1.00 |
| synthetic-near-identity pass rate (control) | **1.00** |
| `d_stab` AUC (adversarial vs benign) | **0.375**, 95% CI [0.15, 0.62] |
| `leakage_rms` AUC | 0.18, 95% CI [0.04, 0.39] |
| benign `d_stab` (min/mean/max) | 0.15 / **27.8** / 228 |
| adversarial `d_stab` (min/mean/max) | 0.46 / **1.55** / 2.83 |
**Honest finding (verbatim in the report):** the §3.7 admit surface on the declared
placeholder frame refuses benign and adversarial versors **alike** — benign
false-refusal is 100% and `d_stab` does **not** separate the classes (AUC 0.375 is
*below* chance: real benign cognition sits ~18× farther from the identity frame
than the crafted attacks do). A gate that refuses everything trivially "detects"
every attack but **is not a discriminator**. The synthetic-near-identity control
passing at 100% confirms the gate *mechanism* is sound — the failure is entirely
that benign cognition does not live near the declared frame. This reproduces and
sharpens the D4 / slice-0 result at the fuller §3.7 surface.
**Claims language (§10 #9), enforced in code and report:** this supports only
*"lawfulness relative to the declared frozen frame."* It does **not** support any
claim of *"semantic inalienability of the value labels."* The gate must stay
default-off; usable separation requires the §11 dynamics-grounding work — **not**
threshold tuning.
---
## 4. §3.7 egress serve wiring (Steps 2.1/2.2) — DONE (Opus)
Wired the fuller admit surface into the live gate, flag-gated + default-off +
byte-identical:
- New **default-off** flag `identity_action_surface` in `core/config.py`
`RuntimeConfig` (separate from `identity_wave_gate`; documented as uncalibrated /
not authorized live).
- Threaded an `AdmissionPolicy` (`placeholder_default()`, `calibrated=False`)
through `chat/runtime.py``IdentityCheck.check(..., admission_policy=)`
`_wave_field_score`. Only acts when `identity_wave_gate` is also on (a
`wave_field` exists).
- On the wave path with the policy present, `evaluate_admission(...)` runs; a
refusal folds into `flagged`, so the **existing** `would_violate` /
`conjugate_correct(refuse=True)` egress abstains — **admit-or-abstain, no
corrector**. `MalformedVersorError` from the primitives propagates as a
fail-closed refusal.
- `IdentityScore` gained optional `action_surface_active` / `d_orth` / `d_stab`
with legacy defaults, so flag-off is byte-identical.
Verified: `tests/test_adr_0246_egress_wiring.py` (flag default-off; flag-off
`check()` byte-identical incl. default §3.7 fields; flag-on refuses a tilt and
admits true near-identity) + **all D4 gate surfaces green unchanged** (wave /
runtime / eval / `test_identity_gate`) — serve byte-identity confirmed.
**Guardrail:** `calibrated=False` + flag default-off ⇒ not live-authorized; the §3
discrimination numbers are the evidence it must stay off pending §11 + calibration.
## 4c. Handoff to Sonnet 5 — remaining ADR-0246 work
1. **§4.1 `IdentityActionRecord` per-turn telemetry** — not built (only the §4.2
`IdentityPathLedger` exists). Add the per-turn record (field/record digests,
gate/policy versions, the §3.7 measures) and emit it only when the wave/action
path ran (preserve flag-off wire format, §4.3). Optionally surface `d_orth`/
`d_stab`/typed channels through the telemetry serializer.
2. **Path-ledger ↔ serve integration** — the ledger (`advance_identity_path`) is
pure and unit-tested but is not yet driven per-turn from `chat/runtime.py`
(session-scoped chain, hard-break on pack/geometry/policy/session). Wire it
flag-gated + off, using the §3.5 scope keys, if a session path budget is wanted.
3. **ADR-0246 body + acceptance packet** — draft `docs/adr/ADR-0246-...md` as
**Proposed** (no self-Accept — provenance guard). Must: state the F1 composition
semantics explicitly; use the §10 claims language ("lawfulness relative to the
declared frozen frame"); carry the honest §6.3 numbers; enumerate the placeholder
ε's/τ's as uncalibrated. Acceptance packet per §10; §8 RULING PENDING.
4. **§11 grounding-feasibility study** (the larger research workstream) — does a
held-out-stable, safety-relevant dynamics-invariant structure exist (fixed
cohort splits, synthetic recovery controls, typed e4/e5 generator analysis,
precision pairs, adversarial discrimination)? This is the only path to a gate
that discriminates; the §6.3 report shows threshold tuning cannot get there.
5. **Open uncertainties still needing a ruling** (Fable notes §4, unchanged):
general-pack `‖·‖_G` convention; structurally-empty `spatial_foreign` channel;
hard-break turn ownership; malformed-F/gate-routing boundary. Carry into the ADR.
---
## 5. Verification (run log: `docs/audit/artifacts/adr-0246-slice1-hardened-runlog.txt`)
- §6.1/§6.2 eval matrix → 14/14, `all_passed=True`.
- ADR-0246 suites (admission, egress wiring, induced-action, path-ledger incl.
raw-sneak hardening, geometric suite, mismatch diagnostic) → **80 passed**.
- Egress wiring + all D4 gate surfaces (wave/runtime/eval/`test_identity_gate`) →
**47 passed** — flag-off byte-identity confirmed (D4 gate unchanged).
- `uv run core test --suite smoke -q`**176 passed** (post-serve-wiring).
- §6.3 discrimination report → the honest numbers in §3 above.

View file

@ -0,0 +1,111 @@
{
"cohorts": {
"adversarial_n": 8,
"held_out_n": 12,
"train_n": 13
},
"cross_cohort_cosine_null_distribution": {
"mean": 0.377394,
"n_trials": 200,
"p95": 0.599818
},
"cross_cohort_cosine_percentile_in_null": 0.87,
"cross_cohort_top2_cosine_similarity": 0.524901,
"discrimination_auc_adversarial_vs_heldout": 0.489583,
"discrimination_auc_ci95": [
0.208333,
0.770833
],
"held_out_eigenvalues": [
79.571248,
20.218919,
7.368282,
3.067749,
1.251647,
1.014757,
0.487365,
0.269996,
0.000952,
5.4e-05
],
"held_out_stability_null_percentile_floor": 0.95,
"held_out_variance_explained_top_2": 0.881142,
"method": {
"generator_proxy": "bivector (grade-2) coefficient block, 10 planes",
"note": "approximates the Lie generator to first order; exact for single-plane simple rotors/boosts, approximate for compound multi-generator turns; no scipy / matrix-log dependency"
},
"null_calibration_sample_size": 12,
"plane_energy_fractions": {
"held_out": {
"e12": 0.197125,
"e13": 0.130823,
"e14": 0.068146,
"e15": 0.112533,
"e23": 0.10294,
"e24": 0.123708,
"e25": 0.07482,
"e34": 0.004372,
"e35": 0.143569,
"e45": 0.041963
},
"train": {
"e12": 0.16094,
"e13": 0.082142,
"e14": 0.12553,
"e15": 0.050535,
"e23": 0.088179,
"e24": 0.168982,
"e25": 0.025171,
"e34": 0.03812,
"e35": 0.12034,
"e45": 0.140062
}
},
"precision_transport": {
"max_bivector_delta": 6.86e-07,
"significant": false
},
"recovery_controls": {
"method_recovers_true_structure": true,
"null_distribution": {
"mean": 0.382094,
"n_trials": 200,
"p50": 0.369315,
"p95": 0.60089
},
"positive_control_cross_cohort_cosine": 0.999463,
"positive_control_percentile_in_null": 1.0,
"sample_size": 12
},
"residual_from_train_top2_subspace": {
"adversarial": {
"mean": 0.817659
},
"held_out": {
"mean": 0.74434
},
"train": {
"mean": 0.656085
}
},
"schema_version": "adr_0246_grounding_feasibility_v1",
"train_eigenvalues": [
17.063268,
8.003419,
0.574088,
0.435995,
0.187462,
0.031598,
0.014257,
0.004931,
0.003561,
0.00118
],
"train_variance_explained_top_2": 0.95239,
"verdict": {
"held_out_stable_structure_found": false,
"honest_finding": "NULL (n_train=13, n_held_out=12): the top-2 generator-proxy subspace found on TRAIN does NOT reliably reproduce on the independently-collected HELD-OUT cohort \u2014 cosine similarity 0.52 sits at only the 87th percentile of what two INDEPENDENT pure-noise cohorts of the same size produce by chance (need >= 95th) and/or does not clear the discrimination bar (AUC 0.49, 95% CI [0.21, 0.77]). This is consistent with \u2014 and sharpens \u2014 the D4/slice-0/\u00a76.3 finding at the GENERATOR level (not just the induced-action level): benign cognition does not have a small, stable, cohort-independent generator subspace detectable at this sample size. Threshold tuning on the current pack cannot produce a discriminating gate; this feasibility study does not find grounds to draft a revised ADR-0246 implementation contract. A much larger cohort (this study used n<=13 per real cohort) would be needed to rule out a real but subtle effect, rather than to overturn this null.",
"recovery_method_validated": true,
"safety_relevant": false
}
}

View file

@ -0,0 +1,45 @@
ADR-0246 slice-1 COMPLETION — final verification run log
branch: feat/adr-0246-slice1-complete (stacked on slice1-hardened; full Ring-1 stack)
pre-commit HEAD: 47e7eb4e65703b186e4cbfcccd0add25b625b0fa
=== §6.1/§6.2 eval harness ===
[geometric_suite]
PASS identity_versor
PASS inplane_pi_inversion_e12
PASS inplane_90deg_permutation_e12
PASS mild_inplane_drift_e12_0.02
PASS alien_tilt_e14_1.5
PASS boost_e15_1.0
PASS near_singular_gram
PASS malformed_f_nan
PASS malformed_f_wrong_shape
[path_suite]
PASS lawful_near_identity_sequence
PASS small_rotations_accumulate_to_session_refusal
PASS interleaved_refuse_admit
PASS hard_break_on_pack_change
PASS raw_product_differs_from_lawful
14/14 cases passed; all_passed=True
placeholders (uncertified): {'epsilon_turn': 0.1, 'epsilon_session': 0.3, 'note': 'UNCERTIFIED — D4 Phase 3 certified only gamma_id; ε not calibrated'}
=== §11 grounding-feasibility (live) — summary of artifact ===
cohorts: {'adversarial_n': 8, 'held_out_n': 12, 'train_n': 13}
recovery: positive_cosine= 0.999463 pctile= 1.0 null_p95= 0.60089
real: cosine= 0.524901 pctile= 0.87
auc= 0.489583 ci= [0.208333, 0.770833]
verdict: {'held_out_stable_structure_found': False, 'recovery_method_validated': True, 'safety_relevant': False}
=== pytest: ALL ADR-0246 suites + adjacent D4 identity + telemetry ===
........................................................................ [ 31%]
........................................................................ [ 63%]
........................................................................ [ 94%]
............ [100%]
228 passed in 131.10s (0:02:11)
=== uv run core test --suite smoke -q ===
........................................................................ [ 81%]
................................ [100%]
176 passed in 130.16s (0:02:10)

View file

@ -0,0 +1,137 @@
{
"cohorts": {
"adversarial": 8,
"benign": 13,
"synthetic_near_identity": 5
},
"policy": {
"calibrated": false,
"epsilon_turn": 0.1,
"gamma_id": 0.2126624458513829,
"note": "gamma_id certified (D4 Phase 3); all other bounds are UNCERTIFIED placeholders",
"orth_tol": 1e-06,
"s_min": 0.0,
"tau_max": 0.2126624458513829
},
"rates": {
"adversarial_detection_rate": 1.0,
"benign_pass_rate": 0.0,
"false_refusal_rate": 1.0,
"synthetic_near_identity_pass_rate": 1.0
},
"representative_benign_refusals": [
{
"d_stab": 9.7988,
"label": "turn_00",
"leakage_rms": 0.7009,
"reasons": [
"d_orth>orth_tol",
"d_stab>epsilon_turn",
"leakage_rms>gamma_id",
"max_leakage>tau_max",
"min_self_alignment<s_min"
]
},
{
"d_stab": 100.9077,
"label": "turn_01",
"leakage_rms": 0.707,
"reasons": [
"d_orth>orth_tol",
"d_stab>epsilon_turn",
"leakage_rms>gamma_id",
"max_leakage>tau_max",
"min_self_alignment<s_min"
]
},
{
"d_stab": 2.0408,
"label": "turn_02",
"leakage_rms": 0.6904,
"reasons": [
"d_orth>orth_tol",
"d_stab>epsilon_turn",
"leakage_rms>gamma_id",
"max_leakage>tau_max"
]
},
{
"d_stab": 0.5397,
"label": "turn_03",
"leakage_rms": 0.296,
"reasons": [
"d_orth>orth_tol",
"d_stab>epsilon_turn",
"leakage_rms>gamma_id",
"max_leakage>tau_max"
]
},
{
"d_stab": 6.8622,
"label": "turn_04",
"leakage_rms": 0.7453,
"reasons": [
"d_orth>orth_tol",
"d_stab>epsilon_turn",
"leakage_rms>gamma_id",
"max_leakage>tau_max",
"min_self_alignment<s_min"
]
},
{
"d_stab": 0.8078,
"label": "turn_05",
"leakage_rms": 0.1443,
"reasons": [
"d_orth>orth_tol",
"d_stab>epsilon_turn"
]
}
],
"runtime": {
"report_wall_seconds": 51.037
},
"schema_version": "adr_0246_discrimination_v1",
"separation": {
"adversarial_d_stab": {
"max": 2.828427,
"mean": 1.549944,
"min": 0.459698,
"n": 8
},
"adversarial_leakage_rms": {
"max": 0.575904,
"mean": 0.222654,
"min": 0.0,
"n": 8
},
"benign_d_stab": {
"max": 228.14348,
"mean": 27.779325,
"min": 0.149209,
"n": 13
},
"benign_leakage_rms": {
"max": 0.814236,
"mean": 0.552724,
"min": 0.144291,
"n": 13
},
"d_stab_auc_adv_vs_benign": 0.375,
"d_stab_auc_ci95": [
0.153846,
0.625
],
"leakage_rms_auc_adv_vs_benign": 0.182692,
"leakage_rms_auc_ci95": [
0.038462,
0.394471
]
},
"verdict": {
"benign_usable_at_this_policy": false,
"claims_language": "lawfulness relative to the declared frozen frame \u2014 NOT semantic inalienability of the value labels",
"gate_discriminates_benign_from_adversarial": false,
"honest_finding": "The \u00a73.7 admit surface on the declared placeholder frame refuses benign and adversarial versors alike: benign false-refusal rate is 1.00 and d_stab does not separate the classes (AUC 0.38, 95% CI [0.15, 0.62]). A gate that refuses everything trivially 'detects' every attack but is not a discriminator. This reproduces the D4 / slice-0 finding \u2014 live benign cognition does not preserve span(e1,e2,e3) \u2014 at the fuller \u00a73.7 surface. The gate must stay default-off; usable separation requires the \u00a711 dynamics-grounding work, not threshold tuning."
}
}

View file

@ -0,0 +1,45 @@
ADR-0246 slice-1 — Opus audit + hardening run log
branch: feat/adr-0246-slice1-hardened (stacked on feat/adr-0246-slice1-scaffold)
pre-commit HEAD: ed54dddacb8c1f282dedbb85364b6e999139632e
=== §6.1/§6.2 eval matrix ===
[geometric_suite]
PASS identity_versor
PASS inplane_pi_inversion_e12
PASS inplane_90deg_permutation_e12
PASS mild_inplane_drift_e12_0.02
PASS alien_tilt_e14_1.5
PASS boost_e15_1.0
PASS near_singular_gram
PASS malformed_f_nan
PASS malformed_f_wrong_shape
[path_suite]
PASS lawful_near_identity_sequence
PASS small_rotations_accumulate_to_session_refusal
PASS interleaved_refuse_admit
PASS hard_break_on_pack_change
PASS raw_product_differs_from_lawful
14/14 cases passed; all_passed=True
placeholders (uncertified): {'epsilon_turn': 0.1, 'epsilon_session': 0.3, 'note': 'UNCERTIFIED — D4 Phase 3 certified only gamma_id; ε not calibrated'}
=== all ADR-0246 tests + adjacent D4 identity surfaces ===
........................................................................ [ 57%]
..................................................... [100%]
125 passed in 53.98s
=== uv run core test --suite smoke -q ===
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
176 passed, 1 warning in 132.38s (0:02:12)
=== §3.7 egress serve wiring (Steps 2.1/2.2) verification ===
egress wiring + all D4 gate surfaces (byte-identity):
............................................... [100%]
47 passed in 54.37s
smoke POST serve-wiring:
................................ [100%]
176 passed in 133.41s (0:02:13)

View file

@ -0,0 +1,38 @@
ADR-0246 slice-1 scaffold — local run log
branch: feat/adr-0246-slice1-scaffold
base: feat/adr-0246-path-ledger (contains §3 primitives + §3.4/3.5 ledger); all descend from main @ 04d67ca5
commit (pre-scaffold-commit HEAD): 6efe4ad80cc9a4914fc97e0e51ec92c1dd43ec72
python: Python 3.12.13
=== §6.1/§6.2 eval harness: python -m evals.adr_0246_geometric_suite ===
[geometric_suite]
PASS identity_versor
PASS inplane_pi_inversion_e12
PASS inplane_90deg_permutation_e12
PASS mild_inplane_drift_e12_0.02
PASS alien_tilt_e14_1.5
PASS boost_e15_1.0
PASS near_singular_gram
PASS malformed_f_nan
PASS malformed_f_wrong_shape
[path_suite]
PASS lawful_near_identity_sequence
PASS small_rotations_accumulate_to_session_refusal
PASS interleaved_refuse_admit
PASS hard_break_on_pack_change
PASS raw_product_differs_from_lawful
14/14 cases passed; all_passed=True
placeholders (uncertified): {'epsilon_turn': 0.1, 'epsilon_session': 0.3, 'note': 'UNCERTIFIED — D4 Phase 3 certified only gamma_id; ε not calibrated'}
=== pytest: ADR-0246 suites + adjacent identity surfaces ===
........................................................................ [ 63%]
.......................................... [100%]
114 passed in 52.42s
=== uv run core test --suite smoke -q ===
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
176 passed, 1 warning in 130.75s (0:02:10)

View file

@ -39,6 +39,35 @@ Do **not** insert Rings 13 into active D4 commits.
---
## 0a. Post-D4 execution sequencing (actual — 2026-07-17)
D4 closed and was ratified; this brief is now the live plan. The R&D assessment's
one-shot "build the whole Ring-1 gate machinery" is being executed as small,
verified units, and the brief's own **§11 semantic-grounding question was promoted
to run as a consumer of the §3 apparatus** (not a re-sequenced blocker), because
D4 Phase 3 + slice 0 proved no fixed spatial frame is dynamically stabilized —
building a lawfulness gate on the declared frame before knowing whether *any*
structure is stabilized would instrument lawfulness on a frame the dynamics ignore
(the "instruments ≠ meaning" trap, §2 / §11).
| Unit | Scope | Status |
|------|-------|--------|
| **Slice 0** — mismatch diagnostic | evidence-only classification of the benign mismatch (foreign leakage vs in-span-unlawful vs numerical vs path vs semantic-coupling-absent) | **merged** `main` (quarantined diagnostic artifact); found: structural e4/e5 foreign leakage, declared frame dynamically unspecial |
| **§3 primitives** | pure `A(F)`, `d_orth`, `d_stab` vs locked `H_id={I}`, typed residual channels in `core/physics/identity_manifold.py` + `identity_action.py`; slice-0 eval rewired to consume them (single source of truth) | **committed** `feat/adr-0246-induced-action-primitives` (RED→GREEN, off-serving, flag untouched) — awaiting review |
| **§3.4/§3.5 path ledger** | lawful-only composition + hard breaks: `PathBudget`, `IdentityChainScope`, `IdentityPathLedger`, `advance_identity_path` in `identity_action.py`; refused turns = break markers (never soft-projected `I`); scope change = hard break onto new chain | **committed** `feat/adr-0246-path-ledger` (RED→GREEN, off-serving), stacked on primitives — awaiting review |
| **§6.1/§6.2 eval matrix (scaffold)** (this unit) | runnable synthetic geometric + path/holonomy suites (`evals/adr_0246_geometric_suite/`), every §6.1/§6.2 case pinned; malformed-F fail-closed (`MalformedVersorError`) | **draft scaffold** `feat/adr-0246-slice1-scaffold` (14/14 eval cases + 114 identity-surface tests + smoke green) — awaiting Opus/Shay audit (`docs/handoff/adr-0246-slice1-scaffold-notes.md`) |
| **§3.7 gate admit surface + §6.3 discrimination** (Opus audit+hardening) | `AdmissionPolicy`/`evaluate_admission` (§3.7 pure surface); wired into `identity.py`/`chat/runtime.py` behind new default-off `identity_action_surface` (byte-identical flag-off, admit-or-abstain, no corrector); §6.3 discrimination report | **committed** `feat/adr-0246-slice1-hardened` — audit PASS, honest finding: gate refuses benign+adversarial alike (AUC 0.375, benign d_stab 18× adversarial), stays off; awaiting Shay ratification (`docs/audit/adr-0246-slice1-opus-audit-and-hardening.md`) |
| **§4.1/§4.2 telemetry + path serve integration** (completion pass) | `IdentityActionRecord` (full digests, `policy_version=version_id()`, multi-condition `refusal_reason`); `manifold_content_digest` + geometry/gate version ids; §3.4-step-2 `admitted` gate on the ledger; `advance_session_identity_path` observe-only serve wiring (same flags, instance lifetime = session boundary); telemetry emits `identity_action_*`/`identity_path_*` keys only when the paths ran | **committed** `feat/adr-0246-slice1-complete` — flag-off byte-identical; all suites green |
| **§11 grounding-feasibility** (completion pass) | fixed TRAIN(13)/HELD-OUT(12)/ADVERSARIAL(8) splits; bivector generator proxy (numpy-only); **sample-size-calibrated null** (200 noise-pair trials at real n) + shared-basis positive recovery control; precision pairs; per-plane energy | **DONE — honest NULL, method validated**: positive control 0.9995 (100th pctile of null) but real cross-cohort cosine 0.52 = 87th pctile of chance; AUC 0.49; no stable generator subspace at this n. Artifact: `docs/audit/artifacts/adr-0246-grounding-feasibility-report.json` |
| **ADR-0246 body + acceptance packet** | `docs/adr/ADR-0246-induced-identity-action-and-path-integrity.md` (**Proposed**; F1 semantics, ‖·‖_G convention, turn-ownership + refusal_reason rulings requested; binding claims language; honest §6.3 + §11 numbers; machine-readable operational-status block); packet `docs/audit/adr-0246-acceptance-packet-2026-07-17.md` §8 **RULING PENDING** | **committed** — no self-Accept; awaiting Shay ruling |
Nothing in the reordering relaxes a §7 non-goal: no `C_id` corrector, no `H_id`
enlargement, no pack/axis redesign, no gate activation. The §11 grounding study
remains *feasibility only* until it produces a held-out-stable, safety-relevant
candidate (per the D4 ratification's activation prerequisites).
---
## 1. Authority documents
| Doc | Role |

View file

@ -0,0 +1,132 @@
# ADR-0246 Slice-1 Scaffold — Handoff Notes (Fable 5 bounded autonomous draft)
**Status:** DRAFT SCAFFOLD ONLY — not a PR, not merged, no status flip, no `main`
push. For review by Opus 4.8 + Joshua Shay before anything proceeds toward `main`.
**Branch:** `feat/adr-0246-slice1-scaffold` (unmerged).
**D4 gate (directive stop-condition #3):** PASSED — D4 is closed. Both acceptance
packets are on `main` (`docs/audit/adr-024{4,5}-acceptance-packet-2026-07-17.md`);
ADR-0244 status line is `Accepted — ratified by Joshua Shay 2026-07-17`; `main @
04d67ca5`. Proceeded.
**Stop condition reached:** #1 — all four build steps complete and the full
§6.1 + §6.2 matrix passes locally (smoke + new tests + eval harness), with results
written to `docs/audit/artifacts/adr-0246-slice1-scaffold-runlog.txt` (not asserted
from memory). No §3/§7 non-goal had to be violated; no calibration numbers were
invented into the modules (see Placeholders).
---
## 1. What was built (directive steps 14)
| Step | Deliverable | Where |
|------|-------------|-------|
| 1 | `induced_action(F)`, `d_orth`, typed residual energy (§3.1/3.2/3.6), pure f64 | `core/physics/identity_manifold.py` |
| 2 | `H_id={I}` policy (`IdentityStabilizer`), `d_stab`, lawful-only path composition + hard-break ledger (§3.3§3.5) | `core/physics/identity_action.py` |
| 3 | Runnable §6.1 synthetic geometric suite + §6.2 path/holonomy suite | `evals/adr_0246_geometric_suite/` |
| 4 | Unit pins for every synthetic case (fail loudly on the exact expected) | `tests/test_adr_0246_{induced_action,path_ledger,geometric_suite}.py` |
### Reuse note (transparent for audit)
Steps 12 are the **already-verified** work from earlier this session, reused
rather than re-derived (RED-first TDD, off-serving):
- `feat/adr-0246-induced-action-primitives` — §3 primitives (commit `4941cf18`)
- `feat/adr-0246-path-ledger` — §3.4/3.5 ledger (commit `6efe4ad8`, stacked)
`feat/adr-0246-slice1-scaffold` is stacked on top of those, so its history carries
both commits (all descend from `main @ 04d67ca5`). The two earlier branches are
therefore **subsumed** by this scaffold and can be pruned if the reviewers prefer
the single-branch deliverable. This scaffold additionally adds: the malformed-F
guard (`MalformedVersorError`), the §6.1/§6.2 eval harness, the extra §6.1 pins,
the run log, and these notes.
---
## 2. Hard-constraint compliance (directive "Hard constraints while building")
- [x] `H_id = {I}` only — `IdentityStabilizer.singleton`; never enlarged; never
soft-projects an unlawful `A` onto `I` (refused turns are break markers).
Pinned: `test_refused_turn_is_break_and_excluded`.
- [x] Path composed from lawful/certified actions only — never raw `A_t`.
`advance_identity_path` composes only turns with `d_stab ≤ ε_turn`; refused/
ill-conditioned turns get a `path_break` marker (never an identity stand-in).
Forensic contrast pinned: `test_raw_product_differs_from_lawful`.
- [x] No nonzero geometric `C_id` / conjugate corrector — admit-or-abstain only.
Nothing in the modules rewrites `F` or `A`.
- [x] `chat/runtime.py`, flag defaults, and D4 gate wiring **untouched**. Verified:
`test_gate_flag_and_bound_untouched` (flag default-off, `_WAVE_LEAKAGE_BOUND`
unchanged); A-04 quarantine pinned by `test_*_is_pure_offserving` /
`test_suite_is_offserving`.
- [x] No discrimination report, ADR-0246 body, or acceptance-packet language
written. No "semantic inalienability" / marketing claim drafted — see §5 TODO.
- [x] `docs/handoff/ADR-0244-D4-IMPLEMENTATION-PLAN.md` **not modified**.
---
## 3. Placeholder values used (directive: list every one + why)
| Placeholder | Value | Where | Why it is a placeholder |
|-------------|-------|-------|--------------------------|
| `epsilon_turn` | 0.1 | `evals/adr_0246_geometric_suite` `PLACEHOLDER_EPSILON_TURN`; test fixtures | **UNCERTIFIED.** D4 Phase 3 certified only `γ_id = 0.2126624458513829`. The two-level path budget (§3.4) is not yet calibrated. Value chosen only to exercise the mechanism (small single-turn drift admits; a 90° rotation refuses). NOT baked into any serve/module default — `PathBudget` is always caller-supplied. |
| `epsilon_session` | 0.3 | same | **UNCERTIFIED.** Same status; chosen so ~7 steps of a 0.05-rad rotation accumulate past it, demonstrating the accumulation guard. Not a policy value. |
| `_NONZERO` = 0.05 | 0.05 | eval harness | Not a calibration number — a "clearly nonzero" marker for the ">0" rows of the §6.1 table (d_stab, leakage). |
| test construction angles (0.02, 0.05, 1.0, 1.5, π/2, π) | — | tests/evals | Case constructions, not policy. Chosen to realize the exact §6.1/§6.2 geometric signatures. |
**Explicitly NOT invented:** `γ_id` (already certified, unchanged), `τ_max`,
`s_min`. The per-turn admit surface that would consume these (§3.7) is **not built
in this scaffold** — that is the gate-wiring unit, deliberately out of scope, so no
placeholder was needed for them.
---
## 4. Uncertainties in §5§7 (directive: list anything you were unsure how to satisfy)
1. **§3.2 general-pack `‖·‖_G` convention.** The brief fixes `d_stab = ‖AH‖_G`
but leaves the general-pack weighted-norm convention to "ADR-0246 proper." I
implemented `‖M‖_G = ‖G^{1/2} M G^{-1/2}‖_F` (metric-consistent; reduces exactly
to Frobenius at `G=I`, which is the only shipped pack). **Needs review/ratification.**
2. **§3.6 `spatial_foreign` channel.** For the default pack (support = e1/e2/e3) it
is structurally ~0 (projection removes in-span components). Implemented generally
(residual energy on grade-1 spatial slots outside the axis support) but it cannot
fire until a non-default pack exists. Untested against a real non-default pack.
3. **§4.1 `IdentityActionRecord` full telemetry** (per-turn `field_digest`,
`record_digest`, gate/policy versions, admitted/refusal_reason) is **not built**;
only the §4.2 `IdentityPathLedger` (with `ledger_digest`, `chain_id`) is. The
per-turn record belongs to the gate-surface/telemetry unit (§3.7), out of scope
here. `advance_identity_path` returns a lightweight per-turn dict, not the full record.
4. **§6.1 "Malformed F → never silent legacy when wave field was supplied."** The
"silent legacy" clause is about the D4 gate's dual-mode fallback in
`identity.py` (untouched here, owned by D4). This scaffold adds a fail-closed
`MalformedVersorError` at the *pure primitive* boundary (`induced_action` /
`typed_residual_energy`). Whether the gate should route malformed-F to this same
typed error is a gate-wiring decision, deferred.
5. **Path budget semantics under a hard break.** I treated a scope change as: start
a fresh chain, and the triggering turn is turn 1 of the new chain (its own action
composes into the fresh `I`). The brief (§3.5) specifies a new `chain_id` and
that the old path is not continued, but does not pin whether the boundary turn
belongs to the old or new chain. Chose new-chain. **Confirm.**
---
## 5. Explicitly deferred to Opus/human review (NOT written here)
> **TODO: Opus/human review** — the following were intentionally left undone per
> the directive; do not treat their absence as an oversight:
- The **discrimination report** (§6.3): benign/adversarial rates, false-refusal,
ablations, CI-bounded separation. Requires the gate-surface + live cohorts.
- The **ADR-0246 body** and any **acceptance-packet** language.
- Any **claim about what the axes mean** ("semantic inalienability", grounding).
The §11 grounding-feasibility study (fixed cohort splits, synthetic recovery
controls, generator analysis, precision pairs, adversarial discrimination) is the
first consumer of these primitives and is **not** part of this scaffold.
- The **gate admit-surface wiring** into `IdentityScore` (§3.7) and the calibration
of `ε_turn`/`ε_session`.
---
## 6. Verification (see run log for actual output)
`docs/audit/artifacts/adr-0246-slice1-scaffold-runlog.txt`:
- `python -m evals.adr_0246_geometric_suite` → 14/14 cases passed, `all_passed=True`.
- pytest ADR-0246 suites + adjacent D4 identity surfaces → 114 passed.
- `uv run core test --suite smoke -q` → (appended to the run log).
No PR. No merge. No status flip. Report back to Shay/Opus for the audit that
decides what, if anything, proceeds toward `main`.

View file

@ -0,0 +1,268 @@
"""ADR-0246 §6.3 discrimination report — does the §3.7 admit surface separate
benign traffic from adversarial reshuffles? (honest numbers, no marketing.)
This runs the pure ADR-0246 §3.7 admit surface (``evaluate_admission``, locked
``H_id={I}``, placeholder thresholds) over three cohorts and reports the numbers
the preflight §6.3 / §10 acceptance criteria demand:
* benign pass rate, false refusal rate
* adversarial / reshuffle detection rate
* per-axis leakage / self-alignment distributions
* ``d_stab`` (and ``leakage_rms``) separation as ROC-AUC with a bootstrap 95% CI
* runtime cost (µs) of the A(F) admission path
* representative benign-refusal examples
**Honesty constraint (§10 #9).** The claim this can support is *"lawfulness
relative to the declared frozen frame"* — NEVER *"semantic inalienability of the
value labels."* The default pack axes are placeholder basis vectors; D4 + slice-0
already established that live benign versors do **not** preserve them. So the
expected and reported finding is that this gate refuses benign and adversarial
alike (no usable separation) and must stay off. The report states that plainly;
it does not frame a refuse-all as a "detector."
Off-serving: pure primitives + a live-versor collector that lazily imports
``chat.runtime`` (A-04 quarantine intact). Deterministic given the fixed probe
sequences and bootstrap seed.
"""
from __future__ import annotations
from typing import Any, Sequence
import numpy as np
from algebra.cl41 import N_COMPONENTS
from core.physics.identity_manifold import IdentityManifoldGeometry
from core.physics.identity_action import (
AdmissionPolicy,
evaluate_admission,
)
BOOTSTRAP_SEED = 20260717
BOOTSTRAP_RESAMPLES = 2000
# grade-2 bivector plane indices
_E12, _E13, _E14, _E15, _E23, _E24, _E25 = 6, 7, 8, 9, 10, 11, 12
def default_geometry() -> IdentityManifoldGeometry:
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
def _rotor(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _boost(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cosh(theta / 2.0)
r[biv] = np.sinh(theta / 2.0)
return r
def adversarial_cohort() -> list[tuple[str, np.ndarray]]:
"""Geometric attacks + in-span reshuffles the gate is *designed* to catch."""
return [
("tilt_e14_1.5", _rotor(_E14, 1.5)),
("tilt_e24_1.0", _rotor(_E24, 1.0)),
("boost_e15_1.2", _boost(_E15, 1.2)),
("boost_e25_1.0", _boost(_E25, 1.0)),
("inversion_e12_pi", _rotor(_E12, np.pi)),
("inversion_e13_pi", _rotor(_E13, np.pi)),
("permutation_e12_halfpi", _rotor(_E12, np.pi / 2.0)),
("permutation_e23_halfpi", _rotor(_E23, np.pi / 2.0)),
]
def synthetic_near_identity_cohort() -> list[tuple[str, np.ndarray]]:
"""Positive control: versors that DO nearly preserve the frame (should admit)."""
return [
(f"near_id_e12_{t}", _rotor(_E12, t)) for t in (0.0, 0.005, 0.01)
] + [
(f"near_id_e13_{t}", _rotor(_E13, t)) for t in (0.0, 0.005)
]
def collect_live_benign(limit: int | None = None) -> list[tuple[str, np.ndarray]]:
"""Real benign ``final_state.F`` versors from a fresh empty-vault runtime.
Reuses the slice-0 collector (instance-local recording; serve untouched;
lazy ``chat.runtime`` import). This is the honest benign cohort the same
live distribution D4 Phase 3 measured as NOT preserving the frame.
"""
from evals.adr_0246_mismatch_diagnostic import collect_live_versors
from evals.adr_0244_gamma_calibration import LIVE_PROBE_SEQUENCE
versors = collect_live_versors(LIVE_PROBE_SEQUENCE)
return versors[:limit] if limit else versors
# --- statistics (numpy-only; deterministic) -----------------------------------
def _roc_auc(positive: Sequence[float], negative: Sequence[float]) -> float:
"""AUC = P(score(pos) > score(neg)) with ties at 0.5 (rank/Mann-Whitney)."""
pos = np.asarray(positive, dtype=np.float64)
neg = np.asarray(negative, dtype=np.float64)
if pos.size == 0 or neg.size == 0:
return float("nan")
allv = np.concatenate([pos, neg])
order = np.argsort(allv, kind="mergesort")
ranks = np.empty(allv.size, dtype=np.float64)
ranks[order] = np.arange(1, allv.size + 1, dtype=np.float64)
# average ranks for ties
_, inv, counts = np.unique(allv, return_inverse=True, return_counts=True)
sums = np.zeros(counts.size)
np.add.at(sums, inv, ranks)
ranks = (sums / counts)[inv]
r_pos = ranks[: pos.size].sum()
return float((r_pos - pos.size * (pos.size + 1) / 2.0) / (pos.size * neg.size))
def _auc_bootstrap_ci(
positive: Sequence[float], negative: Sequence[float]
) -> tuple[float, float]:
pos = np.asarray(positive, dtype=np.float64)
neg = np.asarray(negative, dtype=np.float64)
if pos.size == 0 or neg.size == 0:
return (float("nan"), float("nan"))
rng = np.random.default_rng(BOOTSTRAP_SEED)
aucs = np.empty(BOOTSTRAP_RESAMPLES, dtype=np.float64)
for i in range(BOOTSTRAP_RESAMPLES):
rp = rng.choice(pos, size=pos.size, replace=True)
rn = rng.choice(neg, size=neg.size, replace=True)
aucs[i] = _roc_auc(rp, rn)
return (float(np.percentile(aucs, 2.5)), float(np.percentile(aucs, 97.5)))
def _dist(values: Sequence[float]) -> dict[str, float]:
arr = np.asarray(values, dtype=np.float64)
if arr.size == 0:
return {"n": 0, "min": 0.0, "mean": 0.0, "max": 0.0}
return {
"n": int(arr.size),
"min": round(float(arr.min()), 6),
"mean": round(float(arr.mean()), 6),
"max": round(float(arr.max()), 6),
}
def _evaluate_cohort(
geometry: IdentityManifoldGeometry,
cohort: Sequence[tuple[str, np.ndarray]],
policy: AdmissionPolicy,
) -> list[dict[str, Any]]:
rows = []
for label, versor in cohort:
result = evaluate_admission(geometry, versor, policy)
leak, self_align = geometry.axis_response(versor)
rows.append({
"label": label,
"admitted": result.admitted,
"refusal_reasons": list(result.refusal_reasons),
"d_stab": result.d_stab,
"leakage_rms": result.leakage_rms,
"min_self_alignment": result.min_self_alignment,
"per_axis_leakage": [float(x) for x in leak],
"per_axis_self_align": [float(x) for x in self_align],
})
return rows
def build_discrimination_report(
benign: Sequence[tuple[str, np.ndarray]] | None = None,
*,
geometry: IdentityManifoldGeometry | None = None,
policy: AdmissionPolicy | None = None,
) -> dict[str, Any]:
"""Run the §3.7 surface over all cohorts and report honest §6.3 numbers.
``benign`` defaults to the live-collected cohort (slow spins up a runtime);
pass an explicit cohort for a fast/offline report.
"""
geometry = geometry or default_geometry()
policy = policy or AdmissionPolicy.placeholder_default()
if benign is None:
benign = collect_live_benign()
adversarial = adversarial_cohort()
control = synthetic_near_identity_cohort()
b_rows = _evaluate_cohort(geometry, benign, policy)
a_rows = _evaluate_cohort(geometry, adversarial, policy)
c_rows = _evaluate_cohort(geometry, control, policy)
def _rate(rows, key, want):
return round(sum(1 for r in rows if r[key] is want) / len(rows), 6) if rows else 0.0
benign_pass = _rate(b_rows, "admitted", True)
adversarial_detect = _rate(a_rows, "admitted", False)
control_pass = _rate(c_rows, "admitted", True)
b_dstab = [r["d_stab"] for r in b_rows]
a_dstab = [r["d_stab"] for r in a_rows]
b_leak = [r["leakage_rms"] for r in b_rows]
a_leak = [r["leakage_rms"] for r in a_rows]
dstab_auc = _roc_auc(a_dstab, b_dstab) # adversarial as positive class
dstab_ci = _auc_bootstrap_ci(a_dstab, b_dstab)
leak_auc = _roc_auc(a_leak, b_leak)
leak_ci = _auc_bootstrap_ci(a_leak, b_leak)
# gate "discriminates" only if AUC CI lower bound is clearly above chance (0.5)
gate_discriminates = bool(np.isfinite(dstab_ci[0]) and dstab_ci[0] > 0.6)
false_refusal_rate = round(1.0 - benign_pass, 6)
return {
"schema_version": "adr_0246_discrimination_v1",
"policy": {
"calibrated": policy.calibrated,
"orth_tol": policy.orth_tol,
"epsilon_turn": policy.epsilon_turn,
"gamma_id": policy.gamma_id,
"tau_max": policy.tau_max,
"s_min": policy.s_min,
"note": "gamma_id certified (D4 Phase 3); all other bounds are UNCERTIFIED placeholders",
},
"cohorts": {"benign": len(b_rows), "adversarial": len(a_rows), "synthetic_near_identity": len(c_rows)},
"rates": {
"benign_pass_rate": benign_pass,
"false_refusal_rate": false_refusal_rate,
"adversarial_detection_rate": adversarial_detect,
"synthetic_near_identity_pass_rate": control_pass,
},
"separation": {
"d_stab_auc_adv_vs_benign": round(dstab_auc, 6) if np.isfinite(dstab_auc) else None,
"d_stab_auc_ci95": [round(x, 6) if np.isfinite(x) else None for x in dstab_ci],
"leakage_rms_auc_adv_vs_benign": round(leak_auc, 6) if np.isfinite(leak_auc) else None,
"leakage_rms_auc_ci95": [round(x, 6) if np.isfinite(x) else None for x in leak_ci],
"benign_d_stab": _dist(b_dstab),
"adversarial_d_stab": _dist(a_dstab),
"benign_leakage_rms": _dist(b_leak),
"adversarial_leakage_rms": _dist(a_leak),
},
"representative_benign_refusals": [
{"label": r["label"], "d_stab": round(r["d_stab"], 4),
"leakage_rms": round(r["leakage_rms"], 4), "reasons": r["refusal_reasons"]}
for r in b_rows if not r["admitted"]
][:6],
"verdict": {
"gate_discriminates_benign_from_adversarial": gate_discriminates,
"benign_usable_at_this_policy": bool(false_refusal_rate <= 0.05),
"claims_language": "lawfulness relative to the declared frozen frame — NOT semantic inalienability of the value labels",
"honest_finding": (
"The §3.7 admit surface on the declared placeholder frame refuses "
"benign and adversarial versors alike: benign false-refusal rate is "
f"{false_refusal_rate:.2f} and d_stab does not separate the classes "
f"(AUC {dstab_auc:.2f}, 95% CI [{dstab_ci[0]:.2f}, {dstab_ci[1]:.2f}]). "
"A gate that refuses everything trivially 'detects' every attack but "
"is not a discriminator. This reproduces the D4 / slice-0 finding — "
"live benign cognition does not preserve span(e1,e2,e3) — at the fuller "
"§3.7 surface. The gate must stay default-off; usable separation "
"requires the §11 dynamics-grounding work, not threshold tuning."
),
},
}

View file

@ -0,0 +1,35 @@
"""Run the ADR-0246 §6.3 discrimination report and emit it.
Usage: uv run python -m evals.adr_0246_discrimination [out.json]
Collects the live benign cohort (spins up a fresh empty-vault runtime), runs the
§3.7 admit surface over benign + adversarial + synthetic-near-identity cohorts,
and prints the honest rates / separation / verdict. Optionally writes the JSON.
"""
from __future__ import annotations
import json
import sys
import time
from evals.adr_0246_discrimination import build_discrimination_report
def main() -> int:
t0 = time.perf_counter()
report = build_discrimination_report()
report["runtime"] = {"report_wall_seconds": round(time.perf_counter() - t0, 3)}
print(json.dumps(
{k: report[k] for k in ("cohorts", "rates", "separation", "verdict")},
indent=2, sort_keys=True,
))
if len(sys.argv) > 1:
with open(sys.argv[1], "w", encoding="utf-8") as fh:
fh.write(json.dumps(report, indent=2, sort_keys=True) + "\n")
print(f"\nreport written to {sys.argv[1]}")
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,301 @@
"""ADR-0246 §6.1/§6.2 synthetic geometric + path/holonomy eval suite (scaffold).
A runnable, deterministic harness that constructs every case in the preflight
§6.1 synthetic geometric table and §6.2 path/holonomy table, runs the pure
ADR-0246 primitives (induced action ``A(F)``, ``d_orth``, ``d_stab`` vs the locked
singleton ``H_id={I}``, typed residual channels, lawful-only path ledger), and
checks each against its expected geometric signature. Every case reports
``{name, checks, passed}`` and the suite reports an overall ``passed``.
Scope (bounded scaffold draft NOT an accepted ADR):
* Off-serving: imports only ``algebra`` + ``core.physics.identity_{manifold,action}``;
never ``chat.runtime`` (A-04 quarantine).
* ``H_id={I}`` only; refused turns are break markers, never soft-projected ``I``;
the path composes lawful actions only never the raw product.
* No ``C_id`` corrector; admit-or-abstain only.
* The path-suite ε values are UNCERTIFIED PLACEHOLDERS (see
``PLACEHOLDER_EPSILON_*``): D4 Phase 3 certified only ``γ_id``; ε_turn/ε_session
are not yet calibrated. They exist here solely to exercise the mechanism and
are flagged in the run log. Do NOT read them as policy.
No discrimination report, no claims about what the axes *mean* that is
explicitly deferred to Opus/human review (see the slice-1 scaffold notes).
"""
from __future__ import annotations
from typing import Any, Callable
import numpy as np
from algebra.cl41 import N_COMPONENTS
from core.physics.identity_manifold import (
IdentityManifoldGeometry,
ManifoldConditioningError,
MalformedVersorError,
)
from core.physics.identity_action import (
IdentityChainScope,
PathBudget,
advance_identity_path,
raw_path_product,
stabilizer_defect_for_versor,
)
# grade-2 bivector plane indices (grade-2 block starts at index 6)
_E12, _E13, _E14, _E15, _E23, _E24, _E25 = 6, 7, 8, 9, 10, 11, 12
# --- UNCERTIFIED PLACEHOLDERS (flagged; not policy) ---------------------------
# D4 Phase 3 certified γ_id only. ε_turn / ε_session are NOT calibrated; these
# illustrative values merely exercise the two-level path budget mechanism.
PLACEHOLDER_EPSILON_TURN: float = 0.1
PLACEHOLDER_EPSILON_SESSION: float = 0.3
# "clearly nonzero" marker for the >0 rows in the §6.1 table (not a threshold).
_NONZERO = 0.05
_ZERO = 1e-9
def default_geometry() -> IdentityManifoldGeometry:
"""The shipped default declared frame span(e1,e2,e3), Gram = I3."""
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
def rotor(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def boost(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cosh(theta / 2.0)
r[biv] = np.sinh(theta / 2.0)
return r
def identity_versor() -> np.ndarray:
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
def _case(name: str, checks: dict[str, bool]) -> dict[str, Any]:
return {"name": name, "checks": checks, "passed": all(checks.values())}
def _expect_raises(name: str, fn: Callable[[], Any], exc: type[BaseException]) -> dict[str, Any]:
raised = False
try:
fn()
except exc:
raised = True
except Exception: # wrong exception type is a failure
raised = False
return _case(name, {f"raises_{exc.__name__}": raised})
# --- §6.1 synthetic geometric suite -------------------------------------------
def run_geometric_suite(geometry: IdentityManifoldGeometry | None = None) -> list[dict[str, Any]]:
geometry = geometry or default_geometry()
cases: list[dict[str, Any]] = []
# Identity versor → A≈I, ≈0, s≈+1, d_orth≈0, d_stab≈0
v = identity_versor()
a = geometry.induced_action(v)
leak, self_align = geometry.axis_response(v)
cases.append(_case("identity_versor", {
"A_is_identity": bool(np.allclose(a, np.eye(3), atol=1e-12)),
"leakage_zero": max(leak) < _ZERO,
"self_align_plus_one": min(self_align) > 1.0 - _ZERO,
"d_orth_zero": geometry.orthogonality_defect(v) < _ZERO,
"d_stab_zero": stabilizer_defect_for_versor(geometry, v) < _ZERO,
}))
# In-plane π inversion of e1/e2 → ≈0, s(e1)≈-1, s(e3)≈+1, d_stab>0
v = rotor(_E12, np.pi)
leak, self_align = geometry.axis_response(v)
cases.append(_case("inplane_pi_inversion_e12", {
"leakage_zero": max(leak) < _ZERO,
"self_align_e1_minus_one": self_align[0] < -1.0 + _ZERO,
"self_align_e2_minus_one": self_align[1] < -1.0 + _ZERO,
"self_align_e3_plus_one": self_align[2] > 1.0 - _ZERO,
"d_stab_positive": stabilizer_defect_for_versor(geometry, v) > _NONZERO,
}))
# In-plane 90° permutation e1→e2 → ≈0, s(e1)≈0, d_stab>0
v = rotor(_E12, np.pi / 2.0)
leak, self_align = geometry.axis_response(v)
cases.append(_case("inplane_90deg_permutation_e12", {
"leakage_zero": max(leak) < _ZERO,
"self_align_e1_zero": abs(self_align[0]) < _ZERO,
"self_align_e2_zero": abs(self_align[1]) < _ZERO,
"d_stab_positive": stabilizer_defect_for_versor(geometry, v) > _NONZERO,
}))
# Mild in-plane drift step → small d_stab (per-turn passes ε_turn placeholder)
v = rotor(_E12, 0.02)
d_stab = stabilizer_defect_for_versor(geometry, v)
leak, _ = geometry.axis_response(v)
cases.append(_case("mild_inplane_drift_e12_0.02", {
"leakage_zero": max(leak) < _ZERO,
"d_stab_small_but_positive": _ZERO < d_stab < PLACEHOLDER_EPSILON_TURN,
}))
# Alien tilt e14 → >0, null_or_conformal channel fires, boost channel ≈0
v = rotor(_E14, 1.5)
ch = geometry.typed_residual_energy(v)
cases.append(_case("alien_tilt_e14_1.5", {
"leakage_positive": geometry.leakage_rms(v) > _NONZERO,
"null_or_conformal_fires": ch["null_or_conformal"] > _NONZERO,
"boost_like_zero": ch["boost_like"] < _ZERO,
"unclassified_clean": ch["unclassified"] < _ZERO,
}))
# Boost component (e5) → ,s normalized in range, boost channel fires, d_orth>0
v = boost(_E15, 1.0)
ch = geometry.typed_residual_energy(v)
leak, self_align = geometry.axis_response(v)
cases.append(_case("boost_e15_1.0", {
"leakage_in_unit_range": 0.0 <= max(leak) <= 1.0,
"self_align_in_range": all(-1.0 - _ZERO <= s <= 1.0 + _ZERO for s in self_align),
"boost_like_fires": ch["boost_like"] > _NONZERO,
"null_or_conformal_zero": ch["null_or_conformal"] < _ZERO,
"d_orth_positive": geometry.orthogonality_defect(v) > _NONZERO,
}))
# Near-singular Gram (near-parallel axes) → ManifoldConditioningError at build
cases.append(_expect_raises(
"near_singular_gram",
lambda: IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (1.0, 1e-9, 0.0), (0.0, 0.0, 1.0))
),
ManifoldConditioningError,
))
# Malformed F → MalformedVersorError (NaN and wrong-shape)
nan_v = identity_versor()
nan_v[0] = np.nan
cases.append(_expect_raises(
"malformed_f_nan", lambda: geometry.induced_action(nan_v), MalformedVersorError
))
cases.append(_expect_raises(
"malformed_f_wrong_shape",
lambda: geometry.induced_action(np.ones(7, dtype=np.float64)),
MalformedVersorError,
))
return cases
# --- §6.2 path / holonomy suite -----------------------------------------------
def _scope(pack: str = "packA") -> IdentityChainScope:
return IdentityChainScope(
pack_content_digest=pack,
geometry_version="geomV1",
policy_version="polV1(PLACEHOLDER_epsilons)",
session_id="sess1",
biography_epoch=None,
)
def run_path_suite(geometry: IdentityManifoldGeometry | None = None) -> list[dict[str, Any]]:
geometry = geometry or default_geometry()
budget = PathBudget(
epsilon_turn=PLACEHOLDER_EPSILON_TURN,
epsilon_session=PLACEHOLDER_EPSILON_SESSION,
)
gram = geometry.gram
ident = geometry.induced_action(identity_versor())
cases: list[dict[str, Any]] = []
# Sequence of lawful near-I turns → A_path near I; no false path refusal
ledger = None
for _ in range(20):
ledger, _ = advance_identity_path(ledger, _scope(), ident, gram, budget)
cases.append(_case("lawful_near_identity_sequence", {
"path_near_identity": bool(np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12)),
"session_admit": ledger.session_admit,
"no_breaks": ledger.break_count == 0,
"composed_20": ledger.composed_turn_count == 20,
}))
# Small in-plane rotations each < ε_turn → path eventually breaches ε_session
small = geometry.induced_action(rotor(_E12, 0.05))
ledger = None
all_turns_lawful = True
for _ in range(40):
ledger, rec = advance_identity_path(ledger, _scope(), small, gram, budget)
all_turns_lawful = all_turns_lawful and rec["lawful"]
if not ledger.session_admit:
break
cases.append(_case("small_rotations_accumulate_to_session_refusal", {
"each_turn_lawful": all_turns_lawful,
"session_refused": not ledger.session_admit,
"path_d_stab_exceeds_session": ledger.d_stab_path > PLACEHOLDER_EPSILON_SESSION,
}))
# Interleaved refuse + admit → refused turns break, excluded, raw recorded
big = geometry.induced_action(rotor(_E12, np.pi / 2.0))
seq = [ident, big, ident, big, ident]
ledger = None
breaks_pattern = []
for a in seq:
ledger, rec = advance_identity_path(ledger, _scope(), a, gram, budget)
breaks_pattern.append(rec["path_break"])
cases.append(_case("interleaved_refuse_admit", {
"composed_3": ledger.composed_turn_count == 3,
"breaks_2": ledger.break_count == 2,
"break_pattern": breaks_pattern == [False, True, False, True, False],
}))
# Pack digest change → hard break, new chain_id, old path not continued
ledger, _ = advance_identity_path(None, _scope("packA"), ident, gram, budget)
ledger, _ = advance_identity_path(ledger, _scope("packA"), small, gram, budget)
id_a, drifted = ledger.chain_id, ledger.a_path_lawful.copy()
ledger, rec = advance_identity_path(ledger, _scope("packB"), ident, gram, budget)
cases.append(_case("hard_break_on_pack_change", {
"hard_break": rec["hard_break"],
"new_chain_id": ledger.chain_id != id_a,
"old_path_not_continued": not np.allclose(ledger.a_path_lawful, drifted),
"fresh_chain": ledger.composed_turn_count == 1 and ledger.break_count == 0,
}))
# Raw product ≠ lawful product when a refused turn is present (forensic)
seq = [ident, big, ident]
ledger = None
for a in seq:
ledger, _ = advance_identity_path(ledger, _scope(), a, gram, budget)
raw = raw_path_product(seq)
cases.append(_case("raw_product_differs_from_lawful", {
"raw_neq_lawful": not np.allclose(raw, ledger.a_path_lawful),
"lawful_excludes_refused": bool(np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12)),
}))
return cases
def build_suite_report() -> dict[str, Any]:
geometry = default_geometry()
geometric = run_geometric_suite(geometry)
path = run_path_suite(geometry)
all_cases = geometric + path
return {
"schema_version": "adr_0246_geometric_suite_v1",
"declared_frame": ["truthfulness=e1", "coherence=e2", "reverence=e3"],
"stabilizer": "H_id={I} (locked)",
"placeholders": {
"epsilon_turn": PLACEHOLDER_EPSILON_TURN,
"epsilon_session": PLACEHOLDER_EPSILON_SESSION,
"note": "UNCERTIFIED — D4 Phase 3 certified only gamma_id; ε not calibrated",
},
"geometric_suite": geometric,
"path_suite": path,
"case_count": len(all_cases),
"passed_count": sum(1 for c in all_cases if c["passed"]),
"all_passed": all(c["passed"] for c in all_cases),
}

View file

@ -0,0 +1,42 @@
"""Run the ADR-0246 §6.1/§6.2 geometric + path eval suite and emit the report.
Usage: uv run python -m evals.adr_0246_geometric_suite [out.json]
Deterministic, off-serving. Prints a per-case pass/fail summary and the overall
verdict; optionally writes the structured JSON report. Exit code 0 iff every case
passed (so it can gate a run log), 1 otherwise.
"""
from __future__ import annotations
import json
import sys
from evals.adr_0246_geometric_suite import build_suite_report
def main() -> int:
report = build_suite_report()
for suite in ("geometric_suite", "path_suite"):
print(f"\n[{suite}]")
for case in report[suite]:
mark = "PASS" if case["passed"] else "FAIL"
print(f" {mark} {case['name']}")
if not case["passed"]:
for check, ok in case["checks"].items():
if not ok:
print(f"{check}")
print(
f"\n{report['passed_count']}/{report['case_count']} cases passed; "
f"all_passed={report['all_passed']}"
)
print(f"placeholders (uncertified): {report['placeholders']}")
if len(sys.argv) > 1:
with open(sys.argv[1], "w", encoding="utf-8") as fh:
fh.write(json.dumps(report, indent=2, sort_keys=True) + "\n")
print(f"report written to {sys.argv[1]}")
return 0 if report["all_passed"] else 1
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,479 @@
"""ADR-0246 §11 grounding-feasibility study (research, off-serving, evidence-only).
The brief's §11 defers "semantic axis grounding" as a later workstream because
"instruments ≠ meaning." Slice 0 and the §6.3 discrimination report both showed
that NO fixed spatial 3-frame (declared or random) is dynamically preserved by
benign cognition. This study asks the prior, narrower, and answerable question:
Does *any* held-out-stable, low-dimensional structure exist in what the
live versor's generator actually does — independent of which frame we
declare and if so, does it discriminate benign traffic from adversarial
geometric attacks?
This is explicitly a FEASIBILITY STUDY, not an implementation. Per the Opus
handoff (§4c item 4) it is "the only path to a gate that discriminates"; the
brief's own instruction (research-question authority, not this module) is that
only a positive, held-out-stable, safety-relevant finding here would justify
drafting a revised ADR-0246 implementation contract. This module does not
draft one it reports what the data shows, honestly, including a null result.
**Method (fixed cohort splits, no resampling of the same pool):**
* TRAIN benign versors from ``LIVE_PROBE_SEQUENCE`` (D4 Phase 3 / slice-0's
pinned probe set), n13.
* HELD-OUT versors from ``PARAPHRASE_PROBE_SEQUENCE`` (independently worded,
same semantic register), n12. A genuine generalization test: any structure
found on TRAIN must ALSO appear on HELD-OUT, not merely be re-discovered by
refitting the same pool.
* ADVERSARIAL the existing crafted geometric-attack cohort (tilts, boosts,
inversions, permutations), n=8, reused from ``evals.adr_0246_discrimination``.
**Generator proxy (no scipy; numpy-only per the routing instruction).** Rather
than a matrix logarithm, this study uses the versor's own GRADE-2 (bivector)
coefficient vector (Cl(4,1) indices 6..15, 10 dims) as the generator proxy: for
a versor close to a simple exponential ``F = exp(B/2)``, the bivector block of
``F`` is proportional to ``B`` to leading order, and it is EXACT for the single-
plane simple rotors/boosts used throughout D4/ADR-0246 (this is the same
quantity ``versor_plane_occupancy`` already groups by plane in the slice-0
diagnostic). This is an approximation for compound multi-generator turns and is
documented as such not a claim of an exact Lie-algebra recovery.
**Honesty constraint (same as §6.3):** with n13 samples in a 10-dimensional
proxy space, a covariance fit on TRAIN alone is not evidence of structure
almost any small sample admits a low-rank-looking in-sample fit purely from
degrees of freedom. The only evidence this study credits is CROSS-COHORT
agreement: does the dominant direction found on TRAIN also explain variance on
the independently-collected HELD-OUT cohort? A held-out-stable finding is
reported only if it does; a null finding is reported plainly otherwise.
Off-serving; deterministic (fixed RNG seed for synthetic controls; live cohorts
via the existing lazy ``chat.runtime`` collectors never imported by serve).
"""
from __future__ import annotations
from typing import Any, Sequence
import numpy as np
from algebra.cl41 import N_COMPONENTS
from evals.adr_0246_discrimination import (
_auc_bootstrap_ci,
_roc_auc,
adversarial_cohort,
)
from evals.adr_0246_mismatch_diagnostic import (
IDX_E12,
IDX_E13,
IDX_E14,
IDX_E15,
IDX_E23,
IDX_E24,
IDX_E25,
IDX_E34,
IDX_E35,
IDX_E45,
PARAPHRASE_PROBE_SEQUENCE,
collect_live_versors,
)
from evals.adr_0244_gamma_calibration import LIVE_PROBE_SEQUENCE
# Bivector (grade-2) block: 10 planes, indices 6..15 in the 32-component layout.
BIVECTOR_INDICES: tuple[int, ...] = (
IDX_E12, IDX_E13, IDX_E14, IDX_E15, IDX_E23, IDX_E24, IDX_E25, IDX_E34,
IDX_E35, IDX_E45,
)
BIVECTOR_DIM = len(BIVECTOR_INDICES) # 10
_PLANE_NAMES = ("e12", "e13", "e14", "e15", "e23", "e24", "e25", "e34", "e35", "e45")
RECOVERY_CONTROL_SEED = 20260717
POSITIVE_CONTROL_TRUE_RANK = 2
POSITIVE_CONTROL_NOISE_SIGMA = 0.03
N_NULL_TRIALS = 200
# "Held-out stable" requires the real train-vs-held-out cross-cohort cosine to
# exceed this percentile of the SAME-SAMPLE-SIZE null distribution (two
# independent pure-noise cohorts) — i.e. p < 0.05 one-sided that the observed
# agreement arose by chance alone — AND the discrimination AUC-CI lower bound
# to clear chance (reusing evals.adr_0246_discrimination's own 0.6 bar).
HELD_OUT_STABILITY_NULL_PERCENTILE_FLOOR = 0.95
DISCRIMINATION_AUC_CI_FLOOR = 0.6
def bivector_coefficients(versor: np.ndarray) -> np.ndarray:
"""The 10-dim bivector-block generator proxy of a versor (Cl(4,1) indices 6..15)."""
versor = np.asarray(versor, dtype=np.float64)
return np.array([versor[i] for i in BIVECTOR_INDICES], dtype=np.float64)
def bivector_covariance(versors: Sequence[np.ndarray]) -> np.ndarray:
"""Sample covariance of the bivector-proxy vectors (numpy-only, no scipy)."""
coeffs = np.array([bivector_coefficients(v) for v in versors], dtype=np.float64)
if coeffs.shape[0] < 2:
raise ValueError("covariance requires at least 2 samples")
return np.cov(coeffs, rowvar=False)
def principal_directions(cov: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
"""Eigenvalues (descending) and eigenvectors of a covariance matrix via
``np.linalg.eigh`` (exact for real-symmetric; no scipy dependency)."""
eigvals, eigvecs = np.linalg.eigh(cov)
order = np.argsort(eigvals)[::-1]
return eigvals[order], eigvecs[:, order]
def variance_explained(eigvals: np.ndarray, k: int) -> float:
total = float(np.sum(eigvals))
if total <= 0.0:
return 0.0
return float(np.sum(eigvals[:k])) / total
def subspace_residual_fraction(vec: np.ndarray, top_eigvecs: np.ndarray) -> float:
"""Fraction of ``vec``'s energy OUTSIDE span(top_eigvecs) — 0 = fully inside."""
total = float(np.dot(vec, vec))
if total <= 0.0:
return 0.0
projection = top_eigvecs @ (top_eigvecs.T @ vec)
residual = vec - projection
return float(np.dot(residual, residual)) / total
def cross_cohort_top_pc_cosine_similarity(
train_versors: Sequence[np.ndarray], test_versors: Sequence[np.ndarray], *, k: int = 1
) -> float:
"""|cosine similarity| between the top-``k`` principal directions of two
INDEPENDENTLY collected cohorts the actual generalization signal.
A high value means the dominant generator direction found on one cohort
also explains the other's covariance structure (real, cohort-independent
structure). A value near 0 means the two cohorts' dominant directions are
unrelated (no stable structure matches the D4/slice-0 finding at the
generator level rather than the induced-action level).
"""
_, train_vecs = principal_directions(bivector_covariance(train_versors))
_, test_vecs = principal_directions(bivector_covariance(test_versors))
# top-k subspace overlap via singular values of the k x k Gram of top directions
a = train_vecs[:, :k]
b = test_vecs[:, :k]
overlap = a.T @ b
if k == 1:
return float(abs(overlap[0, 0]))
singular_values = np.linalg.svd(overlap, compute_uv=False)
return float(np.mean(singular_values)) # mean principal angle cosine
# --- synthetic recovery controls ------------------------------------------------
def synthetic_recovery_positive_cohort(
rng: np.random.Generator, n: int, basis: np.ndarray | None = None
) -> list[np.ndarray]:
"""POSITIVE control: bivector coefficients confined to a low-rank subspace
+ small noise.
``basis`` is the true subspace. Pass the SAME basis to generate two
independent cohorts sharing one true structure (the cross-cohort recovery
control); omitting it draws a fresh random subspace two cohorts built
with separate fresh bases share NOTHING and must never be compared as a
positive pair (that was a real bug caught RED in the test suite: the
"positive" pair scored 0.53, indistinguishable from noise, because each
call invented its own subspace).
"""
if basis is None:
basis = np.linalg.qr(
rng.standard_normal((BIVECTOR_DIM, POSITIVE_CONTROL_TRUE_RANK))
)[0]
coeffs = []
for _ in range(n):
weights = rng.standard_normal(POSITIVE_CONTROL_TRUE_RANK)
vec = basis @ weights + POSITIVE_CONTROL_NOISE_SIGMA * rng.standard_normal(BIVECTOR_DIM)
coeffs.append(_embed_bivector(vec))
return coeffs
def synthetic_recovery_negative_cohort(
rng: np.random.Generator, n: int
) -> list[np.ndarray]:
"""NEGATIVE control: isotropic random bivector coefficients (no structure).
The eigen-analysis MUST NOT report a dominant low-rank subspace a false
positive here would mean the method hallucinates structure from noise."""
coeffs = [
_embed_bivector(rng.standard_normal(BIVECTOR_DIM)) for _ in range(n)
]
return coeffs
def _embed_bivector(bivector_coeffs: np.ndarray) -> np.ndarray:
"""Embed a 10-dim bivector-coefficient vector into a full 32-dim versor-shaped
array (scalar part fixed at 1.0) purely so it round-trips through
``bivector_coefficients`` identically these are SYNTHETIC generator-proxy
vectors for the recovery controls, not claims of being valid versors."""
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
for idx, coeff in zip(BIVECTOR_INDICES, bivector_coeffs):
v[idx] = coeff
return v
def null_cross_cohort_cosine_distribution(
n: int, *, n_trials: int = N_NULL_TRIALS, seed: int = RECOVERY_CONTROL_SEED, k: int = 2
) -> np.ndarray:
"""The NULL distribution of ``cross_cohort_top_pc_cosine_similarity`` between
two INDEPENDENT isotropic-noise (no-true-structure) cohorts of size ``n``
calibrated to the ACTUAL sample size under study, not a generic asymptotic
threshold.
This matters because at small ``n`` (comparable to the 10-dim generator-proxy
space), a sample covariance from PURE NOISE still shows an inflated top-k
"variance explained" from finite-sample fluctuation alone (verified
empirically: at n=20 an isotropic negative control showed ~0.44, not the
asymptotic 0.20 chance level for k=2/10). Comparing a real result against a
fixed threshold derived from large-sample asymptotics would be dishonestly
optimistic. Instead every real finding here is judged against a null
distribution generated at the SAME ``n``.
"""
rng = np.random.default_rng(seed)
cosines = np.empty(n_trials, dtype=np.float64)
for i in range(n_trials):
cohort_a = synthetic_recovery_negative_cohort(rng, n)
cohort_b = synthetic_recovery_negative_cohort(rng, n)
cosines[i] = cross_cohort_top_pc_cosine_similarity(cohort_a, cohort_b, k=k)
return cosines
def empirical_percentile(value: float, null_distribution: np.ndarray) -> float:
"""Fraction of the null distribution at or below ``value`` — a one-sided
empirical p-value complement (0.95 value exceeds 95% of pure-noise draws
at the same sample size, i.e. p < 0.05 one-sided)."""
return float(np.mean(null_distribution <= value))
def run_recovery_controls(
n: int, *, seed: int = RECOVERY_CONTROL_SEED, n_trials: int = N_NULL_TRIALS
) -> dict[str, Any]:
"""Sample-size-calibrated recovery sanity check (see module docstring).
Two independent cohorts drawn from the SAME true rank-2 subspace (+ noise)
at size ``n`` each MUST show high cross-cohort cosine similarity, and that
similarity must clear the NULL distribution (two independent noise cohorts
at the same ``n``) confirming the method can detect real shared structure
at this exact sample size, not merely at a generously large one.
"""
rng = np.random.default_rng(seed)
# ONE shared true subspace; two INDEPENDENT cohorts drawn from it.
shared_basis = np.linalg.qr(
rng.standard_normal((BIVECTOR_DIM, POSITIVE_CONTROL_TRUE_RANK))
)[0]
positive_a = synthetic_recovery_positive_cohort(rng, n, basis=shared_basis)
positive_b = synthetic_recovery_positive_cohort(rng, n, basis=shared_basis)
positive_cosine = cross_cohort_top_pc_cosine_similarity(
positive_a, positive_b, k=POSITIVE_CONTROL_TRUE_RANK
)
null_dist = null_cross_cohort_cosine_distribution(
n, n_trials=n_trials, seed=seed + 1, k=POSITIVE_CONTROL_TRUE_RANK
)
positive_percentile = empirical_percentile(positive_cosine, null_dist)
return {
"sample_size": n,
"positive_control_cross_cohort_cosine": round(positive_cosine, 6),
"null_distribution": {
"n_trials": n_trials,
"mean": round(float(np.mean(null_dist)), 6),
"p50": round(float(np.percentile(null_dist, 50)), 6),
"p95": round(float(np.percentile(null_dist, 95)), 6),
},
"positive_control_percentile_in_null": round(positive_percentile, 6),
"method_recovers_true_structure": bool(positive_percentile > 0.95),
}
# --- precision pairs -------------------------------------------------------------
def precision_pair_delta(versor: np.ndarray) -> float:
"""Max abs delta of the bivector-proxy coefficients under an f64->f32->f64
round-trip of the whole versor (same style as the slice-0 transport probe)."""
versor64 = np.asarray(versor, dtype=np.float64)
versor_roundtrip = versor64.astype(np.float32).astype(np.float64)
return float(
np.max(
np.abs(bivector_coefficients(versor64) - bivector_coefficients(versor_roundtrip))
)
)
# --- plane occupancy (typed e4/e5 generator analysis) ---------------------------
def mean_plane_energy_fractions(versors: Sequence[np.ndarray]) -> dict[str, float]:
"""Mean fraction of bivector energy in each of the 10 individual planes,
across a cohort the "typed e4/e5 generator analysis": does the generator
concentrate in specific e4/e5-mixing planes, or spread evenly?"""
fractions = np.zeros(BIVECTOR_DIM, dtype=np.float64)
for versor in versors:
coeffs = bivector_coefficients(versor)
total = float(np.dot(coeffs, coeffs))
if total > 0.0:
fractions += (coeffs ** 2) / total
fractions /= max(len(versors), 1)
return {name: round(float(f), 6) for name, f in zip(_PLANE_NAMES, fractions)}
# --- cohort collection -----------------------------------------------------------
def collect_train_cohort() -> list[np.ndarray]:
"""TRAIN: benign versors from the D4/slice-0 pinned probe sequence."""
return [v for _, v in collect_live_versors(LIVE_PROBE_SEQUENCE)]
def collect_held_out_cohort() -> list[np.ndarray]:
"""HELD-OUT: independently-worded paraphrase versors (genuine generalization test)."""
return [v for _, v in collect_live_versors(PARAPHRASE_PROBE_SEQUENCE)]
def collect_adversarial_cohort() -> list[np.ndarray]:
"""The existing crafted geometric-attack cohort, reused for consistency."""
return [v for _, v in adversarial_cohort()]
# --- full study -------------------------------------------------------------------
def build_feasibility_report(
train: Sequence[np.ndarray] | None = None,
held_out: Sequence[np.ndarray] | None = None,
adversarial: Sequence[np.ndarray] | None = None,
) -> dict[str, Any]:
"""Run the full §11 feasibility study and report an honest verdict.
``train``/``held_out``/``adversarial`` default to the live/synthetic cohorts
described in the module docstring; pass explicit cohorts for a fast/offline
run (as the test suite does).
"""
train = list(train) if train is not None else collect_train_cohort()
held_out = list(held_out) if held_out is not None else collect_held_out_cohort()
adversarial = list(adversarial) if adversarial is not None else collect_adversarial_cohort()
# Null calibration uses the SMALLER of the two real cohort sizes — the more
# conservative (harder-to-clear) choice when the sizes differ.
calibration_n = max(min(len(train), len(held_out)), 3)
recovery = run_recovery_controls(calibration_n)
train_eigvals, train_eigvecs = principal_directions(bivector_covariance(train))
held_out_eigvals, _ = principal_directions(bivector_covariance(held_out))
top_k = 2
cross_cohort_cosine = cross_cohort_top_pc_cosine_similarity(train, held_out, k=top_k)
null_dist = null_cross_cohort_cosine_distribution(calibration_n, k=top_k)
real_percentile = empirical_percentile(cross_cohort_cosine, null_dist)
top_eigvecs = train_eigvecs[:, :top_k]
train_residuals = [subspace_residual_fraction(bivector_coefficients(v), top_eigvecs) for v in train]
held_out_residuals = [subspace_residual_fraction(bivector_coefficients(v), top_eigvecs) for v in held_out]
adversarial_residuals = [subspace_residual_fraction(bivector_coefficients(v), top_eigvecs) for v in adversarial]
auc = _roc_auc(adversarial_residuals, held_out_residuals)
auc_ci = _auc_bootstrap_ci(adversarial_residuals, held_out_residuals)
precision_deltas = [precision_pair_delta(v) for v in train + held_out]
plane_energy_train = mean_plane_energy_fractions(train)
plane_energy_held_out = mean_plane_energy_fractions(held_out)
held_out_stable = bool(
real_percentile >= HELD_OUT_STABILITY_NULL_PERCENTILE_FLOOR
and np.isfinite(auc_ci[0])
and auc_ci[0] > DISCRIMINATION_AUC_CI_FLOOR
)
report = {
"schema_version": "adr_0246_grounding_feasibility_v1",
"method": {
"generator_proxy": "bivector (grade-2) coefficient block, 10 planes",
"note": "approximates the Lie generator to first order; exact for "
"single-plane simple rotors/boosts, approximate for compound "
"multi-generator turns; no scipy / matrix-log dependency",
},
"cohorts": {"train_n": len(train), "held_out_n": len(held_out), "adversarial_n": len(adversarial)},
"null_calibration_sample_size": calibration_n,
"recovery_controls": recovery,
"train_eigenvalues": [round(float(x), 6) for x in train_eigvals],
"held_out_eigenvalues": [round(float(x), 6) for x in held_out_eigvals],
"train_variance_explained_top_2": round(variance_explained(train_eigvals, top_k), 6),
"held_out_variance_explained_top_2": round(variance_explained(held_out_eigvals, top_k), 6),
"cross_cohort_top2_cosine_similarity": round(cross_cohort_cosine, 6),
"cross_cohort_cosine_null_distribution": {
"n_trials": N_NULL_TRIALS,
"mean": round(float(np.mean(null_dist)), 6),
"p95": round(float(np.percentile(null_dist, 95)), 6),
},
"cross_cohort_cosine_percentile_in_null": round(real_percentile, 6),
"held_out_stability_null_percentile_floor": HELD_OUT_STABILITY_NULL_PERCENTILE_FLOOR,
"residual_from_train_top2_subspace": {
"train": {"mean": round(float(np.mean(train_residuals)), 6)},
"held_out": {"mean": round(float(np.mean(held_out_residuals)), 6)},
"adversarial": {"mean": round(float(np.mean(adversarial_residuals)), 6)},
},
"discrimination_auc_adversarial_vs_heldout": round(auc, 6) if np.isfinite(auc) else None,
"discrimination_auc_ci95": [
round(x, 6) if np.isfinite(x) else None for x in auc_ci
],
"precision_transport": {
"max_bivector_delta": round(max(precision_deltas), 9) if precision_deltas else 0.0,
"significant": bool(precision_deltas and max(precision_deltas) > 1e-4),
},
"plane_energy_fractions": {"train": plane_energy_train, "held_out": plane_energy_held_out},
"verdict": {
"recovery_method_validated": bool(recovery["method_recovers_true_structure"]),
"held_out_stable_structure_found": held_out_stable,
"safety_relevant": bool(held_out_stable and auc > 0.5),
},
}
report["verdict"]["honest_finding"] = _honest_finding(report)
return report
def _honest_finding(report: dict[str, Any]) -> str:
v = report["verdict"]
cos = report["cross_cohort_top2_cosine_similarity"]
pct = report["cross_cohort_cosine_percentile_in_null"]
auc = report["discrimination_auc_adversarial_vs_heldout"]
ci = report["discrimination_auc_ci95"]
n = report["cohorts"]
if not v["recovery_method_validated"]:
return (
"INCONCLUSIVE: the recovery-control sanity check failed — at this "
"sample size the method cannot reliably distinguish a real shared "
"structure from chance agreement between two noise cohorts, "
"independent of the real cohorts' outcome. Do not draw a conclusion "
"from the real-cohort numbers below."
)
if v["held_out_stable_structure_found"]:
return (
f"POSITIVE (n_train={n['train_n']}, n_held_out={n['held_out_n']}): the "
f"top-2 generator-proxy subspace found on TRAIN cosine-agrees with the "
f"independently-collected HELD-OUT cohort at {cos:.2f} — the "
f"{pct * 100:.0f}th percentile of the SAME-SAMPLE-SIZE null distribution "
f"(two independent pure-noise cohorts), i.e. this agreement is unlikely "
f"to have arisen by chance alone. It also discriminates the adversarial "
f"cohort from held-out benign at AUC {auc:.2f} (95% CI [{ci[0]:.2f}, "
f"{ci[1]:.2f}], clears chance). This is evidence — NOT proof at this "
f"sample size — that a held-out-stable, safety-relevant structure may "
f"exist. A larger, pre-registered cohort study is required before "
f"drafting an ADR-0246 implementation contract on this basis."
)
return (
f"NULL (n_train={n['train_n']}, n_held_out={n['held_out_n']}): the top-2 "
f"generator-proxy subspace found on TRAIN does NOT reliably reproduce on "
f"the independently-collected HELD-OUT cohort — cosine similarity {cos:.2f} "
f"sits at only the {pct * 100:.0f}th percentile of what two INDEPENDENT "
f"pure-noise cohorts of the same size produce by chance (need >= 95th) "
f"and/or does not clear the discrimination bar (AUC {auc:.2f}, 95% CI "
f"[{ci[0]:.2f}, {ci[1]:.2f}]). This is consistent with — and sharpens — the "
f"D4/slice-0/§6.3 finding at the GENERATOR level (not just the induced-action "
f"level): benign cognition does not have a small, stable, cohort-independent "
f"generator subspace detectable at this sample size. Threshold tuning on the "
f"current pack cannot produce a discriminating gate; this feasibility study "
f"does not find grounds to draft a revised ADR-0246 implementation contract. "
f"A much larger cohort (this study used n<=13 per real cohort) would be "
f"needed to rule out a real but subtle effect, rather than to overturn this null."
)

View file

@ -0,0 +1,40 @@
"""Run the ADR-0246 §11 grounding-feasibility study and emit the report.
Usage: uv run python -m evals.adr_0246_grounding_feasibility [out.json]
Collects the live TRAIN (benign) and HELD-OUT (paraphrase) cohorts (spins up a
fresh empty-vault runtime twice), runs the recovery controls + cross-cohort
generator analysis + discrimination check, and prints the honest verdict.
"""
from __future__ import annotations
import json
import sys
from evals.adr_0246_grounding_feasibility import build_feasibility_report
def main() -> int:
report = build_feasibility_report()
summary = {
"cohorts": report["cohorts"],
"recovery_controls": report["recovery_controls"],
"cross_cohort_top2_cosine_similarity": report["cross_cohort_top2_cosine_similarity"],
"cross_cohort_cosine_percentile_in_null": report["cross_cohort_cosine_percentile_in_null"],
"discrimination_auc_adversarial_vs_heldout": report["discrimination_auc_adversarial_vs_heldout"],
"discrimination_auc_ci95": report["discrimination_auc_ci95"],
"precision_transport": report["precision_transport"],
"plane_energy_fractions": report["plane_energy_fractions"],
"verdict": report["verdict"],
}
print(json.dumps(summary, indent=2, sort_keys=True))
if len(sys.argv) > 1:
with open(sys.argv[1], "w", encoding="utf-8") as fh:
fh.write(json.dumps(report, indent=2, sort_keys=True) + "\n")
print(f"\nfull report written to {sys.argv[1]}")
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -50,9 +50,13 @@ from algebra.cl41 import N_COMPONENTS, grade_project
from core.physics.identity_manifold import (
IdentityManifoldGeometry,
euclidean_norm,
sandwich,
orthogonality_defect_of_action,
_inner0,
)
from core.physics.identity_action import (
IdentityStabilizer,
stabilizer_defect,
)
from evals.adr_0244_gamma_calibration import (
LEAKAGE_ATTACKS,
_boost,
@ -90,93 +94,34 @@ def default_geometry() -> IdentityManifoldGeometry:
return IdentityManifoldGeometry.from_directions(DEFAULT_DIRECTIONS)
# --- brief §3.1: induced action matrix ----------------------------------------
# --- ADR-0246 §3 primitives — thin wrappers over the canonical implementations -
# The substantive definitions now live in ``core.physics.identity_manifold`` /
# ``identity_action`` (promoted from this slice-0 prototype). These wrappers keep
# the diagnostic's call sites and its merged test API stable while delegating to
# the single source of truth.
def induced_action(geometry: IdentityManifoldGeometry, versor: np.ndarray) -> np.ndarray:
"""``A_ij(F) = (G⁻¹)_ik ⟨a_k, F a_j F̃⟩₀`` — the full in-subspace action.
Column ``j`` is the image of axis ``j`` expressed in the axis basis. Captures
in-span permutations/rotations/inversions that per-axis leakage misses. Raw
(unnormalized): a boost that stretches an axis shows up as a column norm > 1
and hence in ``d_orth``, deliberately not hidden by normalization.
"""
versor = np.asarray(versor, dtype=np.float64)
n = len(geometry.axes_psi)
m = np.empty((n, n), dtype=np.float64)
for j, axis_j in enumerate(geometry.axes_psi):
image = sandwich(versor, axis_j)
for k, axis_k in enumerate(geometry.axes_psi):
m[k, j] = _inner0(axis_k, image)
return geometry.gram_inv @ m
"""Induced action ``A(F)`` (delegates to the geometry primitive)."""
return geometry.induced_action(versor)
def d_orth(geometry: IdentityManifoldGeometry, action: np.ndarray) -> float:
"""``‖AᵀGA G‖_F`` — 0 iff the induced action is a G-isometry of the span.
Detects numerical corruption and non-isometric (e.g. boost-stretched) action;
must never be read as a semantic authorization policy (brief §3.2).
"""
G = geometry.gram
return float(np.linalg.norm(action.T @ G @ action - G, ord="fro"))
"""``‖AᵀGA G‖_F`` for a precomputed action (delegates to canonical)."""
return orthogonality_defect_of_action(action, geometry.gram)
def d_stab(geometry: IdentityManifoldGeometry, action: np.ndarray) -> float:
"""``min_{H∈H_id} ‖A H‖_G`` under the LOCKED singleton ``H_id = {I}``.
For the default pack the axis Gram is exactly the identity matrix, so the
G-weighted norm coincides with the Frobenius norm; pinning ·_G for general
packs is ADR-0246-proper work, not this slice's.
"""
eye = np.eye(action.shape[0], dtype=np.float64)
return float(np.linalg.norm(action - eye, ord="fro"))
# --- brief §3.6: typed residual channels --------------------------------------
"""``d_stab`` under the locked singleton ``H_id = {I}`` (delegates to canonical)."""
stabilizer = IdentityStabilizer.singleton(action.shape[0])
return stabilizer_defect(action, geometry.gram, stabilizer)
def typed_residual_channels(
geometry: IdentityManifoldGeometry, versor: np.ndarray
) -> dict[str, float]:
"""Energy split of the out-of-span rejection, summed over axes, as fractions
of total rotated-axis energy.
Channels (pinned blade indices; default pack support = e1/e2/e3 so the
spatial-foreign channel is structurally empty and reported as 0):
* ``null_or_conformal`` e4 grade-1 residual energy (index 4)
* ``boost_like`` e5 grade-1 residual energy (index 5)
* ``spatial_foreign`` grade-1 spatial residual outside the axis
support (empty for the default pack)
* ``unclassified`` everything else (higher-grade contamination
after the sandwich, numerical junk); fail-closed,
no correction policy ever attaches to it
"""
versor = np.asarray(versor, dtype=np.float64)
e4_energy = e5_energy = unclassified = total = 0.0
for axis in geometry.axes_psi:
rotated = sandwich(versor, axis)
rejection = rotated - geometry.project(rotated)
total += euclidean_norm(rotated) ** 2
e4_energy += float(rejection[IDX_E4] ** 2)
e5_energy += float(rejection[IDX_E5] ** 2)
accounted = rejection.copy()
accounted[IDX_E4] = 0.0
accounted[IDX_E5] = 0.0
unclassified += euclidean_norm(accounted) ** 2
if total <= 0.0:
return {
"null_or_conformal": 1.0,
"boost_like": 0.0,
"spatial_foreign": 0.0,
"unclassified": 1.0,
}
return {
"null_or_conformal": e4_energy / total,
"boost_like": e5_energy / total,
"spatial_foreign": 0.0,
"unclassified": unclassified / total,
}
"""Typed residual channel split (delegates to the geometry primitive)."""
return geometry.typed_residual_energy(versor)
def versor_plane_occupancy(versor: np.ndarray) -> dict[str, float]:

View file

@ -0,0 +1,186 @@
"""ADR-0246 §4.1/§4.3 — per-turn IdentityActionRecord telemetry pins.
Pins the pure record builder (`build_identity_action_record`), its full-SHA-256
digests (§4.3 no truncation, no `default=str`), the conditional-population
discipline (never built unless the wave/action surface actually ran), the
minimal serve wiring (IdentityScore.action_record, populated only when
admission_policy is supplied), and the telemetry serializer's conditional
emission (wave_mode_active AND action_surface_active both required flag-off
wire format is provably unchanged).
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from core.physics.identity import IdentityCheck, IdentityManifold, ValueAxis
from core.physics.identity_action import (
AdmissionPolicy,
build_identity_action_record,
)
from core.physics.identity_manifold import IdentityManifoldGeometry
from chat.telemetry import serialize_turn_event
_E14 = 8
def _rotor(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _identity_versor():
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
@pytest.fixture(scope="module")
def geometry():
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
def _manifold():
return IdentityManifold(
value_axes=(
ValueAxis(name="truthfulness", direction=(1.0, 0.0, 0.0)),
ValueAxis(name="coherence", direction=(0.0, 1.0, 0.0)),
ValueAxis(name="reverence", direction=(0.0, 0.0, 1.0)),
)
)
class _Trajectory:
trajectory_id = "record_test"
total_coherence_delta = 0.0
frames = ()
# --- pure builder pins ---------------------------------------------------------
def test_record_schema_and_shape(geometry):
policy = AdmissionPolicy.placeholder_default()
record = build_identity_action_record(
geometry, _identity_versor(), policy, trajectory_id="t1", turn_id=3,
)
d = record.as_dict()
assert d["schema_version"] == "identity_action_v1"
assert d["turn_id"] == 3 and d["trajectory_id"] == "t1"
assert set(d["typed_residual_energy"]) == {
"spatial_foreign", "boost_like", "null_or_conformal", "unclassified",
}
assert len(d["A_raw"]) == 3 and len(d["A_raw"][0]) == 3
assert d["admitted"] is True and d["refusal_reason"] is None
assert d["lawful_action"] == "I"
assert d["path_break"] is False
def test_record_refusal_reason_and_lawful_action_on_attack(geometry):
policy = AdmissionPolicy.placeholder_default()
record = build_identity_action_record(geometry, _rotor(_E14, 1.5), policy)
assert record.admitted is False
assert record.refusal_reason is not None
assert ">" in record.refusal_reason # e.g. "d_orth>orth_tol;..."
assert record.lawful_action == "none"
def test_record_digests_are_full_sha256_and_deterministic(geometry):
policy = AdmissionPolicy.placeholder_default()
r1 = build_identity_action_record(geometry, _identity_versor(), policy)
r2 = build_identity_action_record(geometry, _identity_versor(), policy)
assert len(r1.field_digest) == 64 and len(r1.record_digest()) == 64
int(r1.field_digest, 16)
int(r1.record_digest(), 16)
assert r1.field_digest == r2.field_digest
assert r1.record_digest() == r2.record_digest()
def test_record_digest_changes_with_content(geometry):
policy = AdmissionPolicy.placeholder_default()
r_id = build_identity_action_record(geometry, _identity_versor(), policy)
r_atk = build_identity_action_record(geometry, _rotor(_E14, 1.5), policy)
assert r_id.record_digest() != r_atk.record_digest()
assert r_id.field_digest != r_atk.field_digest
def test_policy_version_id_is_full_sha256_and_reflects_calibration_state(geometry):
p1 = AdmissionPolicy.placeholder_default()
assert len(p1.version_id()) == 64
int(p1.version_id(), 16)
p2 = AdmissionPolicy.placeholder_default()
assert p1.version_id() == p2.version_id() # deterministic
from dataclasses import replace
p3 = replace(p1, gamma_id=0.5)
assert p3.version_id() != p1.version_id() # threshold change -> new version
def test_manifold_content_digest_changes_on_axis_change():
from core.physics.identity import manifold_content_digest
m1 = _manifold()
m2 = IdentityManifold(value_axes=_manifold().value_axes[:2])
d1 = manifold_content_digest(m1)
d2 = manifold_content_digest(m2)
assert len(d1) == 64 and d1 != d2
assert manifold_content_digest(m1) == d1 # deterministic
# --- serve wiring: IdentityScore.action_record ---------------------------------
def test_flag_off_action_record_is_none():
check = IdentityCheck()
score = check.check(_Trajectory(), _manifold(), wave_field=_identity_versor())
assert score.action_record is None
def test_flag_on_populates_action_record():
check = IdentityCheck()
score = check.check(
_Trajectory(), _manifold(), wave_field=_identity_versor(),
admission_policy=AdmissionPolicy.placeholder_default(),
)
assert score.action_record is not None
assert score.action_record.trajectory_id == "record_test"
assert score.action_record.admitted is True
# --- telemetry serialization: conditional emission -----------------------------
class _Event:
turn = 1
identity_score = None
def test_telemetry_flag_off_has_no_action_fields():
check = IdentityCheck()
ev = _Event()
ev.identity_score = check.check(
_Trajectory(), _manifold(), wave_field=_identity_versor()
)
payload = serialize_turn_event(ev)
assert "identity_action_admitted" not in payload
assert "identity_d_orth" not in payload
assert "identity_d_stab" not in payload
def test_telemetry_flag_on_emits_action_surface_fields():
check = IdentityCheck()
ev = _Event()
ev.identity_score = check.check(
_Trajectory(), _manifold(), wave_field=_rotor(_E14, 1.5),
admission_policy=AdmissionPolicy.placeholder_default(),
)
payload = serialize_turn_event(ev)
assert payload["identity_action_admitted"] is False
assert isinstance(payload["identity_d_orth"], float)
assert isinstance(payload["identity_d_stab"], float)
assert "identity_action_record_digest" in payload
assert len(payload["identity_action_record_digest"]) == 64

View file

@ -0,0 +1,124 @@
"""ADR-0246 §3.7 admit-surface + §6.3 discrimination-report pins.
Pins the pure admit surface (`evaluate_admission`, locked `H_id={I}`, placeholder
thresholds) and the honest discrimination verdict: on the declared placeholder
frame the gate refuses benign and adversarial alike and does NOT separate them
a result that must be reported plainly, never framed as a working detector.
Offline/deterministic: cohorts are injected, so no runtime is spun up here.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from core.physics import identity
from core.physics.identity_manifold import IdentityManifoldGeometry, MalformedVersorError
from core.physics.identity_action import (
AdmissionPolicy,
CERTIFIED_GAMMA_ID,
evaluate_admission,
)
from evals.adr_0246_discrimination import build_discrimination_report
_E12, _E14, _E15 = 6, 8, 9
def _rotor(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _boost(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cosh(theta / 2.0)
r[biv] = np.sinh(theta / 2.0)
return r
def _identity_versor():
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
@pytest.fixture(scope="module")
def geometry():
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
def test_certified_gamma_id_matches_d4_bound_no_drift():
# the one certified threshold must equal the D4-pinned serve bound
assert CERTIFIED_GAMMA_ID == identity._WAVE_LEAKAGE_BOUND
def test_placeholder_policy_is_flagged_uncalibrated():
assert AdmissionPolicy.placeholder_default().calibrated is False
def test_identity_versor_is_admitted(geometry):
result = evaluate_admission(geometry, _identity_versor(), AdmissionPolicy.placeholder_default())
assert result.admitted is True
assert result.refusal_reasons == ()
assert result.d_orth < 1e-9 and result.d_stab < 1e-9
@pytest.mark.parametrize("versor", [_rotor(_E14, 1.5), _boost(_E15, 1.2), _rotor(_E12, np.pi)])
def test_attacks_are_refused_with_reasons(geometry, versor):
result = evaluate_admission(geometry, versor, AdmissionPolicy.placeholder_default())
assert result.admitted is False
assert len(result.refusal_reasons) >= 1
def test_admission_is_admit_or_abstain_never_corrects(geometry):
# evaluate_admission returns a verdict + measurements; it never returns a
# modified versor/action (no corrector surface exists)
result = evaluate_admission(geometry, _rotor(_E14, 1.0), AdmissionPolicy.placeholder_default())
assert set(result.as_dict()) == {
"admitted", "refusal_reasons", "d_orth", "d_stab",
"leakage_rms", "max_leakage", "min_self_alignment", "typed_channels",
}
def test_malformed_versor_raises_for_failclosed_serve(geometry):
bad = _identity_versor()
bad[3] = np.nan
with pytest.raises(MalformedVersorError):
evaluate_admission(geometry, bad, AdmissionPolicy.placeholder_default())
def test_discrimination_report_reports_honest_non_separation(geometry):
# inject a benign cohort that mimics REAL benign traffic (far from the frame,
# per D4/slice-0) so the honest verdict is pinned without a live runtime.
benign = [
("benign_like_boost", _boost(_E15, 1.1)),
("benign_like_boost2", _boost(9, 1.3)),
("benign_like_tilt", _rotor(_E14, 1.2)),
("benign_like_big", _rotor(_E12, 2.5)),
]
report = build_discrimination_report(benign, geometry=geometry)
assert report["policy"]["calibrated"] is False
# benign mass-refused; a refuse-all "detects" all attacks but does not discriminate
assert report["rates"]["benign_pass_rate"] == 0.0
assert report["rates"]["false_refusal_rate"] == 1.0
assert report["rates"]["adversarial_detection_rate"] == 1.0
assert report["verdict"]["gate_discriminates_benign_from_adversarial"] is False
assert report["verdict"]["benign_usable_at_this_policy"] is False
# the honest claims language must be present and must NOT oversell
claims = report["verdict"]["claims_language"].lower()
assert "lawfulness relative to the declared frozen frame" in claims
assert "inalienab" in claims # explicitly names what it is NOT
def test_discrimination_control_admits_true_near_identity(geometry):
# the synthetic-near-identity control passing confirms the gate MECHANISM is
# sound — the benign failure is the frame, not a broken gate.
report = build_discrimination_report(
[("benign_like", _boost(_E15, 1.1))], geometry=geometry
)
assert report["rates"]["synthetic_near_identity_pass_rate"] == 1.0

View file

@ -0,0 +1,100 @@
"""ADR-0246 §3.7 egress admit-surface serve wiring — flag-gated, default-off.
Pins that the fuller §3.7 admit surface (d_orth/d_stab/typed channels, via
`evaluate_admission`) is wired into the identity gate ONLY behind the new
default-off `identity_action_surface` flag; that flag-off is byte-identical to the
D4 wave path; and that when on, a versor failing the surface is refused
(admit-or-abstain no corrector, IdentityGateRefusal path).
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from core.config import RuntimeConfig
from core.physics.identity import IdentityCheck, IdentityManifold, ValueAxis
from core.physics.identity_action import AdmissionPolicy
_E14 = 8
def _rotor(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _identity_versor():
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
class _Trajectory:
trajectory_id = "egress_test"
total_coherence_delta = 0.0
frames = ()
def _manifold():
return IdentityManifold(
value_axes=(
ValueAxis(name="truthfulness", direction=(1.0, 0.0, 0.0)),
ValueAxis(name="coherence", direction=(0.0, 1.0, 0.0)),
ValueAxis(name="reverence", direction=(0.0, 0.0, 1.0)),
)
)
def test_flag_default_off():
assert RuntimeConfig().identity_action_surface is False
def test_flag_off_wave_path_is_byte_identical():
check = IdentityCheck()
manifold = _manifold()
tilt = _rotor(_E14, 1.2)
# no admission_policy (default) == exactly the D4 wave path
base = check.check(_Trajectory(), manifold, wave_field=tilt)
same = check.check(_Trajectory(), manifold, wave_field=tilt, admission_policy=None)
assert base == same
# new §3.7 fields carry legacy defaults when the surface is off
assert base.d_orth == 0.0 and base.d_stab == 0.0
assert base.action_surface_active is False
def test_surface_on_populates_measures_and_can_refuse():
check = IdentityCheck()
manifold = _manifold()
tilt = _rotor(_E14, 1.2) # alien tilt: fails d_orth/d_stab/leakage
score = check.check(
_Trajectory(), manifold, wave_field=tilt,
admission_policy=AdmissionPolicy.placeholder_default(),
)
assert score.action_surface_active is True
assert score.d_orth > 0.05 and score.d_stab > 0.05
assert score.flagged is True # §3.7 refusal folds into the gate verdict
assert IdentityCheck.would_violate(score) is True
def test_surface_on_admits_true_near_identity():
check = IdentityCheck()
manifold = _manifold()
score = check.check(
_Trajectory(), manifold, wave_field=_identity_versor(),
admission_policy=AdmissionPolicy.placeholder_default(),
)
assert score.action_surface_active is True
assert score.flagged is False
assert IdentityCheck.would_violate(score) is False
def test_runtime_flag_off_is_default_and_serve_untouched():
# the runtime must default the surface off (no live activation of an
# uncalibrated gate)
cfg = RuntimeConfig()
assert cfg.identity_wave_gate is False
assert cfg.identity_action_surface is False

View file

@ -0,0 +1,98 @@
"""ADR-0246 §6.1/§6.2 eval-suite pins — every synthetic case fails loudly.
Pins the runnable ``evals.adr_0246_geometric_suite`` harness AND the specific
§6.1 rows the preflight table calls out (π-inversion ``s-1``, 90° permutation
``s0``, near-singular Gram ``ManifoldConditioningError``, malformed F
``MalformedVersorError``), so a regression names the exact broken case.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from core.physics.identity_manifold import (
IdentityManifoldGeometry,
ManifoldConditioningError,
MalformedVersorError,
)
from evals.adr_0246_geometric_suite import (
build_suite_report,
default_geometry,
identity_versor,
rotor,
run_geometric_suite,
run_path_suite,
)
_E12 = 6
@pytest.fixture(scope="module")
def geometry() -> IdentityManifoldGeometry:
return default_geometry()
def test_full_suite_all_cases_pass():
report = build_suite_report()
# every case must pass; the assertion message names any that did not
failed = [c["name"] for c in report["geometric_suite"] + report["path_suite"] if not c["passed"]]
assert failed == [], f"failing cases: {failed}"
assert report["all_passed"] is True
assert report["case_count"] == report["passed_count"] == 14
@pytest.mark.parametrize("case", [c["name"] for c in run_geometric_suite()])
def test_each_geometric_case_passes(geometry, case):
result = {c["name"]: c for c in run_geometric_suite(geometry)}[case]
assert result["passed"], result["checks"]
@pytest.mark.parametrize("case", [c["name"] for c in run_path_suite()])
def test_each_path_case_passes(geometry, case):
result = {c["name"]: c for c in run_path_suite(geometry)}[case]
assert result["passed"], result["checks"]
# --- explicit §6.1 pins (directive step 4: fail loudly on the exact expected) --
def test_pi_inversion_self_align_is_minus_one(geometry):
_, self_align = geometry.axis_response(rotor(_E12, np.pi))
assert self_align[0] == pytest.approx(-1.0, abs=1e-9) # e1 inverted
assert self_align[1] == pytest.approx(-1.0, abs=1e-9) # e2 inverted
assert self_align[2] == pytest.approx(1.0, abs=1e-9) # e3 fixed
def test_90deg_permutation_self_align_is_zero(geometry):
_, self_align = geometry.axis_response(rotor(_E12, np.pi / 2.0))
assert self_align[0] == pytest.approx(0.0, abs=1e-9) # e1 → e2, orthogonal
assert self_align[1] == pytest.approx(0.0, abs=1e-9)
def test_near_singular_gram_fails_closed():
with pytest.raises(ManifoldConditioningError):
IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (1.0, 1e-9, 0.0), (0.0, 0.0, 1.0))
)
def test_malformed_versor_raises_typed_error(geometry):
nan_v = identity_versor()
nan_v[5] = np.inf
with pytest.raises(MalformedVersorError):
geometry.induced_action(nan_v)
with pytest.raises(MalformedVersorError):
geometry.typed_residual_energy(np.ones(N_COMPONENTS + 3, dtype=np.float64))
def test_suite_is_offserving():
import evals.adr_0246_geometric_suite as suite
assert suite.__file__ is not None
with open(suite.__file__, encoding="utf-8") as fh:
src = fh.read()
# no actual import of serve modules (the A-04 note in the docstring names
# chat.runtime as forbidden, so match import statements, not the substring)
assert "import chat" not in src and "from chat" not in src

View file

@ -0,0 +1,138 @@
"""ADR-0246 §11 grounding-feasibility study pins.
Pins the recovery-control sanity checks (the method must find structure when it
genuinely exists, and must not hallucinate structure from noise), the
bivector-proxy machinery, and the honest-verdict logic on injected cohorts no
live runtime required. A separate live smoke test (marked slow) exercises the
real collectors.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from evals.adr_0246_grounding_feasibility import (
BIVECTOR_DIM,
build_feasibility_report,
bivector_coefficients,
cross_cohort_top_pc_cosine_similarity,
precision_pair_delta,
run_recovery_controls,
subspace_residual_fraction,
)
from evals.adr_0246_mismatch_diagnostic import IDX_E12, IDX_E13, IDX_E14
def _rotor(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def test_bivector_coefficients_extract_the_right_slots():
v = _rotor(IDX_E12, 0.6)
coeffs = bivector_coefficients(v)
assert coeffs.shape == (BIVECTOR_DIM,)
assert coeffs[0] == pytest.approx(v[IDX_E12])
assert np.count_nonzero(coeffs) == 1 # only e12 is populated
def test_recovery_controls_validate_the_method():
# sample-size-calibrated: two independent cohorts sharing a TRUE rank-2
# subspace must show cross-cohort cosine similarity far above what two
# independent pure-noise cohorts of the SAME size produce by chance.
result = run_recovery_controls(13)
assert result["positive_control_cross_cohort_cosine"] > 0.8
assert result["positive_control_percentile_in_null"] > 0.95
assert result["method_recovers_true_structure"] is True
# the null distribution itself should be well below the positive signal
assert result["null_distribution"]["p95"] < result["positive_control_cross_cohort_cosine"]
def test_cross_cohort_cosine_detects_shared_structure():
# both cohorts confined to the SAME e12/e13 plane pair -> high cosine
cohort_a = [_rotor(IDX_E12, 0.1 * i + 0.05) for i in range(6)]
cohort_b = [_rotor(IDX_E13, 0.1 * i + 0.05) for i in range(6)]
# mix e12/e13 in both cohorts so both share a 2-plane subspace
mixed_a = cohort_a + [_rotor(IDX_E13, 0.05 * i) for i in range(6)]
mixed_b = cohort_b + [_rotor(IDX_E12, 0.05 * i) for i in range(6)]
cosine = cross_cohort_top_pc_cosine_similarity(mixed_a, mixed_b, k=2)
assert cosine > 0.5 # shared 2-plane structure should show real overlap
def test_cross_cohort_cosine_detects_unrelated_structure():
cohort_a = [_rotor(IDX_E12, 0.1 * i + 0.05) for i in range(10)]
# cohort_b lives entirely in an orthogonal plane (e.g. e35, far from e12)
from evals.adr_0246_mismatch_diagnostic import IDX_E35
cohort_b = [_rotor(IDX_E35, 0.1 * i + 0.05) for i in range(10)]
cosine = cross_cohort_top_pc_cosine_similarity(cohort_a, cohort_b, k=1)
assert cosine < 0.3 # unrelated single-plane structure -> low overlap
def test_subspace_residual_fraction_zero_inside_span():
v = _rotor(IDX_E12, 0.5)
coeffs = bivector_coefficients(v)
basis = np.zeros((BIVECTOR_DIM, 1))
basis[0, 0] = 1.0 # e12 direction (index 0 in BIVECTOR_INDICES)
assert subspace_residual_fraction(coeffs, basis) < 1e-9
def test_precision_pair_delta_is_tiny():
for versor in (_rotor(IDX_E12, 0.5), _rotor(IDX_E14, 1.3)):
assert precision_pair_delta(versor) < 1e-4
def test_feasibility_report_null_on_unrelated_cohorts():
# TRAIN and HELD-OUT confined to unrelated planes -> expect a NULL verdict
train = [_rotor(IDX_E12, 0.1 * i + 0.05) for i in range(10)]
from evals.adr_0246_mismatch_diagnostic import IDX_E35, IDX_E45
held_out = [_rotor(IDX_E45, 0.1 * i + 0.05) for i in range(10)]
adversarial = [_rotor(IDX_E14, 1.5), _rotor(IDX_E35, 1.2)]
report = build_feasibility_report(train, held_out, adversarial)
assert report["verdict"]["recovery_method_validated"] is True
assert report["verdict"]["held_out_stable_structure_found"] is False
assert "NULL" in report["verdict"]["honest_finding"]
def test_feasibility_report_positive_on_shared_plane_cohorts():
# TRAIN and HELD-OUT share the same 2-plane structure (e12/e13); adversarial
# lives elsewhere entirely (e14/e35/e45) -> expect the structure to be found
# AND to discriminate against the adversarial cohort.
from evals.adr_0246_mismatch_diagnostic import IDX_E35, IDX_E45
rng = np.random.default_rng(7)
def shared_plane_versor():
theta12 = rng.normal(0, 0.3)
theta13 = rng.normal(0, 0.3)
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
v[IDX_E12] = theta12
v[IDX_E13] = theta13
return v
train = [shared_plane_versor() for _ in range(15)]
held_out = [shared_plane_versor() for _ in range(15)]
adversarial = [_rotor(IDX_E14, 1.5), _rotor(IDX_E35, 1.3), _rotor(IDX_E45, 1.1)]
report = build_feasibility_report(train, held_out, adversarial)
assert report["cross_cohort_top2_cosine_similarity"] > 0.7
assert "POSITIVE" in report["verdict"]["honest_finding"]
def test_report_schema_shape():
train = [_rotor(IDX_E12, 0.1 * i + 0.05) for i in range(10)]
held_out = [_rotor(IDX_E13, 0.1 * i + 0.05) for i in range(10)]
adversarial = [_rotor(IDX_E14, 1.5)]
report = build_feasibility_report(train, held_out, adversarial)
assert report["schema_version"] == "adr_0246_grounding_feasibility_v1"
assert set(report["cohorts"]) == {"train_n", "held_out_n", "adversarial_n"}
assert "honest_finding" in report["verdict"]
def test_module_is_pure_offserving():
import evals.adr_0246_grounding_feasibility as mod
assert mod.__file__ is not None
with open(mod.__file__, encoding="utf-8") as fh:
src = fh.read()
assert "import chat" not in src and "from chat" not in src

View file

@ -0,0 +1,198 @@
"""ADR-0246 Ring-1 §3 — pure induced-action / d_orth / d_stab / typed-residual pins.
These pin the canonical primitives promoted from the slice-0 diagnostic prototype
into ``core.physics.identity_manifold`` (induced action A(F), orthogonality defect
d_orth, typed residual energy) and the new ``core.physics.identity_action`` (the
locked singleton stabilizer H_id={I} and the stabilizer defect d_stab).
Ground truth is the brief §3.1§3.3/§3.6 and §6.1 constructions: identity versor
A=I; an in-span rotation is a G-isometry (d_orth0) but NOT the identity action
(d_stab>0); an in-span permutation/inversion is leakage-invisible but d_stab-visible;
an e4 tilt fires only the null/conformal channel; an e5 boost fires the boost channel
and is non-isometric (d_orth>0). The primitives are pure (algebra-only, off-serving).
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS, basis_vector
from core.physics.identity_manifold import (
IdentityManifoldGeometry,
E4_GRADE1_INDEX,
E5_GRADE1_INDEX,
)
from core.physics.identity_action import (
IdentityStabilizer,
stabilizer_defect,
stabilizer_defect_for_versor,
)
# grade-2 bivector plane indices (grade-2 block starts at 6)
_E12, _E13, _E14, _E15, _E23, _E24, _E25 = 6, 7, 8, 9, 10, 11, 12
def _rotor(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _boost(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cosh(theta / 2.0)
r[biv] = np.sinh(theta / 2.0)
return r
def _identity_versor() -> np.ndarray:
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
@pytest.fixture(scope="module")
def geometry() -> IdentityManifoldGeometry:
# default pack: span(e1,e2,e3), Gram = I3
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
def test_blade_index_constants_match_algebra():
assert basis_vector(3)[E4_GRADE1_INDEX] == 1.0 # e4
assert basis_vector(4)[E5_GRADE1_INDEX] == 1.0 # e5
assert np.count_nonzero(basis_vector(3)) == 1
assert np.count_nonzero(basis_vector(4)) == 1
def test_identity_versor_action_is_identity(geometry):
action = geometry.induced_action(_identity_versor())
assert np.allclose(action, np.eye(3), atol=1e-12)
assert geometry.orthogonality_defect(_identity_versor()) < 1e-12
assert stabilizer_defect_for_versor(geometry, _identity_versor()) < 1e-12
def test_inplane_rotation_is_isometry_but_not_identity_action(geometry):
theta = 0.4
versor = _rotor(_E12, theta)
action = geometry.induced_action(versor)
# e12 rotor rotates the e1/e2 plane; e3 fixed.
assert action[2, 2] == pytest.approx(1.0, abs=1e-9)
assert abs(action[0, 0]) == pytest.approx(abs(np.cos(theta)), abs=1e-6)
assert geometry.orthogonality_defect(versor) < 1e-6 # G-isometry
assert stabilizer_defect_for_versor(geometry, versor) > 0.05 # not H_id={I}
def test_permutation_and_inversion_are_leakage_invisible_but_dstab_visible(geometry):
for versor in (_rotor(_E12, np.pi / 2.0), _rotor(_E12, np.pi)):
leak, _ = geometry.axis_response(versor)
assert max(leak) < 1e-6
assert stabilizer_defect_for_versor(geometry, versor) > 0.05
def test_e4_tilt_fires_only_null_conformal_channel(geometry):
channels = geometry.typed_residual_energy(_rotor(_E14, 1.2))
assert channels["null_or_conformal"] > 0.05
assert channels["boost_like"] == pytest.approx(0.0, abs=1e-12)
assert channels["unclassified"] < 1e-9
def test_e5_boost_fires_boost_channel_and_is_non_isometric(geometry):
versor = _boost(_E15, 1.0)
channels = geometry.typed_residual_energy(versor)
assert channels["boost_like"] > 0.05
assert channels["null_or_conformal"] == pytest.approx(0.0, abs=1e-12)
assert geometry.orthogonality_defect(versor) > 0.05 # boost not a G-isometry
def test_spatial_foreign_channel_is_zero_for_default_pack_by_construction():
"""Resolves the open uncertainty from the Fable/Opus handoff notes: is
``spatial_foreign`` structurally broken? No for the DEFAULT 3-axis pack
(support = e1,e2,e3, i.e. the full spatial grade-1 block), the rejection
``rotated - project(rotated)`` is by construction orthogonal to e1/e2/e3, so
this channel is TAUTOLOGICALLY zero there is no "spatial but outside
support" direction left when the support IS all of span(e1,e2,e3).
"""
geom3 = IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
for versor in (_rotor(_E14, 1.3), _boost(_E25, 0.9), _rotor(_E12, 2.0)):
assert geom3.typed_residual_energy(versor)["spatial_foreign"] == pytest.approx(
0.0, abs=1e-12
)
def test_spatial_foreign_channel_fires_for_reduced_support_pack():
"""A pack whose declared axes do NOT span all of e1/e2/e3 (here: only
e1/e2) has a genuine "spatial but outside support" direction (e3), and a
versor tilting an axis toward it must register nonzero ``spatial_foreign``
confirming the channel is correct in general, not merely inert.
"""
geom2 = IdentityManifoldGeometry.from_directions(((1.0, 0.0, 0.0), (0.0, 1.0, 0.0)))
tilt_toward_e3 = _rotor(_E13, 1.0) # e13 tilts axis e1 toward e3 (out-of-support)
channels = geom2.typed_residual_energy(tilt_toward_e3)
assert channels["spatial_foreign"] > 0.05
assert channels["null_or_conformal"] == pytest.approx(0.0, abs=1e-12)
assert channels["boost_like"] == pytest.approx(0.0, abs=1e-12)
def test_typed_residual_energy_fractions_are_bounded_and_clean(geometry):
for versor in (_rotor(_E14, 0.7), _boost(_E25, 0.6), _rotor(_E12, 0.3)):
ch = geometry.typed_residual_energy(versor)
total = (
ch["null_or_conformal"]
+ ch["boost_like"]
+ ch["spatial_foreign"]
+ ch["unclassified"]
)
assert 0.0 <= total <= 1.0 + 1e-9
# sandwich output of a versor stays grade-1: no unclassified contamination
assert ch["unclassified"] < 1e-9
def test_stabilizer_is_singleton_identity_by_default(geometry):
stab = IdentityStabilizer.singleton(3)
assert len(stab.members) == 1
assert np.allclose(stab.members[0], np.eye(3))
# d_stab of the identity action is 0; of a rotation, > 0
eye = np.eye(3)
assert stabilizer_defect(eye, geometry.gram, stab) < 1e-12
rot = geometry.induced_action(_rotor(_E12, 0.5))
assert stabilizer_defect(rot, geometry.gram, stab) > 0.05
def test_stabilizer_defect_g_weighted_reduces_to_frobenius_at_identity_gram(geometry):
action = geometry.induced_action(_rotor(_E13, 0.35))
stab = IdentityStabilizer.singleton(3)
d = stabilizer_defect(action, geometry.gram, stab)
frob = float(np.linalg.norm(action - np.eye(3), ord="fro"))
assert d == pytest.approx(frob, abs=1e-9) # default pack Gram is I3
def test_induced_action_is_deterministic(geometry):
versor = _boost(_E15, 0.9)
a1 = geometry.induced_action(versor)
a2 = geometry.induced_action(versor.copy())
assert np.array_equal(a1, a2)
def test_primitives_are_pure_offserving():
import core.physics.identity_manifold as m
import core.physics.identity_action as a
for mod in (m, a):
with open(mod.__file__, encoding="utf-8") as fh:
src = fh.read()
assert "chat.runtime" not in src
assert "import chat" not in src
def test_gate_surface_untouched_by_this_branch():
from core.config import RuntimeConfig
from core.physics import identity
assert RuntimeConfig().identity_wave_gate is False
assert identity._WAVE_LEAKAGE_BOUND == 0.2126624458513829

View file

@ -0,0 +1,249 @@
"""ADR-0246 §3.4/§3.5 — lawful-only identity-path ledger pins (§6.2 path suite).
The path ledger composes ONLY the induced actions of turns that were individually
certified lawful (``d_stab ε_turn`` under the locked singleton ``H_id={I}``).
Refused turns insert a break marker and are excluded from the product never a
soft-projected identity matrix masquerading as a pass (brief §3.4 / non-goal #11).
A scope change (pack digest / geometry / policy / session / biography epoch) forces
a hard break: a new ``chain_id`` and a fresh path (§3.5). Pure, off-serving.
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from core.physics.identity_manifold import IdentityManifoldGeometry
from core.physics.identity_action import (
IdentityChainScope,
PathBudget,
advance_identity_path,
raw_path_product,
)
_E12, _E13 = 6, 7
def _rotor(biv: int, theta: float) -> np.ndarray:
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _identity_versor() -> np.ndarray:
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
@pytest.fixture(scope="module")
def geometry() -> IdentityManifoldGeometry:
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
def _scope(pack="packA", geom="geomV1", policy="polV1", session="sess1", bio=None):
return IdentityChainScope(
pack_content_digest=pack,
geometry_version=geom,
policy_version=policy,
session_id=session,
biography_epoch=bio,
)
_BUDGET = PathBudget(epsilon_turn=0.1, epsilon_session=0.3)
def _action(geometry, versor):
return geometry.induced_action(versor)
def test_first_lawful_turn_starts_chain_near_identity(geometry):
ledger, rec = advance_identity_path(
None, _scope(), _action(geometry, _identity_versor()), geometry.gram, _BUDGET
)
assert rec["hard_break"] is True
assert rec["lawful"] is True and rec["path_break"] is False
assert ledger.composed_turn_count == 1 and ledger.break_count == 0
assert np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12)
assert ledger.d_stab_path < 1e-12
assert ledger.session_admit is True
def test_lawful_identity_sequence_stays_admitted(geometry):
ledger = None
for _ in range(20):
ledger, _ = advance_identity_path(
ledger, _scope(), _action(geometry, _identity_versor()), geometry.gram, _BUDGET
)
assert ledger.composed_turn_count == 20 and ledger.break_count == 0
assert np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12)
assert ledger.session_admit is True
def test_small_rotations_accumulate_to_session_refusal(geometry):
small = _action(geometry, _rotor(_E12, 0.05)) # each turn is lawful (small d_stab)
ledger = None
admitted_turns = 0
for _ in range(40):
ledger, rec = advance_identity_path(ledger, _scope(), small, geometry.gram, _BUDGET)
assert rec["lawful"] is True # each small step passes ε_turn
admitted_turns += 1
if not ledger.session_admit:
break
# per-turn always lawful, but the composed path eventually breaches ε_session
assert ledger.session_admit is False
assert ledger.d_stab_path > _BUDGET.epsilon_session
assert ledger.composed_turn_count == admitted_turns
def test_refused_turn_is_break_and_excluded(geometry):
ledger, _ = advance_identity_path(
None, _scope(), _action(geometry, _identity_versor()), geometry.gram, _BUDGET
)
before = ledger.a_path_lawful.copy()
big = _action(geometry, _rotor(_E12, np.pi / 2.0)) # 90° rotation: d_stab huge
ledger, rec = advance_identity_path(ledger, _scope(), big, geometry.gram, _BUDGET)
assert rec["lawful"] is False and rec["path_break"] is True
assert ledger.break_count == 1 and ledger.composed_turn_count == 1
# the refused action does NOT compose (no soft-projected I either): path unchanged
assert np.allclose(ledger.a_path_lawful, before, atol=1e-12)
def test_interleaved_refuse_admit_records_raw(geometry):
ident = _action(geometry, _identity_versor())
big = _action(geometry, _rotor(_E12, np.pi / 2.0))
seq = [ident, big, ident, big, ident]
ledger = None
records = []
for a in seq:
ledger, rec = advance_identity_path(ledger, _scope(), a, geometry.gram, _BUDGET)
records.append(rec)
assert ledger.composed_turn_count == 3 and ledger.break_count == 2
assert [r["path_break"] for r in records] == [False, True, False, True, False]
def test_hard_break_on_pack_digest_change(geometry):
ident = _action(geometry, _identity_versor())
ledger, _ = advance_identity_path(None, _scope(pack="packA"), ident, geometry.gram, _BUDGET)
id_a = ledger.chain_id
# drift the path a little so "not continued" is observable
small = _action(geometry, _rotor(_E12, 0.05))
ledger, _ = advance_identity_path(ledger, _scope(pack="packA"), small, geometry.gram, _BUDGET)
drifted = ledger.a_path_lawful.copy()
# pack change → hard break
ledger, rec = advance_identity_path(ledger, _scope(pack="packB"), ident, geometry.gram, _BUDGET)
assert rec["hard_break"] is True
assert ledger.chain_id != id_a
assert ledger.composed_turn_count == 1 and ledger.break_count == 0 # fresh chain
assert not np.allclose(ledger.a_path_lawful, drifted) # old path not continued
assert np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12)
@pytest.mark.parametrize(
"changed",
[
{"geom": "geomV2"},
{"policy": "polV2"},
{"session": "sess2"},
{"bio": "epoch2"},
],
)
def test_hard_break_on_each_scope_dimension(geometry, changed):
ident = _action(geometry, _identity_versor())
ledger, _ = advance_identity_path(None, _scope(), ident, geometry.gram, _BUDGET)
base_id = ledger.chain_id
ledger, rec = advance_identity_path(ledger, _scope(**changed), ident, geometry.gram, _BUDGET)
assert rec["hard_break"] is True
assert ledger.chain_id != base_id
def test_raw_product_differs_from_lawful_product(geometry):
ident = _action(geometry, _identity_versor())
big = _action(geometry, _rotor(_E12, np.pi / 2.0))
seq = [ident, big, ident]
ledger = None
for a in seq:
ledger, _ = advance_identity_path(ledger, _scope(), a, geometry.gram, _BUDGET)
# forensic pin: composing ALL raw actions (incl. the refused 90°) gives a very
# different result than the lawful-only product — the category error §3.4 forbids.
raw = raw_path_product(seq)
assert not np.allclose(raw, ledger.a_path_lawful)
assert np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12) # lawful excludes the big turn
def test_chain_id_is_deterministic_full_sha256(geometry):
ident = _action(geometry, _identity_versor())
l1, _ = advance_identity_path(None, _scope(), ident, geometry.gram, _BUDGET)
l2, _ = advance_identity_path(None, _scope(), ident, geometry.gram, _BUDGET)
assert l1.chain_id == l2.chain_id
assert len(l1.chain_id) == 64
int(l1.chain_id, 16) # valid hex
def test_ledger_digest_deterministic_and_path_sensitive(geometry):
ident = _action(geometry, _identity_versor())
small = _action(geometry, _rotor(_E13, 0.05))
l1, _ = advance_identity_path(None, _scope(), ident, geometry.gram, _BUDGET)
l1b, _ = advance_identity_path(None, _scope(), ident, geometry.gram, _BUDGET)
assert l1.ledger_digest() == l1b.ledger_digest()
assert len(l1.ledger_digest()) == 64
l2, _ = advance_identity_path(l1, _scope(), small, geometry.gram, _BUDGET)
assert l2.ledger_digest() != l1.ledger_digest()
def test_advance_is_immutable(geometry):
ident = _action(geometry, _identity_versor())
ledger, _ = advance_identity_path(None, _scope(), ident, geometry.gram, _BUDGET)
snapshot = ledger.a_path_lawful.copy()
count_before = ledger.composed_turn_count
_new, _ = advance_identity_path(
ledger, _scope(), _action(geometry, _rotor(_E12, 0.05)), geometry.gram, _BUDGET
)
assert ledger.composed_turn_count == count_before # original untouched
assert np.allclose(ledger.a_path_lawful, snapshot)
def test_as_dict_shape(geometry):
ledger, _ = advance_identity_path(
None, _scope(), _action(geometry, _identity_versor()), geometry.gram, _BUDGET
)
d = ledger.as_dict()
assert d["schema_version"] == "identity_path_v1"
assert d["chain_id"] == ledger.chain_id
assert d["composed_turn_count"] == 1
assert d["break_count"] == 0
assert d["session_admit"] is True
assert "a_path_lawful" in d and "d_stab_path" in d and "ledger_digest" in d
def test_lawful_path_equals_lawful_subproduct_not_raw(geometry):
# HARDENING (ADR-0246 §3.4): a mixed sequence of small LAWFUL rotations
# interleaved with a large REFUSED rotation must compose to exactly the
# product of the lawful actions alone. This fails loudly if the raw product
# (which would include the refused 90° turn) ever sneaks into a_path_lawful.
small_a = _action(geometry, _rotor(_E12, 0.03))
small_b = _action(geometry, _rotor(_E13, 0.04))
big = _action(geometry, _rotor(_E12, np.pi / 2.0)) # refused (d_stab huge)
seq = [small_a, big, small_b, big, small_a]
ledger = None
for a in seq:
ledger, _ = advance_identity_path(ledger, _scope(), a, geometry.gram, _BUDGET)
# independently: product of the LAWFUL turns only, in time order (later on left)
expected = small_a @ (small_b @ small_a)
assert ledger.composed_turn_count == 3 and ledger.break_count == 2
assert np.allclose(ledger.a_path_lawful, expected, atol=1e-12)
# and it must NOT equal the raw product (which includes the two big turns)
assert not np.allclose(ledger.a_path_lawful, raw_path_product(seq))
def test_module_is_pure_offserving():
import core.physics.identity_action as a
with open(a.__file__, encoding="utf-8") as fh:
src = fh.read()
assert "chat.runtime" not in src and "import chat" not in src

View file

@ -0,0 +1,202 @@
"""ADR-0246 §3.4/§3.5 serve integration pins — session identity-path ledger.
Pins the §3.4-step-2 ``admitted`` gate on the pure ledger (a policy-refused turn
must break even when its d_stab is small), the ``advance_session_identity_path``
serve helper (scope from manifold digest + version ids; observe-only), the
runtime wiring (ledger advanced only when both flags are on; instance lifetime
is the session boundary), and the telemetry emission (identity_path_* keys only
when the path ran flag-off wire format byte-identical).
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cl41 import N_COMPONENTS
from core.config import RuntimeConfig
from core.physics.identity import (
GEOMETRY_VERSION,
IdentityManifold,
ValueAxis,
advance_session_identity_path,
manifold_content_digest,
)
from core.physics.identity_action import (
AdmissionPolicy,
IdentityChainScope,
PathBudget,
advance_identity_path,
)
from core.physics.identity_manifold import IdentityManifoldGeometry
from chat.telemetry import serialize_turn_event
_E12, _E14 = 6, 8
def _rotor(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cos(theta / 2.0)
r[biv] = np.sin(theta / 2.0)
return r
def _boost(biv, theta):
r = np.zeros(N_COMPONENTS, dtype=np.float64)
r[0] = np.cosh(theta / 2.0)
r[biv] = np.sinh(theta / 2.0)
return r
def _identity_versor():
v = np.zeros(N_COMPONENTS, dtype=np.float64)
v[0] = 1.0
return v
def _manifold():
return IdentityManifold(
value_axes=(
ValueAxis(name="truthfulness", direction=(1.0, 0.0, 0.0)),
ValueAxis(name="coherence", direction=(0.0, 1.0, 0.0)),
ValueAxis(name="reverence", direction=(0.0, 0.0, 1.0)),
)
)
@pytest.fixture(scope="module")
def geometry():
return IdentityManifoldGeometry.from_directions(
((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
)
# --- §3.4 step-2: the admitted gate on the pure ledger --------------------------
def test_policy_refused_turn_breaks_even_with_small_d_stab(geometry):
scope = IdentityChainScope(
pack_content_digest="p", geometry_version="g", policy_version="v",
session_id="s",
)
budget = PathBudget(epsilon_turn=0.1, epsilon_session=0.3)
small = geometry.induced_action(_rotor(_E12, 0.02)) # d_stab well under 0.1
# admitted=False (e.g. refused on leakage alone) MUST break, not compose
ledger, rec = advance_identity_path(
None, scope, small, geometry.gram, budget, admitted=False
)
assert rec["lawful"] is False and rec["path_break"] is True
assert ledger.composed_turn_count == 0 and ledger.break_count == 1
assert np.allclose(ledger.a_path_lawful, np.eye(3), atol=1e-12)
# same action with admitted=True composes
ledger2, rec2 = advance_identity_path(
None, scope, small, geometry.gram, budget, admitted=True
)
assert rec2["lawful"] is True and ledger2.composed_turn_count == 1
# --- advance_session_identity_path (serve helper) -------------------------------
def test_session_path_near_identity_composes():
policy = AdmissionPolicy.placeholder_default()
ledger, rec = advance_session_identity_path(
None, _manifold(), _identity_versor(), policy
)
assert rec["hard_break"] is True and rec["lawful"] is True
assert ledger.composed_turn_count == 1 and ledger.session_admit is True
assert ledger.scope.pack_content_digest == manifold_content_digest(_manifold())
assert ledger.scope.geometry_version == GEOMETRY_VERSION
def test_session_path_refused_turn_breaks():
policy = AdmissionPolicy.placeholder_default()
ledger, _ = advance_session_identity_path(
None, _manifold(), _identity_versor(), policy
)
ledger, rec = advance_session_identity_path(
ledger, _manifold(), _rotor(_E14, 1.5), policy # alien tilt: refused
)
assert rec["lawful"] is False and rec["path_break"] is True
assert ledger.break_count == 1 and ledger.composed_turn_count == 1
def test_session_path_hard_breaks_on_pack_change():
policy = AdmissionPolicy.placeholder_default()
ledger, _ = advance_session_identity_path(
None, _manifold(), _identity_versor(), policy
)
first_chain = ledger.chain_id
other_manifold = IdentityManifold(value_axes=_manifold().value_axes[:2])
ledger, rec = advance_session_identity_path(
ledger, other_manifold, _identity_versor(), policy
)
assert rec["hard_break"] is True
assert ledger.chain_id != first_chain
# --- telemetry ------------------------------------------------------------------
class _Event:
turn = 1
identity_score = None
identity_path = None
def test_telemetry_no_path_keys_when_absent():
payload = serialize_turn_event(_Event())
assert not any(k.startswith("identity_path_") for k in payload)
def test_telemetry_emits_path_keys_when_present():
policy = AdmissionPolicy.placeholder_default()
ledger, _ = advance_session_identity_path(
None, _manifold(), _identity_versor(), policy
)
ev = _Event()
ev.identity_path = ledger
payload = serialize_turn_event(ev)
assert payload["identity_path_chain_id"] == ledger.chain_id
assert payload["identity_path_composed_turns"] == 1
assert payload["identity_path_breaks"] == 0
assert payload["identity_path_session_admit"] is True
# --- runtime wiring (flag-gated; observe-only) ----------------------------------
def test_runtime_ledger_attribute_defaults_none_and_flag_off_never_advances():
from chat.runtime import ChatRuntime
runtime = ChatRuntime(config=RuntimeConfig(), no_load_state=True)
assert runtime._identity_path_ledger is None
runtime.chat("water boils")
assert runtime._identity_path_ledger is None # both flags off: never advanced
# and the emitted turn event carries no path ledger
assert runtime.turn_log[-1].identity_path is None
def test_runtime_ledger_advances_when_both_flags_on():
from chat.runtime import ChatRuntime
runtime = ChatRuntime(
config=RuntimeConfig(identity_wave_gate=True, identity_action_surface=True),
no_load_state=True,
)
# Not every turn reaches the wave-path check (first-touch turns can take
# the stub path — same reason slice-0 captured 13/16 probe turns), so run
# the duplicated-probe pattern until one main-path turn advances the ledger.
for text in ("water boils", "water boils", "birds fly", "birds fly"):
runtime.chat(text)
if runtime._identity_path_ledger is not None:
break
ledger = runtime._identity_path_ledger
assert ledger is not None
assert ledger.composed_turn_count + ledger.break_count >= 1
# observe-only: chat() raised nothing regardless of session_admit; the
# ledger-bearing turn's event serializes the path keys
ledger_events = [e for e in runtime.turn_log if e.identity_path is not None]
assert ledger_events, "no turn event carried the path ledger"
payload = serialize_turn_event(ledger_events[-1])
assert "identity_path_chain_id" in payload