# Conformance that refuses One reasonable test separates an ontology from a diagram with labels: can the artifact forbid anything? An ontology without axioms, without validation, without architectural intent is a glossary drawn as a graph. It describes; it cannot reject. If Vercy is only that, the criticism lands. So this page answers the test directly, with a yes and a demonstration you can run. Conformance in Vercy is enforced, not decorative. There is a program that reads a model, finds it invalid, and exits non-zero naming the rule it broke. Below is exactly which program, exactly which rule, and one worked refusal. ## Conformance is a gate, not a description The live registry, published at `github.com/ver-cy/registry`, is the running instance of the ELMM profile. Its write path is a pull request, and the admission gate on that path is continuous integration: `ci/run.py` runs seven fail-closed checks in order, and a single red check blocks the merge. Fail-closed means the default is refusal: a model is admitted only if it survives every check, not admitted unless someone objects. The seven checks, each exiting non-zero with a named normative rule on the first violation: - **`check_schema`** (V0 schema validation, ELMM-I8, ELMM-I14): every entry validates against the registry node profile schema, and its upstream-field projection validates against the unmodified upstream entry schema; every edge validates against the edge schema. A record with a missing required field, a malformed identity, or a value outside a controlled vocabulary is rejected here. - **`check_graph`** (MMDG graph integrity): six sub-rules, listed in the next section. - **`check_resolve`** (resolver determinism and replay, ELMM-I23, ELMM-I26, ELMM-I30): the resolver is run twice with the same fixed clock input and must produce byte-identical output; the emitted context pack and Twin Composition Snapshot must validate against their schemas; and where a committed fixture exists, the fresh output must equal it byte for byte. A resolver that reads a wall clock, hits the network, or drifts from its fixtures fails. - **`check_zero_change`** (zero-change registration, ELMM-I7, ELMM-I44): registering a new model of any role and any domain must touch registry data only. The check clones the tree, injects a new model plus an edge, runs the gate, resolves a task that reaches the new kind, then hashes `schema/` and `resolver/` before and after. A non-empty kernel diff is a conformance failure: it would mean admission required changing the kernel. - **`check_facets`** (facet membership and index freshness, ARCH-017): every industry and cluster code on an entry is in its vocabulary; every external Group is mapped; the generated catalogue and the unified index regenerate byte-identical. A drifted vocabulary, an unmapped Group, or a hand-edited generated file fails. - **`check_instantiations`** (B6 transform integrity): each committed external-to-internal instantiation regenerates byte-identical, its entry validates against the node schema and its manifest against the manifest schema, and the mastership control IC-1 holds. - **`check_conventions`** (scaffold conventions, S1, S2): the artifact header schema is a valid JSON Schema, the documented-conventions readme is non-empty, and no filename under `entries/`, `mmdg/`, or `schema/` carries a date. The no-date-in-filename rule and the header conventions are enforced here. This is not a promise about behavior; it is behavior. The gate is the code, and the code is public. ## The graph integrity check, rule by rule `check_graph` is where most structural refusals happen. It enforces six rules, each with its own diagnostic and its own ELMM identifier: 1. **Single node per major identity** (ELMM-I17): no two records share a registry id. 2. **Referential integrity** (ELMM-I19): every edge endpoint, `from` and `to`, is a registered entry id. 3. **Export coverage** (ELMM-I11, ELMM-I19): every kind an edge names appears in the target record's `exports`. The graph is statically computable from records alone, so a reference to a kind the target does not export is rejected before resolve time. 4. **Declared-min agreement** (ELMM-I11): where a record's `requires` names the same target and kind as an edge, the edge's `declared_min` equals that `min_version`. The edge is the sole resolver input under Minimal Version Selection, so the record and the edge must agree. 5. **Kernel isolation** (ELMM-I18): no `composes` edge leaves the kernel node. The kernel orchestrates nothing; its knowledge of models comes from the registry, never from outgoing edges. 6. **Acyclicity** (ELMM-I16): the `composes` subgraph is a directed acyclic graph. Each of these can turn a green tree red on its own. ## One worked refusal Take rule 3, export coverage, and break it on purpose. Suppose the single governed Landscape, `vercy.plmm`, declares that it references a `budget-line` kind owned by the org-unit model `vercy.oumm`. In `mmdg/edges.json` an author adds: ```json { "from": "vercy.plmm", "to": "vercy.oumm", "edge_type": "references", "declared_min": "0.1.0", "compositional_role": "R4", "kinds": ["budget-line"] } ``` The edge is schema-valid: it has every required field, so `check_schema` passes it. Both endpoints are registered, so referential integrity passes. It reads as a perfectly well-formed statement. But `vercy.oumm` does not export `budget-line`. Its exports are `org-unit`, `reporting-line`, `established-position`, and `unit-mandate`; `budget-line` is in none of them. The edge asserts a dependency on meaning the target never published. `check_graph` refuses. The export-coverage sub-check walks every edge, takes the target's `exports` set, and fails on the first named kind absent from it. It emits the target's full export set, sorted, so the reader can see exactly what was and was not published. The run exits non-zero with this diagnostic: ``` check_graph: FAIL edge #N (vercy.plmm -references-> vercy.oumm) references kind 'budget-line' which is not in vercy.oumm exports ['established-position', 'org-unit', 'reporting-line', 'unit-mandate'] (ELMM-I11, export coverage) ``` The merge is blocked. Not flagged, not warned, blocked: `ci/run.py` returns a non-zero exit code and the pull request cannot land. To fix it the author either makes `vercy.oumm` actually export `budget-line`, which is a real change the owning model must publish and stand behind, or stops claiming a reference that was never granted. The registry will not let a model depend on meaning that another model has not exported. That is a thing the artifact forbids. The same shape of refusal exists across the gate. A cyclic composition, where a Landscape composes a model that transitively composes it back, is rejected by acyclicity (ELMM-I16). An edge to a model that does not exist is rejected by referential integrity (ELMM-I19). A `requires` minimum that disagrees with its edge's `declared_min` is rejected by declared-min agreement (ELMM-I11), because the resolver would otherwise select a version the record never validated against. A registration that would force a kernel edit is rejected by the zero-change guarantee (ELMM-I7). A dated filename is rejected by the naming convention (S1). A resolver whose two runs diverge is rejected by determinism (ELMM-I23). In each case the rule is the reason, the identifier is in the message, and the exit code is non-zero. The pattern is the point: every refusal names a normative rule the model can be pointed at, argued with, and fixed against. There is no silent rejection and no rejection by taste. Break the rule, get the exit code, read the identifier. ## Beyond the registry: the model validators The registry gates relationships between models. Individual models carry their own gates. The Collective Meta-Model, published and versioned at `github.com/ver-cy/collective-meta-model`, ships a node validator that runs the V0 to V2 gates plus the model-specific CMM checks and refuses on a broken instance: a member without a collective, an authority grant with no grantor, a mandate that closes no accountability loop. The registration record for that model records V2 validation as its conformance level, and the record is only as good as the validator that backs it. The validator is the reason the level is a claim and not a decoration. ## The honest boundary Two things must be said plainly. First, this is model-instance conformance today. The checks refuse invalid registry records, invalid edges, non-deterministic resolution, and invalid model instances against their validators. They are run in CI on the write path and can be run by anyone locally: clone the registry from `github.com/ver-cy/registry`, run `python ci/run.py`, break a rule, watch it fail. That is real, and it is enough to answer the test. Second, a hosted public validation service, a page or an endpoint where an outsider drops in an arbitrary model and gets a verdict without cloning anything, does not exist yet. It is an open item, named as one. Until it ships, refusal is reproducible but not one-click for a stranger. Third, a reader who clones the registry to reproduce the refusal will find that one reference-implementation entry still carries a commercial-affiliated identifier from before the neutrality pass. It is inert to the demonstration above, which uses only the neutral `vercy.*` ids, but neutralizing that entry and its edge is a named open item on the registry. Neither caveat changes the answer to the test. Until an artifact can refuse, it is a glossary. Here is the refusal: a named check, a non-zero exit, a normative rule, and a merge that does not happen. Run it yourself in the registry CI and in the model validators. Both are public.