feat(data): TRAIN + register the DataClass classifiers — specified→trained→reproduced (task #14) - #264
Merged
Merged
Conversation
…ained→reproduced (task #14) The DataClass contract specified a TF-Lattice classifier + referenced a ModelManifest/RunRecord by URN, but those URNs pointed at nothing (specified, not trained). This closes it: - tools/train_dataclass_classifiers.py trains real per-class LOGISTIC (one-vs-rest) + per-table SOFTMAX heads, MONOTONE-constrained in monotonicFeatures (weight >=0 projection each GD step = the TF-Lattice essence — raising a monotone feature never lowers the class score). Deterministic (seeded, full-batch) so weights + ModelManifest.modelDigest are reproducible. - Emits trained_model.json + a conformant ModelManifest (id=DataClass modelRef) + train/eval RunRecords (ids=runRef/evalRunRef), so the previously-dangling DataClass classifier refs RESOLVE. - validate-trained-classifiers (recompute-don't-trust, in make validate): manifest digest matches the weight bytes; eval accuracy REPRODUCED from weights+fixture (an inflated claim fails); model verified genuinely monotone (perturb up -> score never drops); refs resolve; artifacts conform. Teeth-verified (tampered weights refused). numpy in the make recipe.
mdheller
added a commit
that referenced
this pull request
Aug 3, 2026
…lf-review, no Copilot on #264) (#265) Adversarial + functional review of #264 (which Copilot didn't review) found: - the monotone constraint was VACUOUS — the fixture held decimal_places constant, so its weight trained to 0 and the monotone teeth passed trivially. New fixture makes BOTH monotone features (token_magnitude, decimal_places) the primary label signal → both weights bind strongly positive, accuracy realistic (<1.0), monotonicity genuinely exercised. - standardiser was fit on FULL data (mild train/test leakage) → now fit on the TRAIN split only. - ModelManifest overclaimed 'wide-and-deep'/lattice → renamed 'monotone-logistic' (an honest realisation of the declared tf-lattice-wide-and-deep contract, not a full calibrated lattice). - validator now checks BOTH per-class heads monotone + asserts the constraint BINDS (non-vacuous), and — a latent bug the trivial 1.0-accuracy fixture had masked — compares reproduced accuracy at the stored 4-decimal precision instead of full-precision vs 1e-6 (per-class 0.7857 now reproduces). Tamper teeth still refuses corrupted weights. 8 checks green.
mdheller
pushed a commit
that referenced
this pull request
Aug 4, 2026
…SP-FPRINT-STACK-001) Lands the spine of the six-layer metadata fingerprint classifier: the stance algebra, per-layer witnesses, the admissibility gate, the L5 drift detector, and DR-4 enforcement. The one genuinely new thing is that ZERO (ignorance) and INADMISSIBLE (conflict) are different values. The 2018 source design had the three-channel matcher, OntoDT, the mereotopological framing and DQ-into-access-enforcement already; what it could not say was "I don't know" distinctly from "my evidence contradicts itself". A gap wants more data; a glut wants a human. Everything else here follows from separating them. Structural properties, all enforced rather than documented: - pool -> guard -> quantize, in that order; guards only lower stance in the knowledge order, so gated stances retain conformal coverage (policy costs efficiency, not validity) - every stored verdict is recomputed from what produced it - quorum is n_eff (covariance participation ratio), not Herfindahl concentration - coverage does not compose: depth and the loosened epsilon ride on the stance - guards are measurable w.r.t. evidence and witness only — reading the outcome breaks exchangeability, so `value.*` cannot be named in a guard input path - an inadmissible layer contributes ZERO, never a guess Axiom X1 (parthood and subtyping are disjoint arrows) is enforced as a CI invariant. It is the precondition for the source deck's own two questions — a count over the subtype closure and an enumeration of parts — being simultaneously answerable from one graph. L5's drift detector is blocking, not advisory: under silent repurpose the schema does not change, so L5's evidence is precisely the unchanged schema and it asserts stale semantics with maximum confidence exactly when it is wrong. Retires the `tf-lattice-wide-and-deep` const in DataClass — that repository was archived by its owner in April 2026. The pin now enumerates structurally-monotone constructions, with the dead name deprecated-but-accepted so existing documents stay valid. Teeth: 81 checks, 9 schema negative vectors, and 25 semantic gates proven to bite by a mutation harness that requires each rejection for its stated reason. The M5 monotonicity property test is run against a deliberately non-monotone aggregator and fails if it does not catch it — because the closest precedent in this repo (#264) shipped a monotone constraint whose fixture held the monotone feature constant, so it bound nothing and passed vacuously.
mdheller
pushed a commit
that referenced
this pull request
Aug 4, 2026
…SP-FPRINT-STACK-001) Lands the spine of the six-layer metadata fingerprint classifier: the stance algebra, per-layer witnesses, the admissibility gate, the L5 drift detector, and DR-4 enforcement. The one genuinely new thing is that ZERO (ignorance) and INADMISSIBLE (conflict) are different values. The 2018 source design had the three-channel matcher, OntoDT, the mereotopological framing and DQ-into-access-enforcement already; what it could not say was "I don't know" distinctly from "my evidence contradicts itself". A gap wants more data; a glut wants a human. Everything else here follows from separating them. Structural properties, all enforced rather than documented: - pool -> guard -> quantize, in that order; guards only lower stance in the knowledge order, so gated stances retain conformal coverage (policy costs efficiency, not validity) - every stored verdict is recomputed from what produced it - quorum is n_eff (covariance participation ratio), not Herfindahl concentration - coverage does not compose: depth and the loosened epsilon ride on the stance - guards are measurable w.r.t. evidence and witness only — reading the outcome breaks exchangeability, so `value.*` cannot be named in a guard input path - an inadmissible layer contributes ZERO, never a guess Axiom X1 (parthood and subtyping are disjoint arrows) is enforced as a CI invariant. It is the precondition for the source deck's own two questions — a count over the subtype closure and an enumeration of parts — being simultaneously answerable from one graph. L5's drift detector is blocking, not advisory: under silent repurpose the schema does not change, so L5's evidence is precisely the unchanged schema and it asserts stale semantics with maximum confidence exactly when it is wrong. Retires the `tf-lattice-wide-and-deep` const in DataClass — that repository was archived by its owner in April 2026. The pin now enumerates structurally-monotone constructions, with the dead name deprecated-but-accepted so existing documents stay valid. Teeth: 81 checks, 9 schema negative vectors, and 25 semantic gates proven to bite by a mutation harness that requires each rejection for its stated reason. The M5 monotonicity property test is run against a deliberately non-monotone aggregator and fails if it does not catch it — because the closest precedent in this repo (#264) shipped a monotone constraint whose fixture held the monotone feature constant, so it bound nothing and passed vacuously.
mdheller
added a commit
that referenced
this pull request
Aug 4, 2026
…SP-FPRINT-STACK-001) (#284) Lands the spine of the six-layer metadata fingerprint classifier: the stance algebra, per-layer witnesses, the admissibility gate, the L5 drift detector, and DR-4 enforcement. The one genuinely new thing is that ZERO (ignorance) and INADMISSIBLE (conflict) are different values. The 2018 source design had the three-channel matcher, OntoDT, the mereotopological framing and DQ-into-access-enforcement already; what it could not say was "I don't know" distinctly from "my evidence contradicts itself". A gap wants more data; a glut wants a human. Everything else here follows from separating them. Structural properties, all enforced rather than documented: - pool -> guard -> quantize, in that order; guards only lower stance in the knowledge order, so gated stances retain conformal coverage (policy costs efficiency, not validity) - every stored verdict is recomputed from what produced it - quorum is n_eff (covariance participation ratio), not Herfindahl concentration - coverage does not compose: depth and the loosened epsilon ride on the stance - guards are measurable w.r.t. evidence and witness only — reading the outcome breaks exchangeability, so `value.*` cannot be named in a guard input path - an inadmissible layer contributes ZERO, never a guess Axiom X1 (parthood and subtyping are disjoint arrows) is enforced as a CI invariant. It is the precondition for the source deck's own two questions — a count over the subtype closure and an enumeration of parts — being simultaneously answerable from one graph. L5's drift detector is blocking, not advisory: under silent repurpose the schema does not change, so L5's evidence is precisely the unchanged schema and it asserts stale semantics with maximum confidence exactly when it is wrong. Retires the `tf-lattice-wide-and-deep` const in DataClass — that repository was archived by its owner in April 2026. The pin now enumerates structurally-monotone constructions, with the dead name deprecated-but-accepted so existing documents stay valid. Teeth: 81 checks, 9 schema negative vectors, and 25 semantic gates proven to bite by a mutation harness that requires each rejection for its stated reason. The M5 monotonicity property test is run against a deliberately non-monotone aggregator and fails if it does not catch it — because the closest precedent in this repo (#264) shipped a monotone constraint whose fixture held the monotone feature constant, so it bound nothing and passed vacuously. Co-authored-by: mdheller <charles.peterson@socioprophet.ai>
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.
Close the last owed thread: the classifier was specified, not trained
The DataClass contract (#251) specifies a TF-Lattice classifier and references a
ModelManifest+ train/evalRunRecordby URN — but those URNs pointed at nothing. This trains real classifiers and emits the artifacts they resolve to.tools/train_dataclass_classifiers.pytrains, on a labelled fixture, per-class LOGISTIC heads (one-vs-rest, individually testable per glossary-term) + a per-table SOFTMAX (n-ary head), both MONOTONE-constrained in the declaredmonotonicFeatures— the TF-Lattice essence: the weight on a monotone feature is projected>= 0each GD step, so raising it never lowers the class score. Deterministic → weights +ModelManifest.modelDigestreproducible.trained_model.json+ a conformantModelManifest(id = DataClassmodelRef) + train/evalRunRecords (ids =runRef/evalRunRef) — the previously-dangling references now resolve.Teeth (
make validate-trained-classifiers, recompute-don't-trust)modelRef/runRef/evalRunRefresolve to the emitted artifactsCloses the vocabulary/data-governance program's last owed follow-up (specified → trained → registered → reproduced). numpy installed in the make recipe.