Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .claude/board/EPIPHANIES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
## 2026-09-17 (18) — E-THE-SECOND-FACET-IS-NOT-AN-EDGE-BLOCK-1 — bytes 16..32 are just another content-blind facet cascade; giving them their own type was how the V1 `12 + 4` carving survived its own retirement

**Status:** OPERATOR-RULED (verbatim below) + SHIPPED (`pub type EdgeBlock =
FacetCascade;`, `FacetCascade::as_bytes_mut`, every field site migrated
byte-for-byte). Residue named in
`ISS-EDGE-BLOCK-WAS-A-SECOND-TYPE-FOR-THE-SAME-FACET`.
**Confidence:** HIGH — the ruling is the operator's; the mechanics are a
type alias over an identical `repr(C, align(16))` 16-byte layout, 1425
contract tests unchanged, every in-tree consumer builds.

### The ruling

> *"It's forbidden for the edge block to even know it's an edge block —
> it's just another content blind facet cascade."*
> *"How hard can it be to fold `[u16;8]` / `[u8;16]` — same algorithm,
> just 6 vs 8, 12 vs 16."*
> *"What you call edge codec flavor, quoting 12+4 in/out family, is a V1
> contamination."*

### What it corrects, including in this session

The canon had retired the `12 in-family + 4 out-of-family` carving as a
V1-LEGACY *reading* — but `EdgeBlock { in_family: [u8; 12], out_family:
[u8; 4] }` was that reading spelled as a *type*, and a type outlives a
regraded paragraph. Every `.in_family` / `.out_family` access re-asserted
it. This session then proposed, in order: a fourth `EdgeCodecFlavor`
(`Refs16`), a second view type (`EdgeRefs`), an 8×2×8 `T8` facet shape, a
`ColumnDescriptor::class_id` field, and a §3c ruling — each one a
consequence of treating the second 16 bytes as something other than a
facet. All of it was discarded on the ruling. What remains is one line.

### The shape that is left

`NodeRow = key: FacetCascade | edges: FacetCascade | value(480)`. The
second facet's 4-byte prefix says what its six `(u8:u8)` rails ARE for
this row — the predicate, the codebook — and the ClassView projects them.
"Sixteen refs" is `4 + 12` read as L1 rails; the classid that a `T8` shape
or a lane-level field was invented to carry was already in the register.
`EdgeCodecFlavor` is how a class *reads* the second facet, which is all it
ever was. The fold is `shared::<N>` on `[u8; N]`, one algorithm, `6` or
`8` — the cascade discipline from `E-THREE-CARRIERS-THREE-FOLDS-1` applies
to both facets identically because they are the same type.

### The rule, generalized

**A second type for the same bytes is a carving pretending to be a
layout.** The content-blind invariant is not "the ClassView chooses the
reading"; it is "there is no type in which a reading could hide." Where
the canon has already regraded a reading as legacy, grep for the *type*
that still spells it — the paragraph did not retire it if the struct is
still there.

Cross-ref: `E-V3-FACET-4-PLUS-12` (now visibly true of bytes 16..32 as
well), `E-V1-TAIL-FORBIDDEN-V3-IS-CONTENT-BLIND-1`,
`E-THREE-CARRIERS-THREE-FOLDS-1`, CLAUDE.md § CANON (⊘ note appended),
`le-contract.md` §4 (bullet appended).

## 2026-09-17 (17) — E-THREE-CARRIERS-THREE-FOLDS-1 — one workspace holds THREE prefix-fold carriers; entry (16) measured a real win on one of them and shipped it into another, where it is 2.1× SLOWER

