CommunityProgramación y desarrollogithub.com

lenneTech/ejecución-script-check

Ejecuta el script check de package.json (compatible con monorepos) y lo corrige automáticamente hasta que esté verde, escalando hallazgos de auditoría, cada vez que el trabajo debe demostrar capacidad de ejecución; se activa con "pnpm run check".

¿Qué es ejecución-script-check?

Este skill es la fuente de verdad única para ejecutar el script `check` de `package.json` en los flujos de trabajo de lt-dev. Está diseñado para garantizar que el proyecto sea ejecutable antes de cualquier revisión o fusión, lo que lo convierte en un requisito no negociable. El skill es compatible con monorepos y múltiples gestores de paquetes (pnpm, npm, yarn), y utiliza un script auxiliar dedicado para descubrir todos los scripts `check` definidos en los proyectos monitoreados por git. Una vez descubiertos los proyectos, el skill ejecuta el script `check` de cada uno, y si falla, inicia un bucle de corrección automática: analiza todos los errores (typecheck, lint, build, imports faltantes, vulnerabilidades de auditoría, etc.), los corrige uno por uno en su causa raíz y vuelve a ejecutar `check` desde cero. Este bucle no tiene un límite de iteraciones estricto; termina solo cuando la comprobación sale con código 0 (verde) o cuando una iteración completa no reduce el número de errores (estancado). En caso de estancamiento, el skill exige cambiar de enfoque antes de clasificar el error como residual. Para los hallazgos de auditoría, se sigue una escalera de corrección obligatoria de 8 pasos que va desde actualizaciones compatibles hasta el parcheado del paquete vulnerable o su reemplazo completo. El skill distingue dos modos de invocación: 'Advisory' (informativo, el flujo continúa reportando el fallo) y 'Blocking' (bloqueante, el flujo se detiene si `check` falla). Cada ruta que lleva a una MR/PR o fusión se ejecuta en modo Blocking para evitar que código roto llegue a la rama base y afecte a todo el equipo.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lenneTech/claude-code/tree/HEAD/plugins/lt-dev/skills/running-check-script

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Ejecución del script check

Este skill es la fuente de verdad única para ejecutar el script check de package.json en los flujos de trabajo de lt-dev. Cada revisor, rebasador y orquestador que necesite garantizar la capacidad de ejecución del proyecto debe seguir este procedimiento al pie de la letra — duplicar las reglas entre agentes provoca desviaciones.

Objetivo: Una ejecución de check verdaderamente verde (código de salida 0) es un requisito previo no negociable para que cualquier revisión o rebase se considere completo. El único residual aceptable es una vulnerabilidad de dependencia ascendente donde se haya agotado toda la escalera de corrección.

Cuándo usar este skill

InvocadorFaseDisparadorModo
/lt-dev:reviewFase 1.5Antes de generar cualquier revisor especializadoAdvisory
lt-dev:code-reviewerFase 1.5Antes de la revisión de una sola pasada (omitir si el orquestador ya lo ejecutó)Advisory
lt-dev:test-reviewer(briefing de entrada)Respeta la semántica de omisión definida aquíAdvisory
/lt-dev:take-ticketPASO 8Después de que todos los pilares de prueba estén verdesBloqueante
/lt-dev:git:shipPASO 1, PASO 4bPrevuelo, y después de la reverificación posterior al rebaseBloqueante
/lt-dev:ticket-cyclevía take-ticket + git:shipCiclo completoBloqueante
lt-dev:branch-rebaserFase 6.5Después de lint/formateo, antes de pruebasBloqueante

Modos de invocación

El procedimiento es idéntico en ambos modos. Solo difiere lo que ocurre con un error no resuelto, y esa diferencia es el sentido de la distinción:

  • Advisory — la tarea del invocador es informar. Un check rojo se reporta como un hallazgo Crítico y el flujo continúa, porque el usuario aún desea el resto de la revisión.
  • Bloqueante — la tarea del invocador es entregar. Un check rojo detiene el flujo. No se envía nada, no se crea ninguna MR/PR, no se fusiona nada.

