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
4 changes: 4 additions & 0 deletions .claude/board/AGENT_LOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2026-06-13 — #489 canonicalised: wire-in + self-describing Display + retire Phase-A wrapper

**bardioc cross-session.** Operator pin: *"#489 is canonical."* Audited OGAR/CLAUDE.md P0 against `canonical_node.rs` group-by-group. Key (classid·HEEL·HIP·TWIG·family·identity = 8·4·4·4·6·6 hex) matches exactly; RFC-WAIVED matches ("No UUID ceremony"); 3×4 uniform tiers match (each u16; tier-of-level = `level >> 2`); 16-byte EdgeBlock at fixed offset = row-layout analogue of the zero-fallback ladder (default class's default ClassView reserves it, registry-resolved opt-out for non-default classes, "reserve-don't-reclaim" at row level). **One gap closed:** canon mandates *"every printed GUID is self-describing at sight"* via the dash-groups, wrapper had no `Display`. Added `impl Display for NodeGuid` emitting canonical `{classid:08x}-{heel:04x}-{hip:04x}-{twig:04x}-{family:06x}{identity:06x}` (LE in-memory bytes folded through the accessors so hex print is canon-ordered regardless). +2 Display tests. **Phase-A wrapper retired in the same PR** (operator: *"delete #480 from your mind"*): `identity.rs` deleted (UUIDv8 NodeGuid + RFC ceremony bits + IDENTITY_LAYOUT_VERSION + SHAPE_HASH_BITS/LOCAL_BITS — all canon-incompatible per *"wrappers adapt to the canon, never the reverse"*); `pub use identity::{NodeGuid, IDENTITY_LAYOUT_VERSION}` → `pub use canonical_node::{EdgeBlock, NodeGuid, NodeRow}`; `pub mod identity;` removed. Two stale doc references reworded: `hhtl.rs:192` (`from_packed` now a general HHTL utility, not identity::NodeGuid-specific), `lance-graph-ontology/src/registry.rs:405` (`niblepath_of` now points at the canon's `classid·HEEL·HIP·TWIG` resolution). `cargo test -p lance-graph-contract --lib`: **594/594 green** (−10 retired UUIDv8 tests, +2 Display, +8 wire-in canonical_node tests now visible); `cargo check -p lance-graph-ontology`: clean (5 pre-existing `oxrdf::Subject` deprecation warnings, untouched files); `cargo clippy -p lance-graph-contract --all-targets -- -D warnings`: clean. Anchored on #482 (GUID canon) + #489 (canonical_node) + OGAR/CLAUDE.md P0 (the canon itself, *"wrappers audited against this canon group-by-group — never the reverse"*).

## 2026-06-11 — tombstone commit: emission artifacts removed per PR #477 follow-up

**Main thread (Fable, session splat3d-cpu-simd-renderer).** Executed the PR #477 documented follow-up (the "what does NOT exist" table → source reality): removed `CollapseGateEmission` from `lance-graph-contract::collapse_gate` (+ lib.rs re-export; `MailboxId`/`MergeMode`/`GateDecision` survive), removed `MailboxSoA::emit()`, renamed `last_emission_cycle` → `last_active_cycle`, added in-place `consume_firing(row)` successor (same threshold + same-cycle-idempotency semantics, no carrier object), reworded 4 stale doc references (kanban/episodic_edges/witness_tombstone/mailbox_soa header), superseded the CLAUDE.md Baton-scoping block, fixed cycle-coherent-soa-snapshot-v1 D-SOA-SNAP-1/2 to generic `SnapshotProvider::Column` (closes #477 CodeRabbit Critical — contract stays zero-dep), closed TD-COLLAPSE-GATE-SMALLVEC-1 as moot. Verified #477 codex P2 (`verify_layout` ColumnOutOfBounds) already fixed on main with regression test. Tests: contract 594 (−8 emission, +2 gate/merge), driver 85 (emit tests → consume tests, +1 OOB), clippy clean, workspace check clean. Commit: in PR.
Expand Down
45 changes: 45 additions & 0 deletions crates/lance-graph-contract/src/canonical_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,30 @@ impl NodeGuid {
}
}

/// Canonical self-describing print: `classid-HEEL-HIP-TWIG-family·identity`.
///
/// The dash-groups ARE the semantic delimiters — every printed GUID is
/// self-describing at sight (OGAR canon, P0). `{:08x}-{:04x}-{:04x}-{:04x}-{:06x}{:06x}`
/// renders the canonical 8-4-4-4-12 hex layout regardless of in-memory byte
/// order (the field accessors fold LE bytes into u32/u16/u24 first).
impl core::fmt::Display for NodeGuid {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let h = u16::from_le_bytes([self.0[4], self.0[5]]);
let p = u16::from_le_bytes([self.0[6], self.0[7]]);
let t = u16::from_le_bytes([self.0[8], self.0[9]]);
write!(
f,
"{:08x}-{:04x}-{:04x}-{:04x}-{:06x}{:06x}",
self.classid(),
h,
p,
t,
self.family(),
self.identity(),
)
}
}

/// 16-byte canonical edge block: 12 in-family + 4 out-of-family.
///
/// Canonical, not mandatory: the 16 bytes are ALWAYS reserved (zeroed when unused).
Expand Down Expand Up @@ -233,4 +257,25 @@ mod tests {
fn new_panics_on_identity_overflow() {
let _ = NodeGuid::new(0, 0, 0, 0, 0, 0x0100_0000);
}

#[test]
fn display_is_canonical_self_describing() {
// Canon (OGAR P0): xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12 hex);
// groups = classid · HEEL · HIP · TWIG · family·identity.
let g = NodeGuid::new(0xDEAD_BEEF, 0x1111, 0x2222, 0x3333, 0x00_00AB, 0x00_00CD);
let s = g.to_string();
assert_eq!(s, "deadbeef-1111-2222-3333-0000ab0000cd");
assert_eq!(s.len(), 36, "8-4-4-4-12 + 4 hyphens");
for i in [8usize, 13, 18, 23] {
assert_eq!(s.as_bytes()[i], b'-', "hyphen at {i}");
}
}

#[test]
fn display_zero_default_is_all_zeros() {
// Zero-fallback ladder visible at sight: classid + family == 0 prints
// as ...0...-...0... with identity-only discrimination.
let g = NodeGuid::local(0x00_00CD);
assert_eq!(g.to_string(), "00000000-0000-0000-0000-0000000000cd");
}
}
4 changes: 2 additions & 2 deletions crates/lance-graph-contract/src/hhtl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ impl NiblePath {
}

/// Reconstruct a path from its raw packed `(path, depth)` — the inverse of
/// [`packed`](NiblePath::packed). Used by `identity::NodeGuid` to round-trip
/// the routing-prefix it stores.
/// [`packed`](NiblePath::packed). General HHTL utility for round-tripping
/// a routing path through its packed `(u64, depth)` form.
///
/// Returns `None` if `depth > MAX_DEPTH`, or if `path` has bits set above the
/// `depth` nibbles (an inconsistent pack — leading nibbles must be the route,
Expand Down
Loading
Loading