From 63d425ed2f142ec5f0fe46ff9199ab782a558281 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 22:30:52 +0000 Subject: [PATCH 1/3] probe(planner): W7 -- the Antecedent chip is placed by BINDING, not recency W6 bound fixture-supplied (pronoun, antecedent) pairs -- it proved the write/escalate path, never the resolution. W7 supplies the two RESOLVERS over shared tagger-level features (gold read ONLY by assert arms) and makes them disagree on real KJV text. The operator's entropy-work ruling is the spec: a store must be effort on behalf of the thought after you; bookkeeping a better algorithm makes redundant is a joke pretending to be thinking. The mechanical form is the pull-test: pull the chip -- if a cheap resolver reconstructs the same answer everywhere it was decoration; if somewhere it produces a different, WRONG answer, the chip carried bits no better algorithm recomputes. Gates (probe_binding_not_heuristic.rs, all green + 4 unit tests): - B1 divergence -- Gen 3:1: the relative clause "which the LORD God had made" interposes; recency finds god@15 (d=-4, wrong), structural binding (relative-span skip + subject continuity) finds serpent@2 (gold). - B2 escalate-not-clamp -- the heuristic's wrong answer FITS the +-8 window (asserted: the temptation is real, storable, well-formed); binding's right answer is d=-17, so the binder ESCALATES and the nibble stays 0. Knowing when NOT to place a chip is itself the entropy work -- the joke-store would have been a syntactically perfect nibble pointing at the wrong god. - B3 stay-silent -- Gen 3:7: both resolvers agree with gold on both theys (chips -5, -3, distinct, nonzero). The divergence gate does not fire on everything. - B4 pull-test -- inner they@12 resolves its ultimate referent by following TWO stored nibbles (they@12 -> they@9 -> them@4 via resolves_to): chips COMPOSE, each a local warrant, no far verdict cached. Heuristic-only reconstruction fails on 3:1. Two load-bearing-annotation tests guard against fixture-supplies-the-answer: bare subject-continuity picks eyes@2 (NOT gold; the animacy check repairs it), and god@15 sits inside the relative span (the skip is what excludes it). Deleting either rule breaks a test. Board (same commit): EPIPHANIES E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1 -- canonizes the ruling, the warrant/verdict split (all 16 loci store pointers to evidence, never conclusions; even where the cheap value coincides, the chip carries the VERIFICATION), and the follow-ons: the quorum binder (the never-written Quorum/Contradiction slots and the measured Th(N*k) rescan of TD-LENS-QUORUM are one defect seen from two sides) and PROBE-RUNG-ELIGIBILITY (the pull-test is now its defined pass/fail). Exec-run record in exec-runs/w7-binding-not-heuristic.md. cargo run --example: ALL GATES GREEN (re-verified post-fmt). cargo test --example: 4/4. clippy -D warnings: clean. fmt: clean. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki --- .claude/board/EPIPHANIES.md | 20 + .../exec-runs/w7-binding-not-heuristic.md | 69 +++ .../examples/probe_binding_not_heuristic.rs | 431 ++++++++++++++++++ 3 files changed, 520 insertions(+) create mode 100644 .claude/board/exec-runs/w7-binding-not-heuristic.md create mode 100644 crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 189322d6..148d7abd 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,23 @@ +## 2026-07-30 — E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1 — W7 ran: the `Antecedent` chip is placed by BINDING, not recency — proven where the cheap resolver stores a well-formed wrong nibble and the binder refuses to store at all; the operator's entropy-work ruling becomes the mechanical pull-test + +**Status:** SHIPPED (probe `lance-graph-planner/examples/probe_binding_not_heuristic.rs`, 4 gates + 4 unit tests green, clippy `-D warnings` clean, fmt clean). **Confidence:** High on every asserted gate (fixture-pinned); the resolvers are deliberately COARSE (tagger-level features, two rules) — this is the falsifier for the CHIP, not a coreference system. + +**The operator's ruling (verbatim anchors, now canon):** *"if you're on a ladder you should make an effort on behalf of the thought after you"*; *"a little bookkeeping only takes a better algorithm to make it redundant and make it appear as a joke to pretend it was thinking"*; the chips image — the world throws *"space stations full of chips throwing data hoping it sticks"*, we place **data points where the entropy work is load-bearing**. The mechanical form is the **pull-test**: pull the chip — if a cheap resolver reconstructs the same answer everywhere, it was decoration; if somewhere the cheap resolver produces a *different, wrong* answer, the chip carried bits no better algorithm recomputes. + +**What W7 measured (real KJV, gold read only by assert arms — the honesty gap W6 left):** +- **B1 divergence (can-fire):** Gen 3:1 — the relative clause *"which the LORD God had made"* interposes; recency finds `god`@15 (d=−4, wrong), structural binding (relative-span skip + subject continuity) finds `serpent`@2 (d=−17, gold). The cheap resolver is wrong exactly where structure is doing work. +- **B2 escalate-not-clamp (the load-bearing REFUSAL):** the heuristic's wrong answer FITS the ±8 window — storable, well-formed, wrong. The binder escalates instead (nibble stays 0). **Knowing when NOT to place a chip is itself entropy work** — the joke-store would have been a syntactically perfect nibble pointing at the wrong god. +- **B3 stay-silent:** Gen 3:7 — both resolvers agree with gold on both `they`s (chips −5, −3, distinct, nonzero). The divergence gate does not fire on everything; a guard that always fires carries no information. +- **B4 pull-test + composition:** inner `they`@12 resolves its ultimate referent by following TWO stored nibbles — `they`@12 → `they`@9 → `them`@4 — via `resolves_to`, each chip a LOCAL warrant, no far verdict cached anywhere. Heuristic-only reconstruction fails on 3:1. **Der Gedanke als Lichtblitz, von verschiedenen Seiten reflektiert** — one flash, each chip a reflecting surface passing it on, no surface holding the whole light. + +**The warrant/verdict split is the general law this instantiates.** All 16 witness loci store i4 pointers-to-evidence, never cached conclusions. A warrant store cannot rot (the verdict is recomputed *through* it) and survives the better-algorithm test: even where a cheap resolver's VALUE coincides (3:7), the chip carries the *verification* — the next thought cannot know recency is trustworthy at 3:7 without running the structure that fails at 3:1. The chip stores the verified answer; the load it bears is the verification, not the guess. + +**The four receipts the operator anchored, one arc:** Horizontverschmelzung (B4 hermeneutic-circle termination + B6 both-halves-measured) is the jump to the intellectual tiers *auf der Schwelle zur Erkenntnis* — the Kant ablation showed the reader's category (knowing > seeing) is CONSTITUTIVE of the 3:7 crown; the Doppelspalt (Wittgenstein/Nietzsche/Hegel/Kant, four stances, one arena, invariant reflexive lift) — **ein Korpus als Quelle von Hermeneutik wird zum Kristall**; and W7 now places its chip exactly on that verge: the reflexive lift verse, bound by structure, refused where structure says refuse. + +**Remaining from the entropy-work audit (same ruling, next receipts):** the `Quorum`/`Contradiction` slots are designed and NEVER production-written while `quorum_mantissa_lens` rescans Θ(N·k) per graded row (`TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS`) — the empty slot and the measured debt are ONE defect seen from two sides; a quorum binder in W6/W7's shape retires both. Then `PROBE-RUNG-ELIGIBILITY` (still CONJECTURE in `zero-copy-lens-law.md`) now has its pass/fail: the pull-test, per locus. + +Cross-ref: `E-EYES-OPENED-PRINTS-BLIND-1` (the reflexive signature this binds), `E-FOUR-LIGHTS-ONE-CRYSTAL-1` (the crystal/Doppelspalt), `E-WHOLE-BOOK-WAVE-1` (63.3% beyond ±5 — why escalation is the architecture, not a limitation), `.claude/knowledge/zero-copy-lens-law.md` (the rung-test row this starts promoting), task #60 (W7), `.claude/board/exec-runs/w7-binding-not-heuristic.md`. + ## 2026-07-29 — E-A-CHEAP-PROXY-GETS-PUBLISHED-AS-THE-QUANTITY-IT-RESEMBLES-1 — the doc that named the same-identifier-grep anti-pattern in §9 committed it in §5 **Status:** SHIPPED — first edition merged as #870 (`a50299c`); correction pass merged as **#871** (`f91eeb6`), both on `main`. **Confidence:** High — all four corrections re-measured; two changed the document's conclusions, and the `lance-table` number was produced by a probe that had to leave the workspace to be honest. diff --git a/.claude/board/exec-runs/w7-binding-not-heuristic.md b/.claude/board/exec-runs/w7-binding-not-heuristic.md new file mode 100644 index 00000000..90812742 --- /dev/null +++ b/.claude/board/exec-runs/w7-binding-not-heuristic.md @@ -0,0 +1,69 @@ +# W7 — binding-not-heuristic falsifier — execution record + +## Files touched +- NEW: `crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs` + (only code file created; no core/contract change). +- Board: `EPIPHANIES.md` prepend (`E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1`), + this file. Same commit, per the board-hygiene rule. + +## What W7 closes that W6 left open +W6's binder took ALREADY-RESOLVED `(pronoun_pos, antecedent_pos)` fixture pairs +— it proved the write/escalate path, never the resolution. W7 supplies the two +RESOLVERS (cheap recency baseline vs. structural binding) over shared +tagger-level features, with gold annotations read ONLY by assert arms, and +makes them disagree on real KJV text. The operator's 2026-07-30 entropy-work +ruling is the spec: a store must be effort on behalf of the thought after you; +bookkeeping a better algorithm makes redundant is a joke pretending to be +thinking. Mechanical form: the pull-test. + +## Fixture honesty +- Features are what a POS tagger + chunker emits (POS, number, animacy, + relative spans, main-clause conjunctions, complementizers). No annotation + encodes an antecedent. +- The structural resolver COMPUTES from those features (R1 complement-subject + → matrix subject; R2 subject continuity with relative-span skip + animacy + repair). Two rules only — deliberately coarse; this falsifies the CHIP, it + is not a coreference system. +- Two load-bearing-annotation tests guard against fixture-supplies-the-answer: + `animacy_check_is_load_bearing` (bare R2 picks `eyes`@2, which is NOT gold) + and `relative_span_skip_is_load_bearing` (without the span, `god`@15 would + be clause-0 subject material). + +## Gates (all falsifiable, all green) +- **B1 divergence** — Gen 3:1: heuristic → `god`@15 (d=−4), binding → + `serpent`@2 (gold). Falsifier: resolvers agreeing, or recency being right. +- **B2 escalate-not-clamp** — heuristic's wrong answer FITS ±8 (the temptation + is real and asserted); binding's right answer is d=−17 → binder escalates, + nibble stays 0. Falsifier: a stored nibble (either clamped or cheap-wrong). +- **B3 stay-silent** — Gen 3:7: both resolvers == gold on both `they`s; chips + bound at −5 and −3 (distinct, nonzero — anti-vacuity). +- **B4 pull-test** — chip chain `they`@12 → `they`@9 → `them`@4 via + `resolves_to` (two nibble follows, no far verdict cached); heuristic-only + reconstruction fails on 3:1. Falsifier: chain not composing, or the cheap + resolver sufficing everywhere. + +## Verification +- `cargo run -p lance-graph-planner --example probe_binding_not_heuristic` + → ALL GATES GREEN (re-run after fmt: still green). +- `cargo test -p lance-graph-planner --example probe_binding_not_heuristic` + → 4/4. +- `cargo clippy -p lance-graph-planner --example probe_binding_not_heuristic + -- -D warnings` → clean (pre-existing unrelated `cognitive-shader-driver` + duplicate-bin-target warning only). +- `cargo fmt -p lance-graph-planner` → ran; gates re-verified green after. + +## Honest boundaries +- Escalation is side-band (the binder's return), not row state — a 0 nibble + alone is indistinguishable from never-attempted. Same boundary W6 recorded. +- The resolvers are two rules over annotated features; real-corpus coreference + lives in `probe_eyes_opened.rs` / deepnsm. W7's claim is exactly: the chip's + placement algorithm is structural, and its refusal on 3:1 is a choice + (the wrong answer was storable), not a range limitation. + +## Follow-ons surfaced (not done here) +- Quorum binder: `Locus::Quorum`/`Contradiction` slots are never + production-written while grading rescans Θ(N·k) + (`TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS`) — one defect, two views; W6/W7's + binder shape retires both. +- `PROBE-RUNG-ELIGIBILITY` (CONJECTURE row in `zero-copy-lens-law.md`): the + pull-test is now its defined pass/fail; run per locus. diff --git a/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs b/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs new file mode 100644 index 00000000..c962e713 --- /dev/null +++ b/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs @@ -0,0 +1,431 @@ +//! `probe_binding_not_heuristic` — W7: the falsifier W6 deferred. Prove the +//! `Locus::Antecedent` chip is placed by structural BINDING, not by a distance +//! heuristic — i.e. that the stored nibble carries bits a cheap algorithm +//! cannot recompute, so the chip bears load instead of decorating. +//! +//! **The operator's criterion (2026-07-30), which is this probe's spec:** a +//! store must be *effort on behalf of the thought after you*; bookkeeping that +//! a better algorithm makes redundant is "a joke to pretend it was thinking." +//! The pull-test follows: pull the chip — if a cheap resolver reconstructs the +//! same answer everywhere, the chip was decoration; if somewhere the cheap +//! resolver produces a *different, wrong* answer, the chip was load-bearing. +//! +//! **W6 bound fixture-supplied `(pronoun, antecedent)` pairs — it proved the +//! write path, not the resolution.** This probe supplies the two RESOLVERS and +//! makes them disagree on real KJV text: +//! +//! - **Heuristic** (the cheap baseline, deliberately strong): nearest +//! preceding number-agreeing referential token. This is the resolver a +//! "better algorithm makes it redundant" claim would deploy. +//! - **Binding** (structural): complement-clause subjects bind the MATRIX +//! subject (the reflexive signature from `E-EYES-OPENED-PRINTS-BLIND-1`); +//! main-clause subject pronouns bind the PREVIOUS main clause's subject, +//! skipping relative-clause material, with an animacy check against the +//! pronoun's own verb. +//! +//! Both resolvers read the same tagger-level token features (POS, number, +//! animacy, clause boundaries, relative spans, complementizers). Gold +//! annotations exist ONLY in the assert arms — neither resolver sees them, +//! which is exactly the honesty gap W6 left open. +//! +//! **The adversarial text is Gen 3:1**, where the relative clause *"which the +//! LORD God had made"* interposes between `serpent` and `he`: recency finds +//! `god` at in-window distance −4 (wrong); binding finds `serpent` at −17 — +//! **outside the ±8 chip range, so the binder ESCALATES rather than store +//! anything**. The chip's refusal is the load-bearing act: the cheap resolver +//! would have happily stored a well-formed, in-range, WRONG nibble. Gen 3:7 +//! supplies the stay-silent half (both resolvers agree on both `they`s) plus +//! the chip-composition payoff: inner `they`@12 → matrix `they`@9 → `them`@4 +//! resolves by following two stored nibbles — the chips COMPOSE, each carrying +//! its local warrant, never a cached far verdict. +//! +//! Escalation is side-band (a record, not row state): a `0` nibble alone reads +//! as *unbound*, indistinguishable from never-attempted — same honest boundary +//! W6 documented. +//! +//! Usage: `cargo run -p lance-graph-planner --example probe_binding_not_heuristic` + +use lance_graph_contract::canonical_node::{EdgeBlock, NodeGuid, NodeRow}; +use lance_graph_contract::causal_witness::{CausalWitnessFacet, Locus}; +use lance_graph_contract::witness_fabric::WitnessLens; + +/// Part-of-speech class at tagger granularity — the features both resolvers +/// share. Nothing here encodes an antecedent. +#[derive(Clone, Copy, PartialEq, Eq)] +enum Pos { + /// Referential nominal — an antecedent candidate. + Noun, + /// Referential pronoun — a candidate AND (possibly) a resolvable site. + Pron, + /// Verb. `animate` on a verb token means "requires an animate subject". + Verb, + /// Everything else (particles, adjectives, conjunctions, complementizers). + Other, +} + +/// One fixture token: surface features only (what a POS tagger + chunker +/// emits). `gold` is the referee's answer — read ONLY by assert arms. +struct Tok { + label: &'static str, + pos: Pos, + plural: bool, + /// Noun/Pron: referent animacy. Verb: requires an animate subject. + animate: bool, + /// Token sits inside a relative-clause span ("which … made"). + in_relative: bool, + /// Token is a conjunction opening a NEW main clause. + new_main: bool, + /// Token is a complementizer ("that") introducing a complement clause. + comp: bool, + /// Referee annotation for pronouns: the correct antecedent position. + gold: Option, +} + +impl Tok { + fn t(label: &'static str) -> Self { + Tok { + label, + pos: Pos::Other, + plural: false, + animate: false, + in_relative: false, + new_main: false, + comp: false, + gold: None, + } + } + fn noun(label: &'static str, plural: bool, animate: bool) -> Self { + Tok { + pos: Pos::Noun, + plural, + animate, + ..Tok::t(label) + } + } + fn pron(label: &'static str, plural: bool, gold: usize) -> Self { + Tok { + pos: Pos::Pron, + plural, + animate: true, + gold: Some(gold), + ..Tok::t(label) + } + } + fn verb(label: &'static str, requires_animate: bool) -> Self { + Tok { + pos: Pos::Verb, + animate: requires_animate, + ..Tok::t(label) + } + } + fn conj(label: &'static str) -> Self { + Tok { + new_main: true, + ..Tok::t(label) + } + } + fn rel(mut self) -> Self { + self.in_relative = true; + self + } + fn is_candidate(&self) -> bool { + matches!(self.pos, Pos::Noun | Pos::Pron) + } +} + +/// Gen 3:1 (KJV, lowercased, trimmed): *"now the serpent was more subtil than +/// any beast of the field which the LORD God had made: and he said unto the +/// woman"*. The relative span covers "which … made". Gold: `he`@19 → serpent@2. +fn genesis_3_1() -> Vec { + vec![ + Tok::t("now"), // 0 + Tok::t("the"), // 1 + Tok::noun("serpent", false, true), // 2 + Tok::verb("was", false), // 3 + Tok::t("more"), // 4 + Tok::t("subtil"), // 5 + Tok::t("than"), // 6 + Tok::t("any"), // 7 + Tok::noun("beast", false, true), // 8 + Tok::t("of"), // 9 + Tok::t("the"), // 10 + Tok::noun("field", false, false), // 11 + Tok::t("which").rel(), // 12 + Tok::t("the").rel(), // 13 + Tok::t("lord").rel(), // 14 + Tok::noun("god", false, true).rel(), // 15 + Tok::t("had").rel(), // 16 + Tok::verb("made", false).rel(), // 17 + Tok::conj("and"), // 18 + Tok::pron("he", false, 2), // 19 → serpent@2 (d = -17) + Tok::verb("said", true), // 20 + Tok::t("unto"), // 21 + Tok::t("the"), // 22 + Tok::noun("woman", false, true), // 23 + ] +} + +/// Gen 3:7 (KJV, lowercased, trimmed): *"and the eyes of them both were +/// opened, and they knew that they were naked"*. Gold: matrix `they`@9 → +/// `them`@4 (the pair, not the eyes); inner `they`@12 → matrix `they`@9 (the +/// reflexive signature — knower == overt inner subject). +fn genesis_3_7() -> Vec { + vec![ + Tok::t("and"), // 0 + Tok::t("the"), // 1 + Tok::noun("eyes", true, false), // 2 (plural, inanimate) + Tok::t("of"), // 3 + Tok::noun("them", true, true), // 4 (referential pronoun-as-candidate) + Tok::t("both"), // 5 + Tok::verb("were", false), // 6 + Tok::verb("opened", false), // 7 + Tok::conj("and"), // 8 + Tok::pron("they", true, 4), // 9 → them@4 (d = -5) + Tok::verb("knew", true), // 10 (knowing requires an animate subject) + Tok { + comp: true, + ..Tok::t("that") + }, // 11 + Tok::pron("they", true, 9), // 12 → matrix they@9 (d = -3) + Tok::verb("were", false), // 13 + Tok::t("naked"), // 14 + ] +} + +/// The cheap baseline: nearest preceding number-agreeing referential token. +/// Deliberately ignores clause structure and animacy — that IS its cheapness. +fn heuristic_resolve(toks: &[Tok], p: usize) -> Option { + (0..p) + .rev() + .find(|&i| toks[i].is_candidate() && toks[i].plural == toks[p].plural) +} + +/// Main-clause id per token (increments at each `new_main` conjunction). +fn clause_of(toks: &[Tok], i: usize) -> usize { + toks[..=i].iter().filter(|t| t.new_main).count() +} + +/// The subject of main clause `k`: its first candidate token outside any +/// relative span. +fn subject_of_clause(toks: &[Tok], k: usize) -> Option { + (0..toks.len()) + .find(|&i| clause_of(toks, i) == k && toks[i].is_candidate() && !toks[i].in_relative) +} + +/// The structural resolver. Two rules, both computed from features: +/// +/// - **R1 (complement subject):** a pronoun immediately after a +/// complementizer binds the subject of the clause whose verb takes the +/// complement (the matrix subject) — the reflexive signature. +/// - **R2 (subject continuity, animacy-checked):** a subject pronoun opening +/// a main clause binds the previous main clause's subject — unless the +/// pronoun's own verb requires an animate subject and that subject is +/// inanimate, in which case it binds the nearest preceding number-agreeing +/// ANIMATE candidate. +fn structural_resolve(toks: &[Tok], p: usize) -> Option { + // R1: complement-clause subject → matrix subject. + if p > 0 && toks[p - 1].comp { + let matrix_verb = (0..p - 1).rev().find(|&i| toks[i].pos == Pos::Verb)?; + return subject_of_clause(toks, clause_of(toks, matrix_verb)); + } + // R2: subject pronoun of main clause k → subject of clause k-1. + let k = clause_of(toks, p); + if k == 0 { + return None; + } + let prev_subj = subject_of_clause(toks, k - 1)?; + let own_verb = (p + 1..toks.len()).find(|&i| toks[i].pos == Pos::Verb); + let needs_animate = own_verb.is_some_and(|v| toks[v].animate); + if needs_animate && !toks[prev_subj].animate { + // Animacy repair: nearest preceding number-agreeing animate candidate. + return (0..p).rev().find(|&i| { + toks[i].is_candidate() && toks[i].plural == toks[p].plural && toks[i].animate + }); + } + Some(prev_subj) +} + +/// W6's binder semantics, verbatim: in-range displacement binds the nibble; +/// `0` or out-of-`±8` escalates — the row stays unbound, never clamped. +fn bind(rows: &mut [NodeRow], pronoun: usize, target: usize) -> Result { + let d = target as isize - pronoun as isize; + if d == 0 || !(-8..=7).contains(&d) { + return Err(d); + } + let facet = CausalWitnessFacet::ZERO.with(Locus::Antecedent, d as i8); + WitnessLens::write_register(&mut rows[pronoun], &facet); + Ok(d as i8) +} + +fn fresh_rows(n: usize) -> Vec { + (0..n) + .map(|i| NodeRow { + key: NodeGuid::local(i as u32), + edges: EdgeBlock::default(), + value: [0u8; 480], + }) + .collect() +} + +fn main() { + let mut green = true; + let mut gate = |name: &str, pass: bool, detail: String| { + println!("[{}] {name} — {detail}", if pass { "PASS" } else { "FAIL" }); + green &= pass; + }; + + // ── Fixture A: Gen 3:1 — the divergence text ───────────────────────────── + let a = genesis_3_1(); + let he = 19; + let h_a = heuristic_resolve(&a, he); + let s_a = structural_resolve(&a, he); + + // B1 — can-fire: the resolvers genuinely disagree, and gold sides with + // binding. Falsifier: agreement, or the heuristic being right. + gate( + "B1 divergence", + h_a == Some(15) && s_a == Some(2) && a[he].gold == Some(2) && h_a != s_a, + format!( + "heuristic(he@19) = {:?} ({}), binding = {:?} ({}), gold = serpent@2", + h_a, + h_a.map_or("-", |i| a[i].label), + s_a, + s_a.map_or("-", |i| a[i].label), + ), + ); + + // B2 — the temptation is real, and the chip refuses it. The heuristic's + // wrong answer FITS the ±8 window (d = -4, storable); the structural + // answer does not (d = -17) — so the binder must escalate, leaving the + // nibble unbound rather than storing either a clamped or a cheap value. + let mut rows_a = fresh_rows(a.len()); + let heuristic_d = 15_isize - he as isize; + let bound = bind(&mut rows_a, he, s_a.unwrap()); + let lens_a = WitnessLens::new(&rows_a); + let nibble = lens_a.at(he).map(|f| f.at(Locus::Antecedent)); + gate( + "B2 escalate-not-clamp", + (-8..=7).contains(&heuristic_d) && bound == Err(-17) && nibble == Some(0), + format!( + "heuristic d={heuristic_d} (in-window, storable-but-wrong), binding d=-17 → escalated, nibble={nibble:?}" + ), + ); + + // ── Fixture B: Gen 3:7 — the stay-silent text + chip composition ───────── + let b = genesis_3_7(); + let (matrix, inner) = (9, 12); + let mut rows_b = fresh_rows(b.len()); + let mut agree = true; + let mut displacements = Vec::new(); + for &p in &[matrix, inner] { + let h = heuristic_resolve(&b, p); + let s = structural_resolve(&b, p); + agree &= h == s && s == b[p].gold; + if let Some(t) = s { + if let Ok(d) = bind(&mut rows_b, p, t) { + displacements.push(d); + } + } + } + + // B3 — can-stay-silent: on the reflexive verse both resolvers agree with + // gold and with each other; the divergence gate does not fire on + // everything (a guard that always fires carries no information). The two + // chips hold distinct nonzero displacements (anti-vacuity). + gate( + "B3 stay-silent", + agree && displacements == vec![-5, -3], + format!("both they@9/they@12 agree across resolvers; chips = {displacements:?}"), + ); + + // B4 — the pull-test, both directions. WITH chips: the inner pronoun's + // ultimate referent resolves by following two stored nibbles + // (they@12 → they@9 → them@4) — each chip a local warrant, composed, no + // far verdict cached anywhere. WITHOUT chips (heuristic-only + // reconstruction over both fixtures): Gen 3:7 survives, Gen 3:1 comes + // back wrong — the chip carried exactly the bits recency cannot recompute. + let lens_b = WitnessLens::new(&rows_b); + let hop1 = lens_b + .at(inner) + .and_then(|f| f.resolves_to(Locus::Antecedent, inner, lens_b.len())); + let hop2 = hop1.and_then(|p| { + lens_b + .at(p) + .and_then(|f| f.resolves_to(Locus::Antecedent, p, lens_b.len())) + }); + let heuristic_wrong_somewhere = heuristic_resolve(&a, he) != a[he].gold; + gate( + "B4 pull-test", + hop1 == Some(matrix) && hop2 == Some(4) && heuristic_wrong_somewhere, + format!( + "chip chain they@12 → {:?} → {:?} (gold them@4); heuristic-only reconstruction fails on 3:1", + hop1, hop2 + ), + ); + + println!(); + if green { + println!("ALL GATES GREEN"); + } else { + println!("GATES FAILED"); + std::process::exit(1); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// The probe's own gates, runnable under `cargo test --example`. + #[test] + fn divergence_fires_on_3_1_and_stays_silent_on_3_7() { + let a = genesis_3_1(); + assert_eq!(heuristic_resolve(&a, 19), Some(15), "recency finds god"); + assert_eq!(structural_resolve(&a, 19), Some(2), "binding finds serpent"); + assert_eq!(a[19].gold, Some(2)); + + let b = genesis_3_7(); + for p in [9, 12] { + assert_eq!(heuristic_resolve(&b, p), structural_resolve(&b, p)); + assert_eq!(structural_resolve(&b, p), b[p].gold); + } + } + + /// Deleting the animacy check must break 3:7's matrix resolution (the + /// rule is load-bearing, not decoration): without it, R2 returns the + /// previous clause's subject verbatim — `eyes`@2, which is wrong. + #[test] + fn animacy_check_is_load_bearing() { + let b = genesis_3_7(); + let k = clause_of(&b, 9); + let bare_r2 = subject_of_clause(&b, k - 1); + assert_eq!(bare_r2, Some(2), "bare subject-continuity picks eyes@2"); + assert_ne!(bare_r2, b[9].gold, "…which is NOT the gold answer"); + assert_eq!(structural_resolve(&b, 9), b[9].gold, "the check repairs it"); + } + + /// The relative-clause skip must be load-bearing on 3:1: if `god`@15 + /// counted as a main-clause subject, R2 would bind it. The fixture pins + /// that `god` is inside the relative span and the clause-0 subject is + /// `serpent`. + #[test] + fn relative_span_skip_is_load_bearing() { + let a = genesis_3_1(); + assert!(a[15].in_relative, "god sits inside the relative clause"); + assert_eq!( + subject_of_clause(&a, 0), + Some(2), + "clause-0 subject = serpent" + ); + } + + /// Out-of-window escalation leaves the nibble unbound — never a clamp. + #[test] + fn escalation_leaves_nibble_unbound() { + let a = genesis_3_1(); + let mut rows = fresh_rows(a.len()); + assert_eq!(bind(&mut rows, 19, 2), Err(-17)); + let lens = WitnessLens::new(&rows); + assert_eq!(lens.at(19).map(|f| f.at(Locus::Antecedent)), Some(0)); + } +} From b9160f86ac3243384722b72e65e826d9d9460db2 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 22:41:30 +0000 Subject: [PATCH 2/3] probe(planner): W7 hardening -- review fixes + the quorum ruling canonized Review round (codex 2 findings + CodeRabbit 7 comments), all verified against the code before acting: 1. Gold TYPE-SEPARATED from resolver input (codex #1, CodeRabbit x3): Tok no longer carries a gold field; fixtures return (Vec, Gold) with the referee's pairs in a separate list read only by assert arms. A future toks[p].gold shortcut is now a compile error -- closed by the type system, strictly stronger than the suggested invariance test. 2. B2 exercises the BINDER with the tempting target (codex #2, CodeRabbit x2): binding god@15 into scratch rows asserts Ok(-4) AND stored nibble -4 -- "storable-but-wrong" proven at the binder, not by re-deriving its range predicate in the gate. New test binder_accepts_the_tempting_wrong_target. 3. The relative-span "load-bearing" test was VACUOUS (codex P2, CodeRabbit Major) -- confirmed: subject selection scans forward and English is head-first, so serpent@2 wins with or without the filter; the claim was false for that rule. Replaced with the honest pair: clause_segmentation_is_load_bearing (erase the "and" boundary -> structural resolution FAILS entirely -- the true 3:1 counterfactual) and relative_span_filter_can_fire (synthetic clause whose FIRST candidate is in-relative -- the filter demonstrably changes the outcome vs the unfiltered pick). Doc comment corrected to say what actually bears load. 4. The pull-test had no DIVERGENT stored chip (codex P1) -- confirmed: 3:1 escalates (no chip) and 3:7's chips coincide with the heuristic, so stored state was entirely heuristic-reconstructible. Added the constructed in-range interposition fixture ("the man which the boy saw slept, and he smiled" -- labelled built-English, not KJV): recency -> boy (d=-4, wrong), binding -> man (d=-7, gold, BINDS). New gate B4 asserts the STORED nibble differs from the heuristic reconstruction -- the divergence now lives in stored state; composition renumbered B5. New test divergent_chip_differs_from_heuristic_reconstruction. 5. EPIPHANIES wording fixed pre-merge (CodeRabbit Minor): the chip stores the POINTER the verification selected, never "the verified answer" -- pointer-not-answer kept consistent throughout. Declined with reasons (exec-run addendum): workspace-wide fmt/clippy sweep (repo practice is scoped -p; all-features is the known TD-LANCE-GRAPH-ALL-FEATURES-DELTA-BREAK surface); methods-on-carrier nitpick (the carrier litmus targets cognitive state carriers, not probe fixtures). OPERATOR RULING canonized (EPIPHANIES prepend, E-64K-THOUGHTS-DONT-DO-QUORUM-PLASTICITY-BREATHES-FROM-TENSION-1): the 64k parallel thoughts do NOT do quorum -- the i4 mantissa was never sized for counterfactual agreement; inconsistency is plasticity's work; contradictions are the substrate's fuel, preserved, never voted away; linguistic tension = magnitude of expressivity (W7's stored -7 vs recency's -4 is that quantity in one nibble); NARS breathes from these tensions; and the honesty line runs between EPISODIC causality (stream order) and EPISTEMIC causality (warrant) -- recency IS the episodic proxy whose failure the divergence gates measure. The quorum-binder follow-on from E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1 is withdrawn in place (pre-merge correction); TD-LENS-QUORUM survives as scan-cost debt only. Hermeneutik ladder ordering recorded: Gadamer first, the four stances (Kant/Wittgenstein/Nietzsche/Hegel) next. Gates: 5/5 green (B1-B5). Tests: 7/7. clippy -D warnings clean (one map_identity of my own making, fixed). fmt clean, gates re-verified after. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki --- .claude/board/EPIPHANIES.md | 30 +- .../exec-runs/w7-binding-not-heuristic.md | 48 +++ .../examples/probe_binding_not_heuristic.rs | 306 +++++++++++++----- 3 files changed, 308 insertions(+), 76 deletions(-) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 148d7abd..63c3bd79 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,20 +1,44 @@ +## 2026-07-30 — E-64K-THOUGHTS-DONT-DO-QUORUM-PLASTICITY-BREATHES-FROM-TENSION-1 — operator ruling: the 64k parallel thoughts do NOT do quorum; inconsistency is plasticity's work; contradictions are the substrate's fuel; and the honesty line runs between EPISODIC and EPISTEMIC causality + +**Status:** OPERATOR-RULED (mid-W7-review, verbatim anchors below). **Confidence:** High as a direction ruling; consequences applied same-commit (the quorum-binder recommendation in `E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1` is withdrawn in place, pre-merge). + +**The verbatim anchors, in arrival order:** +1. *"Quorum suggests we don't have mantissa to hold counterfactual. Our inconsistencies don't lie in quorum. We have 64k thoughts in parallel. They don't do quorum. That's plasticity doing its work."* +2. *"Contradictions is what our substrate thrives on."* +3. *"That's linguistic tension, magnitude of expressivity."* +4. *"Our NARS breathes from these tensions."* +5. *"We just need to be honest between episodic causality, or epistemic causality."* +6. *"Gadamer ist the first step, Kant Wittgenstein Nietzsche and Hegel the next."* + +**What this rules out.** The entropy-work audit had proposed a QUORUM BINDER — write `Locus::Quorum`/`Contradiction` pointers at ingest so grading follows pointers instead of rescanning Θ(N·k) (`TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS`). Withdrawn: that reading treats slot 14 as a consensus mechanism, and the substrate has none. The i4 mantissa was never sized to hold counterfactual agreement state because agreement is not what reconciles the 64k threads — each thought adapts (plasticity tenant, NARS revision) rather than polling its peers. The tech-debt entry survives as SCAN-COST debt; its eventual fix must not smuggle in voting. + +**What this rules in — the slots' honest semantics.** `Quorum` = an OBSERVATION pointer (the window event whose reading matched mine — a fact about the past, episodic), never a mechanism. `Contradiction` = the PRESERVED dissenting peer (Staunen×Wisdom depth) — per the standing doctrine *"opinions are committed contradictions preserved, not resolved."* Contradiction is not an error state awaiting cleanup; it is the free-energy gradient the NARS engine breathes from — no tension, no surprise, no thinking (the shader "can't NOT think while surprise exists"). + +**Linguistic tension = magnitude of expressivity, now measured in one nibble.** W7's divergent chip (stored −7 vs recency's −4 on the interposition fixture) is the same quantity the Babel residual measures at lane scale (1 − amplitude = expressiveness escaping the coordinate system): the gap between what a cheap model can address and what the structure actually says. The chips worth placing sit exactly on these tensions — where the cheap reconstruction and the structural read disagree is where a stored bit carries irreplaceable information, and where they agree the verification (not the value) is the load. + +**The honesty line: episodic vs epistemic causality.** Episodic = what happened, in stream order (Lance versions, `temporal.rs`, "A preceded B"). Epistemic = what grounds belief (the warrant chain, "A is why B is held"). Recency IS episodic proximity deployed as an epistemic proxy — and W7's divergence gates measure precisely where that proxy lies (3:1: the episodically-nearest candidate is not the epistemic ground). The witness register's offsets are episodic ADDRESSES carrying epistemic MEANING; conflating the two axes is the category error this ruling fences. Same fence, corpus scale: `E-WHOLE-BOOK-REASONING-RUN-1`'s caveat — `is_a(god, light)` stores episodic adjacency wearing epistemic inheritance's label. + +**The hermeneutik ladder ordering (stone 3 of the operator's three Rosetta stones):** Gadamer (Horizontverschmelzung — the fusion, B4's circle-termination + B6's both-halves-measured) is the FIRST step, the entry to Erkenntnis; the four-stance panel (Kant a-priori / Wittgenstein Aspektsehen / Nietzsche genealogy / Hegel dialectic) is the NEXT — differentiated reads only possible after fusion. One corpus as crystal, thought as Lichtblitz reflected surface to surface, no surface holding the whole light. + +Cross-ref: `E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1` (corrected in place, same PR), `E-FOUR-LIGHTS-ONE-CRYSTAL-1`, `E-WHOLE-BOOK-REASONING-RUN-1`, `TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS` (re-scoped: scan-cost only), CLAUDE.md § "Meaning = AriGraph facts + resonance + magnitude" (contradictions preserved, not resolved). + ## 2026-07-30 — E-A-CHIP-BEARS-LOAD-OR-IT-IS-A-JOKE-1 — W7 ran: the `Antecedent` chip is placed by BINDING, not recency — proven where the cheap resolver stores a well-formed wrong nibble and the binder refuses to store at all; the operator's entropy-work ruling becomes the mechanical pull-test **Status:** SHIPPED (probe `lance-graph-planner/examples/probe_binding_not_heuristic.rs`, 4 gates + 4 unit tests green, clippy `-D warnings` clean, fmt clean). **Confidence:** High on every asserted gate (fixture-pinned); the resolvers are deliberately COARSE (tagger-level features, two rules) — this is the falsifier for the CHIP, not a coreference system. **The operator's ruling (verbatim anchors, now canon):** *"if you're on a ladder you should make an effort on behalf of the thought after you"*; *"a little bookkeeping only takes a better algorithm to make it redundant and make it appear as a joke to pretend it was thinking"*; the chips image — the world throws *"space stations full of chips throwing data hoping it sticks"*, we place **data points where the entropy work is load-bearing**. The mechanical form is the **pull-test**: pull the chip — if a cheap resolver reconstructs the same answer everywhere, it was decoration; if somewhere the cheap resolver produces a *different, wrong* answer, the chip carried bits no better algorithm recomputes. -**What W7 measured (real KJV, gold read only by assert arms — the honesty gap W6 left):** +**What W7 measured (real KJV; gold TYPE-SEPARATED from resolver input — fixtures return `(Vec, gold pairs)` and `Tok` carries no gold field, so a resolver shortcut is a compile error, closing the honesty gap W6 left structurally, per codex/CodeRabbit review on the PR):** - **B1 divergence (can-fire):** Gen 3:1 — the relative clause *"which the LORD God had made"* interposes; recency finds `god`@15 (d=−4, wrong), structural binding (relative-span skip + subject continuity) finds `serpent`@2 (d=−17, gold). The cheap resolver is wrong exactly where structure is doing work. - **B2 escalate-not-clamp (the load-bearing REFUSAL):** the heuristic's wrong answer FITS the ±8 window — storable, well-formed, wrong. The binder escalates instead (nibble stays 0). **Knowing when NOT to place a chip is itself entropy work** — the joke-store would have been a syntactically perfect nibble pointing at the wrong god. - **B3 stay-silent:** Gen 3:7 — both resolvers agree with gold on both `they`s (chips −5, −3, distinct, nonzero). The divergence gate does not fire on everything; a guard that always fires carries no information. - **B4 pull-test + composition:** inner `they`@12 resolves its ultimate referent by following TWO stored nibbles — `they`@12 → `they`@9 → `them`@4 — via `resolves_to`, each chip a LOCAL warrant, no far verdict cached anywhere. Heuristic-only reconstruction fails on 3:1. **Der Gedanke als Lichtblitz, von verschiedenen Seiten reflektiert** — one flash, each chip a reflecting surface passing it on, no surface holding the whole light. -**The warrant/verdict split is the general law this instantiates.** All 16 witness loci store i4 pointers-to-evidence, never cached conclusions. A warrant store cannot rot (the verdict is recomputed *through* it) and survives the better-algorithm test: even where a cheap resolver's VALUE coincides (3:7), the chip carries the *verification* — the next thought cannot know recency is trustworthy at 3:7 without running the structure that fails at 3:1. The chip stores the verified answer; the load it bears is the verification, not the guess. +**The warrant/verdict split is the general law this instantiates.** All 16 witness loci store i4 pointers-to-evidence, never cached conclusions. A warrant store cannot rot (the verdict is recomputed *through* it) and survives the better-algorithm test: even where a cheap resolver's VALUE coincides (3:7), the chip carries the *verification* — the next thought cannot know recency is trustworthy at 3:7 without running the structure that fails at 3:1. The chip stores the POINTER the verification selected; the answer is recomputed through it — the load it bears is the verification, never a cached guess. **The four receipts the operator anchored, one arc:** Horizontverschmelzung (B4 hermeneutic-circle termination + B6 both-halves-measured) is the jump to the intellectual tiers *auf der Schwelle zur Erkenntnis* — the Kant ablation showed the reader's category (knowing > seeing) is CONSTITUTIVE of the 3:7 crown; the Doppelspalt (Wittgenstein/Nietzsche/Hegel/Kant, four stances, one arena, invariant reflexive lift) — **ein Korpus als Quelle von Hermeneutik wird zum Kristall**; and W7 now places its chip exactly on that verge: the reflexive lift verse, bound by structure, refused where structure says refuse. -**Remaining from the entropy-work audit (same ruling, next receipts):** the `Quorum`/`Contradiction` slots are designed and NEVER production-written while `quorum_mantissa_lens` rescans Θ(N·k) per graded row (`TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS`) — the empty slot and the measured debt are ONE defect seen from two sides; a quorum binder in W6/W7's shape retires both. Then `PROBE-RUNG-ELIGIBILITY` (still CONJECTURE in `zero-copy-lens-law.md`) now has its pass/fail: the pull-test, per locus. +**Remaining from the entropy-work audit — ⊘ CORRECTED same day, before merge:** this entry's first draft recommended "a quorum binder in W6/W7's shape" for the never-production-written `Quorum`/`Contradiction` slots. **The operator overruled the direction** (see `E-64K-THOUGHTS-DONT-DO-QUORUM-PLASTICITY-BREATHES-FROM-TENSION-1`, same day): the 64k parallel thoughts don't do quorum; inconsistency is plasticity's work; contradictions are fuel, preserved, never voted away. `TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS` stays filed as scan-cost debt, but its fix is NOT consensus wiring. What survives of this paragraph: `PROBE-RUNG-ELIGIBILITY` (still CONJECTURE in `zero-copy-lens-law.md`) now has its pass/fail — the pull-test, per locus. Cross-ref: `E-EYES-OPENED-PRINTS-BLIND-1` (the reflexive signature this binds), `E-FOUR-LIGHTS-ONE-CRYSTAL-1` (the crystal/Doppelspalt), `E-WHOLE-BOOK-WAVE-1` (63.3% beyond ±5 — why escalation is the architecture, not a limitation), `.claude/knowledge/zero-copy-lens-law.md` (the rung-test row this starts promoting), task #60 (W7), `.claude/board/exec-runs/w7-binding-not-heuristic.md`. diff --git a/.claude/board/exec-runs/w7-binding-not-heuristic.md b/.claude/board/exec-runs/w7-binding-not-heuristic.md index 90812742..a02ff333 100644 --- a/.claude/board/exec-runs/w7-binding-not-heuristic.md +++ b/.claude/board/exec-runs/w7-binding-not-heuristic.md @@ -67,3 +67,51 @@ thinking. Mechanical form: the pull-test. binder shape retires both. - `PROBE-RUNG-ELIGIBILITY` (CONJECTURE row in `zero-copy-lens-law.md`): the pull-test is now its defined pass/fail; run per locus. + +## Post-review hardening (codex 2 findings + CodeRabbit 7 comments, same PR) + +- **Gold type-separated (codex #1, CodeRabbit ×3):** `Tok` no longer carries a + `gold` field; fixtures return `(Vec, Gold)` where `Gold` is a separate + `(pronoun_pos, antecedent_pos)` list read only by assert arms. A future + `toks[p].gold` shortcut is now a COMPILE ERROR — closed by type, not + convention (strictly stronger than the suggested invariance test). +- **B2 exercises the binder (codex #2, CodeRabbit ×2):** the heuristic's wrong + target is bound into scratch rows; the gate asserts `Ok(-4)` AND stored + nibble `-4` — "storable-but-wrong" proven at the binder, not by re-deriving + its range predicate. New unit test `binder_accepts_the_tempting_wrong_target`. +- **Relative-span test was VACUOUS (codex P2, CodeRabbit Major):** confirmed — + `subject_of_clause` scans forward and English is head-first, so `serpent`@2 + wins with or without the filter; the old "load-bearing" claim was false for + this rule. Replaced with the honest pair: + `clause_segmentation_is_load_bearing` (erase the `and` boundary → + resolution FAILS — the true 3:1 counterfactual) and + `relative_span_filter_can_fire` (synthetic clause where the first candidate + is in-relative — filter changes the outcome, asserted against the + unfiltered pick). The earlier claim in this file's "Fixture honesty" section + is superseded by this addendum. +- **Pull-test had no divergent STORED chip (codex P1):** confirmed — 3:1 + escalates (no chip) and 3:7's chips match the heuristic, so stored state was + entirely heuristic-reconstructible. Added the constructed in-range + interposition fixture ("the man which the boy saw slept, and he smiled", + labelled built-English, not KJV): recency → boy (d=−4), binding → man + (d=−7, gold, BINDS). New gate B4 asserts the STORED nibble (−7) differs + from the heuristic reconstruction (−4); old composition gate renumbered B5. + New unit test `divergent_chip_differs_from_heuristic_reconstruction`. +- **EPIPHANIES wording (CodeRabbit Minor):** "chip stores the verified answer" + → "stores the POINTER the verification selected; the answer is recomputed + through it" — pointer-not-answer kept consistent. +- **Declined, with reasons:** workspace-wide `cargo fmt --all` / `clippy + --all-targets --all-features` (repo practice is scoped `-p` runs — a + workspace-wide sweep would touch unrelated crates/files and the + all-features build is the known `TD-LANCE-GRAPH-ALL-FEATURES-DELTA-BREAK` + surface); methods-on-carrier nitpick (the carrier litmus targets cognitive + state carriers, not probe fixtures — two flat resolver functions keep the + falsifier legible; noted, not a doctrine violation). +- **Operator ruling landed mid-review** (see + `E-64K-THOUGHTS-DONT-DO-QUORUM-PLASTICITY-BREATHES-FROM-TENSION-1`): the + quorum-binder follow-on this file proposed is WITHDRAWN — 64k thoughts + don't do quorum; plasticity does that work; contradictions are fuel. + `TD-LENS-QUORUM` survives as scan-cost debt only. + +Re-verified after all changes: 5 gates green (B1–B5), 7 unit tests green, +clippy `-D warnings` clean, fmt clean. diff --git a/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs b/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs index c962e713..ae5877b6 100644 --- a/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs +++ b/crates/lance-graph-planner/examples/probe_binding_not_heuristic.rs @@ -25,19 +25,39 @@ //! //! Both resolvers read the same tagger-level token features (POS, number, //! animacy, clause boundaries, relative spans, complementizers). Gold -//! annotations exist ONLY in the assert arms — neither resolver sees them, -//! which is exactly the honesty gap W6 left open. +//! annotations are TYPE-SEPARATED from resolver input (CodeRabbit hardening on +//! this PR): fixtures return `(Vec, gold pairs)`, and `Tok` carries no +//! gold field at all — a future `toks[p].gold` shortcut is a compile error, +//! not a convention. This closes the honesty gap W6 left open structurally. //! -//! **The adversarial text is Gen 3:1**, where the relative clause *"which the -//! LORD God had made"* interposes between `serpent` and `he`: recency finds -//! `god` at in-window distance −4 (wrong); binding finds `serpent` at −17 — -//! **outside the ±8 chip range, so the binder ESCALATES rather than store -//! anything**. The chip's refusal is the load-bearing act: the cheap resolver -//! would have happily stored a well-formed, in-range, WRONG nibble. Gen 3:7 -//! supplies the stay-silent half (both resolvers agree on both `they`s) plus -//! the chip-composition payoff: inner `they`@12 → matrix `they`@9 → `them`@4 -//! resolves by following two stored nibbles — the chips COMPOSE, each carrying -//! its local warrant, never a cached far verdict. +//! **Three fixtures, three roles** (the third added after codex's P1 on this +//! PR, which caught that the original two left the pull-test's stored state +//! heuristic-reconstructible): +//! +//! - **Gen 3:1** — the refusal text: recency finds `god` at in-window distance +//! −4 (wrong); binding finds `serpent` at −17 — **outside the ±8 chip range, +//! so the binder ESCALATES rather than store anything**. The refusal is a +//! choice, not a range limitation: B2 proves the binder ACCEPTS the tempting +//! wrong target on scratch rows. +//! - **A constructed in-range interposition** (*"the man which the boy saw +//! slept, and he smiled"* — built English, labelled as such, not KJV): both +//! answers are in-window, they DIVERGE (recency → `boy`@−4 wrong, binding → +//! `man`@−7 gold), and the structural answer BINDS — so the stored nibble +//! itself differs from what recency would reconstruct. This is the chip that +//! carries bits the cheap algorithm cannot recompute, IN STORED STATE. +//! - **Gen 3:7** — the stay-silent half (both resolvers agree on both `they`s) +//! plus the chip-composition payoff: inner `they`@12 → matrix `they`@9 → +//! `them`@4 resolves by following two stored nibbles — chips COMPOSE, each +//! carrying its local warrant, never a cached far verdict. +//! +//! **Honesty note on the relative span (codex P2 on this PR):** in head-first +//! English the subject precedes its relative clause, so forward subject +//! selection excludes `god` by ORDER — the `!in_relative` filter is redundant +//! for these fixtures' subject picks. What actually bears load on 3:1 is +//! CLAUSE SEGMENTATION (delete the `and` boundary and resolution fails +//! entirely — asserted as a counterfactual test), and the span filter's +//! discriminative power is proven on a synthetic clause where order does NOT +//! protect it (`relative_span_filter_can_fire`). //! //! Escalation is side-band (a record, not row state): a `0` nibble alone reads //! as *unbound*, indistinguishable from never-attempted — same honest boundary @@ -64,7 +84,9 @@ enum Pos { } /// One fixture token: surface features only (what a POS tagger + chunker -/// emits). `gold` is the referee's answer — read ONLY by assert arms. +/// emits). **Deliberately contains NO gold field** — the referee's answers +/// live in the separate gold list a fixture returns, so the resolvers (which +/// receive only `&[Tok]`) cannot reach them even by a future shortcut. struct Tok { label: &'static str, pos: Pos, @@ -77,8 +99,15 @@ struct Tok { new_main: bool, /// Token is a complementizer ("that") introducing a complement clause. comp: bool, - /// Referee annotation for pronouns: the correct antecedent position. - gold: Option, +} + +/// The referee's answer sheet: `(pronoun_pos, gold_antecedent_pos)` pairs. +/// Read ONLY by assert arms; never passed to a resolver. +type Gold = Vec<(usize, usize)>; + +/// Look up the gold antecedent for a pronoun position. +fn gold_of(gold: &Gold, p: usize) -> Option { + gold.iter().find(|&&(q, _)| q == p).map(|&(_, t)| t) } impl Tok { @@ -91,7 +120,6 @@ impl Tok { in_relative: false, new_main: false, comp: false, - gold: None, } } fn noun(label: &'static str, plural: bool, animate: bool) -> Self { @@ -102,12 +130,11 @@ impl Tok { ..Tok::t(label) } } - fn pron(label: &'static str, plural: bool, gold: usize) -> Self { + fn pron(label: &'static str, plural: bool) -> Self { Tok { pos: Pos::Pron, plural, animate: true, - gold: Some(gold), ..Tok::t(label) } } @@ -135,9 +162,10 @@ impl Tok { /// Gen 3:1 (KJV, lowercased, trimmed): *"now the serpent was more subtil than /// any beast of the field which the LORD God had made: and he said unto the -/// woman"*. The relative span covers "which … made". Gold: `he`@19 → serpent@2. -fn genesis_3_1() -> Vec { - vec![ +/// woman"*. The relative span covers "which … made". Gold (returned separately, +/// never inside `Tok`): `he`@19 → serpent@2. +fn genesis_3_1() -> (Vec, Gold) { + let toks = vec![ Tok::t("now"), // 0 Tok::t("the"), // 1 Tok::noun("serpent", false, true), // 2 @@ -157,20 +185,22 @@ fn genesis_3_1() -> Vec { Tok::t("had").rel(), // 16 Tok::verb("made", false).rel(), // 17 Tok::conj("and"), // 18 - Tok::pron("he", false, 2), // 19 → serpent@2 (d = -17) + Tok::pron("he", false), // 19 → serpent@2 (d = -17) Tok::verb("said", true), // 20 Tok::t("unto"), // 21 Tok::t("the"), // 22 Tok::noun("woman", false, true), // 23 - ] + ]; + (toks, vec![(19, 2)]) } /// Gen 3:7 (KJV, lowercased, trimmed): *"and the eyes of them both were -/// opened, and they knew that they were naked"*. Gold: matrix `they`@9 → -/// `them`@4 (the pair, not the eyes); inner `they`@12 → matrix `they`@9 (the -/// reflexive signature — knower == overt inner subject). -fn genesis_3_7() -> Vec { - vec![ +/// opened, and they knew that they were naked"*. Gold (returned separately, +/// never inside `Tok`): matrix `they`@9 → `them`@4 (the pair, not the eyes); +/// inner `they`@12 → matrix `they`@9 (the reflexive signature — knower == +/// overt inner subject). +fn genesis_3_7() -> (Vec, Gold) { + let toks = vec![ Tok::t("and"), // 0 Tok::t("the"), // 1 Tok::noun("eyes", true, false), // 2 (plural, inanimate) @@ -180,16 +210,39 @@ fn genesis_3_7() -> Vec { Tok::verb("were", false), // 6 Tok::verb("opened", false), // 7 Tok::conj("and"), // 8 - Tok::pron("they", true, 4), // 9 → them@4 (d = -5) + Tok::pron("they", true), // 9 → them@4 (d = -5) Tok::verb("knew", true), // 10 (knowing requires an animate subject) Tok { comp: true, ..Tok::t("that") }, // 11 - Tok::pron("they", true, 9), // 12 → matrix they@9 (d = -3) + Tok::pron("they", true), // 12 → matrix they@9 (d = -3) Tok::verb("were", false), // 13 Tok::t("naked"), // 14 - ] + ]; + (toks, vec![(9, 4), (12, 9)]) +} + +/// A constructed in-range interposition (built English, NOT KJV — labelled +/// honestly): *"the man which the boy saw slept, and he smiled"*. Added for +/// codex's P1: both resolvers' answers are in-window and DIVERGE — recency → +/// `boy`@4 (d = −4, wrong), binding → `man`@1 (d = −7, gold) — and the +/// structural answer BINDS, so the STORED nibble itself differs from what +/// recency would reconstruct. +fn interposed_in_range() -> (Vec, Gold) { + let toks = vec![ + Tok::t("the"), // 0 + Tok::noun("man", false, true), // 1 + Tok::t("which").rel(), // 2 + Tok::t("the").rel(), // 3 + Tok::noun("boy", false, true).rel(), // 4 + Tok::verb("saw", true).rel(), // 5 + Tok::verb("slept", true), // 6 + Tok::conj("and"), // 7 + Tok::pron("he", false), // 8 → man@1 (d = -7) + Tok::verb("smiled", true), // 9 + ]; + (toks, vec![(8, 1)]) } /// The cheap baseline: nearest preceding number-agreeing referential token. @@ -275,7 +328,7 @@ fn main() { }; // ── Fixture A: Gen 3:1 — the divergence text ───────────────────────────── - let a = genesis_3_1(); + let (a, gold_a) = genesis_3_1(); let he = 19; let h_a = heuristic_resolve(&a, he); let s_a = structural_resolve(&a, he); @@ -284,7 +337,7 @@ fn main() { // binding. Falsifier: agreement, or the heuristic being right. gate( "B1 divergence", - h_a == Some(15) && s_a == Some(2) && a[he].gold == Some(2) && h_a != s_a, + h_a == Some(15) && s_a == Some(2) && gold_of(&gold_a, he) == Some(2) && h_a != s_a, format!( "heuristic(he@19) = {:?} ({}), binding = {:?} ({}), gold = serpent@2", h_a, @@ -294,25 +347,34 @@ fn main() { ), ); - // B2 — the temptation is real, and the chip refuses it. The heuristic's - // wrong answer FITS the ±8 window (d = -4, storable); the structural - // answer does not (d = -17) — so the binder must escalate, leaving the - // nibble unbound rather than storing either a clamped or a cheap value. + // B2 — the temptation is real, and the chip refuses it. Proven at the + // BINDER, not by re-deriving its range predicate (CodeRabbit hardening): + // binding the heuristic's target into scratch rows must SUCCEED — the + // binder accepts and stores the wrong-but-in-window nibble (-4) — while + // binding the structural answer (d = -17) must escalate, leaving the real + // rows unbound. The chip's refusal is a choice, not a range limitation. + let mut rows_tempted = fresh_rows(a.len()); + let tempted = bind(&mut rows_tempted, he, h_a.unwrap()); + let tempted_nibble = WitnessLens::new(&rows_tempted) + .at(he) + .map(|f| f.at(Locus::Antecedent)); let mut rows_a = fresh_rows(a.len()); - let heuristic_d = 15_isize - he as isize; let bound = bind(&mut rows_a, he, s_a.unwrap()); let lens_a = WitnessLens::new(&rows_a); let nibble = lens_a.at(he).map(|f| f.at(Locus::Antecedent)); gate( "B2 escalate-not-clamp", - (-8..=7).contains(&heuristic_d) && bound == Err(-17) && nibble == Some(0), + tempted == Ok(-4) + && tempted_nibble == Some(-4) + && bound == Err(-17) + && nibble == Some(0), format!( - "heuristic d={heuristic_d} (in-window, storable-but-wrong), binding d=-17 → escalated, nibble={nibble:?}" + "binder ACCEPTS the heuristic's wrong target ({tempted:?}, nibble {tempted_nibble:?} on scratch rows) — storable-but-wrong is real; binding d=-17 → escalated, nibble={nibble:?}" ), ); // ── Fixture B: Gen 3:7 — the stay-silent text + chip composition ───────── - let b = genesis_3_7(); + let (b, gold_b) = genesis_3_7(); let (matrix, inner) = (9, 12); let mut rows_b = fresh_rows(b.len()); let mut agree = true; @@ -320,7 +382,7 @@ fn main() { for &p in &[matrix, inner] { let h = heuristic_resolve(&b, p); let s = structural_resolve(&b, p); - agree &= h == s && s == b[p].gold; + agree &= h == s && s == gold_of(&gold_b, p); if let Some(t) = s { if let Ok(d) = bind(&mut rows_b, p, t) { displacements.push(d); @@ -338,12 +400,43 @@ fn main() { format!("both they@9/they@12 agree across resolvers; chips = {displacements:?}"), ); - // B4 — the pull-test, both directions. WITH chips: the inner pronoun's - // ultimate referent resolves by following two stored nibbles - // (they@12 → they@9 → them@4) — each chip a local warrant, composed, no - // far verdict cached anywhere. WITHOUT chips (heuristic-only - // reconstruction over both fixtures): Gen 3:7 survives, Gen 3:1 comes - // back wrong — the chip carried exactly the bits recency cannot recompute. + // ── Fixture C: constructed in-range interposition — the divergent CHIP ─── + // (codex P1 on this PR: with only fixtures A and B, every STORED chip came + // from the agreeing verse, so stored state was heuristic-reconstructible + // and the pull-test could not establish its central claim.) + let (c, gold_c) = interposed_in_range(); + let hep = 8; + let h_c = heuristic_resolve(&c, hep); + let s_c = structural_resolve(&c, hep); + let mut rows_c = fresh_rows(c.len()); + let chip_c = bind(&mut rows_c, hep, s_c.unwrap()); + let stored_c = WitnessLens::new(&rows_c) + .at(hep) + .map(|f| f.at(Locus::Antecedent)); + let heuristic_offset = h_c.map(|t| t as i8 - hep as i8); + + // B4 — the pull-test on a DIVERGENT stored chip: both answers in-window, + // resolvers disagree, gold sides with binding, and the STORED nibble (-7) + // differs from what recency would reconstruct (-4). Pull this chip and the + // cheap resolver rebuilds the WRONG antecedent — the stored state itself + // carries bits no better cheap algorithm recomputes. + gate( + "B4 divergent chip", + h_c == Some(4) + && s_c == Some(1) + && gold_of(&gold_c, hep) == Some(1) + && chip_c == Ok(-7) + && stored_c == Some(-7) + && heuristic_offset == Some(-4) + && stored_c != heuristic_offset, + format!( + "recency → boy@4 (would store {heuristic_offset:?}), binding → man@1; STORED nibble {stored_c:?} ≠ heuristic reconstruction — divergence lives in stored state" + ), + ); + + // B5 — chips COMPOSE: the inner pronoun's ultimate referent resolves by + // following two stored nibbles (they@12 → they@9 → them@4) — each chip a + // local warrant, no far verdict cached anywhere. let lens_b = WitnessLens::new(&rows_b); let hop1 = lens_b .at(inner) @@ -353,14 +446,10 @@ fn main() { .at(p) .and_then(|f| f.resolves_to(Locus::Antecedent, p, lens_b.len())) }); - let heuristic_wrong_somewhere = heuristic_resolve(&a, he) != a[he].gold; gate( - "B4 pull-test", - hop1 == Some(matrix) && hop2 == Some(4) && heuristic_wrong_somewhere, - format!( - "chip chain they@12 → {:?} → {:?} (gold them@4); heuristic-only reconstruction fails on 3:1", - hop1, hop2 - ), + "B5 chips compose", + hop1 == Some(matrix) && hop2 == Some(4), + format!("chip chain they@12 → {hop1:?} → {hop2:?} (gold them@4) — two local warrants"), ); println!(); @@ -379,15 +468,15 @@ mod tests { /// The probe's own gates, runnable under `cargo test --example`. #[test] fn divergence_fires_on_3_1_and_stays_silent_on_3_7() { - let a = genesis_3_1(); + let (a, gold_a) = genesis_3_1(); assert_eq!(heuristic_resolve(&a, 19), Some(15), "recency finds god"); assert_eq!(structural_resolve(&a, 19), Some(2), "binding finds serpent"); - assert_eq!(a[19].gold, Some(2)); + assert_eq!(gold_of(&gold_a, 19), Some(2)); - let b = genesis_3_7(); + let (b, gold_b) = genesis_3_7(); for p in [9, 12] { assert_eq!(heuristic_resolve(&b, p), structural_resolve(&b, p)); - assert_eq!(structural_resolve(&b, p), b[p].gold); + assert_eq!(structural_resolve(&b, p), gold_of(&gold_b, p)); } } @@ -396,36 +485,107 @@ mod tests { /// previous clause's subject verbatim — `eyes`@2, which is wrong. #[test] fn animacy_check_is_load_bearing() { - let b = genesis_3_7(); + let (b, gold_b) = genesis_3_7(); let k = clause_of(&b, 9); let bare_r2 = subject_of_clause(&b, k - 1); assert_eq!(bare_r2, Some(2), "bare subject-continuity picks eyes@2"); - assert_ne!(bare_r2, b[9].gold, "…which is NOT the gold answer"); - assert_eq!(structural_resolve(&b, 9), b[9].gold, "the check repairs it"); + assert_ne!( + bare_r2, + gold_of(&gold_b, 9), + "…which is NOT the gold answer" + ); + assert_eq!( + structural_resolve(&b, 9), + gold_of(&gold_b, 9), + "the check repairs it" + ); } - /// The relative-clause skip must be load-bearing on 3:1: if `god`@15 - /// counted as a main-clause subject, R2 would bind it. The fixture pins - /// that `god` is inside the relative span and the clause-0 subject is - /// `serpent`. + /// What ACTUALLY bears load on 3:1 is clause segmentation, not the span + /// filter (codex P2: in head-first English `serpent`@2 precedes `god`@15, + /// so subject selection excludes `god` by ORDER — clearing `in_relative` + /// changes nothing on this fixture). The honest counterfactual: delete the + /// clause boundary and structural resolution FAILS entirely. #[test] - fn relative_span_skip_is_load_bearing() { - let a = genesis_3_1(); - assert!(a[15].in_relative, "god sits inside the relative clause"); + fn clause_segmentation_is_load_bearing() { + let (mut a, gold_a) = genesis_3_1(); + assert_eq!(structural_resolve(&a, 19), gold_of(&gold_a, 19)); + a[18].new_main = false; // erase the "and" boundary assert_eq!( - subject_of_clause(&a, 0), - Some(2), - "clause-0 subject = serpent" + structural_resolve(&a, 19), + None, + "without segmentation the resolver has no previous clause to bind" + ); + assert_ne!(None, gold_of(&gold_a, 19), "…and gold still exists"); + } + + /// The span filter's discriminative power, proven where ORDER does not + /// protect it: a synthetic clause whose FIRST candidate sits inside a + /// relative span. With the filter the subject is the second candidate; + /// the unfiltered first-candidate pick differs. Can-fire, non-vacuous. + #[test] + fn relative_span_filter_can_fire() { + let toks = vec![ + Tok::noun("ghost", false, true).rel(), // 0 — in-relative candidate FIRST + Tok::noun("host", false, true), // 1 — the real subject + ]; + let filtered = subject_of_clause(&toks, 0); + let unfiltered = + (0..toks.len()).find(|&i| clause_of(&toks, i) == 0 && toks[i].is_candidate()); + assert_eq!(filtered, Some(1), "filter skips the in-relative candidate"); + assert_eq!(unfiltered, Some(0), "without it, the wrong token wins"); + assert_ne!(filtered, unfiltered, "the filter changes the outcome"); + } + + /// codex P1's demanded artifact: a DIVERGENT chip in stored state. The + /// in-range interposition binds -7 while recency would reconstruct -4 — + /// the stored nibble itself differs from the cheap reconstruction. + #[test] + fn divergent_chip_differs_from_heuristic_reconstruction() { + let (c, gold_c) = interposed_in_range(); + let h = heuristic_resolve(&c, 8); + let s = structural_resolve(&c, 8); + assert_eq!(h, Some(4), "recency finds boy (wrong)"); + assert_eq!(s, Some(1), "binding finds man (gold)"); + assert_eq!(s, gold_of(&gold_c, 8)); + + let mut rows = fresh_rows(c.len()); + assert_eq!(bind(&mut rows, 8, s.unwrap()), Ok(-7)); + let stored = WitnessLens::new(&rows) + .at(8) + .map(|f| f.at(Locus::Antecedent)); + assert_eq!(stored, Some(-7)); + let heuristic_reconstruction = h.map(|t| t as i8 - 8); + assert_ne!( + stored, heuristic_reconstruction, + "the stored bit is exactly what recency cannot recompute" ); } /// Out-of-window escalation leaves the nibble unbound — never a clamp. #[test] fn escalation_leaves_nibble_unbound() { - let a = genesis_3_1(); + let (a, _) = genesis_3_1(); let mut rows = fresh_rows(a.len()); assert_eq!(bind(&mut rows, 19, 2), Err(-17)); let lens = WitnessLens::new(&rows); assert_eq!(lens.at(19).map(|f| f.at(Locus::Antecedent)), Some(0)); } + + /// The binder ACCEPTS the heuristic's wrong-but-in-window target — the + /// "storable-but-wrong" half of B2 proven at the binder itself, not by + /// re-deriving its range predicate in the gate. + #[test] + fn binder_accepts_the_tempting_wrong_target() { + let (a, gold_a) = genesis_3_1(); + let mut rows = fresh_rows(a.len()); + assert_eq!(bind(&mut rows, 19, 15), Ok(-4), "god@15 binds cleanly"); + let lens = WitnessLens::new(&rows); + assert_eq!(lens.at(19).map(|f| f.at(Locus::Antecedent)), Some(-4)); + assert_ne!( + Some(15), + gold_of(&gold_a, 19), + "…and it is the WRONG target" + ); + } } From 6a46e737c372c50a814500df90f850bf83e83bbb Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 23:02:36 +0000 Subject: [PATCH 3/3] docs(board): measure the workspace-wide fmt sweep instead of asserting the decline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit asked #874 to run `cargo fmt --all` + `cargo clippy --all-targets --all-features`. Both were investigated rather than argued from repo practice: - `cargo fmt --all -- --check` → 1,094 hunks / 20,307 diff lines across 64 files in 9 crates (55 in lance-graph-ontology). ZERO hunks in the PR's own file. Attaching that to a 752-line additive probe would make the diff unreviewable and land pre-existing drift under an unrelated title, so it is deferred to its own mechanical PR — now logged as TD-WORKSPACE-FMT-DRIFT with the per-crate table and the upstream cause (`-p`-scoped fmt means untouched crates accumulate drift; ontology holding 86% of it is the tell). - all-features clippy is blocked, not declined: the delta feature does not build (TD-LANCE-GRAPH-ALL-FEATURES-DELTA-BREAK). Exec-run Verification section records both measurements so the record shows what ran and why the sweep was deferred rather than skipped. Reviewer subsequently verified and withdrew the finding; all nine review threads (codex x2, CodeRabbit x7) are addressed and resolved. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki --- .claude/board/TECH_DEBT.md | 36 +++++++++++++++++++ .../exec-runs/w7-binding-not-heuristic.md | 23 ++++++++++++ 2 files changed, 59 insertions(+) diff --git a/.claude/board/TECH_DEBT.md b/.claude/board/TECH_DEBT.md index 6043d760..29d1b5d7 100644 --- a/.claude/board/TECH_DEBT.md +++ b/.claude/board/TECH_DEBT.md @@ -1,5 +1,41 @@ # Technical Debt Log — Open + Paid (double-entry, append-only) +## TD-WORKSPACE-FMT-DRIFT (2026-07-30) + +**Measured, not estimated.** `cargo fmt --all -- --check` at +`b9160f8` reports **1,094 hunks / 20,307 diff lines across 64 files in 9 +crates**: + +| crate | files | +|---|---| +| `lance-graph-ontology` | 55 | +| `bgz-tensor` | 2 | +| `causal-edge`, `ogar-emitter`, `ogar-encryption`, `ogar-from-ruff`, `ogar-render-askama`, `sigma-tier-router`, `surreal_container` | 1 each | + +Surfaced by a CodeRabbit finding on #874 asking for the workspace-wide sweep. +The sweep was **deferred, not skipped**, and the reason is the measurement: +attaching a 20k-line reformat of nine untouched crates to a 752-line additive +probe PR makes the diff unreviewable and lands pre-existing drift silently +under an unrelated title. #874's own file is fmt-clean (0 of the 1,094 hunks). + +**The real debt is upstream of the sweep**: `-p`-scoped `cargo fmt` is this +workspace's practice (per `CLAUDE.md` Build Commands and the +agent-cargo-hygiene rule's one-shared-`target/` discipline), so crates only get +formatted when someone edits them — drift accumulates in whatever is not being +worked on. `lance-graph-ontology` holding 86 % of it is the tell: a crate +nobody has touched recently. + +**Paying it** is one mechanical PR (`cargo fmt --all`, no behaviour change) — +best landed when no feature branch is mid-review, since it collides with +everything. Note it is NOT free to defer forever: every deferral makes the +eventual sweep collide with more in-flight work. + +**Companion blocker (separate, do not conflate):** +`clippy --all-targets --all-features` cannot pass at all — the `delta` feature +does not build (`TD-LANCE-GRAPH-ALL-FEATURES-DELTA-BREAK`). Any review asking +for the all-features invocation is blocked on that entry first, independent of +formatting. + ## TD-LENS-QUORUM-SCANS-THE-WHOLE-LENS (2026-07-29) **Codex P2 on #868, verified and MEASURED.** The lens migration changes the diff --git a/.claude/board/exec-runs/w7-binding-not-heuristic.md b/.claude/board/exec-runs/w7-binding-not-heuristic.md index a02ff333..806fe8a8 100644 --- a/.claude/board/exec-runs/w7-binding-not-heuristic.md +++ b/.claude/board/exec-runs/w7-binding-not-heuristic.md @@ -52,6 +52,29 @@ thinking. Mechanical form: the pull-test. duplicate-bin-target warning only). - `cargo fmt -p lance-graph-planner` → ran; gates re-verified green after. +### Workspace-wide checks — MEASURED, then deferred (not skipped) + +Review asked for `cargo fmt --all` + `cargo clippy --all-targets +--all-features`. Both were investigated rather than argued from practice: + +- **`cargo fmt --all -- --check` → 1,094 hunks / 20,307 diff lines across 64 + files in 9 crates** (55 in `lance-graph-ontology`; also `bgz-tensor`, + `causal-edge`, `ogar-emitter`, `ogar-encryption`, `ogar-from-ruff`, + `ogar-render-askama`, `sigma-tier-router`, `surreal_container`). + **Zero hunks in this PR's file** — `probe_binding_not_heuristic.rs` is + fmt-clean under the workspace-wide config, which is the property the + guideline protects. Running the sweep here would attach a 20k-line reformat + of nine untouched crates to a 752-line additive probe; the diff stops being + reviewable and pre-existing drift lands silently under an unrelated title. + Deferred to its own PR — logged as `TD-WORKSPACE-FMT-DRIFT`. +- **`clippy --all-targets --all-features`** — blocked, not declined by + preference: all-features is the known `TD-LANCE-GRAPH-ALL-FEATURES-DELTA-BREAK` + surface (the `delta` feature does not build), so the invocation cannot pass + regardless of this diff. The scoped `-D warnings` run above covers every line + the PR adds. + +All nine review threads (codex ×2, CodeRabbit ×7) addressed and resolved. + ## Honest boundaries - Escalation is side-band (the binder's return), not row state — a 0 nibble alone is indistinguishable from never-attempted. Same boundary W6 recorded.