docs: ADR-0024 chain coverage across README, ADR index, contracts, papers
Patent-grade precision pass over the doc surface so every claim
about the Forward Semantic Control chain is backed by a file path,
test count, or commit hash.
Updates by file:
README.md
- Modernize Quick Start: add `core test --suite adr-0024`,
`core demo phase6 / phase5 / all / list-results`, full CLI map.
- New "Forward Semantic Control — The ADR-0024 Chain" section
with layer/ADR mapping and CI-enforced C1/C2/C3 claims table.
- Cross-links to runtime_contracts.md, phase5_stratified_findings,
phase6_comparative_demo, and the central results directory.
docs/decisions/README.md
- Index was stale at ADR-0014. Add ADR-0015 through ADR-0026
with accurate Accepted statuses.
- New "ADR-0024 chain — Forward Semantic Control closure" section
laying out the five-ADR / six-commit dependency order with test
counts per phase.
docs/runtime_contracts.md
- Add "Ranked-with-margin contract (ADR-0026 / Phase 3)" section
between the existing Phase 2 refusal and Phase 4 rotor sections.
- Documents threshold-mode vs margin-mode behaviour, δ = 0.4
default, falsifiability gate, and Cl(4,1) signature motivation.
docs/PROGRESS.md
- Add naming-note disambiguation: capability-roadmap "Phase N"
vs ADR-0024 chain "Phase N" are distinct.
- New top-of-document "ADR-0024 Chain — Forward Semantic Control
Closure" section with per-phase commit + test-count table and
a single-command verification path.
docs/Whitepaper.md
- New Section XII "Forward Semantic Control — Generation Without
Sampling" before Extensions. Five-component description of the
mechanism (region, intersection, destination check, rotor check,
margin gate) with explicit "what a sampling LLM cannot exhibit"
contrast. Existing Section XII renumbered to XIII.
docs/Yellowpaper.md
- New Section IX-B "Forward Semantic Control — Formal Admissibility
Specification" with eight subsections covering:
1. AdmissibilityRegion typed triple (I, B, Φ)
2. Destination-side admissibility (σ_dest, admit_threshold)
3. Rotor-side admissibility (σ_rotor, admit_rotor)
4. Ranked-with-margin gate (admit_margin, deterministic
tie-break by index, default δ = 0.4)
5. Honest refusal (InnerLoopExhaustion typed evidence,
RefusalReason enum, trace fold)
6. Composition order at the generation seam
(admit_step = intersection ∧ destination ∧ rotor)
7. Replay determinism contract (5 test lanes pinning byte
identity across reruns)
8. Verification invariants table (6 new structural contracts)
- Patent-grade: every predicate is named, every module is path-
referenced, every test is file-referenced, the load-bearing
architectural placement decision (rotor admissibility lives in
generate/, NOT algebra/, NOT field/) is stated by name with
its rejection reasoning.
No code changes; tests untouched (1099 passed, 2 skipped baseline
from commit 36aad75 still holds).
This commit is contained in:
parent
36aad75202
commit
3005cd6f9a
6 changed files with 529 additions and 3 deletions
70
README.md
70
README.md
|
|
@ -63,10 +63,76 @@ English establishes the operational base. Hebrew and Koine Greek bring the hidde
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install -e ".[dev]"
|
pip install -e ".[dev]"
|
||||||
pytest tests/test_versor_closure.py # must pass before anything else
|
pytest tests/test_versor_closure.py # the core invariant — must pass first
|
||||||
pytest tests/
|
pytest tests/ # full suite (~4 minutes, 1099 tests)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
The `core` CLI exposes curated entry points so reviewers can run any
|
||||||
|
subsystem in isolation. Highlights:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core test --list-suites # list curated pytest suite aliases
|
||||||
|
core test --suite fast # ~2s iteration lane
|
||||||
|
core test --suite cognition # cognition pipeline lane
|
||||||
|
core test --suite algebra # versor / CGA / vault parity
|
||||||
|
core test --suite adr-0024 # Forward Semantic Control chain (98 tests)
|
||||||
|
|
||||||
|
core demo phase6 # 3-condition comparative table (CORE vs baseline)
|
||||||
|
core demo phase5 # stratified 5-family mechanism-isolation
|
||||||
|
core demo all # both + combined summary
|
||||||
|
core demo list-results # index every JSON report with headline metrics
|
||||||
|
|
||||||
|
core eval --list # discover eval lanes
|
||||||
|
core eval cognition # run a discovered lane
|
||||||
|
core trace "your text here" # one-turn field-telemetry trace
|
||||||
|
core pulse "What is truth?" # one full cognitive pulse
|
||||||
|
core bench --suite latency # benchmark harness
|
||||||
|
core doctor --packs --rust # environment + pack + Rust status
|
||||||
|
```
|
||||||
|
|
||||||
|
Every demo run rewrites `evals/forward_semantic_control/results/`
|
||||||
|
including an auto-refreshed `index.json` manifest — the single
|
||||||
|
place reviewers can read to see every available report.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Forward Semantic Control — The ADR-0024 Chain
|
||||||
|
|
||||||
|
CORE generates text without sampling. The generation walk is
|
||||||
|
deterministic at the algebra level, but a deterministic walk over a
|
||||||
|
boundary-only candidate scorer can still emit tokens that are
|
||||||
|
inadmissible under the relation being asserted (e.g. answering a
|
||||||
|
*causes* question with the *means*-target). The ADR-0024 chain closes
|
||||||
|
that gap with five Architecture Decision Records and six phases of
|
||||||
|
implementation evidence.
|
||||||
|
|
||||||
|
| Layer | What it guarantees | ADR |
|
||||||
|
|---|---|---|
|
||||||
|
| **AdmissibilityRegion** | A typed region (`allowed_indices`, `relation_blade`, `frame_versor`) carried alongside every generation step. | [0022](docs/decisions/ADR-0022-forward-semantic-control.md) |
|
||||||
|
| **Region intersection proof** | The admissible token set is honored at the language/salience intersection layer. | [0023](docs/decisions/ADR-0023-forward-semantic-control-proof.md) |
|
||||||
|
| **Inner-loop destination check** | Each candidate's `cga_inner(versor(candidate), relation_blade)` is checked at the destination; rejection appears in `rejected_attempts`; exhaustion raises a typed `InnerLoopExhaustion`. | [0024](docs/decisions/ADR-0024-inner-loop-admissibility.md) |
|
||||||
|
| **Rotor / frame admissibility** | The rotor's *effect* on the field state is additionally checked against `frame_versor` in `generate/rotor_admissibility.py` — separate from algebra closure (intentional). | [0025](docs/decisions/ADR-0025-rotor-frame-admissibility-design-note.md) |
|
||||||
|
| **Ranked-with-margin gate** | Static-threshold tuning fails geometrically under Cl(4,1) signature; replaced with a scale-invariant margin gate (admit iff `score(top) − score(second) ≥ δ`). | [0026](docs/decisions/ADR-0026-ranked-admissibility-with-margin.md) |
|
||||||
|
|
||||||
|
The chain's three head-to-head claims, all CI-enforced:
|
||||||
|
|
||||||
|
| Claim | Test contract | Live demo |
|
||||||
|
|---|---|---|
|
||||||
|
| **C1 — Replay determinism** | `core test --suite phase6 -k TestC1` | `core demo phase6` |
|
||||||
|
| **C2 — Traced rejection** | `core test --suite phase6 -k TestC2` | `core demo phase6` |
|
||||||
|
| **C3 — Coherent refusal** | `core test --suite phase6 -k TestC3` | `core demo phase6` |
|
||||||
|
|
||||||
|
Full evidence:
|
||||||
|
|
||||||
|
* Runtime contract: [`docs/runtime_contracts.md`](docs/runtime_contracts.md) — Refusal / Margin / Rotor admissibility sections
|
||||||
|
* Stratified findings: [`docs/evals/phase5_stratified_findings.md`](docs/evals/phase5_stratified_findings.md) — 5 failure-mode families, 20 cases, per-family pass rates
|
||||||
|
* Comparative demo: [`docs/evals/phase6_comparative_demo.md`](docs/evals/phase6_comparative_demo.md) — three head-to-head conditions vs in-system baseline
|
||||||
|
* Reports directory: `evals/forward_semantic_control/results/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,51 @@
|
||||||
Tracks completion of the phased plan defined in `docs/capability_roadmap.md`
|
Tracks completion of the phased plan defined in `docs/capability_roadmap.md`
|
||||||
(ADR-0016). Updated as work lands.
|
(ADR-0016). Updated as work lands.
|
||||||
|
|
||||||
|
> **Naming note.** "Phase N" in this document refers to capability-roadmap
|
||||||
|
> phases (Phase 0 through Phase 5+). The ADR-0024 chain has its *own*
|
||||||
|
> six-phase plan (Phase 1 through Phase 6) which is tracked separately
|
||||||
|
> immediately below. Do not conflate the two.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-0024 Chain — Forward Semantic Control Closure
|
||||||
|
|
||||||
|
**Status:** Complete ✓
|
||||||
|
**Closed:** 2026-05-17
|
||||||
|
|
||||||
|
A standalone six-phase plan that closes forward semantic control as a
|
||||||
|
deterministic, trace-evidenced, refuse-able mechanism. Distinct from
|
||||||
|
the capability-roadmap phases below.
|
||||||
|
|
||||||
|
| Phase | Commit | Deliverable | Contract tests |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | `3940290` | Pack-grounded fixture rewrite + architectural finding | (rewrites) |
|
||||||
|
| 2 | `310793a` | Typed `InnerLoopExhaustion` + `RefusalReason` + trace fold | +10 |
|
||||||
|
| 3 | `639e107` | ADR-0026 ranked-with-margin gate (δ = 0.4 default) | +13 |
|
||||||
|
| 4 | `542e13d` | ADR-0025 rotor / frame admissibility (sibling module) | +11 |
|
||||||
|
| 5 | `b664984` | Stratified 5-family mechanism-isolation corpus + benign EXHAUSTION_CEILING corpus | +20 |
|
||||||
|
| 6 | `a076506` | Three-condition comparative demo (C1 replay / C2 traced rejection / C3 coherent refusal) | +17 |
|
||||||
|
| CLI | `36aad75` | Suite aliases (`adr-0024`, `refusal`, `margin`, `rotor`, …) + `core demo` subcommand + results manifest | +14 |
|
||||||
|
|
||||||
|
ADRs moved to Accepted under this chain: 0024, 0025, 0026.
|
||||||
|
ADRs strengthened: 0022 (TBDs closed), 0023 (proof evidence expanded).
|
||||||
|
|
||||||
|
Evidence locations:
|
||||||
|
|
||||||
|
- Runtime contracts: `docs/runtime_contracts.md` — Refusal / Margin / Rotor admissibility sections
|
||||||
|
- Stratified findings: `docs/evals/phase5_stratified_findings.md`
|
||||||
|
- Comparative demo: `docs/evals/phase6_comparative_demo.md`
|
||||||
|
- Reports: `evals/forward_semantic_control/results/` (+ auto-refreshed `index.json`)
|
||||||
|
- ADR index: `docs/decisions/README.md` — "ADR-0024 chain" section
|
||||||
|
|
||||||
|
How to verify on a fresh checkout:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core test --suite adr-0024 # 98 contract tests across the chain (~2 min)
|
||||||
|
core demo all # phase5 + phase6 + combined summary (~40 s)
|
||||||
|
core demo list-results # index of every JSON report with headline metrics
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 0 — Benchmark Methodology Lock-in
|
## Phase 0 — Benchmark Methodology Lock-in
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,102 @@ The `docs/DELETION_LOG.md` records every deleted subsystem and the algebraic rea
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### XII. Extensions
|
### XII. Forward Semantic Control — Generation Without Sampling
|
||||||
|
|
||||||
|
The CORE generation walk is deterministic at the algebra level —
|
||||||
|
every step is a versor product, every selection is the nearest-by-
|
||||||
|
`cga_inner` candidate. But a deterministic walk over a boundary-only
|
||||||
|
scorer can still emit tokens that are *inadmissible under the
|
||||||
|
relation being asserted*. Asking *"what does symbol cause?"* the
|
||||||
|
boundary may return *image* — geometrically nearest, but `means`-
|
||||||
|
related, not `causes`-related. The token is on the manifold; the
|
||||||
|
relation is wrong.
|
||||||
|
|
||||||
|
The Forward Semantic Control chain (ADR-0022 through ADR-0026) closes
|
||||||
|
this gap without introducing sampling, sampling temperature, or any
|
||||||
|
stochastic mechanism whatsoever. The mechanism has five components:
|
||||||
|
|
||||||
|
1. **AdmissibilityRegion** (ADR-0022). A typed region carried
|
||||||
|
alongside every generation step. Fields: `allowed_indices` (the
|
||||||
|
admissible token set), `relation_blade` (the multivector
|
||||||
|
characterizing the relation), and optionally `frame_versor` (the
|
||||||
|
rotor-side constraint). The region is constructed once per turn
|
||||||
|
from the proposition graph and held immutable through the walk.
|
||||||
|
2. **Region intersection at selection** (ADR-0023). At every
|
||||||
|
selection point, the language/salience candidate set is
|
||||||
|
intersected with `allowed_indices` before scoring. An empty
|
||||||
|
intersection raises `ValueError`; the walk routes to the
|
||||||
|
unknown-domain surface (honest refusal at the pre-walk boundary).
|
||||||
|
3. **Inner-loop destination check** (ADR-0024). The boundary
|
||||||
|
selection is re-evaluated against the relation blade via
|
||||||
|
`cga_inner(versor(candidate), relation_blade)`. Rejected
|
||||||
|
candidates are excluded and the walk re-selects; when every
|
||||||
|
candidate is rejected, generation raises `InnerLoopExhaustion`
|
||||||
|
carrying a typed `RefusalReason` (`INNER_LOOP_EXHAUSTION` or
|
||||||
|
`ROTOR_REJECTION`), the responsible region label, the step
|
||||||
|
index, and the full list of rejected attempts as evidence.
|
||||||
|
Refusal is not silent — it is structured data.
|
||||||
|
4. **Rotor / frame admissibility** (ADR-0025). When the region
|
||||||
|
carries a `frame_versor`, the rotor's *effect on the field
|
||||||
|
state* is additionally checked: `cga_inner(versor_apply(V, F),
|
||||||
|
frame_versor) > 0`. This check lives in
|
||||||
|
`generate/rotor_admissibility.py` — *not* in `algebra/versor.py`,
|
||||||
|
because admissibility is a pack-semantic test, not a closure
|
||||||
|
invariant. Putting it in algebra would couple closure to pack
|
||||||
|
state and structurally invite grade-projection "repair" of
|
||||||
|
inadmissible rotors. That coupling was rejected by name in the
|
||||||
|
ADR.
|
||||||
|
5. **Ranked-with-margin gate** (ADR-0026). A static
|
||||||
|
`admissibility_threshold` is brittle under the Cl(4,1)
|
||||||
|
Lorentzian signature: 23 of 85 tokens in the cognition pack have
|
||||||
|
*negative* self-`cga_inner`, so no scalar threshold separates
|
||||||
|
admissible from inadmissible across the corpus
|
||||||
|
(Phase 4 characterization confirms separation_quality < 0.8 at
|
||||||
|
every probed threshold). The chain replaces threshold tuning
|
||||||
|
with a scale-invariant margin test: admit iff
|
||||||
|
`score(top) − score(second) ≥ δ`. Default δ = 0.4, chosen from
|
||||||
|
the minimum observed margin in the Phase 3 adversarial corpus
|
||||||
|
and falsifiable against future cases.
|
||||||
|
|
||||||
|
The chain is enforced by 98 CI-level contract tests
|
||||||
|
(`core test --suite adr-0024`). Three head-to-head claims are pinned
|
||||||
|
against an in-system ablation baseline:
|
||||||
|
|
||||||
|
- **C1 — Replay determinism:** Trace hashes are byte-identical
|
||||||
|
across N reruns under both baseline and CORE; refusal events
|
||||||
|
themselves are replayable because `refusal_reason` is folded into
|
||||||
|
`trace_hash`.
|
||||||
|
- **C2 — Traced rejection:** When the boundary selection diverges
|
||||||
|
from the blade-aligned selection, the rejected token appears in
|
||||||
|
`rejected_attempts`. The rejection is *causally responsible* for
|
||||||
|
the selection difference, not just observable.
|
||||||
|
- **C3 — Coherent refusal:** When no candidate is admissible, the
|
||||||
|
walk raises `InnerLoopExhaustion` with a typed reason and
|
||||||
|
evidence list. The ablation baseline emits an inadmissible
|
||||||
|
candidate with `admitted = False` — observable but not
|
||||||
|
actionable. Typed refusal is *new in CORE*, not present in the
|
||||||
|
boundary-only baseline.
|
||||||
|
|
||||||
|
This is what we mean by "deterministic cognition that can refuse":
|
||||||
|
the system never samples to recover from an inadmissible state — it
|
||||||
|
either selects an admissible candidate, or it reports honestly that
|
||||||
|
it cannot.
|
||||||
|
|
||||||
|
A transformer LLM cannot exhibit these properties at the mechanism
|
||||||
|
level. Sampling has no place to attach an `AdmissibilityRegion`,
|
||||||
|
no way to make refusal first-class evidence, and no replay-
|
||||||
|
deterministic trace. The chain is the structural defense against
|
||||||
|
the confabulation failure mode at exactly the layer where it must
|
||||||
|
be defended — generation itself.
|
||||||
|
|
||||||
|
Full evidence: `docs/runtime_contracts.md` (contracts),
|
||||||
|
`docs/evals/phase5_stratified_findings.md` (geometric
|
||||||
|
characterization), `docs/evals/phase6_comparative_demo.md`
|
||||||
|
(head-to-head demo).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### XIII. Extensions
|
||||||
|
|
||||||
**CORE-Logos** — The language articulation subsystem. Specified in the companion Yellow and White Addenda inherited from `core-ai`. The Logos defines the vocabulary manifold, the token projection law, the holonomy encoder, and the termination condition.
|
**CORE-Logos** — The language articulation subsystem. Specified in the companion Yellow and White Addenda inherited from `core-ai`. The Logos defines the vocabulary manifold, the token projection law, the holonomy encoder, and the termination condition.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,215 @@ Personas compose. Two persona motors can be combined into a single motor before
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### IX-B. Forward Semantic Control — Formal Admissibility Specification
|
||||||
|
|
||||||
|
This section provides the precise mathematical specification of the
|
||||||
|
Forward Semantic Control mechanism (ADRs 0022, 0023, 0024, 0025,
|
||||||
|
0026). The Whitepaper describes the architectural commitment; this
|
||||||
|
section is the formal contract.
|
||||||
|
|
||||||
|
#### 1. AdmissibilityRegion
|
||||||
|
|
||||||
|
An `AdmissibilityRegion` is the triple
|
||||||
|
|
||||||
|
```text
|
||||||
|
R = (I, B, Φ)
|
||||||
|
|
||||||
|
where
|
||||||
|
I ∈ ℕᵏ : the admissible token index set (k ≥ 1)
|
||||||
|
B ∈ Cl(4,1) : the relation blade (a multivector, not necessarily simple)
|
||||||
|
Φ ∈ Cl(4,1)* : an optional frame versor (None ⇒ no rotor constraint)
|
||||||
|
```
|
||||||
|
|
||||||
|
Module: `generate/admissibility.py::AdmissibilityRegion`. The region
|
||||||
|
is constructed once per turn from the proposition graph and is
|
||||||
|
held immutable for the duration of the generation walk. No
|
||||||
|
in-walk mutation of `R` is permitted.
|
||||||
|
|
||||||
|
#### 2. Destination-side admissibility (ADR-0024)
|
||||||
|
|
||||||
|
For a candidate token `t` with versor `V_t ∈ Cl(4,1)`, define the
|
||||||
|
*destination score*
|
||||||
|
|
||||||
|
```text
|
||||||
|
σ_dest(t, R) = cga_inner(V_t, B)
|
||||||
|
```
|
||||||
|
|
||||||
|
In **threshold mode** (the back-compat default), `t` is *admitted*
|
||||||
|
iff
|
||||||
|
|
||||||
|
```text
|
||||||
|
admit_threshold(t, R, τ) ⇔ σ_dest(t, R) > τ
|
||||||
|
```
|
||||||
|
|
||||||
|
where `τ ∈ ℝ` is the `admissibility_threshold` configured per turn.
|
||||||
|
In **margin mode** (ADR-0026), the admissibility test is on a *pair*
|
||||||
|
of ranked candidates rather than a single candidate. See §4.
|
||||||
|
|
||||||
|
Module: `generate/admissibility.py::check_transition`.
|
||||||
|
|
||||||
|
#### 3. Rotor-side admissibility (ADR-0025)
|
||||||
|
|
||||||
|
When `R.Φ ≠ None`, the rotor that would advance the field state must
|
||||||
|
also be admissible. For a rotor `V` and current field state `F`,
|
||||||
|
define the *post-rotor field*
|
||||||
|
|
||||||
|
```text
|
||||||
|
F' = versor_apply(V, F) = V · F · reverse(V)
|
||||||
|
```
|
||||||
|
|
||||||
|
and the *rotor score*
|
||||||
|
|
||||||
|
```text
|
||||||
|
σ_rotor(V, F, Φ) = cga_inner(F', Φ)
|
||||||
|
```
|
||||||
|
|
||||||
|
The rotor is *admitted* iff
|
||||||
|
|
||||||
|
```text
|
||||||
|
admit_rotor(V, F, Φ) ⇔ σ_rotor(V, F, Φ) > 0
|
||||||
|
```
|
||||||
|
|
||||||
|
When `R.Φ = None` (or `||Φ|| < 10⁻⁸`), `admit_rotor` returns `True`
|
||||||
|
unconditionally with `σ_rotor = +∞` as the sentinel.
|
||||||
|
|
||||||
|
Module: `generate/rotor_admissibility.py::check_rotor_admissibility`.
|
||||||
|
|
||||||
|
**Architectural placement (load-bearing).** This check lives in
|
||||||
|
`generate/rotor_admissibility.py`, a sibling-but-separate module to
|
||||||
|
`generate/admissibility.py`. It is **not** placed in
|
||||||
|
`algebra/versor.py` (would couple algebra to pack-derived
|
||||||
|
admissibility state and structurally invite grade-projection
|
||||||
|
"repair" of inadmissible rotors) and **not** in
|
||||||
|
`field/propagate.py` (forbidden normalization/repair site per
|
||||||
|
`CLAUDE.md`).
|
||||||
|
|
||||||
|
#### 4. Ranked-with-margin gate (ADR-0026)
|
||||||
|
|
||||||
|
Given a candidate set `C ⊆ I` and the region `R`, compute the
|
||||||
|
ranked list
|
||||||
|
|
||||||
|
```text
|
||||||
|
ranked(C, R) = sort_descending_by_score_then_index([
|
||||||
|
(t, σ_dest(t, R)) for t in C
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
with stable tie-break by index (strict `<` on integer index, never
|
||||||
|
floating-point comparison on score). Let `(t₁, σ₁), (t₂, σ₂), …` be
|
||||||
|
the ordered list. The margin verdict is
|
||||||
|
|
||||||
|
```text
|
||||||
|
admit_margin(C, R, δ) ⇔
|
||||||
|
|C| = 1 ∧ σ₁ > 0
|
||||||
|
∨ |C| ≥ 2 ∧ σ₁ > 0 ∧ (σ₁ − σ₂) ≥ δ
|
||||||
|
```
|
||||||
|
|
||||||
|
where `δ ∈ ℝ₊` is the `admissibility_margin`. Default `δ = 0.4`.
|
||||||
|
|
||||||
|
The walk admits the top-ranked candidate `t₁` iff
|
||||||
|
`admit_margin(C, R, δ)` holds; otherwise the inner-loop raises
|
||||||
|
`InnerLoopExhaustion` with the full ranked list as evidence.
|
||||||
|
|
||||||
|
Modules:
|
||||||
|
`generate/admissibility.py::rank_candidates_by_blade`,
|
||||||
|
`generate/admissibility.py::check_margin` (returns typed
|
||||||
|
`MarginVerdict`).
|
||||||
|
|
||||||
|
**Why δ on the difference, not τ on the absolute score.** Under
|
||||||
|
the Cl(4,1) Lorentzian signature, self-`cga_inner` is signed: 23 of
|
||||||
|
85 tokens in `en_core_cognition_v1` have `σ_dest(t, V_t) < 0`. No
|
||||||
|
scalar `τ` separates admissible from inadmissible across the
|
||||||
|
corpus (`separation_quality < 0.8` at every probed `τ`,
|
||||||
|
characterized in `evals/forward_semantic_control/results/phase4_characterization_combined.json`).
|
||||||
|
A margin gate is scale-invariant under per-blade norm variation;
|
||||||
|
it survives where the static threshold fails.
|
||||||
|
|
||||||
|
#### 5. Honest refusal (ADR-0024 Phase 2)
|
||||||
|
|
||||||
|
When inner-loop admissibility leaves no admissible destination, or
|
||||||
|
when rotor-side admissibility refuses every candidate, the walk
|
||||||
|
raises `InnerLoopExhaustion`, a typed subclass of `ValueError`
|
||||||
|
carrying:
|
||||||
|
|
||||||
|
```text
|
||||||
|
InnerLoopExhaustion(
|
||||||
|
reason : RefusalReason,
|
||||||
|
region_label : str,
|
||||||
|
step_index : int, # -1 = pre-walk empty intersection
|
||||||
|
# ≥0 = in-walk per-step exhaustion
|
||||||
|
rejected_attempts : tuple[(int, str, float), ...],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
`RefusalReason` is an enum with stable string values:
|
||||||
|
|
||||||
|
| Value | Meaning |
|
||||||
|
|---|---|
|
||||||
|
| `"inner_loop_exhaustion"` | Destination-side: no candidate passed `admit_threshold` / `admit_margin`. |
|
||||||
|
| `"rotor_rejection"` | Rotor-side: candidate passed destination admit, but `admit_rotor` returned `False`. |
|
||||||
|
|
||||||
|
The reason value is folded into `compute_trace_hash` payload only
|
||||||
|
when non-empty, preserving byte-identical hashes for non-refused
|
||||||
|
turns (back-compat invariant) while making refusals themselves
|
||||||
|
replay-deterministic.
|
||||||
|
|
||||||
|
Module: `generate/exhaustion.py`. Trace fold:
|
||||||
|
`core/cognition/trace.py::compute_trace_hash`.
|
||||||
|
|
||||||
|
#### 6. Composition order at the generation seam
|
||||||
|
|
||||||
|
The full per-step admissibility predicate is the conjunction:
|
||||||
|
|
||||||
|
```text
|
||||||
|
admit_step(t, R, F, τ, δ) =
|
||||||
|
t ∈ I (region intersection, ADR-0023)
|
||||||
|
∧ admit_destination(t, R, τ, δ) (destination, ADR-0024 / 0026)
|
||||||
|
∧ admit_rotor(rotor_for(t), F, R.Φ) (rotor, ADR-0025)
|
||||||
|
```
|
||||||
|
|
||||||
|
where `admit_destination` is `admit_threshold` in threshold mode and
|
||||||
|
`admit_margin` in margin mode. The conjunction is evaluated
|
||||||
|
left-to-right and short-circuits at the first failing clause; the
|
||||||
|
clause that failed is encoded in the `RefusalReason` carried by any
|
||||||
|
subsequent `InnerLoopExhaustion`.
|
||||||
|
|
||||||
|
Module: `generate/stream.py::generate` (the seam itself).
|
||||||
|
|
||||||
|
#### 7. Replay determinism contract
|
||||||
|
|
||||||
|
For any fixed `(state, vocab, persona, region, mode, τ, δ)`, the
|
||||||
|
output `GenerationResult` is bit-identical across reruns, including
|
||||||
|
the `admissibility_trace` and (when refused) the `RefusalReason`,
|
||||||
|
`region_label`, `step_index`, and `rejected_attempts` carried by
|
||||||
|
`InnerLoopExhaustion`.
|
||||||
|
|
||||||
|
This contract is exercised by:
|
||||||
|
|
||||||
|
| Lane | Replay tests | File |
|
||||||
|
|---|---|---|
|
||||||
|
| Inner-loop admit | 5-rerun byte identity | `tests/test_inner_loop_admissibility.py` |
|
||||||
|
| Margin gate | 3-rerun replay | `tests/test_margin_admissibility.py` |
|
||||||
|
| Rotor admissibility | 5-rerun admit + 5-rerun refuse | `tests/test_rotor_admissibility.py` |
|
||||||
|
| Phase 5 stratified | 3-rerun across 20 cases | `tests/test_phase5_corpus.py::TestReplayDeterminism` |
|
||||||
|
| Phase 6 demo C1 | 5-rerun on 8 cases, baseline + CORE | `tests/test_phase6_demo.py::TestC1ReplayDeterminism` |
|
||||||
|
|
||||||
|
#### 8. Verification invariants added by the chain
|
||||||
|
|
||||||
|
| Invariant | Expression | Tolerance | Test file |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Refusal is typed | `isinstance(exc, ValueError) ∧ isinstance(exc, InnerLoopExhaustion)` | exact | `test_refusal_contract.py` |
|
||||||
|
| Reason is enumerated | `exc.reason ∈ RefusalReason` | exact | `test_refusal_contract.py` |
|
||||||
|
| Margin tie-break is stable | `rank_candidates_by_blade` returns deterministic ordering under exact tie | exact | `test_margin_admissibility.py` |
|
||||||
|
| Rotor closure preserved | `versor_condition(versor_apply(V, F)) < 1e-6` on admitted rotors | < 1e-6 | `test_rotor_admissibility.py` |
|
||||||
|
| Mechanism isolated (margin) | per-family `pass_rate_margin = 1.0` across 5 families | exact | `test_phase5_corpus.py` |
|
||||||
|
| Three-condition demo passes | `c1_pass ∧ c2_pass ∧ c3_pass` | exact | `test_phase6_demo.py` |
|
||||||
|
|
||||||
|
These are structural contracts, not regression tests. A failing
|
||||||
|
invariant means the chain is broken, not the corpus.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### X. Verification Invariants (The Implementation Gate)
|
### X. Verification Invariants (The Implementation Gate)
|
||||||
|
|
||||||
These are testable predicates. Every invariant has a corresponding test in `tests/`.
|
These are testable predicates. Every invariant has a corresponding test in `tests/`.
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,68 @@ ADRs record significant architectural decisions: what was decided, why, what alt
|
||||||
| [ADR-0012](ADR-0012-core-ingest-governance-layer.md) | `core_ingest` Governance Layer | Accepted |
|
| [ADR-0012](ADR-0012-core-ingest-governance-layer.md) | `core_ingest` Governance Layer | Accepted |
|
||||||
| [ADR-0013](ADR-0013-sensorium-multimodal-protocol.md) | `sensorium/` Multimodal Protocol Layer | Accepted |
|
| [ADR-0013](ADR-0013-sensorium-multimodal-protocol.md) | `sensorium/` Multimodal Protocol Layer | Accepted |
|
||||||
| [ADR-0014](ADR-0014-train-learning-loop.md) | `train/` Learning Loop | Accepted (Stub) |
|
| [ADR-0014](ADR-0014-train-learning-loop.md) | `train/` Learning Loop | Accepted (Stub) |
|
||||||
|
| [ADR-0015](ADR-0015-language-packs-and-holonomy-resonance.md) | Language Packs as Compiled Linguistic Manifolds | Accepted |
|
||||||
|
| [ADR-0016](ADR-0016-capability-roadmap.md) | Capability Roadmap and Eval Methodology | Accepted |
|
||||||
|
| [ADR-0017](ADR-0017-agency-scope.md) | Agency Scope: Responsive-with-Axiology | Accepted |
|
||||||
|
| [ADR-0018](ADR-0018-tool-use-scope.md) | Tool Use Scope: Typed Deterministic Operators | Accepted |
|
||||||
|
| [ADR-0019](ADR-0019-exact-vault-recall-acceleration.md) | Exact Vault Recall Acceleration | Accepted |
|
||||||
|
| [ADR-0020](ADR-0020-phase5-rust-parity-sequencing.md) | Phase 5 / Rust Parity Sequencing | Accepted (2026-05-16) |
|
||||||
|
| [ADR-0021](ADR-0021-epistemic-grade-policy.md) | Epistemic Grade Policy | Accepted |
|
||||||
|
| [ADR-0022](ADR-0022-forward-semantic-control.md) | Forward Semantic Control | Accepted (2026-05-17) |
|
||||||
|
| [ADR-0023](ADR-0023-forward-semantic-control-proof.md) | Forward Semantic Control: Proof Evidence | Accepted |
|
||||||
|
| [ADR-0024](ADR-0024-inner-loop-admissibility.md) | Inner-Loop Per-Rotor Admissibility | Accepted |
|
||||||
|
| [ADR-0025](ADR-0025-rotor-frame-admissibility-design-note.md) | Rotor / Frame Admissibility | Accepted (2026-05-17) |
|
||||||
|
| [ADR-0026](ADR-0026-ranked-admissibility-with-margin.md) | Ranked Admissibility with Margin | Accepted (2026-05-17) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ADR-0024 chain — Forward Semantic Control closure
|
||||||
|
|
||||||
|
ADR-0022 through ADR-0026 form a single coherent chain that closes
|
||||||
|
forward semantic control as a non-stochastic, replay-deterministic,
|
||||||
|
trace-evidenced mechanism. Read in order:
|
||||||
|
|
||||||
|
1. **ADR-0022** — Forward Semantic Control. Establishes the
|
||||||
|
`AdmissibilityRegion` data structure (allowed indices, relation
|
||||||
|
blade, frame versor) and the contract that a region restricts the
|
||||||
|
admissible token set at generation time.
|
||||||
|
2. **ADR-0023** — Proof Evidence. Boundary-only proof that the
|
||||||
|
admissibility region is honored at the *region intersection* level
|
||||||
|
but not yet at the destination-token level.
|
||||||
|
3. **ADR-0024** — Inner-Loop Per-Rotor Admissibility. Adds the
|
||||||
|
destination-side check: each per-step selection is re-evaluated by
|
||||||
|
`cga_inner(versor(candidate), relation_blade) > threshold`, with
|
||||||
|
honest refusal (`InnerLoopExhaustion`) when every admissible
|
||||||
|
candidate is rejected. Six phases of implementation evidence
|
||||||
|
(Phases 1-6) plus typed `RefusalReason` taxonomy.
|
||||||
|
4. **ADR-0025** — Rotor / Frame Admissibility. Adds the rotor-side
|
||||||
|
check: when a region carries a `frame_versor`, the rotor's effect
|
||||||
|
on the field state (`versor_apply(V, F)`) is additionally checked
|
||||||
|
against the frame for positivity in CGA inner product. Lives in
|
||||||
|
`generate/rotor_admissibility.py` — a sibling-but-separate module,
|
||||||
|
not in `algebra/versor.py` (would couple algebra to pack state)
|
||||||
|
and not in `field/propagate.py` (forbidden normalization site).
|
||||||
|
5. **ADR-0026** — Ranked Admissibility with Margin. Replaces static
|
||||||
|
threshold tuning with a scale-invariant margin gate: admit iff
|
||||||
|
the top blade-score exceeds the second by ≥ δ. Defaults to
|
||||||
|
δ = 0.4. Falsifiable; characterization documented in
|
||||||
|
`docs/evals/phase5_stratified_findings.md`.
|
||||||
|
|
||||||
|
Implementation evidence:
|
||||||
|
|
||||||
|
| Phase | Commit | Tests |
|
||||||
|
|---|---|---|
|
||||||
|
| Phase 1 — pack-grounded fixtures | `3940290` | (rewrites) |
|
||||||
|
| Phase 2 — typed refusals + trace fold | `310793a` | +10 |
|
||||||
|
| Phase 3 — ranked-with-margin gate | `639e107` | +13 |
|
||||||
|
| Phase 4 — rotor / frame admissibility | `542e13d` | +11 |
|
||||||
|
| Phase 5 — stratified mechanism-isolation | `b664984` | +20 |
|
||||||
|
| Phase 6 — comparative demo vs baseline | `a076506` | +17 |
|
||||||
|
| CLI surface (suite aliases + `core demo`) | `36aad75` | +14 |
|
||||||
|
|
||||||
|
Runtime contracts for the chain are pinned in
|
||||||
|
[`docs/runtime_contracts.md`](../runtime_contracts.md) (Refusal
|
||||||
|
contract, Margin contract, Rotor admissibility contract sections).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,55 @@ future ADR can wire materialisation (e.g. propagate the typed
|
||||||
exception to `ChatResponse.refusal_reason` or catch at the pipeline
|
exception to `ChatResponse.refusal_reason` or catch at the pipeline
|
||||||
seam) without re-deriving the contract.
|
seam) without re-deriving the contract.
|
||||||
|
|
||||||
|
### Ranked-with-margin contract (ADR-0026 / Phase 3)
|
||||||
|
|
||||||
|
The static `admissibility_threshold` documented above (ADR-0024 Phase 2)
|
||||||
|
is supplemented by a scale-invariant margin gate (ADR-0026 Phase 3).
|
||||||
|
The runtime selects mode via `RuntimeConfig.admissibility_mode`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
RuntimeConfig.admissibility_mode : "threshold" | "margin" (default: "threshold")
|
||||||
|
RuntimeConfig.admissibility_margin : float (default: 0.4)
|
||||||
|
```
|
||||||
|
|
||||||
|
In **threshold mode** (back-compat, ADR-0024):
|
||||||
|
|
||||||
|
```text
|
||||||
|
admit iff cga_inner(versor(candidate), relation_blade) > admissibility_threshold
|
||||||
|
```
|
||||||
|
|
||||||
|
In **margin mode** (ADR-0026):
|
||||||
|
|
||||||
|
```text
|
||||||
|
rank candidates by cga_inner(versor(candidate), relation_blade), descending,
|
||||||
|
stable tie-break by candidate index
|
||||||
|
admit iff (single candidate)
|
||||||
|
or (score(top) > 0 AND score(top) - score(second) >= admissibility_margin)
|
||||||
|
```
|
||||||
|
|
||||||
|
`generate.admissibility.rank_candidates_by_blade` returns the ranked
|
||||||
|
list with deterministic tie-break, and `generate.admissibility.check_margin`
|
||||||
|
returns a typed `MarginVerdict` (`admitted`, `top`, `second`, `gap`,
|
||||||
|
`reason`). The selection invariant is that the *score difference* is
|
||||||
|
the gate, not the absolute score — making the gate robust to per-blade
|
||||||
|
norm variation that defeated static threshold tuning on the
|
||||||
|
Phase 4 characterization corpus (see
|
||||||
|
`docs/evals/phase5_stratified_findings.md`).
|
||||||
|
|
||||||
|
Refusal in margin mode is materialised through the same
|
||||||
|
`InnerLoopExhaustion` mechanism as threshold mode, with
|
||||||
|
`RefusalReason.INNER_LOOP_EXHAUSTION` carrying the full ranked
|
||||||
|
candidate list as evidence so the failure mode is "no candidate has
|
||||||
|
margin over its successor" rather than "no candidate exceeded
|
||||||
|
threshold T."
|
||||||
|
|
||||||
|
The default δ = 0.4 was selected from the minimum observed margin in
|
||||||
|
the Phase 3 v2 corpus (0.456) and is *falsifiable*: any case
|
||||||
|
surfacing a blade-gap below δ where margin-mode refusal is the wrong
|
||||||
|
behavior must be reported as an ADR-0026 falsification rather than
|
||||||
|
silently patched per case. Phase 5's 20-case stratified corpus does
|
||||||
|
not falsify δ = 0.4.
|
||||||
|
|
||||||
### Rotor admissibility contract (ADR-0025 / Phase 4)
|
### Rotor admissibility contract (ADR-0025 / Phase 4)
|
||||||
|
|
||||||
The destination-side admissibility documented above (token-side blade
|
The destination-side admissibility documented above (token-side blade
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue