diff --git a/.claude/agents/dto-soa-savant.md b/.claude/agents/dto-soa-savant.md index 65a47ab6a..b69afcb55 100644 --- a/.claude/agents/dto-soa-savant.md +++ b/.claude/agents/dto-soa-savant.md @@ -51,7 +51,7 @@ reduce to one of: | **FingerprintColumns** | identity (model_name, OGIT URI, codebook entries) | NEVER (read-only) | `Vsa16kF32` identities, `Binary16K`, codebook URIs | | **QualiaColumn** | `[f32; 18]` per-row qualia (whose perspective) | per-row writes via CollapseGate | persona qualia, archetype dimensions | | **MetaColumn** | `MetaWord` bits (which style dispatches) | per-row writes | `MetaWord`, thinking-style bits | -| **EdgeColumn** | `CausalEdge64` (why/how, causal composition) | per-row writes via the Baton handoff | `CausalEdge64` v2 layout | +| **EdgeColumn** | `CausalEdge64` (why/how, causal composition) — the ALU register itself, never a reference | per-row writes of the register; the "Baton" is this register passing from one cycle into the next (the inter-mailbox emission wire is tombstoned) | `CausalEdge64` v2 layout | If the proposed epiphany **cannot** be reduced to one of these four (or to an EXISTING type that already operates over one of them), it is diff --git a/.claude/board/AGENT_LOG.md b/.claude/board/AGENT_LOG.md index 7f3465523..9090bc1cf 100644 --- a/.claude/board/AGENT_LOG.md +++ b/.claude/board/AGENT_LOG.md @@ -1,3 +1,55 @@ +## 2026-09-30 (2) — second 5+3 council on D-CPW (Cam96 v4 → v5; spec only, no code) + +- Operator-invoked (`go ahead with the v4 Phase-0 spec and run the 5+3`). Phases in order: Phase 0 `-v4.md` (committed `cff27034`, D-ids re-minted `95464b74` after `added-plans-have-dids` failed — the `D-C96P` family never matched the pattern); Phase 1 the five; Phase 2 draft v5 (scratchpad); Phase 3 the three on draft v5 only; Phase 4 fixes; Phase 5 ratified `-v5.md` + this board. +- **The 5 (Read-tool discipline, no cargo/git, own tag-files; S3 wrote its own):** + - prior-art (Opus): 10 — 1 VIOLATES (`TailVariant::V3` is the L1 6-byte tail, "there is no tail"); main prior art `causal-rung-standing-wave-v1` (mask → rails, escalation cascade); `E-PARTOF-ISA-vs-PALETTE256-1`; `palette_lookup` gap = pre-NARS strength. + - iron-rules: 10 — YIELDS-WITH-AP; the `FacetSchema` refusal needs a gate at every read; thresholds unlabelled; L-2 must use `pack_v2` and be gated. + - code-truth: every §2 citation graded (3 CLAIMED nuances); `FacetSchema`'s 2-bit field aliases the domain byte and has no reader; `causal_mask_bits` reaches no distance call; `range`/`disp` loaded nowhere; `Antecedent` resolves to an offset only; `_revised_truth` computed and discarded; emit/inverse disagree on mask bit 2. + - cascade: 8 — `PalettePair=3` contained but the field is unratified; `p64_target_identity_probe.rs:103-113` and `edge_v3_compare.rs:81-108` pin `row%256`; `Cam96` alias needs a newtype; 4-PR split. + - different-views: 10 — G-P vacuous by monotonicity; `P` deterministic from `(a,b)`; `M+` is the Gram sum in z; word-shuffle preserves the unigram histogram; named entities alias rank 0; identity is `(lemma, PoS)`. +- **The 3, on draft v5:** + - overclaim-auditor (Opus): **1 BLOCK** (the L4 code cannot be the instance key: lossy, `(x,n)`/`(x,v)` collide, HHTL routes on key bytes 4..12), 7 P1 (§3.2 is a proposal; six gammas; `Z_SELF` ties at 127; `f = range/range_max` is evidence amount; L-2 revises with a different metric; G-FC vacuous; F7/F8 disagree on Level 1), 6 P2. + - dilution-collapse-sentinel: 0 BLOCK, 5 P1 (`SPO ≡ SO`, `PO ≡ O` in geometry; "spread feeds c" a label; `self_code` is the basin's own higher-rung identity, not a copy; B collapsed; L-2's PoS→subspace map does not exist), 5 P2. + - firewall-warden: **1 BLOCK** (`self_code` meaning change with no refusal gate), 3 P1 (L-3 float representation and gating; G2/G3 rows; TECH_DEBT + plan-file rows), 2 P2. +- **v4 → v5 (ratified):** home = the row's second facet (bytes 16..32), key untouched; `self_code` stays as the basin's identity with a per-class reading + refusal + paired test; `P` back in the score as a similarity of spreads; one shared gamma, `Z_SELF = 127`; L-1 `f` = reading share, `c` from `ln(1+freq)`; L-2 on the triple register with the p64 semiring = `T_0`; §3.2 graded PROPOSAL (D-CPW-12); B rejected; G-FC/G-EDGE re-specified; L-3 split (D-CPW-13); F23 three references + `ReferenceSet` + G-REF + D-CPW-14, measured (3 of 4,264 shared words ordinal-aligned; 116 5k lemmas absent from the 20k; the Tigris academic artifact is a vocabulary carve). +- Operator input mid-council: the three-reference-set ruling; the Tigris bucket checked via the `AWS_*` environment (names only, never values): `lance-graph/codebooks/deepnsm-v2-academic-coca-v1/` fetched to the scratchpad, never into the repo. +- Authorized: D-CPW-1. Queued: D-CPW-2, -6, -7, -9, -14. Rest Blocked. + +## 2026-09-30 — 5+3 council on D-C96P (Cam96 → 6 × pairwise; spec only, no code) + +- Operator-invoked `/5plus3` on `deepnsm-v2-cam96-pairwise-v1.md`. The phases ran in order: + - Phase 0: orchestrator brief with frozen decisions F1–F9 and per-savant question sets. + - Phase 1: the five savants. + - Phase 2: draft v2. + - Phase 3: the three reviewers, on v2 only. + - Phase 4/5: ratified `-v3.md`. +- **The 5 (read-only, Read-tool discipline):** + - prior-art (opus): 10 findings, e.g. the contract's atanh already exists; FamilyGamma only in bgz-tensor; the 08-11 level-vs-rank entry; ndarray k-means to reuse. + - iron-rules: I-LEGACY VIOLATES on the persisted `self_code` until D-C96P-7; the others YIELD or NA. + - code-truth (general-purpose): every citation CODED; the §8 consumer list incomplete; G2 vacuous by construction; a metric mismatch in G1. + - cascade-impact: about 30 mandatory + 12 follow-up files; a rename breaks tesseract-rs; ordering D-7 before D-8. + - different-views: c₂ likely carries 2–3 bits; the full-shuffle null cannot stay silent; no Voronoi gate. + - Three savants had no write tool; the orchestrator banked their outputs in the scratchpad. +- **The 3, on v2:** + - overclaim-auditor (opus): 2 BLOCK — the loader's raw arrays alias `Cam96`; G1 compared against pinned figures from absent embeddings. Plus 5 P1 and 5 P2. + - dilution-collapse-sentinel: 0 BLOCK, 4 P1, 7 P2 — no decision rule for B/D; spread and relation conflated; F7 had no falsifier; G4 vacuous. + - firewall-warden: 1 BLOCK — no same-commit board-hygiene clause. Plus 2 P2. +- **Operator input mid-council (2026-09-30):** the resonance reading and the segment reading of `[a,b]`, and whether a merge is correct. The orchestrator checked it against `E-PERTURBATION-CONVERGENCE-1`: + - The merge is exact via the triangle identity `t = θ_a/φ`, with excess `ε`. + - A static position must be stored (invariant 1). + - A, B and D are projections of one object. +- **v1 → v2 → v3:** + - The reading was contested (A/B/D) and is resolved as the merge M, with A/B/D as its ablations and a decision table (Q1 confirmation pending). + - Similarity is the exact Gram reconstruction cosine, which equals the baseline metric. + - G1's bar is an in-harness retrained control. + - The loader returns a view, never raw arrays. + - The board-hygiene clause is added. + - The byte-0 unit gate is restored. + - G3 is an ablation against a noise floor; G4 is structural. + - The §6.3 ClassView key is the owning NodeRow classid (verified); the mechanism goes to the envelope auditor. + - Codec-move defects fixed (module-path re-export, E0116). +- Authorized: D-C96P-0 and D-C96P-1 only. Blocked: everything else, on the embeddings (Q4). + ## 2026-09-29 — D-LXC-1 plan rewritten with Read (orchestrator, no agents, no code) - Operator-directed. The council run below read source with shell diff --git a/.claude/board/INTEGRATION_PLANS.md b/.claude/board/INTEGRATION_PLANS.md index a104d2a66..33bfd2c58 100644 --- a/.claude/board/INTEGRATION_PLANS.md +++ b/.claude/board/INTEGRATION_PLANS.md @@ -1,3 +1,101 @@ +## 2026-09-30 (7) — deepnsm-v2-cam96-pairwise-v5 — §11R: the socket is an observation contract, not an instruction set (revises (6), after #1305) → `-v5.md` §11R + +**Status:** revised, spec only. #1305's committed findings decide it: +- a mask is support, not bag (2-hop `count(*)` 4 vs popcount 3); +- a forward chain is the exact support of the terminal only; +- DataFusion counts walks (5 vs trail 4); +- `consumer_semantics()` names five carrier kinds. + +The stable socket is therefore population · relation (a population with two index lanes, not a fourth primitive) · step(observation) → answer or `Insufficient`. mask-risc's MASK · TRANSPORT · REDUCE become lowering vocabulary below it. One directed hop lowers to ONE existing mask-risc `Program`, and the five #1305 kinds map onto its five observations exactly at k = 1. + +Frozen as law: a carrier crosses a boundary only if sufficient for every promised observation; path semantics is explicit; zero means false only inside a declared `(space, epoch)` domain; rendering is outside computation. Measured violation of the last-but-one: mask-risc's zero fallback plus length-only foreign checks (`ISS-MASK-RISC-ZERO-FALLBACK-IS-NOT-EVALUATED-FALSE`). + +The `ScatterOrU32` prohibition is not relaxed; the condition for a future relaxation is recorded. `CausalEdge64` stays above: a value lane, not a relation. Next PR: quack observation types + the existing doc⋈line⋈partner DuckDB oracle. + +## 2026-09-30 (6) — deepnsm-v2-cam96-pairwise-v5 — §11: the execution socket under the lexical substrate (D-CPW-15) → `-v5.md` §11 + +**Status:** ruled, spec only. The socket the lexical/cognitive stack lowers into already exists: `lance-graph-mask-risc`'s IR (`Program`, `Planes`/`LaneRef`/`Foreign`, `Value`/`Out`). `lance-graph-quack` is the DuckDB-shaped surface ABOVE it, not the ABI. The proposed six verbs reduce to three families already in the IR: MASK, TRANSPORT (`Gather` / `ScatterOrU32` / `EqU32Via` / `GroupKey::Via`) and REDUCE (one terminal). SELECT would be the forbidden `SelectionVector`; multi-hop traversal is OPEN. `CausalEdge64` crosses as a borrowed `u64` lane (`edges_raw()`), bit-preserving; its feature-gated layout stays above the line. Firewall: mask-risc depends on `ndarray` only, through `ndarray::simd`. Falsifiers G-SOCK-1..5: exact equality holds because the IR is integer-only. Measured gap: `MatchU64` is exercised only at bits 12–15. Open: Arrow `ListArray` needs a segment view (`ISS-MASK-RISC-HAS-NO-SEGMENT-VIEW`). + +## 2026-09-30 (5) — deepnsm-v2-cam96-pairwise-v5 — CORRECTION 3: `CausalEdge64` IS the ALU register → `-v5.md` § ⊘ CORRECTION 3 + +**Status:** not a reference, lens, record, carrier, or word container. v5's §3.2 lens framing and §3.4 L-2 "triple edge carries needles" wording struck. Same commit: the live doc comments that called it a "baton edge" (`mailbox_soa.rs`, `backing.rs`, contract `cognition/{cascade,advance}.rs`), `dto-soa-savant.md`'s "via the Baton handoff", `docs/GENETIC_RESEARCH_VIA_STACK.md`, a `CausalEdge64` row in the worker-guardrails vocabulary, and a ⊘ note on `deepnsm-v3-convergence-v1.md`'s "1-byte refs" row. Residue left in code: `TD-CE64-REGISTER-FRAMING-RESIDUE-1`. + +## 2026-09-30 (4) — deepnsm-v2-cam96-pairwise-v5 — CORRECTION 2: `[a,b]` is a word's 16-bit lexical address, not two poles → `-v5.md` § ⊘ CORRECTION 2 + +**Status:** the unit of representation is pinned. Six lexical slots per 96-bit payload; each two-byte address resolves to a word's declared reading (lemma + PoS) in an immutable, versioned lexical codebook (`ReferenceSet`); the driver supplies the relational reading, Fisher-z calibrated. Embeddings are an optional comparison instrument, never the runtime intermediary; embedding reconstruction is not an acceptance criterion. The artifact check that forced this: nothing assigns a word two needles (COCA CAM-PQ gives six, bgz17 `nearest` gives one; "(nearest : second-nearest)" was v1's invention). **First regression = G-LEX:** exact lexical address resolution, lemma/PoS survive, no cross-read across codebooks. + +## 2026-09-30 (3) — deepnsm-v2-cam96-pairwise-v5 — RETRACTED-IN-PART by operator ruling, same day → `-v5.md` § ⊘ RETRACTION + +**Status:** the embedding-slice half of v5 (§3.1–3.3, the word-register half of §3.2, D-CPW-0/3/4/12) is STRUCK. *"We don't want fuzzy embedding of 6 different readings of SPO … no witness … the sentence's deterministic words … no basin identity, superposition of 2 needles … not rails … 6 words each represented as LUT … a word is spatial perturbation LUT."* + +**The design:** one calibrated COCA `palette256` codebook; a word = one pair `(a:b)` = two needles superposed = its cell in the 256×256 LUT; a facet's 12 bytes = six words of the sentence; relations = LUT reads between cells (the p64 `CognitiveShader` over the bgz17 semiring, the perturbation field around the cell — `cognitive-shader-driver` is the machine); meaning in the ClassView. + +**Kept:** F23 three references + `ReferenceSet` (D-CPW-14), `self_code` as the basin's own identity (D-CPW-7), the COCA prior (D-CPW-9), register-F (D-CPW-13), lemma routing (D-CPW-11), the Fisher-z LUT into the contract (D-CPW-1 — now the representation itself). D-CPW-2 and -10 re-scoped to the word-cell. + +**Open:** how the codebook assigns a word its two needles — read from the artifact, not designed in a plan. + +## 2026-09-30 (2) — deepnsm-v2-cam96-pairwise-v5 — RATIFIED by the second 5+3 council → `.claude/plans/deepnsm-v2-cam96-pairwise-v5.md` + +**Status:** RATIFIED v5. Supersedes `-v4.md` (Phase-0 spec) and v3 §3 / §6.3 / §7 decision table. D-ids re-minted as `D-CPW-*` (the `D-C96P` family never matched the D-id pattern). + +**Why a second council:** three operator rulings after v3 — no materialized point and no cosine; the readings are `CausalMask` 2³ projections selected by the rung ladder; the `6×[a,b]` code is a content-blind facet of the 512-byte row — plus the COCA-fixed-points mandate and the three-reference-set ruling. + +**What v5 settles.** +- The identity is `[a,b]` = (nearest, second-nearest), two full palette bytes per subspace, in the row's **second facet** (bytes 16..32), read as `NeedlePair` by ClassView election. Not the key (uniqueness), not `self_code` (the basin's own identity, F25). +- Similarity = Fisher-z table reads over the active planes (O, S, and the spread `P` as a similarity of spreads), one shared gamma, `Z_SELF = 127` by address. No slerp, no cosine. +- The masks are an escalation cascade `O → PO → SPO` (a PROPOSAL, D-CPW-12 — `causal_mask_bits` reaches no distance call today). v3's B rejected (a coordinate, not an address); M/M−j carried `t` and survive only as the G-T lane arm. +- COCA levers: `f` = a reading's share among its surface form's readings, `c` from `ln(1+freq)`; triple edges carry the parsed words' subspace-0 needles with the p64 semiring = `T_0`; register-F is routing, not meaning; lemma routing Blocked (no text→loci producer). +- **F23 three references** (COCA4096 / COCA5K_LEMMA / COCA20K_ACAD), `ReferenceSet` in every reading contract, an explicit `(lemma, PoS)` correspondence artifact, gate G-REF. Measured: 3 of 4,264 shared words keep the same ordinal across the 5k and the 20k; 116 5k lemmas are absent from the 20k. The Tigris academic artifact is a vocabulary carve, not a trained codebook. + +**Authorized:** D-CPW-1 (codec move). Queued: D-CPW-2, -6, -7, -9, -14. Everything else Blocked on the embeddings (Q3) or on those. + +## 2026-09-30 (1) — deepnsm-v2-cam96-pairwise-v3 — RATIFIED by the 5+3 council → `.claude/plans/deepnsm-v2-cam96-pairwise-v3.md` + +**Status:** RATIFIED v3. Supersedes `-v1.md` and the council draft `-v2.md`, which are kept as the record. + +**The reading.** It is the operator's merge **M**: +- byte 0 = the needle `a`; +- byte 1 = `(j : t)`: the `j`-th fixed neighbour `b` of `a`, and the position `t` along the arc a→b. + +It unifies the resonance reading (`r_a`, `r_b`) and the segment reading (`φ = arccos T(a,b)`) through `t = θ_a/φ`. The earlier readings A (2-NN pair), B (Fisher-z values) and D (the table dual) are measured as M's ablations, under a pre-registered decision table. + +**Similarity** is the exact reconstruction cosine from Gram cells and norms, which is the baseline metric itself. + +**Gating.** +- G1's bar is an in-harness retrained 12-axis control. +- Only D-C96P-0 (the harness) and D-C96P-1 (the codec move) are authorized. +- The rest waits on the embeddings (Q4) and on operator Q1–Q5. + +## 2026-09-29 (3) — deepnsm-v2-cam96-pairwise-v1 — Cam96 from twelve independent axes to six pairwise rails → `.claude/plans/deepnsm-v2-cam96-pairwise-v1.md` + +**Status:** SPEC v1, PROPOSAL. No code authorized; `/5plus3` before any wave. + +**The problem:** the shipped Cam96 quantizes 12 unrelated 8-d halves and sums +12 distances (`space.rs:195-272`). That is twelve indices, not the +`6 × (u8:u8)` relations the facet plan and the needle/pair entry specify. + +**The change:** +- **Rail:** each of 6 subspaces gets ONE 256-centroid codebook, and a rail + becomes `(nearest : second-nearest)` in that codebook. Byte 0 alone is the + 48-bit point code. The colon's value is the per-subspace Fisher-z table + cell, i.e. the neighbourhood's spread. +- **Distance:** in z-space, choosing between three candidates by held-out + measurement. +- **Consequences:** + - The Fisher-z codec moves into the contract. + - New artifact magics and a newtype code gate old from new. + - The persisted `EpisodicBasin` self-code needs a read-mode marker first. + +**Blocked:** the 96-d embeddings the retrain needs are not in the release. + +**Open:** +- where the frequency/PoS header lives, given the classid canon; +- the reconstruct choice for `basin.rs`. + +Rail order is settled as nearest-first, because G2 and R3 depend on it. + +D-ids `D-C96P-1..8`. + ## 2026-09-29 (2) — deepnsm-v2-lexical-evidence-consumer-v1 rewritten against the DeepNSM → DeepNSM-v2 migration → `.claude/plans/deepnsm-v2-lexical-evidence-consumer-v1.md` **Status:** PROPOSAL (D-LXC-1..10). No code authorized. Supersedes entry (1) @@ -21,7 +119,6 @@ first version rested on shell searches and missed the migration documents. first-wins today) switched to a counted, named selection rule. FSM input stays one `Pos` per token. Convergence brief for a second session: `.claude/prompts/deepnsm-v2-lexical-consumer-converge.md`. - ## 2026-09-19 (1) — waben-fold-execution-loop-v1 — from the merged folds to one addressed execution loop → `.claude/plans/waben-fold-execution-loop-v1.md` **Status:** PROPOSAL. No code authorized; this is the grounded implementation diff --git a/.claude/board/ISSUES.md b/.claude/board/ISSUES.md index 7e3df4816..f091b48d2 100644 --- a/.claude/board/ISSUES.md +++ b/.claude/board/ISSUES.md @@ -1,3 +1,46 @@ +## ISS-MASK-RISC-ZERO-FALLBACK-IS-NOT-EVALUATED-FALSE — out-of-range and wrong-table inputs answer FALSE silently (2026-09-30) + +**Status:** OPEN. **Basis:** VERIFIED-IN-CODE (`lance-graph-mask-risc` `ir.rs`). +- `MaskOp::Gather` out of range is "the zero-fallback … never an error". +- `Pred::EqU32Via`: an fk naming no foreign row "does not match". +- `GroupKey`: a key past the universe drops the row. +- A `ForeignPlane` is checked only by its `rows`, so a same-length mask over the wrong or a stale table is accepted. + +Inside a declared, fully evaluated domain with validated index lanes these answers are right; outside it they turn not-evaluated into false. +- **Not in scope of** `deepnsm-v2-cam96-pairwise-v5` §11R (D-CPW-15), which freezes the law (§11R.2 rule 5, §11R.6) and builds nothing. +- **What closes it:** `(space, epoch)` identity on populations and index lanes with equality at every join point, a domain declaration, and index-lane validation per epoch. Falsifier: one out-of-range index value and one epoch mismatch each REFUSE, where today they answer. + +## ISS-MASK-RISC-HAS-NO-SEGMENT-VIEW — an Arrow `ListArray` cannot enter the socket without materializing a parent-index lane (2026-09-30) + +**Status:** OPEN. **Basis:** VERIFIED-IN-CODE (`lance-graph-mask-risc` `ir.rs`: `LaneRef = {I32, U32, U64, Strided}`, no offsets view; no `Arrow`/`ListArray` token in mask-risc, quack or report). The IR's factorized adjacency is a per-child index lane (`Gather`, `EqU32Via`, `GroupKey::Via`, `ScatterOrU32`) or a key-ordered lane (`CountKeyRunsU32`). A `ListArray` carries `offsets[parents + 1]`; turning that into a per-child parent-index lane is O(children), a derived-lane materialization. +- **Not in scope of** `deepnsm-v2-cam96-pairwise-v5` §11 (D-CPW-15), which names the gap and builds nothing. +- **What closes it:** a workload that needs it, then one structural view (segments/offsets) plus a parent-mask → child-mask expansion (a union of `mask_set_range` writes) and its reverse. The falsifier is `==` against the same program over the equivalent index lane, with no O(children) allocation. + +## ISS-CE64-EMIT-INVERSE-BIT2-DISAGREE — the driver packs p64 plane bits as a CausalMask; the inverse reads bit 2 differently (2026-09-30) + +**Status:** OPEN. **Basis:** VERIFIED-IN-CODE (council S3, R2). `driver.rs:489` packs `CausalMask::from_bits(h.predicates & 0x07)` where `predicates` is the p64 predicate-plane byte (bit0 CAUSES, bit1 ENABLES, **bit2 SUPPORTS**; `p64-bridge/src/lib.rs:121-128`). `edge_to_layer_mask` (`p64-bridge/src/lib.rs:74-76`) maps mask bit 2 (the S plane) to **CONTRADICTS**. Emit and its inverse disagree on bit 2; three mask vocabularies (rung, Pearl, p64) meet at one byte. +- **Not in scope of** `deepnsm-v2-cam96-pairwise-v5` (recorded there, §3.2). +- **What closes it:** one named mapping in `p64-bridge` used by both directions, with a round-trip test that can fail on bit 2. + +## ISS-DID-PATTERN-EXCLUDED-D-C96P — the `D-C96P` family never matched the D-id regex (2026-09-30) + +**Status:** OPEN. **Basis:** MEASURED (`added-plans-have-dids` on #1303, `plan_dids.py`). The pattern `D-[A-Z]{2,}[A-Z0-9]*(-[A-Z0-9]+)*` requires two letters after `D-`; `C96P` has a digit second, so every `D-C96P-*` row (v1–v3, STATUS_BOARD) was invisible to `plan_dids` and to the supersession coverage column. v5 re-mints them as `D-CPW-*` with an alias column. +- **What closes it:** either the pattern admits a digit after one letter, or the v1–v3 rows are re-labelled; the alias column keeps the history either way. + +## ISS-PAIRPALETTE-IS-TWO-AXES-NOT-A-PAIR — the contract's palette256² is two independent axes (2026-09-29) + +**Status:** OPEN. **Basis:** VERIFIED-IN-CODE. `recipe_substrate::PairPalette`: +- holds two codebooks, `basin` and `identity`; +- its `distance` is "the sum of the per-axis squared-L2s" (`recipe_substrate.rs:125-147`). + +A `(u8, u8)` is therefore a 2-D point on two unrelated axes. It is not a relation +between two centroids of one codebook, which is the needle/pair split of +`E-PALETTE256-IS-A-NEEDLE-THE-COLON-IS-THE-DISTRIBUTION-1`. This is the same +shape as the shipped Cam96 (`entries/2026-09-29-cam96-is-twelve-axes-not-six-pairs.md`). + +- **Not in scope of** `deepnsm-v2-cam96-pairwise-v1`. That plan fixes Cam96 only. +- **What closes it:** decide whether `PairPalette` is meant as a 2-axis point (then rename it, since "pair" misleads) or as the L4 pairwise relation (then rebuild it on the per-codebook Fisher-z table, after D-C96P-1). + ## ISS-REPORT-NO-COMPOSITE-KEY-GROUP-FOLD — a 2-D fold costs one pass per partition member (2026-09-23) **Status:** OPEN. **Basis:** VERIFIED-IN-CODE. mask-risc's `GroupKey` is one diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index 80bd4a365..a1943d3c7 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -1,3 +1,57 @@ +## D-CPW — v5 RETRACTED-IN-PART (2026-09-30, operator, same day): read every row below through `-v5.md` § ⊘ RETRACTION + +**CORRECTION 2 (same day):** `[a,b]` = a word's 16-bit lexical address in a versioned codebook, not two poles. **D-CPW-2** = the 16-bit lexical-address slot type + `ReferenceSet` + exact resolution, gate **G-LEX** (every declared entry resolves to its declared lemma+PoS reading; no cross-read across codebooks) — the FIRST gate; every Jina-fidelity gate is struck as a criterion. **D-CPW-14** (correspondence artifact) is G-LEX's fixture. +**WITHDRAWN:** D-CPW-0, D-CPW-3, D-CPW-4, D-CPW-12 (they built or measured the struck embedding-slice code). **RE-SCOPED:** D-CPW-10 = the driver reads a sentence as six resolved words and supplies the relational reading. **UNCHANGED:** D-CPW-1 (the LUT into the contract — now the representation), -5, -6, -7, -8, -9, -11, -13, -14. Gates G-D/G-A/G-P/G-PO/G-M/G-T/G-ROT/G-UNIQ/G-CASC/G-ε/G1/G3/G3v/G5b are struck with the code they measured. + +Plan: `.claude/plans/deepnsm-v2-cam96-pairwise-v5.md`. The `D-C96P-*` ids never matched the D-id pattern (`D-[A-Z]{2,}…`); tooling joins on `D-CPW-*`. The table below is the ratification-time record. + +| D-id | alias | scope (v5) | status | gate / falsifier | +|---|---|---|---|---| +| **D-CPW-0** | D-C96P-0 | harness: the mask projections + `M+` + `t`-lane arms; in-harness 12-axis / 48-bit / RQ controls; split file | Blocked (embeddings, Q3) | G-D, G-A, G-P, G-PO, G-M, G-T, G-ROT, G0, G-ε, G1, G3, G3v, G5b | +| **D-CPW-1** | D-C96P-1 | Fisher-z codec into the contract; one shared gamma | Queued (authorized) | golden-bytes parity | +| **D-CPW-2** | D-C96P-2 | pair NEWTYPE + `PairReading` + `ReferenceSet` + refusal | Queued (after Q5) | G-L4, G-REF, G-UNIQ, G2, G5, G6 | +| **D-CPW-3** | D-C96P-3 | loaders, digest, view + `ReferenceSet` header | Blocked (on D-0) | G6 | +| **D-CPW-4** | D-C96P-4 | trainer: 6×16-d retrain, second-nearest encoder, `T_s` builder (ndarray fork) | Blocked (on D-0) | G1 | +| **D-CPW-5** | D-C96P-5 | `Cam96AxisSpace` alias; legacy kept; refusal | Blocked (on D-2) | G4, G6 | +| **D-CPW-6** | D-C96P-6 | `SemanticSpace` routing-only | Queued | G4 | +| **D-CPW-7** | D-C96P-7 | `self_code` per-class reading + refusal + paired legacy-nonzero test | Queued (envelope-auditor) | G-SELF, field-isolation matrix | +| **D-CPW-8** | D-C96P-8 | consumer migration, in tree then tesseract-rs | Blocked (on D-5, D-7) | G7, G8 | +| **D-CPW-9** | — | COCA prior reader (`freq`; PM via `freq_is_cosine.rs`) + reading share from `LexicalEvidence` + rank-alignment test | Queued (collides with D-LXC-4) | G-FC | +| **D-CPW-10** | — | driver L-2: triple edges, `T_0` semiring, `pack_v2`, revision wired, test storno | Blocked (on D-2, D-9; BackingStore precondition) | G-EDGE, G-PoS | +| **D-CPW-11** | — | L-4 lemma routing + `Antecedent` → row | Blocked (no text→loci producer) | G-LEM | +| **D-CPW-12** | — | rung → mask → similarity wiring (the cascade) | Blocked (on D-0, D-2) | G-CASC, G-PO | +| **D-CPW-13** | — | driver L-3 register F (`kl_from_prior`) | Blocked (on D-9) | G-F | +| **D-CPW-14** | — | `lexical_correspondence.tsv` generator + `ReferenceSet` digests | Queued | G-REF | +| **D-CPW-15** | — | the execution socket (v5 §11): it is `lance-graph-mask-risc`'s existing IR (quack is the surface above it); three families MASK · TRANSPORT · REDUCE; `CausalEdge64` crosses as a borrowed `LaneRef::U64` via `edges_raw()` and is not an IR type. Next PR: `tests/firewall.rs` (deps == `{ndarray}`, `ndarray::simd` only, no cognitive vocabulary, integer-only) + `tests/u64_register_lane.rs` (full-width `MatchU64`). **⊘ REVISED same day (v5 §11R, after #1305):** the socket is an OBSERVATION contract (population · relation = a population with two index lanes · step(observation) → answer or `Insufficient`), and the mask-RISC families are lowering vocabulary below it. Frozen as law: carrier sufficiency, explicit path semantics, unknown ≠ false inside a declared `(space, epoch)` domain, rendering outside computation. Next PR: quack observation contract + the doc⋈line⋈partner DuckDB differential (v5 §11R.8) | Queued (spec only in #1303) | G-SOCK-1..5 (G-SOCK-1 and -5 already shipped) + the §11R.8 differential, sufficiency refusal and unknown arm | + +## D-C96P — v3 RATIFIED (2026-09-30): SUPERSEDED-IN-PART by the D-CPW block above (v5); kept as the alias record + +Plan: `.claude/plans/deepnsm-v2-cam96-pairwise-v3.md`. The reading is the merge M; A/B/D are its ablations. + +| D-id | scope (v3) | status | gate / falsifier | +|---|---|---|---| +| **D-C96P-0** | the measurement harness: arms M, M−t, M−j, A, B, D; in-harness 12-axis / 48-bit / RQ controls; train/val/eval split file | Blocked (embeddings, Q4) | G0, G1 report, G3, G3v, G5b | +| **D-C96P-1** | Fisher-z codec into the contract; `fisher_z.rs` module-path re-export; atanh clamp factored out; `build_from_palette` becomes a free fn | Queued (authorized) | golden-bytes parity | +| **D-C96P-2..5** | the arm the decision table picks; loaders with a `Cam96PairCodes` view; `Cam96AxisSpace` alias; trainer separate from the harness | Blocked (on D-0) | G1, G2 unit gate, G3, G4, G5, G6 | +| **D-C96P-6** | `SemanticSpace` documented as routing-only; kept exported; no deprecation | Queued | G4 | +| **D-C96P-7** | per-class `self_code` shape reading (`ValueSchema` variant or new ReadMode axis) | Queued | v3-envelope-auditor | +| **D-C96P-8** | consumer migration, in tree then tesseract-rs (ordered after D-7) | Blocked (on D-5, D-7) | G7, G8 | + +## D-C96P — deepnsm-v2 Cam96 → 6 × pairwise distribution (2026-09-29) + +Plan: `.claude/plans/deepnsm-v2-cam96-pairwise-v1.md`. Entry: `entries/2026-09-29-cam96-is-twelve-axes-not-six-pairs.md`. Council (`/5plus3`) before any wave. + +| D-id | scope | status | gate / falsifier | +|---|---|---|---| +| **D-C96P-1** | analytic Fisher-z codec moves into `lance-graph-contract`; `bgz-tensor` consumes it | Queued | byte parity with `bgz-tensor::fisher_z` | +| **D-C96P-2** | `Cam96Pair` + `Cam96PairSpace`: 2-NN rail encode, R1/R2/R3 similarity, diagonal by address | Queued | G2, G5 | +| **D-C96P-3** | `CAM96P01`/`CAM96PW1` loaders, version gate, `Cam96AxisSpace` rename | Queued | G6 | +| **D-C96P-4** | Rust trainer + held-out harness (same seed/split as `train_codebook.py`) | Queued | G1, G3, G3b | +| **D-C96P-5** | the pair-code artifact + release | Blocked (96-d embeddings not in the release) | G1 PASS | +| **D-C96P-6** | retire `SemanticSpace` from the meaning path | Queued | G4 | +| **D-C96P-7** | `EpisodicBasin` read-mode marker for the 12 persisted bytes | Queued | `v3-envelope-auditor` | +| **D-C96P-8** | consumer migration (basin, examples; then tesseract-rs `consistency.rs`) | Queued | G7, G8 | + ## D-LXC — DeepNSM-v2 lexical-evidence consumer + candidate next parts (2026-09-29) Plan: `.claude/plans/deepnsm-v2-lexical-evidence-consumer-v1.md`. Convergence brief: `.claude/prompts/deepnsm-v2-lexical-consumer-converge.md`. diff --git a/.claude/board/TECH_DEBT.md b/.claude/board/TECH_DEBT.md index 81bbe2c6f..915599bf8 100644 --- a/.claude/board/TECH_DEBT.md +++ b/.claude/board/TECH_DEBT.md @@ -1,3 +1,19 @@ +## TD-CE64-REGISTER-FRAMING-RESIDUE-1 (2026-09-30) — OPEN, `CausalEdge64` framed as a carrier in live code + +`CausalEdge64` IS the ALU register (`edge.rs:1-3`; operator 2026-09-30); **"baton" is the same register as it passes from one cycle into the next** (operator, same day). What PR #477 tombstoned was the inter-mailbox emission wire (`CollapseGateEmission`, `emit()`), not the register persisting across cycles. +- ⊘ This entry's first version listed `MailboxSoA::apply_edges(&[(u16, CausalEdge64)])` as tombstoned residue. Struck: it is the register entering a row for the next cycle — the baton metaphor made literal — and is not residue. +- Remaining, open: `lance-graph-contract::transaction::{mod,interactive,bulk,periodisch}` and `cognition/op.rs` name "Baton emission" queues; whether they mean the cycle-to-cycle register (fine) or the tombstoned inter-mailbox wire (not) is a Stage-2 design question with its own owner. +- Historical plans and the frozen archive keep their wording (append-only); the worker-guardrails vocabulary row now states both meanings for workers. + +## TD-CPW-COUNCIL-RESIDUE-1 (2026-09-30) — OPEN, four items from the second Cam96 council + +Recorded by `deepnsm-v2-cam96-pairwise-v5.md` §8; none is a deliverable there. + +1. **Adjective / adverb role gap.** F12's role→PoS map covers S/O→nominal and P→verbal; `left·j` is selected by no S/P/O mask (archive `:21805`). Triple edges (D-CPW-10) fall back to the legacy path for modifiers; no plane exists for them. +2. **`RungLevel::causal_mask_bits` reaches no distance call.** Defined (`cognitive_shader.rs:244, :333`), exercised only by unit tests, `doc_graph.rs`, and a driver comment; `causal_distance` lives once in the planner (`nars_engine.rs:135`) with fixed masks. The rung→mask chain is a pure function until D-CPW-12. +3. **`FacetSchema`'s 2-bit field is provisional and aliases the domain byte.** `facet_schema.rs:48-54` reads `(facet_classid >> 24) & 0b11`; under canon-high those are the domain's low bits (OSINT `0x07` → 3); no `.schema()` caller exists. A reader landing on it would relabel domains. The v4 `PalettePair = 3` proposal was withdrawn for this reason. +4. **Six per-table `FamilyGamma`s make summed Fisher-z codes incommensurable.** `fisher_z.rs:28-33, 63-67`: each table has its own gamma; v5 §3.1 pins ONE shared gamma across the six subspaces and reports per-table fit loss (D-CPW-1). + ## TD-SYM-SUM-MERGE-IS-NOT-ADDITION-1 (2026-09-23) — OPEN, dormant **`GroupFold::SumSymI32`'s seed is not an additive identity, so two partial diff --git a/.claude/board/entries/2026-09-29-cam96-is-twelve-axes-not-six-pairs.md b/.claude/board/entries/2026-09-29-cam96-is-twelve-axes-not-six-pairs.md new file mode 100644 index 000000000..a0df73c26 --- /dev/null +++ b/.claude/board/entries/2026-09-29-cam96-is-twelve-axes-not-six-pairs.md @@ -0,0 +1,23 @@ +# 2026-09-29 — The shipped Cam96 is twelve independent axes, not six pairs + +**Status:** VERIFIED-IN-CODE · OPEN — spec `.claude/plans/deepnsm-v2-cam96-pairwise-v1.md` (D-C96P-1..8) + +## What the code does +- `Cam96Space` requires 12 axis codebooks (`space.rs:195-196`). +- `encode` quantizes each axis's own 8-d chunk against its own centroids (`:230-251`). +- `distance` sums 12 per-axis squared-L2 terms (`:257-272`). +- `rails()` pairs bytes for display only (`:287-289`); no distance reads it. +- The producer split "each 16-d subspace into a 256:256 pair", i.e. 12 × 8-d PQ (`probes/fidelity_48_vs_96.py:7`, `probes/train_codebook.py:57, 77`). +- Consequence: a rail's two bytes are two unrelated halves of a subspace. That is twelve indices, a finer point. It is not the `6×(u8:u8)` six relations that `E-PALETTE256-IS-A-NEEDLE-THE-COLON-IS-THE-DISTRIBUTION-1` and the facet plan (`deepnsm-morton-comma-facet-v1.md` §0) specify. + +## Measured context (already on record) +At 96 bits, held-out KJV: RQ point 0.786, 12-axis 0.774, 48-bit point 0.617 (`probes/README.md` §4). The 12-axis code does not beat an equal-budget point. + +## Also found +- `SemanticSpace` scores words at their frequency-rank `(basin, identity)` address (`space.rs:74-80`, `vocab.rs:14-21`). That is the facet plan's `PF=Payload` defection, and `SemanticSpace` is still exported. +- `recipe_substrate::PairPalette` is the same two-independent-axes shape (`recipe_substrate.rs:125-147`) → `ISS-PAIRPALETTE-IS-TWO-AXES-NOT-A-PAIR`. +- `episodic_basin::BasinRow.self_code` persists 12 Cam96 bytes with no marker of which code shape wrote them (`episodic_basin.rs:78-97`). + +## Open +- The pair-code artifact needs the 96-d embeddings. They are not in the `v0.1.0-cam96-data` release. +- Where the frequency/PoS header lives, given the classid canon, is undecided. diff --git a/.claude/board/entries/2026-09-30-the-execution-socket-is-mask-risc-ir.md b/.claude/board/entries/2026-09-30-the-execution-socket-is-mask-risc-ir.md new file mode 100644 index 000000000..2519bd4e3 --- /dev/null +++ b/.claude/board/entries/2026-09-30-the-execution-socket-is-mask-risc-ir.md @@ -0,0 +1,20 @@ +# 2026-09-30 — The execution socket under the lexical substrate already exists: it is `lance-graph-mask-risc`'s IR + +**Status:** VERIFIED-IN-CODE · OPEN (segment view, multi-hop) — plan `.claude/plans/deepnsm-v2-cam96-pairwise-v5.md` §11 (D-CPW-15) + +## Read (2026-09-30) +- `lance-graph-quack` is the DuckDB-shaped SURFACE: it builds `Program`s and never evaluates one (D-QCK-0..10). The socket is the IR it lowers to: `Program`, `Planes`/`LaneRef::{I32,U32,U64,Strided}`/`Foreign`, `Value`/`Out`/`ExecError`. +- mask-risc `[dependencies]` = `ndarray` only. `src/` reaches it only as `ndarray::simd`. `src/` has zero hits for NARS / Pearl / COCA / Fisher / lemma / `ReferenceSet` / EWA / Jirak / HHTL / shader / thinking / `CausalEdge`, and 26 hits for V3 storage geometry (`facet`, `classid`, `ClassView`, `NodeRow`), almost all in doc comments; one op name, `Pred::MatchFacetStrided`. +- mask-risc `src/` contains no `f32`/`f64`: the IR is integer-only, so executor/oracle `==` is an honest claim. +- `lgj-abi` (Java/Panama) already depends on mask-risc; quack is its dev-dependency only (D-QCK-10). +- `CausalEdge64` is `#[repr(transparent)]` over `u64`; the contract's `MailboxSoaView::edges_raw() -> &[u64]` is the zero-copy view. Its layout is feature-gated (`causal-edge-v2-layout`). +- The six proposed verbs reduce to three existing families: MASK, TRANSPORT (`Gather`, `ScatterOrU32`, `EqU32Via`, `GroupKey::Via`), REDUCE (one terminal). SELECT = mask + `Keep`; an index-compacting select is the forbidden `SelectionVector`. +- **Gap:** `tests/differential.rs` exercises `Pred::MatchU64` only with `care: 0xF000` (bits 12–15); a 32-bit truncation of a `u64` lane would pass. + +## Consequence +Nothing new is minted. The ruling names the socket, its firewall and its falsifiers (G-SOCK-1..5); the next PR adds two test files to mask-risc. + +## Open +- Arrow `ListArray` has no zero-copy route (no segment view): `ISS-MASK-RISC-HAS-NO-SEGMENT-VIEW`. +- Multi-hop traversal is not in the IR; `ISS-NO-MASK-HOP-OP` predates `Gather`/`ScatterOrU32` and was not re-read against them here. +- Whether "Quack" should name the socket (today it names only the surface above it). diff --git a/.claude/board/entries/2026-09-30-the-socket-is-an-observation-contract.md b/.claude/board/entries/2026-09-30-the-socket-is-an-observation-contract.md new file mode 100644 index 000000000..af678b9a2 --- /dev/null +++ b/.claude/board/entries/2026-09-30-the-socket-is-an-observation-contract.md @@ -0,0 +1,25 @@ +# 2026-09-30 — The execution socket is an observation contract; mask-RISC instructions sit below it + +**Status:** VERIFIED-IN-CODE · OPEN — plan `.claude/plans/deepnsm-v2-cam96-pairwise-v5.md` §11R (D-CPW-15). Revises `2026-09-30-the-execution-socket-is-mask-risc-ir.md` the same day. + +## Read (2026-09-30) +- **#1305, as committed** (branch `ccr-2fcc2bd3-8o7m2l`, `cypher-mask-multiplicity-contract-v1`, D-CMM-0..3): + - a mask is support, not bag: 2-hop `count(*)` is 4 under DataFusion, 3 as a popcount; + - a forward chain is the exact support of the terminal only: `count(DISTINCT b)` 3 vs 4; + - DataFusion counts walks: 5 vs trail 4 on a cycle, recorded OPEN; + - `consumer_semantics()` names five carrier kinds. +- The `Population / Relation / step` shape reported alongside #1305 is in no pushed ref; it was evaluated on its merits. +- **One directed hop is ONE mask-risc `Program` over the edge table:** + - `Gather` through the src lane and the dst lane, plus edge predicates, gives the edge population; + - `Any` / `Count` / `ScatterOrU32` / `GroupReduce{Lane}` / `Keep` answer Exists / Count / Support / CountBy / Edges. + - At k = 1 the five #1305 kinds map onto these one-to-one (a binding IS an edge row). +- **The IR collapses unknown to false** (`Gather` zero fallback, `EqU32Via` no-match, `GroupKey` drop), and `ForeignPlane` is checked by length only. +- **The existing quack DuckDB fixture is a FROM–VIA–TO relation** (`doc` ← `line.doc_id` · `line` · `line.partner_id` → `partner`), and quack's contract imports are `{facet, ordered_lane}` only. + +## Consequence +The stable socket is population · relation (a population with two index lanes) · step(observation) → answer or `Insufficient`. MASK · TRANSPORT · REDUCE are lowering vocabulary. Carrier sufficiency, explicit path semantics, unknown ≠ false, and rendering outside computation are frozen as law in the plan. No code. + +## Open +- The count lane for k > 1 (#1305 D-CMM-4); trail identity across hops. +- `(space, epoch)` identity and the domain declaration in code (`ISS-MASK-RISC-ZERO-FALLBACK-IS-NOT-EVALUATED-FALSE`). +- Whether "Quack" names the socket. diff --git a/.claude/board/entries/2026-09-30-three-reference-sets-are-not-ordinal-aligned.md b/.claude/board/entries/2026-09-30-three-reference-sets-are-not-ordinal-aligned.md new file mode 100644 index 000000000..a04996b39 --- /dev/null +++ b/.claude/board/entries/2026-09-30-three-reference-sets-are-not-ordinal-aligned.md @@ -0,0 +1,23 @@ +# 2026-09-30 — The three COCA reference sets are neither nested nor ordinal-aligned + +**Status:** MEASURED · OPEN — plan `.claude/plans/deepnsm-v2-cam96-pairwise-v5.md` §3.7 (F23, D-CPW-14, G-REF) + +## Measured (python over the committed CSVs and the Tigris artifact) +| reference | rows | distinct keys | key | +|---|---|---|---| +| COCA4096 — `crates/deepnsm/word_frequency/word_rank_lookup.csv`, ranks ≤ 4096 | 4,096 ranks | 3,559 words | rank (homographs share a rank) | +| COCA5K_LEMMA — `lemmas_5k.csv` | 5,050 | 4,380 lemmas / 5,050 (lemma, PoS) | (lemma, PoS) | +| COCA20K_ACAD — `academic_20k.csv`; Tigris `lance-graph/codebooks/deepnsm-v2-academic-coca-v1/` | 20,845 | 18,559 words / 20,842 (word, Pos) | `word_id` = admission order | + +- 5k ∩ 20k: 4,895 of 5,050 (lemma, PoS); 4,264 words; **116 of the 5k lemmas are absent from the 20k**. +- 4096 ∩ 20k: 3,462 of 3,559 words. +- **Ordinal alignment: 3 of 4,264 shared words carry the same ordinal in the 5k and in the 20k.** +- Ambiguity differs per set: the 20k carve drops 2,286 same-word-different-Pos duplicates to one id (MANIFEST: 18,559 of 20,480 reserved slots; basins 73..79 empty); the 4096 shares ranks across homographs; the 5k keeps (lemma, PoS) distinct. +- The Tigris "academic codebook" TSV is a `PaletteVocab::from_frequency_ranked` carve (`word_id, basin, slot, …`), not a trained centroid codebook. Its `academic_20k.csv` sha256 equals the committed file's. + +## Consequence +A reading contract names (reference id, version, digest); an ordinal is stable only within its reference; correspondence is an explicit (lemma, PoS) map with `Ambiguous{n}` / `Missing` as values; switching references must preserve the declared map and never reuse an ordinal. Gate G-REF re-derives this table and diffs it. + +## Open +- No embedding artifact exists for the academic reference (v5 Q7: own codebook vs correspondence-mapped centroids). +- `range`/`disp` are loaded by no `src/` code; `Vocabulary::load` never opens `lemmas_5k.csv`. diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index 393a6e819..beaf71087 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,11 +25,15 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately opposite directions; the stranding this convention prevents shows up in exactly one of them, never both. -176 entries, 2026-08-06 .. 2026-09-29. +180 entries, 2026-08-06 .. 2026-09-30. | date | entry id | finding | file | |---|---|---|---| +| 2026-09-30 | `three-reference-sets-are-not-ordinal-aligned` | | [2026-09-30-three-reference-sets-are-not-ordinal-aligned.md](2026-09-30-three-reference-sets-are-not-ordinal-aligned.md) | +| 2026-09-30 | `the-socket-is-an-observation-contract` | | [2026-09-30-the-socket-is-an-observation-contract.md](2026-09-30-the-socket-is-an-observation-contract.md) | +| 2026-09-30 | `the-execution-socket-is-mask-risc-ir` | | [2026-09-30-the-execution-socket-is-mask-risc-ir.md](2026-09-30-the-execution-socket-is-mask-risc-ir.md) | | 2026-09-29 | `deepnsm-v2-counted-pick-tag-deltas` | | [2026-09-29-deepnsm-v2-counted-pick-tag-deltas.md](2026-09-29-deepnsm-v2-counted-pick-tag-deltas.md) | +| 2026-09-29 | `cam96-is-twelve-axes-not-six-pairs` | | [2026-09-29-cam96-is-twelve-axes-not-six-pairs.md](2026-09-29-cam96-is-twelve-axes-not-six-pairs.md) | | 2026-09-26 | `deepnsm-v2-lexical-evidence-survives-routing` | | [2026-09-26-deepnsm-v2-lexical-evidence-survives-routing.md](2026-09-26-deepnsm-v2-lexical-evidence-survives-routing.md) | | 2026-09-25 | `window-scheduling-and-two-level-ternlog` | | [2026-09-25-window-scheduling-and-two-level-ternlog.md](2026-09-25-window-scheduling-and-two-level-ternlog.md) | | 2026-09-25 | `tile-knee-and-compiled-lowering` | | [2026-09-25-tile-knee-and-compiled-lowering.md](2026-09-25-tile-knee-and-compiled-lowering.md) | diff --git a/.claude/plans/deepnsm-v2-cam96-pairwise-v1.md b/.claude/plans/deepnsm-v2-cam96-pairwise-v1.md new file mode 100644 index 000000000..59322de5a --- /dev/null +++ b/.claude/plans/deepnsm-v2-cam96-pairwise-v1.md @@ -0,0 +1,281 @@ +# deepnsm-v2 Cam96 → 6 × pairwise distribution — spec (v1) + +> **Status:** SUPERSEDED by `deepnsm-v2-cam96-pairwise-v3.md` (ratified 2026-09-30); kept as the record. Was: SPEC v1, PROPOSAL. No code authorized. The change alters the +> meaning of 12 bytes that a contract layout already persists (§6.3), retrains +> an artifact, and moves a codec into the contract, so it is council-grade: +> run `/5plus3` on this spec before any implementation wave. +> **D-ids:** `D-C96P-1..8` (§9). +> **Written against:** lance-graph `main` `5282dfa3`. + +## 0. The one-sentence change + +Cam96 today is **12 independent axis codebooks**; each rail's two bytes are +two unrelated halves of a 16-d subspace, quantized apart and summed apart. +It becomes **6 subspaces × one 256-centroid codebook each, with every rail a +`(c₁:c₂)` pair of centroids of that one codebook, and the relation between +them read from a per-subspace Fisher-z table.** One byte finds a point; the +pair carries the spread. + +## 1. Sources, read in full before this spec + +| source | what it decides | +|---|---| +| `.claude/plans/deepnsm-morton-comma-facet-v1.md` §0, §1, §2, §5 | a word = `classid(4B) = norm(prefix, frequency, PoS)` · `payload(12B) = 6 × (FisherZ:FisherZ)`; frequency is a HEADER, never a distance axis; distance is analytic Fisher-z, palette256 is the cache | +| `.claude/board/entries/2026-08-26-e-palette256-is-a-needle-the-colon-is-the-distribution-1.md` | "palette256 can find a point like a needle in a haystack. For distribution it needs pairwise." · "`6×(u8:u8)` is six *relations*, not twelve indices" · the pair's carrier is the Fisher-z k×k LUT · self-similarity is 1.0 **by address**, never a lookup · gamma is fitted on off-diagonals only | +| `.claude/v3/soa_layout/le-contract.md` §3 L4 (`:59`), §"canonical cosine/centroid replacement is ANALYTIC" (`:169-186`) | L4 = `6 × (8:8)` palette256², "each byte pair indexes the 256×256 palette distance/compose tables"; the Fisher-z codec is canon and a k×k table is a cache of the formula | +| `EPIPHANIES-ARCHIVE-2026-09-20.md` `E-CAM96-DISTRIBUTION-MEASURED-1` (`:21058`) and `E-CAM96-REVIEW-CORRECTIONS-1` (`:21036`) | frequency ⟂ meaning (ρ ≈ −0.07 vs Jina); held-out 96-bit 0.766 vs 48-bit 0.624; the `axis_dim` defect and its strong test | +| `crates/deepnsm-v2/probes/README.md` §4 | KJV held-out: 48-bit POINT 0.617 · **96-bit POINT (RQ) 0.786** · 96-bit 12-axis 0.774 — "the 96-vs-48 gain is therefore mostly BUDGET"; the distribution's justification is the facet algebra, which residual coding breaks | +| `crates/deepnsm-v2/probes/fidelity_48_vs_96.py:7`, `train_codebook.py:22-29, 57, 77-95` | how the shipped code was made: "each 16-d subspace split into a 256:256 pair" = 12 × 8-d PQ | +| `crates/deepnsm-v2/src/space.rs`, `codebook.rs`, `basin.rs`, `lib.rs`, `vocab.rs`; `crates/deepnsm-v2/data/README.md` | the shipped code, its loader, its consumers, and where the artifacts live | +| `crates/bgz-tensor/src/fisher_z.rs` | `FamilyGamma` (8 B) + `FisherZTable` (k×k i8), the certified codec | +| `crates/lance-graph-contract/src/distance.rs`, `recipe_substrate.rs:76-156` | the contract's Fisher-z helpers (`similarity_z`, `fisher_z_inverse`, `mean_similarity_fisher`) and `PairPalette` | + +## 2. What ships today (verified in code, not from the board) + +- `pub type Cam96 = [u8; 12]` (`space.rs:163`); `Cam96Space` holds 12 axis + codebooks and panics unless `axes.len() == 12` (`space.rs:182-196`). +- `encode` quantizes each axis's own consecutive chunk against that axis's own + centroids (`space.rs:230-251`). Rail `r`'s two bytes are nearest centroids of + **two different 8-d halves**; neither byte knows the other exists. +- `distance` = `Σ_k ‖axis_k[a_k] − axis_k[b_k]‖²` over 12 axes (`:257-272`). No + pairing, no Fisher-z, no cosine. `rails()` (`:287-289`) is a view that no + distance ever reads. +- The artifact format enforces the same shape: `CAM96CB1`, `n_axes == 12` + (`codebook.rs:12-14, 58`); the trained file is 12 × 256 × 8-d. +- Consequence, in the needle entry's own terms: this is **twelve indices**, a + finer point, not six relations. Its 0.774 sits below the equal-budget RQ + point (0.786), which is what one expects of a finer point that is not a + better one. +- **Frequency also reaches a distance path.** `SemanticSpace::similarity` + scores words at their `(basin, identity)` address from `PaletteVocab::pair` + (`space.rs:74-80`), and `vocab.rs:14-21` makes that basin byte the + frequency-rank band. That is the facet plan's `PF=Payload` defection. It is + exported (`lib.rs:79`) and `Spo::pairs()` documents it as its consumer + (`spo.rs:51`). +- **The header does not exist.** No `classid` is minted for a word; routing is + the frequency-ranked `WordId` (`vocab.rs:23-26`), PoS lives in `fsm::Pos` and + `lexical::PosCode`, counts in `LexicalEvidence` (`data/README.md:19-26`). + +## 3. The target shape — the committed reading + +### 3.1 The rail + +For each of the 6 subspaces `s` (16-d each, the 48-bit code's split), train +**one** codebook `C_s` of 256 centroids. A word's subvector `v_s` encodes to + +``` +rail_s = (c₁ : c₂) c₁ = argmin_c ‖v_s − C_s[c]‖, c₂ = second-nearest in the SAME C_s +``` + +- **Each byte alone is a valid needle** into the same codebook: `c₁` is exactly + the 48-bit point code. This keeps the independent addressability that + `probes/README.md` §4 names as the distribution's reason to exist, and that + residual coding breaks. +- **The colon is the relation.** `(c₁, c₂)` is a cell of `C_s`'s own k×k + Fisher-z table; its value, `cos(C_s[c₁], C_s[c₂])`, is the spread of the + word's neighbourhood in that subspace. That is what "L4: each byte pair + indexes the 256×256 palette distance table" reads as for one word. +- **The diagonal is reserved for a point.** `c₁ == c₂` never arises from + 2-NN, so it is free to mean "no second pole": a word whose second-nearest is + far is written `(c₁ : c₁)` and reads as a needle with zero spread. The + far-threshold is a pre-registered variant, not a default (§7, G3b). + +### 3.2 Distance between two words + +Per subspace, the relation between two rails comes only from `T_s`, the +Fisher-z table of `C_s`. Three candidates, chosen by measurement (G1), not by +taste: + +| id | per-rail similarity | reads | what it is | +|---|---|---|---| +| R1 | `z̄ = mean_z(T(a₁,b₁), T(a₁,b₂), T(a₂,b₁), T(a₂,b₂))` | 4 | both poles against both poles, averaged in z-space | +| R2 | `z̄ = ½·(z(a₁,b₁) + mean_z(T(a₁,b₂), T(a₂,b₁)))` | 3 | the needles weighted as heavily as the cross terms | +| R3 | `T(a₁,b₁)` only | 1 | the 48-bit point, as a control | + +Word similarity = `tanh(mean over 6 rails of z̄_s)`. Averaging in z-space is +the contract's `mean_similarity_fisher` (`distance.rs:62-69`); no averaging +of raw cosines anywhere. + +A cell `(a, a)` is answered as `1.0` by address and never read from `T_s` +(needle entry, "self-similarity is 1.0 by definition of the address"). + +**Stated conflict:** le-contract L4 says "similarity = ONE table read". +R1/R2 read 3–4 cells per rail, and R3, the one-read form, is the needle. Only +R3 matches the one-read wording. If R1 or R2 wins G1, the L4 row needs an +amendment. This spec does not make it. + +### 3.3 Where the Fisher-z codec lives + +`deepnsm-v2` depends on `lance-graph-contract` only, and `FamilyGamma` / +`FisherZTable` live in `bgz-tensor`. **Decision proposed:** move the analytic +codec into the contract. It is about 40 zero-dep lines, and le-contract already +names it as canon for L4. `bgz-tensor` would then consume it rather than own it. +The rejected alternatives: + +- a deepnsm-v2 copy (a reimplementation); +- a `bgz-tensor` dependency (ndarray + holograph weight on a crate that is + zero-dep by design). + +This is a contract change and needs `v3-envelope-auditor` review. + +### 3.4 Readings rejected, and why + +- **B — `(z_location : z_spread)` as two quantized scalars.** Literal to the + plan's `FisherZ:FisherZ`, but a cosine to an anchor loses *which* direction: + two opposite words can share a location byte. It keeps no needle, so it fails + the independent-addressability requirement. +- **C — RQ `(coarse : residual)`**, which is also `deepnsm-morton-comma-facet-v1` + §3b's `(verb-atom : residual)`. It is the best raw point (0.786), but its + second byte is meaningless without the first, which `probes/README.md` §4 + names as the thing the facet algebra forbids. §3b is a v2 hook gated on the + 144-verb basis. It is not in scope and not adopted here. +- **D — keep 12 axes, re-document them as pairs.** The rails would still be + unrelated halves, so this is renaming, not the change. + +## 4. The header (frequency, PoS) + +- **Invariant kept:** frequency and PoS never enter the 12-byte payload or any + word-to-word distance. The trained codes already satisfy this: they come + from embeddings, and frequency only indexes them. `SemanticSpace` breaks it, + so D-C96P-6 retires it from the meaning path. +- **OPEN — the classid conflict.** The plan puts `norm(prefix, frequency, PoS)` + in `classid`. The classid canon (hi u16 = concept minted in `ogar-vocab`, + lo u16 = app prefix, never a shape ordinal) makes classid a class, not + per-word data. This spec does not resolve that. **Interim:** + - frequency stays in the routing `WordId`; + - PoS and counts stay in `LexicalEvidence`; + - both remain outside the payload, which is the invariant the plan's + measurement (`E-DEEPNSM-FACET-BLIND-CONVERGENCE-1`) actually confirmed. + Resolving where the header lives (a minted word concept plus the key + facet's routing tiers, or something else) is its own decision. + +## 5. The producer + +- **The codebook needs the 96-d embeddings, and they are not in the release.** + `v0.1.0-cam96-data` carries the 12 × 8-d codebook, the codes and + `bible_vocab.txt` (`data/README.md:9-13`). `bible_vocab_emb96.npy`, which + `train_codebook.py:3` reads, was never published. +- **Options:** + - (a) Re-embed through `probes/embed_bible_vocab.py` with a key the + operator supplies through the environment. No credential may enter the + repo, a commit or a brief. + - (b) Reconstruct each word from its current 12-axis code and fit on that. + This quantizes a quantization and is **allowed only as a probe arm**, + never as the shipped artifact. +- **The trainer moves to Rust** (`examples/train_cam96p.rs`). It reads a + little-endian `f32` embeddings blob and runs: + - k-means-256 per 16-d subspace; + - the 2-NN encode; + - the per-subspace `FamilyGamma` fit on off-diagonals. + It keeps the seed `0x9E3779B9` and the train/eval split of + `train_codebook.py` so G1 compares against 0.774 / 0.786 / 0.617 on the + same words. Embedding stays a lab script, because it needs the network; the + file it produces is data, not code. + +## 6. Format, types, and the version gate + +### 6.1 Artifacts +- `CAM96P01` codebook, laid out in this order: + 1. `u32` n_sub (6); + 2. `u32` dim (16); + 3. `u32` k (≤256); + 4. the `6 × k × dim` f32 centroids, subspace-major; + 5. `6 × FamilyGamma` (48 B — the "analytic 48 B γ" of the facet plan §5). + + An optional materialized `6 × k × k` i8 table section is a cache and is + never required. +- `CAM96PW1` codes: the same 12 bytes per word, with different meaning. +- **New magics are mandatory.** A `CAM96CB1` blob must be refused by the new + loader, and the old loader must refuse the new blob. + +### 6.2 Types +- The new code is a newtype, `Cam96Pair([u8; 12])`, not the `Cam96` alias, so + a CB1 code cannot be scored in a pair space by accident. Mixing them is a + compile error, not a runtime surprise. Old rows stay readable; new ones + cannot be minted in the old shape (I-LEGACY-API-FEATURE-GATED). +- `Cam96Space` becomes `Cam96AxisSpace`, deprecated. It still loads the + published v0.1.0 artifacts for reading and comparison, and nothing new is + built on it. + +### 6.3 The persisted 12 bytes +`lance-graph-contract::episodic_basin::BasinRow.self_code` (`episodic_basin.rs:78-97`) +and `canonical_node.rs:1062` store "the basin's own Cam96 centroid" as 12 raw +bytes. Once codes change meaning, a stored self-code is ambiguous without a +marker. **Required before any pair-coded self-code is written:** +- a read-mode / version marker on the `EpisodicBasin` lane; +- `v3-envelope-auditor` sign-off. + +Until then no pair-coded self-code is persisted. + +## 7. Pre-registered gates (fill with measured numbers only) + +All on the §5 held-out protocol (train 10,000 / eval 2,543 KJV words). Every +guard below gets a disable run: red with the guard removed, green with it back. + +| gate | criterion | what fails it | +|---|---|---| +| **G1 fidelity** | best of R1/R2 has held-out ρ ≥ **0.774** (the 12-axis) | < 0.774 and ≥ 0.617 means PARTIAL: report it; the operator decides. < 0.617 (the 48-bit point) means KILL | +| G1 report | four separate rows, never merged: R3 (first byte only), beside the **48-bit point 0.617** it should approach; the **96-bit RQ point 0.786** as its own equal-budget baseline, measured as `train_codebook.py`'s `rq_fit` arm; the 12-axis 0.774; and recon MSE for each | — (R3 is the 48-bit point, not the RQ control) | +| **G2 needle** | with the same seeds and split, every word's `c₁` bytes equal its 48-bit PQ code byte for byte; R3's ρ is reported beside the 48-bit ρ | `c₁` is not the point code (R3 scores through `T_s` cosines, not full-vector L2, so its ρ is reported, not gated) | +| **G3 spread is load-bearing** | shuffling every word's `c₂` across words (keeping `c₁`) **lowers** R1/R2 ρ | if ρ does not drop, the second byte is decoration and the change is only a relabel | +| G3b diagonal variant | report ρ with the far-second-pole → `(c₁:c₁)` rule at 3 pre-set thresholds | report only | +| **G4 header orthogonality** | word similarity is bit-identical under a permutation of `WordId` routing and of `LexicalEvidence` counts | frequency or PoS leaking into meaning | +| **G5 diagonal by address** | `sim(a, a) == 1.0` for every code, and no `T_s` diagonal read occurs | a lookup answering a needle question | +| **G6 version gate** | all four loader rejections: the pair-codebook loader refuses `CAM96CB1` and the axis-codebook loader refuses `CAM96P01`; the pair-code loader refuses `CAM96WD1` and the axis-code loader refuses `CAM96PW1`. Also a `compile_fail` doctest showing the two code types do not mix | silent cross-reading. The code files matter most: both carry 12 bytes per word with incompatible meanings, and the type test cannot protect deserialized bytes | +| G7 basin | re-run the D-SRS-3 held-out gates (`basin.rs`) on pair codes | report only; the July negative is not re-litigated | +| G8 downstream | re-measure `tesseract-paperless::consistency`'s four recorded pair similarities and `ABSOLUTE_ENDORSE_THRESHOLD` | report, then re-pin; never defend the old number | + +## 8. Consumers that migrate (named in-tree) + +- `deepnsm-v2`: + - `space.rs`, `codebook.rs`, `lib.rs` (`Nsm` fields and `word_similarity`); + - `basin.rs`, whose `reconstruct → mean → encode` needs a definition of + `reconstruct` for a pair code: `C_s[c₁]` (the needle) or the segment + midpoint. Decided by G7; both reported; + - `examples/bible_wave.rs`, `examples/pop_readout.rs`, and the + `lexical.rs` test at `:566-571`. +- `lance-graph-contract`: `episodic_basin.rs` and `canonical_node.rs` (§6.3), + plus the codec move (§3.3). +- **Out of tree:** `tesseract-paperless/src/consistency.rs` and + `examples/graph_recovery_demo.rs` (tesseract-rs). They migrate after the + artifact lands. + +## 9. Deliverables + +| D-id | deliverable | gate | +|---|---|---| +| D-C96P-1 | analytic Fisher-z codec (`FamilyGamma` encode/decode, off-diagonal fit, table-as-cache) in `lance-graph-contract`; `bgz-tensor` consumes it | parity with `bgz-tensor`'s current output, byte for byte | +| D-C96P-2 | `Cam96Pair` + `Cam96PairSpace` (2-NN encode, R1/R2/R3 similarity, diagonal by address) | G2, G5 | +| D-C96P-3 | `CAM96P01`/`CAM96PW1` loaders + the version gate; `Cam96AxisSpace` rename | G6 | +| D-C96P-4 | Rust trainer `examples/train_cam96p.rs` + the held-out harness | G1, G3, G3b | +| D-C96P-5 | the artifact: produce it (§5 option a) and publish it as a new release | G1 PASS | +| D-C96P-6 | retire `SemanticSpace` from the meaning path (`Spo::pairs` stays an address, never a distance) | G4 | +| D-C96P-7 | `EpisodicBasin` read-mode marker | `v3-envelope-auditor` LAYOUT-GATED verdict | +| D-C96P-8 | consumer migration (§8), in-tree then tesseract-rs | G7, G8 | + +## 10. Non-goals + +- `lance-graph-contract::recipe_substrate::PairPalette` has the same + two-independent-axes shape (`recipe_substrate.rs:125-147`, "sum of the + per-axis squared-L2s"). That is a finding, not in scope; it is filed in + `ISSUES.md`. +- Minting the header classid (§4, OPEN). +- The 144-verb coarse basis (facet plan §3b). +- Vocabulary coverage: the KJV's 12,543 words, about 80% on modern English + and nearly none on German. A per-work lemma codebook is the separate + question the AUTO matcher raises. +- AUTO content cues in `tesseract-paperless`. They wait on this spec. + +## 11. Open points + +- **Rail order is SETTLED: nearest-first.** `c₁` is always byte 0, so byte 0 + of every rail is the 48-bit point code. G2's byte-for-byte check and R3's + `c₁`-only scoring both depend on that. A canonical `min:max` order would halve + the key space, but it can put `c₂` in byte 0. It is therefore not an open + alternative here. If it is ever proposed, it must change §3.1, G2 and R3 in + the same edit. +- Which of R1/R2 wins, and whether the L4 wording changes (§3.2). +- Where the header lives (§4). +- The embedding source for the artifact (§5). +- Whether `basin.rs` should become z-native (average rails in z-space) rather + than point-native. G7 reports both reconstruct choices; neither is assumed. diff --git a/.claude/plans/deepnsm-v2-cam96-pairwise-v2.md b/.claude/plans/deepnsm-v2-cam96-pairwise-v2.md new file mode 100644 index 000000000..2b813f270 --- /dev/null +++ b/.claude/plans/deepnsm-v2-cam96-pairwise-v2.md @@ -0,0 +1,247 @@ +# deepnsm-v2 Cam96 → 6 × pairwise distribution — spec (v2, council draft) + +> **Status:** SUPERSEDED by `deepnsm-v2-cam96-pairwise-v3.md` (ratified 2026-09-30); kept as the council's draft record. Was: DRAFT v2. This is the 5+3 council's consolidation of `-v1.md` and the +> five savants' findings (prior art, iron rules, code truth, cascade impact, +> different views). It is **not ratified**, and no code is authorized. +> **Supersedes** `deepnsm-v2-cam96-pairwise-v1.md` for everything below. v1 stays +> as the record. The change ledger (§12) names every delta and its source. +> **D-ids:** `D-C96P-0..8` (§9). D-C96P-0 is new. +> **Written against:** lance-graph `claude/brave-mayer-65y3cy` @ `81aa42c7` +> (on `main` `0d31c54f`). + +## 0. The one-sentence change + +Cam96 today is **12 independent axis codebooks**. Each rail's two bytes are +nearest centroids of two unrelated 8-d halves, and they are scored as 12 +separate squared-L2 terms. The target is **six rails, each a genuine pair** +whose value is a Fisher-z relation, not two unrelated indices. **Which pair** +is decided by a pre-registered measurement between three readings the +governing documents support (§3). Only one of them survives into code. + +## 1. Frozen decisions (cited; the council checked compliance and re-opened none) + +- **F1.** A word is `classid(4B) = norm(prefix, frequency, PoS)` · `payload(12B) = 6 × (FisherZ:FisherZ)`. Frequency is a header, never a distance axis. + Source: `deepnsm-morton-comma-facet-v1.md` §0, §2, §5. Measured: `E-DEEPNSM-FACET-BLIND-CONVERGENCE-1`. +- **F2.** One palette256 index is a needle. The pair carries the distribution, and its value is read from the Fisher-z k×k LUT. Self-similarity is 1.0 **by address**, never a lookup. Gamma is fitted on off-diagonals only. + Source: `entries/2026-08-26-e-palette256-is-a-needle-the-colon-is-the-distribution-1.md`. +- **F3.** L4 = `6 × (8:8)` palette256². The analytic Fisher-z codec is canon, and a materialized table is a cache of the formula. + Source: `le-contract.md:59`, `:169-186`. +- **F4.** Classid canon: no bit math on a composed classid. + Source: `sonnet-worker-guardrails.md` §1 rule 4. +- **F5.** I-LEGACY-API-FEATURE-GATED: no path silently reads the other version's bytes. +- **F6.** deepnsm-v2 is the inbound leg. + Source: `E-DEEPNSM-V2-IS-INBOUND-LEG-REASONING-LIVES-IN-LANCE-GRAPH-1`. +- **F7.** A rail's byte 0 is its needle (nearest centroid). Byte order is never canonicalized away from that. Settled in PR review; it applies to every reading below that has a needle byte. +- **F8.** Zero-copy law. + Source: `.claude/agents/zero-copy-warden.md`. +- **F9.** Python is lab-only; committed producers are Rust. No `cargo --all`. No model identifiers. +- **F10 (added).** A pair reading is **always selected by the ClassView, never by inspecting payload bytes**. + Source: `le-contract.md:122-140` (S1-8). +- **F11 (added).** Fisher-z wins a RANK/TAIL read and loses an INTERPOLATE/LEVEL read, measured 5× worse there. Which codebook axis a class uses is decided per class, by measurement. + Source: `entries/2026-08-11-e-the-byte-was-only-the-selector-the-pair-is-the-carrier-1.md:45-52` (S1-4). + +## 2. What ships today (every citation graded CODED by S3) + +- `pub type Cam96 = [u8; 12]` (`space.rs:163`). `Cam96Space` has 12 axes and asserts `len == 12` (`:181-196`). +- `encode` works per axis on its own 8-d chunk (`:230-251`). `distance` is `Σ` over 12 squared-L2 terms (`:257-272`). +- `rails()` (`:287-289`) is referenced only by its definition and one test (S3-1). +- The artifact format enforces 12 axes (`codebook.rs:12-14`, `:58`). The producer "split each 16-d subspace into a 256:256 pair" (`fidelity_48_vs_96.py:7`), i.e. 12×8-d PQ (`train_codebook.py:57`, `:77`). +- **Frequency reaches a distance path.** `SemanticSpace::similarity` scores words at their frequency-rank `(basin, identity)` address (`space.rs:74-80`, `vocab.rs:14-21`). That is the facet plan's `PF=Payload` defection. It is exported (`lib.rs:79`). +- **KJV held-out baselines** (`probes/README.md` §4, `codebook.rs:6-8`): + + | code | ρ | + |---|---| + | 48-bit point | 0.617 | + | 96-bit RQ point | 0.786 | + | 12-axis | 0.774 | + + The *general-vocab* probe's numbers (0.624 / 0.766, `space.rs:173-178`) are a different vocabulary and split. They are **not** the bar. This resolves S2-8's "two baselines". +- **The metric behind every baseline** is Spearman of `1 − cos` between **L2-normalized reconstructions**, against Jina cosine distance (`train_codebook.py:61-67`). Rust's `Cam96Space::distance` is un-normalized summed squared-L2, which is a different metric (S3-3). + +## 3. The contested reading, and how it is decided + +The governing documents support **three** readings of `6 × (FisherZ:FisherZ)`. +v1 committed to A without naming B's literal support or D's. The council found +both (S1-5, S1-6, S5-1, S5-2), so the choice is made by measurement (§7, G0). + +| | a rail is | pair value | source for the reading | byte 0 needle? | risk found | +|---|---|---|---|---|---| +| **A** | `(c₁ : c₂)`, the nearest and second-nearest centroid of ONE per-subspace codebook `C_s` | Fisher-z cell `T_s(c₁,c₂)`: the spread of the word's neighbourhood | needle entry: "the pair is `(a,b) → value`"; 08-11 entry: "the pair is a cell in the centroid tile" | yes: `c₁` is the 48-bit PQ code | c₂ may be near-deterministic given c₁, carrying ~2–3 bits (S5-3). Voronoi swaps (S5-6) | +| **B** | `(z_loc : z_spread)`, two quantized Fisher-z *values* per subspace | the two values themselves; L2 over them ≈ cosine | facet plan `:22-28`: "each subspace becomes a 2-D distributional coordinate (FisherZ:FisherZ) … the pair keeps spread, not just location" | **no** — no centroid index | loses direction: two opposite words can share `z_loc` (v1 §3.4) | +| **D** | `(a : b)`, a cell of a jointly trained 256×256 tile over the subspace (two coupled axes of one 16-d subspace) | the tile's Fisher-z cell distance between two words' cells | 08-11 entry "cell in the centroid tile"; `deepnsm-v3-convergence-v1.md:55-56` "the code and its distance-table dual" | **no** (byte 0 alone is one axis, not a point) | the shipped 12-axis code is the uncoupled version of D; coupling must beat 0.774 to justify itself | + +**Committed resolution:** +- **A is the working hypothesis.** It is the only reading that keeps a needle in byte 0 (F7) and makes the colon a relation (F2). B and D are measured, not dismissed. +- G0 (§7) runs all three against the same held-out harness **before any artifact or type is built**. +- If A fails G0's information pre-gate, the spec returns to Phase 0 with G0's numbers. It does not fall back silently. +- The interpretation of F1 is also **escalated to the operator** (§11 Q1): the facet plan's literal text leans to B. + +The rest of this spec is written for A. Everything in §5–§9 that depends on A is marked `[A]`. + +## 4. Shape A in detail `[A]` + +- **Codebook:** one `C_s` per subspace (6 × 16-d), k = 256. +- **Encode:** `c₁ = argmin`, `c₂ = second argmin` in the same `C_s`, written nearest-first (F7). +- **Relation table:** `T_s` = Fisher-z of centroid cosines, with gamma fit on off-diagonals (F2). A diagonal read `(a,a)` returns 1.0 **by address** and never touches `T_s`. That guard is new code, because `FisherZTable::lookup_*` has none (S3-6). +- **Candidate per-rail similarities** (the pick is made on a **validation** split, never on the eval set; S2-8): + + | id | per-rail similarity | + |---|---| + | R1 | `mean_z` of the 4 cross cells, symmetric under an `a₁↔a₂` swap | + | R2 | the needle cell weighted as much as the cross cells | + | R3 | `T(a₁,b₁)` only | + +- **Word similarity:** `tanh(mean_s z̄_s)`, via `contract::distance::mean_similarity_fisher` (`distance.rs:62-69`). +- **The (c₁:c₁) "no second pole" variant (v1 G3b):** report-only, at 3 pre-set thresholds. S5-7 flagged the discontinuity, so it is **never** the default. +- **Stated conflict:** le-contract L4 says "similarity = ONE table read"; R1/R2 read 3–4 cells. That amendment is **escalated** (§11 Q2), not made here. +- **Compose:** undefined for a pair code (z-addition does not compose cosines; `le-contract.md:178-180`). A non-goal (S5-9). + +## 5. The producer `[A, B, D arms]` + +- **The 96-d embeddings are not in the release.** `data/README.md:9-13`; `bible_vocab_emb96.npy` is absent (S3-9). + - **Option (a):** re-embed with an operator-supplied key passed through the environment. It never enters a file, commit or brief. + - **Option (b):** reconstruct from the old codes. Allowed only as a probe arm, never as the artifact. +- **Split parity (S3-9).** A Rust trainer cannot reproduce numpy's PCG64 `permutation`. The lab embedding step therefore writes the train/validation/eval **index file** beside the embeddings (data, not code). The Rust harness reads that file. This is the only way "same words as 0.774" holds. +- **k-means reuse (S1-10).** + - The harness is an example with an **ndarray dev-dependency**, reusing `ndarray::hpc::edge_codec::Codebook::train` (seeded Lloyd's, `edge_codec.rs:69`). + - It does not use `cam_pq::kmeans` (farthest-first, no seed; `cam_pq.rs:541`) and it is not another copy. + - deepnsm-v2 has no dev-dependencies today (`Cargo.toml:23-29`), so this adds the first one. +- **Metric parity (S3-3).** The harness computes the baselines' exact metric (normalized-reconstruction `1 − cos` Spearman) **and** the arm's own similarity. Both are reported; the gate uses the first. +- **The 48-bit reference (S3-10).** The harness trains an **independent** 6×16-d k-means-256 with a different seed, as the G2 comparand. Without it, "c₁ equals the 48-bit code" is true by construction. + +## 6. Format, types and the version gate `[A]` + +### 6.1 Artifacts +- **`CAM96P01` codebook**, laid out as: + - `u32` n_sub (6), `u32` dim (16), `u32` k; + - the centroids; + - 6 × `FamilyGamma` (48 B). +- **`CAM96PW1` codes** carry a **`u64` digest of the codebook blob** in the header (S2-5). The loader refuses a mismatch. + - OPEN: the digest function is chosen at D-C96P-3 from what the contract already exposes; that is not verified here. +- **Magics:** all four rejections — pair codebook ⟂ `CAM96CB1`, axis codebook ⟂ `CAM96P01`, pair codes ⟂ `CAM96WD1`, axis codes ⟂ `CAM96PW1`. + - Two of these already exist (`codebook.rs:43-45`, `:91-93`; S2-6). All four get disable runs. +- **The PW1 loader borrows:** it returns `&[[u8;12]]` over the blob, not a `Vec` (S2-9; the existing loader copies at `codebook.rs:99-105`). + +### 6.2 Types +- The new code is `Cam96Pair`. It has **no public field and no `From<[u8;12]>`**; it is constructible only via the pair encoder or loader (S2-7). +- **The old names stay un-deprecated.** v1 proposed renaming `Cam96Space` → `Cam96AxisSpace`. S4-7 showed that tesseract-rs builds against lance-graph's default branch with no pin (`rust.yml:35-38`, `Dockerfile:98`), so a rename or deprecation breaks it the day it merges. New types are added **beside** the old ones. Retiring the old names is its own proof-gated PR. + +### 6.3 The persisted 12 bytes (the one gate v1 left open) +- **The problem.** `BasinRow.self_code` is a raw `[u8;12]` (`episodic_basin.rs:92`). Its `from_le_bytes` is total (`:130-144`). The row is fully packed at 2+2+12+8+8 = 32 bytes (`:76`, `:120-127`). The newtype never reaches it (S2-3/4, S4-5). +- **Resolution.** The shape of `self_code` becomes a **ClassView-selected reading** (F10), modelled on `EdgeCodecFlavor` (`canonical_node.rs:805-819`): same bytes, per-class reading, no layout change. + - It is a new `ReadMode` axis, which trips the structural fuse at `canonical_node.rs:1629-1633` and touches 16 `ReadMode` literals plus `hotplug.rs` and `lance-graph-ogar` (S1-9, S4). + - **Zero value = the legacy axis reading.** + - It requires a `v3-envelope-auditor` LAYOUT-GATED verdict **before** D-C96P-7 is written. +- **EMPTY is unaffected.** `BasinRow::EMPTY` is judged on the whole row (`member_count = 0`), so an all-zero self-code in a real basin stays distinguishable (S3-7, S4-6). +- **Today's only producer.** `arigraph/episodic.rs:227` writes `[0;12]` (S3-7). No writer of a non-zero code exists, so "nothing pair-coded is persisted" currently holds by absence, not by a guard (S4-6). +- **Ordering rule** (§9): D-C96P-7 lands before D-C96P-8 may emit pair self-codes. + +## 7. Pre-registered gates + +Every guard gets a disable run: red with the guard removed, green with it back. The eval set is the held-out split of §5. The R1/R2 choice is made on validation. + +| gate | criterion | fails when | +|---|---|---| +| **G0 information pre-gate (new, runs first)** | For A: over the real code population, report per subspace (i) the entropy H(c₂ \| c₁) and (ii) the variance of `T_s(c₁,c₂)`. For B and D: their own held-out ρ on the same harness and metric. | A is **KILLED** (return to Phase 0 with the numbers) if H(c₂\|c₁) < 1 bit in 4 of 6 subspaces. The threshold is a **policy pin, labelled as such**. | +| **G1 fidelity** | the best of R1/R2, chosen on validation, has eval ρ ≥ **0.774** on the baselines' own metric | < 0.774 and ≥ 0.617 = PARTIAL (operator decides); < 0.617 = KILL | +| G1 report | separate rows: R1, R2, R3 beside the 48-bit 0.617; RQ 0.786; the 12-axis 0.774; B; D; recon MSE for each | — | +| **G2 needle** | c₁ from `C_s` agrees with the **independently trained** 48-bit reference on at least a reported fraction of words; R3's ρ is reported beside 0.617 | report-only. The byte-for-byte check is dropped because it was vacuous by construction (S3-10) | +| **G3 spread is load-bearing** | shuffling c₂ **only among words that share c₁** lowers R1/R2 ρ by more than a **word-blocked bootstrap noise floor** (hand-tuned block size, labelled) | no drop beyond the floor. The v1 full-shuffle null is dropped: it creates pairs 2-NN never produces, so it could not stay silent (S5-4, S2-8) | +| G3v Voronoi (new) | under a pre-set small embedding perturbation, report the c₁/c₂ swap rate and the c₂-only change rate | report only (S5-6) | +| **G4 header orthogonality** | word similarity is bit-identical under a permutation of `WordId` and of `LexicalEvidence` counts | frequency or PoS leaks in | +| **G5 diagonal by address** | `sim(a,a) == 1.0` with no `T_s` read on the diagonal | a lookup answers a needle question | +| **G6 version gate** | the four magic rejections, the PW1 digest mismatch refused, and a `compile_fail` doctest that the code types do not mix | silent cross-reading | +| G7 basin | D-SRS-3 gates on pair codes, **both** reconstruct choices (`C_s[c₁]`, segment midpoint). Averaging is over decoded points or z, **never over index bytes** (S2-2) | report only. F11 predicts that a LEVEL read may not favour Fisher-z | +| G8 downstream | re-measure `tesseract-paperless::consistency`'s `ABSOLUTE_ENDORSE_THRESHOLD` (0.5, `consistency.rs:289`) on the new scale | report, then re-pin. Its tests track the constant (`:783`, `:791`), so nothing fails on a scale change (S4-8). `LOW_CONFIDENCE_THRESHOLD` is LSTM-side and unaffected | + +**Scope of every verdict:** the KJV held-out vocabulary (2,543 words). No gate here says anything about other vocabularies or languages (S5-10). + +## 8. Consumers (S3-7 + S4 census) + +**In tree, mandatory.** In deepnsm-v2: +- `space.rs`, `codebook.rs`, `lib.rs:14`, `:29-35`, `:61`, `:79`, `:102-140` +- `basin.rs` (33 refs; gates take `&Cam96Space` at `:185`, `:224`, `:262`) +- `lexical.rs:492`, `:566-571`, `spo.rs:51` +- `examples/bible_wave.rs:30`, `:118-119`, `:461-494`, `:951-952` +- `examples/pop_readout.rs:84`, `:168-169`, `:279-280`, `:322`, `:404-417`, `:743` (these include a direct `Cam96` × `self_code` distance) +- `data/README.md`, `probes/README.md` §4 + +In `lance-graph-contract`: `episodic_basin.rs`, `canonical_node.rs:1062`, `:1078`, `:1235`, `:1351`, `:2653-2698`, `band_reading.rs:151`, `lib.rs:98-99`. Also `lance-graph/src/graph/arigraph/episodic.rs:215-233`, `:959`, and `.claude/v3/soa_layout/tenants.md` (the tenant-table row `EpisodicBasin`, D-ACR-6 rail). + +**Codec move.** +- `bgz-tensor/Cargo.toml:27` (the contract dependency goes from optional to required); +- `bgz-tensor/src/fisher_z.rs`, `src/lib.rs:69`, `:114` (it re-exports, so no call-site churn in `shared_palette.rs`, `hhtl_d.rs`, `morton_cascade/*`). + +**Out of tree, follow-up** (after D-C96P-5): +- tesseract-rs `consistency.rs:63`, `:245-289`, `:315-319`, `:826-830`; `examples/graph_recovery_demo.rs:61-62` (hard-coded asset names); +- `README.md:55`, `TOKEN-SEAM-ARCHITECTURE.md:383`, `:465`. + +paperless-rs pins deepnsm-v2 at git rev `abac911b` and is a documented dead copy, so it is **not** migrated. + +**Plans to annotate:** +- `self-reasoning-substrate-v1.md:141`, `:425`, `:456-460` +- `post-teardown-buildup-survey-v1.md:87`, `:141`, `:185`, `:219` +- `deepnsm-v2-lexical-evidence-consumer-v1.md`: the new release must republish an **identical** `bible_vocab.txt`. + +## 9. Deliverables and ordering + +| D-id | deliverable | gate | after | +|---|---|---|---| +| **D-C96P-0** | the G0 harness: all three arms, the metric-parity scorer, the split-index reader, the independent 48-bit reference | G0, G1 report | embeddings (§5) | +| D-C96P-1 | the analytic Fisher-z codec into `lance-graph-contract` (details below) | a **new golden-bytes parity test** vs bgz-tensor's current output; no arithmetic change, so the ρ≥0.999 example certification need not re-run | — | +| D-C96P-2 `[A]` | `Cam96Pair` + `Cam96PairSpace`: 2-NN encode, R1/R2/R3, diagonal by address | G2, G3, G5 | 0 (A survives), 1 | +| D-C96P-3 `[A]` | `CAM96P01`/`CAM96PW1` loaders, digest, four rejections, borrowing codes loader | G6 | 2 | +| D-C96P-4 | the trainer example (same harness as D-0) | G1 | 3 | +| D-C96P-5 | the artifact + release, with an identical `bible_vocab.txt` | G1 PASS | 4 | +| D-C96P-6 | retire `SemanticSpace` from the meaning path | G4 | — | +| D-C96P-7 | the `self_code` shape ReadMode axis | v3-envelope-auditor verdict | — | +| D-C96P-8 | consumer migration, in tree then tesseract-rs | G7, G8 | 5, **7** | + +D-C96P-1 in detail: +- **Moved:** `FamilyGamma` encode/decode/fit, table build, `cosine_f32`; about 100 lines, not v1's "~40" (S3-5). +- **Reused:** the contract's existing `atanh` clamp (`distance.rs:42-52`), so the formula is spelled once (S1-2). +- **Canon clamp:** ±0.9999, as bgz-tensor and the contract already agree. helix's ε = 1e-9 (`helix/src/fisher_z.rs:55-58`) is a separate spatial codec and out of scope (S1-3). +- **Stays in bgz-tensor:** `build_from_palette`, which has no callers (S4-3). +- **bgz-tensor** re-exports the moved items. + +## 10. Non-goals + +- `PairPalette` (`ISS-PAIRPALETTE-IS-TWO-AXES-NOT-A-PAIR`). +- The classid header mint (§11 Q3). +- The 144-verb basis. +- Vocabulary coverage and per-work lemma codebooks. +- AUTO content cues. +- A compose table for pair codes. +- Retiring the old Cam96 names. +- Migrating paperless-rs. + +## 11. Escalated to the operator (not decided by the council) + +- **Q1.** Which reading of `6 × (FisherZ:FisherZ)` did the facet plan intend: A, B or D (§3)? G0 measures all three, but the intent is yours. +- **Q2.** If R1/R2 win, may le-contract L4's "similarity = ONE table read" be amended? +- **Q3.** Where does the frequency/PoS header live, given the classid canon? +- **Q4.** The embedding source (§5 option a) needs a key you supply through the environment. + +## 12. Change ledger (v1 → v2) + +| # | change | source | +|---|---|---| +| 1 | §3 rewritten: the three readings, a measurement-decided choice, and escalation of F1's intent | S1-5, S1-6, S5-1, S5-2 | +| 2 | G0 information pre-gate added, runs first, can KILL A | S5-3, S5-5 | +| 3 | G3 null is within-c₁ with a word-blocked noise floor; the full-shuffle null is dropped | S5-4, S2-8 | +| 4 | G1 uses the baselines' own normalized `1−cos` metric; R1/R2 picked on validation | S3-3, S2-8 | +| 5 | G2 byte-for-byte check dropped as vacuous; an independent 48-bit reference was added | S3-10 | +| 6 | G3v Voronoi instability report added | S5-6 | +| 7 | §6.3 resolved as a ClassView-selected ReadMode axis (zero = legacy); envelope-auditor gate; ordering D-7 before D-8 | S2-3, S2-4, S1-8, S1-9, S4-5, S4-6 | +| 8 | PW1 carries a codebook digest | S2-5 | +| 9 | `Cam96Pair` has no public field or `From`; the PW1 loader borrows | S2-7, S2-9 | +| 10 | Old names kept un-deprecated (v1's rename dropped) | S4-7 | +| 11 | Codec move: ~100 lines, reuse the contract's atanh, canon clamp, `build_from_palette` stays, re-export, golden-bytes test | S1-2, S1-3, S3-5, S3-6, S4-2, S4-3 | +| 12 | Trainer: split-index file, reuse ndarray `edge_codec::Codebook::train` via dev-dependency | S3-9, S1-10 | +| 13 | F10 and F11 added as frozen decisions | S1-8, S1-4 | +| 14 | §8 consumer list completed (arigraph producer, pop_readout, contract refs, tenants.md, asset names, plans) | S3-7, S4-1, S4-8, S4-9 | +| 15 | Baseline disagreement resolved: KJV §4 numbers are the bar; general-vocab numbers labelled | S2-8 | +| 16 | G7 forbids averaging index bytes and reports both reconstruct choices; F11 cited | S2-2, S1-4 | +| 17 | Verdict scope pinned to the KJV vocabulary | S5-10 | +| 18 | Compose is a non-goal | S5-9 | +| — | **not adopted:** S4-10's worry that the codec move duplicates helix/jc Fisher-z. S1-2 showed FamilyGamma exists only in bgz-tensor, and helix is a different (spatial, f64, ε 1e-9) codec. Recorded, not deleted | S4-10 vs S1-2 | diff --git a/.claude/plans/deepnsm-v2-cam96-pairwise-v3.md b/.claude/plans/deepnsm-v2-cam96-pairwise-v3.md new file mode 100644 index 000000000..e931966fe --- /dev/null +++ b/.claude/plans/deepnsm-v2-cam96-pairwise-v3.md @@ -0,0 +1,346 @@ +# deepnsm-v2 Cam96 → 6 × pairwise distribution — spec (v3, RATIFIED) + +> **Status:** SUPERSEDED-IN-PART (2026-09-30) by `-v5.md` — §3 (reading), §6.3 (home), §7 decision table; D-ids re-minted `D-CPW-*`. Everything else stands. Was: RATIFIED v3 of the 5+3 council. +> - v1 was the proposal and v2 the council draft; both are kept as the record. Ledger in §13. +> - **Implementation is authorized only for D-C96P-0 (the measurement harness) and D-C96P-1 (the codec move).** Both run on data that can be produced in-tree. +> - Every other deliverable waits on G0/G1, which wait on the embeddings (§5, Q4). +> - The reading of F1 is resolved as the merged reading **M** (§3). The operator proposed it on 2026-09-30; confirmation is Q1. +> +> **D-ids:** `D-C96P-0..8`. +> **Written against:** lance-graph `claude/brave-mayer-65y3cy` @ `81aa42c7` (base `main` `0d31c54f`). + +## 0. The change in one paragraph + +Today, rail `r`'s two bytes quantize the two contiguous 8-d halves of one 16-d +slice independently (`space.rs:182`, `:287-289`; `train_codebook.py:22-24`), +and distance is 12 separate squared-L2 terms (`space.rs:257-272`). Neither byte +refers to the other. + +The target makes each rail one object: a **needle** plus **where the word sits +between that needle and one of its fixed neighbours**. Similarity is read +exactly from the per-subspace relation table. + +The competing readings A, B and D (v2 §3) are projections of this one object, +measured as its ablations. Losing arms are recorded as findings, never deleted. + +## 1. Frozen decisions + +- **F1.** A word is `classid(4B) = norm(prefix, frequency, PoS)` · `payload(12B) = 6 × (FisherZ:FisherZ)`, and frequency is a header, never a distance axis. + - Source: `deepnsm-morton-comma-facet-v1.md` §0, §2, §5. + - **The literal text is frozen. Its reading was contested (v2 §3) and is resolved here as M, pending Q1.** +- **F2.** One palette256 index is a needle. The pair carries the distribution through the Fisher-z k×k LUT. Self-similarity is 1.0 by address. Gamma is fitted on off-diagonals only. + - Source: `entries/2026-08-26-e-palette256-is-a-needle-…-1.md`. +- **F3.** L4 = `6 × (8:8)` palette256². The analytic Fisher-z codec is canon, and a materialized table is a cache. + - Source: `le-contract.md:59`, `:169-186`. +- **F4.** No bit math on a composed classid. +- **F5.** I-LEGACY-API-FEATURE-GATED: no path silently reads the other version's bytes. +- **F6.** deepnsm-v2 is the inbound leg. +- **F7 — DECISION.** Byte 0 of a rail is its needle, the nearest centroid. + - Basis: PR AdaWorldAPI/lance-graph#1303 review thread on v1 §11. G2 depends on it. + - Scope: every arm that has a needle byte. +- **F8.** Zero-copy law. +- **F9.** Python is lab-only; committed producers are Rust. No `cargo --all`. No model identifiers. +- **F10.** A pair reading is selected by the ClassView, never by inspecting payload bytes. + - Source: `le-contract.md:122-140`. +- **F11.** Fisher-z wins RANK/TAIL reads and loses INTERPOLATE/LEVEL reads (measured 5× worse). The axis is chosen per read, by measurement. + - Source: `entries/2026-08-11-e-the-byte-was-only-the-selector-…-1.md:45-52`, a storm-pressure probe; its transfer to word codes is itself tested by G5b. +- **F12 (added).** "Without materialization" holds only on transmitted-index content. A static position must be **stored**; it cannot be regenerated. + - Source: `E-PERTURBATION-CONVERGENCE-1` invariant 1 (`EPIPHANIES-ARCHIVE-2026-09-20.md:21855`); `E-3DGS-MU-HYDRATION-2`. + +## 2. What ships today + +The citations below were verified by the code-truth savant and the overclaim +reviewer. The README ρ values are recorded Python outputs, not code facts. + +- `pub type Cam96 = [u8;12]` (`space.rs:163`). `Cam96Space` has 12 axes (`:181-196`). +- Encoding is per-axis (`:230-251`). Distance is a sum of 12 squared-L2 terms (`:257-272`). +- `rails()` is a view used only at `:287` and a test (`:368`). +- The 12-axis artifact format: `codebook.rs:12-14`, `:58`. KJV producer: `train_codebook.py:57`, `:77`. +- The quote "each 16-d subspace split into a 256:256 pair" is the **general-vocab** probe (`fidelity_48_vs_96.py:7`). +- `SemanticSpace` scores at the frequency-rank address (`space.rs:74-80`, `vocab.rs:14-21`). + - It is an **exported API with no caller outside its own tests** (searched lance-graph/crates and tesseract-rs). + - It is a latent `PF=Payload` defection, not a live path. +- **KJV held-out reference figures** (`probes/README.md` §4, recorded outputs): + + | code | ρ | + |---|---| + | 48-bit | 0.617 | + | RQ | 0.786 | + | 12-axis | 0.774 | + + - They were measured on `bible_vocab_emb96.npy`, which is **absent**. + - The general-vocab 0.624 / 0.766 (`space.rs:173-178`) are a different vocabulary and split. +- **The baseline metric** is Spearman of `1 − cos` of L2-normalized reconstructions against the reference embedding's (Jina-v3, data provenance) cosine distance (`train_codebook.py:61-67`). + - Rust's `Cam96Space::distance` is a different metric. + +## 3. The reading: M, and A/B/D as its ablations + +**The object.** In subspace `s` there is one codebook `C_s` (256 centroids, 16-d) with norms `n_c = ‖C_s[c]‖` and a centroid-cosine table `T_s(c,c')`. A word's subvector `x` becomes: + +``` +byte 0 = a = argmin_c ‖x − C_s[c]‖ (needle; = the 48-bit PQ code by F7) +byte 1 = (j : 4 bits | t : 4 bits) + b = N_a[j] N_a = the 16 highest-T_s(a,c) centroids with c ≠ a, fixed once C_s is trained + (a is excluded: a self-pair has φ = 0 and the slerp weights divide by sin 0) + t ∈ {0..15}/15 position along the arc a→b, uniform in ANGLE (F11: a level read) + (j, t) chosen to minimize the angle between x and x̂(a, b, t) + byte 1 = 0 means "needle only, no second pole" (t = 0 ⇒ x̂ = u_a) +x̂ = slerp(u_a, u_b, t) · n̄ where u_c = C_s[c]/n_c, φ = arccos T_s(a,b), + w_a = sin((1−t)φ)/sin φ, w_b = sin(tφ)/sin φ, + and n̄ = (1−t)·n_a + t·n_b interpolates the norm +``` + +**Why this is the merge of the two operator readings.** +- The **resonance** reading gives `r_a = cos(x,u_a)` and `r_b = cos(x,u_b)`. +- The **segment** reading gives the fixed arc length `φ`. +- Then `t = θ_a/φ` exactly when `x` lies on the arc (`θ_a + θ_b = φ`). +- The triangle excess `ε = θ_a + θ_b − φ ≥ 0` is what the two poles leave unexplained. +- The "properties in between" are rendered deterministically from `(a, j, t)` and the fixed codebook. Which point the word is (`t`) is stored, per F12. + +**Similarity (one formula, every arm).** +- `x̂` is a combination of two unit centroids, so the exact reconstruction cosine needs no float vector. It reads the Gram blocks from `T_s` and the norms: + + ``` + dot_s(A,B) = Σ_{p∈{a₁,a₂}, q∈{b₁,b₂}} w_p w_q n̄_A n̄_B T_s(p,q) + cos(x̂_A, x̂_B) = Σ_s dot_s(A,B) / sqrt(Σ_s dot_s(A,A) · Σ_s dot_s(B,B)) + ``` + +- This is **exactly the baseline metric** (normalized-reconstruction cosine; §2), so no metric-parity gap exists. +- A shared centroid (`p = q`) contributes `T(p,p) = 1` by address (F2). That is the correct Gram entry, not a needle averaged into a z-mean, so R2's diagonal-mixing concern does not arise here. +- Fisher-z enters only as the storage of `T_s` (i8 + gamma). Its quantization loss is measured by G5b. + +**A, B and D as ablations of M** (each is a G0 arm): + +| arm | what is removed | what it is | source of the reading | +|---|---|---|---| +| M | — | needle + neighbour + position | the operator's 2026-09-30 merge | +| M−t | position (t = ½ fixed) | pole pair, no position | — | +| M−j | neighbour choice (j = 0, the nearest neighbour) | needle + position toward a fixed neighbour | — | +| A | position; the second pole stored as a full byte (2-NN of the word) | v1/v2's `(c₁:c₂)` | needle entry `(a,b)→value`; 08-11 entry `:13` ("a cell in the centroid tile"). The latter is a storm-probe source, a domain transfer | +| B | addresses | per subspace, quantized Fisher-z of `cos(x, anchor₁)`, `cos(x, anchor₂)`, anchors = the subspace's top-2 principal directions | facet plan `:25-27` ("2-D distributional coordinate (FisherZ:FisherZ)") | +| D | per-word position and neighbour | the 48-bit code scored through `T_s` (the code's distance-table dual) | `deepnsm-v3-convergence-v1.md:55-56` | + +- The v2 reading "D = a jointly trained 256×256 tile per word" is **not supported by its cited source** (R1-§3). It would also be a 65,536-cell address the canon never writes (R2-§3). It is dropped as a reading and recorded here. + +**Decision table (pre-registered).** Each rule is applied on **validation** (§5: choices are made on validation), with the noise floor from G3 computed on validation. Eval is report-only: the arm selected on validation is the one reported on eval, and no eval number changes the selection. +- M beats every arm → M ships. +- An ablation ties M (within the floor) → the removed component carries nothing. The **simpler** arm ships and M's extra field is dropped. +- A, B or D beats M (outside the floor) → return to Phase 0 with the numbers; the operator decides (Q5). +- Every arm below the in-harness 48-bit control → KILL the pair program, recorded as a finding. + +## 4. Codebook quantities + +Per subspace, `C_s` also carries: +- the norms `n_c` (256 f32); +- `T_s` as Fisher-z i8 + `FamilyGamma`, gamma fitted on off-diagonals; +- `N_a` (16 u8 per centroid). + +`N_a` is derived from `T_s` at load time by ranking only `c ≠ a`, so a self-pair can never be selected. It is never stored twice. + +Diagonal reads `T(p,p)` return 1.0 by address, and `T_s`'s diagonal is never consulted. That is new code: `FisherZTable::lookup_*` has no guard (`fisher_z.rs:158-172`). + +Compose: the analytic codec does not provide compose (`le-contract.md:178-180`: "the semiring COMPOSE keeps its table"). A compose table for pair codes is a non-goal. + +## 5. The producer and the harness (two separate things) + +**Embeddings.** `bible_vocab_emb96.npy` is not in the release (`data/README.md:9-13`). +- **Option (a):** re-embed with an operator-supplied key passed through the environment. The key never enters a file, commit, brief, CI log or command line, and is never echoed. +- **Option (b):** reconstruct from the old codes. Allowed in a probe only, never for the artifact. + +**D-C96P-0 — the measurement harness** (an example with an ndarray dev-dependency; deepnsm-v2 has none today, `Cargo.toml:23-29`): +- **In-harness controls, retrained on the same vectors and split:** the 12-axis PQ, the 48-bit PQ and the RQ point. This is R1's BLOCK fix: under option (a) the vectors differ from those behind the pinned figures, so the gate compares against controls trained on the same vectors. The pinned 0.617 / 0.786 / 0.774 are reported for reference only. +- **Arms:** M, M−t, M−j, A, B, D (§3). +- **One k-means for all arms:** `ndarray::hpc::edge_codec::Codebook::train` (seeded Lloyd's, `edge_codec.rs:69`), so arm differences are not trainer differences. It is f32 with SplitMix init, which is not the Python baseline's f64 numpy Lloyd. That is one more reason the in-harness controls are the bar. +- **Split:** train / validation / eval, from an index file written by the embedding step (data). Arm and formula choices are made on validation, and every gate is reported on eval. +- **B's anchors** are fitted on train. + +**D-C96P-4 — the trainer** is a separate example that produces only the winning arm's artifact. It carries no probe arms and no option-(b) path. + +## 6. Format, types and the version gate (for M; A-arm formats are harness-internal) + +### 6.1 Artifacts +- **`CAM96P01` codebook**, in this order: + 1. `u32` n_sub, `u32` dim, `u32` k; + 2. the centroids; + 3. the norms; + 4. 6 × `FamilyGamma`. + + The i8 `T_s` table is an optional cache section (F3). +- **`CAM96PW1` codes** carry a `u64` digest of the codebook blob, and the loader refuses a mismatch. The digest function is chosen at D-C96P-3. +- **All four magic rejections:** + - pair codebook ⟂ `CAM96CB1` + - axis codebook ⟂ `CAM96P01` + - pair codes ⟂ `CAM96WD1` + - axis codes ⟂ `CAM96PW1` + + The existing loaders already refuse foreign magics (`codebook.rs:43-45`, `:91-93`). All four get disable runs. + +### 6.2 Types +- `Cam96Pair` is a newtype over `[u8;12]` with no public field and no `From<[u8;12]>`. +- **The PW1 loader never hands out raw arrays.** R1's BLOCK: `pub type Cam96 = [u8;12]` is an alias, so a `&[[u8;12]]` would flow straight into `Cam96Space::distance`. + - It returns a borrowing view `Cam96PairCodes<'a>` over the blob. + - `get(i) -> Cam96Pair` is a 12-byte `Copy` microcopy (data-flow rule 2). + - No slice of raw arrays is exposed. +- **The old names stay.** A non-breaking alias `pub type Cam96AxisSpace = Cam96Space;` is added for disambiguation (R2). + - Justification, downgraded per R1: tesseract-rs builds against lance-graph's default branch with no ref (`rust.yml:35-38`) and reaches `Cam96Space` through `load_cam96_space` (`consistency.rs:63`, `:315-319`). + - A signature change there would break it. Keeping the names avoids having to check that. + +### 6.3 The persisted 12 bytes +- **The row.** `BasinRow.self_code` is raw `[u8;12]` (`episodic_basin.rs:92`) with a total `from_le_bytes` (`:130-144`), in a packed 32-byte row (`:76`, `:120-127`). + - `EpisodicBasin` is `ValueTenant = 15`, a lane in a `NodeRow`'s 480-byte value slab (`canonical_node.rs:1045-1078`). + - So **the ClassView key is the owning row's key classid**, read via `classid_read_mode` (F10). Nothing in the payload selects the reading. +- **Resolution.** The code shape is selected per class. Zero means the legacy axis reading. Two candidate mechanisms: + - (i) a new `ValueSchema` variant on the existing `value_schema` axis; + - (ii) a new `ReadMode` axis. This trips the fuse at `canonical_node.rs:1629-1633` and touches 12 `ReadMode` struct literals (`:1483-1629`), `hotplug.rs:341` and `lance-graph-ogar/src/lib.rs:467`. + + The choice between them is **`v3-envelope-auditor`'s**, and it is made before D-C96P-7 is written. +- **EMPTY.** `is_empty` is `*self == Self::EMPTY`, i.e. all fields zero (`:114-116`). A real basin with an all-zero code has `member_count > 0` and is not empty. +- **Current producer.** The only producer found in lance-graph/crates writes `[0;12]` (`arigraph/episodic.rs:227`). Nothing pair-coded is persisted today, and that holds by absence; D-C96P-7 is ordered before D-C96P-8. + +## 7. Pre-registered gates + +Every guard gets a disable run: red with the guard removed, green with it back. Gates are reported on eval; choices are made on validation. + +| gate | criterion | fails / outcome | +|---|---|---| +| **G0 information** | Per subspace, report: (i) how often the word's true second-nearest centroid is in `N_a`; (ii) the entropy of `j` given `a`; (iii) the distribution of `t`; (iv) the distribution of the triangle excess `ε` | If (i) is < 0.9 in 4 of 6 subspaces, M's neighbour window is too small: G0 reports it, and window 32 (5 bits j, 3 bits t) is added as an arm. Thresholds are policy pins, labelled as such | +| **G1 fidelity** | The shipping arm's eval ρ ≥ the **in-harness 12-axis** ρ, on the baseline metric. **Precondition:** the in-harness 48-bit ρ ≤ the in-harness 12-axis ρ; if the retrained controls invert (48-bit above 12-axis), G1 is not evaluated and the harness itself is reported as suspect (an 8-bit-per-subspace code beating the 16-bit one is a training defect, not a result) | Between the in-harness 48-bit and 12-axis ρ = PARTIAL (operator). Below the 48-bit = KILL. Precondition violated = HARNESS-SUSPECT, no verdict | +| G1 report | One row per arm (M, M−t, M−j, A, B, D) plus each in-harness control and the pinned reference figures, each with recon MSE | — | +| **G2 needle** | Unit gate: for every eval word, byte 0 == argmin over `C_s`, and (j, t) == the encoder's minimizer. Report: agreement of byte 0 with an **independently seeded** 48-bit PQ | The unit gate falsifies F7. Swapping the byte order fails it | +| **G3 each field carries information** | Each ablation's ρ gap to M exceeds a **word-blocked bootstrap noise floor** (hand-tuned block size, labelled). The full shuffle of byte 1 across words is kept **report-only** as a ceiling | No gap beyond the floor = that field carries nothing, and the decision table's tie rule applies. G0 is its anti-vacuity partner: it shows the fields vary, so a tie means "uninformative", not "no power" | +| G3v Voronoi | Under a pre-set small perturbation of eval vectors, report the change rate of byte 0, j and t | report only | +| **G4 no frequency in the code** | Structural: `encode` takes the vector and `C_s` only. Test: encoding the same vectors under a permuted `WordId` assignment gives identical codes per word | A code depends on routing. Embedding-side frequency influence is out of scope (measured ρ ≈ −0.07 in `E-CAM96-DISTRIBUTION-MEASURED-1`) | +| **G5 diagonal by address** | `sim(x,x) = 1.0`, and no diagonal read of `T_s` | a lookup answers a needle question | +| **G5b table parity** | ρ from the i8 Fisher-z `T_s` vs ρ from f32 centroid cosines, reported. Tests F11's transfer to this read | report, and a Fisher-z loss > 0.01 ρ is flagged. Threshold is a policy pin | +| **G6 version gate** | The four magic rejections, the digest mismatch refused, a `compile_fail` doctest that the code types do not mix, and no API returns `[u8;12]` from pair codes | silent cross-reading | +| G7 basin | D-SRS-3 gates on pair codes. Averaging is over decoded points only, never over code bytes | report. An unfavourable result keeps those classes on the legacy read mode (§6.3 zero value) | +| G8 downstream | Re-measure `consistency.rs`'s `ABSOLUTE_ENDORSE_THRESHOLD` (0.5, `:289`) on the new scale | report, then re-pin. Its tests track the constant ±0.05 (`:783`, `:791`) and will not catch a scale change. `LOW_CONFIDENCE_THRESHOLD` (`:245`) is LSTM-side and unaffected | + +**Scope.** Every verdict is scoped to the KJV held-out vocabulary. Nothing here speaks for other vocabularies or languages. + +## 8. Consumers + +**In tree, mandatory.** +- deepnsm-v2: `space.rs`; `codebook.rs`; `lib.rs:14`, `:29-35`, `:61`, `:79`, `:102-140`. +- deepnsm-v2 `basin.rs`: gates at `:186`, `:225`, `:263`. +- deepnsm-v2: `lexical.rs:492`, `:566-571`; `spo.rs:51`. +- deepnsm-v2 examples: `examples/bible_wave.rs` and `examples/pop_readout.rs`. The latter contains a direct `Cam96` × `self_code` distance. Line lists are from the code-truth savant and were not re-verified by R1. +- deepnsm-v2 docs: `data/README.md` and `probes/README.md` §4. +- The contract's `episodic_basin.rs`, `canonical_node.rs`, `band_reading.rs:151` and `lib.rs:98-99`. +- `arigraph/episodic.rs:215-233`, `:959`. +- `.claude/v3/soa_layout/tenants.md`, the tenant-table row `EpisodicBasin` (D-ACR-6 rail). + +**The codec move (D-C96P-1).** +- `bgz-tensor/Cargo.toml:27`: the contract dependency becomes required. +- Every caller uses the **module path** `bgz_tensor::fisher_z::…`: + - `shared_palette.rs:36`; + - `morton_cascade/{mod.rs:29, v3.rs:13, legacy.rs:15}`; + - `examples/probe_l5_fisherz_amortization.rs:29`, `examples/nnue_palette_cosine.rs:30`; + - `thinking-engine/examples/cascade_attention_probe.rs:29`. + + So **`fisher_z.rs` itself re-exports** the moved items. The crate-root re-export at `lib.rs:114` is not enough (R1). + +**Out of tree, follow-up.** +- tesseract-rs: + - `consistency.rs:63`, `:245-289`, `:315-319`, `:826-830`; + - `examples/graph_recovery_demo.rs:61-62` (hard-coded asset names); + - `README.md:55`; + - `TOKEN-SEAM-ARCHITECTURE.md:383`, `:465`. +- paperless-rs (git-rev pinned dead copy) is not migrated. + +**Plans to annotate.** +- `self-reasoning-substrate-v1.md`. +- `post-teardown-buildup-survey-v1.md`. +- `deepnsm-v2-lexical-evidence-consumer-v1.md`. The new release must republish an **identical** `bible_vocab.txt`. + +## 9. Deliverables, ordering and board hygiene + +| D-id | deliverable | gate | after | +|---|---|---|---| +| D-C96P-0 | the measurement harness (§5), producing G0/G1/G2-report/G3/G3v/G5b | G0, G1 report | embeddings | +| D-C96P-1 | the analytic Fisher-z codec into `lance-graph-contract` | a **new golden-bytes parity test** vs bgz-tensor's current output. No arithmetic change, so the ρ≥0.999 example certification need not re-run | — | +| D-C96P-2 | `Cam96Pair`, `Cam96PairSpace` (encoder, Gram similarity, diagonal by address, `N_a`) for the arm the decision table picks | G2, G3, G4, G5 | 0, 1 | +| D-C96P-3 | loaders, digest, four rejections, `Cam96PairCodes` view, `Cam96AxisSpace` alias | G6 | 2 | +| D-C96P-4 | the trainer (winning arm only) | G1 | 3 | +| D-C96P-5 | artifact + release, with an identical `bible_vocab.txt` | G1 PASS | 4 | +| D-C96P-6 | `SemanticSpace` documented as routing-addressed, not meaning. **Kept exported, no `#[deprecated]`**: no caller exists, and a deprecation would fail downstream `-D warnings` builds (S4-7's breakage test re-applied) | G4 | — | +| D-C96P-7 | the §6.3 per-class code-shape reading | `v3-envelope-auditor` verdict | — | +| D-C96P-8 | consumer migration, in tree then tesseract-rs | G7, G8 | 5, **7** | + +D-C96P-1 in detail: +- **Moved:** `FamilyGamma` encode/decode/fit, table build, `cosine_f32`. +- **atanh clamp:** today inline in `Distance::similarity_z` (`distance.rs:42-52`). It is factored into one contract function used by both. That is a contract change, and it is bit-equivalent (±0.9999). +- **helix's ε = 1e-9 f64** (`helix/src/fisher_z.rs:55-58`) is a separate spatial codec and out of scope. +- **`build_from_palette`** is an inherent method today (`fisher_z.rs:150`). It becomes a **free function** in bgz-tensor, because an inherent impl on a foreign type is E0116. It has no callers. + +**Board hygiene (R3 BLOCK fix), binding on every deliverable:** +- Each D-id lands with its board updates **in the same commit**: + - its `STATUS_BOARD` row flips; + - `LATEST_STATE` Contract Inventory is updated for D-C96P-1, -2 and -7; + - measured G0/G1 results go into an `entries/` file plus `python3 .claude/tools/entries_index.py --write`; + - a `PR_ARC_INVENTORY` entry is added after merge; + - `python3 .claude/tools/supersession_index.py > .claude/board/SUPERSESSION-INDEX.md` is run **last**. +- Generated files are regenerated, never hand-edited. Append-only rows are never rewritten. +- Sub-agents write only their own tag-file. The orchestrator is the sole writer of shared board files. + +## 10. Non-goals + +- `PairPalette` (`ISS-PAIRPALETTE-IS-TWO-AXES-NOT-A-PAIR`). +- The classid header mint (Q3). +- The 144-verb basis. +- Vocabulary coverage and per-work lemma codebooks. +- AUTO content cues. +- A compose table for pair codes. +- Retiring the old Cam96 names. +- Migrating paperless-rs. +- Embedding-side frequency effects. + +## 11. Findings kept regardless of outcome + +- The G0/G1 rows of every arm, including losers, are recorded in an `entries/` file. +- A KILL records the program's negative result, not a silence. + +## 12. Escalated to the operator + +- **Q1.** Is M the intended reading of `6 × (FisherZ:FisherZ)`? (It is your 2026-09-30 merge; confirmation is still asked.) +- **Q2.** M's similarity reads up to 4 cells per rail plus norms. May le-contract L4's "similarity = ONE table read" be amended? +- **Q3.** Where does the frequency/PoS header live, given the classid canon? +- **Q4.** The embedding key (§5 option a), supplied through the environment. +- **Q5.** If A, B or D beats M outside the noise floor, fork the spec to that reading, or hold? + +## 13. Change ledger + +### v2 → v3 + +| # | change | source | +|---|---|---| +| 1 | Reading resolved as the merge M; A/B/D recast as its ablations; decision table added; losers kept as findings (§11) | operator 2026-09-30; R2-§0, R2-§3, R2-§11 | +| 2 | Similarity is the exact Gram reconstruction cosine: it equals the baseline metric, uses the within-word cell, and makes diagonal mixing moot | operator merge; R2-§3/§4; S3-3 | +| 3 | G1's bar is the **in-harness** retrained 12-axis control; pinned figures are reference only | R1-§7 BLOCK | +| 4 | The PW1 loader returns a `Cam96PairCodes` view; no raw arrays | R1-§6 BLOCK, R2-§6 | +| 5 | Same-commit board-hygiene clause, generated-file rule, one-writer rule | R3-§9 BLOCK | +| 6 | G2 unit gate restored (falsifies F7); independent-seed report kept | R2-§7 | +| 7 | G3 is a component ablation with a noise floor; the full shuffle is kept report-only; G0 is its anti-vacuity partner | R2-§7 | +| 8 | G4 rewritten as a structural test (the v2 version was vacuous) | R2-§7 | +| 9 | G5b table-parity report (tests F11's transfer); F11 marked as a storm-probe source | R1-§3, R1-§4 | +| 10 | F1 marked as literal-frozen with a contested reading; F7 relabelled DECISION with its PR source | R2-§1, R1-§1 | +| 11 | F12 added (a static position must be stored) | operator question; `E-PERTURBATION-CONVERGENCE-1` | +| 12 | D as a "jointly trained tile" dropped as unsupported by its source; D kept as the table dual | R1-§3, R2-§3 | +| 13 | Harness (D-0) separated from the trainer (D-4) | R2-§9 | +| 14 | `Cam96AxisSpace` alias added; the breakage justification downgraded | R2-§12, R1-§6.2 | +| 15 | §6.3: the ClassView key is the owning NodeRow's classid (verified at `canonical_node.rs:1045-1078`); `ValueSchema` variant vs new axis goes to the envelope auditor; literal count corrected to 12+2; EMPTY semantics corrected; producer claim scoped to lance-graph/crates | R2-§6, R1-§6.3 | +| 16 | Codec move: `fisher_z.rs` re-exports at the module path; `build_from_palette` becomes a free function (E0116); the atanh clamp is factored out (a contract change); the "~100 lines" estimate removed | R1-§8, R1-§9 | +| 17 | D-C96P-6 keeps `SemanticSpace` exported, with no deprecation | R2-§9 | +| 18 | §2 wording: "independently quantized halves of one slice"; `SemanticSpace` has no live caller; the general-vocab quote is labelled; README figures are recorded outputs | R1-§0, R1-§2 | +| 19 | §5 absolutes softened ("cannot" / "only way"); words vs vectors made explicit | R1-§5 | +| 20 | The key must never reach a CI log, a command line or an echo | R3-§5 | +| 21 | "Jina" ruled exempt as data provenance (an embedding model, not an assistant identifier; CLAUDE.md's model registry uses it), written as "the reference embedding (Jina-v3)" | R3-§2 | +| 22 | Compose wording: "the analytic codec does not provide compose", not "undefined" | R1-§4 | +| 23 | Q5 added | R2-§11 | +| 24 | Basin gate line numbers corrected to `:186`, `:225`, `:263` | R1-§8 | +| 25 | Post-ratification review (#1303, CodeRabbit): `N_a` excludes `a` (a self-pair has φ = 0, so the slerp weights divide by sin 0); the decision table is applied on validation and eval is report-only (§5 already said so, §3 contradicted it); G1 gains the precondition 48-bit ρ ≤ 12-axis ρ, else HARNESS-SUSPECT and no verdict | review | +| — | **Not adopted:** R2's G7/G8 wording ("report-only yet gates D-8") is answered by the legacy-read-mode fallback, not by making them hard gates. Nothing measures a threshold for them yet, and a hard gate without a measured bar would be a policy pin posing as a finding | R2-§7 | + +### v1 → v2 + +See `deepnsm-v2-cam96-pairwise-v2.md` §12. diff --git a/.claude/plans/deepnsm-v2-cam96-pairwise-v4.md b/.claude/plans/deepnsm-v2-cam96-pairwise-v4.md new file mode 100644 index 000000000..b633638d2 --- /dev/null +++ b/.claude/plans/deepnsm-v2-cam96-pairwise-v4.md @@ -0,0 +1,256 @@ +# deepnsm-v2 Cam96 pairwise — v4: the L4 identity facet, its 2³ readings, and the COCA fixed points + +**Status:** SUPERSEDED (2026-09-30) by the ratified `-v5.md`; kept as the Phase-0 record. Was: PHASE-0 SPEC (council input). Supersedes `-v3.md` §3 (reading), §6.3 (home), §7 decision table. Everything in v3 not named in §9 below stands. +**Date:** 2026-09-30. **Council:** `/5plus3`, second invocation on D-C96P (deliberate re-invocation per the harness base case: v3 was ratified, then three operator rulings changed its premises). +**Panel:** default five (prior-art on Opus, the rest Sonnet); default three. + +## 0. Why v4 exists — three operator rulings after v3 + +1. *"I'd rather go Perturbationsfeld than violating the cosine replacement centroid materialisierung."* v3 §3 rendered `x̂ = slerp(u_a,u_b,t)·n̄` (a materialized point between centroids) and scored it with a cosine (sqrt, division, a Gram matrix built from atanh values). Both are struck. +2. *"The duality/triplicity runs the NARS decomposition rung ladder 2³ in CausalEdge64."* v3 treated the readings A/B/D as ablations of M with a decision table that drops a tied reading. A reading is not an arm. The readings are the `CausalMask` projections of one register; the rung ladder selects the mask. +3. *"6×2×8bit is part of the 512-byte SoA. The 6 [a,b] should represent the identity the other tenants chime in to."* v3 §6.3 homed the code in `EpisodicBasin.self_code` (a value tenant). The code is the **key facet** under `le-contract.md` §3 **L4**; Tekamolo and CausalWitness point at it. + +Plus the driver mandate: *"use the scientific value of the already calibrated COCA codebook where frequency, PoS and lemma tables are calibrated on billions of words … the fixed points to unhinge the world with a lever."* + +## 1. Frozen decisions (cite; the council may only file VIOLATES with file:line) + +| # | decision | source | +|---|---|---| +| F1 | The V3 atom is `classid(4) + 12-byte payload`; the 12 B is content-blind; the ClassView selects the reading; slot purity (no labels in the payload) | `E-V3-FACET-4-PLUS-12` (archive `:23735`), `le-contract.md` §1–§2 | +| F2 | **L4** = `6 × (8:8) palette256²`, CAM_PQ "digital": each byte pair indexes the 256×256 palette table; similarity = ONE table read. Grounding: *"the codebook is DeepNSM's 4096-word COCA codebook"* | `le-contract.md:59`; archive `:23738` | +| F3 | §3 is byte-axis by construction. Sub-byte carvings are LANE readings, never a §3 payload layout | `causal_witness.rs:13-26` (the G24N4 correction) | +| F4 | No cosine; Fisher-z is the normalized cheap LUT; distance is a table read, never a computed cosine | `hexagon-plasticity-v1.md:500-513` (2026-09-15 STORNO); `E-FISHERZ-CANONICAL-COSINE-REPLACEMENT-1` (archive `:22506`) | +| F5 | No float on reasoning paths; float only as derived decode | `cosine-census-CONSOLIDATED.md:33-36` | +| F6 | "Without materialization" = no global rendered-field cache; the per-class metric table is an ingredient, not the avoided cache (ledger invariant 2); a static position off the transmitted-index manifold re-materializes (invariant 1) | `E-PERTURBATION-CONVERGENCE-1` (archive `:21826-21875`) | +| F7 | `CausalMask` 2³: bit enables one SPO plane in distance; L1 Association = `SO`, L2 Intervention = `PO`, L3 Counterfactual = `SPO` | `causal-edge/src/pearl.rs:6-49` | +| F8 | Rung → Pearl level → mask: rungs 0–2 → `0b001` (O, hand-chosen convention), 3–5 → `0b011` (certified), 6–9 → `0b111` (certified); elevation only widens | `cognitive_shader.rs:221-250`; `driver.rs:685-723` | +| F9 | Compose = mask AND: only planes active in both survive | `causal-edge/src/edge.rs:692-694` | +| F10 | `CausalEdge64` layout: `S[0:7] P[8:15] O[16:23] f[24:31] c[32:39] mask[40:42] dir[43:45] infer[46:49]`; v2 reclaims 52–63; `#[repr(transparent)]` | `edge.rs:138-161` | +| F11 | Frequency-rank = ROUTING, ⟂ meaning (ρ ≈ −0.07 vs Jina); count-derived meaning is a coarse floor (8-genre ρ = +0.039 on random pairs) | `E-CAM96-DISTRIBUTION-MEASURED-1` (archive `:21063-21064`) | +| F12 | The SPO 2³ role mask is a homograph-collapse operator: 809/809 verb∩noun homographs collapse to distinct lemma centroids under P vs S/O | `E-SURFACE-FORM-COLLAPSE-1` (archive `:21796-21809`) | +| F13 | Relations are STORED edges; the substrate generalizes analogically; predicate-token arithmetic fails | archive `:21066` | +| F14 | Fisher-z wins rank reads, loses level reads (v3 F11) | v3 §1 | +| F15 | One copy: lance-graph owns the canonical bytes; a second authority is forbidden; borrows never cross a mailbox | `canonical_node.rs:1710-1728`; lgj `CLAUDE.md` one-copy law | +| F16 | Falsifiability rule: every filter an anti-vacuity test; every guard can-fire AND can-stay-silent; every threshold an inertness test | `CLAUDE.md` § falsifiability | +| F17 | Choices on validation, gates reported on eval; eval never changes a selection | v3 §5, §7 (post-review) | +| F18 | The embedding key reaches the harness by environment only; never a file, commit, brief, CI log, command line or echo | v3 ledger 20 | +| F19 | Lance family upstream; every other forked crate via the AdaWorldAPI fork | `CLAUDE.md` P0 | + +## 2. Input inventory (file:line, read this session) + +### 2.1 The register and its readings (contract) +- `facet.rs:77-135` — `FacetCascade = facet_classid(4) | 6×(8:8)`, 16 B, `#[repr(C, align(16))]`, const-asserted. +- `facet.rs:461-488` — `tier_bytes()` (the 12-unit ladder) and `cascade_byte(shape, group, level)`: *"the same lookup whether the ClassView reads the facet as 6×2, 4×3, or 3×4; the bytes never move."* +- `facet.rs:801-890` — `CascadeShape::{G6D2, G4D3, G3D4}`, `ROTATIONS`, `from_levels`, `index = group·D + level`. +- `facet_schema.rs:21-55` — `FacetSchema::{TierCascade=0, SpoTriplet=1, Pair48=2}`, resolved from `(facet_classid >> 24) & 0b11` ("provisional field position"). **Value 3 is free; L4 has no variant.** +- `awareness_facet.rs:21-65` — `SpoFacet`: six `Palette256Pair = (u8,u8)` rails, 3 SPO + 3 episodic-witness; "similarity between two pairs is one table read … never a float." +- `tekamolo_facet.rs:1-59` — the `G4D3` carving named Te/Ka/Mo/Lo, each lane `256:256:256`; EXPERIMENTAL, not in §3; straddles tier boundaries. +- `causal_witness.rs:28-53, 112-151, 199-219` — `CausalWitnessFacet` = 24 signed i4 loci over 12 B (a LANE reading); `Locus::{Temporal..Contradiction}` incl. `Antecedent = 7` ("relativPronomen → its antecedent"); sign = before/after; 0 = unbound. +- `canonical_node.rs:33-35` — `NodeGuid([u8;16])`; `:786` `pub type EdgeBlock = EdgeFacet`; `:862` `NodeRow`; `:1026` `Tekamolo = 13`, `:1078` `EpisodicBasin = 15`; `:1284-1354` `ValueSchema` (Full carries 13/14/15); `:1411-1423` `TailVariant::{V1,V2,V3}`; `:1454-1483` `ReadMode {tail_variant, value_schema, edge_codec}`; `:1691-1696` `classid_read_mode`. +- `tenants.md:56-58` — tenants 13 (Tekamolo, 16 B facet), 14 (CausalWitness, G24N4, EXPERIMENTAL), 15 (EpisodicBasin, `self_code` 12 B). +- `le-contract.md:50-67` — the L1–L8 catalogue; byte accounting 6×2 = 4×3 = 3×4 = 2×6. + +### 2.2 The edge and the ladder +- `causal-edge/src/pearl.rs` (whole file) — `CausalMask`, `pearl_level()`, `simpsons_paradox_risk`. +- `causal-edge/src/edge.rs:8-134` — `InferenceType`, signed mantissa (`to_mantissa`/`from_mantissa`); `:182-242` `pack` (v2: temporal ignored); `:353-413` mask accessors, `matches_causal`; `:692-694` compose mask AND. +- `causal-edge/src/tables.rs:1-120` — `NarsTables`: 256×256 `PackedTruth` deduction + per-c-quantile revision; `w = c/(1−c)`, `c_rev = ws/(ws+1)` (`:80-84`). +- `cognitive_shader.rs:157-250` — `RungLevel` 0–9, `pearl_level`, `causal_mask_bits`; `:272-335` `RungElevator` (threshold 2, hand-tuned, labelled). +- `p64-bridge/src/lib.rs:45-89` — `edge_to_layer_mask` (causal bits → CAUSES/ENABLES/CONTRADICTS planes; inference → plane); `:105` `edges_to_layered_rows`; `:121-128` plane consts; `:383-429` `CognitiveShader::cascade` (per-plane sweep, `per_col_predicates`, `semiring.distance(query,target)`). + +### 2.3 The driver +- `driver.rs:1-23` — the seven stages; `:72-111` `ShaderDriver` fields (`planes`, `awareness`, `nars_tables: Option>`, `rung_elevator`); `:240-249` rung-widened layer mask; `:263-268` cascade; `:376-387` FreeEnergy from `(top_resonance, std_dev)`; `:454-470` gate; **`:472-497` edge emission: `s_palette = row % 256`, `p = 0`, `o_palette = (row/4) % 256`, `f = c = resonance`, `temporal = cycle_index`** — the edge carries no identity and no prior today. +- `grammar/free_energy.rs:26-35` — `FAILURE_CEILING 0.8`, `HOMEOSTASIS_FLOOR 0.2`, `EPIPHANY_MARGIN 0.05` ("calibrated empirically; adjust once Animal Farm benchmark runs report"); `:104-129` `compose(likelihood, kl) → total = (1−l)+kl`. +- `lib.rs:20-28` — the cycle fingerprint: cache key / retrieval key / replay key / cursor. + +### 2.4 The codec side +- `deepnsm-v2/src/space.rs:38` `AxisCodebook = Vec>`; `:163` `pub type Cam96 = [u8;12]`; `:181-203` `Cam96Space` (12 axes); `:230-251` `encode`; `:257-272` `distance` (Σ 12 squared-L2); `:14, :35-56, :85` `SemanticSpace` over `PairPalette`. +- `recipe_substrate.rs:88-147` — `PairPalette {basin, identity}`; distance = sum of two axis squared-L2s (`ISS-PAIRPALETTE-IS-TWO-AXES-NOT-A-PAIR`, `ISSUES.md:1-13`). +- `contract/distance.rs:20-69` — `Distance` trait, `similarity_z` (inline atanh clamp ±0.9999), `fisher_z_inverse`, `mean_similarity_fisher`; `:82-108` `[u64;256]` Hamming, `[u8;6]` L1. +- `bgz-tensor/src/fisher_z.rs` — `FamilyGamma`, `FisherZTable::lookup_i8`, no diagonal guard (v3 §4). +- `ndarray/src/hpc/edge_codec.rs:46-69` — `Codebook::train(data, n, dim, k, iters, seed)` (Lloyd's, deterministic, re-seeds empty clusters). +- `episodic_basin.rs:76-144` — `BasinRow.self_code: [u8;12]`, `from_le_bytes`; producer `arigraph/episodic.rs:208-227` writes `self_code: [0;12]` ("left zero"). + +### 2.5 The COCA fixed points +- `deepnsm/word_frequency/lemmas_5k.csv:1` — header `rank,lemma,PoS,freq,perMil,%caps,%allC,range,disp,blog,web,TVM,spok,fic,mag,news,acad,…PM`; row 1 `the … range 482995, disp 0.98`. +- `deepnsm/src/vocabulary.rs:18-152` — `VOCAB_SIZE 4096`; row index = COCA rank (`:139`); `pos_table`, `freq_table` per rank (`:85-88`); loads ONLY `rank,word,pos,freq` (`:97`); first-PoS-wins on homographs (`:131-135`). **`range`/`disp`/genre columns are loaded nowhere in `deepnsm` or `deepnsm-v2` `src/`** (grep 2026-09-30: no hit on `\bdisp\b` in a loader). +- `deepnsm/src/pos.rs:9-36` — 13 COCA tags, 4 bits. +- `deepnsm-v2/src/lexical.rs:1-42, 285-382, 398-444` — `LexicalEvidence` keeps every `(surface, PoS, lemma)` reading with exact `Option` counts; refuses conflicts; `WORD_FORMS_HEADER = lemRank,lemma,PoS,lemFreq,wordFreq,word`; API `readings / surface_count / surface_pos_count / lemma_pos_count / lemma_count`. +- `deepnsm-v2/src/vocab.rs:42-87` — `PaletteVocab::from_frequency_ranked`, first id wins, capacity 65 536. +- `deepnsm-v2/src/fsm.rs:38-62` — 7-state `Pos` incl. `Rel` (relativizer → the ±8 antecedent pointer feeder). +- `deepnsm/examples/gridlake_spo_ngrams.rs:1-14` — COCA n-grams are LICENSED, read from a local path, never committed. +- Prior measurements: `E-FREQ-IS-COSINE-REPLACEMENT-1` (8-genre Fisher-z distance ρ = 0.762 on 8 curated NSM pairs; `freq_is_cosine.rs`); `E-SURFACE-FORM-COLLAPSE-1` (`homograph_collapse.rs`); `E-CAM96-DISTRIBUTION-MEASURED-1` (F11, F13). + +## 3. The proposed resolution (committed) + +### 3.1 The identity facet: L4, two full bytes per subspace +- Per subspace `s ∈ 0..6` (16 d of the 96-d embedding): ONE codebook `C_s` (256 × 16-d, `Codebook::train`, deterministic seed), norms `n_c`, a Fisher-z table `T_s` (256×256 i8 + `FamilyGamma`; diagonal never consulted), and `N_a` = the 255 other centroids ranked by `T_s(a,·)`. +- The rail is **`[a, b]`**: `a` = nearest centroid (the needle, v3 F7), `b` = second-nearest centroid **as a full palette byte**. No `j:t` nibble: F3 forbids a sub-byte key payload; this is v3's arm **A**, and it is L4-conformant by construction. +- Position along the arc is **not stored in the key.** If a measured arm needs it (§5 G-T), it lives in a LANE reading (F3), decided then, never now. +- The facet: `FacetCascade { facet_classid, tiers = [(a_0,b_0) … (a_5,b_5)] }`. The **key** of a word/lemma row (`NodeGuid`, `TailVariant::V3`) carries it; `EpisodicBasin.self_code` is a *reference* to the basin row's key, not a second code (§3.5). +- Reading selection: **`FacetSchema::PalettePair = 3`** (the one free value of the provisional 2-bit field, `facet_schema.rs:48-54`). Selected by `facet_classid`, as F1 requires. The 2-bit field is then full — recorded as RISK-C1 for the cascade savant, not decided here. + +### 3.2 The eight readings: one `CausalEdge64` lens per subspace +Each subspace rail reads as an edge — a `Copy` microcopy at read time (data-flow rule 2), never stored: + +| plane | value | source | +|---|---|---| +| **O** | `a` (needle) | stored byte | +| **S** | `b` (second pole) | stored byte | +| **P** | `T_s(a,b)` quantized to u8 — the colon: the spread between the poles | table read, derived | +| `f,c` | §3.4 prior, revised | `NarsTables` | +| mask | selected by rung (F8) | `RungElevator::causal_mask_bits` | + +The eight `CausalMask` projections ARE the readings (F7): + +| mask | reading | v3 name | Pearl | +|---|---|---|---| +| `O` | needle only — the 48-bit point | **D** | Level 1 for rungs 0–2 (F8) | +| `SO` | the pole pair, no spread | **A** (≡ v3's M−t) | Association | +| `PO` | needle + spread, pole implicit | **M−j** | Level 2 | +| `SPO` | needle + pole + spread | **M** | Level 3 | +| `P` | spread alone | **B**'s level read | marginal | +| `S`, `SP`, `None` | free marginals | — | — | + +Nothing is ablated. A reading that fails its own gate (§5) is a finding about the bytes; the other readings stand. Compose is mask AND (F9): a needle-only edge composed with a full edge yields needle-only — a reading may coarsen, never invent. + +### 3.3 Similarity: table reads over the active planes, Fisher-z domain, no x̂ +For two rails `A=[a,b]`, `B=[a',b']` and mask `m`: +``` +d_O = z(a, a') one T_s read +d_S = z(b, b') one T_s read +d_P = |q(T_s(a,b)) − q(T_s(a',b'))| two reads, one u8 difference (a LEVEL read — F14 applies; gate G-P) +score_s(m) = Σ_{plane ∈ m} d_plane summed in the Fisher-z domain (F14) +score(A,B) = Σ_s score_s(m) six subspaces +``` +- No slerp, no sqrt, no division, no reconstruction. Every term is an i8/u8 table read or difference. F4/F5/F6 hold by construction. +- **SPO refinement arm (the perturbation-field render):** `d_SPO+ = d_O + d_S + z(a,b') + z(b,a')` — the cross reads, the two poles' field rendered onto each other's needle. Pre-registered as arm **M+** against `SPO` plane-sum; both are table reads. +- The encoder's merge identity (`t = θ_a/φ`, excess `ε`) survives **offline** as the encoder's diagnostic (G0 reports `ε`); decode never renders it. + +### 3.4 The COCA fixed points in the driver (the lever) +The row index is the COCA rank (`vocabulary.rs:139`); rank, PoS, lemma, `freq`, `range`, `disp` and 8 genre `PM` columns are a billion-word prior. They never enter the 12 identity bytes (v3 G4; F11: frequency is routing, not meaning). They land where NARS already lives: + +| lever | what changes | where | +|---|---|---| +| **L-1 prior truth** | Each identity row's prior `CausalEdge64` truth: `f = range / N_texts` (probability the word occurs in a random COCA text — a frequency of positive evidence), `c = w/(w+1)` with `w = ln(1 + freq)` (policy pin, labelled). Loaded once from `lemmas_5k.csv` columns `freq, range` (a loader that reads them does not exist — `§2.5`). | `nars_tables` prior; new loader in `deepnsm` beside `Vocabulary::load` | +| **L-2 edge emission carries identity** | `driver.rs:472-497` today packs `S = row%256, P = 0, O = (row/4)%256, f = c = resonance`. Change: `O = a` of the row's L4 rail for the plane selected by the row's PoS role (F12: S/O ← nominal, P ← verbal), `S = b`, `P = q(T_s(a,b))`; `f,c` = the L-1 prior REVISED with the hit's resonance through `NarsTables::revise`. | `driver.rs` stage [5] | +| **L-3 F's KL term is measured** | `FreeEnergy::compose(top_resonance, std_dev)` uses std-dev as the KL surrogate. Change: `kl` = divergence of the dispatch window's observed rank histogram from the COCA prior (the genre prior that minimises it, from the 8 `PM` columns). The three thresholds (0.8/0.2/0.05) stay as pins; G-F measures whether they now separate. | `driver.rs:379-387`; `free_energy.rs` gains a `kl_from_prior` helper, zero-dep | +| **L-4 lemma is the identity** | Identity rows are LEMMA rows (`lemRank`); surface forms route through `LexicalEvidence` readings → `(lemma, PoS)`; the `Antecedent` locus (`causal_witness.rs:131-132`) resolves to a lemma row, and coreference compares two key facets with §3.3. | `deepnsm-v2` routing; no contract change | + +Two algebras never merge (F13, v3 SPOFC): structure (the 12 identity bytes, the mask) vs strength (`f,c`). COCA feeds only the second. + +### 3.5 Home and one-copy +- The identity lives in the **key** (`NodeGuid`, `TailVariant::V3`, `FacetSchema::PalettePair`). +- `EpisodicBasin.self_code` (tenant 15) today persists 12 zero bytes. Under one-copy (F15) it becomes a **reference**: the basin row's own key carries its L4 identity; `self_code` is read through the key, and D-C96P-7 re-scopes from "shape reading of `self_code`" to "`self_code` ⇒ key reference or removal". `v3-envelope-auditor` decides the mechanism; this spec commits the direction. +- Tekamolo (tenant 13, `G4D3`) and CausalWitness (tenant 14, `24×i4`) are readings of their OWN 12 B, pointing at identity rows. They are not readings of the identity bytes. The `G4D3` rotation of an L4-coded register is structurally possible (`ROTATIONS`) and is asserted meaningless for an L4 class (G-ROT). + +### 3.6 Migration and gates on legacy +- `Cam96Space` (12 axes) stays as the legacy reading; `pub type Cam96AxisSpace = Cam96Space` (v3). The L4 pair space is a new type in `lance-graph-contract` (the reading is contract law; deepnsm-v2 ships the codebook artifact). Artifact magics `CAM96P01`/`CAM96PW1` and the digest gate (v3 §6) unchanged; the code-file view `Cam96PairCodes<'a>` unchanged. +- I-LEGACY-API-FEATURE-GATED: an L4 read of a 12-axis-coded register is refused by `FacetSchema` mismatch (magic + classid), never silently reinterpreted. + +## 4. Non-goals +- Phrases / n-grams as lemma-one-level-up — the data is licensed and local-only (`gridlake_spo_ngrams.rs:10-12`); a separate plan once an artifact exists. +- Registering Tekamolo in §3 — its own certification (jc pillar) per `tekamolo_facet.rs:40-42`. +- `PairPalette` rename/rebuild — `ISS-PAIRPALETTE-IS-TWO-AXES-NOT-A-PAIR` closes after D-C96P-1. +- The 96-subgenre palette — gitignored; the 8 genres are the floor (F11). +- tesseract-rs migration (D-C96P-8) — after D-7. +- Changing `FAILURE_CEILING`/`HOMEOSTASIS_FLOOR`/`EPIPHANY_MARGIN` — pins stay; G-F measures. + +## 5. Pre-registered gates (validation decides, eval reports — F17) + +| gate | criterion | can fire / can stay silent | +|---|---|---| +| **G-L4 structural** | The key payload is 12 palette bytes; no type in the pair path exposes a nibble; `compile_fail` doctest that `Cam96` and the pair rail do not mix; `FacetSchema::PalettePair` round-trips through `of_classid` | fires on a `(j:t)` type; silent on `[a,b]` | +| **G-D needle** | `O`-only score recovers the in-harness 48-bit control's ρ within the G3 floor | a shuffled `a` fires | +| **G-A pair** | `SO` ρ − `O` ρ > floor (the second pole carries rank information) | `b` replaced by a random `N_a` member fires | +| **G-P spread** | `P` alone is monotone with the true angle φ (Spearman on validation ≥ 0.9, policy pin) — the F14 level-read test | permuted `T_s` fires | +| **G-M full** | `SPO` ≥ every proper sub-mask on validation; `M+` vs `SPO` reported | — | +| **G-T position** | Report only: ρ of `SPO` + a 4-bit `t` LANE vs `SPO`. If the gain exceeds the floor, a lane reading is specified in a follow-up; the key is unchanged either way | — | +| **G-ROT** | The `G4D3` rotation of L4 bytes has ρ within the floor of zero against Jina (must be MEANINGLESS); a class reading L4 must not also read `G4D3` of the same bytes (structural) | a rotation that ranks fires — that would mean the bytes are not content-blind | +| **G-ε agreement** | Encoder's triangle excess `ε` distribution reported per subspace; `N_a` excludes `a` (v3 ledger 25) | — | +| **G1 fidelity** (v3, kept) | Shipping mask's eval ρ ≥ in-harness 12-axis ρ; precondition 48-bit ≤ 12-axis else HARNESS-SUSPECT | — | +| **G-F prior** | With L-3, F separates in-domain KJV text from word-shuffled text at the existing 0.2/0.8 pins (AUC ≥ 0.75, policy pin); the std-dev surrogate is the control | flat prior (uniform) must NOT separate = stays-silent test | +| **G-PoS** | L-2 plane assignment from PoS vs a PoS permutation: the 2³ projections' function-clustering purity (the 15 used_for groups, archive `:21066`) drops under permutation | — | +| **G-LEM** | Coreference agreement (`Antecedent` locus → row) at lemma identity vs surface identity on the `l9_loci_real_text` harness inputs; lemma ≥ surface | — | +| **G-FC** | Prior `c` from `ln(1+freq)` predicts revision magnitude on a held-out text (words with low prior `c` move more); a flat `c` prior must not | stays-silent half | +| **G-EDGE** | Emitted edges: `O == a` of the row's rail (not `row % 256`); `f ≠ c` in general; disable run restores `row % 256` and the equality test fails | — | +| G4 / G5 / G5b / G6 / G7 / G8 (v3) | unchanged | — | + +Every guard: red with it removed, green with it back. + +## 6. Per-savant question sets + +**S1 prior-art (Opus).** +1. Is an L4 `FacetSchema` selector already specified anywhere (plans, OGAR mint tables, `facet_schema.rs` history)? PRIOR-ART-AT or GAP. +2. Does any shipped code already read the key facet as `(needle, second-nearest)` pairs (e.g. `SpoFacet` consumers, `style_rails_at`)? CONFIRMS/GAP. +3. Is the "prior truth from COCA `range`/`freq`" idea already an E-id or a plan row? Name it or GAP. +4. Does `E-SURFACE-FORM-COLLAPSE-1`'s `homograph_collapse.rs` already implement L-2's role→plane map reusably? PRIOR-ART-AT. +5. Any prior ruling that the rung ladder must NOT select codec readings (i.e. that F8 is dispatch-only)? VIOLATES-with-evidence or CONFIRMS. +6. Duplicate E-ids for "one register, N readings" (#729, A1, A9) that §3.2 must cite instead of restating? + +**S2 iron rules.** +1. I-VSA-IDENTITIES: does §3.3 bundle content or compare identities? YIELDS/VIOLATES. +2. I-LEGACY-API-FEATURE-GATED: is every path that could read 12-axis bytes as L4 refused by a gate (§3.6)? Name the ungated path or YIELDS. +3. I-SUBSTRATE-MARKOV: does compose-as-mask-AND (F9) on these lenses touch the bundle algebra? YIELDS/NA. +4. I-NOISE-FLOOR-JIRAK: which §5 thresholds cite a bound and which are labelled pins? List any unlabelled. +5. One-copy (F15): is `self_code` as a key reference (§3.5) a borrow that crosses a mailbox? YIELDS/VIOLATES. +6. AP1–AP9: any anti-pattern in L-2's edge emission change (same fn name, different semantics under a feature)? + +**S3 code truth (general-purpose, Read-tool only).** +1. Every `file:line` in §2 — CODED / CLAIMED / ABSENT. Especially `facet_schema.rs:48-54` (the 2-bit field), `driver.rs:472-497`, `vocabulary.rs:139`, `edge.rs:692-694`. +2. Is `FacetSchema` consulted by any live reader today, or only defined? (Determines whether `PalettePair = 3` is behavioural.) +3. Does `RungElevator::causal_mask_bits` reach any distance call in the driver today (`causal_distance`)? CODED or CLAIMED. +4. Are `range`/`disp` truly loaded nowhere? Confirm the negative by opening `deepnsm/src/vocabulary.rs` and `deepnsm-v2/src/lexical.rs` loaders. +5. Does `Antecedent` resolve to a row anywhere (`wave.rs` / `witness_fabric.rs`), or only to an offset? +6. Does `SpoFacet` have any producer that writes `(a,b)` from a codebook, or is it label-only? + +**S4 cascade impact.** +1. Every file/test/doc/board row that changes if `FacetSchema::PalettePair = 3` lands (the 2-bit field is then full — who else wanted a slot?). +2. The blast radius of changing `driver.rs` stage [5] edge emission — which tests pin `row % 256`? +3. What breaks in `arigraph/episodic.rs` and `episodic_basin.rs` tests if `self_code` becomes a reference? +4. The mandatory vs follow-up split for the new COCA loader (`range`, `disp`, genre PM). +5. Does the `Cam96 → [u8;12]` alias (`space.rs:163`) leak into any consumer that would now compile against the pair type? +6. Board rows: which STATUS_BOARD D-ids re-scope (D-7), which are new. + +**S5 different views (no redesign).** +1. Strongest alternative to `O = a, S = b` (the L1 convention F8 marks hand-chosen) — name it and its second-order consequence; RISK only. +2. Is `P = q(T_s(a,b))` a level read that F14 predicts will fail G-P? What is the honest expectation? +3. Does L-3's KL-from-prior collide with F11 (frequency ⟂ meaning) — i.e. is register detection being mistaken for meaning? +4. Is `M+` (cross reads) a perturbation-field render or a Gram cosine in disguise? Evidence either way. +5. The second-order consequence of lemma-as-identity for named entities (OOV, `is_named_entity`, `vocabulary.rs:49-57`). + +## 7. Operator questions (open; not decided by the council) +- Q1 `O = a` vs `S = a` when the L1 probe runs (F8 convention). +- Q2 `self_code`: reference or removal. +- Q3 the embedding key (environment only, F18) and the 96-d embeddings (Q4 of v3, still blocking D-C96P-0). +- Q4 whether the `t` LANE (G-T) is wanted at all if the pair alone clears G-M. + +## 8. Board hygiene (same commit as ratification) +`INTEGRATION_PLANS.md` PREPEND; `STATUS_BOARD.md` v4 block (the §10 table: D-CPW-0 re-scoped arms, D-CPW-7 re-scoped, new D-CPW-9 COCA loader, D-CPW-10 driver levers); `AGENT_LOG.md` council entry; `entries/2026-09-30-*.md` for the L4-identity finding + `entries_index.py --write`; `SUPERSESSION-INDEX.md` regenerated LAST; v3 status line → SUPERSEDED-IN-PART (§3, §6.3, §7 decision table). + +## 10. Deliverables (D-ids) + +The `D-C96P-*` family used by v1–v3 does not match the workspace D-id pattern (`D-[A-Z]{2,}…`, `plan_dids.py`; the digit in `C96P` breaks it), so those rows were never counted by the supersession coverage column. v4 mints conformant ids and keeps the old names as aliases on the STATUS_BOARD rows; the numbering is preserved 1:1. + +| D-id | alias | scope (v4) | gates | status | +|---|---|---|---|---| +| D-CPW-0 | D-C96P-0 | the harness: eight `CausalMask` projections + `M+`, in-harness 12-axis / 48-bit / RQ controls, split file | G-D, G-A, G-P, G-M, G-T, G-ROT, G-ε, G1, G3, G5b | Blocked (embeddings, Q3) | +| D-CPW-1 | D-C96P-1 | Fisher-z codec into the contract (v3 §6 unchanged) | golden-bytes parity | Queued (authorized) | +| D-CPW-2 | D-C96P-2 | `FacetSchema::PalettePair = 3` + the L4 pair NEWTYPE in `lance-graph-contract`; `[a,b]` encode; reading selected by `facet_classid` | G-L4, G2, G5, G6 | Queued | +| D-CPW-3 | D-C96P-3 | `CAM96P01` / `CAM96PW1` loaders, digest gate, `Cam96PairCodes<'a>` view (v3 §6) | G6 | Blocked (on D-CPW-0) | +| D-CPW-4 | D-C96P-4 | trainer (separate from the harness) | G1 | Blocked (on D-CPW-0) | +| D-CPW-5 | D-C96P-5 | `Cam96AxisSpace` alias; legacy 12-axis reading kept, L4 read of 12-axis bytes refused | G4, G6 | Blocked (on D-CPW-2) | +| D-CPW-6 | D-C96P-6 | `SemanticSpace` documented routing-only, kept exported | G4 | Queued | +| D-CPW-7 | D-C96P-7 | `self_code` ⇒ key reference or removal (`v3-envelope-auditor` decides the mechanism) | field-isolation matrix, version gate | Queued | +| D-CPW-8 | D-C96P-8 | consumer migration, in tree then tesseract-rs | G7, G8 | Blocked (on D-CPW-5, D-CPW-7) | +| D-CPW-9 | — | COCA prior loader (`freq`, `range`; `disp` + genre PM follow-up) beside `Vocabulary::load`, reusing `freq_is_cosine.rs`'s column parsing | G-FC, rank-alignment test | Queued | +| D-CPW-10 | — | driver levers L-2 (edge emission carries identity, versioned) + L-3 (KL from prior) + L-4 (lemma routing) | G-EDGE, G-F, G-PoS, G-LEM | Blocked (on D-CPW-2, D-CPW-9) | + +## 9. Change ledger v3 → v4 (Phase 0) +| # | change | source | +|---|---|---| +| 1 | §3 reading: `[a,b]` two full bytes; `j:t` nibble struck (F3) | operator ruling 3, F3 | +| 2 | Similarity: table reads over active planes, no x̂, no cosine | operator ruling 1, F4–F6 | +| 3 | A/B/D/M: eight `CausalMask` projections; decision table struck; per-reading gates | operator ruling 2, F7–F9 | +| 4 | Home: key facet via `FacetSchema::PalettePair`; `self_code` → reference | operator ruling 3, F1, F15 | +| 5 | Driver levers L-1..L-4 with gates G-F/G-PoS/G-LEM/G-FC/G-EDGE | operator mandate; F11–F13 | +| 6 | G-ROT: content-blindness of L4 bytes under rotation made falsifiable | F1, F16 | diff --git a/.claude/plans/deepnsm-v2-cam96-pairwise-v5.md b/.claude/plans/deepnsm-v2-cam96-pairwise-v5.md new file mode 100644 index 000000000..342314643 --- /dev/null +++ b/.claude/plans/deepnsm-v2-cam96-pairwise-v5.md @@ -0,0 +1,452 @@ +# deepnsm-v2 Cam96 pairwise — v5 RATIFIED: the L4 identity facet, its readings, the COCA fixed points, three reference sets + +**Status:** RETRACTED-IN-PART (operator, 2026-09-30, same day) — see § ⊘ RETRACTION directly below; it overrides §3.1–3.3, the word-register half of §3.2, and the gates and D-ids it names. What it does not name stands. Was: RATIFIED by the second 5+3 council (2026-09-30). Supersedes `-v4.md` and `-v3.md` §3, §6.3, §7. Council record: `AGENT_LOG.md` 2026-09-30 (2). +**Deliverables:** §10 (`D-CPW-*`), read through the retraction. **§11 (added 2026-09-30):** the execution socket beneath the lexical substrate — D-CPW-15, spec only; **read through §11R** (same day, after #1305), which moves the socket from instruction families to an observation contract. + +## ⊘ RETRACTION (operator ruling, 2026-09-30) — the word is a cell of the spatial-perturbation LUT; nothing is sliced from an embedding + +The operator's statement, in order, verbatim where quoted: +- *"We don't want fuzzy embedding of 6 different readings of SPO."* +- *"I don't want any witness."* — *"I want the sentence's deterministic words."* +- *"No basin identity — superposition of 2 needles."* — *"Not rails."* — *"6 words each represented as LUT."* +- *"A word is spatial perturbation LUT"* — which is why the reading belongs to `cognitive-shader-driver`. + +**The design, and all of it:** +- One calibrated COCA `palette256` codebook. Deterministic. +- **A word is one pair `(a:b)`: two `palette256` needles superposed — its cell in the 256×256 LUT.** The LUT is the word's representation. The colon is not a split of anything; it is the superposition. +- **A facet's 12 bytes are six words of the sentence.** Six words, deterministic from the text. Not six readings of one word; not S/P/O roles with witness pairs; not rails. +- Relations between words are LUT reads between cells. This is the machine `cognitive-shader-driver` already is: the p64 `CognitiveShader` over the bgz17 `palette256` semiring (`semiring.distance(query, target)`), the perturbation field `M[addr@coarse]·P(phase)` rendered around the cell. A sentence is six cells; the shader reads their field. +- Meaning is in the ClassView. The bytes stay content-blind. + +**Struck by this ruling (append-only; the text below is kept as the record of the error):** +- §3.1 entirely: the 96-d embedding cut into six 16-d subspaces; per-subspace codebooks; `[a,b]` as nearest/second-nearest of an embedding slice; the retrain; the "home" argument built on that code. +- §3.2's word-register half: the "lens per subspace", the O/S/P plane assignment of `a`/`b`/spread, the "two registers" split. The 2³ mask stays what it always was in this workspace — Pearl over a triple — and is not re-derived here. +- §3.3 entirely (per-subspace sums, shared gamma across subspaces, `Z_SELF`, `M+`). +- Gates G-D, G-A, G-P, G-PO, G-M, G-T, G-ROT, G-UNIQ, G-CASC, G-ε, G1, G3, G3v, G5b as written (they measure the struck code). +- Deliverables D-CPW-0 (harness of the struck arms), D-CPW-3, D-CPW-4 (the retrain), D-CPW-12 (cascade wiring of the struck lens): **WITHDRAWN**. D-CPW-2 re-scoped: the pair type is the word-cell `(a:b)` over the one COCA codebook, with `ReferenceSet`; nothing about subspaces. D-CPW-10 re-scoped: the driver reads a sentence as six cells; its edges carry cells, not "subspace-0 needles". +- The v3/v4 measurements (0.617 / 0.774 / 0.786 on KJV) were measurements of the struck code and are not evidence about this design. + +**Kept (independent of the struck half):** F23 three references and `ReferenceSet` (§3.7, D-CPW-14, G-REF); `self_code` as the basin's own identity (F25, D-CPW-7, G-SELF); the COCA prior `` (L-1, D-CPW-9, G-FC); register-F (L-3, D-CPW-13, G-F); lemma routing (L-4, D-CPW-11); the Fisher-z LUT move into the contract (D-CPW-1) — which gains weight, since the LUT IS the representation. + +**⊘ CORRECTION 2 (operator, 2026-09-30, after the artifact check) — `[a,b]` identifies a WORD, not two poles.** The artifact check found that nothing shipped, released, or in Tigris assigns a word two needles: the COCA CAM-PQ gives six (one per subspace), bgz17/bgz-tensor `nearest`/`assign` give one, and "(nearest : second-nearest)" originated in v1 with no source. The operator then pinned the unit of representation: + +> *Six lexical slots, not six embedding subspaces. Each slot's two-byte address resolves through an immutable, versioned lexical codebook; the driver supplies the selected relational reading.* + +- **The 96-bit payload is `[a_0,b_0] [a_1,b_1] … [a_5,b_5]`: six word slots.** Each pair is a 16-bit lexical address — 65,536 addressable cells, enough for either vocabulary — resolving to a word's **declared reading** (lemma + PoS) in an immutable, versioned lexical codebook (`ReferenceSet`, F23). The split into two bytes carries no semantics of its own. +- **Two interpretations were being silently conflated and are now separated:** (1) `[a,b]` identifies a word (unique identity, exact, this spec); (2) `[a,b]` identifies two lexical poles whose cell is a relation (not automatically a word identity). v4/v5's "nearest and second-nearest centroid" substituted (2) for (1). **(1) is the representation.** (2) is not a unit of identity anywhere in this spec. +- **Relations are the driver's job, not the bytes'.** The cognitive shader driver supplies the selected relational reading between two resolved words, calibrated by Fisher-z through the LUT. Fisher-z governs relation values; it never makes word identity fuzzy. +- **Embeddings are an optional comparison instrument, never the runtime intermediary and never what the bytes mean.** Embedding reconstruction is NOT an acceptance criterion (it would force the representation to imitate a different architecture). Every fidelity gate against Jina reconstructions is struck as a criterion; it may remain as a comparison report. +- **The first regression (G-LEX, replaces every fidelity gate as the first gate):** exact lexical address resolution — every declared vocabulary entry of a `ReferenceSet` resolves to exactly its declared reading; lemma/PoS distinctions survive round-trip; identical ordinals from different codebooks never cross-read (a resolution against the wrong `ReferenceSet` is refused, never a different word). This is G-REF's first half made concrete; D-CPW-14's correspondence artifact is its fixture. +- D-CPW-2 re-scoped: the slot type is a 16-bit lexical address with its `ReferenceSet`, resolved through the versioned codebook — no centroids, no nearest-anything. + +Closeout: `STATUS: corrected | OUTCOME: [a,b] = a word's 16-bit lexical address in a versioned codebook; six word slots per facet; relations driver-supplied, Fisher-z calibrated; embeddings optional comparison only | OPEN: which relational reading(s) the driver selects between two resolved words (ClassView), and the LUT that carries them — not decided here`. + +**⊘ CORRECTION 3 (operator, 2026-09-30) — `CausalEdge64` IS the ALU register.** One `u64`; the NARS truth, Pearl 2³ mask and inference operations run on it directly (`causal-edge/src/edge.rs:1-3`: *"One u64. One register. One read."*). It is not a reference, not a lens over something else, not a record in a store, and not a container for one word's bytes. "Baton" in older docs is this same register as it passes from one cycle into the next (operator, same day). Struck from this document wherever it says otherwise: §3.2's "a `CausalEdge64` lens per subspace" and its O/S/P plane table over a word's bytes; §3.4 L-2's "the driver's emitted `CausalEdge64` is a TRIPLE edge … S/P/O = the parsed words' subspace-0 needles"; and this session's chat framings of S/P/O as "register references" or of packing one word's `[a,b]` into S and O. The six word slots are the facet's stored identity; the register is where reasoning happens. + +## 0. The rulings this version records + +1. *No materialized point, no cosine* → similarity is Fisher-z table reads (§3.3). +2. *The duality/triplicity runs the NARS 2³ rung ladder in `CausalEdge64`* → the readings are `CausalMask` projections of one register, an escalation cascade (§3.2). +3. *6×2×8bit is part of the 512-byte SoA; the 6 [a,b] are the identity the other tenants chime in to* → the identity code is a content-blind facet of the row (§3.1). +4. *Use the calibrated COCA codebook — frequency, PoS and lemma tables on billions of words — as the fixed points* → §3.4. +5. *Three reference sets, kept distinct; correspondence preserved explicitly; an ordinal is never reused across references* → F23, §3.7, G-REF. + +## 1. Frozen decisions + +| # | decision | source | +|---|---|---| +| F1 | V3 atom = `classid(4) + 12 B`, content-blind; the ClassView selects the reading; slot purity; the `(8:8)` pair is polymorphic, classview-selected | `E-V3-FACET-4-PLUS-12` (archive `:23735-23738`); `le-contract.md` §1–2 | +| F2 | L4 = `6×(8:8) palette256²`; a plane's similarity is one table read; grounding = the COCA codebook. Under the `NeedlePair` reading a rail costs |mask| reads (§3.3) — the "one read" is per plane. | `le-contract.md:59` | +| F3 | Sub-byte carvings are lane readings, never a §3 payload layout | `causal_witness.rs:13-26` | +| F4 | No computed cosine; Fisher-z is the LUT; the table replaces the READ, not the semiring COMPOSE | `hexagon-plasticity-v1.md:500-513`; archive `:22506-22509` | +| F5 | No float on reasoning paths at read/dispatch time; offline table BUILD is float (`fisher_z.rs:200-219`) and that is the sanctioned derived side | `cosine-census-CONSOLIDATED.md:33-36` | +| F6 | "Without materialization" = no rendered-field cache; a per-class metric table is an ingredient | `E-PERTURBATION-CONVERGENCE-1` (archive `:21859`) | +| F7 | `CausalMask` 2³ over SPO planes; **Pearl Level 1 = `SO`**, Level 2 = `PO`, Level 3 = `SPO`; `SP` = confounder detection | `pearl.rs:6-49` | +| F8 | The driver's rung→mask convention: rungs 0–2 → `O` (**hand-chosen; NOT Pearl's Level 1**), 3–5 → `PO`, 6–9 → `SPO`; sustained BLOCK elevates, sustained FLOW relaxes to base. Certified only for the planner's triple planes; for the word register it is a hypothesis (§3.2). Reaches no distance call today. | `cognitive_shader.rs:221-250, 304-327`; `driver.rs:240-249, 691-693` | +| F9 | Compose = mask AND | `edge.rs:692-694` | +| F10 | `CausalEdge64` v2 layout (default): `S P O f c mask dir infer(i4) plasticity`, 53–63 reclaimed; `pack` (v1) drops `temporal`; doc block `:138-150` still shows v1 | `edge.rs:138-161, 186-242` | +| F11 | Frequency-rank = routing ⟂ meaning (ρ ≈ −0.07); count-derived meaning is a coarse floor | archive `:21063-21064` | +| F12 | The SPO role mask collapses homographs (809/809); S/O→nominal, P→verbal is a labelled simplification; adjectives fall outside | archive `:21796-21809` | +| F13 | Relations are stored edges; the substrate generalizes analogically | archive `:21066` | +| F14 | Fisher-z wins rank reads, loses level reads | v3 F11 | +| F15 | One copy; borrows never cross a mailbox; elsewhere takes an ADDRESS. **`NodeGuid` is the instance key, unique at mint (`debug_assert` in the default basin).** | `canonical_node.rs:1710-1728`; `CLAUDE.md` § CANON | +| F16 | Falsifiability: anti-vacuity, can-fire AND stay-silent, inertness | `CLAUDE.md` | +| F17 | Choices on validation; eval report-only | v3 | +| F18 | The embedding key is environment-only | v3 ledger 20 | +| F19 | Lance upstream; every other fork via AdaWorldAPI | `CLAUDE.md` P0 | +| F20 | The 8 masks are canonical contract constants with per-class election; the ladder is an escalation cascade, not 8 parallel views | `causal-rung-standing-wave-v1.md:39-42, 98-135`; `soa-32…:184, 217-224` | +| F21 | The nearest-vs-second gap is a pre-NARS match-strength signal, not a replacement for `` | `bindspace-columns-v1.md:133, 136-139` | +| F22 | L1 (`part_of:is_a`) ⟂ L4 (ρ 0.035) | archive `:21463-21469` | +| **F23** | **Three reference sets, distinct, versioned:** the 4,096-word codebook (compact English), the 20k academic COCA codebook (broader academic), the 5k lemma table (lemma, PoS, frequency evidence). A reading contract names (reference id, version, digest). Immutability makes an ordinal stable WITHIN a reference, never interchangeable across them. Correspondence is preserved explicitly — through the lemma, with ambiguity and missing entries as values — never assumed nested or ordinal-aligned. | operator 2026-09-30; measured §3.7 | +| F24 | The second facet (bytes 16..32) is a content-blind facet cascade the ClassView reads; it is forbidden to "know it is an edge block" | `CLAUDE.md` § CANON, `E-THE-SECOND-FACET-IS-NOT-AN-EDGE-BLOCK-1`; `canonical_node.rs:786` | +| F25 | `EpisodicBasin.self_code` is the basin's OWN identity at a strictly higher rung than its inputs — not a cached member, not a copy | `episodic_basin.rs:22-31, 91-92` | + +## 2. Input inventory (all ranges opened; graded by S3 and re-verified by R1) + +### 2.1 Register, key, facets +- `facet.rs:77-135` `FacetCascade`; `:461-488` `tier_bytes`/`cascade_byte`; `:801-890` `CascadeShape`. +- `canonical_node.rs:444-475` byte-identical `From` impls `NodeGuid ↔ FacetCascade` and `NodeGuid::facet()` — the key admits the facet reading; `:786` `pub type EdgeBlock = EdgeFacet` (the second facet); `:862` `NodeRow` = key(16) | second facet(16) | value(480); `:1026/:1044/:1078` tenants 13/14/15; `:1284-1354` `ValueSchema`; `:1411-1423` `TailVariant` (V3 = the L1 6-byte tail, `guid-v3-tail`); `:1454-1483` `ReadMode`; `:1691-1696` `classid_read_mode`. +- `hhtl.rs:386-396` HHTL routing reads KEY bytes 4..12 — untouched by this spec (the identity is not in the key). +- `facet_schema.rs:21-55` `FacetSchema` from `(facet_classid >> 24) & 0b11` — provisional; under canon-high those are the domain byte's low bits (OSINT `0x07` → 3); no `.schema()` caller exists. **Not used by this spec.** +- `awareness_facet.rs:21-65` `SpoFacet` (six `(basin, identity)` pairs). No codebook producer: `text_stream_to_soa.rs:243-255` is an EXAMPLE writing the rank split; `facet_fold.rs:59-77` relabels fields. +- `tekamolo_facet.rs:1-59`; `causal_witness.rs:13-26, 112-151, 199-219`; `witness_fabric.rs:498-501, 588-589` (`Antecedent` → OFFSET only); `wave.rs:50-53, 80-83` (no text→loci producer); `fsm.rs:130, :160`. +- `tenants.md:56-58`; `le-contract.md:50-67`. + +### 2.2 Edge and ladder +- `pearl.rs`; `edge.rs:8-134, 182-242, 353-413, 692-694`; `tables.rs:1-120` (revision indexed by c-quantile bucket midpoints `:78-79, :117-121`; deduction `c_out = f_out` `:69`). +- `cognitive_shader.rs:157-250, 268-335`; `causal_mask_bits` exercised only by tests `:774-864`, `doc_graph.rs:101, :116`, `driver.rs:691-693`; `causal_distance` once, `lance-graph-planner/src/cache/nars_engine.rs:135` (fixed `MASK_*` `:630`). +- `p64-bridge/src/lib.rs:45-89` (`edge_to_layer_mask`: bit2 → CONTRADICTS), `:105`, `:121-128` (predicate plane bit2 = SUPPORTS), `:383-429` (`cascade`: one `semiring.distance(query, target)` over ONE u8 palette, `k = semiring.k`). + +### 2.3 Driver +- `driver.rs:1-23, 72-111, 240-249, 263-268`; `:323-327` resonance = bgz17 single-palette cascade; `:334-341` `_revised_truth = tables.revise(…, c2 = 128)` computed and discarded; `:376-387` `FreeEnergy::compose(top_resonance, std_dev)`; `:454-470` gate; `:472-497` emission (`row%256 / 0 / (row/4)%256`, `f = c`, mask `predicates & 0x07` `:489`, `style_ord_to_inference` `:491`, `temporal` dropped by v2 `pack`). `BackingStore` exposure of a row's facets at stage [5]: NOT verified — D-CPW-10 precondition. +- Pinning tests: `tests/p64_target_identity_probe.rs:103-113`; `src/edge_v3_compare.rs:81-108` (hand mirror), `:114-129`; `w2_differential.rs:166-170`; pass-through `engine_bridge.rs:788, 990`, `grpc.rs:102`, `wire.rs:1008`. +- `grammar/free_energy.rs:26-35, 104-129` (f32 surface; pins 0.8/0.2/0.05 "calibrated empirically"). + +### 2.4 Codec +- `deepnsm-v2/src/space.rs:38, 163` (`Cam96 = [u8;12]` bare alias), `:181-203, 219-224, 230-251, 257-272, 287`; `recipe_substrate.rs:88-147`; `contract/distance.rs:20-69, 82-108`; `bgz-tensor/src/fisher_z.rs:28-33, 63-68, 126-133, 158-166, 199, 200-219` (per-table `FamilyGamma`; diagonal saturates to 127, which is also the code of the closest off-diagonal pair; build is float); `ndarray/src/hpc/edge_codec.rs:46-70` (no second-nearest or `T_s` builder); `episodic_basin.rs:22-31, 76-144, 155-207`; `arigraph/episodic.rs:208-227, 945-970`; `deepnsm-v2/src/basin.rs:46`. + +### 2.5 COCA fixed points and the three references +- `word_rank_lookup.csv` (5,050 rows; ranks ≤ 4096 → 3,559 distinct words); `vocabulary.rs:97-185` (`load` reads `word_rank_lookup.csv` AND `word_forms.csv`; idx = rank−1 `:139`; consecutive-only dedupe `:131-135`; never opens `lemmas_5k.csv`); `pos.rs:9-36`. +- `lemmas_5k.csv` (5,050 (lemma, PoS); 4,380 lemmas; `freq, perMil, range, disp`, 8 genres); `range`/`disp` read by no `src/` code; PM columns parsed by `freq_is_cosine.rs:51`. +- `academic_20k.csv` (20,845 rows; 18,559 distinct words; `ID, band, status, word, Pos, COCA-All, COCA-Acad, ratio, disp, range`). The Tigris artifact `lance-graph/codebooks/deepnsm-v2-academic-coca-v1/` = `MANIFEST.json` (entries 18,559 of 20,480 reserved; basins 73..79 empty; 2,286 duplicate surface forms) + the CSV (sha256 `1dfd5eda…` = the committed file) + `deepnsm_v2_academic_codebook.tsv` (`word_id, basin, slot, word, pos, coca_all, coca_acad, source_rank`) — **a `PaletteVocab` carve of the list, not a trained centroid codebook.** +- `deepnsm-v2/src/lexical.rs:1-42, 285-382, 398-487`; `vocab.rs:42-87`; `homograph_collapse.rs:37-51, 84-92, 259-263`; `deepnsm-morton-comma-facet-v1.md:149-162`; `gridlake_spo_ngrams.rs:10-12`. + +## 3. The resolution (ratified) + +### 3.1 The identity facet: L4 `[a,b]`, in the row's SECOND facet +- Per subspace `s ∈ 0..6` (16 d of the 96-d embedding): one codebook `C_s` (256 × 16-d, `Codebook::train`, deterministic seed), a Fisher-z table `T_s` (256×256 i8) under **ONE shared `FamilyGamma` for all six tables** (pin; per-table fit loss reported) so codes are commensurable when summed, and `N_a` = the other 255 centroids by `T_s(a,·)`. +- The rail is `[a, b]` = (nearest, second-nearest), **two full palette bytes**. No `j:t` nibble (F3). Position along the arc is not stored; G-T reports whether a LANE would earn it. +- **Codebook geometry changes:** 6 subspaces × 16 d × 256 centroids, a second-nearest encoder, a `T_s` builder — none exists. D-CPW-4 (ndarray fork, F19). +- **Home — decision (R1 BLOCK):** the code is NOT the instance key. `NodeGuid` stays the unique mint (F15) and HHTL routing (`hhtl.rs:386-396`) is untouched. The identity code lives in the row's **second facet** (bytes 16..32; F24), read as `NeedlePair` by classes that elect it; such a class has no in-row edge bytes (its edges live in `MaterializedEdges` / the planes — the per-class opt-out `CLAUDE.md` § CANON already provides). ⊘ v4's `TailVariant::V3` and draft v5's "the key IS the facet" are struck. Recorded alternative (Q6): a new 16-B `Identity` value tenant (RESERVE-DON'T-RECLAIM headroom exists; costs an additive lane). +- **Reading selection:** a ClassView-selected reading `PairReading::{RankSplit /* (basin, identity), F11 routing */, NeedlePair /* this spec */}` resolved through `classid → ClassView` (home of the field: Q5). Default for an unmapped class: `RankSplit` (the shipped convention). ⊘ `FacetSchema::PalettePair` withdrawn (§2.1). +- **Reference contract (F23):** every `NeedlePair` artifact and every ClassView naming it carries `ReferenceSet { id ∈ {COCA4096, COCA5K_LEMMA, COCA20K_ACAD}, version, sha256 }`. A code is meaningful only against its reference; mixing references is refused (G-REF). +- **Refusal:** a `NeedlePair` read requires the ClassView naming it AND the artifact digest AND a matching `ReferenceSet`; a rank-split, 12-axis, or other-reference register is refused, never reinterpreted. The pair type is a NEWTYPE (no `[u8;12]` enters the path). + +### 3.2 The readings: a `CausalEdge64` lens per subspace; an escalation cascade (PROPOSAL, D-CPW-12) +| plane | value | source | +|---|---|---| +| O | `a` (needle) | stored | +| S | `b` (second pole) | stored | +| P | `q(T_s(a,b))` — the pair's spread (tightness), u8 | table read, derived (F21: pre-NARS strength) | +| `f, c` | §3.4 prior, revised | `NarsTables` | +| mask | the rung's (F8, convention) | `RungElevator::causal_mask_bits` | + +| mask | geometry (§3.3) | v3 name | rung (F8) | +|---|---|---|---| +| `O` | needle | **D** (48-bit point) | 0–2 (convention; Pearl's L1 is `SO`) | +| `PO` | needle + tightness — **differs from `O`** | — | 3–5 | +| `SPO` | needle + pole + tightness = `SO + s_P` (`s_P` redundant given S; G-M measures whether it helps or hurts) | **A ≡ v3's M−t** | 6–9 | +| `SO` | pole pair | **A** | election | +| `P`, `S`, `SP`, `None` | marginals / confounder detection | — | election | + +- v3's **M** (needle + neighbour + `t`) and **M−j** carried `t`; with `t` out of the key they have no mask. The `t` leg survives as G-T (`SO + t-lane`, `M+ + t-lane` vs `SO`). v3's **B** (quantized Fisher-z coordinates to PCA anchors) is **REJECTED**: a coordinate, not a palette address (F2), and a level read (F14) — recorded here and in §9. +- **Status: PROPOSAL.** `causal_mask_bits` reaches no distance call (§2.2); the cascade `O → PO → SPO` under sustained BLOCK is a deliverable (D-CPW-12), not shipped behaviour. F8's rung→mask certification is for the planner's triple planes; for this register it is a hypothesis tested by G-CASC. +- Two registers, distinguished: the `SpoFacet` TRIPLE register maps mask bits to rails (S = rail 0, P = rail 1, O = rail 2; witness rails 3–5 as contrast — `causal-rung-standing-wave-v1`); this WORD register maps them to planes inside one rail. A third, the p64 predicate-plane byte, is what the driver's `predicates` carries (bit2 = SUPPORTS) and what `edge_to_layer_mask` inverts (bit2 = CONTRADICTS) — the disagreement is `ISS-CE64-EMIT-INVERSE-BIT2-DISAGREE`. The rung, Pearl and p64 masks are three vocabularies; nothing here unifies them. +- Direction: `O = a` kept (L2 drops the neighbour, not the word); G-A carries a swapped-byte control. Q1 stays open. +- Cite: `E-H268-REPLAYABLE-TILE-1`, `E-RECIPE-SUBSTRATE-WIRING-1`, `E-PROOF-IS-A-REGISTER-READING-1`, `E-PARTOF-ISA-vs-PALETTE256-1`, A2 `PearlRungFacet`. + +### 3.3 Similarity: table reads over the active planes, one shared scale +``` +s_O = z(a, a') one T_s read (similarity; i8 ≤ 126 off-diagonal) +s_S = z(b, b') one T_s read +s_P = 127 − |q(T_s(a,b)) − q(T_s(a',b'))| a similarity of spreads (u8 difference; a LEVEL read — F14; gate G-P) +sim_s(m) = Σ_{plane ∈ m} s_plane one shared gamma ⇒ one scale across the six subspaces +sim(A,B) = Σ_s sim_s(m) +``` +- No slerp, sqrt, division, reconstruction at read time; F4/F5/F6 hold at read time (the table build is float, offline — F5's derived side). +- **Diagonal by address:** `Z_SELF = 127` is reserved; off-diagonal codes clamp to `≤ 126` at build. An exact needle match therefore strictly beats its closest neighbour. `T_s(a,a)` is never read (its gamma is fitted on `i` and the F gate. + +| lever | commitment | where | +|---|---|---| +| **L-1 prior truth** | The prior edge of a `(lemma, PoS)` identity row asserts *"this reading is the identity of its surface form"*. **`f` = the reading's share among its surface form's readings** (`form_count(this) / surface_count(surface)` from `LexicalEvidence`; F12 made numeric; `f = 1` for an unambiguous form; unknown counts stay unknown, never 0). **`c = w/(w+1)`, `w = ln(1+freq) / ln(1+freq_max) · K`** (evidence amount; `K` a labelled pin). Quantized to u8 by the loader; no float at dispatch. ⊘ `range`/`disp` leave the truth (collinear; `disp` is evenness, not evidence). | new reader of `lemmas_5k.csv` (`freq`; genre PM reused from `freq_is_cosine.rs:51`) beside `Vocabulary::load`; `LexicalEvidence` for the share; rank-alignment test | +| **L-2 edges carry identity (triple register)** | The driver's emitted `CausalEdge64` is a TRIPLE edge: `S/P/O` = the parsed subject/predicate/object words' **subspace-0 needles** `a_0` (the FSM assigns roles — F12; embedding subspaces are NOT roles, so no PoS→subspace map exists or is claimed). The p64 semiring for those planes is `T_0` (so the cascade's resonance and §3.3's needle plane agree). `` = the L-1 prior revised with the hit's resonance through `NarsTables::revise` (wiring the discarded `_revised_truth`; bucket resolution accepted). `pack_v2`. ClassView-gated (home per Q5): rows whose class does not name `NeedlePair` keep the legacy `row%256` path — G-EDGE's disable run. Tests `p64_target_identity_probe.rs:103-113` (storno) and `edge_v3_compare.rs:81-108` (lockstep) named. Precondition: `BackingStore` exposes the row's facets at stage [5]. | `driver.rs` stage [5] | +| **L-3 register F** | `kl` = divergence of the window's rank histogram from the best of the 8 genre priors — **register detection, routing not meaning (F11)**. It is the existing f32 `FreeEnergy` surface (a derived quantity, F5), with a quantized histogram. ClassView-gated like L-2; `std_dev` stays the default; pins unchanged; G-F measures. `FreeEnergy::kl_from_prior` is a carrier method. | `driver.rs:379-387`; `free_energy.rs` | +| **L-4 lemma routing** (D-CPW-11, Blocked) | Identity rows are `(lemma, PoS)`; surface forms route via `LexicalEvidence`; OOV / named entities have no identity row and stay unknown (never rank 0). `Antecedent` resolves to an offset only and no text→loci producer exists. | `deepnsm-v2` | + +Two algebras never merge (F13): structure (identity bytes, mask) vs strength (`f, c`). + +### 3.5 `self_code`, Tekamolo, CausalWitness +- `EpisodicBasin.self_code` is the basin's own higher-rung identity code (F25) — it stays, 12 B, same lane, no layout change. Its READING is per class (`NeedlePair` vs legacy 12-axis), computed at basin promotion from decoded points (v3 G7; offline, float allowed). **Gate (R3 BLOCK):** the `NeedlePair` reading applies only where the class names it; a non-zero legacy `self_code` under a `NeedlePair` class is refused; a paired legacy-nonzero test in the style of `pal8_v1_nonzero_temporal_is_blocked_by_version_gate`. D-CPW-7. +- Tekamolo (13) and CausalWitness (14) read their own 12 B and point at identity rows; G-ROT asserts the `G4D3` rotation of a `NeedlePair` register is meaningless. + +### 3.6 Legacy +`Cam96Space` (12 axes) stays; `Cam96AxisSpace` alias; pair NEWTYPE in the contract; deepnsm-v2 ships codebook artifacts; `CAM96P01`/`CAM96PW1` + digest + `Cam96PairCodes<'a>` unchanged (v3 §6), each header gaining `ReferenceSet`. + +### 3.7 The three reference sets (F23) — measured 2026-09-30 +| reference | rows | distinct keys | key | +|---|---|---|---| +| COCA4096 (`word_rank_lookup.csv`, ranks ≤ 4096) | 4,096 ranks | 3,559 words | rank (homographs share) | +| COCA5K_LEMMA (`lemmas_5k.csv`) | 5,050 | 4,380 lemmas / 5,050 (lemma, PoS) | (lemma, PoS) | +| COCA20K_ACAD (`academic_20k.csv`; Tigris carve v1) | 20,845 | 18,559 words / 20,842 (word, Pos) | `word_id` = admission order; basins 0..72 | + +Correspondence: 5k ∩ 20k = 4,895 (lemma, PoS) of 5,050; 4,264 words; **116 of the 5k lemmas are absent from the 20k**; 4096 ∩ 20k = 3,462 of 3,559; **only 3 of 4,264 shared words carry the same ordinal in the 5k and the 20k** — the sets are neither nested nor aligned. The 20k drops 2,286 (word, Pos) duplicates to one id; the 4096 shares ranks across homographs; the 5k keeps them distinct. +- **Artifact (D-CPW-14):** `lexical_correspondence.tsv` — one row per `(lemma, PoS)`: `id4096 | id5k | id20k | status ∈ {Exact, Ambiguous{n}, Missing}`, with the three `ReferenceSet` digests in its header. Generated, never hand-edited. +- **Regression invariant (G-REF):** any switch of reference preserves the declared correspondence and never reuses an ordinal as if unchanged: re-derive the table from the artifacts and diff; a code carrying reference X read against Y is refused (§3.1). + +## 4. Non-goals +Phrases (licensed n-grams); Tekamolo registration in §3; `PairPalette` rename; the 96-subgenre palette; tesseract-rs migration (after D-7); the three F pins; wiring `causal_mask_bits` into the planner's `causal_distance`; the bit-2 emit/inverse disagreement (ISSUES); a trained ACADEMIC centroid codebook (the Tigris artifact is a vocabulary carve — recorded, not built here). + +## 5. Pre-registered gates (validation decides, eval reports; every threshold a labelled hand-tuned pin; "floor" = v3 G3's word-blocked bootstrap floor) +| gate | criterion | fires / stays silent | +|---|---|---| +| G-L4 | pair NEWTYPE; no nibble type; `compile_fail` `Cam96` ↔ pair; a `NeedlePair` read without ClassView + digest + `ReferenceSet` is refused | fires on `(j:t)`, rank-split, wrong reference | +| G-REF | `lexical_correspondence.tsv` re-derived == declared; a cross-reference read is refused; the "3 of 4,264" ordinal fact reproduced | fires on a reused ordinal | +| G-UNIQ | structural: the key is unchanged by the identity facet; report: rows per identical L4 code (collision census) | — | +| G-D | `O` ρ ≥ in-harness 48-bit − floor; shuffled `a` drops below | shuffled `a` fires; identity permutation of the table stays silent | +| G-A | `SO` − `O` > floor; swapped-byte control; `b := random N_a` fires | — | +| G-P | `s_P` predicts the `O`-only rank error per word (Spearman ≤ −0.3 pin); permuted spread → |ρ| < floor | both halves | +| G-PO | `PO` ρ − `O` ρ reported; if within floor the rung-3 widening is decoration and D-CPW-12 records it | — | +| G-M | `SO` vs `SPO` vs `M+`; tie within floor ⇒ the simpler ships (`SO`) | — | +| G-T | report: `SO + t-lane`, `M+ + t-lane` vs `SO` | — | +| G-CASC | the cascade under sustained BLOCK yields a strictly wider candidate set at each rung on a fixed query set; never narrower (superset-monotone) | narrowing fires | +| G-ROT | `G4D3` rotation of `NeedlePair` bytes |ρ| < floor; structural no dual read | a ranking rotation fires | +| G0 / G-ε | v3 G0 (ii)–(iv) reported; encoder `ε`; `N_a` excludes `a` | — | +| G1 | shipping mask eval ρ ≥ in-harness 12-axis; precondition 48-bit ≤ 12-axis else HARNESS-SUSPECT | — | +| G3 / G3v | v3: field-carries-information vs floor; Voronoi change rate | — | +| G-F | with L-3, F separates KJV windows from `academic_20k`-register windows (AUC ≥ 0.75 pin); uniform prior must NOT separate; `std_dev` control | both halves | +| G-PoS | triple edges with FSM roles vs permuted roles: used_for purity drops ≥ 0.05 (pin) | — | +| G-FC | prior `c` predicts revision magnitude with `f` partialled out (partial Spearman ≤ −0.3 pin); permuted `c` → |ρ| < floor | both halves | +| G-EDGE | `NeedlePair` rows: emitted `S/P/O == a_0` of the parsed words; pinned rows: `the` (`f = 1`), `record` (`f < 1`); legacy rows keep `row%256` (disable run) | — | +| G-SELF | a non-zero legacy `self_code` under a `NeedlePair` class is refused (paired test) | — | +| G-LEM | (D-CPW-11) in-vocabulary antecedents only | — | +| G2 / G4 / G5 / G5b / G6 / G7 / G8 | v3, unchanged (G5b: one shared gamma, per-subspace fit loss reported) | — | + +## 6. Council record +Phase 1 (5): S1 prior-art (Opus, 10), S2 iron-rules (10, YIELDS-WITH-AP), S3 code-truth (Q1 table + 8), S4 cascade (8), S5 different-views (10). Phase 3 (3) on draft v5: R1 overclaim (1 BLOCK, 7 P1, 6 P2), R2 dilution-collapse (0 BLOCK, 5 P1, 5 P2), R3 firewall (1 BLOCK, 3 P1, 2 P2). Stricter verdict applied throughout. Banked: scratchpad `c96p4-council/{s1..s5,r1..r3,draft-v5,ref-correspondence}.md`. + +## 7. Operator questions (open) +- Q1 `O = a` vs `S = a` (F8 convention; the point-vs-pair gap below rung 3). +- Q2 (closed by F25): `self_code` stays; encoding of its reading per class → envelope-auditor. +- Q3 the 96-d embeddings (block D-CPW-0); the ACADEMIC reference has no embedding artifact at all. +- Q4 the `t` lane, if `SO` clears G-M. +- Q5 the `PairReading` field's home (`ReadMode` vs `ClassView`). +- Q6 second facet vs a new `Identity` tenant as the home (§3.1 commits the facet; the tenant is the recorded alternative). +- Q7 whether ACADEMIC gets its own trained codebook (a fourth artifact) or shares COCA4096's centroids with a correspondence-mapped vocabulary. + +## 8. Board hygiene (this commit) +`INTEGRATION_PLANS.md` PREPEND; `STATUS_BOARD.md` v5 block (§10); `AGENT_LOG.md` council entry; `entries/2026-09-30-three-reference-sets-are-not-ordinal-aligned.md` + `entries_index.py --write`; `ISSUES.md` (`ISS-CE64-EMIT-INVERSE-BIT2-DISAGREE`, `ISS-DID-PATTERN-EXCLUDED-D-C96P`); `TECH_DEBT.md` (adjective/adverb role gap; `causal_mask_bits` unwired; provisional `FacetSchema` field aliases the domain byte; six per-table gammas); v3/v4 status lines → SUPERSEDED-IN-PART / SUPERSEDED; EPIPHANIES: **no Eureka** (the ordinal finding is a measurement; the home decision is a decision); `SUPERSESSION-INDEX.md` regenerated LAST. + +## 9. Change ledger + +### draft v5 → ratified v5 (Phase 4, from the three) +| # | change | source | +|---|---|---| +| 1 | Home moved from the KEY to the second facet; key uniqueness and HHTL routing untouched; G-UNIQ | R1 BLOCK | +| 2 | `self_code` stays as the basin's own identity (F25); per-class reading + refusal + paired test (G-SELF) | R3 BLOCK, R2-7, R1 P2 | +| 3 | `P` back in the score as a spread similarity; `PO ≠ O`; `SPO = SO + s_P` stated; G-PO | R2-3, R1-1 | +| 4 | One shared gamma; `Z_SELF = 127` reserved, off-diagonal ≤ 126; build-is-float stated | R1-2 | +| 5 | L-1: `f` = reading share, `c` from `ln(1+freq)`; `range`/`disp` out; proposition stated; u8 at load | R1-3, R2-5, R3 | +| 6 | L-2 on the TRIPLE register (FSM roles → subspace-0 needles), semiring = `T_0`; PoS→subspace map disclaimed; ClassView-gated | R2-6, R1-4, R3 | +| 7 | §3.2 graded PROPOSAL with D-CPW-12 and G-CASC; F7/F8 Level-1 mismatch named | R1-1, R1-6, R2 §1 | +| 8 | B rejected with reason; M/M−j mapped to G-T; G0/G3v reinstated; G-M tie rule | R2-1/2, R2 §5 | +| 9 | G-FC re-specified (partial out `f`, permuted `c`); G-EDGE pinned rows | R1-5, R1 P2 | +| 10 | L-3: existing f32 surface labelled; gated; D-CPW-13 split from D-CPW-10 | R3 P1, R2 §10 | +| 11 | §8: TECH_DEBT, plan file, EPIPHANIES outcome; G2/G3 rows; alias column marked non-matching | R3 | +| 12 | F23 three references; §3.7 measurement; `ReferenceSet` in the contract; G-REF; D-CPW-14; Q7 | operator 2026-09-30 | +| — | **Not adopted:** R2's suggestion to keep `d_P` as a distance (it is a similarity of spreads now — same leg, right polarity). R1's HHTL note is moot once the key is untouched. | — | + +### v4 → draft v5 (Phase 2) — see scratchpad `draft-v5.md` §9; summary: `TailVariant` struck; `FacetSchema::PalettePair` withdrawn; newtype; `M+` relabelled; cascade wording; L-4 split; thresholds labelled; inventory corrections (S3). + +### v3 → v4 (Phase 0) — `-v4.md` §9. + +## 10. Deliverables +The `D-C96P-*` aliases (v1–v3) do not match the D-id pattern and are cited here only as history; tooling joins on `D-CPW-*`. + +| D-id | (alias) | scope | gates | status | +|---|---|---|---|---| +| D-CPW-0 | D-C96P-0 | harness: masks + `M+` + `t`-lane arms; in-harness 12-axis / 48-bit / RQ controls; split file | G-D, G-A, G-P, G-PO, G-M, G-T, G-ROT, G0, G-ε, G1, G3, G3v, G5b | Blocked (embeddings, Q3) | +| D-CPW-1 | D-C96P-1 | Fisher-z codec into the contract; shared gamma | golden-bytes parity | Queued (authorized) | +| D-CPW-2 | D-C96P-2 | pair NEWTYPE + `PairReading` + `ReferenceSet` + refusal | G-L4, G-REF, G-UNIQ, G2, G5, G6 | Queued (after Q5) | +| D-CPW-3 | D-C96P-3 | loaders, digest, view (v3 §6) + `ReferenceSet` header | G6 | Blocked (on D-0) | +| D-CPW-4 | D-C96P-4 | trainer: 6×16-d retrain, second-nearest encoder, `T_s` builder (ndarray fork) | G1 | Blocked (on D-0) | +| D-CPW-5 | D-C96P-5 | `Cam96AxisSpace` alias; legacy kept; refusal | G4, G6 | Blocked (on D-2) | +| D-CPW-6 | D-C96P-6 | `SemanticSpace` routing-only | G4 | Queued | +| D-CPW-7 | D-C96P-7 | `self_code` per-class reading + refusal + paired test | G-SELF, field-isolation matrix | Queued (envelope-auditor) | +| D-CPW-8 | D-C96P-8 | consumer migration | G7, G8 | Blocked (on D-5, D-7) | +| D-CPW-9 | — | COCA prior reader (`freq`; PM via `freq_is_cosine.rs`) + reading-share from `LexicalEvidence` + rank-alignment test | G-FC | Queued (collides with D-LXC-4) | +| D-CPW-10 | — | driver L-2 (triple edges, `T_0` semiring, `pack_v2`, revision wired, test storno) | G-EDGE, G-PoS | Blocked (on D-2, D-9; BackingStore precondition) | +| D-CPW-11 | — | L-4 lemma routing + `Antecedent` → row | G-LEM | Blocked (no text→loci producer) | +| D-CPW-12 | — | rung → mask → similarity wiring (the cascade) | G-CASC, G-PO | Blocked (on D-0, D-2) | +| D-CPW-13 | — | driver L-3 register F (`kl_from_prior`) | G-F | Blocked (on D-9) | +| D-CPW-14 | — | `lexical_correspondence.tsv` generator + `ReferenceSet` digests | G-REF | Queued | +| D-CPW-15 | — | the execution socket (§11): enforce the firewall + integer-only law on `lance-graph-mask-risc`, and pin the full-width `u64` register lane | G-SOCK-1..5 | Queued (spec only in #1303; next PR per §11.8) | + +## 11. The execution socket under the lexical substrate (D-CPW-15, 2026-09-30) + +**Scope:** a ruling, not an implementation. It names the narrow seam everything in §1–§10 eventually lowers into, so that the semantics above can keep evolving without an ABI revision below. No code lands with it. + +### 11.1 The socket already exists — it is `lance-graph-mask-risc`'s IR, not a new "Quack ABI" +Inspection (2026-09-30) found the proposed socket shipped under other names. **`lance-graph-quack` is the DuckDB-shaped SURFACE** (D-QCK-0..10): it builds programs and never evaluates one. The socket is the IR it lowers to: +- **Program:** `Program { ops: Vec, terminal: Terminal, scratch_slots }` — straight-line, one terminal. +- **Structural views (borrowed, never owned):** `Planes { n_rows, masks: &[&[u64]], lanes: &[LaneRef] }` with `LaneRef::{I32, U32, U64, Strided}`, plus `Foreign { planes, lanes }` for another table's row space. +- **Results:** `Value` + caller-owned `Out::{None, I32, I64, Mask}`; `ExecError` is shared by executor and oracle. +- **Guarantees already enforced:** a row-at-a-time `reference` oracle that never touches ndarray; the executor-vs-oracle differential; tiled == single-tile; zero allocation (`tests/no_alloc.rs`); `the_crate_names_no_isa`. + +The stack in this repo therefore reads, top to bottom: DuckDB-shaped `quack` / Java `lgj-abi` (`plan_eval`) / cognitive consumers → **mask-risc IR (the socket)** → `ndarray::simd` (the only backend layer: scalar, AVX2, AVX-512, NEON, WASM). DuckDB and Java sit ABOVE the socket as lowerings; Arrow is an input VIEW, not a backend. + +### 11.2 The invariant (authoritative) +> **The socket operates on borrowed masks, borrowed integer lanes and caller-owned sinks. It knows no COCA, lemma, PoS, `ReferenceSet`, Fisher-z, NARS, Pearl, EWA, JC/Jirak, HHTL, classid meaning, or `cognitive-shader-driver`. Every meaning is decided above it, by the lowering that builds the `Program`; semantic change above never requires an IR change below.** + +Evidence it already holds: mask-risc's only dependency is `ndarray` (facade features); it reaches ndarray only through `ndarray::simd`; its `src/` has zero hits for the cognitive terms above (NARS, Pearl, COCA, Fisher, lemma, `ReferenceSet`, EWA, Jirak, HHTL, shader, thinking, `CausalEdge`). It does name V3 **storage geometry** (26 hits: `facet`, `classid`, `ClassView`, `NodeRow`), almost all in doc comments that explain why a lane width or stride exists. It names that geometry once in an op: `Pred::MatchFacetStrided`, a content-blind 12-byte ternary match whose name records a layout, not a meaning. Geometry is allowed below the line; meaning is not. Whether that op should carry a geometry-neutral name is **OPEN** and out of scope. + +### 11.3 Primitive vocabulary after inspection — three families, not six verbs +| proposed verb | what the IR already has | verdict | +|---|---|---| +| MASK | `MaskOp::{Pred, And, Or, Xor, AndNot, Not, Ternlog}`, `Pred::Range`, gated evaluation via `under` | **primitive** (family 1) | +| SELECT | a selection IS a mask; `Terminal::Keep` returns it, `Terminal::BlendI32` is the CASE shape | **not a primitive.** An index-compacting select is the `SelectionVector` the IR forbids by law (A1; matrix R1 ELIMINATE). The one row-id exit is the named `materialize_rows`. | +| JOIN | `MaskOp::Gather` (pull a foreign mask through an index lane), `Pred::EqU32Via` (predicate through an fk), `GroupKey::Via` (group key through an fk) | **primitive** (family 2, TRANSPORT) — mask transport through an index lane; no bag-semantics join exists or is wanted | +| TRAVERSE | one step: `Gather` (pull) and `Terminal::ScatterOrU32` (push, the one-to-many hop) | **one step = TRANSPORT.** Multi-hop iteration is NOT in the IR (a scattered mask may not feed another program — its survival condition) — **OPEN**, see §11.8 | +| FOLD / REDUCE | ONE terminal per program: `Count/Any/All`, `MaskedSum/Min/MaxI32`, `MaskedStridedGroupSum`, `GroupSumI32`, `GroupSumViaI32`, `GroupReduce{GroupKey, GroupFold}`, `CountKeyRunsU32`, `ScatterCountU32` (held) | **one primitive** (family 3, REDUCE). "Fold" is also the name of the write-side per-row fold in `persist_sink`; do not reuse it here. | + +So: **MASK · TRANSPORT · REDUCE**, over the structural views of §11.1. No primitive is added by this ruling. A new one earns its place only when a named workload cannot lower without it (the missing-capability STOP rule). + +### 11.4 Where `CausalEdge64` sits — above the line; it crosses as a `u64` lane +- The register crosses as **`LaneRef::U64`**, borrowed through the existing `MailboxSoaView::edges_raw() -> &[u64]`. `CausalEdge64` is `#[repr(transparent)]` over `u64`, so the borrow copies nothing. No wrapper type is minted. +- **`CausalEdge64` itself is not an IR type.** Its field layout is feature-gated (`causal-edge-v2-layout`, default; v1 under `--no-default-features`). Naming it in the socket would couple the IR to that layout. Instead the consumer computes `Pred::MatchU64 { pattern, care }` from the register's own accessors above the line, and the IR compares bits it does not interpret. +- **Bit preservation is the requirement, not an option.** The IR never decodes or re-encodes a lane, so every bit survives, including the defining topology/band bits 59–63 that F-BBB-NARS-2 protects against aliasing. +- **NARS arithmetic does not enter this IR.** `membrane-tiers.md` rules two sibling T1 algebras: the population algebra (this socket) and the epistemic one (`TruthU8`, revision, …, D-BBB-NARS-1..4). A future `Truth(…)` plan operation is the epistemic sibling's, named by T2 `plan_eval`; it is not a mask-risc op. + +### 11.5 The factorized adjacency at the boundary, and Arrow `ListArray` +- **Today's factorized form is an index lane over the child population:** a `U32` lane naming, per child row, its row in the other table (`Gather`, `EqU32Via`, `GroupKey::Via`, `ScatterOrU32`). A key-ordered lane is also a segmentation: `CountKeyRunsU32` counts runs with O(1) state and refuses an unordered lane (`LaneNotOrdered`). +- **Arrow `ListArray` does not map today without materialization.** A `ListArray` carries `offsets[parents + 1]` + child values; the IR has no offsets view. The child values borrow fine as a lane; the SEGMENTATION would have to be expanded into a per-child parent-index lane (O(children) — a derived-lane materialization). **OPEN:** the zero-copy route is one structural view (a segment/offsets view) plus a parent-mask → child-mask expansion (a union of `mask_set_range` writes) and its reverse. Filed as `ISS-MASK-RISC-HAS-NO-SEGMENT-VIEW`; not built here. +- **Arrow bitmaps meet the tail law.** An Arrow validity bitmap reinterpreted as `&[u64]` must have zero bits past `n_rows`, or the program is refused (`ExecError::PlaneTail`) rather than read. Arrow validity is a NULL role, which the socket eliminates (matrix R6); a bitmap enters only as a plane. + +### 11.6 The dependency firewall (named crates) +- **`lance-graph-mask-risc` `[dependencies]` is exactly `{ ndarray }`**, and `src/` reaches it only as `ndarray::simd` — never `ndarray::hpc` (which carries `nars`, `causal_diff`, `styles`, `cascade`). +- **Forbidden in `[dependencies]` and `[dev-dependencies]`** (all real crates in this workspace): `lance-graph-contract`, `causal-edge`, `cognitive-shader-driver`, `thinking-engine`, `deepnsm`, `deepnsm-v2`, `lance-graph-planner`, `lance-graph-cognitive`, `lance-graph`, `p64-bridge`, `bgz17`, `bgz-tensor`, `highheelbgz`, `holograph`, `jc`, `perturbation-sim`. `lance-graph-quack` and `lance-graph-report` too: they are consumers ABOVE the socket. +- **Direction:** consumers depend on the socket, never the reverse — `quack` → mask-risc; `lgj-abi` → mask-risc (it already does); a cognitive consumer that lowers into it → mask-risc. The contract dependency is forbidden on purpose: `lance-graph-contract` carries the cognitive vocabulary (`cognitive_shader`, `nars`, `thinking`). + +### 11.7 Falsifiers (G-SOCK-*) and what "identical" may honestly claim +- **G-SOCK-1 exact equivalence.** For every program in the differential corpus, executor `Value` and every `Out` buffer `==` the reference oracle, and tiled `==` single-tile. **Shipped** (`tests/differential.rs`). Backend realizations are ndarray's to prove (its masking-parity matrix: native / nightly / wasm / wasm-scalar / neon-qemu); mask-risc is backend-independent by construction, but its own suite runs in CI on `x86-64-v3` only (D-MRX-5: NEON/WASM/scalar arms unexercised for this crate), so "identical on every backend" is ndarray's measured claim plus mask-risc's by-construction one — not a mask-risc measurement on each arm. +- **G-SOCK-2 integer-only law.** `==` is honest only because the IR carries no floating point (`i32`/`u32`/`u64` lanes, `i64` sums with stated row bounds that refuse rather than wrap). A float reduction may never join the `==` suite; if one is ever admitted it gets its own declared tolerance class. Fisher-z values, NARS `(f, c)` in f32 and `PerturbationDto` energy therefore stay above the socket. +- **G-SOCK-3 firewall.** `[dependencies]` keys `== ["ndarray"]`; no `ndarray::hpc` in `src/`; zero COGNITIVE vocabulary in `src/` code AND comments (the §11.2 term list — storage-geometry words are allowed). Disable-runs: adding any forbidden crate, and adding one listed term to a `src/` line, each turn it red. +- **G-SOCK-4 full-width register lane.** `Pred::MatchU64` with `care` over high fields (for example bits 40–42 and 59–63), not only low bits: executor `==` oracle `==` an independent per-row `(x ^ pattern) & care == 0` count, two-sided anti-vacuity (`0 < selected < n`). Disable-run: truncating the lane to 32 bits must redden. **Gap measured:** today's differential exercises `MatchU64` only at `care: 0xF000` (bits 12–15), so a 32-bit truncation would pass it. +- **G-SOCK-5 no materialization.** Already enforced (`no_alloc.rs`; tiled state is `slots × TILE_WORDS` words, independent of `n_rows`; only demanded `Out` sinks are population-sized). +- **Later, with the segment view:** the same program over a lane borrowed from an Arrow buffer and over one borrowed from a `Vec` answers `==`; an Arrow bitmap with a dirty tail is refused. + +### 11.8 The smallest next PR (not in #1303) +**Title:** `mask-risc: D-CPW-15 socket guards`. **One crate, no cognitive vocabulary, no new primitive.** +1. `crates/lance-graph-mask-risc/tests/firewall.rs`: `dependencies_are_exactly_ndarray` (reads its own `Cargo.toml` via `include_str!`), `src_reaches_ndarray_only_through_simd`, `src_names_no_cognitive_vocabulary`, `ir_is_integer_only` (production text of `ir.rs` + `value.rs`). Each disable-verified. +2. `crates/lance-graph-mask-risc/tests/u64_register_lane.rs`: G-SOCK-4 on a synthetic `u64` lane (seeded values, several `pattern/care` fields up to bit 63, gated and ungated, tiled and single-tile). +3. Board: D-CPW-15 → Shipped; AGENT_LOG only if workers ran. + +**It demonstrates value with no cognitive vocabulary at all:** "factorized graph operations over compact registers and borrowed structural views, without materialization" is exactly what the existing suite plus these two files prove. + +**Second PR (after):** the cognitive consumer binding. It is a dev-dependency test in `cognitive-shader-driver`, the only side allowed to know both. It borrows `MailboxSoaView::edges_raw()` as `LaneRef::U64`, builds `pattern/care` from `CausalEdge64` accessors, and diffs the count against a per-row decode. It also checks that the borrowed slice's pointer equals the column's (no copy). + +**Deliberately NOT implemented, here or next:** the segment/offsets view and any Arrow adapter; multi-hop traversal; an epistemic (NARS) op; any float reduction; GPU; renaming `quack` or `mask-risc`; moving `CausalEdge64` fields; any change to lexical representation or Fisher-z calibration; #1304's multi-reading problem. + +**Open for the operator:** whether "Quack" should become the umbrella name for the socket. In the repo today it names only the DuckDB-shaped surface above it; this ruling does not rename anything. + +Closeout: `STATUS: ruled (spec only) | OUTCOME: the execution socket is lance-graph-mask-risc's existing IR; three primitive families (MASK · TRANSPORT · REDUCE); CausalEdge64 crosses as a borrowed u64 lane and stays an above-the-line type | OPEN: segment view for Arrow ListArray; multi-hop traversal; umbrella naming`. + +## 11R. ⊘ REVISION of §11 (2026-09-30, same day, after reading #1305) — the socket is an OBSERVATION boundary; the mask-RISC families move below it + +**What changed.** §11 put the socket at mask-risc's instruction families (MASK · TRANSPORT · REDUCE). #1305 (`cypher-mask-multiplicity-contract-v1`, D-CMM-0..3, committed and test-pinned) shows that is the wrong level. Which information survives an operation decides correctness; which instruction computes it does not. §11 is kept as the record. This section overrides §11.3's framing of the three families as the socket, and §11.8's next PR. §11.2's invariant, §11.4 (`CausalEdge64` crosses as a `u64` lane), §11.5, §11.6 and §11.7's G-SOCK-1..5 stand, re-scoped to the whole stack below the firewall. + +**Provenance, stated plainly.** What #1305 **committed** (read 2026-09-30, branch `ccr-2fcc2bd3-8o7m2l`): +- a mask is the SUPPORT of a frontier, never its bag: 2-hop `count(*)` is 4 under DataFusion and 3 as a mask popcount; +- a forward chain is the exact support of the TERMINAL variable only: `count(DISTINCT b)` is 3 against the forward mask's 4; +- DataFusion counts WALKS: 5 against Cypher's trail count of 4 on {1→2, 2→1, 2→2}, recorded OPEN; +- `LogicalOperator::consumer_semantics()`, which classifies the carrier a consumer needs into five kinds and fails closed; +- a `BindingFrontier { support, mult, binding }` shape in spec only; +- a count lane queued as D-CMM-4. + +The `Population / Relation / step(observe) → Answer` candidate is **not in any pushed ref** (it appears in none of #1305's ten files). It is evaluated below on its merits against code; its Rust shapes are not adopted. + +### 11R.1 The layering the code supports +| layer | contents | stability | +|---|---|---| +| **domain semantics** (above the firewall) | `ReferenceSet` / lexical readings, Fisher-z, `cognitive-shader-driver`, NARS / Pearl / EWA / HHTL, `CausalEdge64` bit meaning, Cypher/SQL surface semantics | free to evolve | +| **═ firewall: the observation contract ═** | population · relation · step(observation) → answer or refusal; carrier sufficiency; declared path semantics; evaluated domain | the stable socket | +| **lowering vocabulary** (internal) | mask-risc's MASK · TRANSPORT · REDUCE: `Pred`/`And`/`Ternlog`, `Gather`/`ScatterOrU32`/`EqU32Via`, `Count`/`Any`/`GroupReduce`/`CountKeyRunsU32` | may grow; never public | +| **backends** | mask-risc over `ndarray::simd`; CSR/CSC (`planner/src/adjacency`); a future BLASgraph route | replaceable | +| **adapters (rendering)** | DuckDB table function, Arrow, Java/Panama (`lgj-abi`), WASM | outside graph computation | + +The six earlier verbs belong to the lowering row, not the public one. + +### 11R.2 The eight rulings #1303 freezes (spec only; basis per line) +1. **Domain machinery does not leak downward.** Nothing under the firewall names lexical, calibration, epistemic or cognitive-register concepts. *Basis:* §11.2 evidence (mask-risc `src/` has zero cognitive terms) plus the §11.6 dependency direction. +2. **Population / relation / observation is the candidate mechanical boundary.** *Basis:* one directed hop lowers to ONE mask-risc `Program` over the edge table today (11R.3). *Status:* CANDIDATE until the 11R.8 differential is green. +3. **A carrier may cross an operation boundary only if it is sufficient for every observation that boundary promises; otherwise the step answers `Insufficient` — never an approximation.** *Basis:* #1305 §0 (same terminal support, different `count(*)`). +4. **Path semantics is an explicit input** (walk or trail), never an executor default. *Basis:* #1305 G1b (walk 5 vs trail 4); DataFusion counts walks and is in grace. +5. **Unknown is not FALSE.** A zero means FALSE only inside a declared, fully evaluated domain of a named `(space, epoch)`. Outside it — not evaluated, out of range, stale epoch — the step refuses. *Basis:* 11R.6, which shows today's IR violates this silently. +6. **Rendering and materialization are outside graph computation.** An answer is a scalar, a support mask, per-key counts or an edge mask in caller-owned memory; tables, Arrow arrays, Java segments and row ids are adapter work. *Basis:* mask-risc law A1 and the single named `materialize_rows`. +7. **Backends are replaceable** behind the observation contract; equality is tested per observation (G-SOCK-1 re-scoped). A backend may be faster, never differently-answering. +8. **#1303 implements none of this.** + +### 11R.3 Falsifying the candidate against code +- **One hop, one program — VERIFIED from the IR.** Over the edge table as the executing population: + - `MaskOp::Gather { lane: src, foreign: from_support }` pulls the FROM population onto its edges; + - edge predicates filter the edges themselves; + - `Gather { lane: dst, foreign: to_support }` pulls the TO population onto its edges; + - `And` leaves the edge population E. + + From E: `Exists` = `Any`; `Count` = `Count`; `Support(to)` = `ScatterOrU32` over `dst`; `CountBy(to)` = `GroupReduce { key: Lane(dst), fold: Count }`; `Edges` = `Keep`. The `from` side is symmetric. No binding row is built, and the edge mask carries relationship identity. +- **Relation is not a fourth primitive — simplified.** A relation is a population (the edge address space) whose rows carry two functional index lanes into other spaces. The public contract needs population, index lane and observation; "relation" is the name of a population with two index lanes. +- **The five #1305 consumer kinds map onto one hop's observations:** `TerminalSet` ↔ `Support(to)`; `EarlierSet` ↔ `Support(from)`; `TerminalCount` ↔ `Count` / `CountBy(to)`; `EarlierCount` ↔ `CountBy(from)`; `Bindings` ↔ `Edges` — exact at k = 1, because one binding IS one edge row. So #1305's classifier is the consumer-side twin of this contract: it names what a query needs, the step names what a carrier can answer. +- **What the candidate cannot do today (named, not papered over):** + - A 2-hop `count(*)` needs the per-middle-node multiplicity folded into the next hop — a plus-times count lane (#1305's D-CMM-4). The IR has no such terminal, and feeding a `GroupReduce` sink into a second program is the forbidden intermediate. + - Trail semantics beyond one hop needs relationship identity across hops (the `Bindings` carrier). + - Both are `Insufficient` today, by rule 3. + +### 11R.4 Carrier sufficiency, and the `ScatterOrU32` prohibition +| carrier leaving a step | Exists | Count | CountBy(side) | Support(side) | Edges | next step: Support | next step: Count | +|---|---|---|---|---|---|---|---| +| edge population E | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ only with a count lane (D-CMM-4) | +| node support (after `ScatterOrU32`) | ✓ | ✗ | ✗ | own side only | ✗ | ✓ (walk reachability) | ✗ — multiplicity is gone | +| node count lane (per-key counts) | ✓ | ✓ (Σ) | own side | own side | ✗ | ✓ | ✓ under WALK semantics only | + +mask-risc forbids a scattered mask from feeding another program (`Terminal::ScatterOrU32`'s survival condition). **#1303 does not relax that.** It records the condition under which a future PR may: a sink may feed a later step only if +- (a) it is sufficient, per this table, for every observation the later step promises; and +- (b) no direct projection could serve that later step without the intermediate (the tiled-execution ruling: an intermediate population is forbidden when the next fold can consume the projection directly). + +Both must hold; either alone is not enough. + +### 11R.5 Path semantics +- **One directed hop:** walk ≡ trail by construction (one edge cannot repeat). +- **More than one hop:** the caller declares `walk` or `trail`. + - A WALK count may compose count lanes. + - A TRAIL count needs edge identity across hops. + - Where the carrier cannot prove the declared semantics, the step answers `Insufficient`. +- Neither default is baked in. DataFusion's walk count is a recorded divergence (#1305 D-CMM-5), not a reference semantics. + +### 11R.6 Unknown is not FALSE — what today's IR does, and the minimum machinery +- **Measured in code:** mask-risc collapses unknown to false in three places. + - `Gather` out of range: `ir.rs` calls it the "zero-fallback … never an error". + - `Pred::EqU32Via`: an fk naming no foreign row "does not match". + - `GroupKey`: a key past the universe is dropped. +- **Also measured:** a `ForeignPlane` is checked only by `rows`. A mask over the right-sized but wrong or stale table is accepted silently. +- Inside a declared, fully evaluated domain with validated index lanes these are correct. The socket needs exactly three mechanical distinctions — **evaluated-true, evaluated-false, not-evaluated/insufficient** — and nothing epistemic: + - a `(space, epoch)` identity on every population and index lane, with equality required at every join point; + - a domain declaration: the population's zeros are evaluated falses; + - index-lane validation against the target space (in range, checked once per epoch). +- NARS, HHTL and every graded-truth reading stay above; they receive `Insufficient` and decide what it means. Filed: `ISS-MASK-RISC-ZERO-FALLBACK-IS-NOT-EVALUATED-FALSE`. + +### 11R.7 `CausalEdge64` against this boundary +- **Above the firewall.** In population/relation terms `CausalEdge64` is a value lane on a population, not a relation: its S/P/O bytes are 8-bit palette codes, not row addresses of any space, so they cannot serve as index lanes. +- It enters only to produce a population (a support mask) through the lowering vocabulary, e.g. `Pred::MatchU64` over `edges_raw()` (§11.4), and leaves no trace in the observation contract. +- Direct exposure buys no zero-copy that the generic `u64` lane lacks: the borrow is already copy-free. So the register stays a domain type. + +### 11R.8 The smallest next PR (supersedes §11.8's; not in #1303) +**One crate (`lance-graph-quack`), the existing DuckDB oracle, no cognitive vocabulary.** +- **Why quack:** quack is already the lowering surface that builds programs and never evaluates them. +- **The data is already there:** the fixture in `tests/duckdb/data/` is a FROM–VIA–TO relation — `doc` ← `line.doc_id` · `line` · `line.partner_id` → `partner`. + +What the PR adds: +1. **The observation contract as quack types.** Populations with `(space, epoch)`, rows and a domain declaration; a relation as an edge population with two index lanes; one directed hop; five observations; path semantics as a parameter, with `trail` beyond one hop answering `Insufficient`; a `Refusal` of `Insufficient` / `SpaceMismatch` / `EpochMismatch` / `NotEvaluated`. It lowers to ONE mask-risc `Program` or refuses. The Rust shapes are that PR's decision. +2. **Cases in `cases.tsv`, regenerated by `oracle.py`, never hand-edited.** SQL joins over `doc ⋈ line ⋈ partner` as the oracle for `Exists`, `Count`, `Support(to)` (sorted rid list — the existing encoding), `CountBy(to)` / `CountBy(from)` (the existing grouped encoding) and `Edges`. +3. **The #1305 counterexample on real data.** Two edge filters with the SAME `Support(to)` and different `Count`, asserted both ways (anti-vacuity: `Count > |Support|` on at least one). A `Count` requested from a node-support carrier must refuse `Insufficient`. +4. **The unknown arm.** An index lane with one out-of-range value must refuse `NotEvaluated` rather than answer through the zero fallback. Mismatched `(space, epoch)` must refuse. +5. **The two §11.8 guard files ride along:** `tests/firewall.rs` in mask-risc (deps == `{ndarray}`, integer-only) and full-width `MatchU64`. Plus one guard in quack: its `lance-graph-contract` imports stay within `{facet, ordered_lane}` — the lgj G11-fence pattern. + +**External story, no cognition in it:** graph observations over populations and relationship lanes, without first materializing one binding row per neighbour. The oracle is ordinary SQL. + +**Deliberately NOT in that PR:** multi-hop, the count lane (D-CMM-4), trail enforcement, Arrow/DuckDB/Java adapters, the segment view, any cognitive consumer. The cognitive substrate arrives later as one more consumer that lowers into populations. + +Closeout: `STATUS: revised (spec only) | OUTCOME: the stable socket is an observation contract (population · relation-as-population-with-index-lanes · step(observation) → answer | Insufficient); mask-RISC families are lowering vocabulary below it; carrier sufficiency, explicit path semantics and unknown ≠ false are frozen as law | OPEN: count lane for k>1; trail identity; (space, epoch) identity and the domain declaration in code; umbrella naming`. diff --git a/.claude/plans/deepnsm-v3-convergence-v1.md b/.claude/plans/deepnsm-v3-convergence-v1.md index 12e2528b1..4805e267e 100644 --- a/.claude/plans/deepnsm-v3-convergence-v1.md +++ b/.claude/plans/deepnsm-v3-convergence-v1.md @@ -46,6 +46,14 @@ The representations named as "vs" are one composed stack, bottom to top: | truth | SPO-NARS 2³ (8 Pearl masks over `SpoDistances` 3×256²) | 3-bit mask in `CausalEdge64` bits 40-42; freq/conf; `Meta` tenant | mask **stored**, projections **computed** (P3) | | memory | episodic witness + AriGraph basin | `family` field (basin); `episodic_edges.rs` EW64; `witness_tombstone.rs` | **doc-only / scaffold `todo!()`** | +> ⊘ **Correction (2026-09-30, operator):** the `edge` row's V3-home cell +> ("`EdgeBlock`(16B, 1-byte refs) → `MaterializedEdges`") reads as though a +> `CausalEdge64` were a stored reference record. It is not: **`CausalEdge64` IS +> the ALU register** the NARS / Pearl 2³ operations run on (`edge.rs:1-3`). The +> `MaterializedEdges` tenant is where rows of registers rest; `EdgeBlock` is a +> retired type name (the second facet is a content-blind `FacetCascade`). Row +> kept as written; read it through this note. + **Collision guards** (from the mapper sweep — pin before any code): - "6×256" names **three** objects: CAM-PQ per-query ADC table `[[f32;256];6]`; `SpoDistances` 3×256² pairwise; OGAR key-tier 256×256 centroid tile. Not diff --git a/.claude/v3/knowledge/sonnet-worker-guardrails.md b/.claude/v3/knowledge/sonnet-worker-guardrails.md index ce80529d2..cb831262d 100644 --- a/.claude/v3/knowledge/sonnet-worker-guardrails.md +++ b/.claude/v3/knowledge/sonnet-worker-guardrails.md @@ -87,7 +87,8 @@ exactly the row below, never a neighbor. | **ResonanceDto (awareness_dto.rs)** | the PERSPECTIVAL (Piaget Three-Mountains) resonance — KEEPS its name | a duplicate to dedup | rename/merge it with the Ψ DTO | | **CollapseGate** | a legacy MODULE NAME (`collapse_gate.rs` still hosts live types: MailboxId, KanbanPhase, MergeMode) | a live singleton gate semantic | re-implement gate semantics OR delete the module | | **BindSpace** | the legacy global store, MIGRATION IN PROGRESS → MailboxSoA | something to extend or to delete now | add new writers to it; remove it | -| **baton / emission / CollapseGateEmission / emit()** | tombstoned concepts (removed from source) | anything to restore | reintroduce, even "for compatibility" | +| **emission / CollapseGateEmission / emit()** | tombstoned concepts (removed from source): the inter-mailbox emission wire | anything to restore | reintroduce, even "for compatibility" | +| **CausalEdge64** | THE ALU register: one `u64` the NARS truth, Pearl 2³ mask and inference operations run on directly (`edge.rs:1-3`: "One u64. One register. One read."). **Baton** = this same register as it passes from one cycle into the next — the answer to "how does it reach the next cycle"; keep the word | a reference, a pointer, a record in a store, a container for one word's bytes | describe it as any of those; pack a single word's address into its S/O bytes; read "baton" as a separate wire type; delete the metaphor | | **owner / on_behalf** | `SoaEnvelope::mailbox_owner()` stamp + batch-writer cast pairing | a DTO field | add ownership fields to DTOs (§1 rule 9) | | **0x1000 (custom half)** | the V3-adoption MONITOR marker — permanent (`D-CCF-4` RESCINDED, operator 2026-07-03, `E-V3-DUAL-SCHEMA-0x1000-IS-PERMANENT-1`; ~~temporary by declaration~~ regraded 2026-09-07) | a domain id or a semantic flag; something that retires at 100 % adoption | branch business logic on it; mint new meanings for it; plan its retirement | | **canon / custom** | classid halves: hi u16 = canon concept, lo u16 = custom marker/render | "old/new" | read halves with bit math (§1 rule 4) | diff --git a/crates/cognitive-shader-driver/src/backing.rs b/crates/cognitive-shader-driver/src/backing.rs index 37ad2a04c..b635f3d8b 100644 --- a/crates/cognitive-shader-driver/src/backing.rs +++ b/crates/cognitive-shader-driver/src/backing.rs @@ -113,7 +113,7 @@ impl<'a> BackingStore<'a> { } } - /// `row`'s `CausalEdge64` baton edge — typed on BOTH arms. + /// `row`'s `CausalEdge64` baton (its ALU register) — typed on BOTH arms. /// /// The Singleton arm wraps the raw `u64` (`EdgeColumn` stores `u64`); the /// Mailbox arm returns the natively-typed `CausalEdge64` (zero raw bounce). @@ -191,7 +191,7 @@ impl BackingStoreWrite<'_> { } } - /// Write `row`'s `CausalEdge64` baton edge. + /// Write `row`'s `CausalEdge64` baton (its ALU register). /// /// The Singleton arm unwraps to the raw `u64` that `EdgeColumn::set` stores; /// the Mailbox arm stores the typed edge directly. diff --git a/crates/cognitive-shader-driver/src/mailbox_soa.rs b/crates/cognitive-shader-driver/src/mailbox_soa.rs index 0cd2ef138..40c373fb1 100644 --- a/crates/cognitive-shader-driver/src/mailbox_soa.rs +++ b/crates/cognitive-shader-driver/src/mailbox_soa.rs @@ -62,7 +62,8 @@ pub struct MailboxSoA { /// Per-row spatial-temporal energy accumulator. /// Energy integrates signed-mantissa × confidence contributions from - /// incoming `CausalEdge64` batons until threshold crossing. + /// incoming `CausalEdge64` batons — the ALU registers handed to the row + /// for the next cycle (`apply_edges`) — until threshold crossing. pub energy: [f32; N], /// Per-row Hebbian integration counter (saturating u8 per W6 §4.4). @@ -86,9 +87,11 @@ pub struct MailboxSoA { pub last_write_cycle: [u32; N], // ── NEW: migrated thoughtspace columns (per-mailbox owned, D-MBX-A1) ── - /// Per-row LE baton edge (`CausalEdge64`, 8 B/row). + /// Per-row `CausalEdge64` baton (8 B/row) — the ALU register itself: the + /// NARS truth, Pearl 2³ mask and inference operations run on this `u64` + /// directly, and the baton is how the row's causal state reaches the next + /// cycle — the same register, handed on. It is not a reference to anything. /// Migrated from `BindSpace.edges` (EdgeColumn). - /// This IS the LE contract / baton edge for this mailbox row. pub edges: [CausalEdge64; N], /// Per-row affective role vector (`QualiaI4_16D`, 8 B/row). @@ -266,7 +269,7 @@ pub struct WriteCell<'a> { pub topic: Option<&'a [u64]>, /// Angle identity plane (`WORDS_PER_FP` u64) — borrowed. pub angle: Option<&'a [u64]>, - /// LE baton edge. + /// The row's `CausalEdge64` baton (the ALU register handed to the next cycle). pub edge: Option, /// Affective i4-16D vector. pub qualia: Option, @@ -577,7 +580,7 @@ impl MailboxSoA { // ── Thoughtspace column accessors (D-MBX-A1) ───────────────────────────── - /// Return the `CausalEdge64` baton edge for `row`. + /// Return the `CausalEdge64` baton (the row's ALU register) for `row`. /// /// Panics (debug) / wraps (release) on out-of-bounds; callers /// should stay within `[0, N)`. @@ -586,7 +589,7 @@ impl MailboxSoA { self.edges[row] } - /// Set the `CausalEdge64` baton edge for `row`. + /// Set the `CausalEdge64` baton (the row's ALU register) for `row`. /// /// Panics (debug) / wraps (release) on out-of-bounds; callers /// should stay within `[0, N)`. diff --git a/crates/lance-graph-contract/src/cognition/advance.rs b/crates/lance-graph-contract/src/cognition/advance.rs index 765a8e51e..5dae40d97 100644 --- a/crates/lance-graph-contract/src/cognition/advance.rs +++ b/crates/lance-graph-contract/src/cognition/advance.rs @@ -217,8 +217,10 @@ impl NormalizedEntity { /// /// Per E-CASCADE-AS-EDGECOLUMN-1: cascade traversal goes through /// the `EdgeColumn` walker, not through Odoo-style string-evaluated - /// `@api.depends`. The Baton (`(u16, CausalEdge64)`) carries the - /// causal edge to each dependent mailbox. + /// `@api.depends`. The "Baton" is the `CausalEdge64` ALU register as it + /// passes from one cycle into the next. (⊘ The inter-mailbox emission wire + /// the older wording implied was tombstoned in PR #477; the register + /// persisting across cycles was not.) /// // TODO(Stage 2): wire to Baton emission + [`super::cascade::CascadeWalker`] // traversal per the active transaction context. Stage 2 detail: diff --git a/crates/lance-graph-contract/src/cognition/cascade.rs b/crates/lance-graph-contract/src/cognition/cascade.rs index 70a31e3ff..34defea07 100644 --- a/crates/lance-graph-contract/src/cognition/cascade.rs +++ b/crates/lance-graph-contract/src/cognition/cascade.rs @@ -168,8 +168,11 @@ pub enum TraversalMode { // cognitive_shader_driver::EdgeColumn`. The walker output (the set // of `MailboxRow`s that must be re-evaluated) is fed back into // the Op chain as a new `NormalizedEntity` per dependent row, -// forming the dependency fan-out. The Baton (`(u16, CausalEdge64)`) -// carries the causal edge across mailbox boundaries per E-BATON-1. +// forming the dependency fan-out. The "Baton" is the `CausalEdge64` ALU +// register as it passes from one cycle into the next. ⊘ What E-BATON-1's +// "across mailbox boundaries" wording implied — an inter-mailbox emission wire +// type — was tombstoned in PR #477; the register persisting across cycles was +// not. How dependents receive work is Stage-2 design. pub trait CascadeWalker { /// Walk all downstream dependents of `from` in the `EdgeColumn`. /// diff --git a/docs/GENETIC_RESEARCH_VIA_STACK.md b/docs/GENETIC_RESEARCH_VIA_STACK.md index bdf31c9c3..2a401e64b 100644 --- a/docs/GENETIC_RESEARCH_VIA_STACK.md +++ b/docs/GENETIC_RESEARCH_VIA_STACK.md @@ -110,7 +110,7 @@ Variant-evidence accumulation as a substrate trajectory: a *novel* variant arriv **You know:** RAS/MAPK pathway propagation, MYC-driven transcriptional cascades, viral integration site preferences (HPV, HBV, EBV oncogenic integration), and metastatic seeding all have the same shape: a discrete event triggers a cascade through a graph of cellular sites under partial observability, with *counterfactual* branches you'd love to simulate but can't easily express in standard pipelines. **We have:** -- **`MailboxSoA`** (`crates/cognitive-shader-driver/src/mailbox_soa.rs`) — per-row SoA with `energy: [f32; N]` (signed spatio-temporal accumulator), `plasticity_counter: [u8; N]` (saturating Hebbian = lifetime activation count), `last_active_cycle: [u32; N]` (in-place consumption stamp), `edges: [CausalEdge64; N]` (LE baton edge per row), `consume_firing(row) -> bool` (in-place active inference: row threshold-crosses, energy resets, stamp advances). +- **`MailboxSoA`** (`crates/cognitive-shader-driver/src/mailbox_soa.rs`) — per-row SoA with `energy: [f32; N]` (signed spatio-temporal accumulator), `plasticity_counter: [u8; N]` (saturating Hebbian = lifetime activation count), `last_active_cycle: [u32; N]` (in-place consumption stamp), `edges: [CausalEdge64; N]` (per-row baton — the ALU register that carries the row into the next cycle), `consume_firing(row) -> bool` (in-place active inference: row threshold-crosses, energy resets, stamp advances). - **`CounterfactualMailbox`** (`crates/lance-graph-contract/src/counterfactual.rs:232`) — v3 split-resolution: `SplitPoles` (the alternative-pole representation), `deposit_counterfactual` (writes the minority pole as `InferenceType::Counterfactual` with `to_mantissa() = -6` into the episodic edge), `revise_if_minority_wins` (free-energy comparison flips the canonical reading). **Iron invariant in the doc comment:** *"A counterfactual stays in a separate lane — it is NEVER written as observed SPO. The `InferenceType::Counterfactual` tag is the mechanical enforcement of that invariant."* - **`SPAWN_DISSONANCE_THRESHOLD: f32 = 0.55`** — calibrated threshold for when a substrate state diverges enough to be *"worth a counterfactual test."*