Expediente 111/0: la regla que no podía ver
Escrita para impedir que un mount proveyera menos de lo prometido, juzgaba por un código de salida que vale cero tanto si respondió como si no
🕵️ Mostrar expediente completo → 📋 Protocolo de sesión →
Expediente · Depto. de Homicidios de Código
La regla nueva debía negarse cuando un nivel no se pudiera recuperar. Juzgaba la recuperación por el código de salida — y describe <desconocido> imprime «unknown subcommand» y sale 0, deliberadamente, con un test que lo asegura. Así que un nivel apuntando a una fuente inexistente volvió marcado como materializado con éxito: 111 bytes de texto de ayuda, servidos como conocimiento. La regla contra la provisión silenciosa proveyó en silencio, en su primera ejecución, escrita por quien llevaba el día entero arreglando justo eso.
Mostrar glosario
- cierre-en-fallo
- La mitad del límite que no necesita número: un nivel que el mount no puede recuperar aborta el mount, en vez de encoger la porción en silencio. Una porción que provee menos de lo prometido y no lo anuncia se lee idéntica a una completa.
- señal contractual
- Aquello que un productor promete emitir y alguien comprueba. «unknown subcommand» lo es: hay un test que lo asegura. El código de salida, en este verbo, no lo es — vale 0 tanto si respondió como si no.
- gate que corre y no puede ver
- El tercer rostro del mismo hueco: no un check que falta, ni uno que no se ejecuta, sino uno que se ejecuta y es estructuralmente incapaz de detectar aquello que vigila. Es el más peligroso de los tres, porque informa.
Protocolo para declarar, versionar y verificar esto → ontoref.dev
El doble balance — lo que costó, y lo que dejó
Lo que costó atar un veredicto a una señal muda
- Bytes de texto de ayuda reportados como conocimiento materializado 111
- Código de salida devuelto por
describeante un subcomando inexistente 0 - Niveles marcados
materialized: truesobre una fuente inexistente 1 de 1 - Rechazos emitidos por la regla de cierre-en-fallo en su primera ejecución 0
- Sesiones que la regla llevaba escrita antes de ser falsada 0 — se falsó el mismo día
- Puntos de entrada del verbo que aplicaban el límite antes de revisarlo 1 de 2
- Tiempo que
--materializellevaba muerto por otra ruta pre-ADR-048 desde la migración a constelación
Lo que el caso dejó
- Veredicto atado a la señal contractual, no al código de salida 1
- Rechazo observado antes de confiar en la regla exit 1, nombrando el nivel
- Puntos de entrada que aplican el límite 2 de 2
- Defecto colateral descubierto y cerrado (
--materializeroto) 1 - Techos numéricos inventados o importados 0
Los sospechosos — las pistas falsas
| El código de salida, tomado por señal de recuperación | “Yo valgo 0 cuando el comando se ejecuta. Nunca prometí decir si respondió algo: eso es otra pregunta, y nadie me la hizo.” | exit-code |
| describe <desconocido>, que sale 0 por diseño y con test que lo fija | “Yo salgo cero a propósito, y hay un test que lo asegura desde antes de este caso. Cambiarme habría roto una promesa para tapar una lectura perezosa.” | salida-cero |
| La regla nueva, dada por buena sin haberla visto negarse | “Yo compilaba, tipaba y devolvía el bloque budget correctamente formado. Todo lo que se me pidió demostrar, lo demostré.” | sin-falsar |
| El segundo punto de entrada (view mount-record), sin límite | “Yo soy el gemelo que llaman el daemon y MCP. Si nadie me nombra en la revisión, mi ausencia del arreglo no es cosa mía.” | segunda-puerta |
El arma — El arma · un cero que significa dos cosas distintas
# la regla escrita para impedir la provisión silenciosa: materialized: ($res.exit_code == 0) $ ontoref describe no-such-subcommand-xyz ; echo $? describe: unknown subcommand 'no-such-subcommand-xyz'. 0 # sale CERO — deliberado, y hay un test que lo fija # resultado: el nivel apuntando a la nada, dado por bueno constraints Describe materialized=True bytes=111
La regla entera cabía en una línea, y la línea era razonable:
materialized: ($res.exit_code == 0)
El problema es lo que ese cero significa en este verbo. ontoref describe no-such-subcommand-xyz imprime «unknown subcommand» y sale 0 — y no por descuido: reflection/tests/test_protocol_version.nu:87 lo afirma como comportamiento esperado. La señal era muda por contrato, y el veredicto se ató a ella.
El resultado, medido al romper el nivel constraints a propósito: materialized=True, bytes=111. Ciento once bytes de texto de ayuda entregados a un agente como si fueran las restricciones del proyecto. Nada falló. Nada avisó. El mount informó éxito.
Lo incómodo es la autoría. Esa regla se escribió en la misma sesión en que se cerraron un gate que no miraba y un gate que nadie ejecutaba, por alguien que acababa de escribir que un gate que corre y no puede ver es el más peligroso de los tres. Conocer el patrón no inmuniza contra cometerlo.
El giro — El arreglo · atarse a lo que el productor promete, y verlo negarse
let unknown = ($combined | str contains "unknown subcommand") let empty = (($out | str trim) | is-empty) materialized: (($res.exit_code == 0) and (not $unknown) and (not $empty)) $ ontoref view mount coding --materialize view 'coding': 1 level(s) could not be retrieved — constraints. Mount refused (budget.on_retrieval_error = 'FailClosed). $ echo $? 1
Dos piezas, y la segunda es la que convierte el código en regla.
Atarse a la señal contractual. El veredicto deja de leer sólo el código de salida y pasa a exigir además que la salida no lleve el marcador «unknown subcommand» — el mismo string que un test del protocolo asegura — y que no esté vacía. No se tocó el código de salida del CLI: salir 0 ahí es deliberado y está fijado por test, así que el sitio a corregir era el lector, no el emisor.
Verlo negarse. Con el nivel constraints apuntado a un subcomando inexistente, el mount responde ahora 1 level(s) could not be retrieved — constraints, rechaza, y devuelve 1. Esa observación es el arreglo tanto como el código: una regla que no se ha visto fallar es una intención con sintaxis.
Y en el camino apareció un defecto que nadie buscaba: --materialize llevaba muerto desde el ADR-048, porque invocaba $project_root/ontoref mientras el CLI vive en code/. Nada lo ejercitaba, así que nada lo reportaba — la misma enfermedad, un piso más abajo.
El veredicto
La regla estaba bien concebida y mal atada: vigilaba la provisión silenciosa juzgando por una señal que no puede expresar el fallo que vigila.
Lo instructivo no es el descuido — se corrige en cinco líneas. Es que lo cometió quien llevaba el día entero cerrando esta misma familia: un check que falta, un check que nadie ejecuta, un check que corre y no puede ver. Conocer el patrón no inmuniza; sólo la falsación lo hace.
Por eso la mitad numérica del límite sigue deliberadamente ausente. Un techo que nadie ha medido, importado de otro proyecto, sería exactamente la clase de afirmación cómoda que este caso documenta.
| El veredicto se ataba a una señal que no expresa el fallo | marcador contractual → no el exit code, que aquí es mudo |
| La regla se dio por buena sin verla negarse | falsación → vista fallar antes de darla por buena |
| El límite se aplicaba en un punto de entrada de dos | 2 de 2 puertas → un límite en una puerta no es un límite |
| El techo podía inventarse o importarse de fuera | sin techo importado → «sin medir» ≠ «sin límite» |
| El cambio altera una superficie visible para consumidores | migración 0056 → el cambio de superficie, declarado |
La reconstrucción — la sesión, repetida con protocolo
Lo que se pidió — reconstruido de refs:sessions/2026-08-05-ontology-illusion-barrido-y-gate — extracto acotado en custodia: el prompt verbatim y el oráculo `ontoref describe no-such-subcommand-xyz; echo $?`, con la razón de que el exit code no sirviera como señal — sale 0 por diseño, con test que lo fija.
haz las dos cosas: el barrido de rutas y el gate
Lo que había que pedir
Antes de dar por buena una regla que se niega, hazla negarse. 1. Rompe la entrada a propósito y ejecuta. Una regla que no has visto fallar no es una regla: es una intención con sintaxis. 2. No juzgues por el código de salida sin comprobar que el código de salida puede expresar el fallo. Aquí no podía: `describe <desconocido>` sale 0 por diseño, y hay un test que lo fija. 3. Átate a lo que el productor declara por contrato — el marcador, la respuesta vacía — no a la señal que resulte más cómoda de leer.
| Microtarea | Verificable |
| Falsar la regla antes de confiar en ella | apuntar un nivel a un subcomando inexistente y obtener exit 1 nombrando el nivel |
| Verificar que la señal usada puede expresar el fallo | ontoref describe no-such-subcommand-xyz; echo $? — si devuelve 0, el exit code no es la señal |
| Aplicar el límite en TODOS los puntos de entrada | view mount y view mount-record devuelven ambos el bloque budget |
La puerta antes de delegar: Una regla que se niega no se declara terminada cuando compila: se declara terminada cuando se la ha visto negarse sobre un caso real. Sin esa observación, lo único demostrado es que el código se ejecuta.
El disparador de ADR: Ninguno nuevo — es la aplicación de ADR-066 (decide la comprobación, nunca quien informa) a la superficie de provisión. Lo que sí quedó registrado es la migración 0056, porque cambia por defecto una superficie visible para consumidores.
La jurisprudencia — qué exige hoy la lección
- ✓El veredicto de materialización, atado al marcador contractual y a la respuesta vacía
.ontoref/reflection/modules/view.nu#materialize-level - ✓El límite por vista: techo opcional, abstención tipada, cierre-en-fallo por defecto
.ontoref/reflection/schemas/substrate-view.ncl#budget - ✓La aplicación del límite en los dos puntos de entrada
.ontoref/reflection/modules/view.nu#enforce-budget - ✓El cambio de superficie declarado para consumidores
.ontoref/reflection/migrations/0056-provision-declares-how-much.ncl
Del vocabulario del proyecto (2)
- Gate
- Prerrequisitos tipados y políticas que controlan las transiciones de estado de la máquina de estados de un proyecto.
- ontoref
- El protocolo en sí: una superficie tipada y consultable en la que un proyecto declara LO QUE ES (ontología) y CÓMO ACTÚA (reflexión), de modo que una afirmación sobre el proyecto pueda ser contradicha por una máquina y no sólo por un lector.