feat(evals,tests,docs,adr): FA-1 ruled — cross-language holonomy does not discriminate meaning (NO-GO)

The CORE-Logos "Crown Proof" — ADR-0015's claim that cross-language holonomy
closure is THE validation gate of meaning — was measured against a criterion
registered before the run, and refused.

  G1  separation, all negatives      AUC 0.557   (chance 0.500, bar 0.80)   FAIL
  G2  hardest class, cross-pairing   AUC 0.664   (bar 0.75)                 FAIL
  G3  word-order sensitivity         0.644       (bar 0.90)                 FAIL
  G4  no collapse re-entry           0 lost      (bar: 0)                   PASS

G4 is the half that succeeded: the repairs work. The claim is what failed --
which is the outcome the registration called "worth as much as a GO", because
it retires the largest piece of unearned design in the system.

Both preconditions had to be BUILT before the question could be asked at all,
which is why the 2026-06-14 negative constrained nothing: the shipped compiler
collapsed 37-53 coordinates, and holonomy_encode never closed. Measured on the
repaired ground with a genuine loop, over 1,016 aligned pairs and 58,375
mechanically-generated negatives in three classes, nothing hand-picked.

Diagnosis, not just a number: the encoding reacts more strongly to REORDERING a
clause (median deviation 41.2) than to CHANGING WHAT IT IS ABOUT (32.2). It
measures path shape, not content -- and that follows from the algebra, since
permutation acts on an ordered product through non-commutativity, a first-order
effect, while substituting one of three factors perturbs it only through that
factor. The negative classes do order correctly by meaning-distance
(aligned 27.2 < lexical 32.2 < order 41.2 < cross-pair 53.2), so the geometry is
weak signal rather than noise -- a correlation where the design asked for a gate.

Consequences, all landed here:

  * ADR-0005 and ADR-0015 AMENDED to record the refusal. The three-language
    architecture, the pack contract, morphology-as-structure and Hebrew root
    folding into geometry all survive untouched; only the claim that alignment
    or closure VALIDATES meaning is retired.
  * tests/test_fa1_gate_verdict.py is the tripwire: if a future encoding makes
    the gate real, it fails, and the amendment is withdrawn in the same commit
    that replaces it with a proof. Two sabotages observed red.
  * allow_cross_language_recall RULED by measurement (work-order item 3): it
    gates vault-recall depth over field states, has no language argument and no
    cross-language path, and reaches only walk_surface, which runtime_contracts
    declares telemetry. Stays ON, reclassified DEPLOYMENT, flip condition
    recorded. G-25's own claim that it was "the pillar's own switch" is
    CORRECTED -- that read the flag's name instead of its call graph, which is
    the error the audit exists to find.
  * A sixth defect found while building the harness: en_collapse_anchors_v1
    declares role "collapse_anchor", which is not a LanguageRole member, so
    load_pack() raises. It is registered in the resolver, consumed by opening
    lexicon.jsonl on a raw path that bypasses the loader, and is the target of
    all 24 alignment edges that still resolve to nothing. The enum's own comment
    records the identical failure once before (ADR-0097, domain_seed).

The repairs cross to the keel on their own merit regardless of the verdict:
geodesic blending removes every coordinate collision, and mount-wide edge
resolution connects 39 of the 63 dead edges. The collapse was damaging English's
own vocabulary; seeing that required no theory of meaning.

FA-1 is CLOSED: all four work-order items discharged, L2 verdict recorded as
defective-but-repairable with its central design claim retired.