Cada ruta que lleva a una MR/PR o a una fusión se ejecuta en modo Bloqueante. Un check rojo que llega a la rama base le cuesta a todo el equipo: la CI se vuelve roja para todos, el próximo take-ticket se bifurca desde código roto, y la persona que finalmente lo arregla no tiene idea de qué cambio lo causó. Por eso la escalera en el Paso 3 no tiene límite de iteraciones y por eso la lista de residuales del Paso 5 es tan estrecha.

Procedimiento

Paso 1 — Descubrir scripts check

Usa el script auxiliar dedicado (ubicado en el plugin lt-dev):

bash "${CLAUDE_PLUGIN_ROOT}/scripts/discover-check-scripts.sh"

La salida es TSV, un proyecto por línea:

<ruta package.json>\t<script check>\t<incluye_pruebas:no|unit+api|sí>\t<gestor de paquetes>

includes_tests valores — los invocadores deciden qué hacer con cada uno, el descubrimiento en sí no prescribe ningún comportamiento:

ValorSignificadoCobertura de Playwright
noNo se detectó ningún ejecutor de pruebas en la cadena de check.No cubierta.
unit+apiLa cadena de check delega en el wrapper check.mjs de lt, que ejecuta los pasos de prueba Unit (app) + API (api) y omite deliberadamente Playwright (Playwright se ejecuta vía lt dev test / CI — ver scripts/check.mjs).No cubierta — Playwright aún debe ejecutarse por separado si es necesario.
síCoincidencia directa de patrón con test, vitest, jest o playwright en la cadena de check (de forma transitiva, un nivel de resolución compuesta). El alcance es lo que defina el script.Desconocida — los invocadores deben verificar localmente si se requiere cobertura de Playwright.

El auxiliar:

  • Usa git ls-files "package.json" "**/package.json" para que respete .gitignore y omita node_modules
  • Analiza JSON mediante jq → node -e → cadena de respaldo grep+sed (funciona incluso sin jq instalado)
  • Resuelve scripts compuestos de un solo nivel ("check": "pnpm run ci" → busca ci)
  • Detecta el gestor de paquetes por proyecto mediante el archivo de bloqueo (pnpm-lock.yaml → pnpm, etc.; valor predeterminado pnpm)

Si el auxiliar no devuelve nada → ningún proyecto define check → omitir el resto de este skill.

Paso 1a — Sin correcciones sugeridas de oxlint

