diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 95fb0fe51..114879d59 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,56 @@ +## 2026-09-05 — E-THE-UNFINISHED-FUNCTION-WAS-NOT-THE-DEBT-1 — the execution model that needed `policy_hash_v1` never reached a binary, and neither has its replacement + +**Status:** FINDING (W0 production census, four read-only tracers + orchestrator verification of the contested fact; nothing compiled). Plan: `.claude/plans/open-ideas-fetch-v1.md` §2 (ruling A). Operator ruling the same day: planning migrates to `ogar-loco` / `ogar-r2il`; DataFusion is out; what exists gets a grace period; nothing new migrates to it. +**Confidence:** High for every existence/absence/caller claim (each carries `file:line`; "production" was traced to a binary or axum handler, never inferred from `pub mod`, a feature flag, a registration helper, a test or a comment). The Dockerfile claim was verified by the orchestrator directly, not taken from a tracer. +**Deliverables:** `D-OIF-1` (regraded Superseded) `D-OIF-1-DEC` (withdrawn). + +**The card said "registration". The first re-derivation said "the body". Both were one abstraction generation behind.** The question was never *which hash* — it was *whether anything still executes the plan that would call it*. Measured: + +- `ColumnMaskRewriter` has one non-test constructor in seven repos, `MedCare-rs/crates/medcare-server/src/routes/patient.rs:150`, behind `#[cfg(feature = "lance-phase2-rbac")]` (`:85`) and `?source=lance` (`:52-53`). The feature is default-off (`Cargo.toml:215`) and **no Dockerfile enables it** (`docker/Dockerfile.railway:175` etc. build `lance-phase2,reasoning`). Its decoder `record_batch_to_patient` (`:200-211`) returns `None` unconditionally. No user has ever received a masked row. +- The rewriter is post-hoc by construction: `rewrite_plan` (`callcenter/src/policy.rs:210`) substitutes expressions above the scan and never writes `TableScan.projection` (`:226-241` only reads it). The forbidden column is materialized from Lance, then overwritten — the exact shape the projection invariant forbids. +- `RedactionMode::Hash` (`policy.rs:130-140`) binds a UDF whose `invoke` is `Err(NotImplemented)` (`:339`); `register_vsa_udfs` (`vsa_udfs.rs:574`) has zero callers anywhere. + +**The half that keeps this from being a tidy retirement story:** the canonical replacement is also unenforced. `lance-graph-rbac::authorize()` / `authorize_scoped()` (`authorize.rs:66,182`), `contract::ClassRbac` (`rbac.rs:143`), `ActionInvocation::commit_via` (`action.rs:327`) and `lance-graph-ogar::OgarRbac` (`rbac_impl.rs:38`) have **zero non-test callers**; `effective_mask` is not an identifier in any `.rs`; there is no `ogar-rbac` crate (`ogar-auth` is password/TOTP only). The one real `surface ∩ role` fail-closed projection (`a2ui-server/src/project.rs:70-83`) lives in a crate with no binary and no dependent. MedCare's live gate is the entity-string `Policy` returning an `AccessDecision` with no mask (`patient.rs:280`); its column projection (`views/project.rs:229`) is a **view** mask with no role operand. And the one mask fold that exists, `authorize_scoped` (`authorize.rs:190-216`), returns `FieldMask::FULL` on non-Allow — fail-open in the mask value. + +**So the sentence that is earned is narrower than the one proposed.** Not "the model that needed the function had disappeared" — it never arrived. **The unfinished function was not the debt. The debt is that field-level authorization has no enforced owner on any production path, and the DataFusion rewriter was a second, wrong-layer answer to that vacancy — a storage/query-layer patch for an authorization-layer hole.** Finishing the function would have made the wrong layer *look* finished. + +**Correction, same day (operator): the first pass committed the repo-boundary error.** It read zero call sites *inside lance-graph* as a production verdict for a deliberately cross-repo substrate — the same category error lance-graph-java PR #76 had just corrected for `WideFieldMask` one layer down. Three verdicts struck: "`try_advance_phase` has no production entry point" (bardioc `substrate-b` is a binary over `MailboxSoA<32>` gating every move on the contract's `KanbanColumn::can_transition_to`, `substrate-b/src/kanban.rs:103-120`, with `KanbanShaderSink` tagging emissions by phase); "`ogar-loco` has one live consumer" (blockly-rs, the thinking palette, is a direct first-class consumer — `blockly-web` axum binary, `Cargo.toml:40`); "`ogar-r2il` is probe-only" (it is the R2IL→loco bridge over r2sleigh's live `r2il` crate, and the lance-graph-java lineage consumes R2IL/SSA in-process via `ruff_r2il` — a direct Cargo dep is not the falsifier). The RBAC zero-caller verdict is therefore *rescoped* to the nine repos scanned, never stated globally. **Law: for a cross-repo substrate, production reachability terminates at deployed consumers, not at the repository boundary.** The correction sharpens the ruling: DataFusion planning/policy is grace-period archaeology beside an execution architecture that already has real consumers; `policy_hash_v1` would migrate semantics backwards into it. + +**What holds, so it is not dragged into the retirement:** the Rubicon lifecycle is SoA-owned and checked — `Planning → CognitiveWork` is a one-way edge in `KanbanColumn`'s DAG (`kanban.rs:98-106`), consulted by `try_advance_phase` (`soa_view.rs:314`) with no mutation on refusal (`:329-346`); the `KanbanActor` actor is deleted while `kanban_actor.rs` lives on as the read-only meta-awareness census (`PhaseCensus`/`mul_target`, composed by `cycle_driver.rs:805`, read by the awareness rungs — first wording here said "tombstone"; corrected same day on operator input); no `Baton` type, no `CollapseGateEmission`, no `CommitHook` exists. RBAC holds no Kanban state; lifecycle code makes no authorization decision; `ogar-loco`/`ogar-r2il` contain no authorization vocabulary. Three v3 docs still name the deleted actor as owner — regraded in place this PR. + +**Chronology, so the lesson is not misread as "old code went obsolete":** idea → scaffold (`policy.rs`) → feature-gated integration attempt (MedCare `lance-phase2-rbac`) → never deployed, terminally stubbed → architecture moved elsewhere (operator ruling: loco/r2il; projection-side masking) → the stub falsely reads as unfinished debt. The tree shows no once-live DataFusion masking architecture that was later superseded; it shows an attempted one that accumulated scaffolding and never acquired an execution path. **A conspicuous stub attracts implementation work even when the architecture around it never achieved reality.** Adjudication note: the independent #1188 census reached the same ruling but compressed "not live" into "does not exist" at two points (the MedCare constructor; whole-module removal) — the reachability proof above is what makes the narrower cone (remove Hash + UDF, freeze the rest under grace) the safe one. + +**Rule extracted:** before giving an unfinished function a body, trace the *plan* that would execute it to a deployed consumer — in whatever repo it lives; the repository boundary is not the falsifier. A `cfg(feature)` that no Dockerfile sets, a decoder that returns `None`, and a registration helper with no caller are three independent proofs of the same thing, and any one of them ends the "which algorithm" discussion before it starts. "Superseded" is not a verdict about the code; it is a verdict about whether anything reaches it. + +--- + +## 2026-09-05 — E-A-COLUMN-OF-INDICES-INTO-A-CODEBOOK-THAT-DOES-NOT-EXIST-1 — three stale idea cards, each wrong about its own blocker + +**Status:** FINDING (structural — grep + read of the current tree; nothing compiled). Plan: `.claude/plans/open-ideas-fetch-v1.md`. +**Confidence:** High. Existence and absence claims carry file:line. Caller/reader counts are **grep censuses**, stated as such with their scope: `crates/lance-graph-callcenter/src/vsa_udfs.rs:574` (`register_vsa_udfs`) has zero call sites outside its definition across `crates/**/*.rs`; `ewa_sandwich(` has zero call expressions outside `crates/jc/` and `sigma_propagation.rs`; the only σ writers are `crates/cognitive-shader-driver/src/backing.rs:310` (`set_sigma`, the shim loop) and `crates/cognitive-shader-driver/src/backing.rs:347` (`set_sigma`, a test); the only σ readers are `crates/lance-graph-planner/examples/blw_tenant.rs:190` (`o.sigma[row]`) and `crates/lance-graph-planner/examples/blw_rows.rs:289` (`o.sigma[row]`). Nothing compiled. +**Deliverables (plan `open-ideas-fetch-v1`):** `D-OIF-0` `D-OIF-1` `D-OIF-1-DEC` `D-OIF-2` `D-OIF-2-DEC` `D-OIF-3` `D-OIF-4` `D-OIF-5` `D-OIF-5-DEC` `D-OIF-6` `D-OIF-7`. + +Fetching the three highest-value Open cards from an 82-day-stale `IDEAS.md` produced the same shape three times: **the card names a blocker that is not the blocker.** + +| card | named blocker | measured blocker | +|---|---|---| +| `IDEA-POLICY-HASH-UDF` | "UDF registration" | the **body** — the UDF is bound as an object in the `Expr` (`policy.rs:137`) and executes without by-name registration (`register_vsa_udfs` has zero callers and its UDFs still run); `invoke_with_args` simply returns `NotImplemented` | +| `IDEA-B1-HARDWARE-BACKENDS` | "waits on ndarray AMX/MKL" | the **shape** — a 2×2 f64 sandwich has no 16×16 tile mapping; and `ewa_sandwich(` has **zero production call expressions** (all four "callers" are doc comments), so any faster kernel is a home without a consumer | +| `IDEA-CAUSAL-EDGE-TENSOR-SIDECAR` | "design the 9-byte sidecar" | it **shipped**, as a SoA column (`mailbox_soa.rs:125-133`, `bindspace.rs:54-58`) — the card never learned; what is missing is the **codebook** the column indexes | + +### The sharp one + +Every production row carries `sigma = 0`, documented as "untrained / first centroid" (`bindspace.rs:54`). The `SigmaCodebook` those bytes index is claimed to live in the contract (`sigma_propagation.rs:73`), in `lance-graph-cognitive` (`contract/src/splat.rs:308`), and to be built offline by `jc` (`arm-discovery/aerial/codebook.rs:16`). `grep -rn SigmaCodebook crates/` returns the two doc lines and nothing else; `lance-graph-cognitive/src` has zero hits; `jc` holds the *viability probe* and no builder. **Three claimed homes, zero implementations, one live column of references into them.** Its writers are the write-shim loop (`backing.rs:310`) and one test that writes `9`; its readers are two examples that dump the byte. + +Two further inconsistencies ride on the same claim: the σ provenance is written two incompatible ways — *fitted* by k-means (`sigma_codebook_probe.rs`) vs *declared* from the typed value's `(PropertyKind, Marking, SemanticType)` tuple (`sigma_propagation.rs:74-77`) — and two viability numbers are cited for one probe: `R²=0.9949` (`bindspace.rs:39,57`) vs `ρ=0.9973` (`arm-discovery/src/lib.rs:13`), where the probe computes R² (`:317`) and `0.9973` is elsewhere the 3σ constant and an unrelated Spearman band. + +### The generalizable rule + +**A ledger entry's stated blocker decays faster than its stated goal.** The goal ("hash the column", "propagate Σ faster", "index Σ per edge") survived 4 months; every *mechanism* claim attached to it was stale. So: before acting on an idea card, re-derive its blocker from the tree — the cost is a grep, the alternative is building registration that was never missing, hardware backends for a 3-scalar kernel, or a second projection of a byte that already has a column. The `IDEAS.md` "Status" field should carry the *measured* blocker with a date, and the plan re-derivation is the entry, not a preamble to it. + +Also recorded, because it changes what is owed: an unkeyed 64-bit hash of an identifier column is a lookup table wearing a redaction's name — the v1 target named in `policy.rs:275` ("FNV-64") is the option the plan recommends against (`D-OIF-1-DEC`). + +Cross-ref: `E-A-RULED-HOME-NEEDS-A-FIRST-CONSUMER-OR-IT-IS-A-VACANCY-1` (the batched kernel's sequencing); `I-VSA-IDENTITIES` (indices, not content — why the column is right and the sidecar was wrong); `E-A-GATE-INHERITS-THE-BLIND-SPOT-OF-WHOEVER-WROTE-IT-1` (the same day's other instance of a written mechanism outliving its truth). ## 2026-09-05 — E-VERSIONED-GRAPH-OVERWRITES-SO-ROW-ADDRESSES-ALIAS-ACROSS-VERSIONS-1 — the D-LNC-2 probe found four wrong claims in the plan it was written to execute **Status:** FINDING (measured, `crates/lance-graph/tests/lance_row_identity_probe.rs`, lance 10.0.0, both disable arms verified red-then-green). diff --git a/.claude/board/IDEAS.md b/.claude/board/IDEAS.md index 5d869181d..23098a6f5 100644 --- a/.claude/board/IDEAS.md +++ b/.claude/board/IDEAS.md @@ -87,6 +87,38 @@ Agents filter by `@`-mention or domain to see what's theirs. (Prepend new ideas here with today's date. Format:) +## 2026-09-05 — Σ-propagation: the batched `F64x8` kernel is the real lever; AMX/MKL was the wrong shape for a 2×2 + +`[P2 @savant-architect @sentinel-qa domain:codec D-OIF-4 D-OIF-5]` + +Re-derived from the tree while fetching `IDEA-B1-HARDWARE-BACKENDS`. The kernel is 2×2 f64 (`sigma_propagation.rs:210-227`, 12 mul + 6 add); an AMX tile is 16×16 bf16/int8 and an MKL `dgemm` call costs more than the 18 flops. `F64x8` carries non-FMA `Mul`/`Add` on all four backends (`simd_avx512.rs:446-448`), so eight edges per instruction with **bit identity** to the scalar kernel is reachable as plain consumer code in `jc` — no ndarray change. The catch that decides sequencing: `ewa_sandwich(` has **zero production call expressions** outside `jc` + the contract; every "caller" is a doc comment. So the kernel ships only paired with the hop re-quantization probe that decides whether `MailboxSoA::apply_edges` may advance `sigma[row]`. Plan: `open-ideas-fetch-v1.md` §3. + +**Status:** Open — In plan (`D-OIF-4`, `D-OIF-5`); `D-OIF-5-DEC` (where an edge's `M` comes from — the `CausalEdge64` v2 spare is 3 bits) is the operator's. + +## 2026-09-05 — The σ column indexes a codebook that exists in three doc comments and zero crates + +`[P1 @truth-architect @integration-lead domain:codec D-OIF-0 D-OIF-2 D-OIF-3]` + +`BindSpace.fingerprints.sigma` (`bindspace.rs:54-58`) and `MailboxSoA.sigma` (`mailbox_soa.rs:125-133`) shipped the 1-byte index the `IDEA-CAUSAL-EDGE-TENSOR-SIDECAR` card was still designing. The `SigmaCodebook` it references is claimed to live in the contract (`sigma_propagation.rs:73`), in `lance-graph-cognitive` (`contract/src/splat.rs:308`), and to be built offline by `jc` (`arm-discovery/aerial/codebook.rs:16`) — `grep -rn SigmaCodebook crates/` finds only the two doc lines. Every production row carries `sigma = 0`, "first centroid" of a codebook with no centroids. Two provenance stories coexist — fitted (k-means, `sigma_codebook_probe.rs`) vs declared (typed-value tuple, `sigma_propagation.rs:74-77`) — and two viability numbers are cited for one claim (`R²=0.9949` vs `ρ=0.9973`). Plan: `open-ideas-fetch-v1.md` §4. + +**Status:** Open — In plan (`D-OIF-0` re-runs the probe; `D-OIF-2` the type + builder; `D-OIF-3` the first real writer). `D-OIF-2-DEC` (fitted vs declared) is the operator's. + +## 2026-09-05 — `ndarray::simd::ternlog` ⋂ the §14 voxel cube: the "other 18 cells" are one named immediate each + +`[P2 @simd-savant @kernel-membrane-warden domain:mask]` + +lance-graph-java's `mask-risc-lowering-v1.md` §14 prices a 3-state × 3-tier voxel cube as 9 built primitives with "the other 18 cells ANDs of three". `ndarray::simd::ternlog::{AND3, AND2_ANDNOT, AND_ANDNOT2, …}` (ndarray #299 arc, parity-tested over all 256 immediates on six backends) makes each of those cells ONE instruction with a NAME. Partly realized already: `lance-graph-planner/examples/probe_nxg_hist_1.rs:51-136` calls `mask_ternlog::` / `` by name (E-NXG-2/3). What is still open: (a) §14's arithmetic assumes cell = 3 ANDs — restate it as 1 ternlog and re-price; (b) `ogar_loco::TERNLOG = FnIndex(0x86)` still has no consumer, and the immediate byte IS the call value — the lowering from a §14 cell to a loco call is a table, not code. Interacts with `D-MRL-G2` (mask spans the class's rows or all rows), which is the operator's. + +**Status:** Open (research; blocked on `D-MRL-G2`). + +## 2026-09-05 — Citations should carry the path the decay gate can resolve, or the gate sees 7 % of them + +`[P2 @doctrine-keeper domain:board]` + +The `citation-decay` gate (#1168/#1170) measured **2314 citations / 37 OK / 124 DECAYED / 2153 UNVERIFIABLE** — 93 % unverifiable because the house style cites bare basenames (`policy.rs:137`) that no scanner can resolve to a file. The gate is honest about it (unverifiable never fails). Two possible remedies, neither taken yet: (1) a convention — cite `crate/path.rs:LINE` for anything under `crates/`, basename-only allowed inside a plan that names its crate once in a header; (2) a resolver in the gate that tries `**/` and treats a UNIQUE hit as resolvable, a non-unique one as unverifiable. (2) needs no behaviour change from writers and is measurable (how many of the 2153 become OK vs DECAYED). Recommend (2) first, then decide (1) on the numbers. + +**Status:** Open. + ## 2026-06-15 — Research synergy: CLAM residue ladder ⋂ knee/hip attractor basins (HHTL cascade in REVERSE, fine→coarse ascent) `[P3 @cascade-architect @savant-research domain:codec]` @@ -1061,7 +1093,7 @@ bgz17 crate as the substrate. ### IDEA-B1-HARDWARE-BACKENDS — AMX/MKL hardware backends for sigma_propagation (PR #322) -**Status:** Open 2026-05-05 +**Status:** Reshaped 2026-09-05 — AMX/MKL rejected for the 2×2 kernel (shape mismatch); superseded by the `F64x8` batched kernel, plan `open-ideas-fetch-v1.md` §3 (`D-OIF-4`/`D-OIF-5`) **Priority:** P3 **Source:** PR #322 explicit "What this PR does NOT do" **Author's words:** "No hardware backends (AMX/MKL via ndarray #119/#121). That's B1.5 follow-up." @@ -1125,7 +1157,7 @@ bgz17 crate as the substrate. ### IDEA-CAUSAL-EDGE-TENSOR-SIDECAR — CausalEdgeTensor as 9-byte sidecar (CausalEdge64 + 1 byte Σ index) (PR #288) -**Status:** Open 2026-05-05 +**Status:** Implemented-in-part 2026-09-05 — the 1-byte index shipped as a SoA column (`mailbox_soa.rs:133`, `bindspace.rs:58`), NOT as a sidecar; the codebook it indexes is OPEN, plan `open-ideas-fetch-v1.md` §4 (`D-OIF-2`/`D-OIF-3`) **Priority:** P2 **Source:** PR #288 (sigma codebook probe conclusion) **Author's words:** "Mit diesem Probe-Resultat kann jetzt `CausalEdgeTensor`-Variante als 9-Byte-Sidecar (`CausalEdge64` + 1 Byte Σ-Codebook-Index) entworfen werden, ODER äquivalent über Schemasidecar Block 14/15. Caller-Wahl, beide architektonisch tragbar." @@ -1161,7 +1193,7 @@ bgz17 crate as the substrate. ### IDEA-POLICY-HASH-UDF — policy_hash_v1 UDF registration (PR #301) -**Status:** Open 2026-05-05 +**Status:** Superseded 2026-09-05 (ruling A) — the DataFusion masking path has no deployed consumer and the operator ruled DataFusion out of planning; retirement plan in `open-ideas-fetch-v1.md` §2 (`D-OIF-1`); `D-OIF-1-DEC` withdrawn **Priority:** P2 **Source:** PR #301 **Author's words:** "`NotYetWiredHashUdf` binds at plan time, returns `NotImplemented('policy_hash_v1 UDF not yet registered')` at execute. Plans build; execution fails loud." diff --git a/.claude/board/INTEGRATION_PLANS.md b/.claude/board/INTEGRATION_PLANS.md index 1ca39e2f1..52faeaa70 100644 --- a/.claude/board/INTEGRATION_PLANS.md +++ b/.claude/board/INTEGRATION_PLANS.md @@ -1,3 +1,36 @@ +## 2026-09-05 — `open-ideas-fetch-v1` (MEASURED, planning-only — three decisions gate the workers) + +`.claude/plans/open-ideas-fetch-v1.md`. Three Open cards fetched from an +82-day-stale `IDEAS.md` and re-derived from the current tree; **each card +was wrong about its own blocker** (`E-A-COLUMN-OF-INDICES-INTO-A-CODEBOOK-THAT-DOES-NOT-EXIST-1`). + +- **`policy_hash_v1`** — first re-derived as "the blocker is the body, not + registration"; **superseded the same day by ruling A (plan §2, W0 census):** + the DataFusion masking path has no deployed consumer and redacts above the + scan, and the operator ruled DataFusion out of planning (grace period for + what exists, nothing new). `D-OIF-1` is a retirement plan; `D-OIF-1-DEC` + withdrawn. The field-level obligation's canonical owner (`ClassRbac × + ClassView × WideFieldMask`) is itself unenforced — recorded, not rebuilt. +- **Σ-propagation "hardware backends"** — mis-shaped for a 2×2 f64 kernel; + the lever is `F64x8` batching with bit identity to the scalar kernel, as + consumer code in `jc` (no ndarray change). Zero production call sites + exist, so the kernel ships only paired with the hop re-quantization probe. + `D-OIF-4` + `D-OIF-5`; the edge-`M` source is `D-OIF-5-DEC`. +- **Σ sidecar** — already shipped as a SoA column; the **codebook** the + column indexes exists in three doc comments and zero crates. `D-OIF-0` + (re-run the viability probe, reconcile 0.9949 vs 0.9973), `D-OIF-2` (type + in the contract, builder in `jc`, instance in `cognitive-shader-driver`, no + digest pin), `D-OIF-3` (first real writer), `D-OIF-7` (the loaded instance + loader in `cognitive-shader-driver`, worker W-7); provenance is `D-OIF-2-DEC`. +- **`D-OIF-6`** — the ledger itself: four new entries + three status flips, + shipped in this PR. + +Rejected on record (§5): AMX/MKL for 2×2; the 9-byte sidecar and Block +14/15 (superseded); the in-`u64` index (3 spare bits); an IDEAS-staleness CI +gate (fires on legitimate quiet). §8 lists the four structural claims that +execution must confirm before they are believed. §7 carries the per-D Sonnet +briefs; nothing is dispatched until the three decisions land. + +**Status:** PLANNED — halted for operator decisions D-OIF-2-DEC / 5-DEC (D-OIF-1-DEC withdrawn, ruling A). ## lance-convergence-staged-migration-v1 (2026-09-05) — MEASURED, stages 0–1 ready, stage 3 PROBE-GATED `.claude/plans/lance-convergence-staged-migration-v1.md`. The staged lance diff --git a/.claude/board/ISSUES.md b/.claude/board/ISSUES.md index 20c9b79b2..04c7e3c8f 100644 --- a/.claude/board/ISSUES.md +++ b/.claude/board/ISSUES.md @@ -1,3 +1,35 @@ +## ISS-PIN-RULING-PROSE-DRIFTS-BEHIND-THE-MANIFEST (2026-09-05) — OPEN + +**The pin ruling lives in two places and only one of them is checked.** +`Cargo.toml`'s workspace table is what cargo resolves; root `CLAUDE.md` +§ "Key Dependencies" is what a session READS to learn the ruling. Nothing +compares them, so a bump PR that edits the manifest and not the prose leaves +the authoritative-looking text asserting a retired pin. + +**Measured (this session, after #1190 merged):** `Cargo.toml:261-264` said +`lance = "=11.0.0"` / `lancedb = "=0.38.0"` while `CLAUDE.md:1255-1262` still +said `=9.0.0` / `=0.33.0` and named lancedb 0.33 as the crate that *imposes* +the exact-equals. Two consecutive bumps left it that way — #1187 (lance 10) +updated only the arrow-ceiling paragraph, #1190 (lance 11) updated neither — +so the ruling lines had been wrong across a full major. Corrected in the +`open-ideas-fetch-v1` PR (#1185); the stale ⊘ ruling is regraded in place on +its lance/lancedb coordinates only, its datafusion half untouched. + +**Why it matters more than a typo:** every consumer repo's own `CLAUDE.md` +quotes this block as the cross-repo pin whitelist (MedCare-rs carries it +verbatim as an operator ruling). A session reading the stale text would pin a +consumer to lance 9 against a lance-11 spine and get an unsatisfiable graph — +the exact failure the block itself documents at `Cargo.toml:141-144`. + +**Proposed gate (not built — needs a decision):** a `pins-match-the-manifest` +CI check, same shape as `regenerate-and-diff`: parse the four family lines out +of `Cargo.toml` and out of the `CLAUDE.md` toml fence, fail on any mismatch. +Cheap (≈30 LOC), mechanical, and it fires exactly when a bump PR forgets the +prose. Open question for the operator: run it repo-local, or extend it to the +consumer repos that mirror the block. + +--- + ## ISS-STALE-AUTHORITY-LOCKS-RESIDUE (2026-09-04) — RESOLVED Corrects `ISS-STALE-AUTHORITY-LOCKS` (2026-08-25), whose *"Left open, diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index 2b8c1e3e1..4b57b2937 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -2394,6 +2394,8 @@ Paired mirror of OGAR `2c8836f` (two-sided COUNT_FUSE: `lance-graph-ogar` compil --- +> **Correction 2026-09-05 (W0 census, PR #1185 plan §2.5):** the entry below lists `commit_via` / `OgarRbac` / `graph-flow-action::dispatch_via` and "`impl ClassRbac for OgarClassView`" as shipped enforcement. The types exist; **no non-test caller of `commit_via`, `OgarRbac`, `authorize()` or `authorize_scoped()` exists in any repo on disk**, `rs-graph-llm` is not on disk, and `ogar-class-view/src/lib.rs:399` implements `ClassView` only (the RBAC bridge is the separate newtype `OgarRbac`, `rbac_impl.rs:38`, axes 2-4 unimplemented per its own comment `:74-76`). Field-level authorization (`classview_mask ∧ role_mask`) is UNENFORCED on every production path; recorded as the missing implementation on the canonical `ClassRbac × ClassView × WideFieldMask` path (OGAR `DISCOVERY-MAP.md:1581-1584`). The retired DataFusion masking path is not its replacement. + ## 2026-06-23 — IN PR (`claude/medcare-bridge-lance-graph-wmx76z`) — ActionHandler⟷RBAC⟷orchestration spine `contract::rbac`: `ScopeSpec` (axis-3 Copy token) + `ClassRbac` §4 default methods (`roles_reaching`/`row_scope`/`field_mask`; backward-compat, probe green). `contract::class_view::FieldMask::union`. `contract::action::ActionInvocation::commit_via` (no-admin-bypass convergence of the inline gate). `lance-graph-rbac::{authorize_scoped, ScopedDecision}` (§5 two-stage). `lance-graph-ogar::{OgarRbac, GrantSource}` (Q5 local newtype, §6 evaporation seam). rs-graph-llm: `graph-flow-kanban::{run_cycle, CycleOutcome}` + `graph-flow-action::dispatch_via`. Plan: integration-actionhandler-rbac-orchestration-v1. diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index a329aa1f5..03b8927d3 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -35,6 +35,17 @@ records against itself. | D-id | deliverable | status | |---|---|---| +| D-OIF-0 | Re-run `cargo run -p jc --example sigma_probe` on the current tree; record R², verdict, and reconcile the `R²=0.9949` (`bindspace.rs:39`) vs `ρ=0.9973` (`arm-discovery/lib.rs:13`) citations to their sources. Orchestrator-run, no worker. Falsifier: the recorded number is the probe's own printed R², not either citation | Queued (plan `open-ideas-fetch-v1` §4.3) | +| D-OIF-1 | `policy_hash_v1` — **RULING A, SUPERSEDED (2026-09-05 W0 census, plan §2)**: the DataFusion masking path has no deployed consumer (`ColumnMaskRewriter`'s only constructor is MedCare `patient.rs:150` under default-off `lance-phase2-rbac`, no Dockerfile enables it, decoder stub returns `None`) and redacts above the scan (`policy.rs:210`); operator ruled DataFusion out of planning. Becomes a retirement plan: first removal PR = `RedactionMode::Hash` + `NotYetWiredHashUdf` only; the rest of `policy.rs`/`rls.rs` is grace-period, frozen | Superseded — retirement, no worker | +| D-OIF-1-DEC | ~~hash family + key~~ — **WITHDRAWN 2026-09-05** (ruling A): no hash is chosen because no hash is built; the obligation's canonical owner is `ClassRbac × ClassView × WideFieldMask`, itself unenforced in the nine scanned repos (zero callers of `authorize`/`authorize_scoped`/`commit_via`/`OgarRbac` there; `effective_mask` not an identifier — a scoped statement, per the cross-repo reachability law in plan §2) — recorded as the missing implementation on the canonical path, not resurrected on DataFusion | Withdrawn | +| D-OIF-2 | `SigmaCodebook([Spd2; 256])` TYPE in the zero-dep contract (`from_le_bytes`/`to_le_bytes`, `entry`, `nearest` via the affine-invariant metric, all-SPD boundary check on load per `sigma_propagation.rs:108`); k-means BUILDER/EMITTER in `jc` (float to build); loaded INSTANCE homed in `cognitive-shader-driver` beside the column it serves. Tag + content invariants, **no digest pin**. Gates G1–G4 (§4.4) | Queued (blocked on D-OIF-2-DEC) | +| D-OIF-2-DEC | **Operator decision:** σ provenance — *fitted* (k-means over observed Σ, `sigma_codebook_probe.rs`) vs *declared* (typed-value tuple lookup, `sigma_propagation.rs:74-77`). Recommendation: fitted entries, declared as write-time fallback only. See plan §4.2 | Decision — operator | +| D-OIF-3 | First writer of a non-zero σ at the ingest path that today calls `BackingStoreWrite::set_sigma` with a constant (`backing.rs:310`). Falsifier: ≥2 distinct Σ shapes in → ≥2 distinct non-zero σ (can-fire); identical shapes in → one value (stay-silent) | Queued (blocked on D-OIF-2) | +| D-OIF-4 | `ewa_sandwich_x8` + slice driver in `crates/jc` over `ndarray::simd::F64x8` `Mul`/`Add` (**never `mul_add`**), same 12-mul/6-add order per lane as `ewa_sandwich.rs:185-199`. Gates: bit identity (`to_bits`) vs the scalar contract kernel on 1000 pairs incl. the tail path; bench pinned AFTER measurement (§3.5). Ships only paired with D-OIF-5 (zero production callers today — `E-A-RULED-HOME-…-VACANCY-1`) | Queued (plan §3) | +| D-OIF-5 | Hop re-quantization probe (jc pillar): for n ∈ {1,2,4,8,16}, ≥1000 seeded paths, `log_norm_growth` exact vs re-quantized-to-k=256-per-hop, against `pillar_5plus_bound(n)` with the existing 1.75× slack (`sigma_propagation.rs:268-285`). reduction mirrors the certified `ewa_sandwich::prove` (`ewa_sandwich.rs:325-343`): per depth/arm, CV of `‖log Σ_n‖²_F` across paths, tightness = CV / bound, PASS if ≤ 1.75 — NOT a direct comparison of `log_norm_growth` (an absolute Δ) against the bound (a CV). PASS = evidence for the measured synthetic model only, not proof `apply_edges` is sound; wiring σ-advance needs its own implementation + consumer tests and D-OIF-5-DEC. Arm 1 on the probe's own codebook, arm 2 on D-OIF-2/7's | Queued (plan §3.4) | +| D-OIF-5-DEC | **Operator decision:** where an edge's `M` comes from for σ-advance — `CausalEdge64` v2 spare is 3 bits (`edge.rs:557`), so not a per-edge 256-index; candidates: the source row's own σ, or a per-edge-class M. Wiring into `apply_edges` (`mailbox_soa.rs:348`) is gated on this AND on D-OIF-5 PASS | Decision — operator | +| D-OIF-6 | `IDEAS.md` hygiene: four new Open entries (F64x8 lever / the missing codebook / ternlog ⋂ §14 / citation resolvability) + three in-place Status flips on the fetched cards, each carrying the MEASURED blocker with a date | Shipped (this PR) | +| D-OIF-7 | The loaded `SigmaCodebook` INSTANCE + loader in `cognitive-shader-driver` (`sigma_codebook.rs`, new; owner W-7): read LE bytes + tag, construct through the contract type's boundary SPD check, expose to the driver. Gates: refuses a non-SPD table (can-fire) / accepts a valid one (stay-silent); byte-stable across two loads; tag mismatch fires. Does not touch `mailbox_soa.rs`/`backing.rs` | Queued (blocked on D-OIF-2) | | D-BSW-0 | Put the feature under CI in **BOTH** configurations — `--features mailbox-thoughtspace` AND `--features with-engine,mailbox-thoughtspace` (plan §4 M0). One job is NOT the deliverable: `dispatch_busdto` and `busdto_bridge_test.rs` are `with-engine`-gated (`engine_bridge.rs:280`), so a mailbox-only job compiles neither and stays green while the paired configuration breaks. Today the 4 `w2_differential` bit-identity tests and every `BackingStoreWrite` Mailbox arm have ZERO coverage. Precedent `rust-test.yml:158-173`. Falsifier: test count strictly increases in each configuration and the 4 tests appear by name | Queued (plan `bindspace-mailbox-soa-wiring-v1` §4) | | D-BSW-1 | Wire `BackingStoreWrite` (`backing.rs:164-314`, 9 methods, both arms real) into the driver write path — it has zero callers outside its own test module. Adds a caller, not a capability | Queued (blocked on D-BSW-0) | | D-BSW-2 | Route the production BindSpace writers through the shim — **eight sites, not five**: `engine_bridge` `write_qualia_observed:490` / `write_qualia_17d:548` (direct), `persist_cycle:784` (edge+meta; cycle write is the documented loss), `ingest_codebook_indices:58` (composed last); plus the three `serve.rs` handlers `encode_handler:607` (direct `set_content`), `:139` and `:639` (via `Arc::get_mut`). `dispatch_busdto:281` **wires — tenant TBD by probe** (⊘ regraded 2026-09-05 from "excluded pending a decision" by operator ruling R2, `E-EVERYTHING-WIRES-TO-SOA-V3-CE64-IS-ALU-LEGACY-1`): its 16-dim `qualia_f32` has no f32 VECTOR tenant on MailboxSoA (only the scalar `energy: [f32;N]`, `mailbox_soa.rs:66`); candidates are `QualiaI4_16D` via `set_qualia` or `atoms.rs` `I4x32/I4x64`, chosen by a D-MTS-6-proxy quantization probe pre-registered before its first run (plan §4). All eight must land BEFORE D-BSW-3 or dispatch reads the mailbox while `/v1/shader/encode` writes the singleton | Queued (blocked on D-BSW-1) | diff --git a/.claude/board/SUPERSESSION-INDEX.md b/.claude/board/SUPERSESSION-INDEX.md index 8ce4f62b0..156f5ff85 100644 --- a/.claude/board/SUPERSESSION-INDEX.md +++ b/.claude/board/SUPERSESSION-INDEX.md @@ -14,7 +14,7 @@ ## What this table says **`BindSpace` is the shape of the problem.** Marked RETIRE, and simultaneously the -most-referenced symbol here: **68 crate files, 46 plans, 41 of them blind.** +most-referenced symbol here: **68 crate files, 47 plans, 41 of them blind.** That is a programme, not a cleanup. **`GateState` is the sharpest case: 1 plan names it and *every one* is blind.** @@ -60,8 +60,8 @@ coverage instead. | `GateState` | REPURPOSE | — | 14 | 1 | 1 | | `MergeMode` | REPURPOSE | — | 8 | 13 | 12 | | `ResonanceDto` | REPURPOSE | `PerturbationDto` | 2 | 12 | 7 | -| `BindSpace` | RETIRE | — | 68 | 46 | 41 | -| `CollapseGateEmission` | RETIRE | — | 5 | 13 | 12 | +| `BindSpace` | RETIRE | — | 68 | 47 | 41 | +| `CollapseGateEmission` | RETIRE | — | 5 | 14 | 12 | | `ThinkingStyle` | RETIRE-toward-contract | — | 51 | 28 | 24 | ## Table 2 — plans naming a ruled symbol without citing the ruling (73) diff --git a/.claude/plans/open-ideas-fetch-v1.md b/.claude/plans/open-ideas-fetch-v1.md new file mode 100644 index 000000000..2cc5e9409 --- /dev/null +++ b/.claude/plans/open-ideas-fetch-v1.md @@ -0,0 +1,245 @@ +# Open-ideas fetch — three stale cards re-derived from the tree (v1) + +> **Status:** MEASURED / ready-to-execute — PLANNING ONLY in this PR. Every +> claim below carries file:line from a read of the CURRENT tree (origin/main +> `ac9148f7`, #1171, plus the FF to `afeb0458`). NOT COMPILED, NOT RUN — no +> `cargo` was invoked; every "exists / is wired / has callers" statement is +> structural (grep + read), and §8 names the ones that must be confirmed by +> execution before they are believed. +> +> **READ BY:** the orchestrator that dispatches the Sonnet workers (§7 carries +> the per-D briefs), anyone touching `lance-graph-callcenter::policy`, +> `sigma_propagation`, the `MailboxSoA.sigma` column, or `crates/jc`. +> +> **Origin:** `IDEAS.md` had gone 82 days without an entry (newest 2026-06-15) +> while ~900 PRs merged. Three of its Open cards were picked as the highest +> value; **each one changed shape on contact with the tree**, which is the +> reason this plan exists rather than three direct PRs. +> +> **Confidence:** HIGH on the census; LOW-to-none on anything marked +> DECISION — those are the operator's, stated with a recommendation and +> deliberately not taken. + +## 0. The three headline corrections + +| card (IDEAS.md) | what the card says | what the tree says | +|---|---|---| +| `IDEA-POLICY-HASH-UDF` (`:1162`) | "policy_hash_v1 UDF **registration**" | Registration is not the blocker. The UDF is bound as an `Arc` **object inside the `Expr`** (`policy.rs:137`), and DataFusion executes the embedded object without any by-name lookup — proof: `register_vsa_udfs` (`vsa_udfs.rs:574`) has **zero callers** in the tree and its UDFs still execute in tests. The blocker is the **body**: `invoke_with_args` returns `NotImplemented` (`policy.rs:~330`). **Superseded the same day (§2, W0 census): the body was never the blocker either — the DataFusion masking path has no deployed consumer, and the operator ruled DataFusion out of planning. Ruling A: retire.** | +| `IDEA-B1-HARDWARE-BACKENDS` (`:1062`) | "AMX/MKL backends for sigma_propagation, waits on ndarray #119/#121" | The kernel is a **2×2 f64** sandwich — three scalars, 12 mul + 6 add (`sigma_propagation.rs:210-227`). An AMX tile is 16×16 bf16/int8; an MKL `dgemm` call costs more than the 18 flops it would do. The idea is **mis-shaped for its own kernel**. The real lever is vertical batching — `F64x8` (8 edges/instruction), whose `Mul`/`Add` already exist on every backend. AND: `ewa_sandwich(` has **zero production call expressions** outside `jc` + the contract (grep, §3.2) — every "caller" is a doc-comment mention. | +| `IDEA-CAUSAL-EDGE-TENSOR-SIDECAR` (`:1126`) | "design a 9-byte sidecar (`CausalEdge64` + 1 byte Σ index) OR Block 14/15" | **The 1-byte index already shipped, as a SoA column** — `BindSpace.fingerprints.sigma: Box<[u8]>` (`bindspace.rs:54-58`), `MailboxSoA.sigma: [u8; N]` (`mailbox_soa.rs:125-133`), `set_sigma` (`:670`), `BackingStoreWrite::set_sigma` both arms (`backing.rs:253-257`). Neither the sidecar nor Block 14/15 is live. **What does NOT exist is the codebook the index points at** — §4. | + +## 1. Frozen decisions this plan inherits (cited, not re-derived) + +- **Zero-dep contract.** `lance-graph-contract/Cargo.toml` `[dependencies]` is empty by design and says why (a path dep there broke every CI invocation, 2026-07-07). Nothing in this plan adds a dependency to it. +- **All SIMD from `ndarray::simd`** (`simd-savant`; W1a consumer contract, ndarray `.claude/knowledge/vertical-simd-consumer-contract.md`). Consumer code composes typed wrappers; it never writes intrinsics. +- **Bit identity between the jc kernel and the contract copy is CI law** — `jc::ewa_sandwich::tests::the_contract_copy_matches_the_certified_kernel_bit_for_bit` (`ewa_sandwich.rs:~425`, 1000 sampled SPD pairs, `to_bits()`, no tolerance; `jc-proof.yml`). Any batched kernel joins that law or does not land. +- **Internal head pins are absolutely and permanently prohibited** (MedCare-rs `CLAUDE.md`, operator 2026-08-30). A frozen codebook artifact gets a **tag + content invariants**, never a digest gate. +- **Indices, not content** (`I-VSA-IDENTITIES`; `mailbox_soa.rs:128-131`): the codebook stays shared/cold; rows carry the 1-byte reference. +- **Masking is projection-side, never a DataFusion rewrite** (operator ruling 2026-09-05, recorded on #1188 as `E-PLANNING-MIGRATES-TO-LOCO-R2IL-DATAFUSION-IS-GRACE-PERIOD-1`): the field population is `ClassView × WideFieldMask`, consumed by Lance reads and loco programs; DataFusion-hosted surfaces are grace-period — maintained, never extended. No new operator, rule, or UDF routes into DataFusion. +- **The falsifiability rule** (`CLAUDE.md`): every guard needs a can-fire AND a can-stay-silent test on non-trivial inputs; a threshold needs an inertness test; a doc claim is not a behaviour. +- **Sonnet workers: edit-only, no `cargo`, no `git`, disjoint files; the orchestrator compiles once** (`agent-cargo-hygiene.md`; `sonnet-worker-guardrails.md` §1 pasted verbatim into every brief). + +## 2. D-OIF-1 — `policy_hash_v1`: RULING A, SUPERSEDED — a retirement plan, not a crypto task + +> **Re-derived 2026-09-05 (W0 architecture census, four read-only Opus tracers + orchestrator verification).** +> Independent census on #1188 (banked at `.claude/board/exec-runs/d-oif-1-census-main-thread.md` on that branch) reached the same ruling; it scanned lance-graph only, so it reports the rewriter as test-constructed — the one extra constructor is the private-repo MedCare `routes/patient.rs:150`, which is why the removal cone below is narrower than "delete `policy.rs` entire": that deletion breaks MedCare's `lance-phase2-rbac` compile until MedCare retires the feature first. Its proposed `E-THE-UNFINISHED-UDF-WAS-NOT-THE-DEBT-1` is the same finding as the banked `E-THE-UNFINISHED-FUNCTION-WAS-NOT-THE-DEBT-1` — one entry, not two. +> +> The previous §2 asked "which hash?". That question was one abstraction generation behind: it assumed the DataFusion policy-rewriter execution model still owned field-level authorization. The census below shows it never reached a binary, and the operator ruled the same day: **"every planning is in migration to ogar-loco and ogar-r2il; DataFusion is out of the picture; what exists gets a grace period; nothing new will migrate to it."** A hash body for `policy_hash_v1` is *new* work on the DataFusion path and is barred by that ruling regardless of the census. No hash family is chosen; `D-OIF-1-DEC` is **withdrawn**. + +**Census scope and the law it violated (operator correction 2026-09-05):** the first pass asked "who calls this inside lance-graph?" and read zero local call sites as a production verdict. That is the wrong boundary for a deliberately cross-repo substrate — the same category error lance-graph-java PR #76 corrected for `WideFieldMask` one layer down. **Law: for a cross-repo substrate, production reachability terminates at deployed consumers, not at the repository boundary.** Scanned after the correction: lance-graph, OGAR, MedCare-rs, a2ui-rs, lance-graph-java, r2sleigh, blockly-rs, bardioc (the last two cloned read-only on operator input). Three verdicts below are STRUCK, not softened; the RBAC zero-caller verdict is rescoped to the nine repos, never global. + +### 2.1 Tree verdict (production census; "production" = a real call chain from a binary / server handler, never `pub mod`, a feature flag, a registration helper, a test, or a doc comment) + +1. `ColumnMaskRewriter` has exactly one non-test constructor in all seven repos: `MedCare-rs/crates/medcare-server/src/routes/patient.rs:150`, inside `get_one_via_lance` (`:85`, `#[cfg(feature = "lance-phase2-rbac")]`), reached only for `?source=lance` (`:52-53`). +2. `lance-phase2-rbac` is default-off (`medcare-server/Cargo.toml:215` `default = []`) and **no Dockerfile enables it** (`docker/Dockerfile.railway:175`, `Dockerfile.railway.OCR:49`, `Dockerfile.reasoning` all build `lance-phase2,reasoning`). +3. Even when compiled, the path's row decoder `record_batch_to_patient` (`patient.rs:200-211`) is a stub that logs and returns `None`; the handler 500s. No user has ever received a masked row from this path. +4. The rewriter redacts **above the scan**: `rewrite_plan` (`policy.rs:210`) maps expressions and `recompute_schema`s; `TableScan.projection` is never written (`extract_table_name` `:226-241` only reads it). The forbidden column is scanned from Lance, materialized, then overwritten — post-hoc redaction, the exact anti-pattern the invariant forbids. +5. `RedactionMode::Hash` (`policy.rs:130-140`) binds `NotYetWiredHashUdf`; any plan containing it fails at execute with `NotImplemented` (`:339`). `policy_hash_v1` has no implementation and no `register_udf` anywhere. `register_vsa_udfs` (`vsa_udfs.rs:574`) has zero callers in all repos. +6. `PolicyRewriter` (`policy.rs:56`) has one impl and `dyn PolicyRewriter` appears nowhere — a one-impl indirection, not a policy VM. +7. The replacement path's enforcement is **not found in the nine scanned repos** (a scoped statement, per the law above — not a global one): `lance-graph-rbac::authorize()`/`authorize_scoped()` (`authorize.rs:66,182`), `contract::ClassRbac` (`rbac.rs:143`), `ActionInvocation::commit_via` (`action.rs:327`) and `lance-graph-ogar::OgarRbac` (`rbac_impl.rs:38`) have zero non-test callers there (bardioc and blockly-rs included; `rs-graph-llm`, named as `dispatch_via`'s home, is not on disk and was not scanned). `effective_mask` is not an identifier in any `.rs` file. There is no `ogar-rbac` crate; `ogar-auth` is authentication only (password/TOTP). +8. MedCare's live authorization is entity-string keyed: `patient.rs:280 bridge.authorize_read("Patient", …)` → `lance-graph-rbac::policy::Policy` → `AccessDecision`. No mask reaches it. Field projection in production is `views/project.rs:229` (`WideFieldMask::from_positions` from a **view** spec, no role operand) — a view mask, not RBAC. +9. The only genuine `surface ∩ role` fail-closed projection is `a2ui-server/src/project.rs:70-83` (`WideFieldMask::intersect`, `NoRoleGrant` on empty role) — and `a2ui-server` has no `[[bin]]`, no `main`, and no dependent crate. +10. Rubicon/Kanban — **first verdict STRUCK.** The first pass said "`try_advance_phase` has no production entry point"; that was the repo-boundary error. The checked Kanban law has a production consumer: **bardioc** `substrate-b` (binary `substrate-b/src/bin/substrate_b.rs` over `MailboxSoA<32>`; `substrate-b/src/kanban.rs:54` re-exports the contract's `KanbanColumn`/`KanbanMove`/`RubiconTransitionError`, `:103-120` gates every move on `KanbanColumn::can_transition_to`; `supervisor.rs` drives it; `substrate-b-telemetry/src/shader_sink.rs` `KanbanShaderSink` tags emissions with the source mailbox's phase). Precision: bardioc enters the law through `can_transition_to` on its own `advance`, so `MailboxSoaOwner::try_advance_phase` (`soa_view.rs:311`, seal path `cycle_driver.rs:560` → `advance_phase` → `self.phase = to`, `mailbox_soa.rs:953`) is one of two entry points into the SAME checked DAG (`kanban.rs:98-106`), not the only one. What held from the first pass and still holds: no actor/controller survives — the `KanbanActor`/`KanbanMsg` actor and its RPC drivers were deleted 2026-08-05, while `kanban_actor.rs` itself is LIVE as the read-only meta-awareness surface (`PhaseCensus` `:57`, `mul_target` `:149` composed by the production seal driver `cycle_driver.rs:805`, `parse_kanban_step` `:163`; re-exported `supervisor/src/lib.rs:82`; the one-read-only-pass precedent `rubicon_witness.rs:32`; read by the awareness rungs, `rung_horizon.rs:5`) — a census, never a controller; no `Baton`/`CollapseGateEmission`/`CommitHook` type; the crossing `Planning → CognitiveWork` is one-way; refusal does not mutate (`soa_view.rs:329-346`); RBAC holds no Kanban state, lifecycle makes no authorization decision, loco/r2il carry no authorization vocabulary; lance-graph-java excludes the `kanban` module by design (G11 fence, `native/lgj-abi/tests/g11_contract_import_fence.rs:314`). + +**So:** the invariant «forbidden fields absent from the authorized projection, not materialized and masked by a UDF» is *violated by the only field-level mechanism that was ever written* (item 4) and *satisfied by nothing found deployed in the scanned repos* (items 7–9). The invariant «a Rubicon transition is an SoA-owned mutation, not an actor command» **holds** in code and **in production** (item 10, bardioc) and is contradicted only by stale prose (§2.5). **This makes the ruling more decisive, not less:** DataFusion planning/policy is grace-period archaeology beside an execution architecture that already has real consumers — `ogar-loco` (blockly-rs), Rubicon/Kanban + SoA (bardioc), R2IL via `ogar-r2il`/`ruff_r2il` (r2sleigh → lance-graph-java lineage). `policy_hash_v1` is rejected because new work would migrate semantics *backwards* into the grace-period architecture after the successor acquired consumers — not because the successor is prospective. + +### 2.2 Obligation table + +| old obligation | current owner | production evidence | action | +|---|---|---|---| +| `policy_hash_v1` UDF body (`IDEA-POLICY-HASH-UDF`, PR #301) | none — the DataFusion policy path | items 1–5: no deployed consumer; execute → `NotImplemented` | **RETIRE.** No body, no hash choice. `D-OIF-1-DEC` withdrawn | +| `RedactionMode::Hash` | same | binds a UDF that cannot execute | **REMOVE with the cone** (§2.3) — a landmine, not a mode | +| `NotYetWiredHashUdf` / `policy_hash_v1` | same | `policy.rs:279-339`, zero registrations | **REMOVE with the cone** | +| `ColumnMaskRewriter` / `ColumnMaskRegistry` / `RedactionMode::{Null,Constant,Truncate}` / `PolicyRewriter` / `PolicyKind` | same (`policy.rs`) | one gated, undeployed, stub-terminated MedCare caller | **GRACE PERIOD** (operator ruling): retained as-is, regraded SUPERSEDED, frozen — no new work, no new callers. Removal is its own PR once MedCare's `lance-phase2-rbac` feature is retired (`patient.rs:85-211`, `state.rs` `column_mask_registry`/`rls_registry`/`session_context`, `medcare-analytics::column_mask_bridge`) | +| `RlsRewriter` (`rls.rs`) | same | same single caller (`patient.rs:146`) | **GRACE PERIOD**, same cone, same condition. Not a policy VM: a tenant predicate — but on the retired path | +| `register_vsa_udfs` (`vsa_udfs.rs:574`) | none | zero callers, any repo | **REMOVE** candidate; separate from the policy cone (it is `query`-gated, not `auth-rls-lite`). Not touched in this PR | +| DataFusion RLS / optimizer-rule registration | `patient.rs:146-150` only | the only `with_optimizer_rule` in any repo | **GRACE PERIOD** with the MedCare feature | +| `unified_bridge.rs` `authorize_{read,write,act}` | `lance-graph-callcenter` | live: `patient.rs:280` | **RETAIN.** Entity-level allow/deny before SQL; never touches a plan | +| Field-level authorization (the obligation `policy_hash_v1` was one arm of) | **VACANCY** on the canonical path: `ClassRbac × ClassView × WideFieldMask` | items 7–9 | **RECORD as the missing implementation** on the canonical OGAR/ClassView path (OGAR already says so: `DISCOVERY-MAP.md:1581-1584`, `DOCIR-COMPOSITION-GROUNDING.md:75`, `PROBE-OGAR-RBAC-AUTHORIZE`). Not resurrected on DataFusion. Not built in this plan | +| `authorize_scoped` mask fold | `lance-graph-rbac/authorize.rs:199-216` | zero callers; folds a **union** over roles and returns `FieldMask::FULL` on non-Allow (`:190-196`) — fails OPEN in the mask | **REGRADE** to "TRANSPORT ONLY, fail-open in the mask value" — a design defect to fix on the canonical path, not evidence for the old one | +| Rubicon lifecycle | `KanbanColumn` DAG + `MailboxSoaOwner::try_advance_phase` (contract); read-only meta-awareness `PhaseCensus`/`mul_target` (`kanban_actor.rs`, live); **production consumer: bardioc `substrate-b`** (item 10) | `substrate-b/src/kanban.rs:103-120`, `bin/substrate_b.rs`, `shader_sink.rs` `KanbanShaderSink` | **RETAIN**, production. Prose corrections only (§2.5) | +| Thinking/planning | **production, cross-repo:** `ogar-loco` ← blockly-rs (the thinking palette; axum binary `crates/blockly-web/src/main.rs`, `blockly-abi`/`blockly-shim`/`blockly-run`, `Cargo.toml:40` path dep) and MedCare `ddx_loco` (`views/zugfolge.rs:534`); `ogar-r2il` = the R2IL→loco bridge (r2sleigh's 82 opcodes as an `ogar_loco::Vocabulary` + masked lane projection) over r2sleigh's live `r2il` crate (`r2sleigh-cli` bin); the lance-graph-java lineage consumes R2IL/SSA in-process via `ruff_r2il` (its board: shipped, not pending — a direct `lgj-abi → ogar-r2il` Cargo dep is NOT required as proof, per the law). Planner `thinking/`,`mul/`,`strategy/` linked into medcare-server but uncalled | no DataFusion UDF or rule performs reasoning on any production path (`datafusion_planner/udf.rs:130-663` is vector/hamming distance only) | first-pass verdicts "one live loco consumer" and "ogar-r2il probe-only" **STRUCK** (repo-boundary error). Hypothesis **confirmed**: DataFusion never owned reasoning in production; the successor stack is already production. Nothing to move | + +### 2.3 Remove / retain / regrade (exact) + +- **REMOVE now (this arc, own PR, after grace-period sign-off):** nothing is deleted in #1185. The *first* removal PR is scoped to the dead-by-construction pieces only — `RedactionMode::Hash` + `NotYetWiredHashUdf` + the `policy_hash_v1` name (`policy.rs:130-140, 262-339`) and the test `redaction_mode_hash_binds_not_yet_wired_udf` (`:598-620`) — because they cannot execute today and no grace-period consumer can depend on them. Disable-run: removing the variant must break exactly that test and nothing else. +- **GRACE PERIOD (frozen, regraded SUPERSEDED, no new callers):** `policy.rs` remainder (`PolicyRewriter`, `PolicyKind`, `ColumnMaskRegistry`, `ColumnMaskPolicy`, `ColumnMaskRewriter`, `RedactionMode::{Null,Constant,Truncate}`, and the same-shape stubs `RowEncryptionPolicy` / `DifferentialPrivacyPolicy` `policy.rs:344-420`, zero callers), the DataFusion forward-stubs `datafusion-dispatch` / `datafusion-plan` / `postgrest.rs:940-960` (`Err("not yet implemented")`) / `MembraneRegistry::with_rls`, `rls.rs`, the `lib.rs:114-125` / `:93-99` gates, feature `auth-rls-lite`; MedCare `patient.rs:52-54, 85-211`, `state.rs` `column_mask_registry` / `rls_registry` / `session_context` / `build_session_context`, `medcare-analytics/src/column_mask_bridge.rs`. Removal condition: MedCare retires `lance-phase2-rbac` (its own private-repo PR) — then the callcenter cone falls in one PR. +- **RETAIN, untouched:** `lance-graph-python/src/graph.rs` (`SessionContext` `:1208,:1518`), `lance-graph-catalog/src/{connector,table_reader}.rs`, `holograph/src/storage.rs`, `callcenter/src/{graph_table,filter_expr,lance_membrane,unified_bridge}.rs`, `callcenter/src/bin/audit_verify.rs` + `audit.rs` (Lance dataset open), `lance-graph-planner/src/optimize/` (an in-house `OptimizerRule` trait of the same name, unrelated), MedCare `views/project.rs` + `medcare-rbac`, `tesseract-paperless/src/store.rs`. These are storage/query translation over Lance — the grace-period storage layer, not the policy VM. +- **REGRADE (board):** `IDEA-POLICY-HASH-UDF` → Superseded; `D-OIF-1` → Superseded (retirement plan); `D-OIF-1-DEC` → Withdrawn; `LATEST_STATE.md:2389,2393` claims (see §2.5) get a dated correction line, not an edit. + +### 2.4 Layer audit (Rubicon / Heckhausen vocabulary) + +| layer | owner in code | impersonation found? | +|---|---|---| +| 1 Lifecycle control | `KanbanColumn` DAG (`kanban.rs:98-106`) + `MailboxSoaOwner::try_advance_phase` (`soa_view.rs:311`); Planning = pre-decisional, `Planning→CognitiveWork` = the Rubicon crossing, `CognitiveWork` = actional, `Evaluation` = post-actional, `Commit`/`Plan`/`Prune` = outcomes; `Planning→Prune` = pre-Rubicon veto | none. Production consumer: bardioc `substrate-b`. `Commit`'s calcify step is DECLARED only (`kanban.rs:48-56`) | +| 2 Action semantics | `ActionState` (OGAR `ogar-vocab/lib.rs:676` canonical wire type; contract `action.rs:44` the Rust mirror, unconsumed), `ActionDef`, `KausalSpec`, `ActionInvocation::commit` | `commit` inlines its own RBAC check (`action.rs:283`) — documented design, not drift. `CommitHook` **does not exist** (prose only) | +| 3 Authorization | contract `rbac.rs` + `lance-graph-rbac` (types + un-called kernel); live gate = string-keyed `Policy` | none on lifecycle. The ClassView∧role fold is unbuilt | +| 4 Execution/reasoning | `ogar-loco` (production: blockly-rs, MedCare), `ogar-r2il` (the R2IL→loco bridge over r2sleigh's live IR; lance-graph-java lineage via `ruff_r2il`), planner thinking (linked, uncalled) | none: zero authorization words in loco/r2il | +| 5 Storage/query | Lance / DataFusion (B1–B9 in the census) | the one policy hook (`patient.rs:146-150`) is on the undeployed path; DataFusion owns no lifecycle state | + +**The one category error worth naming:** the prior plan treated *authorization* (layer 3) as a *storage/query* concern (layer 5) because the only code that existed lived there. The census shows layers 3 and 5 are currently **disjoint**, not layered — where ClassView×mask genuinely governs columns (MedCare `views/`, atlas/graph reads of the resident bake), DataFusion and Lance are not in the path at all. + +### 2.5 Stale prose contradicted by the tree (corrected in this PR where the file is ours and non-append-only; dated correction lines elsewhere) + +- `a2ui-rs/CLAUDE.md` § "RBAC is real": "`ClassRbac::field_mask` is being retyped to `WideFieldMask` … `WideFieldMask::ALL`" — `rbac.rs:176` still returns `FieldMask` (u64); `WideFieldMask::ALL` does not exist (`class_view.rs:275` has only `EMPTY`; `full_for` `:360`). *(a2ui-rs repo; not touched here — filed for that repo.)* +- `OGAR/crates/ogar-a2ui-frame/src/lib.rs:32`: states the C1.4 retype as done. *(OGAR repo; not touched here.)* +- `LATEST_STATE.md:2389` lists `commit_via` / `OgarRbac` / `graph-flow-action::dispatch_via` as shipped enforcement — the types exist, the callers do not; `rs-graph-llm` is not on disk. `:2393` "`impl ClassRbac for OgarClassView`" — no such impl (`ogar-class-view/lib.rs:399` impls `ClassView` only). *(Append-only: dated correction line added in this PR.)* +- `.claude/v3/knowledge/mailbox-kanban-model.md:30`, `.claude/v3/COMPONENT-MAP.md:79` ("EXTEND"), `.claude/v3/knowledge/write-on-behalf.md:8` (`ACTOR-OWNED`) and `:68`: present the `KanbanActor` actor as the structural owner / pending W1 work — the actor was deleted 2026-08-05 (`LATEST_STATE.md:1824,1860`); the file survives as the read-only `PhaseCensus` surface (item 10). *(Corrected in this PR: dated notes, in place — first wording called the file a tombstone; corrected same day on operator input.)* +- This plan's own §0 row 1 and `INTEGRATION_PLANS.md` entry: "the blocker is the UDF body" — true as far as it went and still one generation behind; superseded by this §2. +- `.claude/patterns.md:89` names `NotYetWiredHashUdf` as a live pattern — left as-is until the removal PR lands, then updated in that commit. + +### 2.6 What this plan does NOT do (hard constraints honoured) + +No hash body, no hash choice, no new actor/controller, no new lifecycle carrier, no new policy VM, no SoA widening, no RBAC moved into loco/r2il, no Rubicon state moved into RBAC, no deletion in this PR, and DataFusion registration was never counted as ownership evidence. + +## 3. D-OIF-4 / D-OIF-5 — Σ-propagation: the batched kernel and the hop probe + +### 3.1 Why "hardware backends" is the wrong shape + +- Kernel: `Spd2 { a, b, c }` f64 (`sigma_propagation.rs:113-117`); `ewa_sandwich` = 8 products for `P = M·Σ`, 8 for `R = P·Mᵀ`, then `b = 0.5·(r01 + r10)` (`:210-227`). Byte-identical copy in `jc/src/ewa_sandwich.rs:185-199`. +- AMX: `hpc/amx_matmul.rs` exposes 16×16 tiles (`tile_dpbusd`, `tile_dpbf16ps`, `:288-359`); `simd_amx.rs` exposes u8×i8 VNNI dot/matvec. Neither has a 2×2 f64 shape. MKL `dgemm` on 2×2 is dominated by call overhead. **Rejected for this kernel** — recorded, not deferred. +- The 3×3 analogue exists as a jc probe (`ewa_sandwich_3d.rs`, `Spd3`, `:378`); the n×n idea is `IDEA-PILLAR5PLUS-HIGHER-DIM-SPD`. AMX becomes plausible only at ≥16×16 in **bf16**, and bf16 rounding on the SPD cone can lose PSD — that is its own falsifier and **out of scope** here. + +### 3.2 The real lever, and the real gap + +- `F64x8` carries `Add`/`Mul` on **every** backend with no FMA in the path: AVX-512 `impl_bin_op!(F64x8, Mul, mul, _mm512_mul_pd)` (`simd_avx512.rs:446-448`), AVX2 (`simd_avx2.rs:973-987`), NEON (`simd_neon.rs:1019-1047`), scalar via `impl_float_type!(F64x8, f64, 8, …)` (`simd_scalar.rs:510`). `mul_add` exists (`:376`) and **must not be used** — it would break bit identity with the scalar kernel. +- So the batched kernel is ordinary consumer code over typed wrappers: 8 edges per lane-op, same 12-mul/6-add order per lane. **No ndarray change is needed; the STOP rule is not triggered.** +- **Home:** `crates/jc` (deps `ndarray`, `Cargo.toml:21`, "MANDATORY"). Not the contract (zero-dep). Name: `ewa_sandwich_x8(m: &[Spd2; 8], sigma: &[Spd2; 8]) -> [Spd2; 8]` plus a slice driver `ewa_sandwich_batch(m: &[Spd2], sigma: &[Spd2], out: &mut [Spd2])` handling the tail with the scalar kernel. +- **The gap that decides the sequencing:** `grep -rn "ewa_sandwich(" crates/` outside `jc/` and `sigma_propagation.rs` returns **nothing**. The four files that mention it — `cognitive-shader-driver/src/bindspace.rs:41`, `mailbox_soa.rs:129`, `perturbation-sim/src/splat.rs:19`, `lance-graph-arm-discovery/src/aerial/codebook.rs:16` — do so in **doc comments**. A faster kernel for a function nobody calls is `E-A-RULED-HOME-NEEDS-A-FIRST-CONSUMER-OR-IT-IS-A-VACANCY-1` verbatim. Therefore D-OIF-4 ships **only paired with D-OIF-5**, whose result decides whether the first consumer (§3.3) is sound. + +### 3.3 The named first consumer (NOT built in this plan) + +`MailboxSoA::apply_edges` (`mailbox_soa.rs:348-372`) receives `(row, CausalEdge64)` deliveries and today updates only `energy[row]` and `plasticity_counter[row]`; `sigma[row]` is never advanced. The contract's own planned use-site is "B4 shader-driver-sigma-propagate … propagate `sigma_path = ewa_sandwich(...)` along the resonance chain" (`sigma_propagation.rs:78-80`). With a codebook (§4), one hop is: `Σ' = sandwich(M, codebook[sigma[row]])`, then `sigma[row] = nearest(codebook, Σ')`. Two things block wiring it, and this plan does not pretend otherwise: + +1. **Where `M` comes from.** A `CausalEdge64` carries no matrix; its v2 spare is **3 bits** (`edge.rs:194, 557` — bits 61-63), so it cannot carry a 256-entry index. Candidates: the *source* row's own `sigma` (M = codebook[σ_src]), or a per-edge-class M. **DECISION D-OIF-5-DEC, operator's.** +2. **Whether re-quantizing to k=256 after every hop keeps concentration.** That is D-OIF-5. + +### 3.4 D-OIF-5 — the hop re-quantization probe (jc) + +Pre-registered, and **mirrored on the certified comparison** (`crates/jc/src/ewa_sandwich.rs:294-343`, `cv_measured` / `cv_tightness`) — not a new gate shape: + +- **Hop-matrix source:** the SAME seeded generator the certified pillar uses (`ewa_sandwich.rs:95` Box-Muller, `:215` random rotation θ; SplitMix64 state, seed fixed) — one `M` per hop per path. +- **Paths:** `N_PATHS ≥ 1000` per depth, `n ∈ {1, 2, 4, 8, 16}`, seed Σ as in the pillar. +- **Two arms per path:** (i) exact — `Σ_k = ewa_sandwich(M_k, Σ_{k-1})`; (ii) re-quantized — after every hop, `Σ_k ← codebook[nearest(codebook, Σ_k)]` with `nearest` in the affine-invariant metric `d(A,B) = ‖log(B^-½·A·B^-½)‖_F` (the probe's own metric, `sigma_codebook_probe.rs:24`). +- **Reduction (the part the first draft got wrong):** `log_norm_growth` returns an ABSOLUTE change in `‖log Σ‖²_F` (`sigma_propagation.rs:254`) while `pillar_5plus_bound(n)` returns a **coefficient of variation** (`:274-285`); they are not comparable directly. So, exactly as `ewa_sandwich::prove` does: per depth and per arm, take `‖log(Σ_n)‖²_F` over all paths, compute `mean` and `std`, `cv_measured = std / mean`, `tightness = cv_measured / pillar_5plus_bound(n)`, **PASS if `tightness ≤ 1.75`** (`ewa_sandwich.rs:325-343`). Report both arms' tightness and their ratio (does re-quantization widen concentration, and by how much). +- **Verdict semantics:** PASS on arm (ii) at every `n` is **evidence that re-quantization preserves concentration in THIS synthetic model** — it is not proof that `MailboxSoA::apply_edges` is sound. Wiring σ-advance into `apply_edges` stays its own deliverable with its own implementation and consumer tests, outside this plan, and still needs `D-OIF-5-DEC`. Any FAIL at depth `n` shelves that consumer with the number. +- **Arms by artifact:** arm 1 runs on the probe's own k-means codebook (`sigma_codebook_probe.rs`, `N_EDGES=10_000, K=256, 100 iters, SEED` fixed at `:49-52`), so it does not wait on D-OIF-2; arm 2 re-runs on the real codebook once D-OIF-2/D-OIF-7 exist. + +### 3.5 D-OIF-4 gates + +| # | assertion | disable | +|---|---|---| +| G1 | `ewa_sandwich_x8` is **bit-identical** (`to_bits`) to the scalar contract `ewa_sandwich` on 1000 sampled SPD pairs incl. non-zero off-diagonals (the existing test's anti-vacuity guard) | replace one `*` + `+` with `mul_add` | +| G2 | the slice driver's tail path (len % 8 ≠ 0) is bit-identical too | drop the tail loop | +| G3 | a bench (`jc/examples`) prints ns/edge for scalar vs x8 at N = 65 536; the number is **pinned after measurement**, never predicted | — | +| G4 | `jc-proof.yml` still green (the certified kernel is untouched) | — | + +## 4. D-OIF-0 / D-OIF-2 / D-OIF-3 — the Σ codebook that three files point at and none holds + +### 4.1 The finding + +Every σ byte in the substrate is an index into a codebook that **does not exist**: + +- `sigma_propagation.rs:73` — "indexing into a 256-entry static `SigmaCodebook` of `Spd2`". +- `contract/src/splat.rs:308` — "The full SigmaCodebook lives in **lance-graph-cognitive**". +- `arm-discovery/src/aerial/codebook.rs:16-19` — "built and certified **offline by `crates/jc`**". +- `grep -rn SigmaCodebook crates/` → those two doc lines. `crates/lance-graph-cognitive/src` → zero hits. `jc` has the **viability probe** (`sigma_codebook_probe.rs`) and no builder/emitter. + +Three claimed homes, zero implementations. The column's writers: `backing.rs:310` (write-shim loop) and one test (`:347`, writes `9`). Readers: two planner examples dumping the byte (`blw_tenant.rs:190`, `blw_rows.rs:289`). Every production row has `sigma = 0`, documented as "untrained / first centroid" (`bindspace.rs:54`) of a codebook with no centroids. + +**Two numbers, one claim.** `bindspace.rs:39,57` cite "R²=0.9949 at k=256 (#288)". `arm-discovery/src/lib.rs:13` and `codebook.rs:18` cite "ρ=0.9973". The probe computes **R² in log-Euclidean space** (`sigma_codebook_probe.rs:27, 317`, PASS ≥ 0.99). `0.9973` appears elsewhere as the 3σ coverage constant and the ADC-cosine Spearman band (`probe_adc_cosine_head_to_head.rs:6`) — a different quantity. D-OIF-0 settles which number the codebook claim actually rests on. + +### 4.2 Two provenance stories for σ — DECISION D-OIF-2-DEC (operator's) + +| story | where it is written | what it implies | +|---|---|---| +| **Fitted** — σ = nearest of 256 k-means centroids over observed Σ | `sigma_codebook_probe.rs` (Lloyd's, affine-invariant Riemannian metric, R² gate) | needs a per-row observed Σ at write time; the codebook is trained once, offline, in jc (float to build, index to use — the CAM-PQ doctrine, `codebook.rs:19-22`) | +| **Declared** — σ = lookup from the typed value's `(PropertyKind, Marking, SemanticType)` + value range | `sigma_propagation.rs:74-77` ("B3 transcode-sigma-assignment") | needs a mapping table, not k-means; the "codebook" is authored, and the R² probe is irrelevant to it | + +They are not compatible as the *same* v1. Recommendation: **fitted** for the entries, **declared** only as the assignment *fallback* when no Σ is observable at write time — but that is a design choice with consequences for every consumer, so it is stated and not taken. + +### 4.3 D-OIF-0 — re-run the viability probe on the current tree (first, cheap, unconditional) + +`cargo run -p jc --example sigma_probe` (the `[[example]] sigma_probe`, `jc/Cargo.toml`). Record R², the PASS verdict, and the recommendation string it prints (`sigma_codebook_probe.rs:342-360`) in `AGENT_LOG` + this plan's §9. Reconcile 0.9949 vs 0.9973 in one sentence with the source of each. ~seconds of compute; no decision depends on skipping it. + +### 4.4 D-OIF-2 — the codebook TYPE (contract) + BUILDER/EMITTER (jc) + INSTANCE home + +- **Type, in the contract (zero-dep, LE law):** `SigmaCodebook([Spd2; 256])`, `from_le_bytes(&[u8; 256·24])` / `to_le_bytes`, `entry(u8) -> &Spd2`, `nearest(&Spd2) -> u8` (affine-invariant metric via the existing `Spd2::{log_spd, sqrt, pow, eig}` `:130-176`), and a **boundary check** on load — every entry `is_spd(eps)` (`:187`), per the module's own contract that SPD is checked "at boundaries (codebook load, runtime gate)" (`:108-109`). 6 KiB. +- **Builder, in jc:** the k-means the probe already runs, refactored so the emitter writes the frozen table (float to build). Emits **LE bytes + a tag**. **No digest pin, no digest gate** — identity = `K == 256` ∧ all-SPD ∧ `det > 0` ∧ the tag. The operator law on internal pins is absolute. +- **Instance home:** the contract carries the TYPE; the loaded INSTANCE must live where files can be read and where `set_sigma` is called — `cognitive-shader-driver` (owner of `MailboxSoA.sigma`), **not** `lance-graph-cognitive` (which the splat proxy names but which holds nothing). Recommendation only; the crate that owns the column should own the loader. **Owner: W-7 / `D-OIF-7` (§7) — not W-2**, whose scope is the contract type and the `jc` builder only. +- Gates: G1 `from_le_bytes(to_le_bytes(cb)) == cb` bit-exact; G2 a non-SPD entry is **refused** at load (can-fire) and a valid table is not (stay-silent); G3 `nearest` returns the entry's own index for each of the 256 entries (identity), and a perturbed entry returns its unperturbed neighbour (discrimination); G4 the emitted table from the probe's fixed SEED is byte-stable across two runs (determinism). + +### 4.5 D-OIF-3 — the first writer of a non-zero σ (gated on D-OIF-2-DEC) + +Whichever provenance the decision picks, the first writer is the ingest/write path that today calls `BackingStoreWrite::set_sigma` in its loop (`backing.rs:310`) with a constant. Falsifier: after ingesting a batch with ≥2 genuinely different Σ shapes, `sigma` holds ≥2 distinct non-zero values (can-fire) and a batch of identical shapes holds one (stay-silent). **Not built until the decision lands**; the plan carries both shapes' one-line specs so the brief is a paste. + +## 5. What this plan REJECTS, with the reason on record + +| item | verdict | why | +|---|---|---| +| AMX / MKL for the 2×2 sandwich | rejected | shape mismatch: 3 scalars vs 16×16 tiles; call overhead ≫ 18 flops (§3.1) | +| 9-byte `CausalEdge64 + u8` sidecar | superseded | the u8 landed as a SoA column (§0); a second projection of the same byte is `SECOND-PROJECTION` | +| SchemaSidecar Block 14/15 | superseded | same | +| Σ index inside the `u64` | impossible | v2 spare is 3 bits (`edge.rs:557`) | +| wiring σ-advance into `apply_edges` | deferred, gated | needs D-OIF-5 PASS **and** D-OIF-5-DEC (the M source) | +| bf16 ≥16×16 SPD on AMX | out of scope | own falsifier (PSD under bf16 rounding) — file it as an idea, do not build | +| a CI gate on IDEAS.md staleness | rejected | a ledger that is legitimately quiet would fail it — a gate that fires on quiet carries no information (`E-ANTI-EIGENVALUE-…`). A dated census line in `LATEST_STATE` instead. | + +## 6. Sequencing + +```text +D-OIF-0 probe re-run (jc, seconds) ── unconditional, first +D-OIF-1 policy_hash_v1 RETIRED (ruling A) ── withdrawn 2026-09-05; no worker, no decision +D-OIF-4 ewa_sandwich_x8 (jc) ┐ +D-OIF-5 hop re-quant probe ┘ paired ── D-OIF-5 arm 1 needs no artifact +D-OIF-2 SigmaCodebook type + builder + home ── needs D-OIF-2-DEC (fitted vs declared) +D-OIF-3 first σ writer ── needs D-OIF-2 + D-OIF-2-DEC +D-OIF-7 loaded instance + loader (cognitive-shader-driver) ── needs D-OIF-2; W-7 +D-OIF-6 IDEAS ledger: 4 entries + 3 flips ── THIS PR +``` + +Two decisions stand between the plan and the workers: **D-OIF-2-DEC**, **D-OIF-5-DEC** (D-OIF-1-DEC withdrawn under ruling A, §2). D-OIF-0, D-OIF-4, D-OIF-5 (arm 1) and D-OIF-6 need none. + +## 7. Worker briefs (Sonnet, edit-only; the orchestrator compiles once) + +Every brief starts with `sonnet-worker-guardrails.md` §1 **verbatim**, then: *Read `.claude/board/AGENT_LOG.md` first; do NOT write it — leave your record in your own tag-file. Do NOT run `cargo` or `git`. Do not claim it compiles or that tests pass — you did not run them. Your file scope is exactly the files named; another worker owns everything else.* + +- **W-1 (D-OIF-1)** — **WITHDRAWN 2026-09-05 (ruling A, §2).** No worker. The first removal PR (§2.3 bullet 1) is orchestrator work after grace-period sign-off, not a Sonnet brief. +- **W-4 (D-OIF-4)** — files: `crates/jc/src/ewa_sandwich.rs` (append only below the existing kernel), `crates/jc/examples/ewa_sandwich_bench.rs` (new). Spec: §3.2; **no `mul_add`, ever**; same op order per lane as `:185-199`. Tests: §3.5 G1-G2 with the disable named. STOP if any test needs a tolerance — that is a bug, not a tolerance. +- **W-5 (D-OIF-5)** — files: `crates/jc/src/sigma_hop_requant_probe.rs` (new), `crates/jc/src/lib.rs` (one `pub mod` line + one pillar-table entry, `lib.rs:150-185` shape). Spec: §3.4. Output: the table `n → (exact growth, requantized growth, bound, PASS/FAIL)` printed by `prove`. +- **W-2 (D-OIF-2, after D-OIF-2-DEC)** — files: `crates/lance-graph-contract/src/sigma_propagation.rs` (type + loader + boundary check, zero deps), `crates/jc/src/sigma_codebook_probe.rs` (emitter arm). Spec: §4.4, gates G1-G4. +- **W-7 (D-OIF-7, after D-OIF-2)** — files: `crates/cognitive-shader-driver/src/sigma_codebook.rs` (new — the loaded INSTANCE: read LE bytes + tag, construct the contract `SigmaCodebook` through its boundary SPD check, expose `&'static`/`Arc` access to the driver), `crates/cognitive-shader-driver/src/lib.rs` (one `pub mod` line). Spec: §4.4 "Instance home". Gates: G2 (a non-SPD table is REFUSED at load; a valid one is not) and G4 (byte-stable across two loads) re-run THROUGH the loader, plus a can-fire/stay-silent pair on tag mismatch. Does NOT touch `mailbox_soa.rs` or `backing.rs` — the first writer is D-OIF-3's. +- **W-0 (D-OIF-0)** — no edits: the orchestrator runs `cargo run -p jc --example sigma_probe` itself and records the result (§4.3). Not a worker task. + +Orchestrator gates after the fleet lands: `cargo fmt -p `, `cargo clippy -p --all-targets -- -D warnings` per touched crate (`-p`, never `--all` — `tesseract-rs`'s lesson), `cargo test -p ` with the feature sets named above, plus the two board gates and `supersession_index.py` regenerated LAST. + +## 8. Claims in this plan that are STRUCTURAL and must be confirmed by execution + +1. `DataFrame::collect()` compiles under `query-lite` (datafusion sans default features). Fallback named in §2.4. +2. `F64x8` `Mul`/`Add` are non-FMA on **all four** backends — read from `impl_bin_op!` (AVX-512) and the operator impls (AVX2/NEON); the scalar macro body was not read line-by-line. G1 of §3.5 is what proves it. +3. `cargo run -p jc --example sigma_probe` runs on the default feature set (it is not `required-features`-gated in `Cargo.toml:44-56`; `goursat_substrate_probe` is). +4. The probe's k-means codebook is exposable to D-OIF-5 arm 1 without a public API change — if not, W-5 gets a one-line `pub(crate)` accessor in `sigma_codebook_probe.rs` and its scope grows by that file. + +## 9. Results ledger (append as they land) + +- D-OIF-0: _(not yet run)_ diff --git a/.claude/v3/COMPONENT-MAP.md b/.claude/v3/COMPONENT-MAP.md index c5022e6ca..c85a965f6 100644 --- a/.claude/v3/COMPONENT-MAP.md +++ b/.claude/v3/COMPONENT-MAP.md @@ -76,7 +76,7 @@ Meta/Plasticity widths differ persisted-vs-hot with no parity test; | `physical/collapse.rs::CollapseOp` + Strategy #10 | REPURPOSE (rename) | per-query resonance-dispersion gate — NOT the retired singleton; rename candidate (`ResonanceDispersionGate`) to end the vocabulary collision | | `cache/` + `serve.rs` | REUSE | autocomplete/thinking cache; serve.rs is LAB surface | | symbiont `SymbiontBoard` (kanban_loop.rs) | EXTEND | POC proves the loop shape + the −550_000 µs Libet anchor **in code**; gap: `phase` is a bare struct field, not tenant-shaped (W2a); Domino work is called, not free-running — the standing-async-plan is NOT yet realized | -| supervisor `KanbanActor` | EXTEND | the most complete arm: S2 atomic MUL-gate-advance, S3 tick, S4 registry delivery, codex #578/#579 fixes tested; gap: unit-proven on TestBoard only, never integration-driven over a real MailboxSoA | +| supervisor `KanbanActor` | EXTEND | the most complete arm: S2 atomic MUL-gate-advance, S3 tick, S4 registry delivery, codex #578/#579 fixes tested; gap: unit-proven on TestBoard only, never integration-driven over a real MailboxSoA ⊘ **PARTLY STALE (2026-09-05 W0 census, corrected same day on operator input):** the ACTOR half — `KanbanActor`/`KanbanMsg` + the RPC drivers — was DELETED 2026-08-05 (`LATEST_STATE.md:1824,1860`); do not extend or await that symbol. The FILE is live: `kanban_actor.rs` is the read-only meta-awareness surface — `PhaseCensus` (one `&self` pass; the precedent `rubicon_witness.rs:32` cites), `mul_target` (composed by the production seal driver, `cycle_driver.rs:805`), `parse_kanban_step` — re-exported at `lance-graph-supervisor/src/lib.rs:82` and read by the awareness rungs (`rung_horizon.rs:5`). Ownership of the transition itself is `MailboxSoaOwner::try_advance_phase` (`soa_view.rs:311`) / `KanbanColumn::can_transition_to` over the DAG; `&mut` is the serialization. | | **ahead-firing batch writer** | NEW | zero code fires a kanban update at write CAST anywhere (grep-confirmed); lands as a new module wrapping BusDto commits, reading `envelope.mailbox_owner()` | | **delegation cache** | NEW | no delegation concept exists anywhere; small keyed cache inside the batch writer | | surreal_container | BLOCKED→flip-on | **coordinates RESOLVED 2026-06-16**; remaining block is the deliberate cold-build gate (`BlockedColdBuild`) — arm #2 is one dependency-uncomment away, at a ~10 min cold-build cost | diff --git a/.claude/v3/knowledge/mailbox-kanban-model.md b/.claude/v3/knowledge/mailbox-kanban-model.md index f08d2fba1..57831cd57 100644 --- a/.claude/v3/knowledge/mailbox-kanban-model.md +++ b/.claude/v3/knowledge/mailbox-kanban-model.md @@ -27,7 +27,7 @@ proposes; the owner disposes. |---|---|---| | **Arm #1 — planner** | `lance-graph-planner/src/strategy/style_strategy.rs` | The D-MBX-A6 seam: the deferred `Outcome → Candidate/KanbanMove` adapter. Strategy outcomes (converged, cycle_count, gate verdicts) become kanban moves. | | **Arm #2 — symbiont** | `crates/symbiont` (`kanban_loop.rs` = POC) | SurrealDB-on-kv-lance executor: kanban updates as KV transactions on the same Lance substrate. Gated on the AdaWorldAPI surrealdb fork `kv-lance` feature. | -| **Structural owner** | `lance-graph-supervisor/kanban_actor.rs` | ractor actor per mailbox. **ractor is SOLELY the compile-time ownership guarantee** (name the role — the attestation must stay authoritative to the compiler; operator, 2026-07-17) — it spawns and proves single-ownership via move semantics (`KanbanActor` with `type State = O`; the owner MOVES in at `pre_start`); it is NOT a data-plane bus and **not for messaging — it is slow** (operator, 2026-07-02). **It MAY serve as a HELPER where it makes sense** — spawn, supervision, occasional control RPC like the serialized Advance/MulAdvance (the codex #578 atomicity mechanism) — always keeping the speed difference in mind: nothing on the hot path may wait on ractor latency; hot-path dispatch belongs to the D-V3-W2e-probed ExecTarget. | +| **Structural owner** | `lance-graph-supervisor/kanban_actor.rs` | ractor actor per mailbox. **ractor is SOLELY the compile-time ownership guarantee** (name the role — the attestation must stay authoritative to the compiler; operator, 2026-07-17) — it spawns and proves single-ownership via move semantics (`KanbanActor` with `type State = O`; the owner MOVES in at `pre_start`); it is NOT a data-plane bus and **not for messaging — it is slow** (operator, 2026-07-02). **It MAY serve as a HELPER where it makes sense** — spawn, supervision, occasional control RPC like the serialized Advance/MulAdvance (the codex #578 atomicity mechanism) — always keeping the speed difference in mind: nothing on the hot path may wait on ractor latency; hot-path dispatch belongs to the D-V3-W2e-probed ExecTarget. ⊘ **PARTLY STALE (2026-09-05 W0 census, corrected same day on operator input):** the ACTOR half — `KanbanActor`/`KanbanMsg` + the RPC drivers — was DELETED 2026-08-05 (`LATEST_STATE.md:1824,1860`); do not extend or await that symbol. The FILE is live: `kanban_actor.rs` is the read-only meta-awareness surface — `PhaseCensus` (one `&self` pass; the precedent `rubicon_witness.rs:32` cites), `mul_target` (composed by the production seal driver, `cycle_driver.rs:805`), `parse_kanban_step` — re-exported at `lance-graph-supervisor/src/lib.rs:82` and read by the awareness rungs (`rung_horizon.rs:5`). Ownership of the transition itself is `MailboxSoaOwner::try_advance_phase` (`soa_view.rs:311`) / `KanbanColumn::can_transition_to` over the DAG; `&mut` is the serialization. | ## The trigger: kanbanstep. There is no ack — the concept is ELIMINATED (operator, 2026-07-10/17) diff --git a/.claude/v3/knowledge/write-on-behalf.md b/.claude/v3/knowledge/write-on-behalf.md index 939d0231f..5c6b7c586 100644 --- a/.claude/v3/knowledge/write-on-behalf.md +++ b/.claude/v3/knowledge/write-on-behalf.md @@ -5,7 +5,7 @@ > ladybug-rs), and any session adding a write path to SoA rows / Lance > datasets / tenant lanes. -## Status: FINDING (operator-ruled 2026-07-02; batch writer + `owner_adapter` write-on-behalf cast SHIPPED 2026-08-01; `cycle_driver.rs` `cognitive_pass` is the existing production caller of `emit_bootstrap_intent` — HashMap-probe-fleet-driven; the first ACTOR-OWNED `KanbanActor` caller is the open W1 work, plan `kanban-64k-inverted-awareness-v1` D-KIA-A1) +## Status: FINDING (operator-ruled 2026-07-02; batch writer + `owner_adapter` write-on-behalf cast SHIPPED 2026-08-01; `cycle_driver.rs` `cognitive_pass` is the existing production caller of `emit_bootstrap_intent` — HashMap-probe-fleet-driven; the first ACTOR-OWNED `KanbanActor` caller is the open W1 work, plan `kanban-64k-inverted-awareness-v1` D-KIA-A1) ⊘ **STALE (2026-09-05):** the `KanbanActor` actor was deleted 2026-08-05; there is no actor-owned caller to await — see `LATEST_STATE.md:1860`. (`kanban_actor.rs` itself is live as the read-only `PhaseCensus`/`mul_target` surface.) --- diff --git a/CLAUDE.md b/CLAUDE.md index 400814db6..a3bd28357 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1204,9 +1204,8 @@ cd crates/lance-graph-python && maturin develop # lance / lancedb / arrow / datafusion family is pinned at all, and NO repo # tracks a Cargo.lock (.gitignore; ISS-STALE-AUTHORITY-LOCKS, RESOLVED). # -# Measured against crates.io 2026-09-05 -- lancedb 0.33.0 requires: -# lance* = "=9.0.0" (EXACT -- imposed on us, not our choice; it is also why -# the published lance 9.0.1 is unreachable) +# Measured against crates.io 2026-09-05 -- lancedb 0.38.0 requires: +# lance* = "=11.0.0" (EXACT -- imposed on us, not our choice) # arrow* = "^58.0.0" datafusion* = "^54.0.0" (CARET -- so ours must be too) # An exact `=58.4.0` on our side is strictly NARROWER than anything the family # asks for, and that is what makes a graph unsatisfiable: see Cargo.toml:141-144, @@ -1222,11 +1221,17 @@ cd crates/lance-graph-python && maturin develop # (Rust crate line is 0.33.0 -> 0.37.1 -> 0.38.0; 0.34/0.35/0.36 do not exist as # Rust crates -- those numbers are the independently-versioned PyPI package.) # -# The lance family moves in EXACT lockstep -- currently =9.0.0 (lance 7 was the -# 2026-06-14 state, superseded by the lance-9 sweep, b2b08b07 / PR #896 arc). -# moves in EXACT lockstep — currently =9.0.0 (lance 7 was the 2026-06-14 state, -# superseded by the lance-9 sweep, b2b08b07 / PR #896 arc). -arrow = "58" # 58.3.0 resolved; unmoved by the lance-9 sweep +# The lance family moves in EXACT lockstep -- currently =11.0.0. Line of state: +# lance 7 (2026-06-14) -> 9 (the lance-9 sweep, b2b08b07 / PR #896 arc) -> 10 +# (#1187, D-LNC-1) -> 11 (#1190, D-LNC-3, probe-gated on the D-LNC-2 fragment-id +# probe #1189). arrow/datafusion did NOT move with any of them. +# ⊘ The "=9.0.0 / lancedb =0.33.0" ruling recorded below as +# E-PIN-LANCE9-LANCEDB033-DF541-ARROW58-NO-DF53-1 is SUPERSEDED on its lance +# and lancedb coordinates ONLY (now 11 / 0.38.0); its datafusion half stands +# verbatim -- DF 54.1, never DF 53, and the `delta` feature stays removed. +# (A duplicated copy of this sentence stood here since the lance-9 sweep; both +# copies carried the stale number, so both are replaced by this one.) +arrow = "58" # unmoved by the lance-9, -10 and -11 sweeps alike datafusion = "54" # OUR direct pin, in every crate that DEPENDS on it # (lance-graph, -catalog, -callcenter, -python, holograph), # and the sub-crates move with it: datafusion-common / -expr @@ -1251,12 +1256,13 @@ datafusion = "54" # OUR direct pin, in every crate that DEPENDS on it # 2026-08-18; crates.io releases still DF 53) — as its # own deliberate PR if a consumer needs Delta. # Probe: .claude/plans/lance9-datafusion54-upgrade-probe-v1.md -lance = "=9.0.0" # exact-pinned: lancedb 0.33.0 requires lance =9.0.0 -lance-linalg = "=9.0.0" -lance-index = "=9.0.0" -lancedb = "=0.33.0" # the lance-9 pairing. NOTE: lancedb 0.36 is the PyPI - # package, versioned independently — the Rust crate - # tops out at 0.33.0 (probe §1). +lance = "=11.0.0" # exact-pinned: lancedb 0.38.0 requires lance =11.0.0 +lance-linalg = "=11.0.0" +lance-index = "=11.0.0" +lancedb = "=0.38.0" # the lance-11 pairing (`default-features = false` in + # the workspace table). NOTE: the Rust crate line is + # 0.33.0 -> 0.37.1 -> 0.38.0; 0.34/0.35/0.36 exist only + # as the independently-versioned PyPI package. rust = "1.97.1" # rust-toolchain.toml is authoritative; see its bump log ndarray = { path = "../../../ndarray" } # AdaWorldAPI fork, default, optional fallback nom = "7.1"