Expediente 5/0: el despacho que sólo hablaba con el terminal

La política se implementó en el punto de entrada, funcionaba, y por eso alcanzaba exactamente una superficie

Jesús Pérez
Toda capacidad de este proyecto llega al CLI, al daemon, a MCP y a GraphQL porque su lógica vive en un módulo que un llamante carga desde un root. El despacho de comandos de dominio —resolución de alias, las dos vías de activación, la puerta de extensiones, los diagnósticos— se escribió entero dentro de un fichero bash que sólo carga el terminal. No estaba roto: estaba en una dirección desde la que nadie más podía llamarlo. El único síntoma era un grep que devolvía cero, y un cero se lee como «todavía no» en vez de como «no puede».
Caso 5/0: el despacho que sólo hablaba con el terminal

🩺 Mostrar historia clínica → 📋 Protocolo de sesión →

Historia clínica · Patología del Software

El órgano funcionaba. Resolvía el alias, distinguía las dos vías de activación, aplicaba la puerta de extensiones y diagnosticaba mejor que la media del árbol. Estaba implantado dentro del punto de entrada del terminal, que es el único sitio del proyecto por el que ninguna otra superficie pasa.

Historia Nº 5/0Diagnóstico: ANTI-PAP · LA POLÍTICA IMPLEMENTADA EN EL PUNTO DE ENTRADA, Y POR ESO SIN SALIDA DEL TERMINALEstado: RESUELTO · CON DEUDA DECLARADA
El paciente no llegó por esto. Llegó por una pregunta de urbanismo — si un dominio necesita un subdominio propio y un directorio propio — y la exploración descubrió, de paso, que la capacidad sobre la que se estaba discutiendo dónde alojarla no salía del terminal.
Mostrar cuadro
punto de entrada
El envoltorio de shell que recibe argv y decide a quién llamar. Lo carga el terminal y nadie más: el daemon lanza nu -c con current_dir(root) y lo salta entero.
módulo nu
Un fichero .nu bajo reflection/modules/ que cualquier llamante carga con use desde un root. Es la forma declarada de este proyecto para que una capacidad alcance más de una superficie.
célula biop
Comprobación tipada con su afirmación, su severidad y su conducta ante lo que no puede leer. on_unknown = 'Refuse significa que no poder mirar NO cuenta como haber mirado.
dos vías de activación
Un dominio se abre por repo_kind del manifiesto (ADR-012) o por la presencia de su portador de bond (ADR-073). Ninguna colapsa a la otra, y la puerta de required_extensions ata sólo a la primera.

Protocolo para declarar, versionar y verificar esto → ontoref.dev

El doble balance — lo que costó, y lo que dejó

Tras la intervención, el despacho responde por nu -c "use reflection/modules/domain.nu *; ...", que es la forma exacta con la que el daemon ya llama a validate y a describe. La paridad se midió sobre los seis dominios del árbol y sobre un token desconocido, que debe devolverse sin tocar para que el fall-through siga funcionando.

Lo que costó el crimen

  • Rutas de despacho de dominio alcanzables desde el daemon 0
  • Puntos donde el daemon SÍ delega en un módulo nu 5
  • Superficies que la capacidad alcanzaba, de las declaradas 1 de 4
  • Envoltorios que llevaban la política 1 de 2
  • Ficheros del daemon que llaman a nickel por su cuenta 9
  • Callejones sin salida, todos del agente 3

Lo que la intervención dejó

  • Política movida del envoltorio al módulo +189 líneas
  • Política retirada del envoltorio −95 / +70
  • Paridad medida contra el bash enviado 6/6 + fall-through
  • La célula nueva, bajo mutación deliberada EXIT 0 → 1
  • Envoltorios que despachan, tras saldar la deuda 2 de 2
  • Superficies que la capacidad alcanza HOY 1 de 4
  • Deudas declaradas pagadas en la misma sesión 3 de 3