oxlint --fix-suggestions aplica correcciones que el propio oxlint marca como posiblemente modificadoras del comportamiento: su sugerencia no-console elimina la llamada. --fix-dangerously va más allá. Las plantillas actuales no pasan ninguna, pero los proyectos de versiones anteriores aún lo hacen, en el wrapper de check, lint:fix, lint-staged o el scripts/check.mjs de un proyecto. lt fullstack update las elimina en la raíz del espacio de trabajo y en la app (archivos rastreados y limpios solamente); el proyecto API mantiene sus propios archivos, por lo que un acierto allí se elimina manualmente o tomando el archivo actual de nest-server-starter. Observado en nest-server (2026-09, claude-code PR #10): un hook de commit convirtió un console.log en un cuerpo de función vacío y aún reportó "pasó". Antes del Paso 2, busca un uso de cualquiera de las banderas; una mención en un comentario no cuenta:

git grep -n -E "(^|[[:space:]\"']?)--fix-(suggestions|dangerously)" -- '*package.json' '*.lintstagedrc*' '*lint-staged.config.*' '*scripts/check.mjs' \
  | grep -v -E '^[^:]+:[0-9]+:[[:space:]]*(//|/?\*|#)'

El segundo filtro elimina líneas de comentario: el wrapper actual de nest-server-starter explica en un comentario por qué pasa solo --fix simple.

Ante un acierto, la comprobación se ejecuta sin corrección automática:

  • Ejecuta el wrapper de lt como su puerta de solo lectura: <pm> run check --no-fix (npm: npm run check -- --no-fix). Cada wrapper que aún pasa una de las banderas ya conoce --no-fix. Cuando la cadena de un proyecto llama a lint:fix, o su propio scripts/check.mjs es uno de los aciertos, ejecuta los pasos de ese proyecto con lint en lugar de lint:fix.
  • Corrige los hallazgos de lint manualmente o con oxlint --fix simple; formatea con el formateador del proyecto como de costumbre.
  • Nombra cada acierto (archivo:línea) en el informe del Paso 8 con su remedio: lt fullstack update para la raíz y la app, eliminar la bandera manualmente (o el archivo actual de nest-server-starter) para el proyecto API.

Paso 2 — Ejecutar check por proyecto

Para cada proyecto descubierto, cd a su directorio y ejecuta el script check con el gestor de paquetes detectado:

cd "$(dirname <ruta package.json>)"
<gestor de paquetes> run check

Captura stdout, stderr y código de salida. Lleva un contador de iteraciones que comienza en 1.

Paso 3 — Bucle de corrección automática (iterar hasta que esté verdaderamente verde)

Si el check de un proyecto sale con código distinto de cero:

  1. Analiza todos los errores de la ejecución actual (typecheck, lint, build, imports faltantes, discrepancias de tipo, símbolos no utilizados, hallazgos de auditoría, etc.)
  2. Corrige cada error en su causa raíz mediante Read + Edit. Los errores preexistentes también se corrigen — no importa si un error provino de este diff o ya estaba allí; no hace ninguna diferencia para que el proyecto se ejecute, y un check rojo bloquea a la siguiente persona igual de fuerte en cualquier caso. Los límites de alcance no se aplican a la capacidad de ejecución. La única pregunta que decide algo aquí es "¿se puede arreglar esto?", y mientras la respuesta sea sí, se arregla.
  3. Vuelve a ejecutar check desde cero. Nunca confíes en el estado parcial.
  4. Continúa iterando hasta que se cumpla una de estas condiciones terminales:
    • (a) VERDE — check sale con 0 → hecho para este proyecto
    • (b) ESTANCADO — una iteración completa no produjo una reducción neta en el número de errores
  5. Sin límite fijo de iteraciones. Mientras cada iteración reduzca estrictamente el recuento de errores, continúa. El objetivo es el verde verdadero.

Una excepción estrecha, y se trata de colisión, no de alcance. El punto 2 se mantiene: un error preexistente se corrige, porque un check rojo bloquea a la siguiente persona independientemente de quién lo haya escrito. Lo que el punto 2 no cubre es un error dentro de trabajo no confirmado en el que otra sesión activa está en medio de un cambio — remodelar eso no es una cuestión de alcance, son dos sesiones editando un archivo, y el par regresa a una refactorización reescrita habiendo perdido más tiempo del que ahorró la corrección. Cuando el árbol está sucio y bash "${CLAUDE_PLUGIN_ROOT}/scripts/change-provenance.sh" atribuye la ruta fallida a un par activo: corrígelo si es trivial y autocontenido (un import faltante, una violación de formato, un console.log suelto), y de lo contrario repórtalo como un bloqueador nombrando al autor, más un SOLVED que lleve el diagnóstico para que pueda corregir su propio trabajo en un solo paso. Nadie activo, o nada atribuible: el punto 2 se aplica sin cambios.

ESTANCADO es una señal para cambiar de enfoque, no un permiso para detenerse. El recuento deja de caer cuando se reintenta la misma corrección, por lo que la siguiente iteración debe atacar el error de manera diferente: leer el archivo fallido en su totalidad en lugar de parchear alrededor de la línea reportada, verificar si dos errores comparten una causa, observar cómo un módulo hermano funcional resuelve lo mismo, ejecutar el paso fallido solo para ver la salida que la ejecución agregada tragó, verificar si es uno de los peligros conocidos en los Pasos 6.5 a 6.8. Solo cuando se haya probado un enfoque genuinamente diferente y el recuento aún se mantenga, se aplica la clasificación residual en el Paso 5 — y en el modo Bloqueante, todo excepto una vulnerabilidad de dependencia con escalera agotada aún detiene el flujo de trabajo.

Paso 4 — Hallazgos de auditoría: escalera de corrección obligatoria

Cuando pnpm audit / npm audit / yarn audit (invocado por check) reporta una vulnerabilidad, agota esta escalera antes de clasificar el hallazgo como Aceptado. Vuelve a ejecutar check después de cada paso.

#PasoComando (pnpm / npm / yarn)
1Actualizar a la última versión compatiblepnpm update <pkg> / npm update <pkg> / yarn upgrade <pkg>
2Corrección automáticapnpm audit --fix / npm audit fix / yarn audit --fix
3Forzar actualización semver-majorpnpm audit --fix --force / npm audit fix --force
4Subir la dependencia directa a la siguiente major si el advisory lista la corrección allípnpm add <pkg>@<major> / npm install <pkg>@<major> / yarn add <pkg>@<major>
5Forzar una versión de dependencia transitivaBloque pnpm.overrides / resolutions (yarn) / overrides (npm) en package.json, luego reinstalar
6Actualizar el CONSUMIDOR, no el paquete vulnerablela dependencia directa que lo trae, y el framework lt si el framework lo fija (@lenne.tech/nest-server / @lenne.tech/nuxt-extensions) — un /lt-dev:maintenance:maintain completo es la forma exhaustiva
7Parchear el consumidor — solo bajo las condiciones siguientespnpm patch <pkg> → patchedDependencies
8Reemplazar el paqueteCambiar a una alternativa mantenida si está abandonado

El Paso 6 es el escalón que se salta, y es el que más a menudo funciona. Los pasos 1 a 5 empujan el paquete vulnerable hacia adelante. Cuando eso falla, la razón generalmente no es el paquete vulnerable en absoluto — es el consumidor quien lo retiene, fijando un rango vulnerable o usando una API que la major parcheada eliminó. Así que la pregunta a hacer es "¿quién mantiene esta versión aquí?", y la respuesta es una dependencia directa, o un framework cuyo pin una anulación no puede superar. Una anulación es un pin, y un pin es estrictamente peor que una subida de versión real: diverge el árbol de lo que prueba el upstream, y se pudre silenciosamente. Toma la subida donde exista.

El Paso 7 (parcheado) es estrecho a propósito, y la estrechez es el punto. Cuando la major parcheada solo falla al cargar — un export por defecto eliminado, un punto de entrada renombrado — un parche de una línea parece cerrar el advisory correctamente en lugar de suprimirlo. A veces lo hace. Tres condiciones deben cumplirse primero, y la tercera es la que generalmente falla:

  1. El parche apunta a una ruta estable en el paquete vulnerable, y está fijado a una versión exacta. Lo que rompe un parche no es dist/ como tal — los paquetes publicados envían dist/ y nada más — es una ruta que se mueve entre versiones. dist/chunks/<hash>.mjs es renombrado por la próxima compilación y el parche entonces falla para todos en el equipo; dist/index.mjs es el propio punto de entrada del paquete y permanece. Un parche que nombra un símbolo minificado sigue siendo aceptable con el pin de versión, porque el pin convierte el riesgo en un fallo ruidoso de pnpm install en lugar de un mal parche silencioso. Parchea la dependencia vulnerable, no un consumidor que casualmente la importa — ver el caso medido a continuación, donde la primera evaluación miró el chunk del consumidor y rechazó el escalón por esa base.
  2. Sopesa el cierre de producción contra el costo de mantenimiento. Un parche es una obligación permanente en cada subida futura, por lo que para una ruta de herramientas de desarrollo que no puede llegar a producción, bien puede gastar más de lo que compra — en un solo proyecto. Una PLANTILLA invierte esa aritmética: cada proyecto generado hereda un parche, mientras que un residual tendría que ser discutido de nuevo en cada uno de ellos. Esto es un juicio, no un veto; las condiciones 1 y 3 son las difíciles.
  3. Cargar no es lo mismo que funcionar. Una major que eliminó un export generalmente también cambió el comportamiento, por lo que un import parcheado hace que el módulo importe mientras deja al consumidor ejecutándose contra una API en la que nunca fue probado. Si no puedes decir qué más cambió en esa major y por qué no importa aquí, el parche es una conjetura disfrazada de corrección.

Parchea el paquete VULNERABLE, no el consumidor. Esta es la distinción que decide si el escalón funciona, y es fácil de equivocarse, porque el error apunta al consumidor. Medido, lt-crm 2026-10-06: @nuxt/[email protected] hace import Git from 'simple-git', y subir simple-git a la única línea corregida (4.x, que eliminó ese export por defecto) hizo que nuxt prepare abortara con does not provide an export named 'default'. La primera evaluación miró el dist/chunks/module-main.mjs propio de devtools, encontró el import allí, y rechazó parchear por la condición 1 — un chunk compilado — que fue el veredicto correcto sobre el archivo equivocado. El parche pertenece un nivel más abajo, en el dist/index.mjs de simple-git, donde una sola línea añadida reexporta como default la misma fábrica que el módulo ya exporta como simpleGit. Nada sobre el código endurecido cambia; solo la superficie del módulo vuelve.

Con eso, las tres condiciones se cumplen: es el paquete vulnerable en lugar de un artefacto del consumidor, está fijado a una versión exacta (patchedDependencies: { '[email protected]': … } más el destino de anulación), y la API que devtools realmente llama — branch, revparse, log — es la misma en 3.x y 4.x. Si lo que devtools llama hubiera cambiado, el parche aún se consideraría, pero la inspección directa del código fuente de devtools lo habría revelado; no adivines qué API interna usa.

Paso 5 — Clasificar errores residuales

Regla fundamental: Un check rojo nunca se acepta en modo Bloqueante excepto para el único caso listado a continuación. Si no puedes hacer que se ponga verde, no puedes entregar.

EstadoEjemploModo AdvisoryModo Bloqueante
Error de lintVariable no utilizadaReportar como CríticoBLOQUEAR — detener el flujo de trabajo
Error de tipoAsignación number a stringReportar como CríticoBLOQUEAR
Error de compilaciónMódulo no encontradoReportar como CríticoBLOQUEAR
Error de pruebaPrueba fallida (dentro de check)Reportar como CríticoBLOQUEAR
Vulnerabilidad de auditoríahigh severity en lodashReportar como CríticoBLOQUEAR (a menos que la escalera esté agotada)
Vulnerabilidad de dependencia ascendente, escalera agotadaCVE en librería interna de 3ros sin parcheReportar como CríticoAceptado — único residual permitido en modo Bloqueante

Paso 6 — Informar el resultado

Proporciona al invocador un resumen claro:

  • Lista de proyectos verificados y su estado final (VERDE / ESTANCADO / SALTADO)
  • Para cada proyecto VERDE: confirmación de que check salió con 0 en la iteración final
  • Para cada proyecto ESTANCADO:
    • Recuento de errores en la última iteración y en la penúltima (para demostrar la meseta)
    • Los 3-5 errores principales con rutas de archivo, mensajes y contexto de código (suficiente para que un humano empiece a depurar)
    • En modo Advisory: reportar como Hallazgo Crítico de Revisión
    • En modo Bloqueante: reportar como Bloqueador + razón por la que no se pudo resolver (cualquier residual que no sea de escalera agotada = bloqueador)
  • Para hallazgos de auditoría: mostrar qué escalones se probaron y dónde se detuvo la escalera
  • En modo Bloqueante: declaración explícita: "Listo para enviar" o "BLOQUEADO — consulte los residuales arriba"

Paso 7 — Limpiar (solo en modo Bloqueante)

Antes de devolver el control:

git diff --stat

Confirma que todos los cambios son intencionales y que no se modificó ningún archivo fuera del alcance de la tarea (a menos que sea necesario para la ejecutabilidad). Si se corrigieron errores preexistentes fuera del alcance, enuméralos en el informe como "Correcciones de ejecutabilidad fuera del alcance" para visibilidad del equipo.

Paso 8 — Plantilla de informe

## Resultado de `check`

**Modo:** {Advisory|Bloqueante}

| Proyecto | Estado | Iteraciones | Notas |
|----------|--------|-------------|-------|
| `apps/web` | VERDE | 3 | Se corrigieron 2 lint, 1 error de tipo |
| `packages/api` | ESTANCADO | 7 | 3 errores restantes (ver abajo) |
| `packages/shared` | SALTADO | — | Sin script `check` |

### Detalles de ESTANCADO

**packages/api** — meseta en 3 errores (últimas 2 iteraciones):

1. `src/users/user.service.ts:42` — `Type 'string | undefined' is not assignable to type 'string'` (error preexistente)
2. `src/auth/auth.controller.ts:15` — `Module 'crypto' has no exported member 'randomUUID'` (requiere `@types/node`)
3. `pnpm audit` — `protobufjs` CVE-2024-..., escalera agotada en el paso 6 (framework lt lo fija)

### Hallazgos de auditoría

| Paquete | Gravedad | Escalera | Resultado |
|---------|----------|----------|-----------|
| `protobufjs` | Alta | Pasos 1-6 probados | Aceptado — fijado por `@lenne.tech/nest-server`, se necesita actualización del framework |

### Correcciones fuera del alcance

- `src/config/index.ts`: se añadió el import faltante de `ConfigService` (rotura preexistente)

**Veredicto:** {Listo para enviar|BLOQUEADO — ver arriba}

Peligros conocidos y estrategias de depuración

Paso 6.5 — Ejecuciones fallidas de preguntas de ESM/CJS

Cuando un script check ejecuta múltiples herramientas secuencialmente, una herramienta posterior puede fallar porque una anterior dejó el proceso en un estado inconsistente (por ejemplo, jest carga ESM y luego tsc falla debido a cambios en tsconfig.json). Si ves fallos extraños de compilación o prueba después de una corrección exitosa de lint, intenta limpiar:

git stash  # o guarda el trabajo actual
<pkg mgr> run check  # línea base limpia
git stash pop
<pkg mgr> run check  # ahora con los cambios

Paso 6.6 — Límites de memoria/node --heap

Las compilaciones grandes pueden fallar con JavaScript heap out of memory. Si los errores no son de lint ni de tipo, comprueba:

NODE_OPTIONS="--max-old-space-size=4096" <pkg mgr> run check

Paso 6.7 — Errores de tipo que desaparecen al re-ejecutar

tsc --noEmit a veces reporta errores de tipo transitorios cuando se usa con incremental: true. Si el Paso 3 está atascado en un error que ya parece corregido:

rm -rf node_modules/.cache/typescript
<pkg mgr> run check

Paso 6.8 — Contaminación de caché de lint

Si una corrección de lint se aplicó pero la re-ejecución aún reporta el antiguo error de lint:

rm -rf node_modules/.cache/eslint  # o .oxlint_cache
<pkg mgr> run check

Paso 6.9 — Errores de tipo de Vue/SCSS en devtools

Los proyectos devtools de nuxt: a veces vue-tsc se queja de tipos que solo existen en tiempo de compilación de Vite. Si el error está en un archivo .vue y menciona una macro o import virtual, ejecuta npm run dev una vez para generar los tipos, luego vuelve a ejecutar check.

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills relacionados