Skip to content

feat(vocab): GlossaryTerm alignment + typed relations — vocabulary as governance substrate (task #13) - #250

Merged
mdheller merged 1 commit into
mainfrom
feat/glossary-term-alignment
Aug 2, 2026
Merged

feat(vocab): GlossaryTerm alignment + typed relations — vocabulary as governance substrate (task #13)#250
mdheller merged 1 commit into
mainfrom
feat/glossary-term-alignment

Conversation

@mdheller

@mdheller mdheller commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

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.
  • 3-method alignment: (1) ontologyClassRef — formal ontology class; (2) vectorLink — an NP↔VP link in the sovereign 768 space (model+dimension pinned to EmbeddingRequest); (3) estateBinding — a real estate entity/service.
  • 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 (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:related is symmetric; is-a subsumption is acyclic — so a reasoner can derive dependencies + constraints. Teeth-verified (approve-unaligned / broken-reciprocity / broken-symmetry / is-a-cycle all fail). make validate ok.

Dogfood: the draft example is SP-GATE-004's release_gates.* new vocab — unaligned, exactly the divergence the loop must surface.

Follow-ups (queued)

  • Currency: LSA↔LDA divergence (closed glossary vs open estate topics) to flag new/optimal vocab.
  • Agreement: a standard test cross-checking these relations against the governed blast-radius graph + the neurosymbolic agent's domain/symbols, with remediation automation.
  • Feature domains (from the AMG 2.0 deck): TF-Lattice wide-and-deep over feature valid-values/regex/domains + data-governance validations.
    Not auto-merging — for review.

… 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.
Copilot AI review requested due to automatic review settings August 2, 2026 19:50

Copilot AI 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.

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, and relations to schemas/GlossaryTerm.json.
  • Add tools/validate_glossary_alignment_examples.py plus example fixtures and negative vectors for schema conformance.
  • Wire the new validator into make validate and 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
mdheller merged commit 80ddb21 into main Aug 2, 2026
8 checks passed
@mdheller
mdheller deleted the feat/glossary-term-alignment branch August 2, 2026 19:54
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.
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