Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions .claude/board/AGENT_LOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## 2026-06-20 (cont.⁹) — PR #560 codex P2 review fixes (gremlin bag semantics + aiwar cross-family edges)

**Main thread (Opus), autoattended.** Two unresolved P2 codex threads on PR #560, both fixed: (1) `graph_gremlin.rs` `step()` silently deduped targets via a `seen` set — broke Gremlin bag/multiset semantics (`v(["A","C"]).out().count()` = 1 not 2 when both reach B). Rewrote to per-traverser emission (duplicates preserved); added explicit `dedup()` step + `out_preserves_bag_multiplicity` test. (2) `aiwar.rs` `aiwar_node_rows` put cross-category adapter bytes into the first 12 `in_family` slots (labeled `linked`), so `references` queries missed them and the label flipped with fan-out count — aiwar edges are ALL cross-family, so they now go to the 4 `out_family` slots (`references`), cap 4; test asserts `references` present + no `linked`. contract aiwar 3/3, callcenter gremlin 8/8 (+1 bag test), clippy clean (my files; pre-existing TD-CALLCENTER-QUERY-CLIPPY untouched). Pushed to #560; both review threads resolved. **558/559 (NOT mine — OpenProject/Redmine ontology bridges) checked: NOT all resolved** — #558 2 open (codex P2 seed-context-id + CodeRabbit unit-tests), #559 1 open P1 (Redmine/OpenProject entity_type_id convergence). Surfaced to operator (different arc); not auto-fixed.

## 2026-06-20 (cont.⁸) — D-GV2-1 shipped: GUID v2 tail (leaf·family·identity 3×u16), feature-gated

