Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
546b17a
Core vertical slice: docs/abi.md contract, native/lgj-abi, Java facade
AdaWorldAPI Aug 17, 2026
a1e65cc
Merge main (bootstrap commit) into dev branch to establish shared his…
AdaWorldAPI Aug 17, 2026
bdd40b2
Valhalla lab: three-truths method, causal isolation, 3 real reproducers
AdaWorldAPI Aug 17, 2026
317ee83
Merge main (squash of PR #1) to fix history divergence for PR #2
AdaWorldAPI Aug 17, 2026
ea4753c
Merge main (squash of PR #2) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
4ab0da8
Vector API bench: real JMH, cross-checked; the crossing does not alwa…
AdaWorldAPI Aug 17, 2026
96eccff
Merge main (squash of PR #3) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
cd7782b
Phase I synthesis docs + fusion-sweep 256-row re-run + board hygiene
AdaWorldAPI Aug 17, 2026
ddeaecb
Merge main (squash of PR #4) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
e4463cb
Board: PR #4 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
e8b6dc2
SoA row store: 512B rows, 32 facet lanes, ABI minor 2 (W1+W2)
AdaWorldAPI Aug 17, 2026
aff72f3
Merge main (squash of PR #5) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
8fceaca
Board: PR #5 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
91e22f3
Knowledge: assess the archived layout-bridge discussion; name W6
AdaWorldAPI Aug 17, 2026
6927961
Plans: OGAR Machine (exploratory) + lance-graph-hydrate dependency note
AdaWorldAPI Aug 17, 2026
7e218ed
Merge main (squash of PR #6) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
9cc85ad
Board: PR #6 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
f3bbab7
Waves calcified: dispatch maps for every plan; Ghidra plan from real …
AdaWorldAPI Aug 17, 2026
dac0f0b
Merge main (squash of PR #7) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
57a7e48
Board: PR #7 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
83b8994
Plan: lance-graph #958 merged (was open at last check)
AdaWorldAPI Aug 17, 2026
572f865
Java RowStore facade: W3 shipped (185/185, one bug found+fixed)
AdaWorldAPI Aug 17, 2026
b138382
Merge main (squash of PR #8) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
bc6f91a
Board: PR #8 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
619b3de
Plan: r2sleigh recorded as third lift path + decompiler candidate
AdaWorldAPI Aug 17, 2026
84e73ca
Bench Component F: the boundary re-asked on the real row-store layout…
AdaWorldAPI Aug 17, 2026
897fd92
Merge main (squash of PR #9) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
201a626
Board: PR #9 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
ed4fb7c
Parity: the third independent read path (ROW_LAYOUT segment reads)
AdaWorldAPI Aug 17, 2026
6c4afe4
Merge main (squash of PR #10) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
9717cda
Board: PR #10 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
8eecb3b
Consumer example: World/Trades — the zero-object fluent domain API (W5a)
AdaWorldAPI Aug 17, 2026
74e5b6b
Merge main (squash of PR #11) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
9088dc9
Board: PR #11 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
f7974da
Consumer example: Bricks — mask-first authorization, fail-closed, agg…
AdaWorldAPI Aug 17, 2026
ce6fba4
Merge main (squash of PR #12) to keep dev branch history aligned
AdaWorldAPI Aug 17, 2026
239edf0
Board: PR #12 arc entry (post-merge)
AdaWorldAPI Aug 17, 2026
9ee044f
Board: record the C-band ruling — the classid domain byte carries ALT…
AdaWorldAPI Aug 18, 2026
e736d6a
Board: reconcile Ghidra G1/G2 -- superseded by ruff_r2il, not built
AdaWorldAPI Aug 18, 2026
f68335b
Board: ruff #96 is a different arm; read the real staging guide + ran S1
AdaWorldAPI Aug 18, 2026
df35426
Board: R2IL handshake outcomes + the Valhalla-premise storno (operato…
AdaWorldAPI Aug 18, 2026
8806899
rowstore: generate_with_edges -- the graph-consumer wave's real, meas…
AdaWorldAPI Aug 18, 2026
f03a9ce
Merge main (squash of PR #13) to keep dev branch history aligned
AdaWorldAPI Aug 18, 2026
ae02be5
lgj-abi: edge-bearing row store ABI addition (lgj_rowstore_open_with_…
AdaWorldAPI Aug 18, 2026
c8af78b
Merge remote-tracking branch 'origin/main' into claude/lance-graph-ja…
AdaWorldAPI Aug 18, 2026
05a6780
Board: PR #14 arc entry (edge-bearing row store ABI addition)
AdaWorldAPI Aug 18, 2026
99c356c
Merge remote-tracking branch 'origin/main' into claude/lance-graph-ja…
AdaWorldAPI Aug 18, 2026
75aac22
RowStore: public per-row payload accessors (classidAt/payloadLow64At/…
AdaWorldAPI Aug 18, 2026
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
89 changes: 89 additions & 0 deletions .claude/board/EPIPHANIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,95 @@
> `**Status:**`/`**Confidence:**` line. A correction gets its own new,
> dated entry that references the one it corrects — the storno rule.

## 2026-08-18 (even later still) — the same gap, one layer up: no PUBLIC path to a payload either, and a self-caught vacuous disable-run

**Status:** FINDING + a correction of the entry directly below (which
declared the substrate complete at the ABI level, but not at the public
core-facade level) + a process note about catching my OWN vacuous
falsifier rather than an existing one. **Confidence:** High — measured
(full test suite before/after, two disable-runs, one of them initially
wrong and caught by re-reading rather than trusting a green result).

### What the ABI-minor-3 entry's own "genuinely dispatchable" undersold

Immediately after landing `lgj_rowstore_open_with_edges`, worked through
concretely — not just in principle — how `consumers/graph`'s `Graph.hop()`
would decode a matched facet's target row. It could not:
`RowStore.facetMatches` returns a per-row **bitset** of which facets
matched a classid; it never carries the matched facet's payload bytes.
The only capability that ever read raw row bytes at all was
`internal.ffm.Engine.describeLane`, and `ApiSurfaceTest` forbids
`internal.*`/`MemorySegment` from appearing in any consumer-package public
signature, by design, mechanically enforced. Decision D1a's own text —
*"read matched facets' payloads via the raw lane 0 segment (zero-copy, no
crossing)"* — assumed a capability that existed only inside the core
package's own internals, never surfaced to a consumer. Same shape of gap
as the ABI-symbol one, one layer higher: **"the mechanism exists
internally" was mistaken for "a consumer can reach it" twice in the same
wave.**

### The fix — zero new ABI surface, reuse what already exists

`RowStore.classidAt(long row, FacetId facet)` / `payloadLow64At(...)` /
`payloadHi32At(...)`: three new public, primitive-returning methods. No
new `extern "C"` symbol, no ABI minor bump — they reuse `lgj_lane_describe`
(already minor 1, already classified "lifecycle" per abi.md §6), resolved
once per store and cached; every subsequent call is an in-process segment
read with zero further crossings, matching `exports.rs`'s own stated
doctrine verbatim: *"if Java wants one row it reads the MemorySegment
in-process, with no crossing at all."*

Added to `RowStoreParityTest`: the SAME pinned hop numbers (19 at 1 hop,
29 at 2 hops) reproduced a SECOND time — this time through the genuinely
public path — proving not just that the mechanism works, but that a real
`consumers/graph` package can actually reach it. `AllTests` 204/204
(+10 over the prior entry's 194).

### The self-caught vacuous disable-run — worth recording precisely

First draft guarded the closed-store check in `rawLane()` (the method that
actually touches the native pointer) AND, redundantly, in `rowOffset()`
(pure arithmetic, touches nothing). Disabled `rawLane()`'s check to prove
it load-bearing — and the full disable-run test suite came back **30/30
green**, under code that was genuinely broken. The natural move at that
point is to trust the green result and move on. Instead: asked WHY it
didn't fail, and found the answer in Java's own evaluation order —
`a.method(args)` evaluates the receiver `a` before the argument list, so
`rawLane().get(..., rowOffset(row, facet))` always runs `rawLane()` first;
disabling only `rawLane()`'s guard left `rowOffset()`'s redundant copy to
catch the closed-store case anyway, masking the disable entirely.

De-duplicated to the single correct location (the guard belongs on the
method that touches the pointer, not on pure arithmetic downstream of it)
and re-ran the SAME disable-run against the corrected code: this time it
went red exactly as expected (`expected ClosedResourceException but
nothing was thrown` on both affected checks), then green on restore.

**The generalizable rule, sharper than the falsifiability rule's usual
form:** a disable-run that stays green is not automatically a passing
grade for the CODE — it may be a failing grade for the TEST's isolation.
Redundant guards are the one shape of bug a disable-run can silently
paper over, because disabling one leaves the other standing. The fix
generalizes past this file: when a disable-run doesn't fire, the next
question is never "good, unaffected" — it is "did I disable the thing
that actually runs, or a copy of it."

### Gates

`javac -Xlint:all` clean (same 7 pre-existing `[restricted]` warnings, zero
new). `AllTests` **204/204**. `ApiSurfaceTest` unchanged at 3/3 — zero FFM
type introduced into any public signature. Both disable-runs (bounds
guard via `IndexOutOfBoundsException`, closed-store guard via the
corrected single location) verified red-then-green.

### Consequence

The graph-consumer wave is now dispatchable on genuinely solid ground,
proven at three independent, individually-tested levels: the Rust
generator (below), the ABI membrane (below), and the public core facade a
`consumers/graph` package can actually compile against (this entry). G1
(traversal facade) and G2 (falsifier tests) are next, not yet spawned.

## 2026-08-18 (later still) — "the generator exists" ≠ "Java can reach it": the membrane gap the prior entry's own resolution note missed

**Status:** FINDING + a correction of the entry directly below this one.
Expand Down
32 changes: 32 additions & 0 deletions .claude/board/LATEST_STATE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
## 2026-08-18 (even later still) — a SECOND gap, one layer up: the graph wave also had no public path to a payload

Immediately after PR #14/#15 merged, worked through concretely how G1's
`Graph.hop()` would actually decode a matched facet's target row. Answer:
it couldn't. `facetMatches` gives a per-row 32-bit BITSET of which facets
matched — never the payload bytes. The only thing that ever read raw row
bytes was `internal.ffm.Engine.describeLane`, off-limits to a consumer
package (`ApiSurfaceTest` forbids `internal.*`/`MemorySegment` in any
public signature by construction). D1a's own text ("read matched facets'
payloads via the raw lane 0 segment") assumed a capability that existed
internally but had never been surfaced publicly — a second version of the
exact gap PR #14 closed, one layer higher.

Fixed with zero new ABI surface: `RowStore.classidAt`/`payloadLow64At`/
`payloadHi32At` reuse `lgj_lane_describe` (already ABI minor 1, already a
"lifecycle" crossing per abi.md §6) — resolved once, cached, every
subsequent read is in-process. `AllTests` 204/204 (+10 over PR #14's 194).

**A redundancy I introduced and caught myself, worth recording as a
process note:** the first draft guarded the closed-store check in TWO
places; disabling one was silently masked by the other, and the
disable-run came back green under genuinely broken code — a false
negative I could have accepted and moved on. Traced it to Java's
receiver-before-argument evaluation order, de-duplicated to the one
correct location, and only THEN did the same disable-run go properly red.
Full record: `STATUS_BOARD.md` D-LGJ-W7, `EPIPHANIES.md`.

The graph-consumer wave is now dispatchable for real, proven at three
independent levels rather than one: the Rust generator, the ABI membrane,
and the public core facade a consumer package can actually compile
against. G1/G2 next.

## 2026-08-18 (later still) — the graph wave's ABI gap, found and closed before dispatch: `lgj_rowstore_open_with_edges` (minor 3)

Picked up the graph-consumer wave on "everything on track?" — it was marked
Expand Down
1 change: 1 addition & 0 deletions .claude/board/STATUS_BOARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ layout wired end to end. Doctrine: `E-LGJ-THE-MIDDLE-TIER-IS-DELETED-NOT-WRAPPED
| D-LGJ-W4 | Bench Component F: Vector API facet scan vs the crossing, on the REAL layout | **DONE 2026-08-17** — 1 Sonnet worker (F_RowStoreFacetScan + RowStoreData + Kernels facet-match arms, cross-check-in-@Setup discipline), orchestrator-run JMH: 9/9 combos, cross-checks green at every row count. **Finding: Component C's direction survives, its margin collapses** — Vector API wins the 32-facet strided scan at every row count but by 2.51×/1.92×/1.14× (4K/65K/1M rows) vs C's 56×; at 512 MiB traversed all three arms converge on memory bandwidth. Native arm's per-call allocation asymmetry disclosed in §F with a named follow-up (`facetMatchesInto`), not hidden. summarise.sh extended with the F table (and the old 'E/F' section retitled 'E' — a real naming collision); tables regenerated from the merged CSV |
| D-LGJ-W5 | Three consumer examples (trades / bricks / graph) — one plan file each | **trades DONE 2026-08-17** — `consumers/trades/` (own compile unit, core consumed as a third-party would): `Trade` (schema-not-entity: zero public ctors, zero instance fields, reflection-forced construction still throws), `World.open` → the existing lazy `View` under domain names, zero new membrane surface. TradesParityTest 12/12 (chain vs transcribed-generator recomputation at 1K+64K rows; 0 crossings composing / 1 at terminal THROUGH the domain vocabulary; reflection guard). TradesAllocationTest 3/3 — **the poster's number, measured: 240 bytes/query, IDENTICAL at 64K and 1M rows** (row-count independence is the thesis assertion; 64 KiB absolute backstop). Disable-run: VENUE pointed at the wrong lane → the membrane's own LANE_KIND_MISMATCH rejected it (the binding is checked, not trusted); restored green. **bricks DONE 2026-08-17** — `consumers/bricks/` (2 Sonnet workers K1/K2 per `.claude/waves/wave-consumer-bricks.md`): mask-first RBAC where `authorize(Role)` is a real natively-evaluated predicate in the SAME lazy chain as `where(...)` (`Role.EU_ONLY` = `REGION.eq(EU)`, `DENY_ALL` = `REGION.eq(0xFFFF)` — a genuine impossible predicate, not a Java branch), fail-closed (`UnauthorizedQueryException` BEFORE any crossing; no default-allow path exists), aggregate-only egress (every public method returns `BricksQuery`/`long`/`Map` — structurally no row-shaped type). BricksAuthTest **62/62**: parity vs transcribed generator at 1K+64K; RBAC-as-predicate equivalence (EU_ONLY result == GLOBAL+explicit-where); DENY_ALL counts 0 while paying a real crossing; crossing arithmetic — count()=1, sumBy()=**32 crossings (16 groups × 2: plan_eval + lgj_reduce_sum_i32), IDENTICAL at both row counts** (the thesis: crossings ∝ groups, never rows — the measured 32 corrected K1's "1 per group" Javadoc claim, a real finding about sum-terminal cost); reflection guards. Disable-run: `requireAuthorized` short-circuited → **exactly the 3 can-fire fail-closed checks red, 59 green**; restored, 62/62. Core suite unaffected (188/188). **graph: substrate now fully unblocked (D-LGJ-W6, this pass) — dispatch is the next action, not yet executed** |
| D-LGJ-W6 | Edge-bearing row store ABI addition (`lgj_rowstore_open_with_edges`, minor 2→3, docs/abi.md §12) — the D1b-shaped "must land as its own W-tier PR before the consumer wave" the graph wave itself named | **DONE 2026-08-18** — orchestrator-authored (genuinely new ABI surface, not consumer-scope work): `registry::open_rowstore_with_edges` + `lgj_rowstore_open_with_edges` (mirrors `lgj_rowstore_open` exactly: same resource kind, same lane shape, no new mask op — purely an alternative constructor), `Engine.openRowStoreWithEdges`/`Abi.requireMinor(3)`, `RowStore.openWithEdges`. `cargo test` **93/93** (+3: registry-level open/describe, out-of-range-classid-matches-plain, radius-overflow-rejected), clippy/fmt clean, release build exports the new symbol (`nm -D`). Java: `AllTests` **194/194** (+6, all in `RowStoreParityTest`) — the strongest new result is a cross-language reproduction of the D1a hop mechanism itself: Java facet-matches + raw-lane-0 payload decode (zero new ABI op) reaches the EXACT same measured hop counts already pinned as a Rust regression (10-row seed → 19 at 1 hop → 29 at 2 hops, `n=2000, seed=0xF00D_CAFE, edge_classid=0, gate_mask=0x0, radius=25`) — proving the two sides of the membrane see identical edge structure, not merely identical classids. Two disable-runs, both red-then-green: (1) registry-level, a classid-not-threaded bug (`open_rowstore_with_edges` hardcoded classid `0`) caught by the out-of-range-parity test; (2) Java-level, the hop's classid-match condition forced to always skip → 1-hop/2-hop both went to 0 and the anti-vacuity assertion failed, exactly as expected. Caught mid-dispatch: the ABI-facing symbol did not exist before this pass (only the bare `RowStore::generate_with_edges` Rust function did, from the prior session) — the graph wave's own STOP-condition-RESOLVED note undersold what was still missing; closed here rather than discovered by G1/G2 mid-flight |
| D-LGJ-W7 | Core public facade: `RowStore.classidAt`/`payloadLow64At`/`payloadHi32At` — the per-row zero-copy escape hatch a real `Graph.hop()` needs, since neither `maskOfFacetClass` nor `facetMatches` exposes payload bytes and `ApiSurfaceTest` forbids `MemorySegment`/`internal.*` in any consumer-package signature | **DONE 2026-08-18** — found while checking, concretely, how `consumers/graph` (a genuinely external compile unit per every prior consumer wave's own convention) could ever decode a matched facet's target row: it couldn't — D1a's design assumed a zero-copy raw-lane read Java-side, but nothing on the PUBLIC `RowStore` facade exposed one; only `internal.ffm.Engine.describeLane` did, off-limits to a consumer package by construction. Fixed with THREE new primitive-returning `RowStore` methods, zero new ABI surface at all (reuses `lgj_lane_describe`, already ABI minor 1 — a "lifecycle" crossing per abi.md §6, resolved once and cached; every read after is in-process, matching exports.rs's own stated doctrine "if Java wants one row it reads the MemorySegment in-process, with no crossing at all"). `AllTests` **204/204** (+10 over D-LGJ-W6: 6 in `RowStoreParityTest` — the SAME pinned hop numbers (19/29) reproduced a SECOND time, this time through the genuinely public path a real consumer has to use, plus bounds checks; 6 in `RowStoreLifetimeTest` — closed-before-first-read and closed-after-caching, both guarded). **A real self-caught redundancy, not shipped silently**: the first draft carried the closed-store guard in TWO places (`rawLane()` and `rowOffset()`); disabling one was masked by the other and produced a false-negative disable-run (30/30 green under a broken guard) — caught by re-reading WHY the disable didn't fire rather than accepting the green result, traced to Java method-call evaluation order (`rawLane()`, the receiver, evaluates before `rowOffset()`, its argument), de-duplicated to the ONE correct location, disable-run re-run and confirmed genuinely red-then-green. `ApiSurfaceTest` still 3/3 — zero FFM-typed public signature introduced. **The graph-consumer wave is now dispatchable for real**, proven at three independent levels: Rust generator (D-LGJ-W5's own entry below), ABI membrane (D-LGJ-W6), and the public core facade a consumer package can actually compile against (this row) |
75 changes: 75 additions & 0 deletions java/src/main/java/com/adaworldapi/lancegraph/RowStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,81 @@ public FacetMatchView facetMatches(int classId) {
return new FacetMatchView(this, out, rowCount);
}

private static final long ROW_BYTES = 512;
private static final long FACET_BYTES = 16;

/**
* The raw lane-0 window (docs/abi.md §11), resolved once via {@code lgj_lane_describe} (ABI
* minor ≥ 1 — already required by every {@code RowStore}) and cached: this is a
* <strong>lifecycle</strong> crossing, per abi.md §6, not a bulk one, and every read through
* {@link #classidAt}/{@link #payloadLow64At}/{@link #payloadHi32At} afterward is an
* in-process segment read with no further crossing at all — exports.rs's own doctrine, applied:
* "if Java wants one row it reads the MemorySegment in-process, with no crossing at all."
*/
private MemorySegment rawLane;

private MemorySegment rawLane() {
requireOpen("row read");
if (rawLane == null) {
rawLane = Engine.describeLane(handle, 0).segment();
}
return rawLane;
}

private long rowOffset(long row, FacetId facet) {
// No requireOpen() here -- rawLane() (evaluated first, as the receiver, in every one of
// this method's three callers) already owns that check. Pure arithmetic, touches nothing,
// needs no guard of its own; duplicating it here would be a second lock on a door only one
// key opens.
java.util.Objects.requireNonNull(facet, "facet");
if (row < 0 || row >= rowCount) {
throw new IndexOutOfBoundsException(
"row " + row + " is out of range [0, " + rowCount + ")");
}
return row * ROW_BYTES + facet.index() * FACET_BYTES;
}

/**
* The classid at {@code (row, facet)} — a zero-copy, in-process read (see {@link #rawLane()}'s
* doc for why this never crosses the membrane after the first call on this store).
*
* <p>This is the per-row escape hatch the bulk predicates exist alongside, not a replacement
* for them: use {@link #maskOfFacetClass}/{@link #facetMatches} for a bulk selection over every
* row, this for reading one row a caller already knows it wants — e.g. decoding a graph hop's
* target row after {@link #facetMatches} has already named which facet matched.
*
* @throws IndexOutOfBoundsException if {@code row} is not in {@code [0, rowCount())}
*/
public int classidAt(long row, FacetId facet) {
return rawLane().get(ValueLayout.JAVA_INT_UNALIGNED, rowOffset(row, facet));
}

/**
* The low 64 payload bits at {@code (row, facet)}, little-endian — the row-store's
* structured-edge target-row convention (docs/abi.md §12, {@link #openWithEdges}) when this
* facet is a structured edge for this row. Meaningless, but always safe to read, when it is
* not: combine with {@link #classidAt} and {@link #payloadHi32At} to decide that — the
* generator's own convention is {@code classidAt(row, facet) == edgeClassid &&
* payloadHi32At(row, facet) == 0}.
*
* @throws IndexOutOfBoundsException if {@code row} is not in {@code [0, rowCount())}
*/
public long payloadLow64At(long row, FacetId facet) {
return rawLane().get(ValueLayout.JAVA_LONG_UNALIGNED, rowOffset(row, facet) + 4);
}

/**
* The high 32 payload bits at {@code (row, facet)} — {@code 0} exactly when {@link
* #openWithEdges}'s generator wrote a structured edge target here (docs/abi.md §12);
* overwhelmingly non-zero, by construction, for ordinary noise payload — including every
* facet of a store opened with plain {@link #open}.
*
* @throws IndexOutOfBoundsException if {@code row} is not in {@code [0, rowCount())}
*/
public int payloadHi32At(long row, FacetId facet) {
return rawLane().get(ValueLayout.JAVA_INT_UNALIGNED, rowOffset(row, facet) + 12);
}

/**
* The generation-checked registry handle. Package-private — mirrors {@link
* NativePattern#handle()} exactly, including its consumer: {@code bench}'s {@code
Expand Down
Loading