Case 8/4: the discipline without a trigger
Eight assertions without a witness in four hours, four mechanisms that already forbade them in writing — and no alarm, because none of them had a trigger
🕵️ Show the full case file → 📋 Session protocol →
Case file · Code Homicide Dept.
In four hours of session, eight false things were said with total confidence — «it is not written», «no such command», «it sends you to a 404» — and seven were negative: the certainty of someone who only knows that he did not find it. There was no shortage of rules forbidding it. There were four, written, canonical and consultable: the ondaod discipline, the assertion⇒witness principle with its accepted ADR, a 267-line howto that warned about exactly these traps, and an eleven-step mode that prints itself. None fired. Each one bit exactly once, when the human pointed at it — which is the operating definition of a road sign, not of a gate.
Show glossary
- witness
- A signed record that a check was executed and what it returned. It is the difference between «I verified it» and «I am saying it». Seven of this case's eight assertions had none — and the eighth had one that did not say what was asserted.
- negative assertion
- «It does not exist», «it is not written», «there is no such command»: the grammatical form of certainty, spoken by someone who only knows that he did not find it. ADR-072 gives it its exact name: the actor can say «I did not look» — and a search record turns the involuntary lie into a true sentence that sounds very different.
- trigger
- What turns a written rule into an executed one: a hook that serves it at the moment of deciding, a gate in a chain somebody calls, a contract that refuses the file. A mechanism without a trigger is documentation with the syntax of a mechanism — and this case exists because four of them were exactly that.
- inert mechanism
- Declared, canonical, consultable — and inert. This case's four — ondaod, assertion⇒witness, the howto, the mode — existed before the first assertion, were correct, and each one bit exactly once: when the human pointed at it.
- oracle
- Whatever can falsify an assertion without asking its author's permission. This project's files have oracles to spare: contracts that refuse, gates that fail, schemas that will not export. The conversation has none. The only oracle of the human↔agent channel is the human — and that asymmetry is this case's thesis, not its excuse.
The protocol to declare, version and verify this → ontoref.dev
The double ledger — what it cost, and what it left
The figures on the left are the body; the ones on the right, what was left in its place. And the ratio presiding over this case is its own number: 8 and 4. Eight assertions no mechanism stopped; four mechanisms that already forbade them in writing. There is a third figure, the only one green from birth: zero lies reached disk. The file gates all worked — the schema that refuses, the contract that will not export, the gate that fails. What had no gate was the conversation.
What the crime cost
- Incident window, by the log's clock 13:19:10 → 17:26:23 UTC · 4 h 07
- Assertions without a witness, verbatim and timestamped 8
- Mechanisms that already forbade them in writing 4
- Records in the window · agent messages 1,653 · 627
- Tool calls · of them Bash 298 · 217
- …that invoked the CLI governing the project 20
- First CLI invocation 14:14:48 — 55 min in, and because the human asked
- «describe capabilities» (step 1 of the entry protocol), executed 0 times
- …times its name went through a grep without being run 2
- The mode, as a filename in an ls 14:28 — nobody opened it
- The mode, opened for the first time 17:16 — 3 h 57 in, pointed out by the human
- False diagnoses chained on a degraded server 3
- False accusations against another session, withdrawn in this case 2
- Lies that reached disk 0
What the case left behind
- The rule discipline is a rule WITH a trigger; everything else is documentation
- The trigger UserPromptSubmit hook: the Q&A governing the task, served in the prompt
- The gate just server-check — catches the degraded server in one second
- The contract a mode id resolves to ONE DAG (29/29, project precedence)
- The step account_lesson: verified pointers to what executes the lesson, or the debt
- The schema LessonAccounted refuses a case that stays silent about its lesson
- The underlying debt, named a sentence is not an artifact: the channel's oracle is the human
The point of abandonment — what the table doesn't show
The abandonment point was not not-knowing: it was not-asking. The entry protocol was in the CLAUDE.md with its step 1 — describe capabilities — and in four hours it was executed zero times; its name went twice through a grep over the source code, which is the saddest form of almost consulting it. The session measured a great deal — 298 tool calls, 217 Bash — and asked very little: twenty invocations of the CLI that governs the project, the first one fifty-five minutes in, and because the human asked first. Measuring without asking the one who knows is the most laborious way there is of not looking.
The suspects — the false leads
| The agent did not know the rules | “«The agent did not know the rules.» The charitable explanation, and a false one: it knew them all. The start-up orientation hook listed the 29 modes — generate-expediente among them — and the named tensions; the project's CLAUDE.md carries the entry protocol with describe capabilities as step 1. All of it was in context at 13:19:10, before the first tool call. The first CLI invocation came at 14:14:48, fifty-five minutes later, and because the human asked. It was not ignorance. It was that knowing does not trigger anything.” | dismissed — it knew everything from 13:19 |
| The mechanisms did not exist yet | “«The mechanisms did not exist yet.» Verified alibi: all four predate the first assertion. ondaod is in the global CLAUDE.md with a consultable procedure; assertion⇒witness is ADR-072, accepted and with the anti-pattern named; the howto is 267 lines and answers a one-second query; the mode is eleven steps with their actor and prints itself with --dry-run. They existed, they were correct, they were consultable. Dismissed — and this alibi is exactly what turns the slip into a case file.” | dismissed — all four predate the first sentence |
| The rules were ambiguous or badly written | “«The rules were ambiguous or badly written.» Alibi: when they were finally read, they worked on the first try. The howto warned about the exact traps the session fell into — count the card, not the string; verify the page, never the file; start with run-secure.sh or every measurement is false. They needed no interpreting, no correcting, no completing: they needed reading. Dismissed.” | dismissed — they worked on the first try once read |
| «A written rule applies itself» | “«A written rule applies itself.» GUILTY. And it belongs to nobody, because it is the default belief of whoever writes documentation: the rule is drafted, published, and the feeling of having solved it is filed away. None of the four mechanisms had a trigger — nothing served them at the moment of deciding, nothing refused the result of ignoring them. The mode crossed the screen as a filename at 14:28 and nobody opened it until 17:16, three hours fifty-seven in, pointed out by the human. A mechanism like that is not a gate: it is a sign by the road, and signs do not brake for anyone.” | GUILTY — and it is everybody's belief |
The weapon — Eight verbatim assertions, timestamped, from the session's log — seven negative and one positive out of convenience
/* Eight assertions, verbatim and timestamped — from the session's log (cab0fe5c…jsonl).
Seven are NEGATIVE: «it does not exist», said by someone who only knows he did not find it.
The eighth is the same error with the sign flipped: the date matched. */
14:06 «the English glosses are not written» → there were 20; a generator comment was read
14:06 «the schema has nowhere to hang a gloss» → term.ncl: definition | i18n_str, bilingual
14:16 «no such command, and there never was» → describe term existed; the grep read only crates/*.rs
14:39 a server started by hand, never verified → 3 false diagnoses, chained
14:52 «the language switcher sends you to a 404» → it translated fine; the URL was invented
15:23 «the lexicon's 26 are left with no surface» → gen-nota-lenguaje.nu → /sobre-el-idioma
15:32 «the tooltip is blocked by the contract» → reason_type carried 'SourceLanguage for that
17:25 «It is this session» → the id was sitting in the scratchpad path
/* And the four mechanisms that already forbade it, all older than the first sentence:
ondaod in the CLAUDE.md, with a consultable procedure
assertion ⇒ witness adr-072, accepted, with the anti-pattern named
qa:expediente-howto 267 lines; it warned about this session's exact traps
mode:generate-expediente 11 steps with their actor; prints itself with --dry-run
None of them fired. None of them HAD a trigger. */
And two accusations must be withdrawn here, because this case was nearly filed with them inside. The morning session was not careless: it reported seven steps without artifacts because the –artifacts option is walled off from the CLI wrapper — three syntaxes tried, three parse_mismatch, and the five historical runs carry that empty column for the same reason — and it lost the account_lesson step because the DAG it was served had ten steps: the installed copy ran one version behind, and mode list answered with two DAGs for one id without saying which was real. Accusing it was, once again, asserting without reading the log. Both accusations are withdrawn here, with a witness.
The turn — Giving the rules that already existed a trigger
# The fix is not a new rule: it is giving the existing ones a TRIGGER. # 1. The hook — the rule travels toward the agent, not the other way (settings.json:134). # On every prompt, if the task is already governed, the governing Q&A is served whole: "UserPromptSubmit": nu ~/.claude/hooks/onre-prompt-orient.nu # «This is already governed. Do not improvise the procedure: qa:<id> — read it WHOLE.» # It fired in production: the session that wrote this case received it on its first prompt. # 2. The gate — the degraded server dies in one second, not in three diagnoses: just server-check # justfile:589 — fails if the declared routes do not answer # 3. The contract — a mode id resolves to ONE DAG (two versions used to answer for one): # .ontoref/reflection/nulib/shared.nu#all-mode-files — dedupe by id, 29 ids → 29 DAGs # 4. The step the served DAG was missing — and the schema that makes it non-negotiable: # mode:generate-expediente/account_lesson + LessonAccounted (schemas/expediente.ncl): # lesson_codified_in with VERIFIED pointers to what executes the lesson, # or lesson_debt naming what would settle it. A case silent about its lesson does not export.
What the fix does NOT close is stated here, because this series does not hide debts in the last paragraph. –artifacts remains walled off, and the runs will keep their empty column until the wrapper accepts a comma-separated string. verify exists in zero of the mode’s eleven steps: without a per-step oracle, a step’s status is whatever the agent says — adding it to the three steps that admit one is approved. The howto’s step list is not checked against the DAG, and it has already lied once. And the underlying debt, the one no gate can close: a sentence is not an artifact. In this session not one lie reached disk — they all died in the conversation, because files have gates and the channel has none. The only oracle of that channel is the human. That is not an excuse: it is the thesis.
The verdict
The series asks: with ontoref, would it have gone differently? And this case gives the archive’s most uncomfortable answer, because the mechanism that would have caught it did not merely exist: it existed four times. The ondaod discipline, the assertion⇒witness principle with an ADR number, the howto that warned about these specific traps, the mode that turns the procedure into eleven steps with their actor. All declared, all canonical, all consultable — all inert. The honest answer is not «with ontoref it would not have happened»: it is that ontoref, declared, was already there and was not enough — until every rule got its trigger. That is the lesson this case leaves in the archive: discipline is not the rule; it is the rule plus whatever executes it. A hook that serves it where decisions are made, a gate in a chain somebody calls, a contract that refuses the file that ignores it. The rest — the declared but unplugged, the canonical outside any chain, the consultable nobody consults — has an older, less technical name: good intentions.
| A negative assertion without having searched | ADR-072 names it: the actor can say «I did not look». The search record registers WHAT was looked at and with what pattern — and «it does not exist» without a record becomes «I did not find it», which is true and sounds very different. Seven of the weapon's eight sentences die from that one conversion. |
| An improvised procedure with the howto one query away | The orientation hook serves the Q&A governing the task in the prompt itself, before deciding how it is done. The session read an instance instead of the howto and called it «the most reliable way»; with the hook, the howto arrives first — not four hours later, pointed out by the human. |
| A degraded server poisoning every measurement downstream | The just server-check gate asks the routes that only exist if the start-up was the declared one (run-secure.sh), and fails in one second. The three false diagnoses of 14:39 chained precisely because nothing answered that question; the gate answers it before anything is measured — and it is proven in both directions. |
| Two DAGs answering to the same mode id | The shared.nu contract deduplicates by id with project precedence: 29 ids, 29 DAGs. The morning session lost an entire step because it was served the installed copy, one version behind — and nothing said which of the two was real. There are no longer two. |
| A lesson nothing consumes | The account_lesson step demands verified pointers to what executes the lesson — adr:, qa:, mode:, gate:, test:, contract: — or the debt named. And the LessonAccounted schema makes it non-negotiable: a case silent about its lesson does not export. This very file went through that gate. |
| A sentence spoken in the human↔agent channel | No gate is possible, and the case declares it instead of hiding it. What reaches disk goes through gates — and in this session not one lie was published: they all died in the conversation. What is said goes through none. The only oracle of that channel is the human, and containing is not curing. |
Case law — what enforces the lesson today
- ✓A negative assertion demands a search record, or the actor declares «I did not look»
adr:072/the-actor-can-say-i-did-not-look - ✓The Q&A governing the task is served in the prompt, before the procedure is decided
hook:UserPromptSubmit/onre-prompt-orient - ✓The case-file procedure is read from the howto and the mode, never from an instance
qa:expediente-howto - ✓The server starts through the declared path or every later measurement is false
gate:just server-check - ✓A mode id resolves to a single DAG, with project precedence
contract:.ontoref/reflection/nulib/shared.nu#all-mode-files - ✓A case names what executes its lesson, or declares the debt — the schema refuses silence
mode:generate-expediente/account_lesson
⊘Declared debt: «--artifacts» declared list<string> and unreachable from the CLI wrapper — the five historical runs carry an empty column because of it; settled by accepting a comma-separated string or a repeatable option. «verify» in zero of the mode's eleven steps; adding it to the three with an oracle is approved (assemble_case: the .ncl exports; render: the .md reproduces; publish: expedientes-check). The howto's step list is not checked against the DAG; settled by a gate comparing its ids against mode show --fmt json. And the underlying one, with no gate possible: a sentence is not an artifact — the only oracle of the human↔agent channel is the human.
One thing remains to be said, and it files this case within the series. 358/980 measured the box instead of the content. 3/0 checked what existed and never what should exist. 0/318 wrote an impeccable validator nobody ran. This case is that family’s ceiling: not a gate measuring the thing next door, nor one nobody calls — four whole mechanisms, correct and consultable, with nothing to execute them. Which is why the question it leaves is not «is it written?», which here answered yes four times over, but «what triggers it?». If the answer is «someone will remember», the mechanism is a road sign — and the day it matters, a human with just enough patience will point at it. In this case, eight times.
Glosario
Sin coincidencias.