feat(vocab): GlossaryTerm alignment + typed relations — vocabulary as governance substrate (task #13) - #250
Merged
Merged
Conversation
… governance substrate (task #13) Language regulates state, so an approved term must be usable to reason about governance: CAPTURED (ontology class) + VECTOR-ALIGNED (NP↔VP link in the sovereign 768 space) + IMPLEMENTED (estate entity/service). Extends the existing GlossaryTerm (optional, backward- compatible) with partOfSpeech (NP/VP, Tesnière), status, a 3-method alignment block, and typed relations over a CLOSED RDF/RDFS/SKOS/FOAF predicate set (is-type/has-type, is-a, has-a, is-member/has-member, skos:broader/narrower/related, foaf:member, has-datatype). Fail-closed drift-guard (validate_glossary_alignment_examples.py): an approved term missing any alignment method is a governance hole; NP→entity, VP→action/service; vector links reciprocal; relation inverse-pairs reciprocate; skos:related symmetric; is-a subsumption ACYCLIC (so a reasoner can derive dependencies+constraints). Teeth-verified (approve-unaligned, broken reciprocity, broken symmetry, is-a cycle all fail). Dogfood: the draft example is SP-GATE-004's release_gates.* new vocab, unaligned. make validate ok; dup-$id 345. Follow-ups: LSA↔LDA currency detection; agreement test vs the blast-radius graph + neurosymbolic domain.
There was a problem hiding this comment.
Pull request overview
Extends the SourceOS spec’s GlossaryTerm schema and fixtures to support “alignment” (ontology class ref, pinned embedding-space vector link, estate binding) and a closed, typed relations predicate set, with a new validator + Makefile target intended to fail closed for approved terms.
Changes:
- Add
partOfSpeech,status,alignment, andrelationstoschemas/GlossaryTerm.json. - Add
tools/validate_glossary_alignment_examples.pyplus example fixtures and negative vectors for schema conformance. - Wire the new validator into
make validateand add a short normative contract note (specs/glossary-alignment-contract.md) and changelog entry.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/validate_glossary_alignment_examples.py | Adds glossary alignment/relation invariants validator (fail-closed gating for approved). |
| specs/glossary-alignment-contract.md | Documents the glossary alignment + typed relations contract (v0.1). |
| schemas/GlossaryTerm.json | Extends GlossaryTerm with alignment fields and closed typed relations. |
| Makefile | Adds validate-glossary-alignment-examples and runs it under make validate. |
| fixtures/glossary-alignment/conformance.json | Adds negative vectors for schema keyword failures. |
| examples/glossary_term.vp_action.json | Adds an approved VP example with full alignment + relations. |
| examples/glossary_term.np_entity.json | Adds an approved NP example with full alignment + relations. |
| examples/glossary_term.draft_unaligned.json | Adds a draft example with explicitly-null alignment methods. |
| CHANGELOG.md | Documents the new glossary alignment v0.1 capability and validator. |
Comment on lines
+62
to
+70
| CHECKS[f"aligned:{name}"] = True | ||
| # NP→entity, VP→action|service | ||
| kind = a["estateBinding"]["kind"] | ||
| if pos == "noun-phrase" and kind != "entity": | ||
| FAILURES.append(f"{name}: an NP term must bind to an entity, not {kind!r}") | ||
| elif pos == "verb-phrase" and kind not in ("action", "service"): | ||
| FAILURES.append(f"{name}: a VP term must bind to an action/service, not {kind!r}") | ||
| else: | ||
| CHECKS[f"pos-binding:{name}"] = True |
Comment on lines
+71
to
+79
| # vector link must be reciprocal (a relation, not a one-sided claim) | ||
| peer = by_id.get(a["vectorLink"]["peerRef"]) | ||
| if peer is not None: | ||
| back = ((peer.get("alignment") or {}).get("vectorLink") or {}).get("peerRef") | ||
| if back != t["id"]: | ||
| FAILURES.append(f"{name}: vectorLink to {a['vectorLink']['peerRef']} is not reciprocated " | ||
| f"(peer links back to {back!r}) — a link is a relation, not a claim") | ||
| else: | ||
| CHECKS[f"vector-reciprocal:{name}"] = True |
| @@ -0,0 +1,150 @@ | |||
| { | |||
| "description": "Negative vectors for GlossaryTerm alignment v0.1. Each MUST fail on its named failValidator; validate_glossary_alignment_examples.py enforces both, plus the fail-closed invariant that an APPROVED term is fully aligned across all three methods and NP↔entity / VP↔action.", | |||
mdheller
added a commit
that referenced
this pull request
Aug 2, 2026
…side governance (task #14) (#251) * feat(data): DataClass (OntoDT/OntoDQ) + TF-Lattice classifier — data-side governance (task #14) The data-side counterpart to the glossary (biz-side, #250). A DataClass binds, fail-closed: OntoDT datatype-ontology class (capture) + business GlossaryTerm (biz↔data) + ValidValues domain (enum/range/regex) + an optional TF-Lattice wide-and-deep classifier that ASSIGNS the class by inference (OntoDQ) and is a first-class CATALOGED model — modelRef→ModelManifest, runRef→RunRecord, compute on Ray/TritFabric, monotonicFeatures lattice constraint, labels that are GlossaryTerm URNs (assigned in the glossary). EntityField gains an optional dataClassRef. Drift-guard (validate_data_class_examples.py, -resolved via a referencing registry): ontological typing + glossary link + domain required; classifier labels are glossary terms, model is cataloged, compute is ray/tritfabric; a field bound to a DataClass must share its domain kind. 4 negative vectors; teeth-verified (bad-label, kind-mismatch). make validate ok; dup-$id 346. Ties biz-glossary #250 ↔ DataClass ↔ EntityField ↔ model catalog ↔ Ray/TritFabric runs. * feat(data): two-level classifier — per-class LOGISTIC + per-table SOFTMAX (LSA + doc2vec) Per Charles: each class needs an individually-testable classifier, and each table needs a softmax aligning a LSA bag-of-words embedding and a doc2vec sentence-encoder (the n-ary logit→class examples). - DataClass.classifier is now the PER-CLASS head: head=logistic (one-vs-rest, binary) + a REQUIRED evalRunRef (the individual per-class test) + threshold. A class with no eval run is untestable and refused. - New TableClassifier: per-table head=softmax (n-ary), embeddings MUST include BOTH lsa-bag-of-words AND doc2vec-sentence-encoder, a cataloged ModelManifest with a run on Ray/TritFabric, assignsClasses = the N DataClasses. - Validator enforces both + 2 new negative vectors. Teeth-verified (missing-doc2vec, missing-evalRunRef). make validate ok; dup-$id 347. * fix(data): address Copilot review on DataClass (#251) - DataClass.classifier now REQUIRES runRef + compute and both are non-null — a classifier is a fully cataloged model with a run on ray/tritfabric, not a partial block (fail-closed intent). - EntityField: allOf if/then — dataClassRef present ⇒ validValues required, so schema-only validators also catch a field bound to a class without a declared domain. - validate_data_class_examples.py: validate each collection against its INTENDED schema explicitly (never pick schema from the instance's own type — a mistyped doc could validate against the wrong schema). - spec: reword 'binds four things, fail-closed if any missing' → three required + an optional fourth (assignment), matching the schema/validator. make validate ok; dup-$id 347. * fix(data): harden classifier validator — independent runRef check + type-guards (Copilot #251) check_classifier now verifies classifier.runRef is a RunRecord URN independently (not just via the schema pattern), consistent with how it checks modelRef, and guards against a non-dict classifier/compute so a prior schema failure can't crash the validator. check_table_classifiers skips non-dict embedding entries. The other four review items were already resolved in earlier remediation (validate-by-intended-schema, schema requires runRef+compute, EntityField if/then dataClassRef=>validValues, spec reworded 'three + optional fourth'). Teeth-verified.
mdheller
added a commit
that referenced
this pull request
Aug 2, 2026
…output + guard filter - promote() now requires vectorLink.cosine (number in [-1,1], schema-required) AND validates the minted approved term against GlossaryTerm.json — it can never produce a schema-invalid approved term (fail-closed on the output, not just the alignment content). - the #250-guard teeth keyed the terms dict by 'approved'/'peer', but check_alignment prefixes messages with the dict key, so a real failure (e.g. non-reciprocal) whose message lacked the term id could slip the filter. Now keyed by id; filter catches any failure prefixed with the id. - added teeth: missing-cosine refused + a regression test proving the #250-guard filter catches a holey approved term. 9 teeth total.
mdheller
added a commit
that referenced
this pull request
Aug 2, 2026
…od alignment pass (task #13) (#258) * feat(vocab): governed draft->approved glossary promotion — the 3-method alignment pass (task #13) Closes the vocabulary lifecycle. tools/promote_glossary_term.py promotes a draft GlossaryTerm to approved ONLY when the 3-method alignment holds as a fail-closed MEET: capture (ontologyClassRef) AND vector-align (vectorLink pinned to the sovereign nomic/768 space AND reciprocated by the named peer) AND implement (estateBinding entity/service/action). It recomputes the meet (never trusts a declared flag), refuses on any missing/non-reciprocal/off-space method (term stays draft — no governance hole), and its approved output PASSES the #250 alignment drift-guard by construction. validate-glossary-promotion (in make validate) teeth: full alignment promotes; missing-implement, non-reciprocal peer, and off-sovereign-space embedding are each refused; promoted output passes the reused #250 check_alignment. Example: governed-loop <-> operational-dag reciprocal pair. * fix(vocab): guard promotion input — refuse non-term + already-approved (own review) promote() now refuses a non-GlossaryTerm input and an already-approved term (no silent mutation), and uses .get('id') so malformed input can't KeyError. Two teeth added; 7 total. * fix(vocab): remediate Copilot review on #258 — cosine + schema-valid output + guard filter - promote() now requires vectorLink.cosine (number in [-1,1], schema-required) AND validates the minted approved term against GlossaryTerm.json — it can never produce a schema-invalid approved term (fail-closed on the output, not just the alignment content). - the #250-guard teeth keyed the terms dict by 'approved'/'peer', but check_alignment prefixes messages with the dict key, so a real failure (e.g. non-reciprocal) whose message lacked the term id could slip the filter. Now keyed by id; filter catches any failure prefixed with the id. - added teeth: missing-cosine refused + a regression test proving the #250-guard filter catches a holey approved term. 9 teeth total.
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.
Why (doctrine)
Language establishes meaning and regulates state — so if the vocabulary doesn't faithfully represent the estate and we can't validate its capture, currency, and implementation, we can't even reason about the state of governance. This is the drift-guard doctrine applied to language itself.
What
Extends the existing
GlossaryTerm(optional, backward-compatible) with:partOfSpeech(noun-phrase / verb-phrase — Tesnière: NP=entity, VP=action) +status.alignment: (1)ontologyClassRef— formal ontology class; (2)vectorLink— an NP↔VP link in the sovereign 768 space (model+dimension pinned toEmbeddingRequest); (3)estateBinding— a real estate entity/service.relationsover a closed RDF/RDFS/SKOS/FOAF predicate set (is-type/has-type,is-a,has-a,is-member/has-member,skos:broader/narrower/related,foaf:member,has-datatype).Fail-closed drift-guard (the reasoner substrate)
An approved term must be captured + vector-aligned + implemented (NP→entity, VP→action/service) or it's a governance hole; vector links must be reciprocal; relation inverse-pairs reciprocate;
skos:relatedis symmetric;is-asubsumption is acyclic — so a reasoner can derive dependencies + constraints. Teeth-verified (approve-unaligned / broken-reciprocity / broken-symmetry / is-a-cycle all fail).make validateok.Dogfood: the draft example is SP-GATE-004's
release_gates.*new vocab — unaligned, exactly the divergence the loop must surface.Follow-ups (queued)
Not auto-merging — for review.