Skip to content

Commit e1f909f

Browse files
authored
Merge pull request #82 from AdaWorldAPI/claude/great-pascal-k96kok
board: PR #81 arc entry + LATEST_STATE
2 parents 07aa441 + 7751ff1 commit e1f909f

6 files changed

Lines changed: 163 additions & 22 deletions

File tree

.claude/board/EPIPHANIES.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
## E-THE-CI-GAP-WAS-THE-TRIGGER-NOT-THE-COVERAGE-1 (2026-09-19)
2+
3+
**Corrects `E-THE-VALHALLA-FLIP-COST-ONE-WORD-SIX-TIMES-…-1` below**, which
4+
says the `RangeOutOfBounds` break went unseen *"because no CI job here compiles
5+
the native crate."* **That is false, and checkable in one file.**
6+
`.github/workflows/lint.yml` runs `clippy` and `rust-test` jobs that check out
7+
sibling `AdaWorldAPI/lance-graph` (and `ndarray`, and `OGAR`) and then run
8+
`cargo clippy --all-targets -- -D warnings` and `cargo test` from
9+
`native/lgj-abi`. The native crate is compiled against the real sibling on
10+
every push and PR **to this repository**.
11+
12+
**The actual hazard is the TRIGGER.** The workflow is `on: {pull_request,
13+
push}`, which fires for events in *this* repo only. An upstream-only merge in
14+
lance-graph — exactly what added `ExecError::RangeOutOfBounds` — cannot start
15+
it, so the break stayed invisible until the next push here. Coverage was never
16+
missing; the *event* was.
17+
18+
**Consequence for the next session:** do not add a CI job for this — one
19+
exists. The open gap is upstream-change notification, and nothing in this
20+
repository's triggers can close it. Raised by Codex P2 on #82, verified
21+
against the workflow.
22+
123
## E-PANAMA-TIMES-VALHALLA-IS-ONE-MEMBRANE-AND-THE-LAB-FINALLY-HAS-ONE-VARIABLE-1 (2026-09-19)
224

325
**Operator reframing, and it is the correct one:** this was never a JDK 26→28
@@ -131,14 +153,13 @@ tripwire, not a safety net:** it converts an upstream additive change into a
131153
downstream build failure, and nothing in either repo's CI noticed, because no
132154
CI job here compiles the native crate.
133155

134-
**Two false failures I nearly reported, both mine, both caught by reading.**
135-
The flipped suite showed `1 FAILED` twice. Both times it was
136-
`DoctrineFenceTest` refusing to run — it requires `java/src/main/java` AND
137-
`native/lgj-abi/src` relative to CWD, and I had run the flipped build from a
138-
scratch directory that had neither. The fence is *correct*: its first check is
139-
*"a fence that cannot find its corpus must fail, not skip."* Running the flip
140-
in the real tree (committed first, restored with `git checkout`) gave the true
141-
result. **A harness artifact and a regression look identical in a summary
156+
**Harness note, so the next run is not misread.** The flipped suite reports
157+
`1 FAILED` when run from a directory lacking `java/src/main/java` AND
158+
`native/lgj-abi/src``DoctrineFenceTest` resolves both relative to CWD and
159+
refuses to run without them. The fence is behaving correctly: its first check
160+
is *"a fence that cannot find its corpus must fail, not skip."* **Run the flip
161+
in the real tree** (commit first; restore with `git checkout`) or the result is
162+
not the suite's. **A harness artifact and a regression look identical in a summary
142163
line** — this is the ruff trap "a disable that does not apply is
143164
indistinguishable from a guard that is not load-bearing", met from the other
144165
direction.

.claude/board/LATEST_STATE.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
## 2026-09-19 — PR #81 merged (`07aa441`): production IS the Valhalla arm; Panama × Valhalla is one membrane
2+
3+
**The frame, because it is easy to file this wrong:** this was not a JDK
4+
26→28 upgrade. Production WAS Panama-only with Valhalla in a lab arm; they
5+
are now **one production membrane**, with JDK 28 as the enabling toolchain.
6+
Panama = the verb, Valhalla = the noun, **lance-graph / T0 owns storage**.
7+
8+
- **Toolchain:** `/opt/jdks/jdk-28+16` (Temurin `28+16-ea`). FFM final and
9+
flag-free; JEP 401 preview-gated, so `--release 28 --enable-preview` is part
10+
of the shipped build contract — **the flag is Valhalla's, never FFM's.**
11+
- **Production vocabulary:** the six types are `public value record`,
12+
`isValue() == true`. Gates: **183 native tests**, **409 Java checks**,
13+
identical to the unflipped baseline on the same JDK.
14+
- **Carry this forward:** the **8-byte flattening cliff reproduces on JDK 28**,
15+
and `RowRange` / `Row` (16 B) are on the wrong side of it. Two allocation
16+
measurements got WORSE under value semantics (non-escaping construction,
17+
`Row` hydration) — both honest, neither on a production path. The FFM path is
18+
byte-identical across the object model.
19+
- **Still owed:** `bench/` JMH numbers have NOT been re-taken on JDK 28
20+
(`bench/lib` absent here); `bench/RESULTS.md` is JDK 26 historical.
21+
- Full record: `PR_ARC_INVENTORY.md` PR #81.
22+
123
## 2026-09-16 — `hop_cached_vs_gather`: the M1b tile pays off on the second hop; the scatter walk is the access-shape question
224

