|
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 worth the sentence: an exhaustive match |
| 34 | + across a repo boundary turns an upstream ADDITIVE change into a downstream |
| 35 | + build failure, and no CI job here compiles the native crate, so nothing saw |
| 36 | + it.* |
| 37 | +- **Measured** (Temurin `28+16-ea`, fresh `liblgj_abi.so` abi 0.11 avx512): |
| 38 | + **183 native tests**; **`ALL PASSED (409 checks)`** — byte-for-byte the same |
| 39 | + 409 as the unflipped baseline **on the same JDK**, which is the comparison |
| 40 | + that matters. All six types `isValue() == true`; substitutability holds. |
| 41 | + **The 8-byte flattening cliff REPRODUCES on JDK 28:** `LaneId`/`Ordinal` |
| 42 | + (4 B) and `MaskId` (8 B) FLAT; **`RowRange` (2 long, 16 B) and `Row` (16 B) |
| 43 | + NOT-FLAT.** Allocation, record → value, 1M ops: construct-into-array |
| 44 | + 15.26 → **1.87 MiB** (8.2×); allocate+fill 19.07 → 5.65 MiB; `Descriptor` |
| 45 | + 45.78 → 27.89 MiB; ⊘ **never-escaping 4.73 → 5.75 MiB (WORSE** — EA already |
| 46 | + erased the record case**)**; ⊘ **hydrate 65,536 `Row` 1.50 → 2.00 MiB |
| 47 | + (WORSE** — `Row` does not flatten**)**. **FFM path byte-identical across |
| 48 | + arms:** 712 B/query, 0 Java objects per row, same native bytes. |
| 49 | +- **Locked:** `value semantics ≠ flattening` — `RowRange` is a production type |
| 50 | + on the wrong side of the cliff and no performance claim may be read off its |
| 51 | + `isValue()`. Valhalla changes what the VOCABULARY costs; it does not touch |
| 52 | + the membrane. No second graph representation, no row hydration introduced. |
| 53 | +- **Lab re-scoped, and the re-scope removed a confound it always carried:** the |
| 54 | + old A/B was `(record, JDK 26)` vs `(value record, JDK 27 EA)` — two |
| 55 | + variables. Both arms now run JDK 28, so the object model is the only |
| 56 | + difference. Two things it forced: **preview marking is transitive** (the |
| 57 | + `record` arm also runs `--enable-preview`; it is a record arm on a preview |
| 58 | + JVM, not a preview-free one), and **`ValueClass.isFlatArray` narrowed from |
| 59 | + `Object` to `Object[]`** since 27-jep401ea3, which broke the flattening probe |
| 60 | + until adapted. |
| 61 | +- **Struck:** the *"production targets a shipped GA JDK, no preview flags — a |
| 62 | + real, deliberate strength"* decision, in place in `jdk-toolchain-facts.md`. |
| 63 | + It dressed a release constraint as an architectural virtue and had already |
| 64 | + licensed the false claim *"production lgj does not depend on Valhalla at |
| 65 | + all."* |
| 66 | +- **Deferred, stated rather than implied:** `bench/` cannot run here — |
| 67 | + `bench/lib` does not exist, so the JMH jars are absent. `bench/RESULTS.md` |
| 68 | + numbers remain **JDK 26 historicals, correct when taken**, deliberately |
| 69 | + untouched and **NOT re-taken on JDK 28**. `gate-run.sh` carries the new pin |
| 70 | + and flags, so the re-run is one command once the jars are present. |
| 71 | +- **Confidence:** high on everything measured in-container; the JMH |
| 72 | + crossing/allocation figures are unverified on JDK 28 and are labelled so. |
| 73 | + |
11 | 74 | ## 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 | 75 |
|
13 | 76 | > **Post-merge backfill, owned (2026-09-16):** this entry was NOT written at |
|
0 commit comments