Expediente 2/8: la nota que apagó la alarma

El caso del comentario que declaró segura la forma que nadie había mirado, y del siguiente autor que lo creyó: dos hojas de estilo leídas, ocho cargadas, cero consultas al navegador

Jesús Pérez
Un arreglo de CSS correcto dejó escrita, en su propio comentario, una frase que declaraba segura la forma que nunca se renderizó. Siete horas y media después el siguiente autor la leyó, la creyó, y diagnosticó el fallo razonando sobre dos hojas de estilo que la página ni siquiera carga. Una consulta a getComputedStyle devolvía la respuesta entera; se hicieron cero. Lo detectó una captura de pantalla del operador, jamás un check. ADR-072 ya declara que un mecanismo declara su extensión y que la página es la publicación: tres constraints Hard que pasaron de largo, porque gobiernan checks y esto era prosa.
Caso 2/8: la nota que apagó la alarma

🕵️ Mostrar expediente completo → 📋 Protocolo de sesión →

Expediente · Depto. de Homicidios de Código

Un arreglo de CSS correcto dejó escrita, en su propio comentario, una frase que declaraba segura la forma que nadie había renderizado: «so every fenced block with a language was fine». Siete horas y media más tarde el siguiente autor —otro agente— la leyó, la creyó, y diagnosticó el fallo razonando sobre dos hojas de estilo que la página ni siquiera carga. Cero consultas al navegador. La única que hacía falta habría dado la respuesta entera. Lo detectó el operador, adjuntando la captura de un bloque de código ilegible.

Caso Nº 2/8Clasificación: ANTI-PAP · UNA NOTA DECLARÓ SEGURA LA FORMA QUE NADIE HABÍA MIRADOEstado: ABIERTO
Mostrar glosario
extensión declarada (ADR-072)
Un mecanismo dice qué abarca, y un check puede decir «esto no lo miré». El verde de un check es una afirmación sobre su propia extensión, jamás sobre el mundo. La frase que abre este caso hacía lo contrario: afirmaba cobertura sobre una forma que nunca se renderizó.
la página es la publicación
Regla dura de la serie y constraint de ADR-072: un .ncl que valida, un .md que se regenera y un gate en verde son tres afirmaciones sobre FICHEROS. Lo que el lector recibe es la página. Aquí el diagnóstico se construyó sobre dos ficheros que la página ni siquiera carga.
especificidad
El desempate de CSS. `pre { color }` es (0,0,1); la regla anidada de prose que ganaba es (0,1,0). Un selector de clase gana a uno de elemento SIEMPRE, sin importar el orden ni las buenas intenciones. El arreglo anterior nunca ganó ese desempate, y su comentario daba por hecho que sí.
folklore
La palabra que este repositorio usa para una regla que vive donde ninguna superficie y ningún check pueden leerla. Un comentario de CSS es folklore con permisos de escritura: se versiona, se revisa, se lee con confianza — y nada comprueba que lo que afirma sea cierto.
declarado dos veces
El patógeno de la serie. Aquí la segunda copia no es código: es la NOTA sobre el código. El alcance real de una regla está en la cascada renderizada; la nota lo repetía en prosa, y cuando las dos discreparon ganó la prosa, porque es la que se lee primero.

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

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

