lenneTech/running-check-script

Executa o script `check` do package.json (com suporte a monorepo) e aplica correções automáticas até ficar verde, escalando achados de auditoria, sempre que o trabalho precisa comprovar executabilidade; acionado por "pnpm run check".

O que é running-check-script?

Este skill é a fonte única da verdade para executar o script `check` definido no `package.json` em fluxos de trabalho lt-dev. Ele garante que qualquer revisor, rebaser ou orquestrador que precise assegurar a executabilidade do projeto siga um procedimento rigoroso e consistente, evitando divergências entre agentes. O skill suporta modos **Advisory** (reporta falhas como críticas, mas continua o fluxo) e **Blocking** (bloqueia a operação se o `check` falhar), sendo usado em fases como revisão de código, rebase de branch e criação de MR/PR. O processo inclui descoberta automática de scripts `check` via um script auxiliar que respeita `.gitignore` e detecta o gerenciador de pacotes, execução do script por projeto, e um loop de correção automática até que o `check` saia com código 0 ou estagne sem progresso. Além disso, possui uma escada de escalação obrigatória para vulnerabilidades de auditoria (comandos `pnpm audit`), com 8 degraus que vão desde atualizações compatíveis até substituição do pacote, e passos especiais para lidar com flags `oxlint --fix-suggestions`/`--fix-dangerously` que podem alterar comportamento. O skill também lida com colisões entre sessões ativas e com a aplicação de patches em pacotes vulneráveis sob condições restritas, priorizando sempre a executabilidade do projeto sobre limites de escopo.

Funciona com✓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 Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Executando o Script check

Este skill é a fonte única da verdade para executar o script check do package.json em fluxos de trabalho lt-dev. Qualquer revisor, rebaser ou orquestrador que precise garantir a executabilidade do projeto deve seguir este procedimento à risca — duplicar as regras entre agentes leva a divergências.

Objetivo: Uma execução check verdadeiramente verde (código de saída 0) é um pré-requisito inegociável para que qualquer revisão ou rebase seja considerado completo. O único resíduo aceitável é uma vulnerabilidade de dependência upstream onde toda a escada de escalação de correção foi esgotada.

Quando Usar Este Skill

ChamadorFaseGatilhoModo
/lt-dev:reviewFase 1.5Antes de gerar qualquer revisor especializadoAdvisory
lt-dev:code-reviewerFase 1.5Antes da revisão de passagem única (pular se o orquestrador já executou)Advisory
lt-dev:test-reviewer(briefing de entrada)Respeita a semântica de pular definida aquiAdvisory
/lt-dev:take-ticketPASSO 8Depois que todos os pilares de teste estão verdesBloqueante
/lt-dev:git:shipPASSO 1, PASSO 4bPré-voo, e após a re-verificação pós-rebaseBloqueante
/lt-dev:ticket-cyclevia take-ticket + git:shipCiclo completoBloqueante
lt-dev:branch-rebaserFase 6.5Após lint/format, antes dos testesBloqueante

Modos dos Chamadores

O procedimento é idêntico em ambos os modos. Apenas o que acontece com um erro não resolvido difere, e essa diferença é o ponto central da distinção:

  • Advisory — o trabalho do chamador é relatar. Uma falha no check é exibida como um achado Crítico e o fluxo continua, porque o usuário ainda deseja o restante da revisão.
  • Bloqueante — o trabalho do chamador é entregar. Uma falha no check interrompe o fluxo. Nada é enviado, nenhum MR/PR é criado, nada é mesclado.

Todo caminho que leva a um MR/PR ou a uma mesclagem executa no modo Bloqueante. Uma falha no check que chega à branch base custa para toda a equipe: o CI fica vermelho para todos, o próximo take-ticket parte de código quebrado, e a pessoa que eventualmente conserta não tem ideia de qual mudança causou o problema. É por isso que a escada no Passo 3 não tem limite de iterações e por que a lista de resíduos no Passo 5 é tão estreita.

