Skip to content

basin-IS-a-node: members/memberof navigation + GUID self-routing + field-perturbation probe#549

Merged
AdaWorldAPI merged 6 commits into
mainfrom
claude/edge-distance-basin-node-epiphany
Jun 19, 2026
Merged

basin-IS-a-node: members/memberof navigation + GUID self-routing + field-perturbation probe#549
AdaWorldAPI merged 6 commits into
mainfrom
claude/edge-distance-basin-node-epiphany

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the edge-distance / basin-node arc. The result: the substrate is a virtual tree of MailboxSoAs, navigated by pure key arithmetic — with no ownership restructure. A basin IS a node; the tree is the radix trie of the GUID keys; parent↔children is two prefix functions over the flat SoA. The zero-copy / Lance-tombstone invariant is untouched.

Code (lance-graph core — graph::mailbox_scan)

  • members(basin) (one-to-many) — the direct child nodes one HHTL tier down (is_ancestor_of + depth).
  • memberof(node) -> Option<BasinOf> (many-to-one) — the parent basin via NiblePath::parent:
    • BasinOf::Local(row) — parent materialized in this mailbox;
    • BasinOf::Route(NiblePath) — parent in another shard, addressed by its HHTL prefix (the prefix IS the route key — no coarse-fingerprint table);
    • None — only at the top tier (a top basin has no parent).
  • members/memberof are inverses. All pure key arithmetic, zero value decode (F2-guarded). 5 new tests; 16/16 mailbox_scan tests green; clippy clean.

Probe (perturbation-sim — examples/basin_placement_learning.rs)

Tests the one CONJECTURE left in E-BASIN-IS-A-NODE (field-perturbation learns placement). The spectral perturbation already shipped (hhtl_keys = recursive Cheeger/Fiedler bisection = the dominant Laplacian perturbation eigenmode per tier) used as the basin placement, scored by the exact node_distance(PrefixDepth) tree-hop.

grid: 4 communities × 8 nodes, 76 similar pairs
  perturbation-derived placement: mean tree-hop 1.00
  random placement              : 4.13
  improvement                   : 75.8%  (gate >= 15%, asserts)

Green → promotes the mechanism CONJECTURE → measured FINDING [G]. The full online iterative learner stays future work; this proves its precondition. Zero-dep (SplitMix64), deterministic.

Epiphanies (the arc)

  • E-BASIN-IS-A-NODE — basin = node; distance is implicit as hop count = the already-wired node_distance(PrefixDepth); the 4-ary basin fan-out IS the Morton tile pyramid, so the mailbox distribution is a perturbation-learnable field.
  • E-FAMILY-NODE-IS-META-AWARENESS — the parent node IS the coarse Walsh band of its subtree, so meta-awareness is structural (a parent), not a new SoA column.
  • E-GUID-SELF-ROUTES-THE-BASIN-TREE — HHTL-tier truncation of the GUID gives every ancestor's route key; memberof needs no coarse-fingerprint table.

Capstone: one 512-byte key, read five ways — representation / ontology / compute (Morton pyramid) / learning / meta-awareness — four of the five are key-resident, zero value decode.