**Main thread (Opus), autoattended.** Operator "go" on the guid-v2-tail plan (canon version bump + capacity numbers accepted). Built **D-GV2-1** additive + `#[cfg(feature="guid-v2-tail")]` + NON-breaking (v1 untouched): `canonical_node::{new_v2, leaf() 10..12, family_v2() 12..14, identity_v2() 14..16, local_key_v2, decode_v2/GuidPartsV2, to_hex_v2, GUID_TAIL_LAYOUT_VERSION_V2=2}`; `hhtl::from_guid_prefix_v2` (HEEL·HIP·TWIG·leaf, 16 nibbles — leaf in path, family/identity in basin tail). Per `I-LEGACY-API-FEATURE-GATED`: distinct v2 names (no silent semantic swap), field-isolation matrix test (vary one tier → only that accessor changes), v1/v2 coexistence test, version-gate const. **Verified BOTH configs:** default `cargo test -p lance-graph-contract --lib` = **703** (unchanged, non-breaking); `--features guid-v2-tail` = **706** (+3 v2 tests); clippy `-D warnings` clean on both. Cutover (rename v2→canonical, deprecate v1, ENVELOPE_LAYOUT_VERSION bump) = D-GV2-5, after D-GV2-2 (family→Codebook registry) / D-GV2-3 (soa_graph per-family edges) / D-GV2-4 (aiwar re-key) consume the v2 accessors. Pushed to jirak (extends PR #560). Plan D-GV2-1 marked SHIPPED.

## 2026-06-20 (cont.⁷) — codex roll-up + 16-family-adapter edges + Callcenter DataFusion/Gremlin + aiwar POC

**Main thread (Opus), autoattended.** Follow-up to merged PR #557. Pulled the 2 codex P1 review comments (chatgpt-codex-connector; the CodeRabbit arg-count was fixed pre-merge) and rolled both into this PR per operator. **codex #1** (classid filter): `project_snapshot`/`nearest_anchor` now include only rows where `classid == domain.classid` (a classid IS the class, exact — operator). **codex #2** (ambiguous edge bytes): resolved via the operator's **16×8-bit family-node adapter** model — the `EdgeBlock` is read as 16 family adapters (each byte → a FAMILY by `family & 0xFF`, collision-aware skip), not member-by-identity; the >255-member aliasing dissolves (resolution is family-level only). EPIPHANY `E-FAMILY-ADAPTER-EDGES-ARE-RENDER-STABLE` (mixin-dependency traded for render stability + flexibility).

**Callcenter slice (lance-graph-callcenter):** NEW `graph_table` (`query-lite`) — `GraphSnapshot` → `nodes`/`edges` arrow MemTable `TableProvider`s + `register_graph(SessionContext)` (the DataFusion/SQL/Cypher→SQL path, mirrors `transcode::ontology_table`); NEW `graph_gremlin` (always-on, pure contract types) — `g(&snap).v().out()/.in_()/.out_e(label)/.values_kind()` Gremlin POC = the SurrealQL `->edge->` traversal kernel. **aiwar POC (contract `aiwar.rs` + example):** `AiwarClassView` (category ⇒ family-id) + `aiwar_node_rows` ingest the REAL `AdaWorldAPI/aiwar-neo4j-harvest/data/aiwar_graph.json` (174 KB) → OSINT NodeRows → `project_snapshot`. Example run: **221 entities/326 edges → 281 nodes (221 members + 60 family hubs) + 481 edges**. (Honest: 60 families because the class view keys off the raw fine-grained `type` field; coarse `N_*`-bucket grouping is a one-line knob — mechanism is correct.)

Tests: contract **703** lib (+5: aiwar ×3, soa_graph ambiguity+mixed-class ×2), clippy `--all-targets -D warnings` clean. Callcenter **10** graph tests (`--features query`, incl. live SQL roundtrip), default build compiles `graph_gremlin`; my two files clippy-clean (pre-existing oxrdf/doc `-D warnings` debt in unrelated modules logged to TECH_DEBT). q2 wires the GraphSnapshot to the Quadro-2 visual. PR opened (codex fixes rolled in).

## 2026-06-20 (cont.⁶) — SoA-as-graph domain foundation for q2 (OSINT/Gotham 0x0007 + FMA 0x0008)

**Main thread (Opus), autoattended.** Operator: "prepare everything so q2 can render nodes/edges + family nodes + HHTL CLAM hop adjacency, neo4j-emulation; OSINT OGAR class is 0x0007; also FMA anatomy 70k as body with bones as stability anchor — rendering is wired in the q2 session, here just the basic domain + SoA-as-graph." Grounded with two parallel Explore agents (q2 wiring + lance-graph ontology/callcenter/polyglot) BEFORE building — consult-don't-guess paid off twice: (a) `graph_render.rs` ALREADY is the Neo4j/Gotham surface (`GraphSnapshot`/`RenderNode`/`RenderEdge`, consumer = q2 cockpit) → reused, not duplicated; (b) `NiblePath::from_guid_prefix` ALREADY is the canonical GUID→path lowering → de-duped symbiont's third copy onto it.
Expand Down
49 changes: 49 additions & 0 deletions .claude/board/EPIPHANIES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
## 2026-06-20 — E-UNIFORM-MORTON-TILE-PYRAMID — making every GUID tier the same size (8×u16) makes the KEY, the per-family CODEBOOK, the VALUE tile, and the PERTURBATION pyramid all the SAME 2bit×2bit 4×4 Morton-tile primitive — so one kernel (Morton + AMX 4×4 BF16 GEMM), one distance (Morton common-prefix = HHTL hop), and one codebook shape (256×256 per tier) govern the whole substrate

**Status:** FINDING (operator design lock, GUID-v2-tail, 2026-06-20).

The v2 tail's payoff is not just "kills u24" — it's that **uniform tier size collapses four separate structures onto one tile primitive**:

- **1 nibble = 2bit×2bit = a 4×4 Morton tile = `FAN_OUT`-16** (one HHTL level). The atom — the same `morton4(x,y)` interleave `domino.rs` already runs on the value side.
- **1 u16 tier = 4 nibbles = a 256×256 Morton tile** (8 bits/axis) = OGAR's "256×256 centroid tile per tier" (`256 = 4⁴`; nibble-interleave = alternating-axis refinement = Morton in centroid space).
- **8 u16 tiers = one stacked pyramid**, every tier identical in size/shape (`classid_hi·classid_lo·HEEL·HIP·TWIG·leaf·family·identity`).

The same 4×4 Morton primitive then governs four things that were separate:
1. **Key/address** — each tier a 256×256 tile; routing = descend tiles.
2. **Codebook** — a 256×256 centroid tile per family (per-family scoping), selected by the family tier (itself a tile). D-GV2-2.
3. **Value** — the domino BF16 4×4 Morton tile → AMX `TDPBF16PS` GEMM (shipped).
4. **Perturbation/helix** — the stacked-pyramid (exponent=tier-level, location=Morton sub-tile, phase=deterministic, magnitude=stored) lands on the same grid (OGAR `guid-prefix-shape-routing.md` §4).

Payoffs collapse to one each: **one kernel** (Morton addressing + the AMX 4×4 tile GEMM sweeps tiers / codebooks / values uniformly, no special-casing), **one distance** (Morton common-prefix depth = HHTL hop = `family_hop_count` = `E-MIXIN-IS-AN-ADDRESS-REFERENCE-NOT-A-COPY`'s "distance in the address"), **one codebook shape**. The 24+24 tail broke this uniformity (a u24 is neither a clean Morton tile nor u16-aligned); 16+16+16 restores it. Condition: only holds while every tier stays u16 (4-nibble = one 256×256 tile) and the codebook stays the 4⁴ centroid hierarchy (flat k-means-256 breaks the Morton prefix; `OGAR/CLAUDE.md` "Tier interpretation"). Cross-ref: `E-MIXIN-IS-AN-ADDRESS-REFERENCE-NOT-A-COPY`, `E-FAMILY-ADAPTER-EDGES-ARE-RENDER-STABLE`, OGAR canon "256×256 CENTROID TILE" + "Bipolar-phase pyramid", `domino.rs` (`morton4` + AMX tile GEMM), plan `guid-v2-tail-per-family-codebook-v1.md`.

---

## 2026-06-20 — E-MIXIN-IS-AN-ADDRESS-REFERENCE-NOT-A-COPY — when group membership lives in the GUID ADDRESS (the family tier / the 16 family-adapter bytes) and shared state lives ONCE on the family-node basin, a mixin / multiple-membership is O(1) (a byte reference) not O(n) (materialized inherited edges), and inter-node distance is HHTL hop arithmetic on the address, never a BFS over edges — "distance is in the address/hops"

**Status:** FINDING (perennial; operator design lock, GUID-v2-tail plan, 2026-06-20).

Naive multiple-inheritance / multi-group graphs explode: a node in N groups must materialize N inherited edge-sets (copy or link each) → O(n) per node, and "how far apart are A and B" is a BFS over those materialized edges. Both costs vanish when membership is **addressed, not materialized**:

1. **A family node is an episodic basin.** The connections accumulated *on the basin* (its in/out edges) ARE the **supporting edges** of every member — the shared state lives ONCE, on the family-node row, not copied into each member.
2. **A member mixes in a family by reference** — a 1-byte family-adapter slot (or the `family` tier of its own GUID), never a copy. N memberships = N adapter bytes (≤16), bounded. Adding a member to a rich basin is free: it inherits the basin's whole supporting-edge set by pointing at it. **Mixin = O(1).**
3. **Distance is in the address.** Inter-node distance = HHTL hop count (`family_hop_count` / `common_prefix_depth`) computed from the two GUIDs — O(depth) arithmetic, never a graph traversal. "Distance is in the address/hops."

So the three costs that kill multi-group graphs become: membership = O(1) (a byte), shared episodic state = stored once (the basin), distance = O(1) (address arithmetic). This is *why* the GUID-v2 tail (`leaf` HHTL tier · `family` basin · `identity` instance) + per-family codebooks is not just a layout tidy-up — it makes mixins and supporting-edge inheritance asymptotically cheap. The condition is strict: it only holds while membership stays in the head address (never a value-slab list) and the family basin owns the shared edges (never per-member copies). Cross-ref: `E-FAMILY-ADAPTER-EDGES-ARE-RENDER-STABLE` (the edge-resolution face), `E-ANCHOR-IS-A-HEAD-FIELD-NOT-A-VALUE-TYPE` (structure-in-the-head), `E-GUID-IS-THE-GRAPH`, plan `guid-v2-tail-per-family-codebook-v1.md` (D-GV2-2 episodic basin), OGAR codebook-scoping canon.

---

## 2026-06-20 — E-FAMILY-ADAPTER-EDGES-ARE-RENDER-STABLE — resolving graph edges to FAMILY nodes (16×8-bit family-node adapters) instead of to individual members trades a "mixin dependency" (a referenced family must exist) for two structural wins — extreme render stability (family hubs are fixed anchors, members attach to them, the layout doesn't churn) and the dissolution of the >255-member identity-byte aliasing (resolution is only ever family-level)

**Status:** FINDING (perennial; operator model, shipped `contract::soa_graph` 16-adapter reading + `aiwar` POC, 2026-06-20).

The merged `soa_graph` (PR #557) resolved the 12 in-family edge slots to individual sibling members by `identity & 0xFF`. Codex P1 #2 caught the flaw: a family with >255 members aliases on the low byte, so "first match" renders an edge to the *wrong* member by row order. The operator's fix is not a wider member index — it is a **reinterpretation**: read the canonical 16-byte `EdgeBlock` as **16 family-node adapter slots**, every byte resolving to a FAMILY (`family & 0xFF`), never an individual member.

Why this is the right move, not just a bug patch:
1. **The aliasing dissolves at the source.** There is no longer any member-level byte resolution — edges land on family nodes. The only remaining ambiguity is two families sharing a low byte (>256 families), handled by a collision-aware map that skips the ambiguous byte (never a wrong edge). 256 families "covers pretty much everything" for a POC; the prefix/HHTL route is the >256 escalation.
2. **Render stability is structural.** Family nodes are fixed hubs; members attach to them (member-of) and adjacency is member→family. A force-directed layout anchored on a small stable set of family hubs does not churn frame-to-frame — the operator's "extreme render stability." This is the same stability `E-ANCHOR-IS-A-HEAD-FIELD` gives the FMA skeleton (bones = anchor families); the two epiphanies are the static (anchor) and dynamic (edge-resolution) faces of one principle: **structure lives on families, in the head.**
3. **Flexibility + the one cost.** A node mixes in up to 16 family adjacencies (huge flexibility, any-to-any within 256). The named limitation is **mixin dependency**: a referenced family must exist or the slot is a dangling adapter (skipped). That is the honest trade — and it is cheap, because a missing family is a render no-op, not a corruption.

The general rule for graph edges on this substrate: **resolve to the stable grouping (family), not the volatile leaf (member)** — unless a richer flavor (8×16-bit, 32×4 residue, member→member second-hop) is measured to be needed. Cross-ref: `E-ANCHOR-IS-A-HEAD-FIELD-NOT-A-VALUE-TYPE` (the static dual), `E-GUID-IS-THE-GRAPH`, the operator's deferred helix-basin-anchor (CLAM ⇄ Louvain turbovec edge residue) as the eventual richer flavor; `aiwar.rs` (the POC: 221 aiwar entities → 60 category family hubs).

---

## 2026-06-20 — E-ANCHOR-IS-A-HEAD-FIELD-NOT-A-VALUE-TYPE — graph STRUCTURE (domain, family grouping, hierarchy, stability anchors, adjacency) must key off the 32-byte HEAD (classid / family / HHTL path), never the value slab; only then does the whole neo4j/Gotham view — and "FMA bones as stability anchor" — stay zero-value-decode at memory-scan speed

**Status:** FINDING (perennial; shipped `contract::soa_graph` + `NiblePath::family_hop_count`, 2026-06-20).
Expand Down
6 changes: 6 additions & 0 deletions .claude/board/INTEGRATION_PLANS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2026-06-20 — guid-v2-tail + per-family codebook scoping (PROPOSED, operator what-if)

Plan: `.claude/plans/guid-v2-tail-per-family-codebook-v1.md`. Repartition the 48-bit basin tail `family(u24)|identity(u24)` → `leaf(u16)|family(u16)|identity(u16)` (whole key = uniform 8×u16 tiers), and scope **codebooks per family** (`family → Codebook`, the finer sibling of `classid → ClassView`; 12 in-family edge slots = 1-byte index into own family codebook, 4 out-of-family = `(family,index)`). Dissolves the aiwar "60 noisy families" at the root (per-family ≤256 vocabularies), kills the awkward `u24`, makes family-adapter resolution exact, and gives the 3-tier subclass codebook a native home. **Blast radius measured: CONTAINED in lance-graph** (q2/smb-office-rs/medcare-rs = 0; routing prefix `from_guid_prefix`/`mailbox_scan` is tail-agnostic; ~3 layout files + ~35 mostly-test `NodeGuid::new` call sites). **PROPOSED — gated on operator sign-off (canon version bump) + two numbers:** ≤65 536 identities per `(leaf,family)` bucket, ≤256 codebook entries per family before split. Ships feature-gated `guid-v2-tail` (default OFF) per `I-LEGACY-API-FEATURE-GATED` (field-isolation matrix + version gate). D-GV2-1..5.

---

## 2026-06-20 — unified-soa-rubikon-integration (ONE SoA: planner + kanban + SurrealQL + thinking-styles↔Rubikon)

Plan: `.claude/plans/unified-soa-rubikon-integration-v1.md`. The capstone after the golden image: the 16k-board SoA (`NodeRow` key16|edges16|value480) becomes ONE struct-of-arrays the **planner**, **kanban** lifecycle, **SurrealQL membrane**, and **thinking styles** all consume — landing in `lance-graph-planner` + `lance-graph-contract`, consuming Ontology + OGAR inheritance, with **ractor as the dummy ownership guarantee** (no messages/tokio). **SHIPPED foundation (verified file:line):** D0–D3 + NaN-projection + the synchronous writer-fires-kanban loop (D2). **PROPOSED (named targets located):** the four planner superpowers over the one SoA — (1) tenant→fingerprint meta-query (standing wave), (2) `temporal` implicit Markov chaining, (3) project any tenant (witness/CausalEdge64), (4) key-only 32-byte (GUID+EdgeBlock) neo4j render, zero value-decode; the Rubikon/Heckhausen + Libet −550..−200 ms mapping (−200 ms veto on `Planning→Prune`); OGAR class DO/THINK thinking-style selection via i4-32D fingerprint CAM + implicit sparse adjacency; JITson + lance-graph-callcenter outer boundary/SLA/commit membrane. Honest: §1 shipped, §2–§5 not yet running.
Expand Down
Loading
Loading