Case 0/10: the gate that reported zero
A correct validator answered «0 findings» while the axiom asserting that the project describes itself pointed at three files that did not exist
🕵️ Show the full case file → 📋 Session protocol →
Case file · Code Homicide Dept.
ontoref validate ontology answered «61 nodes · 175 edges · 0 findings». In the same file, the self-describing axiom — the one asserting that ontoref describes itself using its own protocol — declared three artifacts, and not one of the three had existed since a documented migration months earlier. The validator was correct in everything it looked at. It never looked at that. And had it looked, it could not have said so: it printed without returning an exit code, and no chain invoked it.
Show glossary
- artifact_paths
- The only field on a node that points OUT of the graph and into the filesystem. Everything else a node declares is checked against the graph itself; this is checked against the disk, and nothing was checking it.
- Unknown
- The third verdict. It is not a failure: it is the refusal to manufacture a judgement the visible slice does not support. Folding it into Reject to obtain a boolean is the `unknown-collapsed-to-reject` anti-pattern, and here it turned 10 real findings into 218 false ones.
- orphan gate
- A correct mechanism that no chain calls. It never fails, because it never runs; and its existence reads as coverage. It is the disease ADR-070 names, and `validate ontology` had it: CLI yes, hook no, recipe no.
The protocol to declare, version and verify this → ontoref.dev
The double ledger — what it cost, and what it left
What a green nobody could watch go red cost
- Findings
validate ontologyreported 0 - Declared paths that existed under no root 10 across 7 nodes
- artifact_paths of the
self-describingaxiom that existed 0 of 3 - Chains running the validator (hook, recipe, CI) 0
- Exit code returned on findings, before the fix 0 — it printed
- First measurement, resolving against one root only 218 across 43 nodes
- Honest measurement, against the declared roots 10
- Occurrences of the pre-0023 path in the seed shipped to consumers 11
What the case left behind
- New rule with three verdicts (Hard · Soft · Unknown) 1
- Findings after the sweep 0 of 10
- Spine hooks that now run the validator 1 (
ontology-integrity) - Node retired for describing a deleted crate 1
- Cost in new protocol 0
The suspects — the false leads
| The validator that existed and that no chain ran | “I was written and I was correct. I checked dangling endpoints, self-edges and the closed vocabulary, and I never once failed at what I was asked to look at.” | orphan |
| The print with no exit code — a check unable to fail | “I report. I never promised to refuse: printing findings and returning 0 is what I did from day one, and nobody asked for anything else.” | no-exit-code |
| The pre-0023 .ontology/ path, alive in the protocol seed | “I was the right path when the seed was written. ADR-032 moving the spine did not erase me from the files, and the code bridges the old path, so nothing broke.” | pre-0023-path |
| The measurement against a single root, which manufactured 218 findings | “I gave 218 and it was honest arithmetic: I counted what did not resolve against the project root. That half of it lived in code/ is not something the number says — it is something the root nobody declared to me says.” | single-root |
The weapon — The weapon · a green emitted two centimetres from its own contradiction
$ ontoref validate ontology 61 nodes · 175 edges · 0 findings · vocabulary: 9 # and in the same core.ncl, the axiom saying ontoref describes itself: id = "self-describing" artifact_paths = [".ontology/core.ncl", ".ontology/state.ncl", "adrs/"] $ ls .ontology/core.ncl .ontology/state.ncl No such file or directory # all three, since ADR-032
The validator and the contradiction shared one command and one file.
61 nodes · 175 edges · 0 findingsartifact_paths = [".ontology/core.ncl", ".ontology/state.ncl", "adrs/"]
The first two have not existed since ADR-032, which consolidated the spine under .ontoref/ and propagated through migration 0023. The third does resolve, but under a different root. The validator was not lying: it checked edges and vocabulary, and about those it was entirely right. It simply had no rule for the one field on a node that points out of the graph.
What makes it a case rather than a typo is the subject. The node is self-describing, the axiom asserting that ontoref describes itself using its own protocol. The project’s most central claim pointed at three absent artifacts, and the instrument that exists to contradict it answered zero — because nobody had ever given it the chance to look there.
The turn — The fix · a rule, an exit code, and something that runs it
$ ontoref validate ontology --fail-on-hard
✗ [artifact-path] node 'self-describing' declares '.ontology/core.ncl'
and it exists under none of the declared roots.
10 hard finding(s) — the ontology points at things that are not there.
$ echo $?
1
# and now something runs it:
$ pre-commit run ontology-integrity
Ontology integrity (edges, vocabulary, artifact paths)....Passed
The fix has three pieces and none works alone.
The rule. artifact-path resolves every declared path against the roots the constellation DECLARES — project root, ONTOREF_ROOT, .ontoref/ — and never against the directory you happen to call from, which is the ADR-070 lesson.
Three verdicts, not two. Hard is does not resolve under any visible root. Unknown is I cannot see the tree it points into — a declared, unmaterialised member, a peer outside the root. Unknown is counted and declared; folding it into Hard is the anti-pattern the protocol itself names, and it is not theoretical: the first measurement, resolving against the project root alone, reported 218 broken paths across 43 nodes. The honest one reports 10. The difference was entirely code/, a slice the instrument could see and was not looking at.
An exit code and a chain. --fail-on-hard returns 1; the ontology-integrity hook lives in the ROOT pre-commit, which is the only one that reaches the spine — the one in code/ cannot, because code/.ontoref does not exist.
The verdict
The mechanism existed and was correct in everything it looked at. It lacked a rule for the one field that points out of the graph, an exit code with which to refuse, and something to invoke it.
An existing, correct, unrun check is indistinguishable from not having one — and it is more dangerous, because it is believed. That sentence was already written in this project’s ontology, in the fifth reading of enforcement-vs-emergence, months before this case. It was named. What there was not, was anything looking at it.
| No rule looked at the declared paths | artifact-path rule → resolves against declared roots, not the cwd |
| The validator could not fail | --fail-on-hard → only Hard closes; Soft and Unknown report |
| The validator was an orphan: no chain called it | ontology-integrity → in the pre-commit that does reach the spine |
| «Does not resolve» and «I cannot see its tree» counted the same | Hard · Soft · Unknown → Unknown is declared, not folded |
| The seed shipped a dead path to every consumer | seed corrected → with its coordinate, so it is not reverted |
The reconstruction — the session, replayed with protocol
What was asked — reconstructed from refs:sessions/2026-08-05-ontology-illusion-barrido-y-gate — a bounded excerpt held in custody: the prompt verbatim and «61 nodes · 175 edges · 0 findings» — sixty-three days of drift under a validation that answered zero AND WAS TELLING THE TRUTH.
where did you invent that from?
What should have been asked
Before quoting a path the ontology declares, run it against the disk. 1. Every `artifact_paths` resolves against the DECLARED roots (project root, ONTOREF_ROOT, `.ontoref/`) — never against the cwd, and never against only one of them. 2. A path that resolves under no visible root is Hard. One whose tree is not in this slice is Unknown — and Unknown is counted, never folded into Hard. 3. The result declares which roots it measured against. A count with no coordinates is a loose number looking for a sentence to take it in.
| Microtask | Verifiable |
| Resolve every artifact_paths against the declared roots | ontoref validate ontology --fmt json | jq .hard — and roots_resolved_against present in the output |
| Separate «does not resolve» from «I cannot see its tree» | the summary distinguishes hard / soft / unknown; unknown > 0 does not close the gate |
| Make the validator able to fail, and make something run it | validate ontology --fail-on-hard returns 1 on findings · the ontology-integrity hook appears in pre-commit run --all-files |
The gate before delegating: A validator that returns no exit code and that no chain invokes is not a gate: it is a report nobody asked for. Before trusting its green you have to be able to watch it go red.
The ADR trigger: None new. ADR-070 already decides that the publication pipeline is governed and not remembered, and ADR-066 that the check decides and never the reporter. This is their application to the ontology surface, not a new decision — criterion 4 of the adr? test does not hold.
Case law — what enforces the lesson today
- ✓The rule resolving artifact_paths against the declared roots, with three verdicts
.ontoref/reflection/modules/validate.nu#artifact-path - ✓The exit code with which the validator can refuse
.ontoref/reflection/modules/validate.nu#fail-on-hard - ✓The chain that runs it, in the pre-commit that reaches the spine
.pre-commit-config.yaml#ontology-integrity - ✓The knowledge entry corrected: it said this validator did not exist
.ontoref/reflection/qa.ncl#dissemination-post-and-narrative-howto
From the project vocabulary (3)
- Gate
- Typed prerequisites and policies controlling FSM state transitions in a project.
- adr?
- Evaluation procedure invoked at the end of a session or feature.
- ontoref
- The protocol itself: a typed, queryable surface on which a project declares WHAT IT IS (ontology) and HOW IT ACTS (reflection), so a claim about the project can be contradicted by a machine and not only by a reader.