ogar-loco: VocabularyRegistry — plug-and-play vocabularies, USB-shaped - #254
Merged
Conversation
The plug-and-play pattern ogar-vocab and lance-graph-contract already use (classid prefix -> resolve), one level down: a classid now selects a *semantic table*, not just a domain tag, so a consumer routes stored function nodes without ever branching on which vocabulary they came from. The USB handshake, made typed: - Enumeration IS validation. `plug` accepts only a CheckedVocabulary, so a device that has not passed conformance cannot reach the port and the hub can never route to an unproven table. - The descriptor IS the classid. `resolve_classid` reads the hi u16 (concept, canon-high per D-CLASSID-CANON-HIGH-FLIP) and ignores the lo u16 — two apps with different render skins share one semantics. - What is stored is data, not a driver: registration copies the composed VocabularyTable (R4), so no trait objects, no lifetimes back into the vocabulary crate, and unplugging that crate cannot invalidate the table. - A contested concept is refused loudly (RegistryError::ConceptTaken), never last-write-wins — two crates claiming one concept must surface at boot, not at read time. Each vocabulary crate now ships its own `plug_into(&mut registry)`: ogar-blockly plugs the Blocks *content* concept (Inventory rows are registry entries, not bodies, so they carry no call vocabulary); ogar-ro plugs the relation-body concept. A consumer (blockly-rs, lance-graph) builds ONE hub at boot from whatever crates it deps. Falsified across crates in ogar-ro/tests/plug_and_play.rs: the same FnIndex resolves to a covered predicate under one classid and refuses under the other; the shared core stays byte-identical across every plugged device (anti-vacuity anchored on ADD/IF_ELSE); an unplugged concept resolves to None rather than a default; a double-plug is refused and the first device keeps its port.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d321178f-c1d1-4a73-9056-8c0e3b6d2187) |
AdaWorldAPI
marked this pull request as ready for review
August 7, 2026 11:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
ogar-locothe plug-and-play patternogar-vocabandlance-graph-contractalready use — classid prefix → resolve — one level down: a classid now selects a semantic table, not just a domain tag, so a consumer routes stored function nodes without ever branching on which vocabulary produced them.The USB handshake, made typed
plugaccepts only aCheckedVocabulary— a device that hasn't passedconformance::validatecannot reach the port, so the hub can never route to an unproven table. No "register now, validate later" path exists.resolve_classidreads the hi u16 (concept, canon-high perD-CLASSID-CANON-HIGH-FLIP) and ignores the lo u16 — two apps with different render skins share one semantics.VocabularyTable(the R4 data-first artifact). No trait objects, no lifetimes back into the vocabulary crate, no generics on the registry type — unplugging the crate that registered it cannot invalidate the table.RegistryError::ConceptTaken), never last-write-wins. Two crates claiming one concept must surface at boot, not at read time.Each device ships its own plug
ogar_blockly::plug_intoregisters the Blocks content concept —Inventoryrows are registry entries, not function bodies, so they deliberately carry no call vocabulary.ogar_ro::plug_intoregisters the relation-body concept. A consumer (blockly-rs, lance-graph) builds ONE hub at boot from whatever crates it deps:Falsified across crates
crates/ogar-ro/tests/plug_and_play.rsbuilds exactly that boot sequence and proves:FnIndexresolves to a covered predicate under one classid and refuses under the other — routing by classid is doing real work;ADD/IF_ELSEso two empty tables couldn't pass;Nonerather than a default — fail-closed, including the deliberately-unpluggedInventoryconcept;Verification
cargo test -p ogar-loco -p ogar-ro -p ogar-blockly— 64 green (3 new registry unit tests + 4 new cross-crate integration tests)cargo clippy --all-targets -- -D warnings— cleanRUSTDOCFLAGS="-D warnings" cargo doc --no-deps— cleancargo fmt— cleanGenerated by Claude Code