Procedimento

Passo 1 — Descobrir scripts check

Use o script auxiliar dedicado (localizado no plugin lt-dev):

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

A saída é TSV, um projeto por linha:

<caminho do package.json>\t<script check>\t<inclui_testes:no|unit+api|yes>\t<gerenciador de pacotes>

Valores de includes_tests — os chamadores decidem o que fazer com cada um, a descoberta em si não prescreve comportamento:

ValorSignificadoCobertura Playwright
noNenhum executor de teste detectado na cadeia do check.Não coberto.
unit+apiA cadeia do check delega para o wrapper check.mjs do lt, que executa etapas de teste Unit (app) + API (api) e deliberadamente pula Playwright (Playwright executa via lt dev test / CI — veja scripts/check.mjs).Não coberto — Playwright ainda deve ser executado separadamente, se necessário.
yesCorrespondência direta de padrão com test, vitest, jest ou playwright na cadeia do check (transitivamente, um nível de resolução composta). O escopo é o que o script define.Desconhecido — os chamadores devem verificar localmente se a cobertura Playwright é necessária.

O auxiliar:

  • Usa git ls-files "package.json" "**/package.json" para respeitar .gitignore e pular node_modules
  • Analisa JSON via jq → node -e → cadeia de fallback grep+sed (funciona mesmo sem jq instalado)
  • Resolve scripts compostos de um único nível ("check": "pnpm run ci" → busca por ci)
  • Detecta o gerenciador de pacotes por projeto através do arquivo de bloqueio (pnpm-lock.yaml → pnpm, etc.; padrão pnpm)

Se o auxiliar não retornar nada → nenhum projeto define check → pule o restante deste skill.

Passo 1a — Sem correções sugeridas do oxlint