325
**PR #79**, `native/lgj-abi/examples/hop_cached_vs_gather.rs` only — no ABI

.claude/board/PR_ARC_INVENTORY.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,87 @@
88
> anti-pattern the imported board rules name. Backfilled below in one
99
> pass rather than left stale; PR #4 onward gets its entry at merge time.
1010
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+
1192
## 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`)
1293

1394
> **Post-merge backfill, owned (2026-09-16):** this entry was NOT written at

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ Rust, SoA layout, SIMD, FFM, or graph-engine internals.
2828
|
2929
View / Mask / Lens DSL <- lazy, monotonic-narrowing
3030
|
31-
stable-JDK implementation
32-
|
33-
Valhalla laboratory <- the tiny vocabulary only
31+
JDK 28: Panama FFM + JEP 401 <- value-typed vocabulary,
32+
| production, not a lab arm
33+
representation probes <- object-model / layout
34+
measurements (historical
35+
directory: valhalla-lab/)
3436
3537
====================== PANAMA FFM ======================
3638

docs/panama.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,20 @@ remains the only thing Panama asks for. What changed is that production
8080
deliberately uses Valhalla value classes (JEP 401, preview on this build), so
8181
`--release 28 --enable-preview` is now part of the shipped build contract.
8282
Read every "no preview" claim below as scoped to FFM: **Panama needs no
83-
preview; the vocabulary types do.** The Valhalla lab
84-
(`valhalla-lab/src/valhalla`) is compiled *separately*, with its own
85-
`-source 27 --enable-preview`, into its own output directory
86-
(`results/valhalla-lab/`), and is never on the classpath the production
87-
tests or the bench harness run against. `--enable-preview`-compiled
88-
classfiles carry a preview marker that poisons every consumer that loads
89-
them; keeping the two trees physically separate (rather than, say,
90-
compiling once and gating features at runtime) is what makes this a
91-
structural guarantee rather than a discipline someone could accidentally
92-
violate. See `.claude/knowledge/jdk-toolchain-facts.md` for the exact
83+
preview; the vocabulary types do.****The paragraph that stood here is doubly stale and is replaced.** It said
84+
the lab compiles *separately* with `-source 27 --enable-preview` and is
85+
*"never on the classpath the production tests run against"*, and it argued
86+
that physical separation kept preview marking out of production. All three
87+
are now false: both probe arms run **JDK 28** with `-source 28 -target 28`,
88+
both **compile and load the production API**, and that API is itself
89+
preview-marked — so there is nothing to quarantine production *from*. The
90+
separation argument was load-bearing only while production was preview-free,
91+
and it stopped being that when production adopted JEP 401.
92+
93+
The isolation that remains is ordinary and smaller: the probe harness builds
94+
into its own output directory and is not on the classpath of the shipped
95+
artifact. It is not a structural guarantee against preview poisoning, because
96+
preview marking is now a property of production itself. See `.claude/knowledge/jdk-toolchain-facts.md` for the exact
9397
verified flag matrix across all three JDKs this project touches.
9498

9599
## What Panama did NOT need to solve here

docs/valhalla-lab.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
# The Valhalla lab — synthesis
1+
# Representation probes — synthesis
2+
3+
> **Legacy name.** The directory is still `valhalla-lab/` and this file is
4+
> still `valhalla-lab.md`, because renaming paths buys churn rather than
5+
> clarity. **The name no longer describes the experiment.** Valhalla is
6+
> production infrastructure — the six vocabulary types are `value record`s on
7+
> JDK 28 (PR #81) — so it is not what is being tested. What this harness
8+
> measures is the CONSEQUENCE of object-model and layout realizations:
9+
> `record` vs `value record` **on the same JDK, against the same
10+
> Valhalla-enabled production API**, with flattening and escape analysis
11+
> toggled. Read every "Valhalla arm" below as "value-record arm", and never as
12+
> evidence that production is fundamentally Panama with Valhalla bolted on.
213
314
> Companion to `valhalla-lab/README.md` and `valhalla-lab/docs/three-truths.md`
415
> (the raw findings and numbers) and `.claude/knowledge/valhalla-three-truths-method.md`

0 commit comments

Comments
 (0)