[Verification]: uv run core test --suite smoke -q -> 786 passed in 239.45s, EXIT=0
                (+4 tests, +15s vs the prior 782/224s -- the FA-1 pin's stated cost).
                Doc-parsing pins re-run after the ADR and register amendments:
                test_adr_status_governance + test_adr_index -> 321 passed;
                test_flag_register -> 6 passed.
This commit is contained in:
Shay 2026-07-28 14:37:07 -07:00
parent 94f05ba84f
commit cbfc8ccbf7
11 changed files with 800 additions and 5 deletions

View file

@ -173,6 +173,16 @@ TEST_SUITES: dict[str, tuple[str, ...]] = {
# observed red. See docs/analysis/logos-substrate-collapse-2026-07-28.md. # observed red. See docs/analysis/logos-substrate-collapse-2026-07-28.md.
# Bit-exact comparison, no tolerances, ~2.1s. # Bit-exact comparison, no tolerances, ~2.1s.
"tests/test_manifold_collapse_floor.py", "tests/test_manifold_collapse_floor.py",
# FA-1 verdict / G-25 — the CORE-Logos validation-gate claim, measured and refused.
# On a ground with ZERO collisions and a genuinely closed loop, cross-language
# holonomy separates aligned from meaning-breaking clauses at AUC 0.557 (chance is
# 0.500) and the ADR's own word-order test holds 64.4% of the time: NO-GO against a
# criterion registered before the run. Pinned because the interesting failure mode
# is the GOOD one — a future encoding making the gate real while four documents still
# say it was refused. Two sabotages observed red (thresholds lowered to chance ->
# verdict flips; geodesic reverted to the shipped overwrite -> G4 fails). Cost 16s,
# stated rather than estimated, for the tripwire on the system's central design claim.
"tests/test_fa1_gate_verdict.py",
# PR-11 / G-5 / R-9 — the soak's evidence is committed, pinned, and CURRENT. # PR-11 / G-5 / R-9 — the soak's evidence is committed, pinned, and CURRENT.
# Two failure modes, deliberately separated: the digest catches a regression, # Two failure modes, deliberately separated: the digest catches a regression,
# and the attested-source hashes catch STALENESS — evidence that no longer # and the attested-source hashes catch STALENESS — evidence that no longer

View file

@ -91,6 +91,24 @@ only when it passes the following gates in order:
7. **Alignment gate** — pack publishes anchor records verifiable against trilingual template 7. **Alignment gate** — pack publishes anchor records verifiable against trilingual template
8. **Coverage gate** — probe set covers minimum lexical and morphological surface 8. **Coverage gate** — probe set covers minimum lexical and morphological surface
> **Amendment · 2026-07-28 — what gate 7 actually verified, measured.** The alignment gate
> presupposes that publishing anchor records establishes cross-language alignment. Measured at
> `472fc0a8`, the mechanism behind those records **destroyed** what it claimed to align:
> `packs.compiler._blend_feature_versors` ignored its strength argument and returned the target
> verbatim, so an "aligned" Hebrew token was *overwritten* by its Greek or English partner
> rather than drawn toward it, and mounting the depth packs removed 37 distinct coordinates
> (`docs/analysis/logos-substrate-collapse-2026-07-28.md`). The eight gates are also not
> enforced as a sequence anywhere in the loader — `gate_engaged` is a single manifest boolean
> consulted by `sensorium/registry.py`, and the seven other gates have no code that runs them.
>
> Two things follow, and only two. **(a)** Alignment must be *interpolation on the versor
> group*, never replacement — `algebra/rotor.py` has shipped that operation since the algebra
> layer's first commit. **(b)** Gate 7's stronger sibling — that alignment establishes
> resonance strong enough to *validate meaning* (ADR-0015's Crown Proof) — was measured and
> refused: `docs/analysis/fa1-holonomy-gate-verdict-2026-07-28.md`. The alignment data itself
> stands: 24 aligned concepts across three languages, and Hebrew root folding into geometry is
> unaffected. What is retired is the claim that alignment, by existing, proves anything.
## Design Rules ## Design Rules
### 1. Lemma-first ### 1. Lemma-first

View file

@ -1,10 +1,44 @@
# ADR-0015 — Language Packs as Compiled Linguistic Manifolds # ADR-0015 — Language Packs as Compiled Linguistic Manifolds
**Status:** Accepted **Status:** Accepted **Crown Proof section AMENDED 2026-07-28: measured and not supported**
**Date:** 2026-05-13 **Date:** 2026-05-13
--- ---
> ## Amendment · 2026-07-28 · the Crown Proof was tested and failed
>
> This ADR's "Crown Proof: Holonomy Resonance" section makes cross-language holonomy
> resonance **the validation gate of meaning***"This is the CORE-Logos proof"* — and the
> Consequences section lists *"Establishes holonomy-level resonance as the validation gate"*
> as a positive. **That claim is retired.** It was measured against a criterion registered
> before the run (`docs/analysis/fa1-holonomy-gate-preregistration.md`) and refused:
>
> * **AUC 0.557** separating aligned clauses from meaning-breaking ones (chance = 0.500,
> required ≥ 0.80), over 1,016 aligned pairs and 58,375 mechanically-generated negatives;
> * **64.4%** word-order sensitivity against this ADR's own stated test (*"word-order changes
> should change holonomy"*, required ≥ 0.90) — a third of permutations close the loop
> *tighter* than the correct order;
> * measured on a ground with **zero coordinate collisions** and with a **genuinely closed
> loop**, both of which had to be built first — the shipped compiler collapsed 3753
> coordinates and the shipped `holonomy_encode` never closed
> (`docs/analysis/logos-substrate-collapse-2026-07-28.md`).
>
> **Diagnosis:** the encoding reacts more strongly to reordering a clause (median deviation
> 41.2) than to changing what the clause is *about* (32.2). It measures path shape, not
> content. The negative classes do order themselves correctly by meaning-distance, so the
> geometry is not noise — it is a weak correlation where the design asked for a gate.
>
> **What survives, unamended:** the three-language architecture with distinct roles, the pack
> contract, the compiled-manifold discipline, morphology as structure, and Hebrew root folding
> into geometry at compile time. What is struck is only the claim that holonomy closure
> *validates* meaning.
>
> **Verdict:** `docs/analysis/fa1-holonomy-gate-verdict-2026-07-28.md` ·
> **Tripwire:** `tests/test_fa1_gate_verdict.py` — if a future encoding makes the gate real,
> that test fails, and this amendment is withdrawn in the same commit that replaces it with a
> proof. The hypothesis was honestly stated and honestly testable; that is why it could be
> settled at all.
## Context ## Context
CORE's language philosophy is not localization. English, Hebrew, and Koine Greek CORE's language philosophy is not localization. English, Hebrew, and Koine Greek

View file

@ -108,6 +108,23 @@ repaired design earns its place there.
clause of triple *j ≠ i*. This is the strongest negative class: same corpus, same clause of triple *j ≠ i*. This is the strongest negative class: same corpus, same
lengths, same construction, different meaning. lengths, same construction, different meaning.
**Amendment A1 (recorded before the run, no numbers seen).** R3 resolves more of the corpus
than this registration assumed: **24 aligned concepts**, of which 6 carry all three languages
and 18 carry two. Clause sets are therefore all `C(24,3) = 2,024` combinations rather than the
"2040 triples" estimated above — a larger corpus than registered, in the direction that makes
the test harder to pass, not easier.
That makes negative class 3 complete-enumeration quadratic (≈4 M pairs). It is bounded by a
rule stated here, before any measurement: **for each aligned pair, the cross negatives are the
first 5 clause sets following it in the deterministic sorted enumeration that share no concept
with it.** Position in a sorted enumeration of concept keys is unrelated to meaning, so the
bound is unbiased; it is deterministic, so the experiment is reproducible; and the count of
generated negatives is reported, so nothing is dropped in silence. Classes 1 and 2 remain
**complete** — every valid substitution, every non-identity permutation.
The G2 threshold is **not** relaxed to compensate. A bound on how many negatives are drawn
does not change how well the aligned pairs must separate from them.
## 4. The criterion — committed, and deliberately unforgiving ## 4. The criterion — committed, and deliberately unforgiving
Let `d(A,B)` be the loop-closure deviation of the cross-language loop (transport along clause Let `d(A,B)` be the loop-closure deviation of the cross-language loop (transport along clause

View file

@ -0,0 +1,126 @@
# FA-1 verdict: **NO-GO** — cross-language holonomy does not discriminate meaning
**Date:** 2026-07-28 · **Criterion registered before the run** at `94f05ba8`
(`docs/analysis/fa1-holonomy-gate-preregistration.md`, amendment A1 recorded before any
number existed) · Runner: `evals/logos/fa1_gate.py` · Deterministic, re-run bit-identical.
> **G4 held.** The repairs work: the ground is clean and the loop closes. The design's
> claim is what failed. Per the registration, this is a full-credit result — *"the outcome
> that would retire the largest piece of unearned design in the system, and it is worth as
> much as a GO."*
---
## 1. The result
| Gate | Requirement | Observed | |
|---|---|---|---|
| **G1** separation, all negatives | AUC ≥ 0.80 | **0.557** | ✗ |
| **G2** hardest class (cross-pair) | AUC ≥ 0.75 | **0.664** | ✗ |
| **G3** word-order sensitivity | ≥ 0.90 | **0.644** | ✗ |
| **G4** no collapse re-entry | `coordinates_lost == 0` | **0** | ✓ |
**VERDICT: NO-GO.** AUC 0.557 against a chance floor of 0.500.
**Controls, reported per anti-gaming rule 4.** Max self-loop deviation `d(A,A) = 3.6e-06`
across all 1,016 aligned pairs — the instrument can report closure, so a null result is a
measurement and not a broken metric. Corpus: **83 authored edges, 59 resolved under R3, 24
concepts** (6 tri-language, 18 bi-language), **2,024 clause sets**, **1,016 aligned pairs**,
**58,375 negatives** (50,748 lexical · 5,080 word-order · 2,547 cross-pair).
## 2. The signal is real, in the right direction, and far too weak
The negative classes order themselves exactly as meaning-distance would predict:
| Class | median `d` | AUC vs aligned |
|---|---|---|
| **aligned** (same content, two languages) | **27.20** | — |
| lexical substitution (one word changed) | 32.17 | 0.547 |
| word-order permutation (same words, reordered) | 41.17 | 0.602 |
| cross-pair (entirely different content) | 53.23 | 0.664 |
Aligned pairs *do* close tighter than negatives, and the further a negative is from the
original meaning the wider its loop opens. The geometry is not noise. But the distributions
overlap so heavily that a classifier built on `d` is barely better than a coin — and the
design does not ask for a correlation, it asks for **a validation gate**. A gate at AUC 0.557
would refuse correct articulations and admit wrong ones at nearly the same rate.
## 3. Why it fails — the diagnosis, not just the number
**The encoding is more sensitive to permutation than to substitution.** Reordering the same
three words moves `d` from 27.2 to 41.2. Replacing one of the three words with a *different
concept* moves it only to 32.2. A quantity that reacts more strongly to shuffling a clause
than to changing what the clause is about is measuring **path shape, not content**.
That follows from the algebra rather than from any defect: `F(X)` is an ordered geometric
product, so permutation acts on it through non-commutativity — a first-order effect — while
substituting one of three factors perturbs it only through that factor's own difference.
Word order is structurally louder than word identity, and meaning lives mostly in identity.
And even the order sensitivity is unreliable per-pair: **G3 = 0.644**, so a third of all
permutations make the loop close *tighter* than the correctly-ordered clause. ADR-0015's own
stated test — *"word-order changes should change holonomy"* — is satisfied only in the trivial
sense that the number moves. It does not move in a consistent direction.
## 4. What this does and does not settle
**Settled.** Cross-language holonomy closure, as ADR-0005/0015 specify it, is **not** a
validation gate of meaning — measured on a ground with zero coordinate collisions, with a
genuinely closed loop, with mechanically-generated negatives in three classes and no
cherry-picking, at a corpus 1,000× the size of the June measurement. The two conditions that
made the June negative uninterpretable were removed and the answer did not change; it became
*more* precise.
**Not settled, and deliberately not tested here.** The cross-language alignment strength is
`0.10` — the value the compiler declares — so aligned tokens across languages sit only 10% of
the way toward each other. A stronger coupling would raise separation, and at strength `1.0`
it would reach it trivially, by re-collapsing the manifold into exactly the state FA-1 found
and G4 forbids. Somewhere between those lies a question worth asking, and **this experiment
does not ask it**, because selecting a coupling *after* seeing the registered value fail is
the definition of the tuning this registration's anti-gaming rules forbid.
If it is ever asked, it must be its own pre-registration, and it must carry a criterion that
G4 cannot be traded against: **separation must improve faster than distinctness degrades**,
with both measured, or the "improvement" is just collapse arriving by a slower road.
**Also not settled:** the token-level question. Whether *individual* aligned versors sit
closer than unaligned ones on the repaired ground is a narrower claim than the clause gate,
and the four tests that nominally proved it are decoration
(`docs/analysis/logos-substrate-collapse-2026-07-28.md` §3). It is worth measuring honestly.
It is not this result and cannot be used to soften it.
## 5. Consequences — what changes
1. **The validation-gate claim is retired.** ADR-0005 and ADR-0015 are amended: cross-language
holonomy resonance is recorded as **measured and not supported**, with this verdict as the
authority. The phrase *"This is the CORE-Logos proof"* does not survive the measurement it
invited. The ADRs are amended, not deleted — the design was a real hypothesis, honestly
stated, and it was tested.
2. **The depth packs keep a smaller, earned role**: lexical and morphological resources with
real cross-language concept alignment (24 concepts, 59 resolved edges), and Hebrew root
folding into geometry at compile time (`triliteral:`), which is untouched by this verdict.
3. **The keel's L3 takes the NO-GO branch.** `logos/` is admitted as lexicon + morphology.
K4's meaning criterion must come from somewhere other than cross-language closure — which
is now a known constraint on the perception design rather than an assumption inside it.
4. **The repairs are worth carrying anyway, and independently of this verdict.** R1 (geodesic
blending) removes 53 coordinate collisions from the six-pack mount and 37 from the
trilingual one; R3 connects 39 of the 63 dead alignment edges. A ground that keeps its
distinctions is worth having whether or not holonomy is its gate — the collapse harmed
English's own vocabulary, and no theory of meaning was required to see that.
## 6. What this cost, and what it bought
One session. It closed the largest open design question in the system with a measurement
instead of a belief, and it did so by first finding that the question had never been askable:
the ground was collapsed and the loop was open, so the June negative measured neither the
design nor the geometry.
The register of geometric-substrate verdicts now reads: wedge **C3-decoration**, operator
ablation **identical-to-baseline**, ADR-0252 §5 **NO-GO**, cross-language holonomy **NO-GO on
a clean ground**. Four independent negatives is not a run of bad luck; it is a boundary. The
honest reading is that this substrate's value has not been demonstrated in *reasoning* — while
its value in *representation* (exact recall, versor conditioning, determinism) is measured and
holds. The keel should be built on what is measured.
**Reproduce:** `uv run python -m evals.logos.fa1_gate` · pinned by
`tests/test_fa1_gate_verdict.py` · raw output in this document's §12 tables.

View file

@ -203,7 +203,9 @@ Own `use_salience`, the two underived constants, the self-narrowing budget feedb
- **G-20 · The `refusal_reason` materialisation** — typed refusal evidence exists and is discarded at the public `str` boundary; the plumbing for materialisation already landed. Cross-listed as H-3. **Authority:** small ADR (anticipated by the ADR-0024 chain). - **G-20 · The `refusal_reason` materialisation** — typed refusal evidence exists and is discarded at the public `str` boundary; the plumbing for materialisation already landed. Cross-listed as H-3. **Authority:** small ADR (anticipated by the ADR-0024 chain).
- **G-25 · CORE-Logos — the designed foundation pillar is seeded, not built** *(new, 2026-07-28 — Tier A; FA-1 of the Foundations Audit)* — ADR-0005/0015 make cross-language holonomy resonance **the validation gate of meaning** (*"holonomy(hebrew) ≈ holonomy(greek) ≈ holonomy(english)… This is the CORE-Logos proof"*), with HE roots as depth anchors and alignment-as-resonance. Measured at `339bfd37`: the alignment corpus is **11 edges / 9 HE morphology rows** (the ADR's own John1:1/Gen1:1 *first cases*, never grown); the serving-path role is an HE-morphology **veto that no-ops on English** (`pipeline.py:544`); the recall bridge is `allow_cross_language_recall`**mystery ON-flag #1 from the flag register, now identified as the pillar's own switch**, gating `recall_top_k=3 vs 0` with no recorded rationale; the `hebrew_greek_textual_reasoning` domain is registered and produced **zero** curriculum bands; and **no path consults cross-language holonomy as a gate** — template match became the de-facto criterion of meaning instead. Root folding into vectors (`triliteral:` tokens) is real, so the first read was **architected, seeded exactly as designed, wired at three mutually-unaware points, load-bearing nowhere**. - **G-25 · CORE-Logos — the designed foundation pillar is seeded, not built** *(new, 2026-07-28 — Tier A; FA-1 of the Foundations Audit)* — ADR-0005/0015 make cross-language holonomy resonance **the validation gate of meaning** (*"holonomy(hebrew) ≈ holonomy(greek) ≈ holonomy(english)… This is the CORE-Logos proof"*), with HE roots as depth anchors and alignment-as-resonance. Measured at `339bfd37`: the alignment corpus is **11 edges / 9 HE morphology rows** (the ADR's own John1:1/Gen1:1 *first cases*, never grown); the serving-path role is an HE-morphology **veto that no-ops on English** (`pipeline.py:544`); the recall bridge is `allow_cross_language_recall`**mystery ON-flag #1 from the flag register, now identified as the pillar's own switch**, gating `recall_top_k=3 vs 0` with no recorded rationale; the `hebrew_greek_textual_reasoning` domain is registered and produced **zero** curriculum bands; and **no path consults cross-language holonomy as a gate** — template match became the de-facto criterion of meaning instead. Root folding into vectors (`triliteral:` tokens) is real, so the first read was **architected, seeded exactly as designed, wired at three mutually-unaware points, load-bearing nowhere**.
**UPGRADED 2026-07-28 by measurement at `472fc0a8` — the pillar is not under-built, it is destroyed at compile time.** Two claims in the paragraph above are struck: the corpus is **83 edges, not 11** (63 of them resolve to nothing, including all edges of the two packs serving actually grounds HE/GRC against), and the "live holonomy machinery" is not in `core/physics/digest.py` (a field digest cycle that passes the value through) — it is `algebra/holonomy.py`, whose reverse walk was **deleted at `fca6216e` with the docstring describing it left in place**, so the object never closes and `alpha` is inert while a caller passes it. The dominant defect: **`packs.compiler._blend_feature_versors` ignores its strength argument and returns the target verbatim**, so all three "nudges" are total overwrites — mounting the depth packs **removes 37 distinct coordinates** (239 surfaces → 202), collapsing nine English question words (`ask/question/what/who/where/how/why/when/which`) onto one point and making `דבר`, `λόγος`, `דברים` and `word` bit-identical. English alone is collision-free, so the loss is *created by the mount*. Four token-level "resonance proofs" are green because the compared arrays are the same array. **The cure was already one layer down and never called:** `algebra/rotor.py` has shipped `rotor_power` + `word_transition_rotor` — the group geodesic — since the algebra layer's first commit; a naive lerp leaves the versor group and `VocabManifold.update()` correctly refuses it, which is what the overwrite was an escape from. **Instrumented:** `evals/logos/manifold_collapse.py` + `tests/test_manifold_collapse_floor.py` (smoke, both directions, bit-exact). **Evidence:** `docs/analysis/logos-substrate-collapse-2026-07-28.md`. This is the missing half of every "geometry adds nothing" verdict: no operator can distinguish what its ground does not distinguish. **Authority:** repair is admitted to the keel (K1/K3), not patched here; the pre-registered gate experiment is `docs/analysis/fa1-holonomy-gate-preregistration.md`. **UPGRADED 2026-07-28 by measurement at `472fc0a8` — the pillar is not under-built, it is destroyed at compile time.** Two claims in the paragraph above are struck: the corpus is **83 edges, not 11** (63 of them resolve to nothing, including all edges of the two packs serving actually grounds HE/GRC against), and the "live holonomy machinery" is not in `core/physics/digest.py` (a field digest cycle that passes the value through) — it is `algebra/holonomy.py`, whose reverse walk was **deleted at `fca6216e` with the docstring describing it left in place**, so the object never closes and `alpha` is inert while a caller passes it. The dominant defect: **`packs.compiler._blend_feature_versors` ignores its strength argument and returns the target verbatim**, so all three "nudges" are total overwrites — mounting the depth packs **removes 37 distinct coordinates** (239 surfaces → 202), collapsing nine English question words (`ask/question/what/who/where/how/why/when/which`) onto one point and making `דבר`, `λόγος`, `דברים` and `word` bit-identical. English alone is collision-free, so the loss is *created by the mount*. Four token-level "resonance proofs" are green because the compared arrays are the same array. **The cure was already one layer down and never called:** `algebra/rotor.py` has shipped `rotor_power` + `word_transition_rotor` — the group geodesic — since the algebra layer's first commit; a naive lerp leaves the versor group and `VocabManifold.update()` correctly refuses it, which is what the overwrite was an escape from. **Instrumented:** `evals/logos/manifold_collapse.py` + `tests/test_manifold_collapse_floor.py` (smoke, both directions, bit-exact). **Evidence:** `docs/analysis/logos-substrate-collapse-2026-07-28.md`. This is the missing half of every "geometry adds nothing" verdict: no operator can distinguish what its ground does not distinguish. **Authority:** repair is admitted to the keel (K1/K3), not patched here.
**RULED 2026-07-28 — the gate experiment ran and the design claim is retired.** On a ground with **zero** coordinate collisions (the geodesic repair works) and a genuinely closed loop, cross-language holonomy separates aligned clauses from meaning-breaking ones at **AUC 0.557** against a chance floor of 0.500 (bar: 0.80), and ADR-0015's own word-order test holds **64.4%** of the time (bar: 0.90). **NO-GO**, criterion registered before the run, 1,016 aligned pairs and 58,375 mechanically-generated negatives across three classes. Diagnosis: the encoding reacts more strongly to *reordering* a clause (median 41.2) than to *changing what it is about* (32.2) — it measures path shape, not content — though the negative classes do order correctly by meaning-distance, so the geometry is weak signal, not noise. **ADR-0005 and ADR-0015 amended** to record the refusal; `tests/test_fa1_gate_verdict.py` is the tripwire that fires if a future encoding makes it real. `allow_cross_language_recall` ruled by measurement (it gates vault-recall depth, has no cross-language path, reaches only telemetry) — and G-25's own claim that it was "the pillar's own switch" is **corrected**: that read the name, not the call graph. **Sixth defect found in passing:** `en_collapse_anchors_v1` cannot be loaded at all (`role: "collapse_anchor"` is not a `LanguageRole` member) yet is registered, consumed via a raw path that bypasses the loader, and is the target of all 24 still-unresolved alignment edges. **Verdict:** `docs/analysis/fa1-holonomy-gate-verdict-2026-07-28.md`. **G-25 status: L2 defective-but-repairable; the validation-gate claim retired.**
- **G-24 · The perception layer inverts its own ratified design, and no served byte is geometric** *(new, 2026-07-28 — Tier A; the arc-closing diagnosis)* — Measured at `0e1be8be`: the entire serving path (`meaning_graph/reader.py` 490 lines, `proof_chain/` 3,916, both surface composers) contains **zero** geometric references — comprehension is a template parser feeding an ROBDD engine. **ADR-0252 §2 stage 1 prescribes** *"containment / transfer / accumulation / comparison … **Not surface-slot regexes**"* — the implementation is surface-slot regexes over categorical/member/ordering/propositional. The corpus confirms the inversion independently: on `holdout_dev/v1`, **read rate 1.28%** (93.16% `no_template_match`), with possession (18.4% of sentences), transfer verbs (14.6%) and quantity comparison (10.0%) unrepresented while `if/then` (0.1% of sentences) holds 21% of the inventory. Geometry participates in exactly two cognitive mechanisms — salience→attention (bypassed by every licensed lane) and `relation_compiler`'s Hamiltonian ground-state solver (off-serving, fed by a 1.0% math reader) — both stranded behind enumerative front ends that cannot generalize by construction, which is why capability lifts have arrived only as overfit slivers. **Not packs** (0.67%), **not wiring** (failures precede every flag). Full findings F-A…F-E and the remediation plan: `docs/plans/2026-07-28-perception-arc.md`. **AMENDED same day:** F-E's "never tested" was wrong — the operator branch has **three negative results** (field wedge 2026-06-04 → C3 decoration; relational operator ablation 2026-07-19 → identical to baseline; §5 → NO-GO), all found only by import-graph census (373 of 666 modules unreachable from serving). Convergent mechanism: geometry isomorphic to the arithmetic reproduces it exactly and adds nothing; the binding constraint in all three was the reader. **Authority:** the Foundations Audit (`docs/plans/2026-07-28-foundations-audit.md`), which now precedes; reopening criterion recorded in its §4. - **G-24 · The perception layer inverts its own ratified design, and no served byte is geometric** *(new, 2026-07-28 — Tier A; the arc-closing diagnosis)* — Measured at `0e1be8be`: the entire serving path (`meaning_graph/reader.py` 490 lines, `proof_chain/` 3,916, both surface composers) contains **zero** geometric references — comprehension is a template parser feeding an ROBDD engine. **ADR-0252 §2 stage 1 prescribes** *"containment / transfer / accumulation / comparison … **Not surface-slot regexes**"* — the implementation is surface-slot regexes over categorical/member/ordering/propositional. The corpus confirms the inversion independently: on `holdout_dev/v1`, **read rate 1.28%** (93.16% `no_template_match`), with possession (18.4% of sentences), transfer verbs (14.6%) and quantity comparison (10.0%) unrepresented while `if/then` (0.1% of sentences) holds 21% of the inventory. Geometry participates in exactly two cognitive mechanisms — salience→attention (bypassed by every licensed lane) and `relation_compiler`'s Hamiltonian ground-state solver (off-serving, fed by a 1.0% math reader) — both stranded behind enumerative front ends that cannot generalize by construction, which is why capability lifts have arrived only as overfit slivers. **Not packs** (0.67%), **not wiring** (failures precede every flag). Full findings F-A…F-E and the remediation plan: `docs/plans/2026-07-28-perception-arc.md`. **AMENDED same day:** F-E's "never tested" was wrong — the operator branch has **three negative results** (field wedge 2026-06-04 → C3 decoration; relational operator ablation 2026-07-19 → identical to baseline; §5 → NO-GO), all found only by import-graph census (373 of 666 modules unreachable from serving). Convergent mechanism: geometry isomorphic to the arithmetic reproduces it exactly and adds nothing; the binding constraint in all three was the reader. **Authority:** the Foundations Audit (`docs/plans/2026-07-28-foundations-audit.md`), which now precedes; reopening criterion recorded in its §4.

View file

@ -30,7 +30,7 @@ The suspicion that CORE-Logos is not integrated as designed was tested against t
| Alignment data | ~~**Seed-scale: 11 edges**~~**83 edges authored, 20 resolve** | Four packs carry `alignment.jsonl`. The two the serving path actually grounds HE/GRC against (`he_core_cognition_v1` 22, `grc_logos_cognition_v1` 41) contribute **zero** — a hardcoded three-entry prefix map drops every one of their edges. The corpus was grown 7.5×; the growth was never connected. | | Alignment data | ~~**Seed-scale: 11 edges**~~**83 edges authored, 20 resolve** | Four packs carry `alignment.jsonl`. The two the serving path actually grounds HE/GRC against (`he_core_cognition_v1` 22, `grc_logos_cognition_v1` 41) contribute **zero** — a hardcoded three-entry prefix map drops every one of their edges. The corpus was grown 7.5×; the growth was never connected. |
| EN lexicon tagging | Present | 91 entries carrying `logos.core` semantic domains | | EN lexicon tagging | Present | 91 entries carrying `logos.core` semantic domains |
| Serving-path role | **Veto only, no-ops on English** | `pipeline.py:544-583``evaluate_logos_on_text` can force a refusal against observed HE plural morphology; *"English-only turns with no HE surface → no-op"* | | Serving-path role | **Veto only, no-ops on English** | `pipeline.py:544-583``evaluate_logos_on_text` can force a refusal against observed HE plural morphology; *"English-only turns with no HE surface → no-op"* |
| Recall bridge | **ON, undocumented** | `allow_cross_language_recall` — one of the two default-ON flags with no recorded rationale (flag register §1) — gates `recall_top_k=3 vs 0`. **The pillar's own switch was mystery flag #1** | | Recall bridge | ~~**ON, undocumented — the pillar's own switch**~~**misnamed; not the pillar's switch at all** | `allow_cross_language_recall` gates `recall_top_k=3 vs 0` into `vault.recall(state.F, top_k)` — a nearest-versor search over stored field states with **no language argument, no pack, no cross-language path**. Its output feeds the generation walk, which is telemetry-only (`runtime_contracts.md:44`). Ruled 2026-07-28: stays ON, reclassified DEPLOYMENT. **This row's original claim read the flag's name instead of its call graph — the exact error this audit exists to find, committed by the audit.** |
| Curriculum | Registered, bandless | `hebrew_greek_textual_reasoning` in `DOMAIN_PACKS` with corpora; produced **zero** curriculum bands at the PR-14 measurement | | Curriculum | Registered, bandless | `hebrew_greek_textual_reasoning` in `DOMAIN_PACKS` with corpora; produced **zero** curriculum bands at the PR-14 measurement |
| Validation-gate role | **Never assumed** | ADR-0015 §"Establishes holonomy-level resonance as the validation gate" — no serving or licensing path consults cross-language holonomy; template match became the de-facto gate instead | | Validation-gate role | **Never assumed** | ADR-0015 §"Establishes holonomy-level resonance as the validation gate" — no serving or licensing path consults cross-language holonomy; template match became the de-facto gate instead |
@ -70,6 +70,34 @@ Bottom-up. A layer's audit is complete only when each component in it has all fo
**Instrument** (from the census at `339bfd37`): 666 modules, **293 reachable from serving, 373 dark**. Every dark module gets exactly one of: *seam scheduled* · *deliberately-dark with recorded reason* · *deletion candidate*. The census script becomes a pinned lane so this number is a ratchet, not a snapshot. **Instrument** (from the census at `339bfd37`): 666 modules, **293 reachable from serving, 373 dark**. Every dark module gets exactly one of: *seam scheduled* · *deliberately-dark with recorded reason* · *deletion candidate*. The census script becomes a pinned lane so this number is a ratchet, not a snapshot.
### FA-1 · CLOSED 2026-07-28 — all four work-order items discharged
| Item | Outcome |
|---|---|
| 1 · map the designed logos contract | Done as the defect map: `docs/analysis/logos-substrate-collapse-2026-07-28.md` — six defects, each with its site, its measurement, and its cure |
| 2 · decide the holonomy-gate question | **NO-GO**, pre-registered, G4 held: `docs/analysis/fa1-holonomy-gate-verdict-2026-07-28.md`. AUC 0.557 (chance 0.500, bar 0.80); word-order sensitivity 64.4% against the ADR's own test. ADR-0005 and ADR-0015 amended; tripwire pinned |
| 3 · rule `allow_cross_language_recall` | **Ruled by measurement:** it gates vault-recall depth, has no cross-language path, and reaches only telemetry. Stays ON, reclassified DEPLOYMENT, with the flip condition recorded (`docs/specs/flag_register.md` §1) |
| 4 · grow-or-declare the alignment corpus | **Answered before it started:** 83 edges authored, 63 resolving to nothing. Not a growth problem — a connection problem |
**L2 verdict: DEFECTIVE (repairable), and its central design claim RETIRED.** The repairs are
real and measured — the geodesic blend removes every coordinate collision (37 on the
trilingual mount, 53 on the six-pack logos mount), and mount-wide edge resolution connects 39
of the 63 dead edges. What does not survive is the claim that the repaired ground *validates*
meaning by holonomy closure.
**A sixth defect, found while building the experiment:** `en_collapse_anchors_v1` declares
`role: "collapse_anchor"`, which is not a member of `packs.schema.LanguageRole`, so
`load_pack()` raises before reading it. It is listed in `chat/pack_resolver.py`, consumed by
`chat/pack_grounding.py` **by opening `lexicon.jsonl` on a raw path** — bypassing the loader
that would reject it — and is the target of all 24 still-unresolved alignment edges. The enum
carries a comment recording this exact failure once before (ADR-0097, `domain_seed`): a
registry widened by hand falls behind by hand.
**What this changes downstream.** L3's audit no longer waits on an open question — it inherits
a ruled one. A reader over this ground cannot get its meaning criterion from cross-language
closure, which converts the 1.28% read rate from *"a reader problem we might solve with better
grounding"* into *"a reader problem, full stop."* That is a smaller and more honest question.
## 3. Sequencing ## 3. Sequencing
**FA-1 (logos, L2)** → **FA-0 (L0 closure — cheap, likely already masterful, and everything cites it)****FA-2 (L1 physics role-audit)****FA-3 (L3 perception, absorbing the Perception Arc phases, now on a verified ground)****FA-4 (L4)****FA-5 (L5)** → close with the full articulable map: every component, four articulations, evidence-linked. **FA-1 (logos, L2)** → **FA-0 (L0 closure — cheap, likely already masterful, and everything cites it)****FA-2 (L1 physics role-audit)****FA-3 (L3 perception, absorbing the Perception Arc phases, now on a verified ground)****FA-4 (L4)****FA-5 (L5)** → close with the full articulable map: every component, four articulations, evidence-linked.

View file

@ -34,14 +34,22 @@ These four are live in every default `RuntimeConfig`. They are the only flags wh
| flag | class | governing ADR | recorded rationale | what would turn it OFF | | flag | class | governing ADR | recorded rationale | what would turn it OFF |
|---|---|---|---|---| |---|---|---|---|---|
| `allow_cross_language_recall` | CAPABILITY | **none** | **none — no comment block in `core/config.py`** | *no criterion recorded* | | `allow_cross_language_recall` | ~~CAPABILITY~~**DEPLOYMENT (telemetry depth)** | **FA-1 verdict, 2026-07-28** | see the ruling below | flips if walk output is ever routed into the user-facing surface |
| `use_salience` | CAPABILITY | **none** | **none — no comment block in `core/config.py`** | *no criterion recorded* | | `use_salience` | CAPABILITY | **none** | **none — no comment block in `core/config.py`** | *no criterion recorded* |
| `discourse_planner` | CAPABILITY | **none** | yes — builds a deterministic `DiscoursePlan`; BRIEF mode is byte-identical to single-clause output | evidence that multi-clause rendering degrades a served lane | | `discourse_planner` | CAPABILITY | **none** | yes — builds a deterministic `DiscoursePlan`; BRIEF mode is byte-identical to single-clause output | evidence that multi-clause rendering degrades a served lane |
| `deduction_serving_enabled` | POSTURE | **ADR-0256** | yes — ROBDD entailment intercepts argument-shaped turns; 716/716 `wrong=0` | a `wrong>0` result on the sealed band, which revokes the license by construction | | `deduction_serving_enabled` | POSTURE | **ADR-0256** | yes — ROBDD entailment intercepts argument-shaped turns; 716/716 `wrong=0` | a `wrong>0` result on the sealed band, which revokes the license by construction |
**Finding (measured 2026-07-28).** Of the four flags that are ON in production, **one** has a governing ADR and **two have no recorded reason of any kind** — no ADR, no comment, no criterion. In an architecture whose entire posture is *earned* licenses and *refuse-don't-guess*, two permanently-on capability flags with no recorded decision is the mirror image of the hesitancy problem this register was built to find: **accumulated permissiveness**. **Finding (measured 2026-07-28).** Of the four flags that are ON in production, **one** has a governing ADR and **two have no recorded reason of any kind** — no ADR, no comment, no criterion. In an architecture whose entire posture is *earned* licenses and *refuse-don't-guess*, two permanently-on capability flags with no recorded decision is the mirror image of the hesitancy problem this register was built to find: **accumulated permissiveness**.
This is registered, not fixed. Writing a rationale for `allow_cross_language_recall` after the fact would be inventing a decision that was never made, which is worse than recording that it is missing. **Owed:** a one-line rationale-or-flip for each, from whoever knows why they are on. Until then their "what flips it" column stays honest. This was registered, not fixed. Writing a rationale after the fact would be inventing a decision that was never made, which is worse than recording that it is missing. **Owed:** a one-line rationale-or-flip for each, from whoever knows why they are on. `use_salience` remains owed; the other has since been **ruled by measurement** rather than by recollection:
> ### Ruling · `allow_cross_language_recall` · 2026-07-28 (FA-1 work-order item 3)
>
> **It does not do what its name says, and its blast radius is telemetry.** The flag has exactly one consumer: `chat/runtime.py:2844`, which passes `recall_top_k = 3 if allow_cross_language_recall else 0` into `generate()`. That parameter reaches `generate.stream._recall_state`, which calls `vault.recall(state.F, top_k)` — a **nearest-versor search over stored field states by CGA inner product**. It has no language argument, no pack, and no cross-language path of any kind. The flag sets vault-recall *depth*, and the word "cross_language" in its name describes nothing in the code it controls.
>
> Its effect is also bounded away from the user. `_recall_state`'s own INV-24 note records that recalled versors become rotor transitions on the **generation walk**, which feeds `walk_surface`*"retained telemetry/evidence"* per `docs/specs/runtime_contracts.md:44` — while the user-facing surface comes from `realize(proposition, vocab)`. So the flag adjusts how much recalled context colours an evidence trace, not what anyone is told.
>
> **Ruled: stays ON, reclassified DEPLOYMENT, renamed in the keel.** Turning it off would reduce evidence richness to buy nothing, and it is not the CORE-Logos switch. **This also corrects the Foundations Audit's own characterisation of it as "the pillar's own switch"** — that read the name, not the call graph, which is the error the audit exists to find. **What flips it:** the condition `_recall_state` states itself — if walk output is ever routed into the user-facing surface, this becomes a CAPABILITY flag, must pass `min_status=COHERENT`, and needs a fresh ruling.
**A second-order gap, closed with this register.** `tests/test_adr_status_governance.py::test_default_on_flag_is_not_governed_by_a_proposed_adr` is parameterized over *(default-on flag × cited ADR)*. Three of the four ON flags cite no ADR, so they generate **zero** cases — the pin covers exactly one flag. Its non-vacuity guard asserts that *some* flag cites an ADR, which stays green even if the parametrization drops to zero. That guard is tightened alongside this register. **A second-order gap, closed with this register.** `tests/test_adr_status_governance.py::test_default_on_flag_is_not_governed_by_a_proposed_adr` is parameterized over *(default-on flag × cited ADR)*. Three of the four ON flags cite no ADR, so they generate **zero** cases — the pin covers exactly one flag. Its non-vacuity guard asserts that *some* flag cites an ADR, which stays green even if the parametrization drops to zero. That guard is tightened alongside this register.

273
evals/logos/fa1_gate.py Normal file
View file

@ -0,0 +1,273 @@
"""FA-1 — the pre-registered holonomy-gate experiment.
Criterion, corpus rules, negative classes and anti-gaming rules are registered in
`docs/analysis/fa1-holonomy-gate-preregistration.md` committed at `94f05ba8`, and amended
once (A1, the corpus bound) before any discrimination number existed. This module executes
that registration; every threshold it applies is quoted from it, and none is computed here.
Run: ``uv run python -m evals.logos.fa1_gate``
"""
from __future__ import annotations
import json
from collections import defaultdict
from dataclasses import dataclass
from itertools import combinations, permutations
import numpy as np
from algebra.cl41 import geometric_product, reverse as cl_reverse
from algebra.versor import unitize_versor
from alignment.graph import load_alignment
from evals.logos.manifold_collapse import _census
from evals.logos.repaired_ground import IDENTITY, LOGOS_MOUNT, forward_walk, repaired_compiler
from packs.compiler import load_mounted_packs, load_pack_entries
#: Packs whose alignment.jsonl is read. Every edge they author participates; none is dropped
#: by hand. An edge whose endpoints do not resolve inside LOGOS_MOUNT is counted and reported.
ALIGNED_PACKS = ("he_logos_micro_v1", "grc_logos_micro_v1", "he_core_cognition_v1", "grc_logos_cognition_v1")
#: Three content words is ADR-0015's own canonical clause shape ("Logos, beginning, truth"),
#: and the shortest length at which word order can be broken in more than one way.
CLAUSE_LEN = 3
#: Pre-registered thresholds — anti-gaming rule 1 forbids editing these after numbers exist.
G1_AUC = 0.80
G2_AUC = 0.75
G3_ORDER_SENSITIVITY = 0.90
#: Amendment A1: cross-pair negatives per aligned pair, drawn deterministically from the
#: sorted enumeration. Classes 1 and 2 stay complete.
CROSS_NEGATIVES_PER_PAIR = 5
@dataclass(frozen=True)
class Concept:
"""One aligned meaning and its realisation in each language that carries it."""
key: str
surfaces: tuple[tuple[str, str], ...] # (language, surface), sorted — hashable
@property
def by_language(self) -> dict[str, str]:
return dict(self.surfaces)
@property
def languages(self) -> frozenset[str]:
return frozenset(language for language, _ in self.surfaces)
def _relation_stem(relation: str) -> str:
"""`cross_lang.logos.illumination.pointed.en` → `cross_lang.logos.illumination`."""
return relation.replace(".pointed", "").replace(".en_collapse", "").replace(".en", "")
def build_concepts() -> tuple[list[Concept], dict]:
"""Group every resolvable alignment edge into meanings. Mechanical; nothing hand-picked.
Where a language offers several surfaces for one meaning (`אור` / `אוֹר`), the
lexicographically first is taken one rule, applied uniformly, fixed before the run.
"""
surface_of: dict[str, tuple[str, str]] = {}
for pack_id in LOGOS_MOUNT:
for entry in load_pack_entries(pack_id):
surface_of[entry.entry_id] = (entry.language, entry.surface)
grouped: dict[str, dict[str, set[str]]] = defaultdict(lambda: defaultdict(set))
edges = unresolved = 0
for pack_id in ALIGNED_PACKS:
for edge in load_alignment(pack_id).aligned_pairs("cross_lang"):
edges += 1
source, target = surface_of.get(edge.source_id), surface_of.get(edge.target_id)
if source is None or target is None:
unresolved += 1
continue
stem = _relation_stem(edge.relation)
grouped[stem][source[0]].add(source[1])
grouped[stem][target[0]].add(target[1])
concepts = [
Concept(key=stem, surfaces=tuple(sorted((lang, sorted(surfaces)[0]) for lang, surfaces in langs.items())))
for stem, langs in sorted(grouped.items())
if len(langs) >= 2
]
census = {
"edges_authored": edges,
"edges_unresolved_under_R3": unresolved,
"concepts": len(concepts),
"trilingual_concepts": sum(1 for concept in concepts if len(concept.languages) >= 3),
"clause_sets": len(list(combinations(range(len(concepts)), CLAUSE_LEN))),
}
return concepts, census
def _auc(positive: list[float], negative: list[float]) -> float:
"""P(a random aligned pair deviates LESS than a random negative). Ties count a half.
Computed by sorting rather than by the O(n·m) double loop the corpus is ~10^5 negatives
and the naive form is the difference between seconds and an hour.
"""
if not positive or not negative:
return float("nan")
pos = np.sort(np.asarray(positive, dtype=np.float64))
neg = np.asarray(negative, dtype=np.float64)
strictly_less = np.searchsorted(pos, neg, side="left").sum() # positives below each negative
less_or_equal = np.searchsorted(pos, neg, side="right").sum()
ties = less_or_equal - strictly_less
return float((strictly_less + 0.5 * ties) / (len(pos) * len(neg)))
def run() -> dict:
concepts, census = build_concepts()
index_of = {concept: position for position, concept in enumerate(concepts)}
with repaired_compiler(LOGOS_MOUNT):
manifold = load_mounted_packs(LOGOS_MOUNT)
surfaces, distinct, groups = _census(manifold)
walk_cache: dict[tuple[tuple[str, ...], str], np.ndarray | None] = {}
def walk(sequence: tuple[Concept, ...], language: str) -> np.ndarray | None:
"""`F(X)` for one clause, memoised — the same ordered tuple recurs constantly."""
key = (tuple(concept.key for concept in sequence), language)
if key not in walk_cache:
try:
versors = [manifold.get_versor(concept.by_language[language]) for concept in sequence]
except KeyError:
walk_cache[key] = None
else:
walk_cache[key] = forward_walk(versors)
return walk_cache[key]
def deviation(sequence_a: tuple[Concept, ...], la: str, sequence_b: tuple[Concept, ...], lb: str) -> float | None:
"""`d(A,B) = ‖unitize(F(A)·reverse(F(B))) 1‖`, versor sign-ambiguity resolved."""
forward, backward = walk(sequence_a, la), walk(sequence_b, lb)
if forward is None or backward is None:
return None
holonomy = unitize_versor(geometric_product(forward, cl_reverse(backward)))
return float(min(np.linalg.norm(holonomy - IDENTITY), np.linalg.norm(holonomy + IDENTITY)))
# ---- the aligned corpus: every C(24,3) concept set, every language pair carrying it
aligned: list[float] = []
pairs: list[tuple[tuple[Concept, ...], str, str]] = []
clause_sets = list(combinations(concepts, CLAUSE_LEN))
for concept_set in clause_sets:
shared = sorted(frozenset.intersection(*(concept.languages for concept in concept_set)))
for position, la in enumerate(shared):
for lb in shared[position + 1 :]:
value = deviation(concept_set, la, concept_set, lb)
if value is None:
continue
aligned.append(value)
pairs.append((concept_set, la, lb))
# ---- class 1, lexical substitution (complete: every position × every replacement)
n_lexical: list[float] = []
for concept_set, la, lb in pairs:
for position in range(CLAUSE_LEN):
for replacement in concepts:
if replacement in concept_set or lb not in replacement.languages:
continue
broken = concept_set[:position] + (replacement,) + concept_set[position + 1 :]
value = deviation(concept_set, la, broken, lb)
if value is not None:
n_lexical.append(value)
# ---- class 2, word order (complete: every non-identity permutation of the return clause)
n_order: list[float] = []
order_sensitive = order_total = 0
for index, (concept_set, la, lb) in enumerate(pairs):
base = aligned[index]
for permuted in permutations(concept_set):
if permuted == concept_set:
continue
value = deviation(concept_set, la, permuted, lb)
if value is None:
continue
n_order.append(value)
order_total += 1
order_sensitive += int(value > base)
# ---- class 3, cross-pairing (Amendment A1: first 5 disjoint sets in sorted order)
n_cross: list[float] = []
cross_offered = 0
for concept_set, la, lb in pairs:
start = max(index_of[concept] for concept in concept_set)
taken = 0
for other in clause_sets:
if taken >= CROSS_NEGATIVES_PER_PAIR:
break
if min(index_of[concept] for concept in other) <= start:
continue
if set(other) & set(concept_set):
continue
cross_offered += 1
value = deviation(concept_set, la, other, lb)
if value is None:
continue
n_cross.append(value)
taken += 1
# ---- controls, reported regardless of outcome (anti-gaming rule 4)
self_loops = [
value
for value in (deviation(concept_set, la, concept_set, la) for concept_set, la, _ in pairs)
if value is not None
]
negatives = n_lexical + n_order + n_cross
g1 = _auc(aligned, negatives)
g2 = _auc(aligned, n_cross)
g3 = order_sensitive / order_total if order_total else float("nan")
g4_lost = surfaces - distinct
verdict: dict = {
"corpus": census,
"ground_after_repair": {
"mount": list(LOGOS_MOUNT),
"surfaces": surfaces,
"distinct_coordinates": distinct,
"coordinates_lost": g4_lost,
"collision_groups": len(groups),
},
"controls": {
"max_self_loop_deviation": max(self_loops) if self_loops else float("nan"),
"aligned_pairs": len(aligned),
"negatives_generated": {
"lexical_substitution": len(n_lexical),
"word_order": len(n_order),
"cross_pair": len(n_cross),
"cross_pair_candidates_offered": cross_offered,
},
},
"measurements": {
"median_aligned": float(np.median(aligned)) if aligned else float("nan"),
"median_negative": float(np.median(negatives)) if negatives else float("nan"),
# Per-class, for diagnosis. These are the pre-registered classes reported
# separately; no criterion is attached to them that is not already in §4.
"median_lexical": float(np.median(n_lexical)) if n_lexical else float("nan"),
"median_word_order": float(np.median(n_order)) if n_order else float("nan"),
"median_cross_pair": float(np.median(n_cross)) if n_cross else float("nan"),
"auc_vs_lexical": _auc(aligned, n_lexical),
"auc_vs_word_order": _auc(aligned, n_order),
"auc_vs_cross_pair": _auc(aligned, n_cross),
},
"criterion": {
"G1_separation": {"required": f"AUC >= {G1_AUC}", "observed": g1, "pass": bool(g1 >= G1_AUC)},
"G2_cross_pair": {"required": f"AUC >= {G2_AUC}", "observed": g2, "pass": bool(g2 >= G2_AUC)},
"G3_word_order": {"required": f">= {G3_ORDER_SENSITIVITY}", "observed": g3, "pass": bool(g3 >= G3_ORDER_SENSITIVITY)},
"G4_no_collapse": {"required": "coordinates_lost == 0", "observed": g4_lost, "pass": bool(g4_lost == 0)},
},
}
verdict["VERDICT"] = "GO" if all(gate["pass"] for gate in verdict["criterion"].values()) else "NO-GO"
return verdict
def main() -> int:
print(json.dumps(run(), indent=2, ensure_ascii=False))
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -0,0 +1,154 @@
"""The repaired semantic ground — R1/R2/R3 of the FA-1 pre-registration.
`docs/analysis/fa1-holonomy-gate-preregistration.md` registers three repairs and the
criterion that judges them. This module implements the repairs; it takes no verdict.
Nothing here modifies the serving compiler. R1 and R3 are applied by *substituting two
module-level functions* inside a context manager, against the real compile path, so the
experiment measures the shipped pipeline with two operations corrected rather than a
re-implementation that could drift from it. The caches are cleared on entry and on exit,
so a repaired ground never leaks into anything else in the process.
R1 blend on the group instead of overwriting `algebra/rotor.py`'s geodesic
R2 close the loop around the *pair* `loop_deviation` below
R3 resolve alignment edges against the packs actually mounted, not an id-prefix table
"""
from __future__ import annotations
from contextlib import contextmanager
from typing import Iterator
import numpy as np
from algebra.cl41 import geometric_product, reverse as cl_reverse
from algebra.rotor import rotor_power, word_transition_rotor
from algebra.versor import unitize_versor
from packs import compiler as _compiler
#: The six packs that carry logos data. The serving path grounds Hebrew and Greek against
#: the `*_cognition_v1` pair (`chat/pack_grounding.py:56-57`); the micro packs are the
#: ADR-0015 seed. R3 exists so both participate — 63 of the 83 authored edges live in the
#: cognition packs and currently resolve to nothing.
LOGOS_MOUNT: tuple[str, ...] = (
"en_minimal_v1",
"en_core_cognition_v1",
"he_logos_micro_v1",
"he_core_cognition_v1",
"grc_logos_micro_v1",
"grc_logos_cognition_v1",
)
#: `en_collapse_anchors_v1` is DELIBERATELY ABSENT and cannot be added: its manifest declares
#: `role: "collapse_anchor"`, which is not a member of `packs.schema.LanguageRole`, so
#: `load_pack()` raises before the lexicon is read. `chat/pack_grounding.py` consumes it by
#: opening `lexicon.jsonl` on a raw path — bypassing the loader that would reject it — and 24
#: alignment edges point into it, all of which therefore resolve to nothing. The enum carries
#: a comment recording this exact failure once before (ADR-0097, `domain_seed`); a registry
#: widened by hand falls behind by hand. Reported by the gate as `edges_unresolved_under_R3`
#: rather than silently excluded.
#: Identity of Cl(4,1): the scalar 1. A closed loop returns here.
IDENTITY = np.zeros(32, dtype=np.float64)
IDENTITY[0] = 1.0
# ---------------------------------------------------------------------------
# R1 — interpolation that stays on the versor group
# ---------------------------------------------------------------------------
def geodesic_blend(source: np.ndarray, target: np.ndarray, strength: float) -> np.ndarray:
"""Move `source` a fraction `strength` along the group geodesic toward `target`.
The operation the compiler's `_blend_feature_versors` was named and parametrised for.
A linear combination of two versors is not a versor the group is not closed under
addition which is why `VocabManifold.update()` refuses one, and why returning the
target verbatim became the escape. `R^t · source`, with `R` the transition rotor, is
lawful at every `t`: it stays on the group by construction.
Endpoints are exact: `t=0` returns the source, `t=1` the target.
"""
strength = max(0.0, min(1.0, float(strength)))
src = np.asarray(source, dtype=np.float64)
if strength <= 0.0:
return np.asarray(source, dtype=np.float32).copy()
tgt = np.asarray(target, dtype=np.float64)
if strength >= 1.0:
return np.asarray(target, dtype=np.float32).copy()
moved = geometric_product(rotor_power(word_transition_rotor(src, tgt), strength), src)
return np.asarray(unitize_versor(moved), dtype=np.float32)
def _clear_pack_caches() -> None:
_compiler._load_pack_cached.cache_clear()
_compiler._load_mounted_packs_cached.cache_clear()
_compiler._load_pack_entries_cached.cache_clear()
@contextmanager
def repaired_compiler(pack_ids: tuple[str, ...] = LOGOS_MOUNT) -> Iterator[None]:
"""Compile with R1 (geodesic blending) and R3 (mount-wide edge resolution) in force.
R3 replaces the hardcoded `{"he": , "grc": , "en": }` prefix table with the packs
actually being mounted. Entry ids are pack-local, so a global prefix table can only
ever address the three packs it names; every edge belonging to any other pack of the
same language resolves to a pack that has never heard of it and is dropped in silence.
"""
original_blend = _compiler._blend_feature_versors
original_infer = _compiler._infer_foreign_pack_ids
def _infer_from_mount(home_pack_id: str, _graph) -> list[str]: # noqa: ANN001 - private type
# The graph is ignored on purpose: membership of the mount, not the shape of the
# edge ids, decides which packs an edge may address.
return [pack_id for pack_id in pack_ids if pack_id != home_pack_id]
_compiler._blend_feature_versors = geodesic_blend
_compiler._infer_foreign_pack_ids = _infer_from_mount
_clear_pack_caches()
try:
yield
finally:
_compiler._blend_feature_versors = original_blend
_compiler._infer_foreign_pack_ids = original_infer
_clear_pack_caches()
# ---------------------------------------------------------------------------
# R2 — the loop, closed around a pair of representations
# ---------------------------------------------------------------------------
def forward_walk(versors: list[np.ndarray]) -> np.ndarray:
"""`F(X) = v₁ · v₂ · … · vₙ` — the ordered geometric product of a clause's versors.
No per-token position rotor. The shipped encoder conjugates each token by its absolute
index, which was introduced so path order would survive degenerate scalar/vector test
fixtures; across languages, clauses differ in length, so that schedule injects a length
artefact into every cross-language comparison (RQ2 of the 2026-06-14 finding). Order
sensitivity does not depend on it: the geometric product is non-commutative.
"""
if not versors:
raise ValueError("cannot walk an empty clause")
walk = unitize_versor(np.asarray(versors[0], dtype=np.float64))
for versor in versors[1:]:
walk = geometric_product(walk, unitize_versor(np.asarray(versor, dtype=np.float64)))
walk = unitize_versor(walk)
return walk
def closed_holonomy(clause_a: list[np.ndarray], clause_b: list[np.ndarray]) -> np.ndarray:
"""`H(A,B) = unitize(F(A) · reverse(F(B)))` — transport out along A, return along B."""
return unitize_versor(geometric_product(forward_walk(clause_a), cl_reverse(forward_walk(clause_b))))
def loop_deviation(clause_a: list[np.ndarray], clause_b: list[np.ndarray]) -> float:
"""`d(A,B) = ‖H(A,B) 1‖` — the single declared metric of the FA-1 criterion.
Zero when the loop closes. The null hypothesis is the identity, so there is no
similarity threshold to calibrate and no metric to select after seeing the numbers
the failure mode of the June measurement, forbidden here by construction.
Sign note: `H` and `H` describe the same transport (versors are defined up to sign),
so the deviation is taken to the nearer of `±1`.
"""
holonomy = closed_holonomy(clause_a, clause_b)
return float(min(np.linalg.norm(holonomy - IDENTITY), np.linalg.norm(holonomy + IDENTITY)))

View file

@ -0,0 +1,125 @@
"""FA-1's verdict, pinned as a tripwire (G-25, L2, the CORE-Logos validation-gate claim).
Measured 2026-07-28 against the criterion registered at `94f05ba8`: on a semantic ground with
**zero** coordinate collisions and a genuinely closed loop, cross-language holonomy separates
aligned clauses from meaning-breaking ones at **AUC 0.557** a chance floor is 0.500. The
design's own word-order test holds only **64.4%** of the time. **NO-GO.**
Full result and diagnosis: `docs/analysis/fa1-holonomy-gate-verdict-2026-07-28.md`.
This pin exists for the reason the 2026-06-14 holonomy finding gave for its own tripwires: a
negative result that nothing checks decays into folklore, and the *interesting* failure mode
is the good one a future encoding that makes the gate real, landing silently while four
documents still say it was measured and refused. If any of these assertions goes red because
the numbers improved, that is not a regression: replace the guard with a proof, amend the ADRs
back, and update the verdict document in the same commit.
Both directions are pinned. The verdict may not silently become GO, and the measured values
may not silently drift either the gate is deterministic, so any movement means the ground,
the encoder, or the corpus changed, and each of those is a decision someone should be making
on purpose.
Cost: ~16s. Paid deliberately for the tripwire on the system's central design claim, the way
the daemon pin's 9.4s was paid — stated here rather than estimated.
"""
from __future__ import annotations
import pytest
from evals.logos.fa1_gate import G1_AUC, G2_AUC, G3_ORDER_SENSITIVITY, run
#: Measured 2026-07-28 at `94f05ba8`+1, deterministic and re-run bit-identical.
RECORDED = {
"G1_separation": 0.5570894467955959,
"G2_cross_pair": 0.6641552204384346,
"G3_word_order": 0.6444881889763779,
"G4_no_collapse": 0,
}
RECORDED_ALIGNED_PAIRS = 1016
RECORDED_CONCEPTS = 24
RECORDED_UNRESOLVED_EDGES = 24 # every one of them into the unloadable collapse-anchor pack
@pytest.fixture(scope="module")
def verdict() -> dict:
return run()
def test_the_repairs_still_work(verdict: dict) -> None:
"""G4 and the controls. If these fail, the NO-GO below is uninterpretable.
This is the half of the result that SUCCEEDED: the geodesic blend keeps every distinction
(0 lost coordinates where the shipped compiler loses 53 on this mount), and the closed loop
reports closure on a self-pair. A null result measured with a broken instrument constrains
nothing, which is exactly why the June measurement had to be re-run.
"""
assert verdict["ground_after_repair"]["coordinates_lost"] == 0, (
"G4 FAILED: the repaired ground now collapses coordinates. Every discrimination number "
"in this file is measured on a different ground than the verdict document describes."
)
assert verdict["controls"]["max_self_loop_deviation"] < 1e-4, (
"the loop no longer closes on a self-pair — the metric is broken, not the hypothesis"
)
assert verdict["controls"]["aligned_pairs"] == RECORDED_ALIGNED_PAIRS, (
f"corpus changed: {verdict['controls']['aligned_pairs']} aligned pairs vs "
f"{RECORDED_ALIGNED_PAIRS} recorded — re-baseline deliberately, in the verdict doc too"
)
def test_the_verdict_is_still_no_go(verdict: dict) -> None:
"""The tripwire. Red here means the design became real — go read the failure message."""
assert verdict["VERDICT"] == "NO-GO", (
"FA-1's holonomy gate now PASSES. This is good news and it is not a test failure to "
"silence: replace this guard with a proof, amend ADR-0005/0015 back (they were amended "
"to record the negative), and rewrite "
"docs/analysis/fa1-holonomy-gate-verdict-2026-07-28.md in the same commit."
)
criterion = verdict["criterion"]
assert not criterion["G1_separation"]["pass"], f"G1 now passes at {criterion['G1_separation']['observed']}"
assert not criterion["G2_cross_pair"]["pass"], f"G2 now passes at {criterion['G2_cross_pair']['observed']}"
assert not criterion["G3_word_order"]["pass"], f"G3 now passes at {criterion['G3_word_order']['observed']}"
def test_the_recorded_numbers_have_not_drifted(verdict: dict) -> None:
"""Deterministic gate, exact record. Movement in either direction is a reviewed decision."""
for gate, expected in RECORDED.items():
observed = verdict["criterion"][gate]["observed"]
assert observed == pytest.approx(expected, abs=1e-9), (
f"{gate} moved: {observed} vs {expected} recorded. The gate is deterministic, so "
"the ground, the encoder, or the corpus changed. Update this constant and the "
"verdict document together — two records that disagree is the G-22 disease."
)
assert verdict["corpus"]["concepts"] == RECORDED_CONCEPTS
assert verdict["corpus"]["edges_unresolved_under_R3"] == RECORDED_UNRESOLVED_EDGES, (
"the unresolved-edge count moved. All 24 point into en_collapse_anchors_v1, which "
"cannot load because its manifest declares role='collapse_anchor' and that is not a "
"member of packs.schema.LanguageRole. If this dropped to 0 the enum was widened — good; "
"record it, because those edges then join the corpus and every number above moves."
)
def test_the_gate_is_not_vacuous(verdict: dict) -> None:
"""A criterion that cannot pass proves nothing (R-11's lesson, PR-12's hollow guard).
The thresholds must be reachable and the classes must be ordered by meaning-distance
otherwise "NO-GO" would be an artefact of an impossible bar rather than a measurement.
"""
assert 0.5 <= G1_AUC <= 1.0 and 0.5 <= G2_AUC <= 1.0 and 0.5 <= G3_ORDER_SENSITIVITY <= 1.0, (
"a threshold outside [0.5, 1.0] would be unreachable or trivially met by chance"
)
measurements = verdict["measurements"]
assert measurements["median_aligned"] < measurements["median_negative"], (
"aligned pairs no longer close tighter than negatives — the signal reversed sign, which "
"is a different (and larger) finding than the recorded weak-but-correct-direction one"
)
# The classes order themselves by distance from the original meaning. This is the part of
# the design that DID hold, and it is what makes the null a measurement rather than noise.
assert (
measurements["median_lexical"] < measurements["median_word_order"] < measurements["median_cross_pair"]
), (
"the negative classes no longer order by meaning-distance "
f"(lexical={measurements['median_lexical']}, order={measurements['median_word_order']}, "
f"cross={measurements['median_cross_pair']}) — re-diagnose before trusting the verdict"
)
assert verdict["controls"]["negatives_generated"]["cross_pair"] > 0, "no negatives generated"