The gap was there before the agent
Your agent is not hallucinating your schema. It is reading it. A century-old cataloguing standard has a test for whether a definition can be read by someone who was not in the room — so we ran it against our own glossary, and it found 11 terms citing a corpus that does not exist.
There is a sentence in Jessica Talisman’s «Semantics Evolved» that reorganizes the whole argument about agents and bad data:
The machine consumer does not create the gap and no, your agent is not hallucinating. Because human inquiry and labor conceals the gap in understanding, agents surface the wrong meaning because they simply misunderstand for lack of robust concepts with definitions.
The mechanism is worth stating slowly, because the reflex runs the other way.
An analyst cannot tell whether cust_status_cd means enrolled or billed.
They ask the engineer who owns the pipeline. They get an answer. They use it.
Nothing is written down, so the next analyst asks the same question and gets the
same answer. The cost is recurring, and it is never attributed to the
definition — it is absorbed as the ordinary friction of working somewhere.
An agent has no engineer to ask. Where the published context underdetermines meaning, it does not stop:
It completes the definition from prior statistical exposure to thousands of other organizations’ schemas, and the completion is plausible, and specific to a company that is not yours.
That is not a model defect. It is an instrument reading a gauge that was always wrong, and finally saying so out loud.
The test that has existed since 2005
The interesting part of Talisman’s piece is not the diagnosis. It is that library and information science has carried the tests for this for decades, and they are cheap to run.
ISO/IEC 11179-4 says a definition must stand alone: state what the concept is, which values it admits and refuses, and where it stops. A description that expands the label into a longer version of the label has resolved nothing, because the label is where the ambiguity started.
ANSI/NISO Z39.19 says a term is admitted into a controlled vocabulary on one of three distinct grounds, and requires them reconciled deliberately:
- literary warrant — the corpus being described,
- user warrant — what the people and machines searching actually say,
- organizational warrant — what the institution approves.
They are listed separately because they conflict. The failure the standard warns about is specific: organizational warrant quietly stands in for user warrant, and the institution’s preferred term gets recorded as evidence of what consumers say.
Both of these are auditable. Neither requires a research program. So we pointed them at our own glossary.
What it found here
ontoref keeps a controlled vocabulary at .ontoref/ontology/glossary.ncl, typed
by a contract that already separates the compartments a text box cannot: a
definition, a scope note in notes, aliases, related_terms, and an
origin recording on whose authority the term exists. Thirty-odd terms, and the exact
count moves — which is the point of measuring it with a command rather than a memory.
nickel export .ontoref/ontology/glossary.ncl | jq '[.terms[].origin.kind] | group_by(.)'
terms: 35
origin.kind Adr=9 Axiom=5 External=17 Practice=1 Schema=1 Tension=2
External WITH ref 6
External WITHOUT ref 11
no scope note 18
Two findings, and the second is the one that stung.
Eighteen of them state no boundary. More than half the
vocabulary says what a concept is and never where it stops. This is exactly
the question Talisman says a catalog cannot answer — «You cannot ask which
concepts have no stated boundary» — and the only reason we can ask it is that
definition and notes are separate fields. Having the capability and never
having exercised the query is a different state from not having it. It was ours.
Eleven terms declare a warrant they do not have. The contract reads:
origin | origin_type | default = { kind = 'External, ref = "" },
'External means literary warrant — this term comes from a corpus outside the
project. A term admitted without anyone thinking about warrant therefore
records itself as citing a body of literature, with no literature cited. Not
an empty field: a field quietly asserting something false. Eleven of them.
A default is a decision that gets executed once per term without anyone taking it.
The same substitution, one layer up
The node graph carries warrant too — [| 'Adr, 'Emergence, 'Interview, 'Session, 'External |], added by ADR-069 after
her previous article. Those five are
provenance kinds where Z39.19’s three are grounds, but the correspondence is
legible: 'Adr and 'Session are organizational, 'Interview and 'Emergence
are user, 'External is literary.
Five nodes carry a warrant today: three 'Session, one 'Adr, one
'Interview. Four organizational, one user, zero literary.
That is the substitution the standard names, in a project that had already read the standard and typed the field. It is visible only because the field was typed — which is the argument for typing it, and no comfort at all.
What a validator cannot reach
ontoref ships validate ontology: dangling endpoints, self-edges, edge kinds
against a frozen vocabulary, symmetric reciprocity, artifact paths that resolve.
It is a real gate, it fails CI, and it does not get tired.
It is also, structurally, the test Talisman opens with:
A definition written by data producers and validated by data producers tests if producers agree.
validate ontology checks that our declarations cohere with each other.
That is the producers-agree test, one level up. Every file under .ontoref/ was
written and is graded by the same party. The axiom sufficient-verification
already concedes the shape of this — verification is local and partial, and
completeness is renounced as the basis of trust — but warrant is precisely the
axis on which local verification is blind. Coherence among declarations says
nothing about whether a second reader would take them to mean the same thing.
So the honest claim, and it is narrower than the one we have been tempted to make: ontoref moves the grading from opinion to execution. It does not move it from the producer to the consumer. A gate that re-runs is enormously better than a working group that met once. It is not a different judge.
What is missing is a reader, not a refuser
The tempting fix — make origin required, reject terms without a warrant — is
the wrong direction, and the project has already written down why: a required
warrant is ceremony-capture. You get a whole glossary with the field filled in to
get past the gate, which is worse than eleven honest defaults, because now the
lie typechecks.
What is missing is the opposite of a gate. Z39.19’s user warrant is harvested: you read where consumers already write — tickets, dashboard titles, prompts to internal assistants — and every harvested term that collides with the preferred one is registered as an alternative label rather than corrected away.
Correcting a consumer’s terminology deletes evidence. Registering it preserves the evidence
On that one point we are ahead of the standard we are converging with:
skos:hiddenLabel keeps a deprecated form searchable but records nothing about
why it was refused, while ontoref’s rendering policy types the refusal —
'Calque, 'FalseFriend, 'Displaces, 'Regional — which is what stops
someone from «fixing» a false friend back in six months later.
But every alias here is author-declared. Two surfaces already hold the raw
material and neither feeds the registry: interaction-trace, the typed JSONL
record of agent and human sessions, and drift-observation, the background
watcher over the ontology tree. The material is on disk. Nothing reads it into
the vocabulary.
Two addresses, and nothing fixed
This post does not end with a fix. It ends with two backlog items, which is a weaker claim and a truer one:
- bl-049 — harvest user warrant into the registry. The audit stays Soft,
never Hard, for the reason above. It would be the second measurable proxy for
the emergence pole; the opt-in
--warrantaudit was the first. - bl-050 — type the relation on
related_terms. Today it is a bareArray String. Two concepts can coexist, but nothing distinguishes «these two are close» from «these two are the same», and nothing carries the deliberate non-transitivity that makesskos:closeMatchsafe to chain. One typed relation kind — not the SKOS mapping vocabulary imported wholesale.
The measurement is the deliverable. Eleven and eighteen are now numbers a command produces, on a schedule, against a file anyone can read. They will be wrong in a different way next quarter, and the difference from last quarter is that we will be able to say so.
Your agent was never the one making things up. It was the first reader you had who could not ask.