From 0ef275bcca08d44e07271cc702c87cdaf6197ca0 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 6 Sep 2026 23:57:55 +0000 Subject: [PATCH 1/5] =?UTF-8?q?plan:=20FMA=20bake=20v4=20=E2=80=94=20the?= =?UTF-8?q?=20address=20layer,=20not=20the=20mesh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FMA bake mints identity three different ways and two of them depend on iteration order, so a key minted by one producer does not resolve in another's output; the part_of relation upstream is a DAG while the cascade consumes a tree; and the composite/primitive table that carries laterality is not read at all. None of this is visible from a correct render or a green build, because every defect is in the key. This plan records the nine findings with the file:line or command behind each, seven caveats bounding what the evidence can support, five weighted decisions, and six probes that gate any of them landing. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012wrzeZAdwGYTCKoxamwQht --- .../plans/2026-09-06-fma-bake-v4-plan.md | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 claude-notes/plans/2026-09-06-fma-bake-v4-plan.md diff --git a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md new file mode 100644 index 000000000..ead6c672f --- /dev/null +++ b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md @@ -0,0 +1,222 @@ +# FMA bake v4 — findings, caveats, and weighted options + +> Status: PROPOSAL. Nothing here is scheduled. Every claim carries the command +> or file:line that produced it; unmeasured items are labelled CONJECTURE. +> Written against q2 @ HEAD (shallow clone — see C-7 on what that limits). + +## 0. Why a v4 at all + +The 20260629c bake is correct as rendered geometry and is serving. What this +plan addresses is the **address layer**: three producers mint three different +identities for the same concept, one of them from iteration order; the source +part_of relation is a DAG while the cascade consumes a tree; and an axis-edge +table that upstream ships (laterality) is not consumed at all. + +None of this is a rendering bug. All of it is an addressing bug, which is why +it has been invisible to a green build and a correct-looking body. + +--- + +## 1. Findings (measured) + +### F-1 — Identity is minted three ways, one of them order-dependent [BLOCKING] + +| producer | identity expression | content-stable? | +|---|---|---| +| `fma/src/bin/guid.rs:119` | `golden_id(k)`, then `+1` probe on collision (`:120-123`) | **NO** — `k` is enumeration index | +| `fma/src/bin/anchor.rs:111` | `fnv16(&path.join("/"))` | yes; **no** collision probe | +| `crates/osint-bake/src/bin/body.rs:129` | `row` (JSON node index) | **NO** — JSON order | + +`golden_id` (`guid.rs:44-47`) is `((20 + 4k)·φγ mod 1)·65536`. The γ+φ +low-discrepancy walk is the right generator; feeding it `k` instead of a +content hash is what breaks immutability. Re-order the input file and every +identity in the bake moves. + +Consequence: a `(classid, tiers, identity)` key minted by one producer does not +resolve in the other's output. Any cross-bake join (mesh ↔ anchor ↔ label) is +currently unsound and only appears to work because each consumer reads one bake. + +### F-2 — `row: u32` is written into a `u16` identity slot, unchecked [LATENT] + +`body.rs:129` passes `row` (u32) as `mint_for`'s identity argument. Under V3 the +slot is `identity_v2: u16`. At 1,658 concepts this never fires; at >65,536 it +wraps silently. Same shape as the OBO V3/V1 false-green (60,478 rows → 658 +apparent identities). No assertion guards it. + +### F-3 — part_of is a DAG upstream; the cascade consumes a tree [OPEN] + +Measured on `AdaWorldAPI/BodyParts3D` (version **3.0**), +`assets/BodyParts3D_data/conventional_part_of.txt`: + +- 2,358 edges over 1,523 nodes +- **536 nodes (35%) have more than one parent** +- single root `FMA20394` "human body" + +Measured earlier on the **4.0** mesh-derived subset the bake actually walks: +1,368 nodes / 1,367 edges / **0** multi-parent / max depth 16. + +CONJECTURE (needs measurement, see P-1): the 4.0 `partof_BP3D_4.0_obj_99` +source is also a DAG and the bake's cascade builder is collapsing it to a +spanning tree by first-parent-wins. If so, 35% of concepts are being addressed +under one arbitrary parent. This is NOT yet proven — the two numbers come from +different dataset versions and are not directly comparable. + +### F-4 — Laterality ships as an edge table and is not consumed [OPEN] + +`composite_parts.txt`: 12,530 composite→primitive edges. **8,265 (66%)** have a +primitive whose name is the composite's name plus an axis word: + + right 3871 left 3849 proximal 311 distal 310 lateral 287 posterior 256 + anterior 250 superior 248 lower 239 upper 236 medial 196 inferior 192 + dorsal 34 + +The bake reads neither this file nor any axis concept: zero hits for +`dorsal|ventral|anterior|posterior|superior|inferior|lateral|medial` across +`bake_body_v3.py`, `bake_body_soa.py`, `body.rs`. Laterality survives only +inside label strings, where it is unaddressable. + +### F-5 — `is_a` is populated and unused for addressing [OPEN] + +2,905 nodes, root "anatomical entity", max depth 20, max children 32. The V3 +key rails are `part_of : is_a` (le-contract L1), i.e. the layout has a byte +lane for is_a per tier — but `body.rs:107-118` fills all six tiers from the +`is_a` ancestor **sibling-rank** chain and nothing from part_of. The rails are +carrying one relation in both axes. + +### F-6 — Depth exceeds the addressable tiers [OPEN] + +part_of max depth 16; the key offers classid + 5 tier slots + identity. 279 +FMA nodes (20%) sit deeper than the 7 addressable levels (118 counted below the +classid). Current behaviour: `tier_at(k)` returns 0 past the cascade length +(`body.rs:110-117`), so deep nodes share a prefix with their ancestor. + +### F-7 — Upstream deliberately rejected the version we bake from [CONTEXT] + +`AdaWorldAPI/BodyParts3D` README: *"The latest version 4.0, although more +complete, was not chosen as it appears to have intersecting skin/muscle areas."* +Our bakes read 4.0 (`bake_body_v3.py:139-140`). The 20260629b/c re-bakes were +both spent on classification overlap (connective structures floating in ORGAN +and SKIN, teeth outside skeleton). Not proof of a common cause; enough to check. + +### F-8 — Two group-membership mechanisms already exist [DESIGN] + +- `lance-graph/.claude/v3/soa_layout/le-contract.md:57` — **L2 facet + `6 × (8:8)` `memberof : members`**, a sanctioned carving. +- `q2/crates/cockpit-server/src/osint_gotham.rs:12-16` — the EdgeBlock + **16 × 8-bit adapter mask**, "a node implements the basins it points at". + +Both address many-to-many. A v4 that needs group semantics must pick one, not +add a third. The materialized hub node is already ruled out +(`osint_gotham.rs:1081-1087`): *"A materialized hub cannot dock as an edge."* + +### F-9 — Prior art solved F-3/F-4 with relation types, not extra nodes [CONTEXT] + +Pommert et al., *Medical Image Analysis* 5(3) 2001 (VOXEL-MAN/InnerOrgans, 650 +constituents / >2000 relations over the Visible Human): + +- *"Views are represented as attributes of relations."* The kidneys appear under + abdominal viscera / urogenital system / primary retroperitoneal organs + depending on view — F-3's multi-parent, made explicit rather than collapsed. +- A separate `branching from` relation type *"modeling the arterial blood flow"* — + arterial convergence is not part_of and was never forced into it. +- `hidden part of`, so a constituent assembled from several segmented objects + presents as one entity — the job `composite_parts.txt` does upstream. + +--- + +## 2. Caveats on the evidence + +- **C-1** The q2 clone is `--depth 1`. Every file carries the same mtime; git + dates are useless for "which producer is youngest". Recency was established + from **release asset timestamps** instead (20260628 → 29 → 29b → 29c). +- **C-2** F-3's two node counts come from **different dataset versions** (3.0 + table vs 4.0 mesh subset). They are not a before/after. +- **C-3** No producer was re-run in this session. Every number is read from + committed source, committed data, or release metadata. +- **C-4** F-9 is a reading of a paper against our tables. No code linkage + between VOXEL-MAN and this stack was measured, and none is claimed. +- **C-5** The `20260629c` note in `cockpit/public/body.manifest.json` documents a + layer reclassification (39 connective structures) — that is a real fix and is + not among the open items here. +- **C-6** `body.soa.gz` is fetched, not committed; a v4 changes a release asset, + so the manifest + Dockerfile pull are part of the blast radius. +- **C-7** Absence of a symbol at HEAD is not absence in history (the shallow + clone). A bounded `git fetch --depth=1000` is required before any claim of + the form "X was never tried". + +--- + +## 3. Options, weighted + +### D-1 — Identity mint (addresses F-1, F-2) + +| # | Option | Cost | Risk | Verdict | +|---|---|---|---|---| +| a | **One shared minter, content-addressed**: `identity = f(stable concept key)`, the FMA id being the obvious stable key. All three producers call it. | medium — touches 3 binaries | low | **RECOMMENDED** | +| b | Keep `golden_id` but feed it a content hash instead of `k` | low | medium — collision probe still order-dependent, so collisions resolve differently per run | fallback | +| c | Status quo + document the divergence | zero | high — the unsound join stays | reject | + +FMA ids max at 270,201 = 19 bits. That does **not** fit `identity_v2: u16`, so +(a) forces a decision: hash to 16 bits and accept collisions with a +deterministic, content-ordered probe, or carry the exact id in a value tenant +(see D-4) and let the key hold a hash. The quad `4 × u24` (`identity_quad.rs`, +`LegacyOutlier::WideTriple`) exists precisely for exact identifier ordinals +where *"invertibility (not similarity) is the acceptance criterion"* — 19 bits +fits a u24 slot exactly. + +### D-2 — Multi-parent / views (addresses F-3, F-5) + +| # | Option | Cost | Risk | Verdict | +|---|---|---|---|---| +| a | **Fill the rails as designed**: `part_of` in one byte axis, `is_a` in the other, per L1 | medium | low — uses the carving that already exists | **RECOMMENDED** | +| b | Pommert-style views: a node addressed once per view, view selected by ClassView | high | medium — needs a view carrier that does not exist | worth a probe, not a v4 | +| c | First-parent-wins (status quo) + record which parent won | low | medium — silently arbitrary | interim only | + +(a) is the cheap win and is what the rails were carved for. It does not solve +multi-parent; it stops wasting half the rail on a duplicate relation. + +### D-3 — Laterality (addresses F-4) + +| # | Option | Cost | Risk | Verdict | +|---|---|---|---|---| +| a | **Consume `composite_parts.txt` as an edge relation** composite→primitive; the axis stays an edge, never a key tier | medium | low — matches how upstream ships it, and Pommert's `hidden part of` | **RECOMMENDED** | +| b | Encode the axis as a byte in a rail | low | **high** — an axis is not a mereology tier; poisons prefix routing | reject | +| c | Leave in the label | zero | high — 66% of the relation unaddressable | status quo | + +### D-4 — Depth overflow (addresses F-6) + +| # | Option | Cost | Risk | Verdict | +|---|---|---|---|---| +| a | Accept the cap, record the truncated remainder in a value tenant | low | low | **RECOMMENDED** | +| b | Registry resolve + ref-escape past 12 native levels (the OGAR canon answer) | high | low | correct long-term | +| c | Widen the key | — | — | **forbidden** (canon: scale is the next cascade level, never field-widening) | + +### D-5 — Source version (addresses F-7) + +Measure before deciding. Options: stay on 4.0; move to 3.0 (loses concepts, +gains the overlap fix upstream made); or bake 4.0 and diff the skin/muscle +intersection against 3.0 as a falsifier. + +--- + +## 4. Probes — run before any of D-1..D-5 lands + +- **P-1** Parse `partof_BP3D_4.0_obj_99`; count nodes, edges, multi-parent, max + depth. Settles F-3 and C-2. Blocks D-2. +- **P-2** Run `guid.rs` and `anchor.rs` over the same input; count concepts whose + identity differs. Expected: ~all. Quantifies F-1. +- **P-3** Re-run `guid.rs` with the input shuffled; count identity changes. + Expected: ~all. This is the immutability falsifier. +- **P-4** Join `composite_parts.txt` against the meshed concept set: how many + composites and primitives are actually in the bake? Sizes D-3. +- **P-5** Diff 4.0 vs 3.0 skin/muscle geometry for intersection. Settles F-7/D-5. +- **P-6** `git fetch --depth=1000` and grep history for `tribonacci` / + earlier vessel-radius sequences. Settles C-7. + +A v4 that lands without P-1, P-2 and P-3 green is a rebake with the same +addressing defects and a new date in its filename. + +## 5. Explicitly out of scope + +Geometry, palettes, LOD, the 20260629c connective-layer fix, the renderer, and +the surfel/torso line. This plan is about the key, not the mesh. From bb3c9be89417d3b4fe7179a044fb95df00f1ecd2 Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 7 Sep 2026 00:04:07 +0000 Subject: [PATCH 2/5] plan: record the v4 operator sketch as research, not decisions The sketch names nine directions and most of them are already carved in the lance-graph V3 layout contract, so a research pass that starts from scratch would re-derive the second-relationship GUID, the analytic Fisher-z read, the Signed360 helix tenant, and three separate many-to-many mechanisms. Section 6 records where each already lives with its file:line, separates the three that are genuinely new, and marks the whole section TO BE RESEARCHED so nothing in it reads as a verdict. Also corrects an earlier claim in this session that the 24-slot i4 lane was unsanctioned: it exists as tenant 14 CausalWitness, read G24N4, experimental by its own doc-comment. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012wrzeZAdwGYTCKoxamwQht --- .../plans/2026-09-06-fma-bake-v4-plan.md | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md index ead6c672f..1260f4001 100644 --- a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md +++ b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md @@ -220,3 +220,100 @@ addressing defects and a new date in its filename. Geometry, palettes, LOD, the 20260629c connective-layer fix, the renderer, and the surfel/torso line. This plan is about the key, not the mesh. + +--- + +## 6. Operator sketch — v4 direction (added 2026-09-07) + +> **STATUS: TO BE RESEARCHED.** Nothing in this section is decided, scheduled, +> or recommended. It records an operator sketch and what the contract already +> says about each item, so the research starts from the carved state instead of +> re-deriving it. Verdicts belong to a later pass; the §3 weighted decisions and +> §4 probes are unchanged by anything here. + +Nine directions, checked against `AdaWorldAPI/lance-graph`'s +`.claude/v3/soa_layout/` contract. Most are already carved; three are new. The +split matters because a carved item needs *wiring*, and a new one needs a +*ruling* first. + +### 6.1 Already carved — wire, don't invent + +| direction | where it already lives | +|---|---| +| **2 × 12 (second GUID for relationships)** | `le-contract.md:130-137` — *"**Second GUID (relationships):** when a node carries a second GUID dedicated to relationships, its rail plane is ENCOURAGED to carry six relations as `basin : relationtype` pairs"*; and *"if the basins are **12 static**, the pair upgrades to `relationtype : relationtype_orthogonal`"* | +| **6 × palette256² for Fisher-z** | `le-contract.md:171-186` — L4 reads through the **analytic Fisher-z codec** (`bgz-tensor::fisher_z::{FamilyGamma, FisherZTable}`), certified ρ≥0.999, `E-FISHERZ-CANONICAL-COSINE-REPLACEMENT-1`. *"A materialized k×k table is a CACHE of the formula, never the canon."* Boundary: replaces the distance/rank READ; the semiring COMPOSE keeps its table | +| **helix Signed360** | tenant 4 `HelixResidue`, 6 B `[112,118)` — *"48-bit helix place (2× 24-bit equal-area hemisphere, Signed360)"*. Sibling of the above: *"helix is to Fisher-2z what the cosine-replacement is to Fisher-z"* | +| **many-to-many nodes** | **three** existing mechanisms — tenant 15 `EpisodicBasin` (§6.2), L2 facet `memberof : members`, and q2's own EdgeBlock 16×8-bit adapter mask (`osint_gotham.rs:12-16`) | +| **24 × i4 Markov context** | tenant 14 `CausalWitness`, `U8 × 16` `[204,220)`, read **G24N4** — *"24 signed i4 loci… each nibble is a context pointer (signed ±8 window offset), not a strength"*. Slots 16..24 reserved-zero. **EXPERIMENTAL**, and by its own doc-comment *"not in the operator-locked §3 catalogue"*; it is a **lane shape name, never a `CascadeShape` variant** | + +### 6.2 The many-to-many node already encodes the no-hub ruling + +Tenant 15 `EpisodicBasin` — *"a promoted basin as **REFERENCES**: `subject` u16 · +`member_count` u16 · `self_code` 12 B (Cam96 centroid) · `version_from`/`version_to` +u64. **Members are reached by following `(subject, [from,to))` into the triple +stream, never inlined** — the fat-concept guard §3a names. Width is NOT stored +(recomputable through the references)."* + +A group that carries a member *count* and a version range but not a member +*list*. That is the same ruling q2 reached independently at +`osint_gotham.rs:1081-1087` (*"A materialized hub cannot dock as an edge"*), +arrived at from the other side. **A v4 needing group semantics picks one of the +three; it does not add a fourth.** + +### 6.3 Genuinely new — TO BE RESEARCHED + +- **Zipper over 2 × 12 = 24 bytes.** Arithmetic first: 24 bytes read as `(8:8)` + rails is **12 rails**, not 24. With classid that is 13 addressable levels + against part_of's measured max depth of **16** (F-6). It closes most of the + 279 over-deep nodes but not all, so it *pairs with* D-4b (registry resolve + + ref-escape), it does not replace it. Open: whether the second 12 B comes from + the EdgeBlock or from a second GUID per §6.1 — these are different rows. +- **Hexagon substrate with trie addressing.** CONFLICT, at the arithmetic + level: HHTL is `FAN_OUT = 16`, one nibble per level, tier-of-level = + `level >> 2` — *"a shift, never a branch"* (OGAR canon). A hex lattice has 6 + neighbours (7 with centre); neither divides a nibble. Adopting it trades away + the shift/mask uniformity the 3×4-vs-4×3 ruling was decided on. Needs the + standing-watch flip condition (a measured workload where it wins) before it + is more than an idea. TO BE RESEARCHED, not proposed. +- **Volumetric fill as an EXPLICIT trie + spatial edges.** The stronger half of + the same thought, and it does *not* carry the hex conflict. + `fill_body_soa.py` already does 3D connected-component analysis (`:82-83`) + and ring-sweeps a core (`:115-146`); today it emits triangles. Emitting an + addressed trie with spatial edges instead is a real substrate change and is + what Gagvani & Silver's volumetric skeleton (*"an advanced data structure for + referencing all of the voxels"*) was reaching for. Prerequisite: decide + whether the trie is the address or a second index beside it. +- **BPE for behaviour.** No prior art found anywhere in the workspace. Needs a + statement of what the token vocabulary is over before it can be weighed. + +### 6.4 Adjacent, and deliberately still out of scope + +- **Better vessels** — geometry, excluded by §5. The shipped fix is empirical + clamps (`caliber × CAP`, `PCTL = 0.30`), not a growth sequence; a v4 that + also re-opens vessel caliber should say so explicitly and take §5 with it. +- **"Street" nodes repurposed** — the OSM `.chains` sidecar is the one carrier + in the stack that holds an **ordered, variable-length path** + (`osm_features.rs:829`, *"vertex chains for tagged ways"*). If vessel + centerlines want to be first-class paths rather than swept triangles, that is + the shape to reuse. Note its sparse-ordinal cost is already documented: + chains need an ascending ordinal index (~17.6 MB at ~4.4 M entries) because + row position ≠ ordinal, where dense books need none + (`osm_chains_books_lance.rs:19-41`). +- **Masking algebra** — measured (ternlog `T3/T1 → 0.50` by K=8, flat in K, + contingent on L2 residency: 138 → 15 GB/s past L2). Not wired to any FMA + read path today; it is a consumer of whichever addressing v4 settles on, not + an input to it. + +### 6.5 One doc-drift found while checking the above [DOC-ONLY] + +`.claude/v3/soa_layout/tenants.md:88` describes the `Full = 3` preset as +*"all 15 tenants 0–14 (Meta … `CausalWitness`)"*. The tenant table in the same +file runs **0–15**, ending at `EpisodicBasin`. + +The **code is correct** — `canonical_node.rs:942` has `EpisodicBasin = 15`, and +`:1252` compile-asserts +`ValueSchema::Full.field_mask().count() == VALUE_TENANTS.len()`, which would not +build if the preset and the table disagreed. So this is stale prose in +`tenants.md`, not a defect: 16 tenants, 0–15. Belongs upstream in lance-graph, +not in this repo; noted here only so a v4 session reading that line does not +size a preset from it. From 35393fb76f934d120a445ac254416735e34778af Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 7 Sep 2026 00:07:28 +0000 Subject: [PATCH 3/5] plan: map every flaw to what closes it, and record the prior art MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The plan listed findings and weighted options in separate sections, so nothing said which option closes which flaw or what it leaves standing — and two gaps were invisible that way: the u32-to-u16 mint guard is closed by no option on its own, and the three coexisting group-membership mechanisms have no owning decision at all. Section 7 is the defect-to-remedy matrix with residuals and the probe ordering; section 8 and a new reference doc under .claude/docs record the BodyParts3D, VOXEL-MAN and volumetric-skeleton sources, what each establishes, which finding it bears on, and the required data attribution. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012wrzeZAdwGYTCKoxamwQht --- .claude/docs/anatomy-substrate-prior-art.md | 157 ++++++++++++++++++ .../plans/2026-09-06-fma-bake-v4-plan.md | 68 ++++++++ 2 files changed, 225 insertions(+) create mode 100644 .claude/docs/anatomy-substrate-prior-art.md diff --git a/.claude/docs/anatomy-substrate-prior-art.md b/.claude/docs/anatomy-substrate-prior-art.md new file mode 100644 index 000000000..002c24774 --- /dev/null +++ b/.claude/docs/anatomy-substrate-prior-art.md @@ -0,0 +1,157 @@ +# Anatomy substrate — prior art and sources + +> Reference companion to `claude-notes/plans/2026-09-06-fma-bake-v4-plan.md`. +> Descriptive: what each source is, what it establishes, and which finding in +> that plan it bears on. No verdicts here — the plan owns those. + +## Attribution (required, and already carried in-tree) + +The body geometry is **BodyParts3D**, and its licence requires attribution +wherever the data is used. The bake tools already carry it +(`crates/osint-bake/tools/bake_torso_mesh.py:22`, +`bake_body_v3.py:25`); restated here so a reader of this doc does not have to +go find it: + +> BodyParts3D, © The Database Center for Life Science, licensed under +> CC Attribution-Share Alike 2.1 Japan. + +Data archive DOI: `10.18908/lsdba.nbdc00837-000`. + +--- + +## 1. BodyParts3D — the geometry and the two relation tables + +**Mitsuhashi N, Fujieda K, Tamura T, Kawamoto S, Takagi T, Okubo K.** +*BodyParts3D: 3D structure database for anatomical concepts.* +Nucleic Acids Research 2009 Jan;37(Database issue):D782-5. +doi:[10.1093/nar/gkn613](https://doi.org/10.1093/nar/gkn613) · +PMC[2686534](https://pmc.ncbi.nlm.nih.gov/articles/PMC2686534/) + +Project page: http://lifesciencedb.jp/bp3d/ + +Mirror used in this session: `AdaWorldAPI/BodyParts3D` (STL conversion of the +**3.0 / 20110915** release + a Julia interface). Our bakes read **4.0** +(`bake_body_v3.py:139-140` → `isa_BP3D_4.0_obj_99`, `partof_BP3D_4.0_obj_99`). + +The tables under `assets/BodyParts3D_data/`, measured: + +| file | lines | schema | bears on | +|---|---|---|---| +| `conventional_part_of.txt` | 2,359 | `id ⇥ name ⇥ part id ⇥ part name` | **F-3** — 2,358 edges / 1,523 nodes / **536 multi-parent** / single root `FMA20394` "human body" | +| `FMA.csv` | 104,724 | `FMAID, Preferred Label, Parent FMAID` | **F-5** — the is_a table; max FMAID 270,201 = 19 bits, which is why **F-1**'s 16-bit identity slot is a forced choice | +| `composite_parts.txt` | 12,531 | `composite id ⇥ composite name ⇥ primitive id ⇥ primitive name` | **F-4** — 8,265 of 12,530 edges add an axis word to the composite name | +| `parts_list_e.txt` | 1,524 | FMAID → English name | label slab | + +Axis-word census over `composite_parts.txt` (the laterality that is *not* +consumed by any bake): + + right 3871 left 3849 proximal 311 distal 310 lateral 287 posterior 256 + anterior 250 superior 248 lower 239 upper 236 medial 196 inferior 192 + dorsal 34 + +The mirror's README also records, in upstream's own words, why it ships 3.0: +*"The latest version 4.0, although more complete, was not chosen as it appears +to have intersecting skin/muscle areas."* Bears on **F-7**; the plan treats a +shared cause with our 20260629b/c re-bakes as CONJECTURE pending **P-5**. + +--- + +## 2. VOXEL-MAN / InnerOrgans — the spatial/symbolic split + +**Pommert A, Höhne KH, Pflesser B, Richter E, Riemer M, Schiemann T, +Schubert R, Schumacher U, Tiede U.** *Creating a high-resolution +spatial/symbolic model of the inner organs based on the Visible Human.* +Medical Image Analysis 5(3), 2001. +PDF: https://www.virtual-body.org/media/pommert-medical-image-analysis-2001.pdf +Gallery: https://www.virtual-body.org/gallery/visible-human/torso-and-internal-organs/ +Institute of Mathematics and Computer Science in Medicine (IMDM), +University Hospital Hamburg-Eppendorf. + +Scale: >1000 cryosections + congruent fresh/frozen CT of the male Visible +Human; a 573×330×1049 mm³ volume; **650 anatomical constituents, >2000 +relations**. (For calibration: BodyParts3D's part_of table is 1,523 nodes / +2,358 edges — same order, independent lineage.) + +Three things it establishes, each with a direct counterpart in the plan: + +**(a) Views as attributes of relations — bears on F-3, D-2b.** Verbatim: + +> the kidneys can be seen according to structural or functional criteria: +> • regional anatomy — the kidneys are shown as part of the **abdominal viscera** +> • systemic anatomy — part of the **urogenital system** +> • relation to peritoneum — part of the **primary retroperitoneal organs** +> +> *"Views are represented as attributes of relations."* + +One object under three part_of parents, the view selecting the reading. This +is the multi-parent case the cascade currently collapses, solved in 2001 by +naming the view rather than picking a winner. It is also, in one sentence, what +`ClassView` does — arrived at independently. + +**(b) A separate `branching from` relation type — bears on F-3, and on the +arterial-convergence episode.** Verbatim: *"our model also contains a +'branching from' type, **modeling the arterial blood flow**."* Arterial +branching was not forced into the part hierarchy; it got its own relation. + +**(c) `hidden part of` — bears on F-4.** Where a constituent is several +segmented objects with individual labels, this relation hides the technical +ones so it *"appears as one single entity."* Structurally the job +`composite_parts.txt` does upstream. + +Also relevant to the vessel work (§6.4) — their segmentation is codebook + +connected-component, the same two operations in the same order as +`fill_body_soa.py`: + +> *"this cluster is approximated by a **parameterized ellipsoid**, which is +> described by its center and three axis vectors."* +> *"there are other regions present in the volume which also match this +> colour-space description. If they are not connected to the target organ, it +> can be **isolated easily by a 3D connected component analysis**."* + +And the scope line our bake inherits without stating: *"we decided to **model +non-segmentable objects like nerves and small blood vessels artificially** on +the basis of landmarks… their size and contrast is too small."* + +Sources cited inside Pommert that matter for the symbolic half: Höhne et al. +1995 (the semantic-network knowledge base); Rosse et al. 1998 (Digital +Anatomist symbolic knowledge base); Schiemann et al. 1997 (colour-space +classification); Federative Committee on Anatomical Terminology 1998 +(standardised nomenclature). + +--- + +## 3. Gagvani & Silver — the volumetric skeleton + +**Gagvani N, Silver D.** *Animating the Visible Human Dataset.* +Dept. of Electrical and Computer Engineering & CAIP Center, Rutgers. + +A skeleton computed **directly from the Visible Human voxels**, imported into a +commercial animation package for skeletal animation. Their own framing of what +the artifact is: + +> *"an advanced data structure for referencing all of the voxels in a +> volumetric model."* + +Bears on **§6.3's explicit volumetric trie**: an address spine over a volume, +extracted rather than authored — the same role HHTL plays for us, from voxels +instead of a mesh hierarchy. + +Pommert (§2) cites this work and states its limit, which is the argument for +having an address at all: per-voxel transparency *"fails to display internal +structures properly. In addition, **organ borders are not explicitly +indicated**, thus making the removal or exclusive display of an organ +impossible."* A skeleton that references every voxel still cannot answer +"show me only the liver." + +--- + +## 4. Visible Human Project + +https://www.nlm.nih.gov/research/visible/visible_human.html — NLM. The +cryosection + CT/MRI source underlying §2 and §3. + +**Lineage caution.** VOXEL-MAN and Gagvani are both **voxel** models over the +Visible Human. BodyParts3D is **surface mesh**, from DBCLS/Anatomography, +independent. Our bake is on the mesh line. The convergence recorded in §2 is in +the **addressing**, not the geometry; no code path linking the lineages has +been measured, and none is claimed. diff --git a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md index 1260f4001..f62b62e3a 100644 --- a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md +++ b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md @@ -317,3 +317,71 @@ build if the preset and the table disagreed. So this is stale prose in `tenants.md`, not a defect: 16 tenants, 0–15. Belongs upstream in lance-graph, not in this repo; noted here only so a v4 session reading that line does not size a preset from it. + +--- + +## 7. Defect → remedy matrix (added 2026-09-07) + +What is wrong today, what closes it, and what each remedy leaves standing. +Read with §2: several rows are gated on a probe that has not run, and one row +has no owning decision at all. + +### 7.1 The matrix + +| flaw | observable symptom today | closed by | partially addressed by | residual after the fix | +|---|---|---|---|---| +| **F-1** identity minted three ways, two order-dependent | a key from one producer does not resolve in another's output; re-ordering the input moves every identity | **D-1a** (one shared content-addressed minter) | D-1b (content hash into `golden_id`) — its `+1` collision probe still resolves in enumeration order, so collisions differ per run | FMA ids are 19 bits and `identity_v2` is 16: D-1a forces the sub-choice of hash-with-probe vs the `4 × u24` quad. Unresolved until that is picked | +| **F-2** `row: u32` → `identity: u16`, unchecked | silent wrap past 65,536 concepts; today never fires at 1,658 | **nothing on its own** | D-1a removes `row` as the identity source | **D-1a does not add a guard.** F-2 needs an explicit `TryFrom`/`debug_assert` at the mint regardless of which D-1 option wins. Do not treat it as closed by D-1 | +| **F-3** part_of is a DAG upstream; cascade consumes a tree | ~35% of concepts (3.0 table) addressed under one arbitrary parent — CONJECTURE for 4.0 | **D-2b** (views as attributes of relations) | D-2c (record which parent won) makes the arbitrariness auditable, not correct | D-2b needs a **view carrier that does not exist**. Blocked on **P-1**; until P-1 runs, the size of this flaw in 4.0 is unknown | +| **F-4** laterality edge table unconsumed | 8,265 of 12,530 composite→primitive edges carry an axis word; the axis is reachable only by string-matching a label | **D-3a** (consume `composite_parts.txt` as an edge relation) | — | Sized by **P-4** — unknown how many composites/primitives are in the meshed set. D-3b (axis into a key tier) is *rejected*, not deferred | +| **F-5** `is_a` fills both rail axes | the L1 `part_of : is_a` carving carries one relation twice; part_of contributes nothing to the address | **D-2a** (fill the rails as designed) | — | Closes the waste, **not F-3**. A node with three parents still gets one | +| **F-6** part_of depth 16 > 7 addressable levels | 279 nodes (20%) share a prefix with an ancestor via the `tier_at → 0` fallback | **D-4b** (registry resolve + ref-escape) | D-4a (record the truncated remainder in a tenant) makes it lossless-on-read, not addressable; §6.3's 2×12 zipper reaches 13 levels of 16 | D-4c (widen the key) is **forbidden by canon** — scale is the next cascade level, never field-widening | +| **F-7** we bake 4.0; upstream rejected 4.0 for intersecting skin/muscle | two re-bakes (20260629b, c) spent on classification overlap | **no option yet** — D-5 is deliberately undecided | — | Gated on **P-5**. Until measured, a common cause is CONJECTURE only | +| **F-8** three group-membership mechanisms coexist | `EpisodicBasin` (tenant 15), L2 `memberof : members`, and q2's EdgeBlock adapter mask all address many-to-many | **no owning decision — this is a gap in §3** | §6.2 states the constraint ("pick one, do not add a fourth") but assigns no verdict | Needs a **D-6** before any group work lands, or the v4 adds a fourth by accident | +| **§6.5** `tenants.md:88` says 15 tenants; the table runs 0–15 | a session sizing a preset from the prose is off by one | a one-line doc fix **in lance-graph** | — | **Not fixable from this repo.** Code is correct (`canonical_node.rs:1252` compile-asserts the pairing); prose only | + +### 7.2 What no remedy in this plan touches + +- **Multi-parent addressing is not solved by anything currently on the table.** + D-2a stops the rails wasting an axis; D-2b is the real answer and needs a + carrier that does not exist. If P-1 shows the 4.0 part_of is a DAG, this + becomes the largest open item in the plan, larger than F-1. +- **Vessel caliber** (§6.4) is excluded by §5 and no D-item covers it. +- **The hex substrate / explicit volumetric trie** (§6.3) are research, not + remedies; neither closes a flaw listed above. + +### 7.3 Ordering constraint + +F-1 is BLOCKING and independent — D-1a can land before any probe. Everything +else has a gate: + + P-1 ──gates──▶ D-2 (F-3, F-5) + P-4 ──sizes──▶ D-3 (F-4) + P-5 ──gates──▶ D-5 (F-7) + P-2, P-3 ─────▶ quantify and falsify F-1 (evidence, not a gate on D-1a) + +D-1a plus the F-2 guard is therefore the only work in this plan that could +begin today. Everything else waits on a measurement, and the plan's §4 rule +stands: a v4 that lands without P-1, P-2 and P-3 green is a rebake with the +same addressing defects and a new date in its filename. + +--- + +## 8. Sources + +Full reference doc — what each source is, what it establishes, and the required +BodyParts3D attribution — lives at +**`.claude/docs/anatomy-substrate-prior-art.md`**. Short form: + +| source | establishes | bears on | +|---|---|---| +| Mitsuhashi et al., *Nucleic Acids Res* 2009 (PMC2686534, doi:10.1093/nar/gkn613) — **BodyParts3D** | the geometry + the `part_of` / `is_a` / `composite_parts` tables our bakes read | F-3, F-4, F-5, F-7 | +| Pommert et al., *Medical Image Analysis* 5(3), 2001 — **VOXEL-MAN / InnerOrgans** | *"views are represented as attributes of relations"*; a separate `branching from` type for arterial flow; `hidden part of`; ellipsoid + connected-component segmentation | F-3 (→ D-2b), F-4 (→ D-3a), §6.4 vessels | +| Gagvani & Silver (Rutgers) — **Animating the Visible Human** | a volumetric skeleton as *"an advanced data structure for referencing all of the voxels"* | §6.3 explicit volumetric trie | +| NLM **Visible Human Project** | the cryosection/CT source under both of the above | lineage context only | + +**Lineage caution, restated because it is easy to lose:** VOXEL-MAN and Gagvani +are voxel models over the Visible Human; BodyParts3D is surface mesh from +DBCLS/Anatomography, independent. Our bake is on the mesh line. The convergence +recorded above is in the **addressing**, not the geometry — no code path linking +the lineages was measured, and none is claimed (C-4). From 71b360e388a900ba54e0c95f611c19811b2b2787 Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 7 Sep 2026 00:10:21 +0000 Subject: [PATCH 4/5] ci: drop the redundant borrow the clippy gate rejects in pampa's example-list test The newly-ungated `cargo clippy --workspace --all-targets -- -D warnings` rejects `&pandoc.blocks[0]` as a `useless_borrows_in_formatting` argument, so `pampa` fails to compile its integration test and the run exits 101. The failure is on the base branch, not in this branch's diff, which touches only markdown; the same one-line change is already in the open clippy-gate PR and this port no-ops once that lands. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012wrzeZAdwGYTCKoxamwQht --- crates/pampa/tests/integration/test_treesitter_coverage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pampa/tests/integration/test_treesitter_coverage.rs b/crates/pampa/tests/integration/test_treesitter_coverage.rs index 20f7eee50..c68db0d7e 100644 --- a/crates/pampa/tests/integration/test_treesitter_coverage.rs +++ b/crates/pampa/tests/integration/test_treesitter_coverage.rs @@ -466,7 +466,7 @@ fn test_example_list() { assert!( matches!(&pandoc.blocks[0], Block::OrderedList(_)), "Expected OrderedList, got {:?}", - &pandoc.blocks[0] + pandoc.blocks[0] ); if let Block::OrderedList(list) = &pandoc.blocks[0] { From a5a8d4df91e341ed442670f535658f506f63a70d Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 7 Sep 2026 00:12:42 +0000 Subject: [PATCH 5/5] plan: pin the level-counting convention and stop D-2a reading as a multi-parent fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two sections counted address depth differently — one treated identity as a level and reached seven, the other counted classid plus rails and reached thirteen — so the 279-node overflow figure was measured against a reading the plan contradicts elsewhere; the convention is now pinned once, the count is withdrawn until P-1 reports a depth histogram, and D-2's heading and verdict no longer let "fill the rails as designed" read as closing multi-parent when the prose beneath it says the opposite. The G24N4 entry cited the tenant's 16-byte lane width where the carving applies to the 12-byte payload; corrected against causal_witness.rs, where 12 bytes is 24 nibbles with 16 named and slots 16..24 reserved-empty. Also corrects the new-direction count from three to four. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012wrzeZAdwGYTCKoxamwQht --- .../plans/2026-09-06-fma-bake-v4-plan.md | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md index f62b62e3a..7e12c486f 100644 --- a/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md +++ b/claude-notes/plans/2026-09-06-fma-bake-v4-plan.md @@ -85,10 +85,23 @@ carrying one relation in both axes. ### F-6 — Depth exceeds the addressable tiers [OPEN] -part_of max depth 16; the key offers classid + 5 tier slots + identity. 279 -FMA nodes (20%) sit deeper than the 7 addressable levels (118 counted below the -classid). Current behaviour: `tier_at(k)` returns 0 past the cascade length -(`body.rs:110-117`), so deep nodes share a prefix with their ancestor. +**Level-counting convention, pinned here and used everywhere in this plan:** +a *level* is the classid (the root) plus one per **rail**; `identity` is the +instance slot and is NOT a level. Under that convention the V3 key gives +**6 levels** — classid + the 5 cascade rails `body.rs:121-129` fills +(HEEL/HIP/TWIG/LEAF/family), with the 6th rail spent on `identity`. This is +the same convention §6.3 uses to reach *classid + 12 rails = 13 levels*. + +part_of max depth is **16**, so the key is short by 10 levels. Current +behaviour: `tier_at(k)` returns 0 past the cascade length (`body.rs:110-117`), +so deep nodes share a prefix with their ancestor. + +⚠ **The overflow counts need re-deriving.** The earlier measurement — 279 FMA +nodes (20%) over the cap, 118 counted below the classid — was taken against a +7-level reading that counted `identity` as a level, which the convention above +rejects. The shape of the finding is unchanged (the tree is deeper than the key) +but the magnitude is not yet trustworthy at the pinned convention. **P-1 must +report the depth histogram, not just the max**, and D-4 is sized from that. ### F-7 — Upstream deliberately rejected the version we bake from [CONTEXT] @@ -164,16 +177,21 @@ deterministic, content-ordered probe, or carry the exact id in a value tenant where *"invertibility (not similarity) is the acceptance criterion"* — 19 bits fits a u24 slot exactly. -### D-2 — Multi-parent / views (addresses F-3, F-5) +### D-2 — Rail contents and multi-parent (F-5 is closable here; F-3 is not) | # | Option | Cost | Risk | Verdict | |---|---|---|---|---| -| a | **Fill the rails as designed**: `part_of` in one byte axis, `is_a` in the other, per L1 | medium | low — uses the carving that already exists | **RECOMMENDED** | +| a | **Fill the rails as designed**: `part_of` in one byte axis, `is_a` in the other, per L1 | medium | low — uses the carving that already exists | **RECOMMENDED — for F-5 only** | | b | Pommert-style views: a node addressed once per view, view selected by ClassView | high | medium — needs a view carrier that does not exist | worth a probe, not a v4 | | c | First-parent-wins (status quo) + record which parent won | low | medium — silently arbitrary | interim only | -(a) is the cheap win and is what the rails were carved for. It does not solve -multi-parent; it stops wasting half the rail on a duplicate relation. +(a) is the cheap win and is what the rails were carved for, but it closes +**F-5 and nothing else**: one byte-axis per relation still stores exactly ONE +`part_of` parent, so a node with three parents keeps getting one. **Do not read +the RECOMMENDED verdict as covering F-3.** Multi-parent is closable only by (b), +which needs a view carrier that does not exist; until that carrier is designed, +F-3 stays open whatever this row says. §7.2 states the same thing from the +remedy side. ### D-3 — Laterality (addresses F-4) @@ -232,7 +250,8 @@ the surfel/torso line. This plan is about the key, not the mesh. > §4 probes are unchanged by anything here. Nine directions, checked against `AdaWorldAPI/lance-graph`'s -`.claude/v3/soa_layout/` contract. Most are already carved; three are new. The +`.claude/v3/soa_layout/` contract: **five already carved (§6.1), four new +(§6.3)**. The split matters because a carved item needs *wiring*, and a new one needs a *ruling* first. @@ -244,7 +263,7 @@ split matters because a carved item needs *wiring*, and a new one needs a | **6 × palette256² for Fisher-z** | `le-contract.md:171-186` — L4 reads through the **analytic Fisher-z codec** (`bgz-tensor::fisher_z::{FamilyGamma, FisherZTable}`), certified ρ≥0.999, `E-FISHERZ-CANONICAL-COSINE-REPLACEMENT-1`. *"A materialized k×k table is a CACHE of the formula, never the canon."* Boundary: replaces the distance/rank READ; the semiring COMPOSE keeps its table | | **helix Signed360** | tenant 4 `HelixResidue`, 6 B `[112,118)` — *"48-bit helix place (2× 24-bit equal-area hemisphere, Signed360)"*. Sibling of the above: *"helix is to Fisher-2z what the cosine-replacement is to Fisher-z"* | | **many-to-many nodes** | **three** existing mechanisms — tenant 15 `EpisodicBasin` (§6.2), L2 facet `memberof : members`, and q2's own EdgeBlock 16×8-bit adapter mask (`osint_gotham.rs:12-16`) | -| **24 × i4 Markov context** | tenant 14 `CausalWitness`, `U8 × 16` `[204,220)`, read **G24N4** — *"24 signed i4 loci… each nibble is a context pointer (signed ±8 window offset), not a strength"*. Slots 16..24 reserved-zero. **EXPERIMENTAL**, and by its own doc-comment *"not in the operator-locked §3 catalogue"*; it is a **lane shape name, never a `CascadeShape` variant** | +| **24 × i4 Markov context** | tenant 14 `CausalWitness`, a 16-byte lane at `[204,220)` holding the V3 4+12 facet. The **G24N4 carving applies to the 12-byte payload, not the 16-byte lane**: `WITNESS_REGISTER_BYTES` = 12 B = **24 nibbles**, `WITNESS_LOCI = 24`, `NAMED_LOCI = 16`, and slots **`16..24` (half-open, 8 slots) reserved-empty** — "held open, never padded with a construct to reach 24" (`causal_witness.rs:71-85`). Each nibble is a context pointer (signed ±8 window offset), never a strength. **EXPERIMENTAL**: `causal_witness.rs:14-19` records that the cited "§3 L9 `G24N4`" entry **does not exist** — §3 is L1–L8 — and that a sub-byte carving is a **lane shape NAME**, never a `CascadeShape` variant | ### 6.2 The many-to-many node already encodes the no-hub ruling @@ -334,8 +353,8 @@ has no owning decision at all. | **F-2** `row: u32` → `identity: u16`, unchecked | silent wrap past 65,536 concepts; today never fires at 1,658 | **nothing on its own** | D-1a removes `row` as the identity source | **D-1a does not add a guard.** F-2 needs an explicit `TryFrom`/`debug_assert` at the mint regardless of which D-1 option wins. Do not treat it as closed by D-1 | | **F-3** part_of is a DAG upstream; cascade consumes a tree | ~35% of concepts (3.0 table) addressed under one arbitrary parent — CONJECTURE for 4.0 | **D-2b** (views as attributes of relations) | D-2c (record which parent won) makes the arbitrariness auditable, not correct | D-2b needs a **view carrier that does not exist**. Blocked on **P-1**; until P-1 runs, the size of this flaw in 4.0 is unknown | | **F-4** laterality edge table unconsumed | 8,265 of 12,530 composite→primitive edges carry an axis word; the axis is reachable only by string-matching a label | **D-3a** (consume `composite_parts.txt` as an edge relation) | — | Sized by **P-4** — unknown how many composites/primitives are in the meshed set. D-3b (axis into a key tier) is *rejected*, not deferred | -| **F-5** `is_a` fills both rail axes | the L1 `part_of : is_a` carving carries one relation twice; part_of contributes nothing to the address | **D-2a** (fill the rails as designed) | — | Closes the waste, **not F-3**. A node with three parents still gets one | -| **F-6** part_of depth 16 > 7 addressable levels | 279 nodes (20%) share a prefix with an ancestor via the `tier_at → 0` fallback | **D-4b** (registry resolve + ref-escape) | D-4a (record the truncated remainder in a tenant) makes it lossless-on-read, not addressable; §6.3's 2×12 zipper reaches 13 levels of 16 | D-4c (widen the key) is **forbidden by canon** — scale is the next cascade level, never field-widening | +| **F-5** `is_a` fills both rail axes | the L1 `part_of : is_a` carving carries one relation twice; part_of contributes nothing to the address | **D-2a** (fill the rails as designed) — and D-2a closes **nothing else** | — | Closes the waste, **not F-3**. A node with three parents still gets one | +| **F-6** part_of depth 16 > the key's 6 addressable levels | deep nodes share a prefix with an ancestor via the `tier_at → 0` fallback; the old 279-node/20% figure is withdrawn pending P-1's depth histogram (see F-6) | **D-4b** (registry resolve + ref-escape) | D-4a (record the truncated remainder in a tenant) makes it lossless-on-read, not addressable; §6.3's 2×12 zipper reaches 13 levels of 16 | D-4c (widen the key) is **forbidden by canon** — scale is the next cascade level, never field-widening | | **F-7** we bake 4.0; upstream rejected 4.0 for intersecting skin/muscle | two re-bakes (20260629b, c) spent on classification overlap | **no option yet** — D-5 is deliberately undecided | — | Gated on **P-5**. Until measured, a common cause is CONJECTURE only | | **F-8** three group-membership mechanisms coexist | `EpisodicBasin` (tenant 15), L2 `memberof : members`, and q2's EdgeBlock adapter mask all address many-to-many | **no owning decision — this is a gap in §3** | §6.2 states the constraint ("pick one, do not add a fourth") but assigns no verdict | Needs a **D-6** before any group work lands, or the v4 adds a fourth by accident | | **§6.5** `tenants.md:88` says 15 tenants; the table runs 0–15 | a session sizing a preset from the prose is off by one | a one-line doc fix **in lance-graph** | — | **Not fixable from this repo.** Code is correct (`canonical_node.rs:1252` compile-asserts the pairing); prose only | @@ -344,8 +363,10 @@ has no owning decision at all. - **Multi-parent addressing is not solved by anything currently on the table.** D-2a stops the rails wasting an axis; D-2b is the real answer and needs a - carrier that does not exist. If P-1 shows the 4.0 part_of is a DAG, this - becomes the largest open item in the plan, larger than F-1. + carrier that does not exist. D-2a is marked RECOMMENDED for F-5 **only** — + reading that verdict as covering F-3 is the specific misreading §3's D-2 note + now guards against. If P-1 shows the 4.0 part_of is a DAG, this becomes the + largest open item in the plan, larger than F-1. - **Vessel caliber** (§6.4) is excluded by §5 and no D-item covers it. - **The hex substrate / explicit volumetric trie** (§6.3) are research, not remedies; neither closes a flaw listed above.