draft(adr-0246): slice-1 scaffold — §6.1/§6.2 eval suite + malformed-F guard

BOUNDED AUTONOMOUS SCAFFOLD DRAFT (Fable 5) — not a PR, not merged, no status
flip, no main push. For Opus 4.8 + Shay audit before anything proceeds toward main.
Stacked on the verified §3-primitives + §3.4/3.5-ledger stack (reuse, not re-derive;
all descend from main @ 04d67ca5).

Adds (directive steps 3-4):
  + evals/adr_0246_geometric_suite/  runnable §6.1 synthetic geometric suite
    (identity, pi-inversion, 90deg-permutation, mild drift, alien tilt e14,
    boost e15, near-singular Gram, malformed F) + §6.2 path/holonomy suite
    (lawful sequence, small-rotation session accumulation, interleaved refuse,
    pack-change hard break, raw!=lawful forensic). 14/14 cases pass.
  + tests/test_adr_0246_geometric_suite.py  pins every case + explicit §6.1 pins
    (pi-inversion s=-1, 90deg s=0, near-singular Gram error, malformed-F error)
  + identity_manifold.py: MalformedVersorError + _validate_versor guard on
    induced_action / typed_residual_energy (§6.1 fail-closed on malformed F)
  + docs/handoff/adr-0246-slice1-scaffold-notes.md  placeholder list, §5-§7
    uncertainties, constraint-compliance record, explicit Opus/human TODOs
  + docs/audit/artifacts/adr-0246-slice1-scaffold-runlog.txt  actual run output

Constraints honored: H_id={I} only; no soft-projection of unlawful A; path
composes lawful actions only (never raw product); no C_id corrector; chat/runtime,
flags, D4 gate wiring untouched (A-04 quarantine pinned); no discrimination report,
no ADR body, no claims language (deferred TODO: Opus/human); D4 plan not modified.
epsilon_turn/epsilon_session are UNCERTIFIED PLACEHOLDERS, never baked into a
module default (PathBudget is caller-supplied) — flagged in notes + run log.

[Verification]: uv run core test --suite smoke -q => 176 passed;
python -m evals.adr_0246_geometric_suite => 14/14 all_passed;
ADR-0246 suites + adjacent D4 identity surfaces => 114 passed (see run log).
This commit is contained in:
Shay 2026-07-17 22:09:32 -07:00
parent 6efe4ad80c
commit ed54dddacb
7 changed files with 645 additions and 5 deletions

View file

@ -160,6 +160,28 @@ 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).
@ -270,8 +292,11 @@ class IdentityManifoldGeometry:
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 = np.asarray(versor, dtype=np.float64)
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):
@ -310,8 +335,11 @@ class IdentityManifoldGeometry:
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 = np.asarray(versor, dtype=np.float64)
versor = _validate_versor(versor)
e4_energy = e5_energy = spatial_foreign = unclassified = total = 0.0
for axis in self.axes_psi:
rotated = sandwich(versor, axis)

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

@ -54,9 +54,10 @@ structure is stabilized would instrument lawfulness on a frame the dynamics igno
|------|-------|--------|
| **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** (this unit) | 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 | in progress — RED→GREEN, off-serving; stacked on the primitives branch |
| §3.7 gate admit surface | wire d_orth/d_stab/typed channels into `IdentityScore` (flag default-off) | after ledger |
| §6 eval matrix + §11 feasibility | synthetic + path suites + discrimination report; the invariant/semantic-grounding feasibility study runs here as the **first consumer** of the §3 primitives (fixed cohort splits, synthetic recovery controls, typed e4/e5 generator analysis, precision pairs, adversarial discrimination) | after gate surface |
| **§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 | wire d_orth/d_stab/typed channels into `IdentityScore` (flag default-off); calibrate ε_turn/ε_session | after audit |
| §6.3 + §11 feasibility | discrimination report; the invariant/semantic-grounding feasibility study runs here as the **first consumer** of the §3 primitives (fixed cohort splits, synthetic recovery controls, typed e4/e5 generator analysis, precision pairs, adversarial discrimination) | after gate surface |
| ADR-0246 body + acceptance packet | §10 criteria; no self-Accept | last |
Nothing in the reordering relaxes a §7 non-goal: no `C_id` corrector, no `H_id`

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,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,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