**Status:** MEASURED (`crates/lance-graph-contract/examples/facet_axis_lcp_probe.rs`,
Expand Down
84 changes: 84 additions & 0 deletions .claude/board/ISSUES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,87 @@
## ISS-EDGE-BLOCK-WAS-A-SECOND-TYPE-FOR-THE-SAME-FACET (2026-09-17) — RESOLVED at the type; the readers that still split at 12 are the named residue

**Operator ruling (verbatim, 2026-09-17):** *"It's forbidden for the edge block to even
know it's an edge block — it's just another content blind facet cascade."* And the diagnosis
that preceded it: *"what you call edge codec flavor … quoting 12+4 in/out family is a V1
contamination."*

**The contamination:** bytes 16..32 of the node row had their own type, `EdgeBlock
{ in_family: [u8; 12], out_family: [u8; 4] }`. The canon had already regraded the `12 + 4`
carving as *"NOT the layout … V1-LEGACY READING"* (CLAUDE.md § CANON), but a struct with
those two field names IS that reading, stated as a type — and every reader that touched
`.in_family` / `.out_family` re-asserted it. A session drafting an ontology edge reading
(this one) reached for a *fourth* `EdgeCodecFlavor` and a *second* view type beside it,
and wrote a test that pinned the 12+4 split as the baseline the new reading sat beside.
That draft was discarded; this is what replaced it.

**Resolved at the type (this branch):** `pub type EdgeBlock = FacetCascade;` — the second
16 bytes are the same `4 + 12` content-blind facet as the key. Byte positions unchanged;
`NodeRow`, `node_rows_from_le_bytes`, every `EdgeBlock::default()` and every equality
compile unchanged (OGAR `lance_sink.rs` pulls the contract from git `main` and uses only
`default()` / `==`, so it is unaffected until merge and unbroken after).
`FacetCascade::as_bytes_mut` added (same `SAFETY` pattern as `as_bytes`) so the in-place
writers have a lens. `EdgeCodecFlavor` stays: it is how a ClassView READS the second facet,
which was always its job.

**The residue — readers that still split the 16 bytes at 12 on their own authority** (all
migrated to `as_bytes()[..12]` / `[12..]` mechanically so the bytes they read are exactly
the bytes they read before; none was redesigned, per the "alias only" scope):

| site | what it still believes |
|---|---|
| `lance-graph/src/graph/mailbox_scan.rs` `edge_slots_coarse` → `EdgeNeighbors { in_family, external }` | 12 local + 4 external |
| `lance-graph-contract/src/soa_graph.rs` render (`domain.in_family_edge` / `out_family_edge` labels) | two edge kinds by byte position |
| `lance-graph-contract/src/aiwar.rs` (writes bytes 12..16 as "the 4 canonical out-of-family slots") | 4 adapter slots |
| `symbiont/src/{domino,key_render,kanban_loop}.rs` (⊘ deprecated crate) | ring neighbour at byte 0, adapter at byte 12 |
| `lance-graph-callcenter/src/graph_table.rs` test fixture | adapter byte 0x0B at byte 12 |
| `deepnsm/examples/tri_fidelity_edges.rs`, `perturbation-sim/examples/reinforce.rs` (prose only) | "12 in-family + 4 out-of-family" |
| `EdgeCodecFlavor::CoarseOnly` doc comment | "the 12+4 block read literally" |

Each becomes correct the moment its ClassView names what the second facet's prefix and
rails mean for that class — which is the whole point: the READING belongs to the class,
never to the slot. Closing this issue = every row above reads through the ClassView (or is
deleted with its crate).

## ISS-MASK-RISC-HAD-NO-RANGE-OP (2026-09-17) — PARTLY RESOLVED: the IR op shipped; the quack lowering still waits on ordering knowledge

**The chain, as found:** `ndarray::simd::mask_set_range(out_words, lo, hi)` is on the
facade (`simd_masking_ops.rs`, `pub fn mask_set_range`) — a three-pass contiguous fill,
no per-row compare. `lance-graph-mask-risc`'s IR had **no op that reaches it** (`ir.rs`
`Pred` was the ten lane predicates and nothing else). So `lance-graph-quack`'s
`Filter::prefix_u64` — *"the closest DuckDB comes to the V3 address"*, matrix row R5 —
lowered an address prefix to a full `MatchU64` ternary SWEEP, and its own doc said
*"NOT yet a range WRITE … waits on the primitive."* The primitive existed; the IR
name did not. **ndarray has it → mask-risc can't name it → quack sweeps.**

