Quality-Gate System — Critical Assessment, Catalog and Replication Playbook (Español)
Parte 1 — Veredicto y clasificación de madurez
Sección titulada «Parte 1 — Veredicto y clasificación de madurez»Calificación general: A− / “Avanzado”. Entre el ~5–10 % de los mejores proyectos. El sistema implementa de manera independiente varios patrones que el sector identifica explícitamente, lo cual constituye la señal de alineación más sólida (no copiamos una lista de comprobación; convergimos en las prácticas correctas).
| Marco de referencia | Nuestra situación | Calificación |
|---|---|---|
| OWASP DSOMM (5 niveles, 5 dimensiones) | Nivel 3 sólido, aproximándose al 4 en Intensidad de las pruebas y Profundidad estática. La mayoría de las organizaciones se sitúan en los niveles 1–2. | L3→L4 |
| OpenSSF Scorecard (18 comprobaciones) | Superamos CI-Tests, Code-Review, Dependency-Update-Tool, Fuzzing, SAST, Signed-Releases (procedencia), Token-Permissions, Vulnerabilities y Dangerous-Workflow. Carencias: Branch-Protection en main está desactivada; algunas acciones no están fijadas. |
~7–8/10 |
| SLSA (4 niveles) | npm publish --provenance + id-token: write + compilación alojada en GitHub = L2, aproximándose a L3. Falta un entorno de compilación reforzado/hermético para L3+. |
L2→L3 |
| SonarQube “Clean as You Code” | Filosofía idéntica: el ratchet garantiza la ausencia de regresiones (el código nuevo no empeora la métrica). Divergencia: Sonar recomienda pocas condiciones; nosotros tenemos ~46 controles (riesgo de fatiga). | Alineado, con matices |
| Patrón Quality-Ratchet | Implementación de referencia: ratchet + dedicatedGate + tightenSlack + --require-tighten + omisión controlada. Más sofisticada que la mayoría de los ejemplos públicos. |
Ejemplar |
| DORA 2024 | Muy sólido en el eje de estabilidad. Riesgo: unos controles exigentes pueden aumentar el tiempo de entrega — mitigado mediante la división de controles rápidos, aunque con una carencia de cobertura (véase la Parte 2). | Sólido (estabilidad) |
| OWASP LLM Top 10 (2025) | Cubrimos el riesgo n.º 1 (inyección de prompts) con una protección en tiempo de ejecución + promptfoo (evaluación) + garak (red teaming). Herramientas estándar del sector. | Cubierto |
| Pruebas de mutación | Stryker se ejecuta cada noche, con umbrales de 70/50 y 8 módulos críticos. Consenso del sector (60 % en código existente / 80 % en código nuevo, ejecución nocturna) — lo superamos. Carencia: la puntuación aún no utiliza un ratchet. | Casi logrado |
Parte 2 — Evaluación crítica (fortalezas + debilidades sinceras)
Sección titulada «Parte 2 — Evaluación crítica (fortalezas + debilidades sinceras)»Fortalezas (lo que está por encima de la media)
Sección titulada «Fortalezas (lo que está por encima de la media)»- Motor de trinquete multimétrica. El corazón del sistema. 24 métricas en
quality-baseline.json- 4 líneas base específicas, cada una con dirección (
up/down), tolerancia (eps), margen (tightenSlack) y el indicadordedicatedGate. Lo que se corrige permanece corregido: es el antídoto contra la entropía de la base de código.
- 4 líneas base específicas, cada una con dirección (
- Defensa en profundidad para la cadena de suministro. SAST (CodeQL/Sonar) + secretos (gitleaks con
useDefault) + SCA (osv/npm-audit/Trivy/Dependabot) + licencias + lockfile + SBOM + procedencia SLSA + Scorecard + refuerzo de workflows (zizmor). Pocas bases de código tienen una pila tan completa. - Antídotos contra la ley de Goodhart. Usar la cobertura como objetivo es un antipatrón clásico
(«cuando una medida se convierte en objetivo, deja de ser una buena medida»). Contamos con los
contrapesos: pruebas de mutación (miden si la prueba detecta el error, no solo si ejecuta
la línea),
check-test-masking(impide debilitar las aserciones para aprobar), umbrales mínimos de cobertura por módulo (obligan a probar el código de ALTO riesgo, no solo las partes fáciles) ycheck-pr-evidence(regla estricta n.º 18). - Controles contra alucinaciones y de coherencia. Una categoría poco común y valiosa:
check-known-symbols,check-fetch-targets,check-openapi-routesycheck-docs-symbolsgarantizan que la documentación, las especificaciones y los despachos mediante cadenas apunten a símbolos existentes. Detectan el «deterioro» que el linting y las pruebas no detectan. - Ciclo de vida consultivo→bloqueante. Los nuevos controles se incorporan como consultivos (no bloquean las fusiones mientras maduran) y después pasan a ser bloqueantes al final del ciclo. Esto reduce la fricción sin perder el nivel máximo de exigencia.
- Omisión controlada cuando falta infraestructura. Los analizadores (
--ratchet) terminan conexit 0si falla el binario o la red: la falta de infraestructura nunca bloquea una PR legítima. Ingeniería madura. - Cultura codificada. Las reglas estrictas +
trust-but-verify+ la lista de excepciones obsoletas + el control de evidencias convierten la disciplina en verificación automatizada.
Debilidades sinceras (carencias reales)
Sección titulada «Debilidades sinceras (carencias reales)»- 🔴 La separación de controles rápidos aún deja un vacío estructural.
quality.yml(PR→release/**) ahora ejecuta la comprobación de tipos, pruebas deterministas rápidas y una compilación de producción consultiva para las PR de código, pero todavía no ejecuta toda la superficie de PR de lanzamiento deci.yml(trinquetes de cobertura, artefacto de paquete, integración, E2E, SonarQube). La motivación (velocidad) es válida, pero el control debería estar donde se produce la fusión (shift-left). La mayor corrección estructural pendiente. - 🟠 Riesgo de proliferación y fatiga de controles. ~46 controles + 25 jobs es MUCHO. El propio Sonar advierte de que demasiadas condiciones provocan «fatiga de controles» y debates sobre prioridades, con el riesgo de que se ignore algún control. DORA advierte de que los controles pesados perjudican el tiempo de entrega. Lo mitigamos con niveles consultivos y trinquetes no absolutos, pero falta una revisión periódica del ROI de cada control (algunos microcontroles de sincronización de documentación se pueden consolidar).
- 🟠 La puntuación de mutación aún no es un trinquete. El antídoto más potente contra la manipulación de la cobertura es consultivo. Es el elemento pendiente de mayor valor (y ya está construido al 90 %).
- 🟡 Controles consultivos que deberían bloquear (con el alcance adecuado).
osv(vulnCount) yoasdiffson consultivos a pesar de tener líneas base congeladas. Que osv sea consultivo tiene sentido (un nuevo CVE en una dependencia antigua bloquearía una PR no relacionada), pero existe un término medio (bloquear solo vulnerabilidades CRITICAL+corregibles, como hicimos con Trivy). Que oasdiff sea consultivo implica que puede pasar un cambio que rompa el contrato. - 🟡 La seguridad en tiempo de ejecución solo se comprueba por la noche. schemathesis/garak/promptfoo/chaos/k6 se ejecutan por la noche. Es una decisión correcta (son lentos y necesitan un servidor activo), pero una PR puede introducir una regresión en la protección contra inyecciones que solo se detectará la noche siguiente.
- 🟡 La protección de la rama
mainestá DESACTIVADA.BRANCH_LOCK_TOKENbloquea las ramas de release, peromainno está protegida. Scorecard/DSOMM lo penalizan. Se requiere una acción del propietario. - 🟡 Configuración predeterminada de CodeQL; semgrep no está codificado. La configuración predeterminada
funciona (0 alertas), pero un
codeql.ymlconfirmado en el repositorio ofrece más control; semgrep se ejecuta mediante una plataforma externa en la nube y no está versionado en el repositorio.
Parte 3 — Catálogo completo de puntos de control de calidad (portable)
Sección titulada «Parte 3 — Catálogo completo de puntos de control de calidad (portable)»Las 12 categorías siguientes constituyen el «sistema de calidad» en formato reutilizable. Cada una enumera el objetivo (qué proteger), las herramientas que utilizamos y el equivalente independiente de las herramientas para reproducirlo en cualquier stack.
1. Estilo y formato (deterministas, rápidos)
Sección titulada «1. Estilo y formato (deterministas, rápidos)»- OmniRoute: Prettier + ESLint mediante lint-staged (pre-commit), 2 espacios/comillas dobles/100 columnas.
- Genérico: un formateador con corrección automática + un linter, ejecutados en pre-commit sobre los archivos preparados.
2. Tipos
Sección titulada «2. Tipos»- OmniRoute:
typecheck:core(bloqueante) +typecheck:noimplicit:core(orientativo) + umbral incremental detype-coveragedel 92.17% + presupuesto deanypor archivo. - Genérico: comprobación estricta de tipos en CI + métrica incremental de cobertura de tipos + presupuesto por archivo para
any/vías de escape.
3. Pruebas (intensidad)
Sección titulada «3. Pruebas (intensidad)»- OmniRoute: 2 ejecutores sin solapamiento (Node nativo + vitest), 8 particiones, cobertura global 60/60/60/60 + umbral incremental de ~76% + 8 mínimos por módulo para módulos críticos + pruebas de propiedades nocturnas + pruebas de mutación nocturnas.
- Genérico: ejecutor(es) de pruebas + mínimo absoluto de cobertura (evita el cero) + umbral incremental de cobertura (evita regresiones) + mínimos por módulo para código de alto riesgo (antídoto contra la ley de Goodhart) + pruebas basadas en propiedades para lógica pura + pruebas de mutación nocturnas como medida real de la calidad de las pruebas.
4. Política de pruebas (antimanipulación)
Sección titulada «4. Política de pruebas (antimanipulación)»- OmniRoute:
pr-test-policy(el código de producción requiere una prueba),check-test-masking(bloquea aserciones debilitadas),pr-evidence(una afirmación de éxito requiere un bloque de evidencias),test-discovery(cada prueba es recopilada por un ejecutor). - Genérico: control «código nuevo ⇒ prueba nueva» + detector de aserciones eliminadas/tautologías + requisito de evidencias (TDD o prueba viva) + garantía de que ninguna prueba quede huérfana fuera de los patrones glob.
5. Complejidad y salud del código (umbrales incrementales)
Sección titulada «5. Complejidad y salud del código (umbrales incrementales)»- OmniRoute: advertencias de ESLint (3769↓), duplicación con jscpd (5.72%↓), complejidad ciclomática+máximo de líneas (1800↓), complejidad cognitiva con sonarjs (753↓), código muerto/exportaciones sin usar con knip (339↓), tamaño por archivo (congelado, solo puede reducirse), dependencias circulares (Tarjan personalizado, bloqueante).
- Genérico: aplicar un umbral incremental a cada métrica de salud (advertencias, duplicación, complejidad ciclomática y cognitiva, código muerto, tamaño de archivos, ciclos de importación). La dirección siempre es «no empeorar».
6. Seguridad estática (SAST + secretos)
Sección titulada «6. Seguridad estática (SAST + secretos)»- OmniRoute: CodeQL (umbral incremental de alertas = 0), gitleaks (
[extend] useDefault=true— ¡crítico!), SonarQube, reglas de seguridad personalizadas (public-creds, error-helper, route-guard-membership, route-validation). - Genérico: SAST (CodeQL/Sonar/semgrep) con umbral incremental de alertas + escáner de secretos con conjunto de reglas predeterminado heredado (una configuración personalizada que reemplace la predeterminada = punto ciego) + controles de seguridad de Reglas Estrictas específicos del proyecto.
7. Cadena de suministro (dependencias)
Sección titulada «7. Cadena de suministro (dependencias)»- OmniRoute: osv-scanner + npm-audit + Trivy + Dependabot (SCA), license-checker (lista de permitidos SPDX), lockfile-lint (HTTPS+sha512+registro),
check-depscontra slopsquatting (lista de permitidos + antigüedad ≥72 h). - Genérico: SCA con múltiples fuentes + lista de licencias permitidas + comprobación de integridad del archivo de bloqueo + lista de dependencias permitidas con comprobación de antigüedad/typosquatting + bot de actualizaciones agrupadas.
8. Cadena de suministro (compilación y publicación)
Sección titulada «8. Cadena de suministro (compilación y publicación)»- OmniRoute: SBOM (CycloneDX + syft), procedencia SLSA (
--provenance), OpenSSF Scorecard (semanal), refuerzo de workflows (zizmor: artipacked→persist-credentials:false, envenenamiento de caché, permisos de tokens). - Genérico: generar una SBOM al publicar + procedencia firmada (SLSA L2+) + Scorecard programado + reforzar todos los workflows (tokens con privilegios mínimos, sin credenciales persistentes en checkouts que no realizan push, acciones fijadas por SHA).
9. Contratos y API
Sección titulada «9. Contratos y API»- OmniRoute: oasdiff (cambios incompatibles de OpenAPI), schemathesis (fuzzing de contratos nocturno), openapi-coverage (% de rutas documentadas, umbral incremental del 38.3%), openapi-security-tiers (especificación frente a protección de rutas).
- Genérico: comparación de contratos para detectar cambios incompatibles (oasdiff/buf) + fuzzing basado en propiedades contra la especificación (schemathesis) + cobertura de documentación con umbral incremental + coherencia entre especificación↔código.
10. Documentación e i18n (antideterioro)
Sección titulada «10. Documentación e i18n (antideterioro)»- OmniRoute: docs-sync (versiones reflejadas), docs-counts-sync (cifras de la documentación frente al código), env-doc-sync, doc-links, fabricated-docs, cli-i18n, i18n-ui-coverage (
--threshold=65+ umbral incremental del 80.1%). - Genérico: sincronizar versiones/cifras/variables de entorno entre la documentación y el código (mediante un control, no por confianza) + validar enlaces internos + cobertura de i18n con umbral incremental.
11. Antialucinaciones/coherencia (la categoría poco común)
Sección titulada «11. Antialucinaciones/coherencia (la categoría poco común)»- OmniRoute: known-symbols (despacho por cadenas ⇒ símbolo vivo), provider-consistency, fetch-targets (fetch del cliente ⇒ ruta real), docs-symbols, db-rules (Reglas Estrictas n.º 2/n.º 5), migration-numbering.
- Genérico: para cada «fuente de verdad duplicada» (registro, despacho por cadenas, referencias entre capas), un control que demuestre que ambos lados coinciden. Detecta el deterioro que la comprobación de tipos y las pruebas no detectan.
12. Resiliencia y dominio (específico del producto)
Sección titulada «12. Resiliencia y dominio (específico del producto)»- OmniRoute: caos (inyección de fallos), crecimiento del heap (fugas), k6 (prueba prolongada), promptfoo+garak (red team de LLM según OWASP LLM Top 10), las 3 leyes de resiliencia (circuit-breaker/cooldown/lockout).
- Genérico: identificar los modos de fallo de tu dominio y disponer de un control (aunque sea nocturno) para cada uno. Para aplicaciones de IA: red team contra inyecciones. Para sistemas distribuidos: caos + fugas + pruebas prolongadas.
Parte 4 — Plan de replicación para cualquier proyecto
Sección titulada «Parte 4 — Plan de replicación para cualquier proyecto»Constrúyalo en fases, cada una de las cuales aporta valor por sí sola. No intente implementar las 12 categorías a la vez — eso provoca exactamente la fatiga de controles sobre la que advierte la Parte 2. Cada nuevo control comienza como consultivo y se vuelve bloqueante cuando es estable.
La pieza central reutilizable: la «anatomía de un control de trinquete»
Sección titulada «La pieza central reutilizable: la «anatomía de un control de trinquete»»Todo el sistema gira en torno a este patrón de 3 archivos. Cópielo primero:
baseline.json— el valor congelado de la métrica +direction(up/down) +eps(antifallos intermitentes) +tightenSlack+dedicatedGate.collect-metrics.<ext>— ejecuta la herramienta, extrae el número y escribemetrics.json.check-ratchet.<ext>— comparametrics.jsonconbaseline.json;exit 1solo si ha empeorado más allá deeps;exit 0(omisión controlada) si faltaba la herramienta/infraestructura; con--require-tighten,exit 1si mejoró sin actualizar la línea base (consolida la mejora).
Una vez implementado esto, cada nueva métrica (cobertura, complejidad, advertencias, alertas SAST, tamaño del paquete, puntuación de mutación…) es simplemente una línea en la línea base.
Fase 0 — Base (semana 1)
Sección titulada «Fase 0 — Base (semana 1)»Existe CI; formateador + linter + comprobación de tipos + 1 ejecutor de pruebas + umbral absoluto de cobertura (p. ej., 60 %). El pre-commit ejecuta comprobaciones rápidas que pueden corregirse automáticamente. Resultado: ninguna PR rompe lo básico.
Fase 1 — El motor de trinquete (semana 2) — la base de todo
Sección titulada «Fase 1 — El motor de trinquete (semana 2) — la base de todo»Implemente los 3 archivos anteriores. Congele las líneas base de: advertencias, cobertura, complejidad, duplicación, código muerto y tamaño de archivo. Resultado: a partir de aquí, el código base solo puede mejorar.
Fase 2 — Profundidad del análisis estático (semana 3)
Sección titulada «Fase 2 — Profundidad del análisis estático (semana 3)»SAST (CodeQL/Sonar/semgrep) con trinquete de alertas; escáner de secretos (herede el conjunto de reglas predeterminado); SCA (osv/Dependabot) + lista de licencias permitidas + lockfile-lint. Resultado: las vulnerabilidades conocidas y los secretos filtrados no pasan.
Fase 3 — Cadena de suministro de compilación (semana 4)
Sección titulada «Fase 3 — Cadena de suministro de compilación (semana 4)»SBOM al publicar + procedencia firmada (SLSA L2) + Scorecard programado + refuerzo de los workflows (zizmor: permisos mínimos de tokens, sin credenciales persistentes y acciones ancladas a versiones específicas). Resultado: versiones trazables y a prueba de manipulaciones.
Fase 4 — Intensidad de las pruebas (semanas 5–6)
Sección titulada «Fase 4 — Intensidad de las pruebas (semanas 5–6)»Un segundo ejecutor si resulta útil; umbrales de cobertura por módulo para módulos críticos (anti-Goodhart);
pruebas basadas en propiedades para lógica pura; pruebas de mutación nocturnas → cuando llegue la primera puntuación, convierta
mutationScore en un trinquete. Resultado: la cobertura deja de ser una métrica de vanidad; las pruebas demuestran que detectan errores.
Fase 5 — Contratos y análisis dinámico (semana 7)
Sección titulada «Fase 5 — Contratos y análisis dinámico (semana 7)»Si existe una API pública: oasdiff (cambios incompatibles, bloqueante) + schemathesis (fuzzing nocturno). DAST/equipo rojo nocturno según corresponda al dominio. Resultado: los contratos no se rompen silenciosamente.
Fase 6 — Antialucinaciones y dominio (semana 8)
Sección titulada «Fase 6 — Antialucinaciones y dominio (semana 8)»Un control de coherencia por cada «verdad duplicada» del proyecto. Controles de modos de fallo específicos del dominio (para IA: equipo rojo contra inyección). Resultado: la degradación estructural y los fallos del dominio cuentan con una red de seguridad.
Fase 7 — Gobernanza (continua)
Sección titulada «Fase 7 — Gobernanza (continua)»- Ciclo consultivo→bloqueante para cada nuevo control.
stale-allowlist: cada supresión tiene una justificación + incidencia; se detectan las supresiones obsoletas.evidence-gate: toda afirmación de éxito en una PR requiere pruebas (una prueba o prueba viva).- Revisión trimestral del ROI por control (elimine o retire la financiación a los que no resulten rentables; combate la fatiga).
- Convierta las reglas estrictas de su proyecto en controles ejecutables.
Principios transversales (no negociables)
Sección titulada «Principios transversales (no negociables)»- Trinquete, no valor absoluto. Controle la ausencia de regresiones, no un número fijo (excepto los umbrales anti-cero).
- Umbral absoluto y trinquete juntos. El umbral evita el colapso; el trinquete evita la erosión gradual.
- Anti-Goodhart por diseño. Cada métrica objetivo necesita un contrapeso (cobertura ⇒ mutación + antienmascaramiento; umbrales por módulo para forzar las pruebas del código difícil).
- Omisión controlada. La falta de infraestructura nunca bloquea; solo bloquean las regresiones reales.
dedicatedGatepara métricas costosas. Las métricas que requieren un binario externo obtienen su propio script (con omisión), fuera del trinquete central síncrono.- Coloque el control donde se produce la fusión. No deje una brecha entre el control rápido y la fusión real (la lección de la separación de controles rápidos).
- Pocos controles bloqueantes, bien elegidos. Sonar/DORA: demasiadas condiciones = fatiga. Prefiera controles consultivos + trinquete antes que un muro de controles bloqueantes.
Parte 5 — Mejoras recomendadas (priorizadas, compatibles)
Sección titulada «Parte 5 — Mejoras recomendadas (priorizadas, compatibles)»P0 — mayor ROI, casi listo
- Ratchet de puntuación de mutación (después de que la primera ejecución nocturna de Stryker produzca valores). Antídoto clave contra el Goodhart de cobertura; ~90% completado.
- Cerrar el agujero restante de las verificaciones rápidas — promover la compilación de producción de
quality.ymldespués de su semana de advertencia y seguir trasladando las verificaciones deterministas exclusivas de las PR de publicación a la ruta PR→publicación. - Protección de ramas en
main(configuración del propietario) — mejora Scorecard y cierra la brecha de DSOMM.
P1 — valioso 4. osv/oasdiff → bloqueantes con el alcance adecuado — osv solo para vulnerabilidades CRITICAL+corregibles (en dos pasos, como Trivy); oasdiff bloquea los cambios incompatibles. 5. require-tighten → bloqueante (fin del ciclo) — consolida las mejoras en las métricas. 6. Revisión de ROI/tiempo por verificación en ci-summary — identificar y eliminar verificaciones lentas o de poco valor.
P2 — rendimientos decrecientes 7. SLSA L3 — compilador hermético/reproducible (generador SLSA de GitHub) si se desea avanzar desde L2. 8. Configuración de CodeQL incluida en el repositorio + semgrep versionado — mayor control/reproducibilidad. 9. Pruebas de humo DAST por PR — subconjunto rápido de schemathesis/promptfoo en los endpoints de mayor riesgo (no solo cada noche). 10. Panel de inestabilidad + métricas DORA — garantizar que las verificaciones no estén reduciendo la velocidad.
Parte 6 — Lecciones concretas de publicación (verificaciones que añadir en la Fase 9)
Sección titulada «Parte 6 — Lecciones concretas de publicación (verificaciones que añadir en la Fase 9)»Esta sección registra incidentes reales de cierres de publicaciones en los que faltaba una verificación, con evidencias concretas y la verificación propuesta. Cada elemento es un candidato para la Parte 5.
Lección de v3.8.27 (2026-06-17) — el «agujero de las verificaciones rápidas» permite que regresiones deterministas lleguen al día de publicación
Sección titulada «Lección de v3.8.27 (2026-06-17) — el «agujero de las verificaciones rápidas» permite que regresiones deterministas lleguen al día de publicación»Qué ocurrió. Durante /generate-release de v3.8.27, la PR de publicación (release/v3.8.27 → main)
fue la primera ejecución de la matriz completa de ci.yml en el ciclo integrado. Resultado: 12 fallos
a la vez — 3 pruebas deterministas + ~9 fallos intermitentes/del entorno. Ninguno era una regresión activa del producto, pero
todos pasaron inadvertidos porque las PR del ciclo entran en release/** mediante el Fast QG
(quality.yml), que NO ejecuta el conjunto completo de pruebas unitarias, ni pr-test-policy (enmascaramiento de pruebas), ni el
conjunto completo de pruebas de integración, ni la comprobación de paridad de esquemas. Los 3 deterministas fueron:
- Prueba desactualizada por un cambio en la interfaz de usuario —
permissions modal switch buttons declare button type: #4034 añadió un cuarto interruptor (se mantuvotype="button"para a11y); el recuento=== 3de la prueba quedó desactualizado. El análisis estático debería haberlo detectado en la PR #4034. - Prueba desactualizada por un cambio de empaquetado —
findMissingArtifactPaths ... root runtime files:dist/http-method-guard.cjspasó a ser una ruta requerida legítima; la lista esperada de la prueba quedó desactualizada. - Divergencia por modularización con pérdida de datos (la más grave) —
settings schemas accept ... unprefixed toggle: elupdateSettingsSchemamodularizado (schemas/settings.ts, creado por #3988) divergió del canónico (settingsSchemas.ts): 45 campos frente a 85 — 40 eliminados + 6 divergentes (qdrant*). Era código muerto (el entorno de ejecución usa el canónico), por lo que no hubo impacto real, pero solo una prueba de paridad escrita a mano lo detectó. #4030 restauró 16 eliminaciones análogas de #3988/#3993, pero esta pasó inadvertida.
Verificaciones propuestas (Fase 9):
- G1 — Cerrar realmente el agujero de las verificaciones rápidas (amplía P0 #2). En
quality.yml(PR→release/**), además de la comprobación de tipos + las pruebas afectadas, ejecutarpr-test-policy(enmascaramiento de pruebas) + el conjunto completo de pruebas unitarias deterministas (o, al menos, los archivos estáticos/de paridad, que son rápidos y no intermitentes). De esta manera, las pruebas desactualizadas y la eliminación de aserciones se detectan en la PR que las introduce, no el día de publicación. Mantener fuera las pruebas de integración/e2e (lentas/inestables), pero la capa determinista NO PUEDE permanecer únicamente en PR→main. - G2 — Verificación de paridad de modularización (NUEVA, no cubierta actualmente). Una comprobación que, para cada símbolo
reexportado por un barrel modularizado (
src/shared/validation/schemas/*, módulos deproviderRegistry, etc.), compare la estructura (claves dez.object, entradas del registro) con la fuente canónica y falle si existe divergencia (campo eliminado/adicional). Habría detectado la eliminación de 40 campos de #3988 en esa misma PR. Generaliza las pruebas de paridad escritas a mano (que solo existen cuando alguien recordó escribirlas). Es barata: importa ambos elementos y comparaObject.keys(shape). - G3 — Triaje determinista de fallos intermitentes (apoyo). Las pruebas de inicio de LiveWS y de
combinación de integración/breaker fallan debido a tiempos de espera del servidor/fallos en cascada en CI (entorno), no por la lógica. Marcarlas como
known-flaky(puestas en cuarentena con una incidencia) para que el estado rojo de la PR de publicación contenga solo señales reales, no ruido que enmascare regresiones deterministas entre medias.
Principio: la verificación debe ejecutarse donde ocurre la fusión (ya incluido en «Principios transversales»). El incidente de v3.8.27 demuestra que esto también se aplica a la capa de pruebas deterministas, no solo a lint/comprobación de tipos; de lo contrario, la deuda de pruebas desactualizadas + modularización con pérdida de datos solo aparece en PR→main, en bloque y en el peor momento.
Fuentes (mejores prácticas de la industria)
Sección titulada «Fuentes (mejores prácticas de la industria)»- Modelo de Madurez de DevSecOps de OWASP (DSOMM) — https://dsomm.owasp.org/about
- OpenSSF Scorecard / SLSA — https://openssf.org · https://slsa.dev
- «Clean as You Code» de SonarQube — https://docs.sonarsource.com/sonarqube-server/latest/user-guide/clean-as-you-code
- Trinquetes de calidad (LeadDev) — https://leaddev.com/software-quality/introducing-quality-ratchets-tool-managing-complex-systems
- Mejora continua del código mediante trinquetes (Greiner) — https://robertgreiner.com/continuous-code-improvement-using-ratcheting/
- Informe DORA 2024 sobre el estado de DevOps — https://cloud.google.com/blog/products/devops-sre/announcing-the-2024-dora-report
- Mejores prácticas de pruebas de mutación (Stryker) — https://stryker-mutator.io
- La cobertura como antipatrón (Goodhart) — https://www.industriallogic.com/blog/code-coverage-complications/
- OWASP Top 10 para aplicaciones de LLM (2025) — https://owasp.org/www-project-top-10-for-large-language-model-applications/
- Pruebas de contratos (oasdiff/schemathesis) — https://www.oasdiff.com · https://schemathesis.readthedocs.io
HagiCode
HagiCode es un espacio de trabajo de programación con agentes, flujos estructurados, ejecución multiagente y vistas de Hero Dungeon.
Convierte ideas en software útil con un flujo de trabajo con agentes más inteligente, rápido y ameno.

- SmartLos flujos estructurados convierten la intención en un itinerario ejecutable desde la idea hasta la entrega.
- EfficientLos flujos multiagente permiten avanzar en paralelo con la investigación, implementación y revisión.
- FunHero Dungeon hace que las largas sesiones de programación sean visuales y colaborativas.