ADR 0109 — La salud del lint se lee junta
Estado: aceptado · Fecha: 2026-11-07
Enmienda el punto de la hoja de ruta del ADR 0105 que pintaba los hallazgos del resto en las hojas de Docs y config. La cobertura de cada artefacto sigue siendo la del ADR 0107. El riesgo no cambia: sigue leyendo scopeHealth de cada fichero de código (ADR 0108).
El ADR 0110 enmienda la decisión 3: el código puede quedar
complete cuando cada herramienta declara su universo, sin esperar a que el artefacto traiga una
enumeración que nunca se escribía.
Contexto
Sección titulada «Contexto»El código se guarda en lint.repmod.json y los documentos en lint-rest.repmod.json. Cada uno tiene su meta.tree. La ficha de Código leía solo el primero, así que un legado 1.2 vacío salía como cobertura desconocida y los doc/broken-link acababan en Docs y config, mezclados con el catálogo.
Sumar los dos en la interfaz duplica la cuenta en cuanto alguien vuelve a sumar. Hace falta un solo adaptador.
Decisión
Sección titulada «Decisión»- La suma vive en una función pura. No escribe artefactos, no cambia
domainy no guarda salud por carpeta.
function scopeHealthMerged( artifacts: readonly (LintArtifact | null)[], scope: HealthScope, snapshot?: HealthSnapshot): MergedScopeHealth- Los hallazgos se funden por ruta canónica. Cada uno conserva
domain,toolyruleId. Si el artefacto de código no dice qué herramienta escribió el mensaje —eslint y oxlint comparten fichero—, la herramienta se infiere por elruleIddemeta.systemsy el hallazgo quedainferred. Si las dos podrían haberlo escrito, no se duplica:tooljunta las candidatas.anchordice el mapa (codeorest) y la ruta, para que la UI pueda abrir el nodo. - La cobertura va por origen y por ruta. Un documento enumerado sale
enumerateden susmeasuredPaths. Un legado salelegacy/unknownen las suyas, con el motivolegacy-version(«medido con una versión anterior»).summary.measured > 0de un 1.0–1.2 no lo pasa acomplete. Un código 1.3 con ESLint enumerado yeligiblePaths: null, y oxlint enunknown, sigue enpartial: no se fuerza acomplete. - El agregado solo es limpio si todos los dominios aplicables a la selección están en
complete, confresh === truey cero hallazgos. Un legado o ununknownaplicable no es limpio. Un dominio que la ruta canónica deja fuera no cuenta. - En la raíz no se recortan los documentos con la lista de rutas del snapshot de código. En carpeta y fichero manda la ruta canónica.
meta.treeno se funde. Cada origen guarda el suyo y su frescura. Si el snapshot es el árbol del otro origen, la frescura de este queda ennull: no se declara viejo y no se finge que los dos árboles son uno.- El riesgo no llama a
scopeHealthMerged. Sigue leyendo el artefacto de código. - Docs y config lee el catálogo, no los hallazgos.
systemActivityderivaactiveRulesycountState(known-complete,partialounknown) demeta.systems. No se escriben en el fichero. Oxlint con la nota «no se enumeran» y sin lista esunknown, nunca cero. - Las reglas del sistema
codarchsalen decodarchActiveRulesenpackages/lint/src/rest.ts: el enlace roto siempre, y huérfanos, frontmatter y gemelas solo si el bloquedocs:los enciende. No salen de los mensajes.buildRestLintlas escribe enmeta.systems[].rules, campo que ya existía.
Checksum
Sección titulada «Checksum»El checksum del artefacto sigue siendo el de { domain, tools, systems, files, coverage }. countState, activeRules, inferred y anchor no entran: se calculan al leer.
Escribir rules en el sistema codarch sí cambia el checksum de un lint-rest.repmod.json nuevo, porque systems ya formaba parte de la entrada. Un artefacto ya guardado no se recalcula: readLintArtifact conserva el checksum del fichero. Un sistema sin rules se sigue leyendo; el catálogo, si falta la lista, enseña codarchRuleCatalog() y no los hallazgos.
Consecuencias
Sección titulada «Consecuencias»- La ficha de Código enseña la salud y los hallazgos de los dos dominios, filtrados por la selección. Docs y config no enseña cuentas de hallazgos ni ficheros afectados.
- Un
.mdno es un nodo del mapa de código: las extensiones del análisis no lo incluyen. Está en el mapa del resto. Elanchordel hallazgo apunta a ese mapa. Si la ficha de código no tiene el nodo, el botón no puede seleccionarlo ahí. - La frescura de los documentos no se verifica contra el checksum del código. Con los dos árboles distintos, el agregado no se llama limpio.
Alternativas descartadas
Sección titulada «Alternativas descartadas»- Reescribir los dos artefactos en uno. Un
meta.treeno puede firmar dos árboles. - Sumar en cada panel. La segunda suma no cuadra con la primera.
- Tratar el legado con
measured > 0como verificado. El número no dice qué rutas se miraron. - Forzar el código 1.3 a
complete. ESLint deja el universo ennully oxlint no enumera: erapartiala propósito. El ADR 0110 cambia la premisa: ahora las dos herramientas pueden declarar su universo. - Guardar
countStateen el fichero. Obligaría a un campo nuevo en el checksum para un dato que sale de la nota y derules.
Hoja de ruta
Sección titulada «Hoja de ruta»Sin fase nueva.
- ✅
scopeHealthMerged, el catálogo concountStatey las reglas decodarchen el productor. - ✅ La ficha de Código lee los dos orígenes. Docs y config queda en el catálogo.
El registro de lo hecho vive en el feed de la guía.