Why it matters: on an address-ordered lane a prefix names ONE contiguous subtree, and
that is the whole reason V3 has the survivor-skip lever at all — `adaptive_order_probe`'s
clustered regime skips **99.61 %** of words precisely because the prefix term's
survivors fill one block. A range write makes that selection free instead of a sweep
that happens to be cheap. It is also the "mask from root, O(1) adjacent" half of the
similarity question (`E-…-POPCOUNT-×-SELF`, LATEST_STATE 2026-09-15 (6)–(8)) as an IR
op rather than a per-row match.

**Resolved 2026-09-17 (this branch):** `Pred::Range { lo: u32, hi: u32 }` — rows
`lo <= i < hi`, reads no lane; exec = `mask_set_range` (+ `mask_and_assign` under a
gate); oracle = row-index predicate; `ExecError::RangeOutOfBounds` for `lo > hi` or
`hi > n_rows`, refused by the shared validator before any write. Three differential
tests across the eight row counts (word-edge shapes incl. 63/64/65; `== hi − lo`
counted through the EXECUTOR; identical refusal). Disable-verified: an off-by-one in
the exec arm fails two of the three.

**Still OPEN — the lowering.** `Filter::prefix_u64` still emits the sweep, and
correctly so: the IR does not know whether a lane is address-ordered (a V3 table's
row address is its rail; a borrowed `&[u64]` of edge targets is not), and quack's
`Filter` carries no ordering evidence. Lowering a prefix to `Range` on an unordered
lane is a wrong answer, not an error. The remaining arm is therefore on the planner
side: an ordering witness on the lane (or on `Col`) that licenses `prefix → Range`.
Until it exists the sweep is the honest lowering, and the quack doc now says exactly
that.

**Also named, not built:** `mask_set_range` has no `_under` sibling on the facade;
the gated form here is two passes (`set_range` then `and_assign`). One fused pass is
a T1 follow-up, measured-then-pinned like every other facade member.

## ISS-NIBLEPATH-FOLD-IS-CARRIER-2-UNMASKED (2026-09-17) — OPEN, the one prefix fold that genuinely wants a mask, and does not have one

`NiblePath::common_prefix_depth` (`crates/lance-graph-contract/src/hhtl.rs`, `fn common_prefix_depth`) is
Expand Down
67 changes: 67 additions & 0 deletions .claude/board/LATEST_STATE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,70 @@
## 2026-09-17 (3) — CONTRACT INVENTORY DELTA: `EdgeBlock` is now `pub type EdgeBlock = FacetCascade` (the V1 `12 + 4` struct is gone); `FacetCascade::as_bytes_mut` added

- **State consumers should know:** bytes 16..32 of `NodeRow` are the same
`4 + 12` content-blind facet type as the key. `EdgeBlock` survives as a
NAME only; `.in_family` / `.out_family` no longer exist — read through
`as_bytes()`, write through the new `as_bytes_mut()`. Byte positions are
unchanged, `NODE_ROW_STRIDE` unchanged, `node_rows_from_le_bytes`
unchanged, no `ENVELOPE_LAYOUT_VERSION` bump. `EdgeBlock::default()` and
equality compile as before (OGAR `lance_sink.rs` uses only those, via git
`main`). Every in-tree field site (symbiont ×3, soa_graph, aiwar,
callcenter, weather-poc, mailbox_scan, contract tests) migrated
mechanically to the same bytes.
- **Operator ruling:** *"It's forbidden for the edge block to even know it's
an edge block — it's just another content blind facet cascade."* Board:
`E-THE-SECOND-FACET-IS-NOT-AN-EDGE-BLOCK-1`.
- **Residue named, not touched:** the readers that still split at 12 on
their own authority — `ISS-EDGE-BLOCK-WAS-A-SECOND-TYPE-FOR-THE-SAME-FACET`.
- **Withdrawn this session before landing:** `EdgeCodecFlavor::Refs16`,
`EdgeRefs`, the `T8` facet shape, `ColumnDescriptor::class_id`, and a
`le-contract.md` §3c ruling — all consequences of the contamination, all
discarded on the ruling. Nothing of them is on `main` or on this branch.

