diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index 155015910..eca4bc35c 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -124,6 +124,31 @@ and NOT DataFusion — the same class numbers are stale after the `mint_for` V2/V3 drift; re-anchor to symbols before Phase 3. +## 2026-09-14 — PR #1225 (`73d3b41`) and PR #1226 (`0b1ebaa`) merged: the masking floor is on `main` + +- **New workspace member: `crates/lance-graph-mask-risc`** — the mask RISC + above `ndarray::simd`. `ir` / `exec` / `reference` / `fuse` / + `ternlog_dispatch` / `value`, with a differential suite (executor vs a + scalar oracle that never touches `ndarray`), a zero-allocation gate, and a + CI line (`member-tests`) plus a generated-dispatch consistency check. +- **Contract inventory delta (PR #1225):** `AlphaMask`, `WideFieldMask` and + `FieldMask` gained borrowed-word and caller-owned/in-place forms; + `NestedBands` hoists its buffers. The field-mask vs row-mask distinction is + preserved deliberately. +- **Public surface added (PR #1226):** `execute`, `materialize_rows`, + `Scratch`, `fuse` / `fuse_program` / `ternlog_imm` / `BoolExpr` / + `FuseError` / `Fused`, `LaneRef` / `MaskOp` / `Operand` / `Planes` / `Pred` + / `Program` / `Terminal`, `MASKED_SUM_I32_MAX_ROWS`, `MAX_SCRATCH_SLOTS`, + `reference_execute` / `reference_scratch`, `ternlog_dispatch` / + `ternlog_dispatch_assign`, `ExecError` / `LaneKind` / `Value`, `words_for`. +- **The crate has no backends, by law.** `ndarray` IS the SIMD polyfill; + mask-risc contains no `cfg(target_feature)` and a test enforces it, so + executor-vs-oracle equality is backend-independent by construction and + per-realization correctness is ndarray's, with ndarray's parity tests. An + earlier draft of this delta called backend coverage a gap in THIS crate — + corrected; see the storno in `PR_ARC_INVENTORY.md` under #1226. +- Arc entries: `PR_ARC_INVENTORY.md` under PR #1226 and PR #1225. + ## 2026-09-07 — PR #1218 merged (`7bb393ef`): plan inventory + V3 harvest mirrors are on `main` - The 2026-09-07 "plan inventory landed" delta below is now merged history. Post-review deltas since that delta was written: `TD-NDARRAY-SIMD-GATHER` is **PARTIAL** (not SHIPPED); W1b reads 0 of 5 TD entries closed / 1 of 7 files migrated; ENTROPY M1–M27 reconciles to 9 + 7 + 10 + 1; COMPONENT-MAP `StepMask` row and the Sonnet guardrails `StepMask` / `0x1000` rows regraded; the nexgen `(classid, version)` key is marked PROPOSED (shipped `NestedBands` is version-only). Arc entry: `PR_ARC_INVENTORY.md` under PR #1218. diff --git a/.claude/board/PR_ARC_INVENTORY.md b/.claude/board/PR_ARC_INVENTORY.md index d2496771d..b591570b3 100644 --- a/.claude/board/PR_ARC_INVENTORY.md +++ b/.claude/board/PR_ARC_INVENTORY.md @@ -1,3 +1,95 @@ +## 2026-09-14 — lance-graph PR #1226 (merged `0b1ebaa`, branch `claude/clone-repositories-71a5sw`) — the mask-risc executor, and five findings that arrived AFTER the council + +- **Added:** `crates/lance-graph-mask-risc` — `ir` (the op vocabulary), + `exec` (the borrowing evaluator over caller-owned `Scratch`), `reference` + (the row-at-a-time oracle that never touches `ndarray`), `fuse` (Boolean + tree → one `Ternlog` by truth table), `ternlog_dispatch` (GENERATED 256-arm + runtime-immediate → const-generic bridge, CI-checked against its generator), + `value`. Plus `tests/differential.rs`, `tests/no_alloc.rs`, + `tests/oracle_alloc.rs`, `examples/count_probe.rs`, and the `member-tests` + CI line. +- **Locked.** Laws renamed to end a real ambiguity: **A1–A4** are the + architectural doctrine (`lib.rs`), **L1–L5** the structural laws a test + enforces (`exec.rs`). A3 and L2 are both "no ISA", so a bare "law 3" was + ambiguous; the mapping is written out (A1 → L1 + L5, A3 → L2, A4 → L4; A2 + has no structural counterpart, L3 has no architectural one and is + `[claimed, unverified]` with no instrument). `MAX_SCRATCH_SLOTS = 65_536`, + with `const _: () = assert!(MAX_SCRATCH_SLOTS == 65_536)` pinning the VALUE + independently of its derivation — the falsifiers are written as + `MAX_SCRATCH_SLOTS + 1` and therefore TRACK the constant, so they cannot be + what catches a change to it. +- **Five findings landed after the eight-review council, two of them + regressions introduced by fixing the first.** In order: the scratch-slot + ceiling (a public `u32` field could declare 4e9 slots naming no operand, + which every per-operand check is structurally blind to) → `execute` + disagreeing with the oracle because my ceiling fix ran after the capacity + check → a truncating `bytes / reps` in the probe → validation quadratic in + op count (3.06 s at 65,536 ops) → the oracle sizing its bitmap from + `scratch_slots` BEFORE `validate` checked it (512 MiB, measured). **The + council is not the last gate; it is the first one that reads the whole + diff.** +- **A third-party docstring agent committed to the branch mid-review** + (`2967143`, CodeRabbit, started by someone other than the authoring + session). It was read, checked against the code, and **kept — not + reverted.** Four of its five edits were genuine corrections, three of them + to drift THIS BRANCH introduced the same day: `execute`'s "before any + write" became false when the read-before-write bitmap went caller-owned; + `validate`'s numbered list was stale once the ceiling check moved to the + front; `Program::new` said "from the ops" where the count is over every + operand including the terminal's. `0f8cdeb` restored the `O(n_rows)` bound + it dropped from `materialize_rows` and narrowed an over-general claim it + added about `written_bits`. **A doc comment is not a behaviour, so no test + in the suite could have caught any of it.** +- **Deferred, named:** `hop` (PR5); a strided `Operand` — the gap is in THIS + IR, not in T1, since `ndarray::simd` already ships + `ternary_match_strided_to_mask` and nothing here can name a + `(base, stride, group)` source; the Cypher `mask_lower` seam; and L3's + missing instrument. The ternlog duplication filed by this PR is **stornoed + below** rather than carried. +- **Docs:** `.claude/plans/mask-risc-executor-v1.md`, + `.claude/board/exec-runs/w2-ternlog-dispatch.md`, `AGENT_LOG` entry. +- **Confidence: high.** The differential suite proves executor == oracle, + and that claim is **backend-independent by construction**: this crate + contains no `cfg(target_feature)`, no ISA, no fallback chain — law A3, with + `the_crate_names_no_isa` enforcing it. **`ndarray` IS the SIMD polyfill**, + so "which backend" is ndarray's question and ndarray's parity tests answer + it. Running this suite under another realization would test ndarray through + a proxy, not this crate. + > **⊘ CORRECTED, same day, operator-caught.** This bullet first read + > "medium on the backend claim … NEON, WASM and scalar are unexercised", + > as though per-backend coverage were a gap in THIS crate's verification. + > It is not a property this crate has. Stating it that way describes + > mask-risc as carrying five realizations to verify — precisely what the + > polyfill exists to make untrue — and is the same confabulation as the + > storno's "backend realization" line. **The merged `lib.rs` module doc + > carries the identical framing** ("NEON, WASM and scalar are + > unexercised") and needs the same correction in code; filed rather than + > silently fixed here, since it shipped in #1226. +- **Process, worth keeping.** A SHA-locked merge is only as strong as the + provenance of the SHA: this session put a FABRICATED full SHA into a merge + instruction (correct 8-char prefix, 33 invented digits after) by extending + a short SHA from `git log --oneline` instead of running `git rev-parse`. + The lock would have refused it — fail-safe against its own operator — which + is the only reason it cost nothing. Three stale `check_suite.completed` + events also arrived naming superseded heads; **a completion event is never + evidence about the current head.** + +## 2026-09-14 — lance-graph PR #1225 (merged `73d3b41`, branch `claude/clone-repositories-71a5sw`) — the contract's masking debt, paid in borrowed words + +- **Added:** borrowed-word and caller-owned/in-place forms across + `AlphaMask` / `WideFieldMask` / `FieldMask`; `NestedBands` buffers hoisted + out of the hot path; every discovered debt site carrying a hot-path + `Box`/`Vec` converted; the `lance-graph-mask-risc` IR skeleton that PR + #1226 then filled in. +- **Locked.** The field-mask vs row-mask distinction is PRESERVED, not + unified — they are different questions (which FIELDS participate vs which + ROWS survive) and a single type would have made the confusion + unrepresentable in the wrong direction. +- **Docs:** equivalence tests pinning each new borrowed form against the + allocating one it replaces. +- **Confidence: high.** The equivalence tests are the gate, and each was + disable-verified. + ## 2026-09-07 — lance-graph PR #1217 (merged `b518dbf1`, branch `claude/great-curie-d2ufyl`) — a commit orphaned by a reset, and a board that recorded the opposite - **Added:** `.claude/plans/nodeguid-new-repurpose-audit-v1.md` (5+3 council SPEC v1 diff --git a/.claude/board/TECH_DEBT.md b/.claude/board/TECH_DEBT.md index 24832dbec..7bec0d9fd 100644 --- a/.claude/board/TECH_DEBT.md +++ b/.claude/board/TECH_DEBT.md @@ -7,6 +7,34 @@ lgj-abi delegates to the crate, or the crate is scoped to the evaluator — and stornos the other doc. Filing costs a paragraph now; de-duplicating after PR4 wires `plan_eval` costs a refactor. + > **⊘ STORNO 2026-09-14 (kernel-membrane ruling, + > `lance-graph-java/.claude/board/exec-runs/pr4-kernel-membrane.md`).** The + > two options this item offers are a false choice: **both preserve the + > duplication.** The resolution is neither: an **additive + > `mask_ternlog_dyn` in `ndarray::simd`**, with `lgj-abi` and + > `ternlog_dispatch` both delegating to it. **ndarray IS the SIMD + > polyfill** — every SIMD-shaped surface a consumer needs lives there, and + > that is the whole argument. `mask_ternlog` is ``, a const + > generic instantiates only from a literal, so a consumer holding a + > RUNTIME immediate has no export to call and fans out 256 ways. That is a + > **missing export in the polyfill**, nothing more. Verified against source + > in lance-graph-java `dfbdfcf`: `mask_ternlog` and `mask_ternlog_assign` + > are the only two names the facade re-exports and no `_dyn` form exists at + > any level. Straight application of the missing-capability STOP rule — and + > two consumers hand-rolling the SAME missing export is the signal read + > twice. The item stays OPEN, re-scoped to that ndarray addition; the + > original text is left verbatim above. + > **⊘⊘ SELF-CORRECTION, same day, operator-caught.** The first version of + > this storno justified the ndarray home with "T0 owns backend + > realization, and a 256-arm match on an immediate IS backend + > realization", and framed the rejected options as "a T1 kernel depending + > on a T2 evaluator". **Both are confabulation.** A match on a runtime + > immediate is a monomorphization fan-out — pure Rust, byte-identical on + > every backend, nothing to do with AVX-512 vs NEON. It is not backend + > realization by any reading. The tier story dressed a missing export as + > an architecturally interesting membrane problem and, in doing so, made + > the polyfill look like one tier among several rather than **the** place + > SIMD lives. The correct argument needs no tiers at all. - **`D-MRL-1a`'s `TERNARY_MATCH(pattern[12], care[12])` has no carrier.** The IR offers `MatchU32`/`MatchU64` only; a 96-bit match over the V3 facet register exists in neither this IR nor ndarray T1. Per the missing-