El caso se archiva RESUELTO CON DEUDA DECLARADA, y la palabra DECLARADA hizo trabajo el mismo día: de las tres deudas escritas, dos se pagaron al leerlas en voz alta. rg no estaba declarado como capacidad —el hueco que jq ya había tenido—, así que se declaró y la célula pasó de no poder mirar a responder por su arnés. Y el envoltorio de fuente ganó detección, con lo que code/ontoref pm scope responde donde antes moría en nu::parser::extra_positional. Pagar la segunda abrió un hueco nuevo —dos despachadores, una célula vigilando uno— y la célula pasó a vigilar los dos; una mutación de comprobación reveló además que su mitad de delegación la satisfacía un COMENTARIO, y ahora está atada a la llamada. Queda 1 de 3, la que no tiene mecanismo: la premisa importada de la memoria del agente. La capacidad sigue alcanzando 1 de 4 superficies, y eso no es deuda sino secuencia — el módulo es la condición para las otras tres, no las otras tres. Este caso es uno de los cuatro errores de aquella tarde; la lectura amplia de los cuatro —y de por qué son hábitos humanos ordinarios antes que fallos de máquina— está en El espejo que no adula.

El punto de abandono — lo que no sale en la tabla

Lo que dejó de vigilarse no fue el despacho: fue la pregunta «¿desde dónde se puede cargar esto?». Toda capacidad de este proyecto la respondió alguna vez de la misma forma, poniendo su lógica en un módulo. Ninguna regla obligaba a responderla, así que la única que no lo hizo tampoco tuvo que declararlo.

Diagnóstico diferencial — lo que se descartó

«El orden correcto no es CLI antes que daemon: es el daemon como servicio antes que cualquier afirmación sobre rutas de dominio»“Descartado por el humano CON CÓDIGO, no con argumento: cinco puntos de delegación en nu (api.rs:1825 y 1982, mcp/mod.rs:2343, 2487 y 2559), los cinco con current_dir del root. Yo había generalizado desde domain.rs, que es justo el trozo que NO delega.”Refutado con código
«La memoria de este proyecto dice que las rutas se hornean en build»“Descartado abriendo el fichero: su cuerpo dice SUPERSEDED IN PART y `domains` está dentro del superset horneado. La premisa venía de la línea-gancho de un índice, no del fichero que esa línea señala.”Premisa sin abrir
Dar por verde una célula cuyo oráculo no llegó a ejecutarse“Descartado por mutación: `nickel export` fallaba sin `--import-path` y se ejecutaban cero bytes. El verde no atestiguaba el sujeto, atestiguaba un fichero vacío.”Oráculo vacío

Etiología — la causa — El emplazamiento, verbatim

# install/ontoref-global — bash
_dispatch_domain() {
  # Two activation paths coexist (ADR-012 repo_kind ⊕ ADR-073 bond; ADR-076 G-1=A).
  local bond_carrier="${ONTOREF_PROJECT_ROOT}/.domains-ontoref/${first_arg}/bonds.ncl"
  ...
  if [[ -z "$activation_path" ]]; then
    echo "  ontoref: domain '${first_arg}' is not available for this project" >&2
    exit 1
  fi
}

El proyecto tenía además DOS envoltorios, y sólo uno llevaba esta política: grep -c _dispatch_domain code/ontoref → 0. Por eso code/ontoref pm scope moría con nu::parser::extra_positional mientras el binario instalado respondía. Dos síntomas, una causa, y ninguno era legible desde el otro.

Tratamiento — La terapia

# .ontoref/reflection/modules/domain.nu
export def "domain dispatch" [domain_id: string, ...args: string] {
  let id  = (domain resolve-alias $domain_id)
  let act = (domain activation $id)
  ...
}

# la misma forma con la que el daemon ya llama a validate y a describe:
$ nu -c 'use reflection/modules/domain.nu *; domain dispatch "pm" "scope"'
  role-scope  /Users/Akasha/Development/ontoref
  ADRs 100 · modes 35        EXIT=0

La detección se queda en bash a propósito, y con su razón escrita en el propio fichero: «¿es argv[1] un dominio?» se pregunta en cada invocación de ontoref y no debe costar un arranque de nu. La política no tenía esa excusa.

Pronóstico