## 2026-09-17 (2) — `Pred::Range` lands in mask-risc: the contiguous-range write the IR could not name — one IR variant + one error, NO contract inventory delta

- **State consumers should know:** `lance-graph-mask-risc` gains
`Pred::Range { lo: u32, hi: u32 }` (rows `lo <= i < hi`, reads no lane) and
`ExecError::RangeOutOfBounds`. Exec is `ndarray::simd::mask_set_range`
(+ `mask_and_assign` under a gate); the oracle is a row-index predicate;
`lo <= hi <= n_rows` is refused by the shared validator before any write.
`D-MRX-7`, in PR on `claude/great-pascal-k96kok` (`c3931a1a`).
- **Why:** `mask_set_range` was on the ndarray facade with nothing in the IR
able to reach it, so `lance-graph-quack`'s `Filter::prefix_u64` — an
address prefix, which on an ordered lane is ONE contiguous subtree —
lowered to a full ternary sweep and said *"waits on the primitive"*. The
primitive was there; the name was not (`ISS-MASK-RISC-HAD-NO-RANGE-OP`).
This is the "mask from root, O(1) adjacent" half of the similarity
question ((6)–(8) below) as an op, and the mechanism behind the 99.61 %
clustered word-skip in `adaptive_order_probe`.
- **What did NOT move:** quack still lowers `prefix_u64` to the sweep, and
should — the IR does not know whether a lane is address-ordered, and
`Filter` carries no ordering evidence. The remaining arm is an ordering
witness on the planner side; quack's doc now says so. The
`lance-graph-contract` inventory is untouched.
- **Process receipt:** the first draft of the population test counted
through the oracle (`Fixture::count`) and a disable-run with an
off-by-one in the exec arm PASSED it — vacuous against the side under
test. Fixed to count through `execute`; the disable-run now fails 2 of 3.
Same session also walked into the ruff "commit BEFORE you disable" trap
once (`git checkout` after a disable-run reverted uncommitted work);
re-applied, then committed first and re-ran.

## 2026-09-17 — PR #1245 merged (`83369cad`): the facet per-axis LCP is the `shared6` byte chain again, verbatim pre-#1241 — NO contract inventory delta

`FacetCascade::{hi_distance, lo_distance}` are back to the by-value
`shared6` chain, byte-identical to `95e28637^`; #1241's masked `u128`
readout survives only as `masked_axis_oracle` under `#[cfg(test)]`. No
type added or removed; the public signature is exactly pre-#1241. Measured
in-tree (`examples/facet_axis_lcp_probe.rs`, oracle over every pair): chain
1.72 ns vs masked 3.64 on 64K random — #1241's ordering inverted on its own
carrier. Doctrine: `.claude/knowledge/three-prefix-fold-carriers.md` —
three prefix-fold carriers (bit-planes / nibble path / facet cascade), and
the rule *masking wins when the slice is granular, PEEK wins when the slice
is addressed*. The real masking opportunity is carrier 2
(`NiblePath::common_prefix_depth`), filed as
`ISS-NIBLEPATH-FOLD-IS-CARRIER-2-UNMASKED`, gated on its own probe. Arc:
`PR_ARC_INVENTORY.md` 2026-09-17 #1245.

## 2026-09-16 — PR #1241 merged (`d5d3f7ab`): the facet's per-axis LCP is one masked register readout — NO contract inventory delta

`FacetCascade::hi_distance` / `lo_distance` now read
Expand Down
55 changes: 55 additions & 0 deletions .claude/board/PR_ARC_INVENTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
## 2026-09-17 — lance-graph PR #1245 (merged `83369cad`, branch `claude/great-pascal-k96kok`) — the facet's per-axis LCP goes BACK to the `shared6` byte chain, verbatim; #1241's masked readout is the test oracle now; three prefix-fold carriers named

