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
|
||||
pip install -e ".[dev]"
|
||||
pytest tests/test_versor_closure.py # must pass before anything else
|
||||
pytest tests/
|
||||
pytest tests/test_versor_closure.py # the core invariant — must pass first
|
||||
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
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3,6 +3,51 @@
|
|||
Tracks completion of the phased plan defined in `docs/capability_roadmap.md`
|
||||
(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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
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-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-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
|
||||
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)
|
||||
|
||||
The destination-side admissibility documented above (token-side blade
|
||||
|
|
|
|||
Loading…
Reference in a new issue