Skip to content

feat(data): DataClass (OntoDT/OntoDQ) + TF-Lattice classifier — data-side governance (task #14) - #251

Merged
mdheller merged 4 commits into
mainfrom
feat/dataclass-ontodq
Aug 2, 2026
Merged

feat(data): DataClass (OntoDT/OntoDQ) + TF-Lattice classifier — data-side governance (task #14)#251
mdheller merged 4 commits into
mainfrom
feat/dataclass-ontodq

Conversation

@mdheller

@mdheller mdheller commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

What (data-side of the vocabulary/governance program; AMG 2.0 deck)

The data-side counterpart to the glossary (#250, biz-side). Where a GlossaryTerm says what a thing means, a DataClass says what its data is — ontologically — so data quality can be inferred and enforced, not asserted.

A DataClass binds four things, fail-closed:

  • OntoDTontologyClassRef: the datatype-ontology class (capture).
  • biz↔dataglossaryTermRef: the business GlossaryTerm it realizes.
  • domaindomain ($ref ValidValues): enum / range / regex.
  • assignment (optional) — a TF-Lattice wide-and-deep classifier that assigns the class by inference (OntoDQ), a first-class cataloged model: modelRefModelManifest, runRefRunRecord, compute.platform ∈ {ray, tritfabric}, monotonicFeatures (lattice shape constraint), labels that are GlossaryTerm URNs (labels assigned in the glossary).

EntityField gains an optional dataClassRef; the drift-guard enforces field↔class domain conformance (a field can't claim a class it doesn't fit), classifier integrity (glossary labels · cataloged model · Ray/TritFabric compute), and ontological typing. 4 negative vectors; teeth-verified (bad-label, kind-mismatch). make validate ok; dup-$id 346.

This closes the loop your last messages drew: biz glossary ↔ DataClass ↔ EntityField ↔ model catalog ↔ Ray/TritFabric runs ↔ glossary labels. Not auto-merging — for review.

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

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

Introduces a new DataClass schema and supporting fixtures/examples to formalize the data-side governance node (OntoDT/OntoDQ) and connect it to GlossaryTerm and EntityField, plus a validator + Makefile target to enforce conformance and negative controls.

Changes:

  • Added schemas/DataClass.json plus example + negative vectors, and a validator (tools/validate_data_class_examples.py) wired into make validate.
  • Extended schemas/EntityField.json with optional dataClassRef and added an EntityField example that binds to a DataClass.
  • Added initial contract documentation (specs/data-class-contract.md) and a changelog entry.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tools/validate_data_class_examples.py New validator for DataClass/EntityField examples + negative vectors and cross-binding checks.
specs/data-class-contract.md New short contract doc describing DataClass and its intended invariants.
schemas/EntityField.json Adds optional dataClassRef for binding fields to DataClass.
schemas/DataClass.json New DataClass JSON Schema including optional TF-Lattice classifier block.
Makefile Adds validate-data-class-examples and includes it in validate.
fixtures/data-class/conformance.json Adds negative vectors for DataClass schema validation.
examples/entity_field.revenue.json Adds example EntityField bound to a DataClass.
examples/data_class.currency.json Adds example DataClass with classifier metadata.
CHANGELOG.md Documents the new DataClass feature in Unreleased.
Suppressed comments (1)

tools/validate_data_class_examples.py:98

  • check_field_conformance() is currently fail-open when an EntityField sets dataClassRef but omits validValues: field_kind becomes None and the code records the check as passing. This contradicts the contract text (“field’s validValues must conform…”) and prevents the drift-guard from enforcing domain conformance for such fields.
        field_kind = (fld.get("validValues") or {}).get("kind")
        class_kind = (dc.get("domain") or {}).get("kind")
        if field_kind and class_kind and field_kind != class_kind:
            FAILURES.append(f"{name}: validValues.kind {field_kind!r} does not conform to DataClass {ref} "
                            f"domain kind {class_kind!r}")
        else:
            CHECKS[f"field-conforms:{name}"] = True

Comment thread tools/validate_data_class_examples.py Outdated
Comment on lines +55 to +63
def check_conformance(dataclass_schema, field_schema, dcs, fields) -> None:
for name, d in {**dcs, **fields}.items():
schema = dataclass_schema if d.get("type") == "DataClass" else field_schema
errs = sorted(validator_for(schema).iter_errors(d), key=str)
if errs:
for e in errs:
FAILURES.append(f"{name}: {e.message}")
else:
CHECKS[f"schema:{name}"] = True
Comment thread schemas/DataClass.json
Comment on lines +55 to +60
"required": [
"kind",
"modelRef",
"version",
"labels"
],
Comment thread specs/data-class-contract.md Outdated
The business vocabulary (`GlossaryTerm`) says what a thing MEANS; the `DataClass` says what
its DATA is, ontologically — so data quality can be inferred and enforced, not asserted.

A `DataClass` binds four things and is fail-closed if any is missing:
Comment thread schemas/EntityField.json
Comment on lines +49 to 58
"dataClassRef": {
"type": [
"string",
"null"
],
"pattern": "^urn:srcos:data-class:[A-Za-z0-9._~:-]+$",
"description": "Optional binding to the OntoDQ DataClass this field is an instance of. When set, the field's validValues must conform to the DataClass domain (validator)."
}
}
}
Comment thread tools/validate_data_class_examples.py Outdated
Comment on lines +66 to +80
def check_classifier(dcs) -> None:
for name, dc in dcs.items():
clf = dc.get("classifier")
if not clf:
CHECKS[f"classifier:{name}:none"] = True
continue
labels = clf.get("labels") or []
if not all(l.startswith("urn:srcos:glossary:") for l in labels):
FAILURES.append(f"{name}: classifier labels must all be GlossaryTerm URNs (assigned in the glossary)")
elif not clf.get("modelRef", "").startswith("urn:srcos:model-manifest:"):
FAILURES.append(f"{name}: classifier.modelRef must be a ModelManifest (cataloged model)")
elif (clf.get("compute") or {}).get("platform") not in ("ray", "tritfabric"):
FAILURES.append(f"{name}: classifier compute must run on ray|tritfabric")
else:
CHECKS[f"classifier:{name}:cataloged-on-compute-with-glossary-labels"] = True
…TMAX (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.
@mdheller

mdheller commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

Extended per your review with the two-level classifier architecture: (a) DataClass.classifier is now the per-class LOGISTIC head (one-vs-rest, binary) with a required evalRunRef so each class/glossary-term is individually testable (a class with no eval run is refused); (b) new TableClassifier is the per-table SOFTMAX (n-ary) that MUST align both an lsa-bag-of-words embedding AND a doc2vec-sentence-encoder — the n-ary logit→class representations — as a cataloged model on Ray/TritFabric assigning N DataClasses. Drift-guard enforces both; teeth-verified (missing-doc2vec, missing-evalRunRef). make validate ok.

- 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.
@mdheller

mdheller commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all 4 Copilot findings: (1) classifier now requires runRef + compute (both non-null) — a fully cataloged model on Ray/TritFabric, not partial; (2) EntityField allOf: dataClassRef present ⇒ validValues required (schema-level); (3) validator validates each collection against its intended schema explicitly (not by the instance's type); (4) spec reworded to 'three required + optional assignment'. make validate ok.

…ype-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
mdheller merged commit 95ea967 into main Aug 2, 2026
7 checks passed
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