|
8 | 8 | > anti-pattern the imported board rules name. Backfilled below in one |
9 | 9 | > pass rather than left stale; PR #4 onward gets its entry at merge time. |
10 | 10 |
|
| 11 | +## PR #81 — Panama × Valhalla as ONE production membrane (merged `07aa441`, branch `claude/great-pascal-k96kok`, head `1c66091`, 3 commits) |
| 12 | + |
| 13 | +**Entry written at merge**, not backfilled. |
| 14 | + |
| 15 | +- **Frame, and it is the point:** NOT a JDK 26→28 migration. The two halves |
| 16 | + that were split — Panama FFM in production, Valhalla in the lab — became one |
| 17 | + production membrane. JDK 28 is the enabling toolchain, nothing more. Panama |
| 18 | + carries the VERB (reach into canonical bytes); Valhalla carries the NOUN |
| 19 | + (identity-free semantic addresses over them); **lance-graph / T0 still owns |
| 20 | + the only canonical copy.** |
| 21 | +- **Added:** `CLAUDE.md` § P0 (the operator mandate); the six vocabulary types |
| 22 | + as `public value record` (`LaneId`, `MaskId`, `Ordinal`, `FacetId`, |
| 23 | + `RowRange`, `WideFieldMask`); `plan_lower::range_falsifier:: |
| 24 | + no_opcode_lowers_to_pred_range`; JDK 28 + preview across `bench/run.sh`, |
| 25 | + `bench/gate-run.sh`, `java/README.md`, `README.md`, `docs/panama.md`, |
| 26 | + `panama-bridge-engineer.md`, `BOOT.md`; `jdk-toolchain-facts.md` § "JDK 28 — |
| 27 | + INSTALLED AND MEASURED" with the obtain route. |
| 28 | +- **Fixed (this blocked everything):** `lgj-abi` did not compile against |
| 29 | + lance-graph `main`. `mask_risc::ExecError` gained `RangeOutOfBounds` with the |
| 30 | + `Pred::Range` work and `exec_error_to_status` matches exhaustively. Mapped |
| 31 | + into the documented *"bug in THIS file"* family — no new public status, no |
| 32 | + ABI bump — and fenced by the falsifier above, **disable-verified |
| 33 | + red-then-green**. *Standing hazard, corrected before merge (Codex P2 on #82, |
| 34 | + verified against `.github/workflows/lint.yml`): an exhaustive match across a |
| 35 | + repo boundary turns an upstream ADDITIVE change into a downstream build |
| 36 | + failure. ⊘ The first draft blamed the wrong thing — it said "no CI job here |
| 37 | + compiles the native crate", which is FALSE: the `clippy` and `rust-test` |
| 38 | + jobs check out sibling `AdaWorldAPI/lance-graph` and run |
| 39 | + `cargo clippy --all-targets` / `cargo test` from `native/lgj-abi`, so CI |
| 40 | + compiles it on every push and PR **to this repo**. The real gap is the |
| 41 | + TRIGGER, not the coverage: `on: {pull_request, push}` fires on this |
| 42 | + repository only, so an upstream-only merge in lance-graph cannot start this |
| 43 | + workflow and the break stays invisible until someone pushes here. Naming it |
| 44 | + as missing coverage would have sent the next session to add a job that |
| 45 | + already exists.* |
| 46 | +- **Measured** (Temurin `28+16-ea`, fresh `liblgj_abi.so` abi 0.11 avx512): |
| 47 | + **183 native tests**; **`ALL PASSED (409 checks)`** — byte-for-byte the same |
| 48 | + 409 as the unflipped baseline **on the same JDK**, which is the comparison |
| 49 | + that matters. All six types `isValue() == true`; substitutability holds. |
| 50 | + **The 8-byte flattening cliff REPRODUCES on JDK 28:** `LaneId`/`Ordinal` |
| 51 | + (4 B) and `MaskId` (8 B) FLAT; **`RowRange` (2 long, 16 B) and `Row` (16 B) |
| 52 | + NOT-FLAT.** Allocation, record → value, 1M ops: construct-into-array |
| 53 | + 15.26 → **1.87 MiB** (8.2×); allocate+fill 19.07 → 5.65 MiB; `Descriptor` |
| 54 | + 45.78 → 27.89 MiB; ⊘ **never-escaping 4.73 → 5.75 MiB (WORSE** — EA already |
| 55 | + erased the record case**)**; ⊘ **hydrate 65,536 `Row` 1.50 → 2.00 MiB |
| 56 | + (WORSE** — `Row` does not flatten**)**. **FFM path byte-identical across |
| 57 | + arms:** 712 B/query, 0 Java objects per row, same native bytes. |
| 58 | +- **Locked:** `value semantics ≠ flattening` — `RowRange` is a production type |
| 59 | + on the wrong side of the cliff and no performance claim may be read off its |
| 60 | + `isValue()`. Valhalla changes what the VOCABULARY costs; it does not touch |
| 61 | + the membrane. No second graph representation, and **no PRODUCTION row |
| 62 | + hydration** introduced — scoped deliberately, because this entry reports a |
| 63 | + `hydrate 65,536 Row` number two bullets up and an unqualified claim would |
| 64 | + contradict its own measurement. That number is a LAB probe of what hydration |
| 65 | + would cost; production takes no such path. |
| 66 | +- **The harness is now a REPRESENTATION probe suite, not a "Valhalla lab" — |
| 67 | + Valhalla graduated to production infrastructure and is no longer the thing |
| 68 | + under test.** `valhalla-lab/` keeps its directory name for path |
| 69 | + compatibility only; a doc banner says so. What it measures is object-model |
| 70 | + and layout consequence: `record` vs `value record` **on one JDK, against the |
| 71 | + same Valhalla-enabled production API**, with flattening and EA toggled. |
| 72 | + **The re-scope also removed a confound the harness always carried:** the old |
| 73 | + A/B was `(record, JDK 26)` vs `(value record, JDK 27 EA)` — two variables. |
| 74 | + Both arms now run JDK 28, so the object model is the only difference. Two things it forced: **preview marking is transitive** (the |
| 75 | + `record` arm also runs `--enable-preview`; it is a record arm on a preview |
| 76 | + JVM, not a preview-free one), and **`ValueClass.isFlatArray` narrowed from |
| 77 | + `Object` to `Object[]`** since 27-jep401ea3, which broke the flattening probe |
| 78 | + until adapted. |
| 79 | +- **Struck:** the *"production targets a shipped GA JDK, no preview flags — a |
| 80 | + real, deliberate strength"* decision, in place in `jdk-toolchain-facts.md`. |
| 81 | + It dressed a release constraint as an architectural virtue and had already |
| 82 | + licensed the false claim *"production lgj does not depend on Valhalla at |
| 83 | + all."* |
| 84 | +- **Deferred, stated rather than implied:** `bench/` cannot run here — |
| 85 | + `bench/lib` does not exist, so the JMH jars are absent. `bench/RESULTS.md` |
| 86 | + numbers remain **JDK 26 historicals, correct when taken**, deliberately |
| 87 | + untouched and **NOT re-taken on JDK 28**. `gate-run.sh` carries the new pin |
| 88 | + and flags, so the re-run is one command once the jars are present. |
| 89 | +- **Confidence:** high on everything measured in-container; the JMH |
| 90 | + crossing/allocation figures are unverified on JDK 28 and are labelled so. |
| 91 | + |
11 | 92 | ## PR #79 — `hop_cached_vs_gather`: the M1b tile pays off on hop two; the scatter walk is the access-shape question (opened 2026-09-16, merged `9cb63e9`, head `c10029b`) |
12 | 93 |
|
13 | 94 | > **Post-merge backfill, owned (2026-09-16):** this entry was NOT written at |
|
0 commit comments