Deferred

  • Full online iterative placement learner (inject delta → minimise cascade surprise → re-place).
  • memberof cross-shard row-fetch via a path→row index (the route key is returned today; the fetch is the consumer's).
  • CHAODA reclassified as a unary node_anomaly (out of DistanceMeans); helix/PqAdc value-tier means.

Board hygiene

PR_ARC_INVENTORY.md + LATEST_STATE.md updated in-branch (per the Mandatory Board-Hygiene Rule).

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added graph navigation functions for querying parent-child relationships in hierarchical structures.
    • New example program for learning-based node placement strategies.
  • Documentation

    • Updated internal project notes with design decisions and architectural updates.

claude added 6 commits June 19, 2026 12:30
…istance, Morton-pyramid perturbation field

A basin IS a GUID-keyed Node owning a MailboxSoA of its members; the
substrate becomes a tree of MailboxSoAs (= E-PANCAKES radix subtree made
physical). Distance is implicit as hop count = the already-wired
node_distance(PrefixDepth) tree-hop metric [G]. The 4-ary basin fan-out
IS the Morton tile pyramid (quadtree subdivision = HHTL nibble-interleave),
so mailbox distribution is modeled by perturbation-sim's L1-L4 cascade and
becomes a field perturbation-learning surface. Out-family slot resolution
subsumes the operator's 3 options: ClassView inheritance (1+2) picks the
sibling basin-node; global edge (3) = basin-tree ref-escape walk, no
16-byte-block widening.

SoA-ownership recursion graded CONJECTURE (deserves a 5+3 before wiring);
distance=hop=PrefixDepth identity is FINDING [G]; field-perturbation-
learning needs a probe before promotion. CHAODA reclassified as unary
node_anomaly, not a pairwise DistanceMeans.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
…oarse Walsh band of its members

In a Morton/Walsh tile pyramid the parent tile is the low-pass downsample
(coarse Walsh band) of its 4 children. E-BASIN-IS-A-NODE made the basin
the parent node in that pyramid, so a family/basin node structurally
carries the coarse-band summary of its members' field in its own value =
walsh_pyramid_energy coarse fraction = the per-basin free-energy proxy
(E-WHT-META-AWARENESS Claim 1). Meta-awareness is therefore not a new SoA
column or service — it is what a family node already IS by sitting one
pyramid level above its mailbox. Recursion: the root node is global
meta-awareness; surprise is visible at the parent without a member sweep.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
… navigation

Realizes basin-IS-a-node (E-BASIN-IS-A-NODE) as virtual tree navigation over
the flat MailboxSoA — no ownership change, no SoA restructure, zero-copy
invariant untouched. Both are pure key arithmetic, zero value decode:

- members(basin_row): the direct child nodes one HHTL tier down
  (is_ancestor_of + depth check) — one-to-many.
- memberof(member_row): the parent basin via NiblePath::parent — many-to-one;
  None at the top tier or when the parent lives in another shard (resolve via
  the coarse router).

They are inverses: every r in members(b) has memberof(r) == b. 5 new tests
(direct-children, parent + inverse property, top-tier None, cross-shard None,
F2 zero-value-decode guard). 15/15 mailbox_scan tests pass; clippy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
…es the basin tree

E-GUID-SELF-ROUTES-THE-BASIN-TREE: the HHTL nibbles are already in the GUID
(classid·HEEL·HIP·TWIG), so the parent basin's address is HHTL-tier truncation
of the child's own key (NiblePath::parent / from_guid_prefix). That prefix IS
the shard/route key (E-COARSE-QUANTIZER) — no separate coarse-fingerprint table.

memberof now returns Option<BasinOf>:
- Local(row)  — parent materialized in this mailbox;
- Route(path) — parent in another shard, addressed by its HHTL prefix (route it);
- None        — only at the top tier (a top basin has no parent).

An unmaterialized parent is a Route, not an absence: the GUID self-routes, so
the entire ancestor chain's addresses derive from one key by truncation, zero
lookups for addresses. 16/16 mailbox_scan tests pass (new: routes-when-parent-
in-another-shard); clippy clean. Epiphany prepended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
…in tree (green)

Tests the one CONJECTURE left in E-BASIN-IS-A-NODE: that the Morton-pyramid
distribution is perturbation-learnable. Minimal falsifiable form — the spectral
perturbation already shipped (hhtl_keys = recursive Cheeger/Fiedler bisection,
the dominant Laplacian perturbation eigenmode per tier) used AS the basin
placement, measured by the exact node_distance(PrefixDepth) tree-hop metric.

Result on a planted-community grid (4×8 nodes, 76 similar pairs):
  perturbation-derived placement: mean tree-hop 1.00 over similar pairs
  random placement              : 4.13
  improvement                   : 75.8% (gate >= 15%, asserts)

Promotes the mechanism CONJECTURE -> measured FINDING [G]: the field
perturbation finds a placement that clusters similar items at far lower hop
than random. The full online iterative learner stays future work; this proves
its precondition. Zero-dep (SplitMix64), deterministic; clippy + fmt clean.
Epiphany updated with the probe result.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
Board-hygiene prepend for the members/memberof navigation + GUID-self-routing
+ field-perturbation probe + three epiphanies (E-BASIN-IS-A-NODE,
E-FAMILY-NODE-IS-META-AWARENESS, E-GUID-SELF-ROUTES-THE-BASIN-TREE).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds members, memberof, and the BasinOf enum to crates/lance-graph/src/graph/mailbox_scan.rs, implementing one-to-many and many-to-one HHTL basin-tree navigation. Adds a basin_placement_learning perturbation probe example asserting ≥15% placement improvement over random. Internal board notes document corresponding epiphanies and arc state.

Changes

Basin Navigation and Placement Probe

Layer / File(s) Summary
BasinOf enum, members, memberof, and tests
crates/lance-graph/src/graph/mailbox_scan.rs
Adds BasinOf { Local(NodeMatch), Route(NiblePath) }, members (enumerates one-tier-down children via HHTL ancestry checks), and memberof (resolves a node's parent basin to a local row or a routed HHTL prefix). Four new unit tests cover child enumeration, members/memberof inversion, routed parent, and key-only access guard.
Basin placement learning probe
crates/perturbation-sim/Cargo.toml, crates/perturbation-sim/examples/basin_placement_learning.rs
Registers and implements a new example that builds a planted-community graph, runs perturbation-derived HHTL placement and a deterministic random baseline using a zero-dependency SplitMix64 PRNG, computes mean tree-hop distances, and asserts perturbation wins with ≥15% improvement.

Internal Dev-Board Notes

Layer / File(s) Summary
Epiphanies, latest state, and arc inventory
.claude/board/EPIPHANIES.md, .claude/board/LATEST_STATE.md, .claude/board/PR_ARC_INVENTORY.md
Appends June 19 epiphanies (truncation-is-route identity, basin meta-awareness, unified basin-node model with proposed wiring), a new IN PR entry for the branch, and a PR arc inventory entry with locked invariants and deferred follow-ups.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • AdaWorldAPI/lance-graph#544: Directly scaffolds the mailbox_scan.rs HHTL-keyed, zero-decode routing infrastructure upon which the new members/memberof/BasinOf navigation is built.

Poem

🐇 Hop, hop, hop through the basin tree,
Each nibble a route — no table for me!
members descends, memberof climbs back,
Perturbation beats random — right on track!
The substrate's a tree of mailboxes bright,
Basin-is-a-node, and everything's right. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely summarizes the three main contributions: basin-as-node model, members/memberof navigation, GUID self-routing, and field-perturbation probe validation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 839c4a953a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

/// - `None` — only at the top tier (`parent() == None`, the basin/DOLCE top facet
/// has no parent).
pub fn memberof<V: MailboxSoaView>(view: &V, member_row: usize) -> Option<BasinOf> {
let parent = view.hhtl_path_at(member_row)?.parent()?;

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 Distinguish missing HHTL paths from top-tier basins

When a view uses the documented deferred-binding behavior for MailboxSoaView::hhtl_path_at and returns None, this ? makes memberof return the same None used for a real top-tier basin. That contradicts the new API contract that None means only parent() == None, and consumers cannot tell “no path materialized; fall back” from “this node has no parent,” so rows with missing HHTL paths will silently stop routing instead of being handled as unresolved.

Useful? React with 👍 / 👎.

@AdaWorldAPI AdaWorldAPI merged commit 6e93dd1 into main Jun 19, 2026
5 of 6 checks passed
AdaWorldAPI added a commit that referenced this pull request Jun 19, 2026
…outage-probe

basin-node follow-up: codex #549 P2 (memberof Top vs unresolved) + outage-over-HHTL probe (corrects E-BASIN-IS-A-NODE)
AdaWorldAPI pushed a commit that referenced this pull request Jun 19, 2026
…erit are the same members/memberof primitive (#545..#551)

Operator nudge (2026-06-19): "the family nodes introduced in lance-graph
545..551 could serve as mixin — group.memberof/members where group is
the mixin node."

This RESOLVES a divergence I flagged wrong earlier this session. When
asked whether the Rails spine could verify Odoo AR-shapedness, I said
yes but called Odoo's _inherit "a non-AR shape with no Rails analog."
That was wrong: the Rails analog is include (concerns), and BOTH lower
to the family-node members/memberof primitive from #549
(graph::mailbox_scan::{members, memberof, BasinOf}). A mixin IS a
family/group node; include/_inherit IS the memberof edge.

New surface:
- mixin_members(triples, ns, is_rails) -> BTreeMap<group, BTreeSet<member>>
  Reads includes_module (Rails) or inherits_from (Odoo), ns-strips,
  returns the `members` direction (memberof is the transpose).
- shared_mixin_groups(members, min) -> Vec<group>
  The ≥2-member fan-out filter: a group shared by ≥2 classes is a
  genuine mixin; a single-member group is an STI base / model
  extension, not a mixin. Same distinction members(basin) draws in #549.

Grounded in the harvest (not asserted):
- OSB carries 37 includes_module triples (Client→PublicActivity::Model,
  Estimate→Trackstamps/DateFormats).
- Odoo carries 166 inherits_from triples; mail_thread is a group node
  with 70+ members (sale_order, account_account, purchase_order, ...).
  account_move rides mail_activity_mixin + sequence_mixin, NOT
  mail_thread directly — the test preserves the harvest's distinction.
- Cross-curator semantic convergence: OSB PublicActivity::Model
  (activity tracking) ≈ Odoo mail_thread / mail_activity_mixin. Both
  curators independently grew an activity mixin group.

4 tests, all green:
- odoo_mail_thread_is_a_family_group_node_with_many_members
- osb_rails_public_activity_model_is_a_family_group_node
- rails_include_and_odoo_inherit_are_the_same_family_node_primitive
  (the divergence-resolution test)
- single_member_extension_is_not_a_mixin_group (fan-out honesty)

Plus all 31 prior tests still green → 35/35 total. ar_shape clippy-clean.

The lesson: an apparent "Odoo non-AR divergence" should first be checked
against the lance-graph substrate primitives (#545..#551 members/memberof,
the family-node tree) before being called a divergence — the substrate
already had the home for it. The mixin group node carries shared behaviour
down to members, which is E-FAMILY-NODE-IS-META-AWARENESS instantiated for
ERP mixins (parent = coarse summary members inherit).

EPIPHANIES E-OGAR-AR-SHAPE-SMOKE-6 prepended (includes the correction of
my earlier wrong claim).

Cross-refs:
- E-BASIN-IS-A-NODE + E-FAMILY-NODE-IS-META-AWARENESS +
  E-GUID-SELF-ROUTES-THE-BASIN-TREE (the #545..#551 family-node arc)
- graph::mailbox_scan::{members, memberof} (#549 substrate primitive)
- E-OGAR-AR-SHAPE-SMOKE-5 (the concept-edge AST test; mixin membership
  is the inheritance-edge complement to the composition-edge graph)
- AdaWorldAPI/OGAR project_actor (STI-collapse used the same shape)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
AdaWorldAPI pushed a commit that referenced this pull request Jun 19, 2026
…erit are the same members/memberof primitive (#545..#551)

Operator nudge (2026-06-19): "the family nodes introduced in lance-graph
545..551 could serve as mixin — group.memberof/members where group is
the mixin node."

This RESOLVES a divergence I flagged wrong earlier this session. When
asked whether the Rails spine could verify Odoo AR-shapedness, I said
yes but called Odoo's _inherit "a non-AR shape with no Rails analog."
That was wrong: the Rails analog is include (concerns), and BOTH lower
to the family-node members/memberof primitive from #549
(graph::mailbox_scan::{members, memberof, BasinOf}). A mixin IS a
family/group node; include/_inherit IS the memberof edge.

New surface:
- mixin_members(triples, ns, is_rails) -> BTreeMap<group, BTreeSet<member>>
  Reads includes_module (Rails) or inherits_from (Odoo), ns-strips,
  returns the `members` direction (memberof is the transpose).
- shared_mixin_groups(members, min) -> Vec<group>
  The ≥2-member fan-out filter: a group shared by ≥2 classes is a
  genuine mixin; a single-member group is an STI base / model
  extension, not a mixin. Same distinction members(basin) draws in #549.

Grounded in the harvest (not asserted):
- OSB carries 37 includes_module triples (Client→PublicActivity::Model,
  Estimate→Trackstamps/DateFormats).
- Odoo carries 166 inherits_from triples; mail_thread is a group node
  with 70+ members (sale_order, account_account, purchase_order, ...).
  account_move rides mail_activity_mixin + sequence_mixin, NOT
  mail_thread directly — the test preserves the harvest's distinction.
- Cross-curator semantic convergence: OSB PublicActivity::Model
  (activity tracking) ≈ Odoo mail_thread / mail_activity_mixin. Both
  curators independently grew an activity mixin group.

4 tests, all green:
- odoo_mail_thread_is_a_family_group_node_with_many_members
- osb_rails_public_activity_model_is_a_family_group_node
- rails_include_and_odoo_inherit_are_the_same_family_node_primitive
  (the divergence-resolution test)
- single_member_extension_is_not_a_mixin_group (fan-out honesty)

Plus all 31 prior tests still green → 35/35 total. ar_shape clippy-clean.

The lesson: an apparent "Odoo non-AR divergence" should first be checked
against the lance-graph substrate primitives (#545..#551 members/memberof,
the family-node tree) before being called a divergence — the substrate
already had the home for it. The mixin group node carries shared behaviour
down to members, which is E-FAMILY-NODE-IS-META-AWARENESS instantiated for
ERP mixins (parent = coarse summary members inherit).

EPIPHANIES E-OGAR-AR-SHAPE-SMOKE-6 prepended (includes the correction of
my earlier wrong claim).

Cross-refs:
- E-BASIN-IS-A-NODE + E-FAMILY-NODE-IS-META-AWARENESS +
  E-GUID-SELF-ROUTES-THE-BASIN-TREE (the #545..#551 family-node arc)
- graph::mailbox_scan::{members, memberof} (#549 substrate primitive)
- E-OGAR-AR-SHAPE-SMOKE-5 (the concept-edge AST test; mixin membership
  is the inheritance-edge complement to the composition-edge graph)
- AdaWorldAPI/OGAR project_actor (STI-collapse used the same shape)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
AdaWorldAPI pushed a commit that referenced this pull request Jun 20, 2026
…erit are the same members/memberof primitive (#545..#551)

Operator nudge (2026-06-19): "the family nodes introduced in lance-graph
545..551 could serve as mixin — group.memberof/members where group is
the mixin node."

This RESOLVES a divergence I flagged wrong earlier this session. When
asked whether the Rails spine could verify Odoo AR-shapedness, I said
yes but called Odoo's _inherit "a non-AR shape with no Rails analog."
That was wrong: the Rails analog is include (concerns), and BOTH lower
to the family-node members/memberof primitive from #549
(graph::mailbox_scan::{members, memberof, BasinOf}). A mixin IS a
family/group node; include/_inherit IS the memberof edge.

New surface:
- mixin_members(triples, ns, is_rails) -> BTreeMap<group, BTreeSet<member>>
  Reads includes_module (Rails) or inherits_from (Odoo), ns-strips,
  returns the `members` direction (memberof is the transpose).
- shared_mixin_groups(members, min) -> Vec<group>
  The ≥2-member fan-out filter: a group shared by ≥2 classes is a
  genuine mixin; a single-member group is an STI base / model
  extension, not a mixin. Same distinction members(basin) draws in #549.

Grounded in the harvest (not asserted):
- OSB carries 37 includes_module triples (Client→PublicActivity::Model,
  Estimate→Trackstamps/DateFormats).
- Odoo carries 166 inherits_from triples; mail_thread is a group node
  with 70+ members (sale_order, account_account, purchase_order, ...).
  account_move rides mail_activity_mixin + sequence_mixin, NOT
  mail_thread directly — the test preserves the harvest's distinction.
- Cross-curator semantic convergence: OSB PublicActivity::Model
  (activity tracking) ≈ Odoo mail_thread / mail_activity_mixin. Both
  curators independently grew an activity mixin group.

4 tests, all green:
- odoo_mail_thread_is_a_family_group_node_with_many_members
- osb_rails_public_activity_model_is_a_family_group_node
- rails_include_and_odoo_inherit_are_the_same_family_node_primitive
  (the divergence-resolution test)
- single_member_extension_is_not_a_mixin_group (fan-out honesty)

Plus all 31 prior tests still green → 35/35 total. ar_shape clippy-clean.

The lesson: an apparent "Odoo non-AR divergence" should first be checked
against the lance-graph substrate primitives (#545..#551 members/memberof,
the family-node tree) before being called a divergence — the substrate
already had the home for it. The mixin group node carries shared behaviour
down to members, which is E-FAMILY-NODE-IS-META-AWARENESS instantiated for
ERP mixins (parent = coarse summary members inherit).

EPIPHANIES E-OGAR-AR-SHAPE-SMOKE-6 prepended (includes the correction of
my earlier wrong claim).

Cross-refs:
- E-BASIN-IS-A-NODE + E-FAMILY-NODE-IS-META-AWARENESS +
  E-GUID-SELF-ROUTES-THE-BASIN-TREE (the #545..#551 family-node arc)
- graph::mailbox_scan::{members, memberof} (#549 substrate primitive)
- E-OGAR-AR-SHAPE-SMOKE-5 (the concept-edge AST test; mixin membership
  is the inheritance-edge complement to the composition-edge graph)
- AdaWorldAPI/OGAR project_actor (STI-collapse used the same shape)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
AdaWorldAPI pushed a commit that referenced this pull request Jun 20, 2026
…erit are the same members/memberof primitive (#545..#551)

Operator nudge (2026-06-19): "the family nodes introduced in lance-graph
545..551 could serve as mixin — group.memberof/members where group is
the mixin node."

This RESOLVES a divergence I flagged wrong earlier this session. When
asked whether the Rails spine could verify Odoo AR-shapedness, I said
yes but called Odoo's _inherit "a non-AR shape with no Rails analog."
That was wrong: the Rails analog is include (concerns), and BOTH lower
to the family-node members/memberof primitive from #549
(graph::mailbox_scan::{members, memberof, BasinOf}). A mixin IS a
family/group node; include/_inherit IS the memberof edge.

New surface:
- mixin_members(triples, ns, is_rails) -> BTreeMap<group, BTreeSet<member>>
  Reads includes_module (Rails) or inherits_from (Odoo), ns-strips,
  returns the `members` direction (memberof is the transpose).
- shared_mixin_groups(members, min) -> Vec<group>
  The ≥2-member fan-out filter: a group shared by ≥2 classes is a
  genuine mixin; a single-member group is an STI base / model
  extension, not a mixin. Same distinction members(basin) draws in #549.

Grounded in the harvest (not asserted):
- OSB carries 37 includes_module triples (Client→PublicActivity::Model,
  Estimate→Trackstamps/DateFormats).
- Odoo carries 166 inherits_from triples; mail_thread is a group node
  with 70+ members (sale_order, account_account, purchase_order, ...).
  account_move rides mail_activity_mixin + sequence_mixin, NOT
  mail_thread directly — the test preserves the harvest's distinction.
- Cross-curator semantic convergence: OSB PublicActivity::Model
  (activity tracking) ≈ Odoo mail_thread / mail_activity_mixin. Both
  curators independently grew an activity mixin group.

4 tests, all green:
- odoo_mail_thread_is_a_family_group_node_with_many_members
- osb_rails_public_activity_model_is_a_family_group_node
- rails_include_and_odoo_inherit_are_the_same_family_node_primitive
  (the divergence-resolution test)
- single_member_extension_is_not_a_mixin_group (fan-out honesty)

Plus all 31 prior tests still green → 35/35 total. ar_shape clippy-clean.

The lesson: an apparent "Odoo non-AR divergence" should first be checked
against the lance-graph substrate primitives (#545..#551 members/memberof,
the family-node tree) before being called a divergence — the substrate
already had the home for it. The mixin group node carries shared behaviour
down to members, which is E-FAMILY-NODE-IS-META-AWARENESS instantiated for
ERP mixins (parent = coarse summary members inherit).

EPIPHANIES E-OGAR-AR-SHAPE-SMOKE-6 prepended (includes the correction of
my earlier wrong claim).

Cross-refs:
- E-BASIN-IS-A-NODE + E-FAMILY-NODE-IS-META-AWARENESS +
  E-GUID-SELF-ROUTES-THE-BASIN-TREE (the #545..#551 family-node arc)
- graph::mailbox_scan::{members, memberof} (#549 substrate primitive)
- E-OGAR-AR-SHAPE-SMOKE-5 (the concept-edge AST test; mixin membership
  is the inheritance-edge complement to the composition-edge graph)
- AdaWorldAPI/OGAR project_actor (STI-collapse used the same shape)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
AdaWorldAPI pushed a commit that referenced this pull request Jun 21, 2026
…erit are the same members/memberof primitive (#545..#551)

Operator nudge (2026-06-19): "the family nodes introduced in lance-graph
545..551 could serve as mixin — group.memberof/members where group is
the mixin node."

This RESOLVES a divergence I flagged wrong earlier this session. When
asked whether the Rails spine could verify Odoo AR-shapedness, I said
yes but called Odoo's _inherit "a non-AR shape with no Rails analog."
That was wrong: the Rails analog is include (concerns), and BOTH lower
to the family-node members/memberof primitive from #549
(graph::mailbox_scan::{members, memberof, BasinOf}). A mixin IS a
family/group node; include/_inherit IS the memberof edge.

New surface:
- mixin_members(triples, ns, is_rails) -> BTreeMap<group, BTreeSet<member>>
  Reads includes_module (Rails) or inherits_from (Odoo), ns-strips,
  returns the `members` direction (memberof is the transpose).
- shared_mixin_groups(members, min) -> Vec<group>
  The ≥2-member fan-out filter: a group shared by ≥2 classes is a
  genuine mixin; a single-member group is an STI base / model
  extension, not a mixin. Same distinction members(basin) draws in #549.

Grounded in the harvest (not asserted):
- OSB carries 37 includes_module triples (Client→PublicActivity::Model,
  Estimate→Trackstamps/DateFormats).
- Odoo carries 166 inherits_from triples; mail_thread is a group node
  with 70+ members (sale_order, account_account, purchase_order, ...).
  account_move rides mail_activity_mixin + sequence_mixin, NOT
  mail_thread directly — the test preserves the harvest's distinction.
- Cross-curator semantic convergence: OSB PublicActivity::Model
  (activity tracking) ≈ Odoo mail_thread / mail_activity_mixin. Both
  curators independently grew an activity mixin group.

4 tests, all green:
- odoo_mail_thread_is_a_family_group_node_with_many_members
- osb_rails_public_activity_model_is_a_family_group_node
- rails_include_and_odoo_inherit_are_the_same_family_node_primitive
  (the divergence-resolution test)
- single_member_extension_is_not_a_mixin_group (fan-out honesty)

Plus all 31 prior tests still green → 35/35 total. ar_shape clippy-clean.

The lesson: an apparent "Odoo non-AR divergence" should first be checked
against the lance-graph substrate primitives (#545..#551 members/memberof,
the family-node tree) before being called a divergence — the substrate
already had the home for it. The mixin group node carries shared behaviour
down to members, which is E-FAMILY-NODE-IS-META-AWARENESS instantiated for
ERP mixins (parent = coarse summary members inherit).

EPIPHANIES E-OGAR-AR-SHAPE-SMOKE-6 prepended (includes the correction of
my earlier wrong claim).

Cross-refs:
- E-BASIN-IS-A-NODE + E-FAMILY-NODE-IS-META-AWARENESS +
  E-GUID-SELF-ROUTES-THE-BASIN-TREE (the #545..#551 family-node arc)
- graph::mailbox_scan::{members, memberof} (#549 substrate primitive)
- E-OGAR-AR-SHAPE-SMOKE-5 (the concept-edge AST test; mixin membership
  is the inheritance-edge complement to the composition-edge graph)
- AdaWorldAPI/OGAR project_actor (STI-collapse used the same shape)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants