feat(demo): ADR-0074 — orthogonality tour (anchor-lens × register)

A single demo that walks the full 3 × 3 × 2 matrix (register × lens
× prompts, 18 cells) and pins five claims simultaneously, packaging
both single-axis invariants into one composition gate.

The single-axis tours assert opposite invariants:

  register-tour    : per (lens, prompt), trace_hash CONSTANT across
                     registers (R5 / ADR-0072).
  anchor-lens-tour : per (register, prompt), engaged lens diverges
                     in trace_hash from the unanchored baseline
                     (L1.4 / ADR-0073d).

Orthogonality-tour packages both claims simultaneously across the
full matrix, plus three surface-level claims that pin the markers
operators actually see.

Composed claims (all five must hold)

  A) inner_register_invariant_within_lens
     For each (lens, prompt) cell, the three register runs share an
     identical trace_hash.  (R5 register-tour, applied 6 times:
     3 lenses × 2 prompts.)

  B) outer_lens_distinctness_within_register
     For each (register, prompt) cell where any non-unanchored lens
     engages, that engaged lens's trace_hash differs from the
     unanchored baseline at the same (register, prompt).
     (L1.4 anchor-lens-tour, applied 6 times: 3 registers × 2 prompts.)

  C) surface_carries_register_marker_under_convivial
     Every convivial cell with a non-empty surface has a non-empty
     register_variant_id.

  D) surface_carries_lens_annotation_when_engaged
     Every engaged cell carries [lens(<id>):<mode>] in surface AND
     a non-empty anchor_lens_mode_label.

  E) no_substrate_glyph_leak_across_grid
     No cell's surface contains Greek/Hebrew/Syriac/Arabic glyphs.
     (ADR-0073c gate re-asserted across the full matrix.)

CLI wiring

  core demo orthogonality-tour            human-readable grid + claims
  core demo orthogonality-tour --json     structured report

Exit code 0 iff all five claims hold.

Files

  evals/orthogonality_tour/__init__.py             NEW
  evals/orthogonality_tour/run_tour.py             NEW
  core/cli.py                                       EDIT
    - cmd_demo handler wires orthogonality-tour
    - demo choices + EPILOG examples updated
  tests/test_orthogonality_tour_demo.py             NEW (9 tests)
  docs/decisions/ADR-0074-orthogonality-tour.md     NEW

Sanity check baked into tests
  test_engaged_cells_appear_for_both_non_trivial_lenses pins that
  grc_logos_v1 engages on knowledge in all 3 registers (3 cells)
  and he_logos_v1 engages on truth in all 3 registers (3 cells).
  Prevents the lift claims being vacuously satisfied by a future
  engagement regression.

Lane evidence

  - 9 new orthogonality-tour tests pass.
  - core demo register-tour      → all_claims_supported: True
  - core demo anchor-lens-tour   → all_claims_supported: True
  - core demo orthogonality-tour → all_claims_supported: True
  - python -m core.cli eval cognition → byte-identical 100/100/91.7/100.
  - Full lane: 2745 passed / 4 skipped / 1 pre-existing failure
    (+9 over L1.4's 2736; the one failure remains
    test_all_preamble_explains_combined_run, unrelated).

No runtime / composer / loader / pack / schema changes.  Pure demo
consumer of existing telemetry contracts.
This commit is contained in:
Shay 2026-05-19 20:33:33 -07:00
parent 1feec74b1c
commit 4426f387d1
5 changed files with 649 additions and 1 deletions

View file