Lo incómodo del caso es que no hay nada que reparar en el código movido: se movió casi intacto, y la paridad se midió dominio a dominio contra el bash enviado. Lo que falló fue una decisión de emplazamiento tomada una vez, hace meses, sin que nada volviera a preguntarla — y que nadie podía notar leyendo el código, porque el código funcionaba. El único síntoma disponible era un grep que devolvía cero, y un cero se lee como «todavía no» en vez de como «no puede».

La política vive en el punto de entradaLa célula capability-reachable-beyond-the-terminal ('Block): el módulo debe declarar domain dispatch y el envoltorio no puede volver a invocar un commands.nu. La DETECCIÓN se queda en bash —se pregunta en cada invocación y no debe costar un arranque de nu—; la INVOCACIÓN no.
Una premisa importada de la memoria del agenteADR-074 nombraba el patrón —un portador consultado en lugar del gobernador— con su ámbito apuntando a CLAUDE.md, a MEMORY.md y a los ganchos, y sin nada que los recorriera: la regla no obligaba a nadie justo donde se escribió. La célula memory-hook-carries-no-stale-fact los recorre. Un fichero que se declara superado debe decirlo en su gancho, y ninguno puede faltar del índice.
Verde sobre un oráculo que no llegó a ejecutarseMutación obligatoria antes de declarar verde: introducir la invocación directa en el envoltorio y comprobar que el EXIT pasa de 0 a 1 nombrando install/ontoref-global:731. Un verde que no se ha visto ponerse rojo no atestigua nada.
No poder mirar, contado como haber miradoEste sostuvo, y aguantó el tiempo justo. on_unknown = 'Refuse hizo que la célula informara I DID NOT LOOK en vez de pasar, porque el registro no declaraba rg — el mismo hueco que jq tuvo. La ignorancia quedó nombrada, se leyó y se cerró declarando la capacidad; entonces la célula pudo responder por su arnés y no sólo a mano.
Una capacidad con dos puertas y una sola gobernadaAl saldar la deuda, code/ontoref ganó detección y la célula habría vigilado uno de dos despachadores. Vigila los dos, con el conjunto DECLARADO y no descubierto por comodín: un comodín que deja de casar no vigila nada y pasa en silencio.

La pauta — la sesión, repetida con protocolo

Lo que se pidió — reconstruido de .coder/sessions/2026-08-25-172344-fix-after-coder-session-2026-08-25-0.txt:6 — el prompt de apertura verbatim, con su número de línea. El mismo fichero conserva en :352 la refutación humana que descartó el primer callejón y en :421 la orden de mover el despacho al módulo.

después de la sesión .coder/sessions/2026-08-25-012742-tengo-la-sensacin-de-que-mucho-de-lo-que-hay.txt
no me quedó claro si necesitamos un subdominio en outreach tipo pragma.ontoref.dev
y un directorio propio dentro de ontoref o fuera

Lo que había que pedir

Antes de opinar sobre dónde vive un dominio, mide desde qué superficies se alcanza hoy su
despacho y por qué. Y cualquier premisa que venga de tu memoria: ábrela, cítala por fichero y
línea, o no la uses.
MicrotareaVerificable
Medir cuántas rutas del daemon despachan un comando de dominio, antes de proponer nadagrep -rn "commands.nu\|domain_command" code/crates/ontoref-daemon/src | wc -l → 0
Medir el patrón de delegación que YA existe, en vez de inferirlo de un ficherogrep -rn 'use reflection/modules/' code/crates/ontoref-daemon/src --include=*.rs → 5 líneas: api.rs:1825, api.rs:1982, mcp/mod.rs:2343, 2487, 2559
Citar toda premisa de memoria por fichero y línea antes de partir de ellaabrir el fichero de memoria citado y buscar su propia caducidad: grep -n 'SUPERSEDED' <fichero> → el cuerpo dice SUPERSEDED IN PART y domains está en el superset horneado
Escribir la célula y verla FALLAR antes de mover una línea de políticaañadir la invocación directa al envoltorio → EXIT 0 → 1 nombrando install/ontoref-global:731; revertir → EXIT 0
Comprobar la paridad del módulo contra el bash enviado, dominio por dominiodomain resolve-alias + domain activation sobre pm·prov·rustelo·librosys·personal·framework y un token desconocido → pm=layer1, prov=bond, rustelo=bond, desconocido devuelto sin cambio

La puerta antes de delegar: La célula capability-reachable-beyond-the-terminal escrita y observada FALLANDO antes de mover una sola línea. Sin ella, el movimiento se declara hecho y nada distingue «la política está en el módulo» de «la política está en los dos sitios», que es la forma en que este defecto vuelve.

El disparador de ADR: El momento en que se decidió que la DETECCIÓN se queda en el envoltorio y la INVOCACIÓN no. No es una preferencia de estilo: es una regla que hereda cualquier capacidad futura, y separa un coste por invocación de una política. Ahí habría disparado adr?, no tres pasos después.

La profilaxis — qué exige hoy la lección

  • La regla, argumentada y con su reparto de severidades: el punto de entrada detecta, nunca invocaadr:101/entry-point-detects-never-invokes
  • La claim general, Soft y con su verificador ausente nombrado (no hay oráculo estático para «política»)adr:101/capability-policy-is-not-entry-point-only
  • El despacho de dominio vive en un módulo, no en el punto de entradacontract:.ontoref/biop/capability-reachable-beyond-the-terminal.ncl#nucleus.cmd
  • La política retirada del envoltorio, con su contrato de entorno declarado.ontoref/reflection/modules/domain.nu — domain dispatch · domain activation · domain resolve-alias
  • El envoltorio conserva la DETECCIÓN y escribe por qué ese es el límitecode/install/ontoref-global — cabecera de _dispatch_domain
  • El envoltorio de fuente también despacha: code/ontoref pm scope respondecode/ontoref — _dispatch_domain, delegando en el módulo, nunca invocando
  • La célula vigila LOS DOS envoltorios, y su oráculo es la llamada, no la palabracontract:.ontoref/biop/capability-reachable-beyond-the-terminal.ncl#nucleus.cmd
  • rg declarado como capacidad: la célula puede responder por su arnés.ontoref/reflection/capabilities.ncl — capability rg
  • Un gancho de índice de memoria no puede llevar un hecho caducado, ni faltarcontract:.ontoref/biop/memory-hook-carries-no-stale-fact.ncl#nucleus.cmd
  • Un almacén de memoria ausente se informa unknown, nunca como acusación.ontoref/reflection/modules/checks.nu — firma «no agent memory store» en harness-failure

Deuda declarada: Las tres deudas se pagaron, y lo que queda es un LÍMITE declarado, no una tarea pendiente: la regla general que se pidió —«un gancho lleva un puntero, nunca un hecho»— no tiene oráculo estático, porque distinguir un puntero de una afirmación es una lectura y no un rg. Lo que sí se comprueba es el modo de fallo que costó: un hecho CADUCADO en un gancho, y una memoria SIN gancho. El límite se declara dentro de la propia célula, donde lo encuentra quien la lea.

Del vocabulario del proyecto (6)
.domains-ontoref/
El contenedor del lado consumidor que lleva un proyecto vinculado: una subcarpeta por dominio vinculado (`.domains-ontoref/<dominio>/`).
Dominio (extensión CLI por repo_kind)
Una extensión CLI activada por repo_kind bajo code/domains/{id}/: el repo_kind de un proyecto enciende su dominio, dando comandos conscientes del tipo de proyecto (p.
Núcleo
El `.ncl` de una célula: afirmación, evaluación e interfaz, más la identidad y el linaje que la hacen ser la misma célula en tejidos distintos.
Vínculo
Relación tipada entre proyectos (y sus domains) dentro del marco ontoref — distinta de un `link`, que es una referencia genérica entre nodos (el esquema `ln`/Link).
adr?
Procedimiento de evaluación que se invoca al final de una sesión o feature.
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.

Vocabulario completo del proyecto →

¿Te ha resultado útil? Valóralo
¿Tienes algo que aportar? Cuéntame qué opinas, qué sugieres, o si seguimos explorando este tema.
· lecturas

Usamos cookies para que este sitio funcione, entender el uso del servicio y apoyar acciones de marketing. Política de cookies para más información.