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
17 changes: 17 additions & 0 deletions .claude/board/EPIPHANIES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
## 2026-06-19 — E-OUTAGE-CASCADE-IS-NON-LOCAL — CORRECTION to `E-BASIN-IS-A-NODE`: the electricity-outage perturbation does NOT decay with HHTL hop; the "cascade round = hop / hop bounds reach" identity is a property of the COGNITIVE substrate (propagation rides basin-tree EDGES by construction), NOT of the DC-power-flow electrical metaphor — they must not be conflated

**Status:** FINDING (measured correction; probe `perturbation-sim/examples/outage_over_hhtl_hops.rs`). **Corrects** the second [H] sub-claim posted in `E-BASIN-IS-A-NODE` ("cascade round k = nodes at hop-distance k; Weyl bounds magnitude per round, hop-count bounds the reach"). Operator prompt: "model the electricity outage perturbation again with the HHTL L1-L4." The honest answer: I did, and it **refutes** the literal-electrical reading.

**What the probe measured.** A sparse hierarchically-coupled backbone (8 leaf basins, Cheeger bisection recovers the L1-L4 HHTL tiers), seeded at the max-base-flow line, `simulate_outage` run, perturbation `node_field` and `trip_round` scored against the `node_distance(PrefixDepth)` tree-hop from the seed:
- magnitude vs hop is **non-monotone** (hop0 5.13, hop2 5.22, hop4 0.22, **hop6 rebounds to 2.82**), Spearman ρ = **−0.233** (weak);
- the cascade **islands** (the grid fragments — node_field becomes a least-norm proxy, not physical);
- trip-order vs hop ρ = **−0.20** (if anything, later rounds trip *closer*, the opposite of hop-local).

So on the DC-power-flow model the outage is **non-local**: a far basin can feel as much shape as a near one, because flow redistributes globally (LODF), and the network islands. **The identity is NOT a property of the electrical metaphor.**

**What survives (the load-bearing distinction).** The hop = cascade-level identity holds for the **cognitive substrate**, where propagation is constrained to the basin-tree EDGES *by construction* — a delta reaches a node only through its HHTL neighbours, so reach IS hop-bounded and `node_distance(PrefixDepth)` IS the propagation metric. The electrical DC cascade is the **non-local counter-model that proves the distinction**: do not import "cascade reach = hop" from the power-grid analogy into the substrate as if measured there. The cognitive case is edge-local (trivially hop-bounded); the electrical case is globally-coupled (not hop-bounded). `E-BASIN-IS-A-NODE`'s *other* axes are untouched — basin=node, distance=hop=`PrefixDepth` (the placement probe `basin_placement_learning.rs`, green 75.8 %, stands), Morton-pyramid distribution. Only the electrical-cascade-as-propagation framing is corrected.

**Self-correction note (process):** the probe's first auto-verdict rubber-stamped ρ=−0.233 as "SUPPORTED" (threshold ρ<−0.2). That was the confirmation-bias trap (`adk-behavior-monitor`: "feels like success"). The verdict was tightened to require **monotone decay AND no islanding AND ρ<−0.5**; under the honest gate the result reads CORRECTED, not supported. Cross-refs: `E-BASIN-IS-A-NODE` (the corrected claim), `perturbation-sim::cascade::simulate_outage`, `mailbox_scan::node_distance` (the edge-local metric that IS hop-bounded).

---

## 2026-06-19 — E-GUID-SELF-ROUTES-THE-BASIN-TREE — `memberof` needs no coarse-fingerprint table: the HHTL nibbles ALREADY IN the GUID (classid·HEEL·HIP·TWIG) are the basin-tree route; the parent's address = HHTL-tier truncation of the child's own GUID, so every ancestor's route key derives from one key by truncation, zero lookups for addresses

