feat(arm-discovery): D-ARM-14 Phase 2 — aerial→hub landing + the OWL/DOLCE-domain HHTL potential#443
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR completes D-ARM-14 Phase 2 by implementing DOLCE-gated identity emission and validating proposer-to-hub landing via a gated Wikidata end-to-end test; it documents shared HHTL compartmentalization, adds an ChangesD-ARM-14 Phase 2: Landing & Compartmentalization
Sequence Diagram(s)sequenceDiagram
participant Fixture as Wikidata Fixture
participant Discovery as OntologyProjector
participant HubPrims as Hub Primitives (NiblePath/FieldMask)
participant Validator as Landing Assertions
participant NDJSON as ndjson Output
Fixture->>Discovery: corpus (WClass items, basins, nibbles, properties)
Discovery->>Discovery: extract_rules, dolce_subclass("wd:")
Discovery->>Validator: per-etype dolce_id basins
Fixture->>HubPrims: nibble_path, presence, inherit, signature
HubPrims->>Validator: landed (ClassId, StructuralSignature, FieldMask)
Validator->>NDJSON: to_ndjson(CandidateRule/CandidateTriple)
NDJSON->>Validator: contains rdfs:subClassOf
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 64fe411a4d
ℹ️ 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".
| /// with intent: a DOLCE projector's consequent category IS the `dolce_id`. | ||
| #[must_use] | ||
| pub fn from_index(category: u32) -> Option<DolceCategory> { | ||
| Self::from_basin(category as u8) |
There was a problem hiding this comment.
Reject out-of-range DOLCE indexes before casting
For callers that pass a discovery category outside 0..3, this lossy u32 -> u8 cast wraps values like 256 to 0, so from_index(256) returns Some(Endurant) instead of None. Since this helper is public and documented as the category-index decoder for the stable dolce_id, oversized/invalid category IDs can be silently routed to the wrong DOLCE basin; check the u32 range before converting to u8.
Useful? React with 👍 / 👎.
…d emit + worked Wikidata example) Answers "how to use aerial + the 10000^2 splat + land on Wikidata-shaped HHTL": builds the proposer->hub seam end-to-end, verifiable standalone. (a) The OD-DOLCE alignment #442 deferred to this lane: - OntologyProjector::dolce_id() emits the stable dolce_id u8 (= basin nibble, already matching dolce_id::{ENDURANT=0,..}) — the proposer hands the hub the enum-free routing key; the IRI becomes a late-resolvable label (resolve-through-cache). + DolceCategory::from_index, + is_dolce flag. (b) The worked end-to-end example (tests/wikidata_landing.rs, --features landing): - splat top-k -> extract_rules recovers all 6 DOLCE basins -> lands each on the REAL lance-graph-contract::class_view::FieldMask (presence) + hash::fnv1a_str (the StructuralSignature value). The 16^n NiblePath router is inlined (annotated) until #442's contract::hhtl lands on main. - CONFIRMED on data: corpus collapses 6->5 shape-families (film Q11424 ≡ tv-series Q5398426, sig 0xad7fade7); human ⊂ person inherits path + mask-as-delta; basin preserved down the subclass path. - Firewall intact: the lib never imports the hub. The example uses an opt-in dev-dep on the zero-dep lance-graph-contract (the exact pattern jc uses for bridge examples), gated behind the `landing` feature so the default build stays zero-dep. Only the (ClassId, signature, FieldMask) triple + dolce_id u8 cross the seam. Verified: default (zero-dep) 42/42 + clippy -D warnings clean; --features landing -> wikidata_landing green + clippy clean. Run: cargo test --manifest-path crates/lance-graph-arm-discovery/Cargo.toml \ --features landing --test wikidata_landing -- --nocapture Remaining (documented): the real jc/blasgraph splat producing the lists; the ndjson->WikidataClass loader; swap the inline nibble routing for contract::hhtl::NiblePath once #442 merges; gated on D-ARM-7 (jc::jirak). https://claude.ai/code/session_012SorR8UbtEvYmbX8cXftj7
…ding feature) Cargo.lock update from the D-ARM-14 Phase 2 `landing` feature's optional dev-dep on the zero-dep lance-graph-contract. Purely additive (+134 lines: contract + its serde/serde_yaml transitive locks); the default build does not pull these. https://claude.ai/code/session_012SorR8UbtEvYmbX8cXftj7
…alizes into one HHTL, fed by aerial Generalizes D-ARM-14 Phase 2: medicine (SNOMED/FMA), finance (FIBO), geography, law, Odoo, and all of Wikidata are not bespoke loaders — each yields the SAME (ClassId, StructuralSignature, FieldMask) row (basin = DOLCE dolce_id, nibble path = P279 descent, FieldMask = presence, signature = shape-family). Domain enters only as content, never structure (cognitive-risc-classes N4). aerial is the per-domain runtime feed: point it at a domain splat codebook + corpus, swap the fixture, no new hub code. - knowledge/owl-dolce-hhtl-compartments-aerial-fed.md (the map + the proof chain + the compartmentalization rule + scale-freezes) - EPIPHANIES: the generalization FINDING https://claude.ai/code/session_012SorR8UbtEvYmbX8cXftj7
There was a problem hiding this comment.
🧹 Nitpick comments (3)
.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.md (2)
45-45: ⚡ Quick winClarify the StructuralSignature description.
The table states "FNV-1a over the canonical property-id set," but context snippet 1 shows the signature is computed over a richer canonical tuple:
[kind_disc, field_hist×6, method_hist×5, has_state_machine]. While the claim "label/QID/domain-independent" is correct, "property-id set" undersells the structural inputs.Consider rephrasing to "FNV-1a over the canonical structural tuple (kind + field/method histograms + state presence)" to match the actual implementation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.md at line 45, Update the StructuralSignature description to accurately reflect the implementation: replace "FNV-1a over the canonical property-id set — label/QID/domain-independent" with something like "FNV-1a over the canonical structural tuple (kind_disc + field_hist×6 + method_hist×5 + has_state_machine) — label/QID/domain-independent" so it documents that class_signature::StructuralSignature is computed from the tuple [kind_disc, field_hist×6, method_hist×5, has_state_machine] rather than a simple property-id set.
132-132: 💤 Low valueBirthday bound approximation is slightly high.
The birthday bound for a 32-bit hash is approximately sqrt(2^32) ≈ 65,536, not ~77k. The collision probability reaches ~50% at around 77,163 hashes (using the precise formula), but the commonly cited bound is ~65k.
Consider using "~65k" for consistency with standard birthday-paradox references, or note "~77k for 50% collision probability" if using the precise calculation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.md at line 132, Update the wording around StructuralSignature being u32 to correct the birthday-bound claim: change the "~77k" figure to the standard approximation "~65k" (sqrt(2^32) ≈ 65,536) or explicitly state both values (≈65k as the rough sqrt approximation and ≈77,163 as the precise 50% collision point) so the note about potential aliasing for StructuralSignature (u32) is accurate and unambiguous.crates/lance-graph-arm-discovery/tests/wikidata_landing.rs (1)
56-75: ⚡ Quick winTechnical debt: swap inline NiblePath for contract::hhtl::NiblePath on
#442merge.The inline
np_root,np_child,np_basin,np_is_ancestorimplementations reproduce the nibble-path logic becausecontract::hhtl::NiblePathfrom#442isn't on main yet. The comment at line 12 documents the swap plan. The implementations look correct (4-bit nibble shifts at depth-dependent offsets), and this is test-only code bridging both sides of the firewall before the full API lands.Recommendation: add a tracking comment or issue referencing
#442so this swap isn't forgotten when that PR merges.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/lance-graph-arm-discovery/tests/wikidata_landing.rs` around lines 56 - 75, Add a TODO tracking comment in the test-only nibble-path implementations (np_root, np_child, np_basin, np_is_ancestor, nibble_path) that explicitly references PR `#442` and notes these inlined functions should be replaced with contract::hhtl::NiblePath once that PR is merged; include the issue/PR number, a short rationale, and an estimated follow-up (e.g., "replace with contract::hhtl::NiblePath from `#442` when merged") so the swap won't be forgotten.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In @.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.md:
- Line 45: Update the StructuralSignature description to accurately reflect the
implementation: replace "FNV-1a over the canonical property-id set —
label/QID/domain-independent" with something like "FNV-1a over the canonical
structural tuple (kind_disc + field_hist×6 + method_hist×5 + has_state_machine)
— label/QID/domain-independent" so it documents that
class_signature::StructuralSignature is computed from the tuple [kind_disc,
field_hist×6, method_hist×5, has_state_machine] rather than a simple property-id
set.
- Line 132: Update the wording around StructuralSignature being u32 to correct
the birthday-bound claim: change the "~77k" figure to the standard approximation
"~65k" (sqrt(2^32) ≈ 65,536) or explicitly state both values (≈65k as the rough
sqrt approximation and ≈77,163 as the precise 50% collision point) so the note
about potential aliasing for StructuralSignature (u32) is accurate and
unambiguous.
In `@crates/lance-graph-arm-discovery/tests/wikidata_landing.rs`:
- Around line 56-75: Add a TODO tracking comment in the test-only nibble-path
implementations (np_root, np_child, np_basin, np_is_ancestor, nibble_path) that
explicitly references PR `#442` and notes these inlined functions should be
replaced with contract::hhtl::NiblePath once that PR is merged; include the
issue/PR number, a short rationale, and an estimated follow-up (e.g., "replace
with contract::hhtl::NiblePath from `#442` when merged") so the swap won't be
forgotten.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b1c02c64-9aae-490f-976b-322fe250288b
⛔ Files ignored due to path filters (1)
crates/lance-graph-arm-discovery/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (7)
.claude/board/AGENT_LOG.md.claude/board/EPIPHANIES.md.claude/board/STATUS_BOARD.md.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.mdcrates/lance-graph-arm-discovery/Cargo.tomlcrates/lance-graph-arm-discovery/src/aerial/ontology.rscrates/lance-graph-arm-discovery/tests/wikidata_landing.rs
…:NiblePath (#442 merged) The Phase-2 worked example reproduced NiblePath's bit-shift addressing inline because contract::hhtl wasn't on main yet. #442 merged, so tests/wikidata_landing.rs now uses the REAL contract::hhtl::NiblePath::{root,child,basin,is_ancestor_of,depth} + FieldMask::inherit — the landing is on the canonical 16^n router, not a stand-in. Rebased onto post-#442 main (415971a). default 42/42 + clippy clean; --features landing wikidata_landing green (real NiblePath depths: person 0x1 d2 → human 0x12 d3; film≡tv collapse holds). https://claude.ai/code/session_012SorR8UbtEvYmbX8cXftj7
64fe411 to
04995a9
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/lance-graph-arm-discovery/tests/wikidata_landing.rs (1)
117-188: ⚖️ Poor tradeoffConsider splitting this end-to-end test into focused scenarios.
end_to_end_splat_to_wikidata_hhtlasserts several independent invariants in one body: basin recovery (Stage A/B), per-class landing, shape-family collapse, subclass path/mask/basin inheritance, and the ndjson seam. Splitting these into separate#[test]functions (sharingcorpus()/helpers) would pinpoint which invariant regressed on failure and aligns with the repo's preference for focused scenarios over broad integration tests.As per coding guidelines: "prefer focused scenarios over broad integration tests".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/lance-graph-arm-discovery/tests/wikidata_landing.rs` around lines 117 - 188, The test end_to_end_splat_to_wikidata_hhtl bundles multiple independent assertions; split it into focused #[test] functions that each cover one invariant (e.g., basin discovery test using corpus() + discover_dolce_ids for Stage A/B, per-class landing test using nibble_path/signature/presence for Stage C, shape-collapse test asserting sigs length and film/tv signatures, subclass inheritance test using nibble_path and FieldMask::from_positions, and ndjson seam test using OntologyProjector::dolce_subclass and to_ndjson). Extract the shared setup (let classes = corpus(), discovered = discover_dolce_ids(&classes), and any common logging) into a small helper used by each test so you avoid duplication, and give each new test a descriptive name (e.g., basin_recovery_from_splat, landing_preserves_basin_and_mask, shape_family_collapse, subclass_inherits_path_and_mask, ndjson_seam_contains_predicate). Ensure assertions from the original function are moved verbatim into the appropriate new test to preserve semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/lance-graph-arm-discovery/tests/wikidata_landing.rs`:
- Around line 117-188: The test end_to_end_splat_to_wikidata_hhtl bundles
multiple independent assertions; split it into focused #[test] functions that
each cover one invariant (e.g., basin discovery test using corpus() +
discover_dolce_ids for Stage A/B, per-class landing test using
nibble_path/signature/presence for Stage C, shape-collapse test asserting sigs
length and film/tv signatures, subclass inheritance test using nibble_path and
FieldMask::from_positions, and ndjson seam test using
OntologyProjector::dolce_subclass and to_ndjson). Extract the shared setup (let
classes = corpus(), discovered = discover_dolce_ids(&classes), and any common
logging) into a small helper used by each test so you avoid duplication, and
give each new test a descriptive name (e.g., basin_recovery_from_splat,
landing_preserves_basin_and_mask, shape_family_collapse,
subclass_inherits_path_and_mask, ndjson_seam_contains_predicate). Ensure
assertions from the original function are moved verbatim into the appropriate
new test to preserve semantics.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2f33bcd0-5789-4c6a-bd9b-c2d783161e79
⛔ Files ignored due to path filters (1)
crates/lance-graph-arm-discovery/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (7)
.claude/board/AGENT_LOG.md.claude/board/EPIPHANIES.md.claude/board/STATUS_BOARD.md.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.mdcrates/lance-graph-arm-discovery/Cargo.tomlcrates/lance-graph-arm-discovery/src/aerial/ontology.rscrates/lance-graph-arm-discovery/tests/wikidata_landing.rs
✅ Files skipped from review due to trivial changes (4)
- .claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.md
- .claude/board/EPIPHANIES.md
- .claude/board/AGENT_LOG.md
- .claude/board/STATUS_BOARD.md
🚧 Files skipped from review as they are similar to previous changes (2)
- crates/lance-graph-arm-discovery/Cargo.toml
- crates/lance-graph-arm-discovery/src/aerial/ontology.rs
…pick) - codex P2 (ontology.rs): DolceCategory::from_index range-checks the u32 BEFORE the u8 cast. 'category as u8' wrapped (256 → 0), so from_index(256) returned Some(Endurant) — silently routing an invalid index to a wrong DOLCE basin. Now compares in u32 first; added regression asserts (256, u32::MAX → None). - CodeRabbit nitpick (wikidata_landing.rs): split the one broad end-to-end test into 5 focused #[test]s sharing corpus()/helpers — basin_recovery_from_splat, landing_preserves_basin_and_mask, shape_family_collapse, subclass_inherits_path_and_mask, ndjson_seam_contains_predicate — so a failure names the regressed invariant (repo guideline: focused scenarios over broad integration tests). Verified: default 42/42 + clippy clean; --features landing 5/5 + clippy clean. https://claude.ai/code/session_012SorR8UbtEvYmbX8cXftj7
…perseded-by-#441 + EPIPHANY E-CHESS-IS-NOT-RETIREABLE + FINDING F-DIAGRAMS-450-CLOSES-LOOP The parallel `claude/sleepy-cori-aRK2x` + `claude/jolly-cori-clnf9` sessions shipped what my plan v1 (#440) was about to over-engineer. Reconciling my branch's audit trail with their shipped reality. STATUS_BOARD (status-flip per append-only doctrine; row content preserved as audit trail of "approach considered, not shipped"): - D-CLS-1 → Superseded (dissolved: DOLCE resolved late through cache, not consolidated; 4 enums coexist; OD-DOLCE-CANONICAL closed b31464d) - D-CLS-2 → Superseded-by-D-CLS-SIG (Rust function, not static PSV) - D-CLS-3 → Superseded-by-D-CLS-SIG (was VAPORWARE per #441 review; Aerial+ is for runtime data, not structural shapes) - D-CLS-4 → Superseded (no new crate; trait in contract + impl in ontology) - D-CLS-5 → Superseded-by-D-CLS-FM (reuses PR #437's MailboxSoaView class_id) - D-CLS-6 → Superseded (dissolved: class derived from signature(), not stored; "meta-DTO resolves; it does not store") - D-CLS-7 → Superseded-by-D-CLS-FM (FieldMask u64; position table IMPLICIT in OdooEntity.fields[] declaration order) - D-CLS-8 → Superseded-by-D-CLS-RENDER (trait method; C2 enforced by the TYPE not docstring; askama engine deferred) - D-CLS-9 → Superseded-by-D-CLS-AUDIT (falsifiable corpus-collapse; no 66-snapshot N4-freeze) D-CHESS-BRINGUP-1 unchanged (Queued); my earlier chat-statement proposing retirement was wrong and fully retracted (user: "retiring chess is incompetence"). EPIPHANIES (prepended): - F-DIAGRAMS-450-CLOSES-THE-LOOP — the two user-posted architecture diagrams (ODoo×OGIT+DOLCE+GoBD→Elixir/OTP; Dual Grammar §14) are now backed by shipped code via #450 panel-by-panel; board hygiene is training/seeding data for the panel-7 epiphany/fact/signal output loop, not human-only documentation - E-CHESS-IS-NOT-RETIREABLE-PLURAL-FALSIFIERS — retracting my retire-proposal; plural falsifiers is the doctrine (Odoo business-richness, Wikidata open-world, Chess minimal-ISA-closure, future medicine SNOMED/finance FIBO/law per #443's owl-dolce-hhtl-compartments-aerial-fed.md); each domain hits the machinery from a different angle; substitution is the anti-pattern; "we're only touching X" is the diagnostic signature classes.md F4 warned against AGENT_LOG (prepended): full reconciliation entry — rebase audit (no content deletions in any of my commits per `git show --stat`), context (PRs #441..#450), discipline correction (the "I'll discard" chat statement violated append-only as intent even though I committed everything), next steps. https://claude.ai/code/session_017gZ6sPRXYPj5n7uJ7NBtRv
Summary
D-ARM-14 Phase 2 — the proposer→hub landing, plus the documented generalization: how to feed any OWL/DOLCE Wikidata domain into the HHTL via the aerial crate. Builds on Phase 1 (#438, merged) and converges with the hub-side D-CLS arc (#441 merged, #442 open).
(1) The
dolce_idalignment #442 deferred to this laneOntologyProjector::dolce_id()now emits the stabledolce_idu8 (= the basin nibble, already matchingdolce_id::{ENDURANT=0, …}) — the proposer hands the hub the enum-free routing key, and thedolce:…IRI becomes a late-resolvable label (resolve-through-cache, per OD-DOLCE).+ DolceCategory::from_index,+ is_dolce. The firewall is untouched: aerial stays the zero-dep proposer.(2) The worked end-to-end example —
tests/wikidata_landing.rsGated
--features landing. It runs the full seam on a Wikidata-shaped fixture and lands on the real merged contract types:Splat top-k →
extract_rulesrecovers all 6 DOLCE basins → each lands on the realcontract::class_view::FieldMask(presence) +hash::fnv1a_str(theStructuralSignaturevalue). Confirmed on data:film (Q11424) ≡ tv-series (Q5398426)collapse to one signature (0xad7fade7);human ⊂ personinherits path + mask-as-delta with the basin preserved.Discipline: the aerial lib never imports the hub. The example uses an opt-in
dev-depon the zero-deplance-graph-contract(the exact patternjcuses for bridge examples), behind thelandingfeature — so the default build stays zero-dep.contract::hhtl::NiblePathisn't onmainyet (it's #442), so the 16ⁿ routing is reproduced inline and annotated — a one-line swap toNiblePath::{root,child,is_ancestor_of}once #442 merges.(3) The potential — any OWL/DOLCE domain → one HHTL, fed by aerial
.claude/knowledge/owl-dolce-hhtl-compartments-aerial-fed.md(+ EPIPHANIES FINDING): medicine (SNOMED/FMA), finance (FIBO), geography, law, Odoo, and all of Wikidata are not bespoke loaders — each yields the same(ClassId, StructuralSignature, FieldMask)row (basin = DOLCEdolce_id, nibble path = P279 descent, FieldMask = presence, signature = shape-family). Domain enters only as content, never structure (cognitive-risc-classes.mdN4). A new domain is "fed via aerial" by pointing it at a domain splat codebook + a domain corpus — swap thewikidata_landingfixture, no new hub code. The doc carries the per-layer proof chain, the compartmentalization rule (one tree axis; domain = orthogonal facet/namespace, not a second path), and the scale-freezes to watch (NiblePathdepth-16 truncation,StructuralSignatureu32 birthday bound, the DOLCE nibble/byte reconciliation).Verification
Remaining (documented)
The real jc/blasgraph splat producing the edge lists; the
ndjson → WikidataClassloader; swap the inline nibble routing forcontract::hhtl::NiblePathon #442 merge; gated on D-ARM-7 (the Jirak floor,jc::jirak) before any domain's feed writes the store.Board hygiene (same branch)
STATUS_BOARD(D-ARM-14 Phase 2),AGENT_LOG,EPIPHANIES(the OWL/DOLCE-domain generalization FINDING), and the new knowledge doc.https://claude.ai/code/session_012SorR8UbtEvYmbX8cXftj7
Generated by Claude Code
Summary by CodeRabbit
New Features
Tests
Documentation