Lo que costó creerse la nota

  • Hojas de estilo sobre las que se construyó el diagnóstico 2
  • …de ellas, cargadas por la página 0
  • Hojas que la página sí enlaza 8
  • Consultas al DOM antes de declarar la causa 0
  • Consultas al DOM que bastaron para tenerla entera 1
  • Bloques de código del post 3
  • …ilegibles en modo claro 2
  • Contraste del texto invisible (#e5e7eb sobre #f8fafc) 1.16:1 · AA exige 4.5
  • Especificidad de la regla que se creyó ganadora 0,0,1
  • Especificidad de la que ganaba de verdad 0,1,0
  • Arreglos escritos antes de que uno resolviera el síntoma 2
  • Lenguajes del post registrados en el bundle de hljs (nu · nickel) 0
  • Horas que la frase estuvo en el árbol antes de cegar al siguiente autor 7h34m (04:07:40 → 11:42)
  • Verificaciones propias que pasaron en verde estando ciegas, ese mismo día 1
  • Ficheros del MISMO commit que ya contenían la refutación de la frase 1
  • Distancia entre la afirmación y su refutación un fichero · cero commits

Lo que el caso dejó

  • Bloques legibles en claro tras el arreglo real 3 de 3
  • Contraste medido tras el arreglo (claro · oscuro) 9.9:1 · 11.87:1
  • Correcciones escritas dentro del comentario que mintió 2
  • Punteros verificados en lesson_codified_in 5
  • Gates que impidan repetirlo 0 → deuda declarada

Los sospechosos — las pistas falsas

La nota del arreglo anterior, que declaró segura la forma no mirada“Yo describía lo que el arreglo tocaba, y en eso no me equivoqué: el <pre> pelado era el caso de los expedientes. Que la frase siguiente hablara de una forma que nadie renderizó no la hace mentira: la hace no comprobada. Nadie me pidió una medición para escribirla.”la-nota
Dos hojas de estilo que la página no carga, leídas como si fueran la cascada“Estábamos en el fichero correcto. app.min.css y site.min.css contienen exactamente las reglas de prose que explicaban el síntoma — palabra por palabra. Que esta página cargue otras ocho no lo dice ninguna de las dos.”hojas-fantasma
La paleta github-dark, culpable parcial y coartada perfecta“Yo pinto tokens sobre fondo oscuro y lo hago bien. Nadie me sirvió condicionalmente: me enlazaron siempre, después de custom.css, y encima acerté a medias — los tokens estaban mal en claro.”github-dark
La caché del navegador (max-age=86400), que explicaba el síntoma sin ser la causamax-age=86400 es lo que se me pidió. Y el síntoma que producía era idéntico al real, lo cual me convierte en la explicación más cómoda: el navegador veía algo viejo. Era cierto, y no era la causa.”cache
hljs sin módulo para nu ni nickel — el mecanismo real, invisible en todo fichero“No tengo módulo para nu ni para nickel, así que me rindo en silencio y no añado la clase .hljs. Eso no aparece en ningún fichero del repositorio. Solo en la página.”hljs-sin-modulo

El arma — El arma · una frase que ningún check respalda

/* custom.css — comentario del arreglo anterior, commit 3294761, 04:07:40 */

   It only bites the BARE <pre>. `pre code` already reads `--code-text`,
   which does flip, so every fenced block with a language was fine
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

# Ningún check respalda esa frase. Ninguna página con un fence etiquetado
# se renderizó para escribirla. A las 11:42 el operador adjuntó la captura
# de un fence ```nu ilegible: la forma declarada segura.

El arreglo anterior fue bueno. Corrigió un <pre> pelado que en modo claro salía casi blanco sobre casi blanco, y lo documentó con el detalle que esta serie exige. Después escribió una frase más:

It only bites the BARE <pre>. pre code already reads --code-text, which does flip, so every fenced block with a language was fine

Ningún check respalda esa última línea. Ninguna página con un fence etiquetado se renderizó para escribirla. Es una afirmación sobre una forma que el autor no miró, colocada justo donde el siguiente lector la va a leer antes que la regla.

A las 11:42 el operador adjuntó una captura: un fence ```nu gris lavado, ilegible. La forma declarada segura.

Y lo que hace el caso es lo que pasó después. El siguiente autor no ignoró la nota: la usó. Buscó la causa donde la nota decía que no estaba —en la paleta de tokens— escribió un arreglo para eso, y lo declaró resuelto sin medir nada. Cuando el operador preguntó «¿por qué las correcciones css no se ven?», el diagnóstico llevaba construido sobre app.min.css y site.min.css: dos ficheros que contienen exactamente las reglas que explicaban el síntoma, y que esta página no carga. Ocho hojas enlazadas, ninguna de las dos entre ellas.

Una consulta a getComputedStyle devolvía la respuesta entera. Se hicieron cero.

Y hay una vuelta de tuerca que sale del propio git show. El commit 3294761 toca dos ficheros: custom.css (+91) y gen-expediente.nu (+56). En el segundo, su autor escribió que la primera reparación de este mismo fallo «resolvía contra una hoja que este sitio ni siquiera carga» — el hecho exacto que siete horas después nadie usó. El conocimiento existía, en el mismo commit, en el fichero de al lado. Lo que no existía era su co-locación con la afirmación que lo desmentía.

El giro — El arreglo · una consulta al DOM, y la cascada que de verdad ganó

// una consulta, y la respuesta entera:
[...document.querySelectorAll('.post-content-body pre')].map(pre => {
  const code = pre.querySelector('code');
  return { lang: code.className, ink: getComputedStyle(code).color };
});

// language-nu               #e5e7eb   ← sin clase .hljs, nada lo pisa
// language- hljs sql        #334155   ← hljs lo rescató con !important
// language-nickel           #e5e7eb
//
// Dos bloques, una página, resultados opuestos.
// La diferencia nunca fue el tema: era si existía el módulo del lenguaje.

Medido en el navegador, en modo claro, antes de tocar nada:

bloqueclase del <code>tintacontraste
0language-nu#e5e7eb1.16:1
1language- → hljs sql#3341559.9:1
2language-nickel#e5e7eb1.16:1

AA exige 4.5:1. Los bloques 0 y 2 no tienen clase .hljs porque el bundle de hljs no trae módulo para nu ni para nickel: highlightElement se rinde y no marca nada. El bloque 1 sí se marcó, y entonces .hljs { color: … !important } lo rescató.

Y la regla que ganaba en los dos casos perdidos estaba en website.css, anidada:

:is([prose=""]) :where(pre):not(…) { color: var(--un-prose-pre-code) }   (0,1,0)
:where(pre code):not(…)            { color: inherit }

Contra eso, pre { color: var(--code-text) } es (0,0,1). Pierde. El arreglo anterior nunca ganó ese desempate — ni para los posts ni para los expedientes.

Entonces, ¿qué arregló los expedientes? Esto, en gen-expediente.nu:

.exp pre { color: var(--exp-ink) }        (0,1,1)  →  gana a prose (0,1,0)

La clase .exp que envuelve cada expediente sube la especificidad justo lo suficiente. Y está en el mismo commit 3294761 — 91 líneas en custom.css, 56 en gen-expediente.nu, un solo autor, una sola madrugada. Con un comentario que dice, palabra por palabra, que la primera reparación «resolvía contra una hoja que este sitio ni siquiera carga».

El conocimiento no faltaba. Estaba a cincuenta líneas, en otro fichero del mismo commit — y no junto a la afirmación que lo refutaba.

El arreglo real sube la especificidad a (0,1,2), en las dos formas —clase y atributo— porque el cuerpo del post lleva class="prose" y la regla de UnoCSS está escrita para [prose=""]. Dar por hecho cuál aplicaba es cómo se llegó a creer que el anterior funcionaba.

Después, otra vez medido: 3 de 3 bloques a #334155, 9.9:1 en claro y 11.87:1 en oscuro.

El veredicto

Tres constraints Hard ya dicen lo necesario — un mecanismo declara su extensión, un check puede decir «esto no lo miré», la página es la publicación — y ninguna alcanzó la frase que abrió este caso, porque gobiernan CHECKS y esto era un COMENTARIO. Un comentario es folklore con permisos de escritura: se versiona, se revisa, viaja con el fichero y se lee antes que la regla que explica, y nada comprueba que lo que afirma sea cierto. El patrón de la serie es «declarado dos veces»; aquí la segunda copia no es código, es la nota sobre el código, y cuando las dos discreparon ganó la prosa porque es la que se lee primero. La coartada de la nota casi se sostiene, y por eso este caso importa más que un error: su autor estaba siendo cuidadoso, y el defecto no fue descuido sino una afirmación de cobertura escrita sin la medición que la respaldaba. Peor aún, y es lo que el git show reveló al escribir este expediente: el mismo commit toca dos ficheros, y en el segundo su autor había dejado escrito el hecho exacto que refutaba la frase del primero. El conocimiento no faltaba — faltaba su co-locación. Una afirmación y su refutación pueden convivir en un commit sin que nada las enfrente, porque el diff las presenta como dos cambios y no como una contradicción. Lo que no se cierra aquí queda dicho abajo: sigue sin existir nada que rechace un arreglo cuya justificación afirma una cobertura que nunca se renderizó. Y mientras se escribía este expediente, en la misma sesión, una comprobación propia pasó en verde sin poder mirar: un patrón que no cruzaba un salto de línea. Cuatro veces en un día — el mismo defecto, con y sin nota.

La nota afirmó una cobertura que nadie midióADR-072 a-mechanism-declares-its-extent → la extensión se declara, no se supone
El diagnóstico se hizo sobre ficheros, no sobre la páginaADR-072 the-page-is-the-publication → verifica la página, nunca el fichero
Se leyeron dos hojas que la página no cargagetComputedStyle → el sustrato, a una consulta
Una comprobación propia pasó en verde sin poder mirarADR-072 a-check-can-say-i-did-not-look → el verde declara su extensión
La refutación estaba en el mismo commit, en otro ficheroninguno hoy → nada co-loca la afirmación con su refutación
Nada impidió que la nota se escribiera sin respaldoninguno hoy → ADR-072 no alcanza a la prosa que justifica un arreglo

La reconstrucción — la sesión, repetida con protocolo

Lo que se pidió — reconstruido de refs:sessions/2026-08-06-la-nota-que-apago-la-alarma — extracto acotado en custodia. La sesión contiene el incidente Y la escritura del caso; autorreferencia declarada. Se identificó por el TRABAJO que hizo (editó custom.css, ejecutó las consultas al DOM), nunca contando menciones.

css el tema de los tags <pre> se arregó para los expedientes en modo light pero en los post no lo está
[captura adjunta del post servido en claro]

Lo que había que pedir

css el tema de los tags <pre> se arregó para los expedientes en modo light pero en los post no lo está
[captura adjunta]

Antes de escribir una sola regla:

1. Mide el DOM, no leas hojas de estilo. Para cada <pre> de la página: clases del
   <code>, `getComputedStyle(...).color` calculado, y el contraste contra el fondo.
   Pega la salida. Una causa sin esa tabla es una hipótesis, no un diagnóstico.
2. Comprueba QUÉ HOJAS CARGA la página antes de razonar sobre su cascada. Una regla
   leída en un fichero que la página no enlaza es una regla que no existe.
3. Compara con el caso que SÍ funciona (un expediente) en el mismo turno: la diferencia
   entre los dos es el diagnóstico, y adivinarla sale más caro que medirla.
4. Después del arreglo, vuelve a medir los mismos números. Y no escribas en el comentario
   ninguna afirmación sobre una forma que no hayas renderizado.
MicrotareaVerificable
Enumerar las hojas que la página carga de verdadcurl -s <url> | rg -o 'href="/styles/[^"]*"' pegado — cero razonamientos de cascada sobre ficheros ausentes de esa lista
Medir el color calculado de cada bloque de código en el tema reportadogetComputedStyle(code).color por bloque, con su clase — cero causas declaradas antes de esa tabla
Comparar contra el caso que funciona en el mismo turnoexpediente y post medidos con la misma consulta; la diferencia observada es la causa, no la inferida
Re-medir tras el arreglo, en los dos temascontraste calculado ≥ 4.5:1 en claro Y en oscuro — el arreglo se declara con el número, no con la intención
No afirmar cobertura no renderizada en el comentario del arreglotoda frase del comentario que hable de una forma nombra la medición que la respalda, o no se escribe

La puerta antes de delegar: Un arreglo de presentación no se declara hasta que el número medido en el DOM está pegado, antes y después, en el tema reportado. Sin eso el agente entrega su razonamiento sobre la cascada, no la página — que es exactamente lo que ocurrió: dos hojas leídas, cero consultas, y la única que hacía falta habría dado la respuesta entera.

El disparador de ADR: Ninguno nuevo: ADR-072 ya declara que un mecanismo declara su extensión y que la página es la publicación. Lo que falta no es la decisión, es el gate — ver lesson_debt.

La jurisprudencia — qué exige hoy la lección

  • Un mecanismo declara qué abarca; el verde es una afirmación sobre su propia extensión, nunca sobre el mundoadr:072/a-mechanism-declares-its-extent
  • Lo que el lector recibe es la página: un fichero que valida y un gate en verde son afirmaciones sobre ficherosadr:072/the-page-is-the-publication
  • Un check puede —y debe— decir «esto no lo miré» en vez de pasar en silencioadr:072/a-check-can-say-i-did-not-look
  • Verifica la página, nunca el fichero; y si un check y un lector discrepan, sospecha primero del transporte del checkqa:expediente-howto
  • Toda cifra sale de un log o un artefacto; la que no se puede trazar se cae del recuento en vez de estimarsemode:generate-expediente/gather_metrics

Deuda declarada: Nada rechaza hoy un arreglo de presentación cuya JUSTIFICACIÓN afirma una cobertura que nunca se renderizó. ADR-072 gobierna checks y mecanismos; un comentario de código no es ninguno de los dos, y por eso sus tres constraints Hard pasaron de largo por la frase que abrió este caso. Lo que lo saldaría: un gate que, ante un cambio en una hoja de estilo servida, exija en el mismo cambio el número medido en el DOM —antes y después, en los dos temas— y que rechace el commit sin él; medible con lo que ya existe (getComputedStyle y un cálculo de contraste), sin protocolo nuevo. Nombrado, no encogido de hombros, y NO sustituido por «revisar mejor los comentarios», que es una promesa de disciplina y es exactamente lo que falló: la frase la escribió alguien que estaba siendo cuidadoso.

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.

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.