- **Added:** `examples/facet_axis_lcp_probe.rs` — four-arm benchmark
(A chain PEEK / B pack-to-`u64` / C masked `u128` / D shared-load PEEK),
64K pairs × 8 workloads, min of 7, oracle over EVERY pair before timing,
depth-knob and anti-vacuity gates that `assert!` (a flat depth-0→5 slope
fails the process). `.claude/knowledge/three-prefix-fold-carriers.md`
(doctrine); `.claude/plans/three-carrier-blast-radius-v1.md` (read-only
census, gates only); `ISS-NIBLEPATH-FOLD-IS-CARRIER-2-UNMASKED`; EPIPHANIES
(17) `E-THREE-CARRIERS-THREE-FOLDS-1` + partial strike appended to (16);
STATUS_BOARD D-TCF-1..5. 8 files, 5 commits.
- **Reversed (of #1241):** `shared_axis(xor, mask)` + `HI_BYTES`/`LO_BYTES`
are gone from the shipped path. `shared6([u8; 6], [u8; 6])` and the
by-value `hi_distance(self, other: Self)` / `lo_distance` are restored
**byte-identical to `95e28637^`** (diff-verified; the first revert commit
had shipped a semantically-equivalent respelling — `6e79c784` corrected
it). The falsifier is REVERSED, not deleted: the masked form lives on as
`masked_axis_oracle` under `#[cfg(test)]`, so the test compares shipped
against oracle rather than against a restatement of itself. Public API is
exactly pre-#1241.
- **Locked:** *masking wins when the slice is granular; PEEK wins when the
slice is addressed.* A measurement is a statement about
`(operation, carrier, workload)`; drop the carrier and it is a slogan.
Three carriers: bit-planes (`mailbox_soa` `&[u64]`, mask — untouched);
nibble path (`NiblePath`, packed `u64`, mask — NOT DONE, walks
nibble-by-nibble); facet cascade (`FacetCascade`, 6×2×8 byte-addressed,
PEEK — this PR). Before moving a fold, name its carrier.
- **Measured (64K random pairs, release, min of 7, both axes):** A chain
**1.72 ns** vs C masked 3.64 — the opposite of #1241's "12.5 → 5.8"; A
wins at every depth 0..5 and on identical; both pack-to-register arms are
slowest (the author's prediction that B would win was wrong). A's
depth-0→5 slope +81–111% across runs is the anti-vacuity evidence.
Disassembly: LLVM never materializes the `[u8; 6]` — `movzbl`/`cmp`
straight against memory/`jne`; arm C issues the same loads then
reassembles, `movabs` mask, two `tzcnt` + `cmove`, `−32`, no early exit.
*"The gather dominated"* is refuted. What #1241's 12.5 ns timed is
unknown (no harness shipped with it); entry (17) gives the carrier-2
account as the strongest available and labels it so.
- **Deferred / named:** `as_u128()` is NOT a reinterpret — it rebuilds
through `to_bytes()` while `as_bytes()` (the documented no-op) sits unused
on that path; the E-carve (`{axis} × {near, far}`, stride 2) and the
fixed-width-register sentence for doctrine §1; carrier-2's masked rewrite
(gated on its own probe, D-TCF-4); the census passes (D-TCF-5). None
built.
- **Review:** Codex 2× P2 on the probe (oracle checked 256 of 65,536; the
anti-vacuity check warned and exited 0) — both real, both fixed in
`c3de1d2e`. Two board gates red on the first push — `D-3CF-*` does not
match the D-id pattern (two letters first) → `D-TCF-*`; two `ISSUES.md`
line-number citations → stable symbol anchors. CodeRabbit had not
finished when the operator merged.
- **Confidence:** HIGH on the numbers (in-tree, reproducible, oracle-first,
three independent runs same ordering). HIGH that the restore is verbatim
(diff). The three-carrier taxonomy is a reading of the tree offered as
explanation, not a proof of what #1241 timed.

## 2026-09-16 — lance-graph PR #1241 (merged `d5d3f7ab`, branch `claude/c64-6502-falsifier-shztkk`) — the facet's per-axis LCP reads the single register; the `"{0}{1}" -f` fold is done ONCE at mint

- **Added:** `FacetCascade::{HI_BYTES, LO_BYTES}` (const byte masks over the
Expand Down
Loading
Loading