oxlint --fix-suggestions aplica correções que o próprio oxlint marca como possivelmente alteradoras de comportamento: sua sugestão no-console deleta a chamada. --fix-dangerously vai além. Os modelos atuais não passam nenhuma delas, mas projetos de modelos mais antigos ainda o fazem, no wrapper do check, em lint:fix, lint-staged ou no próprio scripts/check.mjs do projeto. lt fullstack update as remove na raiz do workspace e no app (apenas arquivos rastreados e limpos); o projeto API mantém seus próprios arquivos, então um acerto lá é removido manualmente ou usando o arquivo atual do nest-server-starter. Observado em nest-server (2026-09, claude-code PR #10): um hook de commit transformou um console.log em um corpo de função vazio e ainda relatou "passou". Antes do Passo 2, procure por um uso de qualquer uma das flags; uma menção em um comentário não conta:

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

O segundo filtro descarta linhas de comentário: o wrapper atual do nest-server-starter explica em um comentário por que passa apenas --fix simples.

Em um acerto, o check executa sem correção automática:

  • Execute o wrapper lt como sua porta de entrada somente leitura: <pm> run check --no-fix (npm: npm run check -- --no-fix). Todo wrapper que ainda passa uma das flags já conhece --no-fix. Onde a cadeia do próprio projeto chama lint:fix, ou seu próprio scripts/check.mjs é um dos acertos, execute as etapas desse projeto com lint em vez de lint:fix.
  • Corrija achados de lint manualmente ou com oxlint --fix simples; formate com o formatador do projeto como de costume.
  • Nomeie cada acerto (arquivo:linha) no relatório do Passo 8 com seu remédio: lt fullstack update para a raiz e o app, remover a flag manualmente (ou o arquivo atual do nest-server-starter) para o projeto API.

Passo 2 — Executar check por projeto

Para cada projeto descoberto, cd para seu diretório e execute o script check com o gerenciador de pacotes detectado:

cd "$(dirname <caminho do package.json>)"
<gerenciador de pacotes> run check

Capture stdout, stderr e código de saída. Acompanhe um contador de iterações começando em 1.

Passo 3 — Loop de correção automática (iterar até ficar verdadeiramente verde)

Se o check de um projeto sair com código não-zero:

  1. Analise todos os erros da execução atual (typecheck, lint, build, imports faltantes, incompatibilidades de tipo, símbolos não utilizados, achados de auditoria, etc.)
  2. Corrija todo erro na causa raiz via Read + Edit. Erros pré-existentes também são corrigidos — não importa se um erro veio deste diff ou já estava lá para a executabilidade do projeto, e um check vermelho bloqueia a próxima pessoa exatamente da mesma forma de qualquer maneira. Limites de escopo não se aplicam à executabilidade. A única questão que decide algo aqui é "isso pode ser corrigido?", e enquanto a resposta for sim, é corrigido.
  3. Re-execute check do zero. Nunca confie em estado parcial.
  4. Continue iterando até que uma destas condições terminais seja atingida:
    • (a) VERDE — check sai com 0 → concluído para este projeto
    • (b) ESTAGNADO — uma iteração completa não produziu redução líquida na contagem de erros
  5. Sem limite máximo de iterações. Enquanto cada iteração reduzir estritamente a contagem de erros, continue. O objetivo é o verde verdadeiro.

Uma exceção restrita, e é sobre colisão, não sobre escopo. O ponto 2 permanece: um erro pré-existente é corrigido, porque um check vermelho bloqueia a próxima pessoa independentemente de quem o escreveu. O que o ponto 2 não cobre é um erro dentro de trabalho não commitado no qual outra sessão ativa está no meio de uma edição — remodelar isso não é uma questão de escopo, são duas sessões editando um arquivo, e o par retorna a uma refatoração reescrita tendo perdido mais tempo do que a correção economizou. Onde a árvore está suja e bash "${CLAUDE_PLUGIN_ROOT}/scripts/change-provenance.sh" atribui o caminho com falha a um par ativo: corrija se for trivial e autocontido (um import faltante, uma violação de formatação, um console.log perdido), e caso contrário, relate como um bloqueador nomeando o autor, mais um SOLVED carregando o diagnóstico para que eles possam corrigir seu próprio trabalho em uma etapa. Ninguém ativo, ou nada atribuível: o ponto 2 se aplica inalterado.

ESTAGNADO é um sinal para mudar de abordagem, não permissão para parar. A contagem para de cair quando a mesma correção está sendo repetida, então a próxima iteração deve atacar o erro de forma diferente: leia o arquivo com falha por completo em vez de aplicar patches ao redor da linha relatada, verifique se dois erros compartilham uma causa, veja como um módulo irmão funcional resolve a mesma coisa, execute a etapa com falha sozinha para ver a saída que a execução agregada engoliu, verifique se é um dos perigos conhecidos nos Passos 6.5 a 6.8. Somente quando uma abordagem genuinamente diferente foi tentada e a contagem ainda se mantém, a classificação residual do Passo 5 se aplica — e no modo Bloqueante, tudo exceto uma vulnerabilidade de dependência com escada esgotada ainda interrompe o fluxo.

Passo 4 — Achados de auditoria: escada de escalação de correção obrigatória

Quando pnpm audit / npm audit / yarn audit (invocado por check) relata uma vulnerabilidade, esgote esta escada antes de classificar o achado como Aceito. Re-execute check após cada etapa.

#EtapaComando (pnpm / npm / yarn)
1Atualizar para a última compatívelpnpm update <pkg> / npm update <pkg> / yarn upgrade <pkg>
2Remediação automáticapnpm audit --fix / npm audit fix / yarn audit --fix
3Forçar upgrade semver-majorpnpm audit --fix --force / npm audit fix --force
4Avançar dependência direta para o próximo major se o advisory listar correção lápnpm add <pkg>@<major> / npm install <pkg>@<major> / yarn add <pkg>@<major>
5Forçar versão de dependência transitivaBloco pnpm.overrides / resolutions (yarn) / overrides (npm) no package.json, então reinstalar
6Avançar o CONSUMIDOR, não o pacote vulnerávela dependência direta que o puxa, e o framework lt se o framework o fixar (@lenne.tech/nest-server / @lenne.tech/nuxt-extensions) — um /lt-dev:maintenance:maintain completo é a forma aprofundada
7Aplicar patch no consumidor — apenas sob as condições abaixopnpm patch <pkg> → patchedDependencies
8Substituir o pacoteMudar para uma alternativa mantida se abandonado

A Etapa 6 é o degrau que é pulado, e é o que mais frequentemente funciona. As etapas 1 a 5 todas empurram o pacote vulnerável para frente. Quando isso falha, a razão geralmente não é o pacote vulnerável — é o consumidor o segurando, ao fixar um intervalo vulnerável ou ao usar uma API que o major corrigido removeu. Então a pergunta a fazer é "quem mantém esta versão aqui?", e a resposta é uma dependência direta, ou um framework cujo fix um override não consegue superar. Um override é um fix, e um fix é estritamente pior do que um bump de versão real: ele diverge a árvore do que upstream testa, e apodrece silenciosamente. Faça o bump onde ele existe.

A Etapa 7 (patching) é estreita de propósito, e a estreiteza é o ponto. Quando o major corrigido apenas falha ao carregar — um export default removido, um ponto de entrada renomeado — um patch de uma linha parece fechar o advisory corretamente em vez de suprimi-lo. Às vezes funciona. Três condições precisam ser atendidas primeiro, e a terceira é a que geralmente falha:

  1. O patch tem como alvo um caminho estável no pacote vulnerável, e é fixado em uma versão exata. O que quebra um patch não é dist/ como tal — pacotes publicados enviam dist/ e nada mais — é um caminho que se move entre versões. dist/chunks/<hash>.mjs é renomeado pela próxima build e o patch então falha para todos na equipe; dist/index.mjs é o ponto de entrada do próprio pacote e permanece. Um patch que nomeia um símbolo minificado ainda é aceitável com o fix de versão, porque o fix transforma o risco em uma falha ruidosa de pnpm install em vez de um patch silencioso incorreto. Aplique patch na dependência vulnerável, não em um consumidor que por acaso a importa — veja o caso mensurado abaixo, onde a primeira avaliação olhou para o chunk do consumidor e rejeitou o degrau nessa base.
  2. Pese o fechamento de produção contra o custo de manutenção. Um patch é uma obrigação contínua em cada bump futuro, então para um caminho de ferramentas de desenvolvimento que não pode alcançar a produção, ele pode gastar mais do que compra — em um único projeto. Um TEMPLATE inverte essa aritmética: cada projeto gerado herda um patch, enquanto um resíduo teria que ser re-argumentado em cada um deles. Isso é um julgamento, não um veto; as condições 1 e 3 são as difíceis.
  3. Carregar não é o mesmo que funcionar. Um major que removeu um export geralmente também mudou comportamento, então um import corrigido faz o módulo importar enquanto deixa o consumidor rodando contra uma API na qual nunca foi testado. Se você não pode dizer o que mais mudou naquele major e por que não importa aqui, o patch é um palpite vestido de correção.

Aplique patch no pacote VULNERÁVEL, não no consumidor. Esta é a distinção que decide se o degrau funciona, e é fácil errar, porque o erro aponta para o consumidor. Medido, lt-crm 2026-10-06: @nuxt/[email protected] faz import Git from 'simple-git', e avançar simple-git para a única linha corrigida (4.x, que removeu aquele export default) fez nuxt prepare abortar com does not provide an export named 'default'. A primeira avaliação olhou para o próprio dist/chunks/module-main.mjs do devtools, encontrou o import lá, e rejeitou o patch na condição 1 — um chunk compilado — que foi o veredito certo sobre o arquivo errado. O patch pertence um nível abaixo, no próprio dist/index.mjs do simple-git, onde uma única linha adicionada re-exporta como default a mesma fábrica que o módulo já exporta como simpleGit. Nada sobre o código endurecido muda; apenas a superfície do módulo retorna.

Com isso, todas as três condições se mantêm: é o pacote vulnerável em vez de um artefato do consumidor, está fixado em uma versão exata (patchedDependencies: { '[email protected]': … } mais o alvo do override), e a API que o devtools realmente chama — branch, revparse, log — é estável através dos majors (simple-git não removeu nada que devtools usa). A Etapa 7 é aceita aqui.

Passo 5 — Classificar resíduos

Se, após esgotar a escada, restar um erro:

ResíduoAção em AdvisoryAção em BloqueanteExplicação
Vulnerabilidade de dependência onde a escada completa foi executada e a Etapa 8 foi tentada/esgotadaRelatar como Crítico com o degrau mais alto da escada alcançado.Não bloqueia — mas listar no relatório.Nenhum código próprio foi alterado; a vulnerabilidade está em um artefato publicado. Bloquear impede todo o trabalho da equipe.
Qualquer outro erro (typecheck, lint, build, etc.)Relatar como Crítico.BLOQUEIA. Nada avança.A executabilidade está quebrada. Nenhum código que não executa deve ser mesclado.

Passo 6 — Relatar resultado

Retorne uma estrutura de dados contendo:

  • status: green | red
  • detalhes por projeto: lista de objetos com:
    • project: caminho do package.json
    • status: green | red | stalled
    • iterations: número de iterações
    • packageManager: pacote usado
    • stdout: saída padrão da execução final
    • stderr: saída de erro da execução final
    • errors:** lista de objetos de erro (quando red ou stalled):
      • type: vulnerability | typecheck | lint | build | other
      • file: caminho do arquivo (quando aplicável)
      • message: mensagem do erro
      • fixAttempted: correção tentada
      • escalationStep: degrau da escada alcançado (para vulnerabilidades)
      • resolved: true | false
  • mdReport: relatório em Markdown formatado para humanos

Passo 7 — Modo Bloqueante: interromper ou continuar

Se qualquer projeto estiver red ou stalled e o modo for Bloqueante, interrompa todo o fluxo de trabalho com uma mensagem de erro. Não crie MR/PR, não mescle, não envie.

Passo 8 — Relatório de resumo (Advisory e Bloqueante, quando bloqueante permite continuação)

Produza um resumo Markdown:

## Resultado da Execução do `check`

**Status Geral:** <green|red>
**Modo:** <Advisory|Bloqueante>

### Projetos

| Projeto | Status | Iterações |
|---------|--------|-----------|
| <caminho> | <status> | <n> |

### Achados Críticos

<lista de erros não resolvidos com tipo, arquivo, correção tentada>

### Detalhes

<qualquer contexto adicional relevante>

Notas Técnicas

  • O script discover-check-scripts.sh está localizado em ${CLAUDE_PLUGIN_ROOT}/scripts/
  • O script change-provenance.sh está em ${CLAUDE_PLUGIN_ROOT}/scripts/
  • A resolução de scripts compostos é de nível único ("check": "pnpm run ci" → apenas busca ci, não resolve recursivamente)
  • A detecção do gerenciador de pacotes prioriza:
    1. pnpm-lock.yaml → pnpm
    2. package-lock.json → npm
    3. yarn.lock → yarn
    4. Padrão: pnpm
  • A saída deve ser capturada com redirecionamento de saída padrão (stdout) e saída de erro (stderr)
  • O código de saída deve ser capturado via $? ou uma construção equivalente
  • O contador de iterações começa em 1
  • O loop de correção automática não tem limite máximo de iterações, mas estagna se nenhuma redução líquida for observada após uma iteração completa
  • A Etapa 7 (patching) requer que todas as três condições sejam atendidas; caso contrário, permanece na Etapa 6 ou avança para a Etapa 8

Individual skills in this repo

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

Habilidades Relacionadas