Extension Model
cks-mcp validates structures against a small, normative core rule set by
default (unique identities, no dangling relations, derivation arity and
acyclicity). Beyond that, six opt-in extensions add domain-specific
checks — each one defined in cks-core as a Constraint, and activated
per call via validate_knowledge's extensions parameter:
{"json_data": "...", "extensions": ["embedding_projection", "type_hierarchy"]}
All six share one property: additive by default. A structure that
doesn't use the relevant Knowledge Object type (EmbeddingProjection,
TypeRule, MutualExclusionRule, ...) is entirely unaffected by the
corresponding extension, whether or not you request it — the check only
ever activates on structures that opt in structurally, by containing the
declaration type it looks for.
| Name | Constraint identity | Checks |
|---|---|---|
embedding_projection |
CKS-EXT-EMBEDDING-PROJECTION |
Every EmbeddingProjection object has exactly one represents link to a real object, and references its vector externally. |
verification_record |
CKS-EXT-VERIFICATION-RECORD |
Every VerificationRecord has the right shape and exactly one verified_by link. Enforced unconditionally — see below. |
type_hierarchy |
CKS-EXT-TYPE-HIERARCHY-CYCLE |
TypeDefinition.parent_type chains don't form a cycle. |
relation_type |
CKS-EXT-RELATION-TYPE |
Relations connect object types allowed by any declared TypeRule. |
mutual_exclusion |
CKS-EXT-MUTUAL-EXCLUSION |
No pair of relation types declared mutually exclusive both connect the same source→target pair. |
functional_relation |
CKS-EXT-FUNCTIONAL-RELATION |
No source has more than one target via a relation type declared single-valued. |
embedding_projection
Gives citation/retrieval a mechanical anti-hallucination guarantee: an
EmbeddingProjection object represents a vector-space embedding of some
other canonical object, without ever holding the vector itself. This
constraint requires:
- Exactly one
representsrelation from the projection to a real, existing source object. - A non-empty
store_reffield pointing at wherever the actual vector lives (an external index) — never an inlinevector/embeddingkey.
If a generation step cites an EmbeddingProjection, this constraint
(together with the always-on dangling-relation check) guarantees that
citation resolves to a real object — never a fabricated one.
verification_record
Checks that every VerificationRecord has the right shape: required
fields present, and exactly one verified_by link to the object it's
about. This is a structural check only — it cannot tell a genuine record
from a well-formed fake, because static validation has no way to know
whether the recorded check actually happened.
That's why validate_knowledge enforces this extension unconditionally
— it activates the moment a VerificationRecord object appears in the
structure, regardless of whether you listed it in extensions. On top of
that, cks-mcp layers a second, independent check that cks-core has no
way to perform itself: the record's HMAC signature (see
Security Model). Shape and signature together are what make
"verified" mean verified — this extension alone only proves the record is
well-formed, not that it's genuine.
type_hierarchy and relation_type
ObjectIdentity.type is an unconstrained string by design — CKS has no
built-in taxonomy. These two extensions let a graph declare its own
taxonomy, as ordinary Knowledge Objects, and then check against it:
TypeDefinitionobjects ({"type_name": "Planet", "parent_type": "CelestialBody"}) declare a subtype relationship.type_hierarchyflags a cycle in the resulting chain (e.g. Planet is-a Moon is-a Planet).TypeRuleobjects ({"relation_type": "orbits", "allowed_source_types": ["Planet", "Moon"], "allowed_target_types": ["Star", "Planet"]}) declare which types a relation may connect.relation_typeflags any relation of that type connecting a disallowed pair — catching something like "Earth orbits Pasta". If twoTypeRuleobjects declare the samerelation_type, the last one encountered wins (treated as a modeling error to fix, not something the constraint reconciles).
mutual_exclusion and functional_relation
These declare contradiction rules, also as ordinary Knowledge Objects, catching relations that are each individually well-typed and yet jointly nonsensical:
MutualExclusionRule({"relation_type_a": "supports", "relation_type_b": "refutes"}) — flags a graph asserting both relation types between the exact same ordered source→target pair.FunctionalRelationRule({"relation_type": "orbits"}) — declares a relation type single-valued; flags a source with more than one target through it (e.g. both "Earth orbits Sun" and "Earth orbits Mars").
Multiple rule declarations of either kind accumulate (set union), unlike
TypeRule's last-one-wins behavior — there's no conflicting parameter to
arbitrate between two exclusion or functional rules.
Two ways to run these same two checks: pass mutual_exclusion/
functional_relation to validate_knowledge's extensions to get
diagnostics as part of validation (and block the version from committing
if they fail); or call
detect_contradictions
directly for a read-only report against the current state without
attempting to validate or commit anything. Same rules, same rule objects —
different tool depending on whether you want validation-time enforcement
or an on-demand check.
Why unconditional enforcement matters
Every other extension is opt-in and harmless if skipped — a structure
that doesn't use EmbeddingProjection or TypeRule objects is simply
unaffected. verification_record is the one exception: an unchecked
VerificationRecord looks exactly like a checked one to anyone reading the
result downstream. A caller (or a forgetful/malicious model) omitting it
from extensions must not be a way to bypass the check — so cks-mcp
activates it the moment the relevant object type appears, independent of
what was requested. See Security Model for the full
provenance story this is one half of.