@ -23,7 +23,7 @@ _CORE_RS_DIR = _REPO_ROOT / "core-rs"
_CORE_RS_MANIFEST = _CORE_RS_DIR / "Cargo.toml"
DESCRIPTION = "CORE versor engine command suite."
EPILOG = "Examples:\n core chat\n core pulse \"What is truth?\"\n core pulse --no-glove --json \"Compare knowledge and wisdom\"\n core bench\n core bench --suite all\n core bench --suite all --json --report bench_all.json\n core bench --suite determinism --runs 50\n core bench --suite speedup --json\n core trace \"word beginning truth\"\n core trace --output-language grc --frame-pack grc --json \"logos\"\n core rust status\n core rust build\n core oov covenant\n core pack list\n core pack verify en_minimal_v1\n core teaching audit\n core teaching audit --json\n core teaching gaps --top 10\n core teaching queue --threshold 3\n core teaching propose <candidate-jsonl-path>\n core teaching proposals --state pending\n core teaching review <proposal_id> --accept --review-date 2026-05-18\n core teaching supersede cause_light_reveals_truth --subject light --intent cause --connective grounds --object truth --review-date 2026-05-18\n core teaching supersessions\n core teaching supersessions --json\n core test --suite fast -q\n core test --suite pulse -q\n core test --suite proof -q\n core test --suite cognition -q\n core test -- tests/test_alignment_graph.py -q\n core demo audit-tour\n core demo register-tour\n core demo anchor-lens-tour\n core demo pack-measurements\n core demo long-context-comparison\n core demo anti-regression\n core demo learning-loop\n core demo articulation\n core demo conversation\n core demo conversation --no-stream\n core demo all\n core demo adr-0024-chain\n core eval --list\n core eval cognition\n core eval cognition --json --save\n core eval cognition --split dev --version v1\n core eval cognition --split holdout"
EPILOG = "Examples:\n core chat\n core pulse \"What is truth?\"\n core pulse --no-glove --json \"Compare knowledge and wisdom\"\n core bench\n core bench --suite all\n core bench --suite all --json --report bench_all.json\n core bench --suite determinism --runs 50\n core bench --suite speedup --json\n core trace \"word beginning truth\"\n core trace --output-language grc --frame-pack grc --json \"logos\"\n core rust status\n core rust build\n core oov covenant\n core pack list\n core pack verify en_minimal_v1\n core teaching audit\n core teaching audit --json\n core teaching gaps --top 10\n core teaching queue --threshold 3\n core teaching propose <candidate-jsonl-path>\n core teaching proposals --state pending\n core teaching review <proposal_id> --accept --review-date 2026-05-18\n core teaching supersede cause_light_reveals_truth --subject light --intent cause --connective grounds --object truth --review-date 2026-05-18\n core teaching supersessions\n core teaching supersessions --json\n core test --suite fast -q\n core test --suite pulse -q\n core test --suite proof -q\n core test --suite cognition -q\n core test -- tests/test_alignment_graph.py -q\n core demo audit-tour\n core demo register-tour\n core demo anchor-lens-tour\n core demo orthogonality-tour\n core demo pack-measurements\n core demo long-context-comparison\n core demo anti-regression\n core demo learning-loop\n core demo articulation\n core demo conversation\n core demo conversation --no-stream\n core demo all\n core demo adr-0024-chain\n core eval --list\n core eval cognition\n core eval cognition --json --save\n core eval cognition --split dev --version v1\n core eval cognition --split holdout"
_TEST_SUITES: dict[str, tuple[str, ...]] = {
"fast": (
@ -1981,6 +1981,14 @@ def cmd_demo(args: argparse.Namespace) -> int:
print(json.dumps(result, indent=2, sort_keys=True, default=str))
return 0 if result.get("all_claims_supported", False) else 1
if target == "orthogonality-tour":
from evals.orthogonality_tour.run_tour import run_tour as run_ortho_tour
result = run_ortho_tour(emit_json=args.json)
if args.json:
print(json.dumps(result, indent=2, sort_keys=True, default=str))
return 0 if result.get("all_claims_supported", False) else 1
if target == "pack-measurements":
from scripts.publish_pack_measurements import (
build_combined_report,
@ -2877,6 +2885,7 @@ def build_parser() -> argparse.ArgumentParser:
"audit-tour",
"register-tour",
"anchor-lens-tour",
"orthogonality-tour",
"pack-measurements",
"long-context-comparison",
"anti-regression",
@ -2901,6 +2910,9 @@ def build_parser() -> argparse.ArgumentParser:
"prompts × three lenses; trace_hash DISTINCT across lenses, "
"no substrate glyph leak. Opposite invariant from register-tour; "
"both must hold continuously. "
"orthogonality-tour: ADR-0074 composition demo — full 3 × 3 × 2 "
"matrix (register × lens × prompts, 18 cells); pins five "
"claims simultaneously including both single-axis invariants. "
"pack-measurements: ADR-0043 — pack-layer claims → CI-enforced "
"numbers across the three ratified identity packs. "
"long-context-comparison: ADR-0045 — CORE exact recall NIAH at "

View file

@ -0,0 +1,181 @@
# ADR-0074 — Orthogonality tour: anchor-lens × register composition demo
**Status:** Accepted
**Date:** 2026-05-19
**Ratified:** 2026-05-19
**Author:** Shay
**Builds on:** [ADR-0072](./ADR-0072-register-telemetry-operator-surface.md)
(register-tour, R5), [ADR-0073d](./ADR-0073d-anchor-lens-telemetry-tour.md)
(anchor-lens-tour, L1.4)
---
## Context
Two single-axis tours ship today:
* `core demo register-tour` — pins `trace_hash CONSTANT` across
registers within a fixed lens.
* `core demo anchor-lens-tour` — pins `trace_hash DISTINCT` across
lenses within a fixed register.
L1.3's `test_register_seam_within_lens_holds` already parametrizes
the inner claim over every lens choice. ADR-0074 packages **both
claims simultaneously** into a single demo that walks the full
register × lens × prompt matrix and asserts the orthogonality holds
turn-by-turn across the entire grid.
Without this composition demo, an operator can verify each axis
independently but has no single artifact answering the question:
> When I drive `core chat --register X --anchor-lens Y`, are the two
> axes actually independent, or does some unintended coupling
> sneak in?
ADR-0074 ships that artifact as `core demo orthogonality-tour`.
---
## Decision
### Demo shape
A single 3 × 3 × 2 grid:
* **Lenses (3):** `default_unanchored_v1`, `grc_logos_v1`, `he_logos_v1`
* **Registers (3):** `default_neutral_v1`, `terse_v1`, `convivial_v1`
* **Prompts (2):** `"What is knowledge?"` (grc engages),
`"What is truth?"` (he engages)
That is 18 cells. For each cell the demo records:
```
surface, trace_hash, grounding_source,
register_id, register_variant_id,
anchor_lens_id, anchor_lens_mode_label
```
### Composed claims
```
A) inner_register_invariant_within_lens:
For each (lens, prompt) cell, the three register runs share an
identical trace_hash.
(R5 register-tour, applied 6 times: 3 lenses × 2 prompts.)
B) outer_lens_distinctness_within_register:
For each (register, prompt) cell where any non-unanchored lens
engages, that engaged lens's trace_hash differs from the
unanchored baseline's trace_hash for the same (register, prompt).
(L1.4 anchor-lens-tour, applied 6 times: 3 registers × 2 prompts.)
C) surface_carries_register_marker_under_convivial:
For every convivial cell with a non-empty surface,
register_variant_id is non-empty (convivial always picks an
opening from its non-empty bucket).
D) surface_carries_lens_annotation_when_engaged:
For every cell where a non-unanchored lens engages on the
prompt's en lemma, the surface contains `[lens(<id>):<mode>]`
and anchor_lens_mode_label is non-empty.
E) no_substrate_glyph_leak_across_grid:
No cell's surface contains Greek/Hebrew/Syriac/Arabic letter
blocks. (ADR-0073c gate re-asserted across the full matrix.)
```
The five claims together pin the orthogonality: A says register
varies the surface without changing the proposition; B says lens
varies the proposition; C and D say the user-visible markers behave
as expected; E says no axis leaks substrate glyphs even under
composition.
### Files
```
evals/orthogonality_tour/__init__.py NEW
evals/orthogonality_tour/run_tour.py NEW
core/cli.py EDIT
- cmd_demo handler wires orthogonality-tour
- demo target choices add "orthogonality-tour"
- cmd_demo description gains a line for orthogonality-tour
- EPILOG gains "core demo orthogonality-tour"
tests/test_orthogonality_tour_demo.py NEW
- Five claims pinned individually
- all_claims_supported overall
- grid shape sanity check (3 × 3 × 2 = 18 cells)
docs/decisions/ADR-0074-orthogonality-tour.md NEW (this file)
```
No runtime, composer, loader, pack, or schema changes. The demo is
a pure consumer of the existing telemetry contracts.
### Invariants pinned
```
register-tour (R5) — preserved
anchor-lens-tour (L1.4) — preserved
register_invariant_grounding (R3) — preserved
anchor_lens_byte_identity_null_lift (L1.2) — preserved
anchor_lens_lifts_proposition (L1.3) — preserved
anchor_lens_no_glyph_leak (L1.3) — preserved
invariant_orthogonality_tour_seam (NEW):
evals/orthogonality_tour/run_tour.py asserts the five composed
claims above on the full 3 × 3 × 2 grid. Exits non-zero on any
violation. Pinned by tests/test_orthogonality_tour_demo.py.
```
---
## Consequences
### Capability unlocked
A single command answers "are register and anchor-lens genuinely
orthogonal under composition?" with structured evidence — 18 cells'
worth of surfaces, trace hashes, and telemetry fields, plus five
falsifiable claim booleans.
### Cognition lane
Unchanged. The demo is consumer-only; no production code path is
touched.
### Performance
The demo runs 18 chat turns sequentially. At current per-turn
latency this lands in single-digit seconds. No caching changes.
### Trust boundaries
* No new mutation surface. Demo only reads telemetry.
* Glyph-leak gate is re-asserted in the demo's own claim bundle so
it can never silently regress under composition.
* CLI choice list is the only operator-visible change; the
underlying flags (`--register`, `--anchor-lens`) are unchanged.
---
## Verification
```
python -m pytest tests/test_orthogonality_tour_demo.py -q N passed
core demo orthogonality-tour exit 0
core demo orthogonality-tour --json stable schema
Curated lanes (must remain green):
smoke / cognition / teaching / packs / runtime / algebra
Existing single-axis tours continue to pass:
core demo register-tour exit 0
core demo anchor-lens-tour exit 0
```
The orthogonality tour's exit code is the canonical composition
gate — if it ever exits non-zero in CI, the orthogonality between
the two axes has regressed and one of the single-axis tours is also
likely to be failing.

View file

@ -0,0 +1,4 @@
"""Orthogonality tour — composes register × anchor-lens × prompts
into a single 3 × 3 × 2 grid and asserts five orthogonality claims
hold under composition. See ``run_tour.py``.
"""

View file

@ -0,0 +1,345 @@
"""Orthogonality tour — composes register × anchor-lens × prompts in
one 3 × 3 × 2 grid (ADR-0074).
The single-axis tours assert opposite invariants:
register-tour : per (lens, prompt), trace_hash CONSTANT across
registers (R5 / ADR-0072).
anchor-lens-tour : per (register=neutral, prompt), trace_hash
DISTINCT across engaging lenses
(L1.4 / ADR-0073d).
This tour packages both claims simultaneously into a single demo
that walks the full register × lens × prompt matrix and asserts
the orthogonality holds turn-by-turn across all 18 cells.
Composed claims
---------------
* **A) inner_register_invariant_within_lens** for each
(lens, prompt), the three register runs share an identical
trace_hash.
* **B) outer_lens_distinctness_within_register** for each
(register, prompt) where any non-unanchored lens engages, the
engaged lens's trace_hash differs from the unanchored baseline.
* **C) surface_carries_register_marker_under_convivial** every
convivial cell with a non-empty surface has a non-empty
``register_variant_id``.
* **D) surface_carries_lens_annotation_when_engaged** every
engaged cell carries the ``[lens(<id>):<mode>]`` annotation and a
non-empty ``anchor_lens_mode_label``.
* **E) no_substrate_glyph_leak_across_grid** no cell's surface
contains Greek/Hebrew/Syriac/Arabic glyphs.
Exit code 0 iff every claim holds.
"""
from __future__ import annotations
import json
from typing import Any
from chat.runtime import ChatRuntime
from core.cognition.pipeline import CognitiveTurnPipeline
from core.config import RuntimeConfig
_REGISTERS = (
"default_neutral_v1",
"terse_v1",
"convivial_v1",
)
_LENSES = (
"default_unanchored_v1",
"grc_logos_v1",
"he_logos_v1",
)
_PROMPTS = (
"What is knowledge?",
"What is truth?",
)
_FORBIDDEN_BLOCKS: tuple[tuple[int, int, str], ...] = (
(0x0370, 0x03FF, "Greek and Coptic"),
(0x1F00, 0x1FFF, "Greek Extended"),
(0x0590, 0x05FF, "Hebrew"),
(0x0700, 0x074F, "Syriac"),
(0x0600, 0x06FF, "Arabic"),
)
_VERBOSE = True
def _say(*args: Any, **kwargs: Any) -> None:
if _VERBOSE:
print(*args, **kwargs)
def _print_header() -> None:
_say()
_say("=" * 76)
_say(" CORE Orthogonality Tour — register × anchor-lens × prompts")
_say("=" * 76)
_say(
" Walks the full 3 × 3 × 2 matrix (18 cells) and asserts:\n"
" A) varying register inside a fixed lens keeps trace_hash CONSTANT\n"
" B) varying lens inside a fixed register moves trace_hash where\n"
" the lens engages (DISTINCT from unanchored baseline)\n"
" C) convivial register attaches discourse markers\n"
" D) engaged lens emits [lens(<id>):<mode>] annotations\n"
" E) no substrate glyphs (Greek/Hebrew/…) leak into surfaces\n"
"\n"
" Together these pin orthogonality under composition — register and\n"
" anchor-lens never interfere even when both flags are set."
)
_say()
def _substrate_glyph_violations(surface: str) -> list[tuple[int, str, str]]:
out: list[tuple[int, str, str]] = []
for i, ch in enumerate(surface):
cp = ord(ch)
for start, end, label in _FORBIDDEN_BLOCKS:
if start <= cp <= end:
out.append((i, ch, label))
break
return out
def _run_one_cell(register_id: str, lens_id: str, prompt: str) -> dict[str, Any]:
runtime = ChatRuntime(config=RuntimeConfig(
register_pack_id=register_id,
anchor_lens_id=lens_id,
))
pipeline = CognitiveTurnPipeline(runtime=runtime)
result = pipeline.run(prompt)
turn_event = runtime.turn_log[-1]
return {
"prompt": prompt,
"register_id": register_id,
"lens_id": lens_id,
"surface": turn_event.surface,
"trace_hash": result.trace_hash,
"grounding_source": getattr(turn_event, "grounding_source", ""),
"register_variant_id": getattr(turn_event, "register_variant_id", ""),
"anchor_lens_id": getattr(turn_event, "anchor_lens_id", ""),
"anchor_lens_mode_label": getattr(turn_event, "anchor_lens_mode_label", ""),
}
def _build_grid() -> list[dict[str, Any]]:
cells: list[dict[str, Any]] = []
for register_id in _REGISTERS:
for lens_id in _LENSES:
for prompt in _PROMPTS:
cells.append(_run_one_cell(register_id, lens_id, prompt))
return cells
def _cells_by(
cells: list[dict[str, Any]],
*,
register_id: str | None = None,
lens_id: str | None = None,
prompt: str | None = None,
) -> list[dict[str, Any]]:
out: list[dict[str, Any]] = []
for c in cells:
if register_id is not None and c["register_id"] != register_id:
continue
if lens_id is not None and c["lens_id"] != lens_id:
continue
if prompt is not None and c["prompt"] != prompt:
continue
out.append(c)
return out
def _check_claims(cells: list[dict[str, Any]]) -> dict[str, Any]:
glyph_violations: list[str] = []
register_invariant_failures: list[str] = []
lens_distinctness_failures: list[str] = []
convivial_marker_failures: list[str] = []
lens_annotation_failures: list[str] = []
# Claim E — glyph leak across whole grid.
for c in cells:
for pos, ch, block in _substrate_glyph_violations(c["surface"]):
glyph_violations.append(
f"register={c['register_id']!r} lens={c['lens_id']!r} "
f"prompt={c['prompt']!r}: substrate glyph {ch!r} "
f"(block={block}) at pos {pos}"
)
# Claim A — register-tour seam inside every (lens, prompt) cell.
for lens_id in _LENSES:
for prompt in _PROMPTS:
triple = _cells_by(cells, lens_id=lens_id, prompt=prompt)
hashes = {c["trace_hash"] for c in triple}
if len(hashes) != 1:
register_invariant_failures.append(
f"lens={lens_id!r} prompt={prompt!r}: "
f"trace_hashes varied across registers: "
f"{sorted(hashes)}"
)
# Claim B — lens distinctness inside every (register, prompt) cell.
# Engaged lenses' trace_hashes must differ from the unanchored
# baseline at the same (register, prompt).
for register_id in _REGISTERS:
for prompt in _PROMPTS:
unanchored_cell = _cells_by(
cells,
register_id=register_id,
lens_id="default_unanchored_v1",
prompt=prompt,
)[0]
for lens_id in _LENSES:
if lens_id == "default_unanchored_v1":
continue
cell = _cells_by(
cells,
register_id=register_id,
lens_id=lens_id,
prompt=prompt,
)[0]
if cell["anchor_lens_mode_label"]:
# Engaged → require trace_hash divergence.
if cell["trace_hash"] == unanchored_cell["trace_hash"]:
lens_distinctness_failures.append(
f"register={register_id!r} lens={lens_id!r} "
f"prompt={prompt!r}: engaged lens did not "
f"move trace_hash (still "
f"{cell['trace_hash'][:12]}...)"
)
# Claim C — convivial register attaches discourse markers.
for c in _cells_by(cells, register_id="convivial_v1"):
if c["surface"] and not c["register_variant_id"]:
convivial_marker_failures.append(
f"convivial cell lens={c['lens_id']!r} "
f"prompt={c['prompt']!r} has empty register_variant_id "
f"despite non-empty surface"
)
# Claim D — engaged lens emits annotation + non-empty mode_label.
for c in cells:
if c["anchor_lens_mode_label"]:
expected = f"[lens({c['lens_id']}):{c['anchor_lens_mode_label']}]"
if expected not in c["surface"]:
lens_annotation_failures.append(
f"register={c['register_id']!r} lens={c['lens_id']!r} "
f"prompt={c['prompt']!r}: mode_label="
f"{c['anchor_lens_mode_label']!r} but surface lacks "
f"annotation {expected!r}. Surface: {c['surface']!r}"
)
return {
"inner_register_invariant_within_lens": not register_invariant_failures,
"outer_lens_distinctness_within_register": not lens_distinctness_failures,
"surface_carries_register_marker_under_convivial": (
not convivial_marker_failures
),
"surface_carries_lens_annotation_when_engaged": not lens_annotation_failures,
"no_substrate_glyph_leak_across_grid": not glyph_violations,
"register_invariant_failures": register_invariant_failures,
"lens_distinctness_failures": lens_distinctness_failures,
"convivial_marker_failures": convivial_marker_failures,
"lens_annotation_failures": lens_annotation_failures,
"glyph_violations": glyph_violations,
}
def _print_grid(cells: list[dict[str, Any]]) -> None:
for prompt in _PROMPTS:
_say(f" Prompt: {prompt!r}")
for register_id in _REGISTERS:
_say(f" register = {register_id}")
for lens_id in _LENSES:
cell = _cells_by(
cells, register_id=register_id, lens_id=lens_id,
prompt=prompt,
)[0]
mode = cell["anchor_lens_mode_label"] or "-"
variant = cell["register_variant_id"] or "-"
_say(
f" lens={lens_id:24s} "
f"trace={cell['trace_hash'][:12]}"
f"mode={mode:18s} variant={variant}"
)
_say()
def run_tour(*, emit_json: bool = False) -> dict[str, Any]:
"""Run the orthogonality tour and return a structured report."""
global _VERBOSE
_VERBOSE = not emit_json
if not emit_json:
_print_header()
_say(f" Building grid: {len(_REGISTERS)} registers × "
f"{len(_LENSES)} lenses × {len(_PROMPTS)} prompts = "
f"{len(_REGISTERS) * len(_LENSES) * len(_PROMPTS)} cells")
_say()
cells = _build_grid()
if not emit_json:
_say("-" * 76)
_say(" Composition grid")
_say("-" * 76)
_print_grid(cells)
claims = _check_claims(cells)
all_supported = all(
claims[k] for k in (
"inner_register_invariant_within_lens",
"outer_lens_distinctness_within_register",
"surface_carries_register_marker_under_convivial",
"surface_carries_lens_annotation_when_engaged",
"no_substrate_glyph_leak_across_grid",
)
)
if not emit_json:
_say("=" * 76)
_say(" Orthogonality claims (composition gate)")
_say("=" * 76)
for label, key in (
("A) inner_register_invariant_within_lens ",
"inner_register_invariant_within_lens"),
("B) outer_lens_distinctness_within_register ",
"outer_lens_distinctness_within_register"),
("C) surface_carries_register_marker_convivial",
"surface_carries_register_marker_under_convivial"),
("D) surface_carries_lens_annotation_engaged ",
"surface_carries_lens_annotation_when_engaged"),
("E) no_substrate_glyph_leak_across_grid ",
"no_substrate_glyph_leak_across_grid"),
):
_say(f" {label}: {claims[key]}")
_say()
_say(f" all_claims_supported : {all_supported}")
_say()
return {
"registers": list(_REGISTERS),
"lenses": list(_LENSES),
"prompts": list(_PROMPTS),
"cells": cells,
"claims": claims,
"all_claims_supported": all_supported,
}
if __name__ == "__main__": # pragma: no cover
import sys
emit_json = "--json" in sys.argv
report = run_tour(emit_json=emit_json)
if emit_json:
print(json.dumps(report, indent=2, sort_keys=True, default=str))
sys.exit(0 if report["all_claims_supported"] else 1)

View file

@ -0,0 +1,106 @@
"""Orthogonality tour demo — composition gate (ADR-0074).
Pins the five composed claims that the single-axis tours only assert
in isolation:
A) inner_register_invariant_within_lens
B) outer_lens_distinctness_within_register
C) surface_carries_register_marker_under_convivial
D) surface_carries_lens_annotation_when_engaged
E) no_substrate_glyph_leak_across_grid
Any one failing is the composition-regression signal.
"""
from __future__ import annotations
from evals.orthogonality_tour.run_tour import (
_LENSES,
_PROMPTS,
_REGISTERS,
run_tour,
)
def test_tour_returns_structured_report():
report = run_tour(emit_json=True)
assert set(report) >= {
"registers", "lenses", "prompts", "cells", "claims",
"all_claims_supported",
}
assert list(report["registers"]) == list(_REGISTERS)
assert list(report["lenses"]) == list(_LENSES)
assert list(report["prompts"]) == list(_PROMPTS)
def test_grid_has_18_cells():
"""3 registers × 3 lenses × 2 prompts."""
report = run_tour(emit_json=True)
assert len(report["cells"]) == 18
def test_claim_A_register_invariant_within_each_lens():
"""Inner register-tour: for every (lens, prompt) the three
register runs share an identical trace_hash."""
report = run_tour(emit_json=True)
assert report["claims"]["inner_register_invariant_within_lens"] is True
assert report["claims"]["register_invariant_failures"] == []
def test_claim_B_lens_distinctness_within_each_register():
"""Inner anchor-lens-tour: engaged lenses diverge from the
unanchored baseline at every (register, prompt) cell."""
report = run_tour(emit_json=True)
assert report["claims"]["outer_lens_distinctness_within_register"] is True
assert report["claims"]["lens_distinctness_failures"] == []
def test_claim_C_convivial_carries_register_marker():
report = run_tour(emit_json=True)
assert report["claims"]["surface_carries_register_marker_under_convivial"] is True
assert report["claims"]["convivial_marker_failures"] == []
def test_claim_D_engaged_lens_carries_annotation():
report = run_tour(emit_json=True)
assert report["claims"]["surface_carries_lens_annotation_when_engaged"] is True
assert report["claims"]["lens_annotation_failures"] == []
def test_claim_E_no_substrate_glyph_leak_across_grid():
report = run_tour(emit_json=True)
assert report["claims"]["no_substrate_glyph_leak_across_grid"] is True
assert report["claims"]["glyph_violations"] == []
def test_all_claims_supported():
"""Canonical composition gate — every claim must hold or exit non-zero."""
report = run_tour(emit_json=True)
assert report["all_claims_supported"] is True
def test_engaged_cells_appear_for_both_non_trivial_lenses():
"""Sanity: the grid actually exercises engagement. grc_logos_v1
engages on knowledge; he_logos_v1 engages on truth. Each
non-trivial lens must produce at least one engaged cell
(otherwise the lift claim is vacuously satisfied)."""
report = run_tour(emit_json=True)
grc_engaged = [
c for c in report["cells"]
if c["lens_id"] == "grc_logos_v1"
and c["anchor_lens_mode_label"] == "systematic"
]
he_engaged = [
c for c in report["cells"]
if c["lens_id"] == "he_logos_v1"
and c["anchor_lens_mode_label"] == "covenant-verity"
]
# grc engages on knowledge in every register (3 cells); same for he on truth.
assert len(grc_engaged) == len(_REGISTERS), (
f"expected grc_logos_v1 engagement in {len(_REGISTERS)} cells "
f"(once per register on 'What is knowledge?'), got {len(grc_engaged)}"
)
assert len(he_engaged) == len(_REGISTERS), (
f"expected he_logos_v1 engagement in {len(_REGISTERS)} cells "
f"(once per register on 'What is truth?'), got {len(he_engaged)}"
)