**Status:** FINDING **[G]** for the truncation-is-route identity (pure key arithmetic; `NiblePath::parent`/`from_guid_prefix` already wired). Operator sharpening ("what about using the HHTL in the guid") — resolves the open cross-shard `memberof` question raised at `E-BASIN-IS-A-NODE` and corrects this session's own "hand the parent to a separate coarse-fingerprint table" framing. Sharpens `E-COARSE-QUANTIZER-IS-SCALE-FREE-ROUTER` and `E-TENANT-ANGLE-RANK-IS-CAM-PQ-ADC`.
Expand Down
82 changes: 73 additions & 9 deletions crates/lance-graph/src/graph/mailbox_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,15 +299,22 @@ pub fn members<V: MailboxSoaView>(view: &V, basin_row: usize) -> Vec<NodeMatch>
.collect()
}

/// The resolution of a [`memberof`] query: the parent basin is either
/// materialized in this mailbox (`Local`) or lives in another shard, addressed
/// by its HHTL prefix (`Route`).
/// The resolution of a [`memberof`] query: the parent basin is materialized in
/// this mailbox (`Local`), lives in another shard addressed by its HHTL prefix
/// (`Route`), or the node IS a top-tier basin with no parent (`Top`).
///
/// The GUID self-routes (`E-GUID-SELF-ROUTES-THE-BASIN-TREE`): the parent's HHTL
/// prefix **is** the shard/route key (`E-COARSE-QUANTIZER-IS-SCALE-FREE-ROUTER`
/// — the prefix is simultaneously the CLAM cluster key, the IVF cell, and the
/// shard key). So an unmaterialized parent is a **`Route`, not an absence** — no
/// separate coarse-fingerprint table is consulted; the prefix routes directly.
///
/// `Top` is the genuine "no parent" case (the DOLCE top facet). It is **distinct
/// from [`memberof`] returning `None`**, which means the node's own HHTL path is
/// not materialized (the deferred-binding default of
/// [`MailboxSoaView::hhtl_path_at`]) — i.e. *unresolved, fall back to a coarser
/// facet*, NOT *no parent*. Conflating the two would silently stop routing a row
/// whose path simply has not been bound yet.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BasinOf {
/// The parent basin-node row, materialized in this mailbox.
Expand All @@ -316,6 +323,10 @@ pub enum BasinOf {
/// the shard that owns the prefix (the coarse router keys on exactly this).
/// Zero value decode; the route key derives from the child's own GUID.
Route(NiblePath),
/// The node is a top-tier basin (`NiblePath::parent() == None`) — the DOLCE
/// top facet, genuinely no parent. Distinct from `memberof` returning `None`
/// (path not materialized; unresolved).
Top,
}

