diff --git a/.claude/board/AGENT_LOG.md b/.claude/board/AGENT_LOG.md index a1f1df27e..081eab956 100644 --- a/.claude/board/AGENT_LOG.md +++ b/.claude/board/AGENT_LOG.md @@ -1,3 +1,13 @@ +## 2026-07-28 — rails-shaped rung lift: 144-cell reasoning + 4×4 Morton cascade + qualia (main-thread, no subagent) + +- **Operator steers (4, same arc):** "use the 12×12=144 verb matrix for reasoning" (not a flat membership bit); "4×4 Morton cascade inverse pyramid perturbation shader"; "either as is or expanded to 16×16" → as-is, reserves dormant; "verbs actionability should be deterministic" → table reads only; "the qualia of blind × context would make awareness even better" → quale = cell modal × Staunen-at-lift; "(3×4)² irrational Morton drifting Pythagoras comma" → real mechanism, [S], logged as PROBE-COMMA-144 with the golden-step null as falsifier template. +- **Built — contract:** verb_table Morton cascade layer (quadrants, morton_cell, quadrant_prior + 4 tests incl. the MEASURED residual probe: mean 0.0774 / max 0.500 Grounds.lokal, pinned); verb_lexicon IRREGULAR_PASTS + epistemic lemmas (see→Mirrors 0.70, know→Abstracts 0.85; WordNet supersense split concurs) + epistemic_reading (cue gate × matrix read) + 5 tests incl. the catalogue↔matrix weld. +- **Built — probe:** lift gate → epistemic_reading; meta-truth discount = cell modal (never a constant); RungLift carries modal/cell/staunen_at/quale; B5 falsifier (scene-scale quale crowns reflexive 3:7, context factor must rise independently). +- **Measured:** fixture all green (3:7 quale 0.155 ≈ 2× 3:6's 0.086); corpus-scale mean-staunen DILUTES (1:4 0.062 > 3:7 0.056) — honest finding, rate-not-count one layer up; PROBE-QUALE-LOCAL pre-registered, not tuned in. +- **Gates:** 135 grammar tests green · clippy `-D warnings` clean ×2 · fmt clean · fixture asserts green. +- **Codex review round (#859, both confirmed real, fixed pre-merge):** P1 — snapshot taken AFTER admit_derived leaked modal into its own context factor; fix (snapshot before output) FLIPPED the corpus verdict: blind ranking now crowns 3:7 (0.047; 1:4 = 0.000 pristine) and the earlier "mean dilutes" finding is superseded as substantially artifact. P2 — homograph irregulars (saw = tool, bore = drill) unconditionally past-classified in public classify_verb → split: AMBIGUOUS_IRREGULAR_PASTS resolve only under the cue gate (epistemic_reading); read_verb("saw") stays None (sparsity preserved), tested. +- **Board (this commit):** EPIPHANIES E-RUNG-LIFT-RAILS-SHAPED-144-QUALIA-1 · LATEST_STATE inventory. Task #49. + ## 2026-07-28 — PROBE-EYES-OPENED: the Adam awareness printed blind (main-thread, no subagent) - **Operator arc:** "the most brutal test would be to find out how the KJV bible bake needs to connect the dots about the Adam awareness — 'Their eyes were opened'" + "we could start with that and Hermeneutik" + "how does Hermeneutik compute to NARS". Built the four-blade probe over the real KJV bake (`/tmp/pg10.txt`, Gutenberg #10, local-only). diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index bd9e53dab..50cba1115 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,15 @@ +## 2026-07-28 — E-RUNG-LIFT-RAILS-SHAPED-144-QUALIA-1 — the rung-lift stops being a membership bit and becomes a 144-CELL READ (operator: "use the 12×12=144 verb matrix for reasoning"), the 144 gets its 4×4 Morton cascade addressing (operator: "4×4 Morton cascade inverse pyramid"; "either as is or expanded to 16×16" → as-is, reserves dormant), and awareness gains the quale = BLIND × CONTEXT (operator: cell modal × Staunen-at-lift) — which, after the codex-P1 measurement fix (snapshot BEFORE the lift's own output), crowns 3:7 in the BLIND corpus ranking at full scale. + +**Status:** SHIPPED + MEASURED. Contract: `verb_lexicon::{IRREGULAR_PASTS, epistemic_reading, EpistemicReading}` (epistemic lemmas minted into the matrix: SEE-class → `Mirrors` modal 0.70, KNOW-class → `Abstracts` modal 0.85 — WordNet independently makes the same cut, verb.perception vs verb.cognition, two of its 15 supersenses ≈ the 16-cell coarse grid; troponymy = the pyramid below) + `verb_table::{FamilyQuadrant, TenseQuadrant, morton_cell, same_quadrant, quadrant_prior}` (one byte per cell `[fq:2|tq:2|fm:2|tm:2]`, high nibble = coarse quadrant = nibble-ancestry, D-TILE256-shaped; 12×12 occupied in the 16×16 = palette256 page, reserves RESERVE-DON'T-RECLAIM). Probe: cell-graded meta-truth (the discount IS the cell's tense-modulated modal, never a constant) + B5 quale falsifier. Gates: 135 grammar tests green, clippy `-D warnings` ×2 clean, fixture asserts green. **Confidence:** High on all pinned numbers; the family-quadrant carve and epistemic placements are STARTER (wordnet-supersense alignment probe queued). + +**The rails-shaping (the operator's correction, one layer up from #842's).** #858 gated rung lifts on flat `is_perception_verb` membership — the same hand-rolling anti-pattern the archetype-consumer PR fixed for relations. Now: the cue catalogue only licenses the that-complement (a lexical fact — `resemble` is Mirrors but takes no that-clause; Moore's cheap check); the REASONING is the cell read: `(family, tense) → base_prior.combine(tense_modifier) → modal` = the lift's epistemic force, + the cell's Morton byte for carriage. The catalogue↔matrix WELD test makes drift impossible: every cue surface form must read a cell. The 144 immediately earns its keep on the first text: "the woman SAW that the tree was good" (3:6, Mirrors/Past, 0.70) < "they KNEW that they were naked" (3:7, Abstracts/Past, 0.85) — seeing and knowing graded by the matrix, Change-quadrant SIBLINGS in the pyramid (same coarse cell, different members). + +**The inverse-pyramid residual probe (measured, the 4×4 claim tested).** The table was secretly already pyramid-shaped — `base_prior` groups the 12 families into exactly the 4 quadrant superclasses (its own comment headers: Change/Action/State/Discovery) and `tense_modifier` is class-shaped over the 4 tense quadrants (`t/3`: Simple/Continuous/Perfect/Mood). Measured over all 144 cells × 5 axes: **mean residual 0.0774** (cells ARE small perturbations on quadrant centroids — the pyramid claim holds on the mean) with a named outlier catalogue: **Grounds.lokal 0.500** (the State class's lokal outlier), Causes.temporal 0.300, Contradicts.kausal 0.279, Mirrors.lokal 0.275 — the per-family axis signatures the coarse level deliberately does not carry. **Lokal is the axis the 4-class carve compresses worst** — a real input to the wordnet tune. Quadrant centroids keep the class signal (Action→kausal-dominant, State→modal-dominant, asserted) = graceful degradation: an unknown-but-quadrant-resolvable verb still reads class-correct priors. All deterministic (operator: "verbs actionability should be deterministic") — table reads, no stochastic scoring. + +**B5 — awareness = blind × context (quale = modal × Staunen-at-lift), with a codex-P1 correction that FLIPPED the corpus verdict.** First cut snapshotted the arena AFTER `admit_derived` — the lift's own modal-scaled meta-belief sat inside its own context factor, so `modal` leaked into both sides of the product and the corpus ranking crowned 1:4 (staunen 0.089, mostly contamination + early-arena entropy). Codex caught it (P1: "measure context before admitting the graded meta-belief"). Post-fix, context = the arena strictly BEFORE the lift's output: **1:4's context collapses to exactly 0.000** (a pristine, fully-confident creation arena has zero felt context — no unresolved truth, no committed contradiction), and the **blind corpus ranking over all ten lifts crowns 3:7**: quale 0.047 > 1:12's 0.041 > 3:6's 0.035 > … > 1:4's 0.000. Scene-scale (asserted): 3:6 saw = 0.70 × 0.053 = 0.037 vs 3:7 knew = 0.85 × 0.133 = **0.113** (3×), with the assert requiring the CONTEXT factor alone to rise between them (the eat reversal lands in between) so the quale is never decoration over reflexivity. The earlier "field-mean staunen dilutes at corpus scale" reading is **superseded — it was substantially the contamination artifact**; the mean-dilution mechanism remains real in principle (margins are modest: 0.047 vs 0.041), so **PROBE-QUALE-LOCAL** (Δstaunen, the shipped `Dissolution` step delta) is demoted from "needed rescue" to "optional sharpening", still pre-registered, never tuned in post hoc. Lesson for the ledger: a measurement-hygiene review fix did not just clean a number — it flipped a scientific verdict; the context factor MUST exclude the event's own output (context precedes consequence, mechanically). + +**Queued probes (logged, not built):** PROBE-QUALE-LOCAL (above); **PROBE-WORDNET-QUADRANTS** (families ↔ WordNet 15 verb supersenses alignment over the in-house wordnet rail, D-RCC-5-adjacent — the corpus tune for both the carve and the epistemic placements); **PROBE-COMMA-144** (operator: "(3×4)² irrational Morton cascade drifting Pythagoras comma" — REAL as mechanism: the tense carve is 3×4 and a mixed-radix (3,4) interleave never closes, 3ᵏ≢4ᵐ, the wrap defect = a comma analogue, D-QUANTGATE's coprime-walk slot; but [S] until a probe names WHAT READS THE PHASE — the golden-step null (E-BASE17-…-RELABEL-1: GOLDEN_STEP=11 carried zero information) is the falsifier template: a drifting relabel is information-free unless a reader consumes phase). **O7 fence held:** all of this addresses verb_table's 144 ONLY; the divergent sigma_rosetta 144 (E-RUNG2-TWO-144S-1) is untouched. Refs: E-EYES-OPENED-PRINTS-BLIND-1 (the probe this hardens), E-SCI-1-VERB-TABLE-ARCHETYPE-CONSUMER-AND-FSM-FEEDER-1 (the relation-side rails-shaping), persona-vs-rung-ladder.md (rung-2 = the 144 thinking atoms), task #49. + ## 2026-07-28 — E-EYES-OPENED-PRINTS-BLIND-1 — PROBE-EYES-OPENED: the Adam awareness event ("their eyes were opened", Gen 3:7) PRINTS as epistemic structure, found BLIND on real KJV Genesis 1–4 (106 verses) — across TEN rung lifts exactly ONE is self-referential and it is 3:7 `they —knew→ naked`; the blind contradiction ranking surfaces the fall's two hinges (`eat`, `die`, both 0.850) PLUS two genuine reversals nobody designed for (`god→good` @2:18, `they→respect` @4:4-5); and the hermeneutic circle gets its missing TERMINATION PROOF from NARS. **Status:** SHIPPED + MEASURED. `crates/lance-graph-planner/examples/probe_eyes_opened.rs` (self-asserting 13-verse KJV fixture in CI; real-corpus mode `-- /tmp/pg10.txt` local-only) + `contract/grammar/clause_cues.rs` gains `is_negation` / `is_perception_verb` (exact catalogues, fire+silent tests). Gates: contract 6 unit + 4 doctests green, clippy `-D warnings` clean ×2, fmt clean, fixture falsifier asserts green. **Confidence:** High on every asserted number (fixture pinned to measurement); the extractor is deliberately COARSE (single-scene pronoun coreference → one `they` referent; no conditionals; no object scoping) and the real-corpus run is informational, not asserted. diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index b14070ba1..37a3b8eea 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -1,3 +1,10 @@ +## 2026-07-28 — branch `claude/x265-x266-plans-review-h9osnl` — rails-shaped rung lift (144-cell reasoning + Morton cascade + qualia) + +### Current Contract Inventory — verb matrix cascade + epistemic reading +- `lance_graph_contract::grammar::verb_table::{FamilyQuadrant, TenseQuadrant, morton_cell, same_quadrant, quadrant_prior}` (`E-RUNG-LIFT-RAILS-SHAPED-144-QUALIA-1`) — the 4×4 Morton cascade addressing of the 144: one byte per cell `[fq:2|tq:2|fm:2|tm:2]`, high nibble = coarse quadrant (nibble-ancestry, D-TILE256-shaped), 12×12 occupied in the 16×16 palette256 page, reserves RESERVE-DON'T-RECLAIM. Inverse-pyramid residual probe MEASURED + pinned: mean 0.0774, max 0.500 = Grounds.lokal (outlier catalogue named; lokal = the axis the carve compresses worst). Deterministic throughout. +- `lance_graph_contract::grammar::verb_lexicon::{IRREGULAR_PASTS, EpistemicReading, epistemic_reading}` — the rails-shaped rung-lift condition: cue gate (that-complement licensing) + 144-cell read (tense-modulated modal = epistemic force + Morton address). Epistemic lemmas minted: SEE-class → Mirrors (0.70), KNOW-class → Abstracts (0.85) — WordNet's verb.perception/verb.cognition supersense split independently confirms the cut. Catalogue↔matrix WELD test forbids drift. Irregular pasts (knew/saw/understood/…) classify with correct tense. +- `probe_eyes_opened` B5 — awareness quale = blind × context (cell modal × Staunen-at-lift), context snapshotted BEFORE the lift's own output (codex P1 fix — the first cut leaked modal into both factors and the fix FLIPPED the corpus verdict): scene-scale asserted (3:7 = 0.85×0.133 = 0.113 > 3:6 = 0.70×0.053 = 0.037, both factors independently); corpus-scale the BLIND ranking over ten lifts crowns 3:7 (0.047; 1:4's pristine arena reads exactly 0.000 context). Codex P2 also fixed: homograph irregulars (saw/bore) stay sparse in the public classifier, resolving only under the cue gate. PROBE-QUALE-LOCAL demoted to optional sharpening. Also queued: PROBE-WORDNET-QUADRANTS, PROBE-COMMA-144 ([S] until a phase-reader is named). O7 fence held. Detail: EPIPHANIES + AGENT_LOG 2026-07-28. + ## 2026-07-28 — branch `claude/x265-x266-plans-review-h9osnl` — PROBE-EYES-OPENED (the Adam awareness printed blind from the KJV bake) ### Current Contract Inventory — new clause_cues catalogues + probe example diff --git a/crates/lance-graph-contract/src/grammar/verb_lexicon.rs b/crates/lance-graph-contract/src/grammar/verb_lexicon.rs index 9898c2c1c..1a798992f 100644 --- a/crates/lance-graph-contract/src/grammar/verb_lexicon.rs +++ b/crates/lance-graph-contract/src/grammar/verb_lexicon.rs @@ -121,6 +121,14 @@ const FAMILY_LEXICON: &[(&str, VerbFamily)] = &[ ("conceptualize", VerbFamily::Abstracts), ("idealize", VerbFamily::Abstracts), ("model", VerbFamily::Abstracts), + // Epistemic KNOW-class: knowing forms a concept from the world — the + // mind abstracts. Cell modal 0.85 = the strongest epistemic force in + // the matrix (the 144 grades knowing above seeing; see + // `epistemic_reading`). "they KNEW that they were naked" (Gen 3:7). + ("know", VerbFamily::Abstracts), + ("understand", VerbFamily::Abstracts), + ("realize", VerbFamily::Abstracts), + ("recognize", VerbFamily::Abstracts), // ── Enables — Discovery/enablement: high Kausal + Lokal ── ("enable", VerbFamily::Enables), ("allow", VerbFamily::Enables), @@ -160,6 +168,12 @@ const FAMILY_LEXICON: &[(&str, VerbFamily)] = &[ ("mimic", VerbFamily::Mirrors), ("correspond", VerbFamily::Mirrors), ("match", VerbFamily::Mirrors), + // Epistemic SEE-class: perceiving mirrors the world in the perceiver — + // representation, not yet concept. Cell modal 0.70 < the KNOW-class's + // 0.85 (Abstracts): the 144 grades seeing below knowing. "the woman + // SAW that the tree was good" (Gen 3:6). + ("see", VerbFamily::Mirrors), + ("perceive", VerbFamily::Mirrors), // ── Dissolves — Change verb: high Temporal + Modal ── ("dissolve", VerbFamily::Dissolves), ("dissipate", VerbFamily::Dissolves), @@ -218,11 +232,37 @@ pub fn family_of_lemma(lemma: &str) -> Option { .map(|(_, f)| *f) } +/// Irregular past surface forms → base lemma. Consulted BEFORE the +/// bare-form-as-Present fallback, so `knew` classifies as (know, Past) and +/// never as a Present lemma in its own right. Small and exact — only forms a +/// consumer catalogue actually needs (extend alongside `FAMILY_LEXICON`). +const IRREGULAR_PASTS: &[(&str, &str)] = &[ + ("knew", "know"), + ("understood", "understand"), + ("grew", "grow"), + ("arose", "arise"), + ("became", "become"), + ("brought", "bring"), + ("held", "hold"), + ("upheld", "uphold"), +]; + +/// Irregular pasts that are HOMOGRAPHS of unrelated words — `saw` (the tool), +/// `bore` (to drill) — and therefore NEVER resolve in the context-free public +/// [`classify_verb`] (codex P2: an unconditional past reading would make +/// `read_verb` emit confidently mistyped relations for "saw the plank" where +/// the honest behavior is sparsity). They resolve ONLY through a cue-gated +/// path that supplies the missing context — today that is +/// [`epistemic_reading`], where `is_perception_verb` + the that-complement +/// license the verb reading of `saw`. `bore` has no cue consumer yet, so it +/// keeps returning `None` everywhere — ambiguity preserved, not guessed. +const AMBIGUOUS_IRREGULAR_PASTS: &[(&str, &str)] = &[("saw", "see"), ("bore", "bear")]; + /// Candidate (lemma, tense) readings for a surface form, in priority order. -/// Regular English inflection only — `-ing`/`-ed`/`-es`/`-s` with the `-e` -/// restoration (`caus` → `cause`) and single doubled-consonant collapse -/// (`running` → `run`). The surface form itself is tried first (irregulars and -/// already-base forms), as present tense. +/// Irregular pasts first (`knew` → know/Past), then regular English +/// inflection — `-ing`/`-ed`/`-es`/`-s` with the `-e` restoration +/// (`caus` → `cause`) and single doubled-consonant collapse (`running` → +/// `run`). The surface form itself is tried as present tense (base forms). fn lemma_candidates(w: &str) -> Vec<(String, Tense)> { let mut out: Vec<(String, Tense)> = Vec::new(); let push = |s: String, t: Tense, out: &mut Vec<(String, Tense)>| { @@ -230,7 +270,11 @@ fn lemma_candidates(w: &str) -> Vec<(String, Tense)> { out.push((s, t)); } }; - // Bare surface form (irregular past / present base): try as present. + // Irregular past: the surface form IS a past tense of a known base. + if let Some((_, base)) = IRREGULAR_PASTS.iter().find(|(s, _)| *s == w) { + push((*base).to_string(), Tense::Past, &mut out); + } + // Bare surface form (present base): try as present. push(w.to_string(), Tense::Present, &mut out); // -ing → present continuous. @@ -363,6 +407,76 @@ pub fn read_verb(word: &str) -> Option<(VerbFamily, Tense, TekamoloSlot)> { Some((family, tense, slot_for(family, tense))) } +/// The 144-cell reading of an epistemic (rung-lift) verb — the RAILS-SHAPED +/// lift condition. A flat catalogue-membership bit is not a reasoning +/// condition; the cell is: +/// +/// * the **cue gate** (`clause_cues::is_perception_verb`) licenses the +/// that-complement — a lexical fact (the Mirrors family also holds +/// `resemble`, which takes no that-clause), Moore's cheap check first; +/// * the **matrix read** supplies the reasoning: `(family, tense)` → the +/// cell's tense-modulated MODAL prior = the lift's epistemic force, and +/// the cell's one-byte Morton address for downstream carriage. +/// +/// The 144 grades knowing above seeing: KNOW-class verbs sit in `Abstracts` +/// (modal 0.85 — concept formation) and SEE-class in `Mirrors` (modal 0.70 — +/// representation), so "they KNEW that they were naked" (Gen 3:7) carries +/// more epistemic force than "the woman SAW that the tree was good" (3:6) — +/// graded by the matrix, not by a constant. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct EpistemicReading { + /// The verb's family (KNOW-class → `Abstracts`, SEE-class → `Mirrors`). + pub family: VerbFamily, + /// Tense read from morphology (irregular pasts resolved: `knew` → Past). + pub tense: Tense, + /// The cell's tense-modulated modal prior — the lift's epistemic force. + pub modal: f32, + /// The cell's one-byte Morton cascade address (`verb_table::morton_cell`). + pub cell: u8, +} + +/// Read an epistemic verb through the 144 matrix, or `None` if the word is +/// not a rung-lift operator (cue gate) or does not classify (matrix gate). +/// Both gates must pass — the weld test asserts the catalogue can never +/// drift from the matrix. +/// +/// ``` +/// use lance_graph_contract::grammar::verb_lexicon::epistemic_reading; +/// use lance_graph_contract::grammar::verb_table::VerbFamily; +/// let knew = epistemic_reading("knew").unwrap(); +/// let saw = epistemic_reading("saw").unwrap(); +/// assert_eq!(knew.family, VerbFamily::Abstracts); // knowing forms concepts +/// assert_eq!(saw.family, VerbFamily::Mirrors); // seeing represents +/// assert!(knew.modal > saw.modal); // the 144 grades them +/// assert_eq!(epistemic_reading("sewed"), None); // action verb — no lift +/// assert_eq!(epistemic_reading("resembled"), None); // Mirrors, but no that-clause cue +/// ``` +#[must_use] +pub fn epistemic_reading(word: &str) -> Option { + let lower = word.to_ascii_lowercase(); + if !crate::grammar::clause_cues::is_perception_verb(&lower) { + return None; // cheap cue gate: licenses the that-complement + } + // The cue gate IS the context an ambiguous homograph needs: within this + // path, `saw` is a perception verb awaiting a that-complement, never the + // tool — so the ambiguous irregulars resolve here and only here. + let (family, tense) = if let Some((_, base)) = AMBIGUOUS_IRREGULAR_PASTS + .iter() + .find(|(surface, _)| *surface == lower.as_str()) + { + (family_of_lemma(base)?, Tense::Past) + } else { + classify_verb(&lower)? + }; + let prior = base_prior(family).combine(tense_modifier(tense)); + Some(EpistemicReading { + family, + tense, + modal: prior.modal, + cell: crate::grammar::verb_table::morton_cell(family, tense), + }) +} + #[cfg(test)] mod tests { use super::*; @@ -493,4 +607,128 @@ mod tests { Some((VerbFamily::Prevents, Tense::Past)) ); } + + // ── The rails-shaped rung lift (144-cell reasoning) ── + + #[test] + fn irregular_pasts_classify_with_past_tense() { + assert_eq!( + classify_verb("knew"), + Some((VerbFamily::Abstracts, Tense::Past)) + ); + assert_eq!( + classify_verb("understood"), + Some((VerbFamily::Abstracts, Tense::Past)) + ); + // Regulars via morphology still work for the new lemmas. + assert_eq!( + classify_verb("knowing"), + Some((VerbFamily::Abstracts, Tense::PresentContinuous)) + ); + assert_eq!( + classify_verb("sees"), + Some((VerbFamily::Mirrors, Tense::Present)) + ); + } + + /// The catalogue↔matrix WELD: every perception-verb surface form the cue + /// catalogue fires on MUST classify through the 144 matrix. This is what + /// makes the flat catalogue unable to drift from the reasoning matrix — + /// a cue without a cell is a compile-adjacent failure here, not a silent + /// membership bit at a consumer. + #[test] + fn every_perception_cue_reads_a_matrix_cell() { + for w in [ + "know", + "knew", + "knows", + "knowing", + "see", + "saw", + "sees", + "perceive", + "perceived", + "understand", + "understood", + "realize", + "realized", + "recognize", + "recognized", + ] { + use crate::grammar::clause_cues::is_perception_verb; + assert!(is_perception_verb(w), "{w} must be in the cue catalogue"); + let r = epistemic_reading(w); + assert!( + r.is_some(), + "{w} fires the cue but reads NO matrix cell — drift" + ); + } + } + + /// The 144 grades epistemic force: knowing (Abstracts, modal 0.85) above + /// seeing (Mirrors, modal 0.70) — the exact pins of the shipped starter + /// priors at Past (no tense delta). Inertness: these are cell reads, so + /// changing base_prior moves them (re-pin on tune). + #[test] + fn the_matrix_grades_knowing_above_seeing() { + let knew = epistemic_reading("knew").unwrap(); + let saw = epistemic_reading("saw").unwrap(); + assert_eq!(knew.family, VerbFamily::Abstracts); + assert_eq!(saw.family, VerbFamily::Mirrors); + assert!( + (knew.modal - 0.85).abs() < 1e-6, + "knew modal = Abstracts base 0.85" + ); + assert!( + (saw.modal - 0.70).abs() < 1e-6, + "saw modal = Mirrors base 0.70" + ); + // Tense modulates the force: Potential ("might know") +0.25 clamps at 1.0. + let mut has_tense_effect = false; + if let Some(r) = epistemic_reading("knowing") { + // PresentContinuous: modal −0.05 → 0.80 < 0.85. + assert!((r.modal - 0.80).abs() < 1e-6); + has_tense_effect = true; + } + assert!(has_tense_effect, "the tense COLUMN must modulate the cell"); + } + + /// The cell address rides along: knew and saw live in DIFFERENT family + /// quadrants (Change holds both Abstracts and Mirrors — same fq — so the + /// discrimination is at the member level, not the quadrant level: the + /// pyramid places seeing and knowing as siblings under Change). + #[test] + fn epistemic_cells_are_change_quadrant_siblings() { + use crate::grammar::verb_table::{same_quadrant, FamilyQuadrant}; + let knew = epistemic_reading("knew").unwrap(); + let saw = epistemic_reading("saw").unwrap(); + assert_eq!(VerbFamily::Abstracts.quadrant().0, FamilyQuadrant::Change); + assert_eq!(VerbFamily::Mirrors.quadrant().0, FamilyQuadrant::Change); + // Same tense (Past → Simple) + same family quadrant → same coarse cell; + // different members → different full address. + assert!(same_quadrant(knew.cell, saw.cell)); + assert_ne!(knew.cell, saw.cell); + } + + /// The two gates are BOTH required (stay-silent halves): an action verb + /// fails the cue gate; a Mirrors verb without that-complement licensing + /// (`resembled`) fails the cue gate despite classifying in the matrix. + #[test] + fn epistemic_reading_stays_silent_without_both_gates() { + assert_eq!(epistemic_reading("sewed"), None, "action verb"); + assert_eq!( + epistemic_reading("caused"), + None, + "relational verb, not epistemic" + ); + assert!( + classify_verb("resembled").is_some(), + "resemble IS in the matrix" + ); + assert_eq!( + epistemic_reading("resembled"), + None, + "…but takes no that-clause: cue gate must hold it back" + ); + } } diff --git a/crates/lance-graph-contract/src/grammar/verb_table.rs b/crates/lance-graph-contract/src/grammar/verb_table.rs index 484712286..bdfd5c94f 100644 --- a/crates/lance-graph-contract/src/grammar/verb_table.rs +++ b/crates/lance-graph-contract/src/grammar/verb_table.rs @@ -327,6 +327,151 @@ pub fn default_table() -> VerbRoleTable { t } +// ═══════════ The 4×4 Morton cascade reading (operator, 2026-07-28) ═══════════ +// +// The 144 table addressed in the canonical 16×16 = 256 cascade space (one +// palette256 page): each cell is ONE BYTE `[fq:2|tq:2|fm:2|tm:2]` whose HIGH +// NIBBLE is the coarse 4×4 quadrant pair — nibble = ancestry, the D-TILE256 +// rigor condition. The 12×12 stays AS-IS (occupied); the 4 spare members per +// quadrant axis are RESERVE-DON'T-RECLAIM — minted later with zero layout +// change, never compacted away. +// +// The INVERSE-PYRAMID perturbation reading: apex (uniform prior) → quadrant +// centroid (the coarse semantic signal) → member cell (a small residual +// perturbation on its centroid). The table was already secretly this shape — +// `base_prior` groups the 12 families into exactly these 4 superclasses (its +// own comment headers) and `tense_modifier` is class-shaped over the 4 tense +// quadrants — the cascade only makes the pyramid ADDRESSABLE. Deterministic +// throughout (verb actionability is table reads; no stochastic scoring). +// +// Compartment grounding (starter, wordnet-tunable): WordNet's verb inventory +// is compartmentalized into 15 supersenses (verb.change / verb.cognition / +// verb.perception / verb.motion / verb.stative / …) — a near-fill of the 16 +// coarse cells — with troponymy as the pyramid below; Levin's alternation +// classes make the same coarse cuts. A families↔supersenses alignment probe +// over the in-house wordnet rail is the queued corpus tune (D-RCC-5 adjacent). +// +// O7 fence: this addresses verb_table's 144 ONLY. The divergent sigma_rosetta +// 144 (E-RUNG2-TWO-144S-1) is NOT bridged here. + +/// The four family superclasses — the coarse family axis of the 4×4 quadrant +/// grid, lifted from `base_prior`'s own grouping. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u8)] +pub enum FamilyQuadrant { + /// Change verbs — high Temporal + Modal (Becomes, Dissolves, Abstracts, Mirrors). + Change = 0, + /// Action verbs — high Kausal + Temporal (Causes, Prevents, Transforms; 1 reserve). + Action = 1, + /// State verbs — high Modal, low Temporal (Supports, Contradicts, Refines, Grounds). + State = 2, + /// Discovery / enablement — high Kausal + Lokal (Enables; 3 reserve). + Discovery = 3, +} + +/// The four tense superclasses — the coarse tense axis (`tense as usize / 3`, +/// matching `Tense`'s declaration order and `tense_modifier`'s class shape). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u8)] +pub enum TenseQuadrant { + /// Present / Past / Future — unmarked (zero modifier). + Simple = 0, + /// The three continuous aspects — ongoing process. + Continuous = 1, + /// Perfect / Pluperfect / FuturePerfect — completion, temporal anchoring. + Perfect = 2, + /// Habitual / Potential / Imperative — marked mood. + Mood = 3, +} + +impl VerbFamily { + /// This family's (quadrant, member-index) coordinate in the coarse grid. + /// Member indices are dense within each quadrant; unassigned indices are + /// RESERVED (Action 3; Discovery 1..=3). + #[must_use] + pub fn quadrant(self) -> (FamilyQuadrant, u8) { + match self { + Self::Becomes => (FamilyQuadrant::Change, 0), + Self::Dissolves => (FamilyQuadrant::Change, 1), + Self::Abstracts => (FamilyQuadrant::Change, 2), + Self::Mirrors => (FamilyQuadrant::Change, 3), + Self::Causes => (FamilyQuadrant::Action, 0), + Self::Prevents => (FamilyQuadrant::Action, 1), + Self::Transforms => (FamilyQuadrant::Action, 2), + Self::Supports => (FamilyQuadrant::State, 0), + Self::Contradicts => (FamilyQuadrant::State, 1), + Self::Refines => (FamilyQuadrant::State, 2), + Self::Grounds => (FamilyQuadrant::State, 3), + Self::Enables => (FamilyQuadrant::Discovery, 0), + } + } +} + +/// A tense's (quadrant, member-index): `(t/3, t%3)` by declaration order. +/// Member 3 of every tense quadrant is RESERVED. +#[must_use] +pub fn tense_quadrant(tense: Tense) -> (TenseQuadrant, u8) { + let t = tense as u8; + let q = match t / 3 { + 0 => TenseQuadrant::Simple, + 1 => TenseQuadrant::Continuous, + 2 => TenseQuadrant::Perfect, + _ => TenseQuadrant::Mood, + }; + (q, t % 3) +} + +/// The cell's one-byte Morton address: `[fq:2|tq:2|fm:2|tm:2]` MSB→LSB. The +/// high nibble `(fq,tq)` is the coarse quadrant pair — two addresses share a +/// coarse cell iff `a >> 4 == b >> 4` (ancestry by nibble). +#[must_use] +pub fn morton_cell(family: VerbFamily, tense: Tense) -> u8 { + let (fq, fm) = family.quadrant(); + let (tq, tm) = tense_quadrant(tense); + ((fq as u8) << 6) | ((tq as u8) << 4) | (fm << 2) | tm +} + +/// Do two cell addresses share a coarse quadrant (high-nibble ancestry)? +#[must_use] +pub fn same_quadrant(a: u8, b: u8) -> bool { + a >> 4 == b >> 4 +} + +/// The coarse-cell centroid: mean of the OCCUPIED member cells' full priors +/// in the `(fq, tq)` quadrant. This is the pyramid's middle level — what an +/// unknown verb resolvable only to a quadrant reads (graceful degradation; +/// Moore's cheap-check-first at the representation level). Reserved members +/// contribute nothing (occupied-mean, never zero-padded). +#[must_use] +pub fn quadrant_prior(fq: FamilyQuadrant, tq: TenseQuadrant) -> SlotPrior { + let mut sum = [0.0f32; 5]; + let mut n = 0.0f32; + for family in VerbFamily::ALL { + if family.quadrant().0 != fq { + continue; + } + for tense in Tense::ALL { + if tense_quadrant(tense).0 != tq { + continue; + } + let p = base_prior(family).combine(tense_modifier(tense)); + sum[0] += p.temporal; + sum[1] += p.kausal; + sum[2] += p.modal; + sum[3] += p.lokal; + sum[4] += p.instrument; + n += 1.0; + } + } + SlotPrior { + temporal: sum[0] / n, + kausal: sum[1] / n, + modal: sum[2] / n, + lokal: sum[3] / n, + instrument: sum[4] / n, + } +} + #[cfg(test)] mod tests { use super::*; @@ -586,4 +731,110 @@ mod tests { assert!(p.lokal >= 0.0 && p.lokal <= 1.0); assert!(p.instrument >= 0.0 && p.instrument <= 1.0); } + + // ── The 4×4 Morton cascade layer ── + + /// Every occupied (family, tense) cell gets a UNIQUE byte address, and the + /// high nibble is exactly the quadrant pair (ancestry by nibble). + #[test] + fn morton_addresses_are_unique_and_nibble_ancestored() { + let mut seen = std::collections::HashSet::new(); + for family in VerbFamily::ALL { + for tense in Tense::ALL { + let cell = morton_cell(family, tense); + assert!(seen.insert(cell), "duplicate address {cell:#04x}"); + let (fq, _) = family.quadrant(); + let (tq, _) = tense_quadrant(tense); + assert_eq!(cell >> 4, ((fq as u8) << 2) | (tq as u8)); + } + } + assert_eq!(seen.len(), 144, "12×12 occupied cells in the 16×16 space"); + } + + /// Ancestry discriminates: same-quadrant pairs share the high nibble, + /// cross-quadrant pairs do not (fire + stay-silent on non-trivial input). + #[test] + fn same_quadrant_fires_and_stays_silent() { + // Becomes/Dissolves are both Change; Present/Past both Simple. + let a = morton_cell(VerbFamily::Becomes, Tense::Present); + let b = morton_cell(VerbFamily::Dissolves, Tense::Past); + assert!( + same_quadrant(a, b), + "Change×Simple pair shares the coarse cell" + ); + // Causes is Action — different family quadrant. + let c = morton_cell(VerbFamily::Causes, Tense::Present); + assert!(!same_quadrant(a, c), "Change vs Action must not share"); + // Same family, mood tense — different tense quadrant. + let d = morton_cell(VerbFamily::Becomes, Tense::Potential); + assert!(!same_quadrant(a, d), "Simple vs Mood must not share"); + } + + /// The inverse-pyramid residual probe — MEASURED, then pinned. The claim: + /// the 144's information lives mostly at the coarse level — each occupied + /// cell is a small perturbation on its quadrant centroid. Measured on the + /// shipped starter priors: **mean residual 0.0774** (the pyramid claim + /// holds on the mean), **max 0.500 = Grounds.lokal** vs the State + /// quadrant's lokal centroid 0.35 — the largest of a named outlier + /// catalogue (Grounds.L 0.500, Causes.T 0.300, Contradicts.K 0.279, + /// Mirrors.L 0.275): the per-family axis SIGNATURES the coarse level + /// deliberately does not carry. Lokal is the axis the 4-class carve + /// compresses worst — a real input to the queued wordnet-supersense + /// alignment tune. Inertness: max must sit AT the Grounds.lokal value + /// (a smaller max means the priors changed and the pins are stale); + /// mean far under the ~0.30 spread a shuffled family→quadrant + /// assignment would produce. + #[test] + fn quadrant_centroids_reconstruct_cells_within_measured_residuals() { + let mut max_res = 0.0f32; + let mut sum_res = 0.0f32; + let mut n = 0.0f32; + for family in VerbFamily::ALL { + let (fq, _) = family.quadrant(); + for tense in Tense::ALL { + let (tq, _) = tense_quadrant(tense); + let cell = base_prior(family).combine(tense_modifier(tense)); + let cen = quadrant_prior(fq, tq); + for (c, q) in [ + (cell.temporal, cen.temporal), + (cell.kausal, cen.kausal), + (cell.modal, cen.modal), + (cell.lokal, cen.lokal), + (cell.instrument, cen.instrument), + ] { + let r = (c - q).abs(); + max_res = max_res.max(r); + sum_res += r; + n += 1.0; + } + } + } + let mean_res = sum_res / n; + assert!( + (0.49..=0.51).contains(&max_res), + "max residual {max_res:.3} — pinned at Grounds.lokal 0.500; a different \ + value means the priors changed and these pins need re-measuring" + ); + assert!( + (0.07..=0.09).contains(&mean_res), + "mean residual {mean_res:.4} — measured 0.0774: cells are small \ + perturbations on centroids (the pyramid claim, on the mean)" + ); + } + + /// Graceful degradation: a quadrant centroid preserves its class's + /// DOMINANT semantic axis — the read an unknown-but-quadrant-resolvable + /// verb receives is still class-correct. + #[test] + fn quadrant_centroids_keep_the_class_signal() { + // Action×Simple: kausal dominates (Causes/Prevents/Transforms class). + let action = quadrant_prior(FamilyQuadrant::Action, TenseQuadrant::Simple); + assert!(action.kausal > action.temporal && action.kausal > action.modal); + // State×Simple: modal dominates. + let state = quadrant_prior(FamilyQuadrant::State, TenseQuadrant::Simple); + assert!(state.modal > state.temporal && state.modal > state.kausal); + // Change×Simple: temporal+modal high, kausal low. + let change = quadrant_prior(FamilyQuadrant::Change, TenseQuadrant::Simple); + assert!(change.temporal > change.kausal && change.modal > change.kausal); + } } diff --git a/crates/lance-graph-planner/examples/probe_eyes_opened.rs b/crates/lance-graph-planner/examples/probe_eyes_opened.rs index 7bd599e7c..6139733a4 100644 --- a/crates/lance-graph-planner/examples/probe_eyes_opened.rs +++ b/crates/lance-graph-planner/examples/probe_eyes_opened.rs @@ -53,9 +53,23 @@ //! ## Determinism + scope (honest) //! //! No LLM, no model, no RNG: catalogues (`clause_cues::{is_negation, -//! is_perception_verb, is_modal_aux, is_causal_cue via verb_lexicon}`), -//! the `verb_table` archetype consumer (`read_verb`), and one morphology -//! fallback (`-ed` action predicate). The extractor is COARSE by design — +//! is_modal_aux}`, `verb_lexicon::{is_causal_cue, is_copula}`), the +//! `verb_table` archetype consumers (`read_verb` for relations, +//! `epistemic_reading` for rung lifts — the RAILS-SHAPED condition: the +//! lift's condition AND force are 144-cell reads, never a membership bit), +//! and one morphology fallback (`-ed` action predicate). +//! +//! **B5 — awareness = blind × context (operator).** Each lift's quale = +//! the cell's tense-modulated modal prior (blind archetype: knowing/ +//! Abstracts 0.85 > seeing/Mirrors 0.70) × Staunen of the arena AT the +//! lift site (felt context; wonder = committed-contradiction tension). +//! Scene-scale: both factors independently order 3:6 below 3:7 (asserted). +//! Corpus-scale (measured, honest): field-MEAN staunen dilutes — at 106 +//! verses the early-arena entropy of 1:4 (0.089) outweighs 3:7's +//! two-contradiction wonder (0.065); means wash out events, so reflexivity +//! stays the corpus-scale crown and a LOCAL context measure (Δstaunen, +//! the shipped `Dissolution` step delta) is the pre-registered follow-up +//! probe — never tuned in post hoc. The extractor is COARSE by design — //! single-scene pronoun coreference (all personal pronouns → one discourse //! referent `they`; God/serpent/woman stay nouns), no conditionals, no //! object scoping ("eat" vs "eat-of-THE-tree" flatten to one statement — @@ -73,10 +87,14 @@ use std::collections::HashMap; use lance_graph_contract::grammar::clause_cues::{ - is_modal_aux, is_negation, is_perception_verb, pronoun_case, PronounCase, + is_modal_aux, is_negation, pronoun_case, PronounCase, +}; +use lance_graph_contract::grammar::verb_lexicon::{ + epistemic_reading, is_causal_cue, is_copula, read_verb, +}; +use lance_graph_planner::nars::{ + staunen, BeliefArena, CStmt, Copula, ReviseOutcome, Snapshot, Stamp, TruthValue, }; -use lance_graph_contract::grammar::verb_lexicon::{is_causal_cue, is_copula, read_verb}; -use lance_graph_planner::nars::{BeliefArena, CStmt, Copula, ReviseOutcome, Stamp, TruthValue}; /// The Genesis 1 control — affirmation-only creation narrative. Contains /// rung lifts ("God saw the light, that it was good") but NO negations, NO @@ -214,6 +232,17 @@ struct RungLift { knower: u16, verb: u16, object: u16, + /// The 144-cell's tense-modulated modal prior — the lift's BLIND + /// epistemic force (Abstracts/knew 0.85 > Mirrors/saw 0.70). + modal: f32, + /// The cell's one-byte Morton cascade address. + cell: u8, + /// Staunen of the arena AT the lift site — the felt CONTEXT + /// (0.5·truth_entropy + 0.5·wonder, wonder = committed-contradiction + /// tension). + staunen_at: f32, + /// Awareness quale = blind × context = modal × staunen_at. + quale: f32, self_referential: bool, } @@ -255,15 +284,16 @@ fn stream( let mut subject_is_pronoun = false; let mut armed = false; // copula/modal/aux/typed-verb armed a predicate let mut negated = false; - let mut await_that: Option<(u16, u16)> = None; // (knower, perception verb id) + // (knower, verb id, cell modal, cell address) — the 144 reading rides along. + let mut await_that: Option<(u16, u16, f32, u8)> = None; let mut await_budget: u8 = 0; // content tokens left before the wait expires - let mut lift_verb: Option<(u16, u16)> = None; // (knower, verb) — "that" seen - // Did the inner clause re-anchor its OWN subject after "that"? A - // dropped inner subject ("God saw that [it] was good") inherits the - // knower — inherited identity is NOT evidence of reflexivity. The - // real-corpus blind run measured this: without the overt-subject - // requirement, the Genesis 1 refrain produced five degenerate - // "self-referential" lifts; with it, 3:7 stands alone. + let mut lift_verb: Option<(u16, u16, f32, u8)> = None; // …after "that" is seen + // Did the inner clause re-anchor its OWN subject after "that"? A + // dropped inner subject ("God saw that [it] was good") inherits the + // knower — inherited identity is NOT evidence of reflexivity. The + // real-corpus blind run measured this: without the overt-subject + // requirement, the Genesis 1 refrain produced five degenerate + // "self-referential" lifts; with it, 3:7 stands alone. let mut inner_subject_seen = false; let mut causal_effect: Option = None; // effect predicate awaiting cause let mut last_pred: Option = None; // most recent emitted predicate @@ -312,10 +342,13 @@ fn stream( causal_effect = last_pred; continue; } - if is_perception_verb(&w) { + // Rails-shaped rung-lift gate: the verb must READ A 144 CELL + // (cue gate licenses the that-complement; the matrix supplies the + // reasoning — tense-modulated modal force + Morton address). + if let Some(er) = epistemic_reading(&w) { if let Some(s) = subject { let verb_id = intern.id(&w); - await_that = Some((s, verb_id)); + await_that = Some((s, verb_id, er.modal, er.cell)); await_budget = 3; // complementizer must be near } continue; @@ -377,7 +410,7 @@ fn stream( // passes (pass-2 admit_derived on an unchanged // derived statement is a no-op) so the stamp // sequence stays identical across passes. - if let Some((knower, verb)) = lift_verb.take() { + if let Some((knower, verb, modal, cell)) = lift_verb.take() { if let Some(inner) = arena.get(stmt) { let inner_truth = inner.truth; let inner_id = arena @@ -391,17 +424,45 @@ fn stream( cop: Copula::Rel(verb), p, }; + // Context BEFORE output (codex P1): the + // snapshot must precede admit_derived, else + // the modal-scaled meta-belief sits inside + // its own context factor and `modal` leaks + // into BOTH sides of quale = modal × staunen + // (and duplicate lifts become incomparable). + // The inner emission IS stream context; the + // meta-belief is the lift's own output. + let staunen_at = if pass2 { + 0.0 + } else { + staunen(&Snapshot::of(arena, 0.0)) + }; + // Cell-graded epistemic force: the meta-truth + // discount IS the 144 cell's tense-modulated + // modal prior — knowing (Abstracts, 0.85) + // lifts harder than seeing (Mirrors, 0.70), + // graded by the matrix, never a constant. let t = TruthValue::new( - inner_truth.frequency * 0.9, - inner_truth.confidence * 0.9, + inner_truth.frequency * modal, + inner_truth.confidence * modal, ); arena.admit_derived(meta, t, &[inner_id], 1); if !pass2 { + // Blind × context: the cell's modal + // (text-independent archetype) × the + // arena's Staunen AT the lift site + // (0.5·truth_entropy + 0.5·wonder; wonder + // = committed-contradiction tension — the + // felt stakes accumulated so far). out.lifts.push(RungLift { verse: verse.clone(), knower, verb, object: p, + modal, + cell, + staunen_at, + quale: modal * staunen_at, // Reflexive ONLY with an OVERT inner // subject: "they knew that THEY were // naked" — an inherited subject @@ -531,15 +592,19 @@ fn report(label: &str, verses: &[(String, String)]) -> (BeliefArena, Interner, R ); } - // B2 — rung lifts, reflexive vs not. - println!(" — B2 RUNG LIFTS (X knew/saw THAT …) —"); + // B2 — rung lifts, reflexive vs not, with the 144-cell reading + quale. + println!(" — B2 RUNG LIFTS (X knew/saw THAT …) — cell-graded, quale = modal × staunen —"); for l in &out.lifts { println!( - " {} {} —{}→ {} rung=1 {}", + " {} {} —{}[cell {:#04x}, modal {:.2}]→ {} staunen {:.3} quale {:.3} {}", l.verse, intern.name(l.knower), intern.name(l.verb), + l.cell, + l.modal, intern.name(l.object), + l.staunen_at, + l.quale, if l.self_referential { "SELF-REFERENTIAL ← the awareness signature" } else { @@ -764,6 +829,45 @@ fn main() { "Genesis 1 states no 'because' — no Impl edges" ); + // B5 — awareness = BLIND × CONTEXT (operator, 2026-07-28): the quale + // (cell modal × Staunen-at-lift) must crown the reflexive 3:7 lift. + // Both factors point the same way and BOTH are blind: the 144 grades + // knew (Abstracts, 0.85) above saw (Mirrors, 0.70), and 3:7 fires after + // BOTH reversals (die @3:4, eat @3:6) while 3:6's lift fires after only + // one — Adam's eyes open at the moment of maximal felt surprise. + let mut by_quale: Vec<&RungLift> = out.lifts.iter().collect(); + by_quale.sort_by(|a, b| b.quale.total_cmp(&a.quale)); + println!( + " B5 quale ranking: {:?}", + by_quale + .iter() + .map(|l| format!("{} {}={:.3}", l.verse, intern.name(l.verb), l.quale)) + .collect::>() + ); + let top = by_quale.first().expect("scene has lifts"); + assert!( + top.self_referential && top.verse == "3:7", + "the max-quale lift must be the reflexive 3:7 awareness, got {} (quale {:.3})", + top.verse, + top.quale + ); + // The context factor alone must ALSO order them (staunen at 3:7 > 3:6 — + // two held contradictions vs one), so the verdict never rests on the + // modal factor alone (that would make the quale decoration over B2). + let l37 = out.lifts.iter().find(|l| l.verse == "3:7").unwrap(); + let l36 = out.lifts.iter().find(|l| l.verse == "3:6").unwrap(); + assert!( + l37.staunen_at > l36.staunen_at, + "context factor must rise between 3:6 ({:.3}) and 3:7 ({:.3}) — the second \ + reversal (eat) landed in between", + l36.staunen_at, + l37.staunen_at + ); + assert!( + l37.modal > l36.modal, + "and the blind factor grades knew above saw" + ); + // B4: the hermeneutic circle converges — pass 2 changed NOTHING. println!( " B4 pass-2: scene admitted={} revised={}, control admitted={} revised={}",