Skip to content

Commit 5aaefd5

Browse files
committed
feat(contract): D-CLS-RENDER — ClassView::render_rows (off-bits-skipped render surface) + Wikidata-HHTL plan
render_rows(class,mask)->Vec<RenderRow{label,predicate}>: the C2 presence-only render surface (classes.md:49), template-agnostic (askama engine deferred to its crate-Wave). Completes the contract side of the XML-parse stack. Review->fix: clippy -D warnings caught a doc-list-indent lint -> reflowed. 497 contract lib green; clippy+fmt clean. Also records the Wikidata-HHTL plan as the next arc: the classes.md-N4 second-domain falsifier that reuses FieldMask/signature/ClassView; smallest slice = HHTL 16^n nibble router + OWL/DOLCE facet template + mask-inherits-as-delta (defer the 115M streaming load). https://claude.ai/code/session_01R9AWgFa65uPnLyS2my2d2R
1 parent 92cdab4 commit 5aaefd5

4 files changed

Lines changed: 75 additions & 4 deletions

File tree

.claude/board/EPIPHANIES.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## 2026-05-31 — SHIPPED D-CLS-RENDER + PLANNED Wikidata-HHTL (the N4 second-domain falsifier)
2+
3+
**Status:** D-CLS-RENDER SHIPPED-in-PR; Wikidata-HHTL = PLANNED (next arc, the classes.md:N4 falsifier).
4+
5+
**D-CLS-RENDER (shipped):** `ClassView::render_rows(class,mask) -> Vec<RenderRow{label,predicate}>` — the off-bits-skipped render surface (classes.md:49). Presence-ONLY (C2): a row appears iff its bit is set; the mask never changes meaning. Template-agnostic — an askama per-class template iterates these rows; the engine (F3=askama, OD ratified) is the deferred render-crate Wave (the plan's Wave-4 multi-agent, not a solo slice). Review->fix: clippy -D warnings caught a doc-list-indent lint (line starting with `+` read as a bullet) -> reflowed. 497 contract lib green; class_view clippy+fmt clean. Completes the CONTRACT side of the XML-parse stack: SoA=doc, ObjectView=XSD, ClassView=parser, FieldMask=presence, render_rows=the XSLT output rows.
6+
7+
**Wikidata-HHTL — the next arc (planned, why it matters):** classes.md N4 = "don't freeze the SoA schema until >=2 genuinely different domains run through it"; faiss-homology closed-picture = "chess + Odoo + Wikidata-anatomy all run through the same Class+SoA+HHTL+CAM with no special-case." Odoo is domain-1 (D-CLS shipped). **Wikidata HHTL is the SECOND-DOMAIN FALSIFIER** that proves FieldMask/StructuralSignature/ClassView are universal, not Odoo-cosplaying. DIRECT REUSE: wikidata facet-bitmask = my `FieldMask`; shape = my `signature()`; (class_id, shape_hash, presence_bitmask) persisted row = exactly the D-CLS triple.
8+
9+
**The right SMALLEST slice (not the 115M load — that's a streaming pipeline):** the wikidata-hhtl doc's bring-up = the **HHTL 16^n nibble router + OWL/DOLCE facet template**. Concretely shippable + reuses D-CLS: (a) `HhtlPath` (16^n nibble sequence = the P279/subClassOf Abstammungs-path, the ONE tree axis; bit-shift routing, O(1)); (b) the OWL-construct -> HHTL-form table as a typed mapping (subClassOf->path, closed-ObjectProperty->facet-bit=my FieldMask, DatatypeProperty->Quartett slot, disjointWith->collision-free additive); (c) mask-inherits-along-path-as-DELTA (the leaf stores only its increment over the parent — prevents the union disease). zero-dep contract types + a tiny falsifiable test (a 2-level P279 path + a facet, assert the leaf mask = parent-delta). DEFER: the streaming json.gz loader, the 115M scaling, the reasoning Derived store.
10+
11+
**Cross-ref:** D-CLS arc (FM/RES/SIG/AUDIT/RENDER, the reused machinery); wikidata-hhtl-load.md (the pipeline); faiss-homology-cam-pq.md (facet u64 = SoA facet column = FieldMask; HHTL=IVF cell); classes.md N3/N4 + :49; cognitive-risc-core (HHTL=Schedule-layer bucket router).
112
## 2026-05-31 — SHIPPED-in-PR: D-CLS-AUDIT — curated-corpus shape-family audit (classes.md:42 CONFIRMED on real data, falsifiably) + clippy fix
213

314
**Status:** SHIPPED-in-PR (#440 D-CLS Wave-2 input). Extends D-CLS-SIG from one lane to the full curated corpus.

.claude/board/STATUS_BOARD.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ Plan path: `.claude/plans/unified-soa-convergence-v1.md`. Handover `.claude/hand
572572
| D-CLS-RES | `class_resolver`: `RegistryClassView` impls `ClassView` over the live OntologyRegistry — the ontology-side 'parser' (class_id -> shape, DOLCE resolved LATE via classify_odoo from the cache URI, memoized over the O(n) registry scan) | lance-graph-ontology | 200 | LOW | **In PR** | #440 D-CLS; makes the contract trait live; field-set supplied (D-CLS audit deferred); 4 teeth-tests |
573573
| D-CLS-SIG | `class_signature`: deterministic structural-signature audit of curated OdooEntity consts (FNV-1a over kind+field-hist+method-hist+state-machine) -> shape-family group-by + `object_view()` derives the real ObjectView bit-basis (fills the D-CLS-RES placeholder) | lance-graph-ontology | 230 | LOW | **In PR** | #440 D-CLS; the HONEST D-CLS-3 (group-by-on-structural-hash, NOT aerial-cluster vaporware, classes.md:43); 4 teeth-tests over real l1 data |
574574
| D-CLS-AUDIT | `class_signature` corpus audit: `curated_entities()` (all 15 l-lanes, 64 consts) + `corpus_summary()` + falsifiable test that the real curated corpus collapses entities->fewer shape-families (classes.md:42 CONFIRMED on real data, not asserted) | lance-graph-ontology | 90 | LOW | **In PR** | #440 D-CLS Wave-2 input; +clippy fix (unused FieldMask import in class_resolver) |
575+
| D-CLS-RENDER | `ClassView::render_rows` + `RenderRow{label,predicate}` — the off-bits-skipped render surface (C2 presence-only; template-agnostic, askama engine deferred to its own crate-Wave) | lance-graph-contract | 50 | LOW | **In PR** | #440 D-CLS; the render LOGIC (classes.md:49), not the engine; +doc-lint fix |
575576

576577
---
577578

crates/lance-graph-contract/src/class_view.rs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
//! Today OGIT (`lance-graph-ontology::OntologyRegistry`) is a **hashtable doing
66
//! single lookups**: `uri → row`, `entity_type_id → row` — one key, one value,
77
//! O(1), leaf. That is the *single* lookup. What a class needs is a **meta
8-
//! lookup**: `class_id → the whole shape` (ordered field set + labels + template
9-
//! + the presence-bit basis). The class composes many leaf lookups into one
10-
//! shape — the way an XSD schema composes element declarations.
8+
//! lookup**: `class_id → the whole shape` — the ordered field set, labels,
9+
//! template, and the presence-bit basis. The class composes many leaf lookups
10+
//! into one shape — the way an XSD schema composes element declarations.
1111
//!
1212
//! ```text
1313
//! SoA row = the XML document (agnostic bytes, no meaning)
@@ -159,6 +159,35 @@ pub trait ClassView {
159159
pos: 0,
160160
}
161161
}
162+
163+
/// The **render rows** for an instance: only the populated `(label, predicate)`
164+
/// pairs, off-bits skipped (`cognitive-risc-classes.md`:49). This is the
165+
/// template-agnostic render surface — an askama/jinja per-class template iterates
166+
/// these rows; the engine choice (F3, askama) lives in the deferred render crate.
167+
///
168+
/// Presence-only (C2): a row appears iff its bit is set; the mask NEVER changes a
169+
/// row's meaning, only its presence. The labels are the meta-DTO's late resolution
170+
/// (above the SoA), the mask is the SoA's structural delta.
171+
fn render_rows<'a>(&'a self, class: ClassId, mask: FieldMask) -> Vec<RenderRow<'a>> {
172+
self.project(class, mask)
173+
.filter(|(_, present)| *present)
174+
.map(|(f, _)| RenderRow {
175+
label: f.label.as_str(),
176+
predicate: f.predicate_iri.as_str(),
177+
})
178+
.collect()
179+
}
180+
}
181+
182+
/// One populated field to render — the late-resolved `label` + its `predicate` key.
183+
/// Produced only for set bits (off-bits are skipped), so a template never branches
184+
/// on presence (C2): it just iterates the rows it is given.
185+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186+
pub struct RenderRow<'a> {
187+
/// The display label, resolved late from the OGIT cache (above the SoA).
188+
pub label: &'a str,
189+
/// The field's predicate IRI (the stable key behind the label).
190+
pub predicate: &'a str,
162191
}
163192