/// **`memberof`** (many-to-one) — the basin a node belongs to: the parent path
Expand All @@ -330,11 +341,28 @@ pub enum BasinOf {
/// Returns:
/// - `Some(BasinOf::Local(row))` — the parent basin-node is in this mailbox;
/// - `Some(BasinOf::Route(prefix))` — the parent lives in another shard, addressed
/// by its HHTL prefix (route it; **never `None` for a node that has a parent**);
/// - `None` — only at the top tier (`parent() == None`, the basin/DOLCE top facet
/// has no parent).
/// by its HHTL prefix (route it; **never an absence for a node that has a parent**);
/// - `Some(BasinOf::Top)` — the node is a genuine top-tier basin: a **depth-1**
/// root (`NiblePath::root(0..16)`) whose `parent()` is `None`;
/// - `None` — **unresolved**: either the node's HHTL path is not materialized (the
/// deferred-binding default of [`MailboxSoaView::hhtl_path_at`]) OR it is the
/// **depth-0 `NiblePath::EMPTY` "no route" sentinel**. Both mean *fall back to a
/// coarser facet*, NOT "no parent". Kept distinct from `Top` so a yet-to-be-bound
/// row — or an explicit no-route sentinel — is not mistaken for a root and
/// silently dropped from routing.
pub fn memberof<V: MailboxSoaView>(view: &V, member_row: usize) -> Option<BasinOf> {
let parent = view.hhtl_path_at(member_row)?.parent()?;
// `None` here = path not materialized (deferred-binding) → unresolved.
let path = view.hhtl_path_at(member_row)?;
// The depth-0 `EMPTY` "no route" sentinel is ALSO unresolved — its `parent()`
// is `None` like a real root, but it is not a top-tier basin (it has no basin
// at all). Distinguish by depth before classifying `Top` (codex #550 P2).
if path.depth() == 0 {
return None;
}
// A real top-tier basin: a depth-1 root, path exists but has no parent.
let Some(parent) = path.parent() else {
return Some(BasinOf::Top);
Comment on lines +363 to +364

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat empty HHTL paths as unresolved

When hhtl_path_at materializes the no-route sentinel as Some(NiblePath::EMPTY), this branch now reports BasinOf::Top because EMPTY.parent() is also None. NiblePath::EMPTY is documented as “no basin routed yet” and root(>=16) returns it as the “no route” sentinel (crates/lance-graph-contract/src/hhtl.rs:62-68), so classifying it as a genuine top-tier basin silently prevents the fallback/routing behavior this change is trying to preserve. Please distinguish path.depth() == 0 from depth-1 roots before returning Top.

Useful? React with 👍 / 👎.

};
Some(
(0..view.n_rows())
.find(|&row| view.hhtl_path_at(row) == Some(parent))
Expand Down Expand Up @@ -689,8 +717,9 @@ mod tests {
for m in members(&soa, 2) {
assert_eq!(local_row(memberof(&soa, m.row)), Some(2));
}
// row4 (9) is a top-tier basin (depth 1) → parent() is None.
assert_eq!(memberof(&soa, 4), None);
// row4 (9) is a top-tier basin (depth 1) → parent() is None → Top,
// NOT None (None is reserved for an unmaterialized path).
assert_eq!(memberof(&soa, 4), Some(BasinOf::Top));
}

#[test]
Expand All @@ -701,6 +730,41 @@ mod tests {
assert_eq!(memberof(&soa, 2), Some(BasinOf::Route(NiblePath::root(1))));
}

#[test]
fn memberof_unmaterialized_path_is_none_not_top() {
// Codex #549 P2: a deferred-binding row (hhtl_path_at == None) must return
// None (unresolved, fall back) — DISTINCT from a real top-tier basin,
// which returns Some(Top). Conflating them silently stops routing a
// not-yet-bound row.
let mut soa = sample();
soa.paths[0] = None; // row0's path not materialized
assert_eq!(
memberof(&soa, 0),
None,
"unmaterialized path ⇒ None (fall back)"
);
// row4 still a genuine top-tier basin ⇒ Some(Top), not None.
assert_eq!(memberof(&soa, 4), Some(BasinOf::Top));
}

#[test]
fn memberof_empty_sentinel_is_none_not_top() {
// Codex #550 P2: NiblePath::EMPTY (depth 0, the "no route" sentinel) has
// parent() == None like a real root, but it is NOT a top-tier basin — it
// has no basin at all. It must read as None (unresolved), not Some(Top),
// so the no-route fallback is preserved.
let mut soa = sample();
soa.paths[4] = Some(NiblePath::EMPTY); // depth-0 sentinel
assert_eq!(
memberof(&soa, 4),
None,
"EMPTY (depth 0) ⇒ None (unresolved), never Top"
);
// root(>=16) also yields EMPTY → same no-route classification.
soa.paths[4] = Some(NiblePath::root(16));
assert_eq!(memberof(&soa, 4), None);
}

#[test]
fn members_memberof_are_key_only_no_value_decode() {
// F2: navigating the virtual basin tree must never touch the value slab.
Expand Down
4 changes: 4 additions & 0 deletions crates/perturbation-sim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,7 @@ path = "examples/inertia_ingest.rs"
[[example]]
name = "basin_placement_learning"
path = "examples/basin_placement_learning.rs"

[[example]]
name = "outage_over_hhtl_hops"
path = "examples/outage_over_hhtl_hops.rs"
Loading
Loading