164193
/// An iterator over a class's fields paired with their presence bit — the
@@ -265,4 +294,34 @@ mod tests {
265294
assert_eq!(classes.field_count(7), 3);
266295
assert_eq!(classes.field_count(999), 0); // unknown class
267296
}
297+
298+
#[test]
299+
fn render_rows_skips_off_bits_presence_only() {
300+
let classes = FakeClasses::new();
301+
// Tax (pos 1) is off → it must NOT produce a render row (C2: off-bits skipped).
302+
let rows = classes.render_rows(7, FieldMask::from_positions(&[0, 2]));
303+
assert_eq!(rows.len(), 2, "only the 2 populated fields render");
304+
assert_eq!(
305+
rows[0],
306+
RenderRow {
307+
label: "Total",
308+
predicate: "amount_total"
309+
}
310+
);
311+
assert_eq!(
312+
rows[1],
313+
RenderRow {
314+
label: "Partner",
315+
predicate: "partner_id"
316+
}
317+
);
318+
// Empty mask → zero rows (no template branch needed, just an empty iteration).
319+
assert!(classes.render_rows(7, FieldMask::EMPTY).is_empty());
320+
// Full mask → all 3 rows, in class order (the bit basis).
321+
let all = classes.render_rows(7, FieldMask::from_positions(&[0, 1, 2]));
322+
assert_eq!(
323+
all.iter().map(|r| r.label).collect::<Vec<_>>(),
324+
vec!["Total", "Tax", "Partner"]
325+
);
326+
}
268327
}

crates/lance-graph-contract/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub mod world_map;
9797
pub mod world_model;
9898

9999
// Re-exports for the most commonly used collapse_gate types.
100-
pub use class_view::{ClassId, ClassProjection, ClassView, FieldMask};
100+
pub use class_view::{ClassId, ClassProjection, ClassView, FieldMask, RenderRow};
101101
pub use collapse_gate::{CollapseGateEmission, GateDecision, MailboxId, MergeMode};
102102
pub use kanban::{ExecTarget, KanbanColumn, KanbanMove, RubiconTransitionError};
103103
pub use soa_view::{MailboxSoaOwner, MailboxSoaView};

0 commit comments

Comments
 (0)