lenneTech/running-check-script

Exécute le script `check` de `package.json` (compatible monorepo) et corrige automatiquement jusqu'à ce que tout soit vert, en escaladant les résultats d'audit, chaque fois que le travail doit prouver son exécutabilité ; se déclenche sur "pnpm run check".

Qu'est-ce que running-check-script ?

Cette compétence est la source de vérité unique pour exécuter le script `check` de `package.json` dans les flux de travail lt-dev. Elle garantit qu'un projet est entièrement exécutable avant toute revue, rebasage ou livraison. La compétence découvre d'abord les scripts `check` dans un monorepo à l'aide d'un script d'assistance dédié, puis les exécute projet par projet. Si un script échoue, une boucle de correction automatique s'active : chaque erreur est analysée et corrigée à la racine, puis le script est relancé jusqu'à ce qu'il soit vert (code de sortie 0) ou qu'aucune réduction nette du nombre d'erreurs ne se produise (situation de blocage). Les résultats d'audit de sécurité suivent une échelle d'escalade obligatoire en huit étapes, de la simple mise à jour au remplacement du paquet, avant d'être acceptés comme résiduels. La compétence fonctionne en deux modes : **Consultatif** (les erreurs sont signalées mais le flux continue) et **Bloquant** (une erreur rouge arrête le flux), ce dernier étant utilisé pour tous les chemins menant à une fusion ou à une livraison.

Compatible avec✓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 Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Exécution du script check

Cette compétence est la source de vérité unique pour exécuter le script check du package.json dans les flux de travail lt-dev. Tout relecteur, rebaseur ou orchestrateur qui doit garantir l'exécutabilité du projet doit suivre cette procédure textuellement — dupliquer les règles entre les agents entraîne une dérive.

Objectif : Une exécution check vraiment verte (code de sortie 0) est une condition préalable non négociable pour que toute revue ou tout rebasage soit considéré comme complet. Le seul résidu acceptable est une vulnérabilité de dépendance amont pour laquelle l'échelle d'escalade complète a été épuisée.

Quand utiliser cette compétence

AppelantPhaseDéclencheurMode
/lt-dev:reviewPhase 1.5Avant de lancer tout relecteur spécialiséConsultatif
lt-dev:code-reviewerPhase 1.5Avant la revue en un seul passage (ignorer si l'orchestrateur l'a déjà exécuté)Consultatif
lt-dev:test-reviewer(briefing d'entrée)Honore la sémantique de saut définie iciConsultatif
/lt-dev:take-ticketÉTAPE 8Après que tous les piliers de test sont vertsBloquant
/lt-dev:git:shipÉTAPE 1, ÉTAPE 4bPrévol, et après la revérification post-rebasageBloquant
/lt-dev:ticket-cyclevia take-ticket + git:shipCycle completBloquant
lt-dev:branch-rebaserPhase 6.5Après lint/format, avant les testsBloquant

Modes d'appel

La procédure est identique dans les deux modes. Seul ce qui se passe avec une erreur non résolue diffère, et cette différence est tout l'intérêt de la distinction :

  • Consultatif — le travail de l'appelant est de signaler. Un check rouge est signalé comme un résultat critique et le flux continue, car l'utilisateur souhaite toujours le reste de la revue.
  • Bloquant — le travail de l'appelant est de livrer. Un check rouge arrête le flux. Rien n'est poussé, aucune MR/PR n'est créée, rien n'est fusionné.

Chaque chemin qui mène à une MR/PR ou à une fusion s'exécute en mode Bloquant. Un check rouge atteignant la branche de base coûte cher à toute l'équipe : l'IC devient rouge pour tout le monde, le prochain take-ticket bifurque à partir d'un code cassé, et la personne qui finit par le corriger n'a aucune idée du changement qui l'a causé. C'est pourquoi l'échelle de l'étape 3 n'a pas de limite d'itération et pourquoi la liste des résidus de l'étape 5 est aussi étroite.

Procédure

Étape 1 — Découvrir les scripts check

Utilisez le script d'assistance dédié (situé dans le plugin lt-dev) :

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

La sortie est au format TSV, un projet par ligne :

<chemin package.json>\t<script check>\t<includes_tests:no|unit+api|yes>\t<gestionnaire de paquets>

Valeurs includes_tests — les appelants décident quoi faire avec chacune, la découverte elle-même ne prescrit aucun comportement :

ValeurSignificationCouverture Playwright
noAucun exécuteur de test détecté dans la chaîne de check.Non couvert.
unit+apiLa chaîne check délègue au wrapper lt check.mjs, qui exécute les étapes de test Unité (app) + API (api) et saute délibérément Playwright (Playwright s'exécute via lt dev test / CI — voir scripts/check.mjs).Non couvert — Playwright doit toujours être exécuté séparément si nécessaire.
yesCorrespondance directe avec test, vitest, jest ou playwright dans la chaîne de check (transitivement, un niveau de résolution composite). La portée est celle définie par le script.Inconnu — les appelants doivent vérifier localement si la couverture Playwright est requise.

Le script d'assistance :

  • Utilise git ls-files "package.json" "**/package.json" pour respecter .gitignore et ignorer node_modules
  • Analyse le JSON via jq → node -e → chaîne de repli grep+sed (fonctionne même sans jq installé)
  • Résout les scripts composites à un seul niveau ("check": "pnpm run ci" → recherche ci)
  • Détecte le gestionnaire de paquets par projet via le fichier de verrouillage (pnpm-lock.yaml → pnpm, etc. ; par défaut pnpm)

Si le script d'assistance ne renvoie rien → aucun projet ne définit check → ignorer le reste de cette compétence.

Étape 1a — Aucune suggestion de correctif d'oxlint

oxlint --fix-suggestions applique les correctifs qu'oxlint marque lui-même comme potentiellement modificateurs de comportement : sa suggestion no-console supprime l'appel. --fix-dangerously va plus loin. Les modèles actuels ne passent ni l'un ni l'autre, mais les projets issus de modèles plus anciens le font toujours, dans le wrapper de check, lint:fix, lint-staged ou le propre scripts/check.mjs d'un projet. lt fullstack update les supprime à la racine de l'espace de travail et dans l'application (fichiers suivis et propres uniquement) ; le projet API conserve ses propres fichiers, donc une occurrence y est supprimée manuellement ou en prenant le fichier actuel de nest-server-starter. Observé dans nest-server (2026-09, claude-code PR #10) : un hook de commit a transformé un console.log en un corps de fonction vide et a tout de même signalé "réussi". Avant l'étape 2, recherchez une utilisation de l'un ou l'autre indicateur ; une mention dans un commentaire ne compte pas :

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

Le second filtre supprime les lignes de commentaire : le wrapper actuel de nest-server-starter explique dans un commentaire pourquoi il ne passe que --fix simple.

En cas d'occurrence, le check s'exécute sans correction automatique :

  • Exécutez le wrapper lt comme sa porte en lecture seule : <pm> run check --no-fix (npm : npm run check -- --no-fix). Chaque wrapper qui passe encore l'un des indicateurs connaît déjà --no-fix. Lorsque la propre chaîne d'un projet appelle lint:fix, ou que son propre scripts/check.mjs est l'une des occurrences, exécutez les étapes de ce projet avec lint au lieu de lint:fix.
  • Corrigez les résultats de lint à la main ou avec le simple oxlint --fix ; formatez avec le formateur du projet comme d'habitude.
  • Nommez chaque occurrence (fichier:ligne) dans le rapport de l'étape 8 avec son remède : lt fullstack update pour la racine et l'application, suppression manuelle de l'indicateur (ou le fichier actuel de nest-server-starter) pour le projet API.

Étape 2 — Exécuter check par projet

Pour chaque projet découvert, cd dans son répertoire et exécutez le script check avec le gestionnaire de paquets détecté :

cd "$(dirname <chemin package.json>)"
<gestionnaire de paquets> run check

Capturez stdout, stderr et le code de sortie. Suivez un compteur d'itérations commençant à 1.

Étape 3 — Boucle de correction automatique (itérer jusqu'à ce que ce soit vraiment vert)

Si le check d'un projet se termine avec un code non nul :

  1. Analysez toutes les erreurs de l'exécution en cours (vérification de type, lint, build, imports manquants, incompatibilités de type, symboles inutilisés, résultats d'audit, etc.)
  2. Corrigez chaque erreur à la cause racine via Read + Edit. Les erreurs préexistantes sont également corrigées — qu'une erreur provienne de ce diff ou qu'elle soit déjà là ne fait aucune différence pour l'exécutabilité du projet, et un check rouge bloque la personne suivante exactement aussi fort dans les deux cas. Les limites de portée ne s'appliquent pas à l'exécutabilité. La seule question qui décide quoi que ce soit ici est "cela peut-il être corrigé ?" et tant que la réponse est oui, cela est corrigé.
  3. Ré-exécutez check à partir de zéro. Ne faites jamais confiance à un état partiel.
  4. Continuez d'itérer jusqu'à ce que l'une de ces conditions terminales soit atteinte :
    • (a) VERT — check se termine avec 0 → terminé pour ce projet
    • (b) BLOQUÉ — une itération complète n'a produit aucune réduction nette du nombre d'erreurs
  5. Aucune limite d'itération stricte. Tant que chaque itération réduit strictement le nombre d'erreurs, continuez. L'objectif est le vrai vert.

Une exception étroite, et elle concerne la collision plutôt que la portée. Le point 2 reste valable : une erreur préexistante est corrigée, car un check rouge bloque la personne suivante quel que soit son auteur. Ce que le point 2 ne couvre pas, c'est une erreur à l'intérieur d'un travail non validé sur lequel une autre session en direct est en train de travailler — remanier cela n'est pas une question de portée, c'est deux sessions modifiant un seul fichier, et le pair revient à une refactorisation réécrite ayant perdu plus de temps que le correctif n'en a économisé. Lorsque l'arbre est sale et que bash "${CLAUDE_PLUGIN_ROOT}/scripts/change-provenance.sh" attribue le chemin défaillant à un pair en direct : corrigez-le s'il est trivial et autonome (un import manquant, une violation de format, un console.log errant), et sinon signalez-le comme un bloqueur en nommant l'auteur, plus un SOLVED portant le diagnostic afin qu'il puisse corriger son propre travail en une étape. Personne en direct, ou rien d'attribuable : le point 2 s'applique inchangé.

BLOQUÉ est un signal pour changer d'approche, pas une permission de s'arrêter. Le compteur cesse de baisser lorsque le même correctif est réessayé, donc la prochaine itération doit attaquer l'erreur différemment : lisez le fichier défaillant en entier plutôt que de patcher autour de la ligne signalée, vérifiez si deux erreurs partagent une cause, regardez comment un module frère fonctionnant résout la même chose, exécutez l'étape défaillante seule pour voir la sortie que l'exécution agrégée a avalée, vérifiez s'il s'agit de l'un des dangers connus des étapes 6.5 à 6.8. Ce n'est que lorsqu'une approche vraiment différente a été essayée et que le compteur reste stable que la classification résiduelle de l'étape 5 s'applique — et en mode Bloquant, tout, à l'exception d'une vulnérabilité de dépendance à l'échelle épuisée, arrête toujours le flux.

Étape 4 — Résultats d'audit : échelle d'escalade obligatoire des correctifs

Lorsque pnpm audit / npm audit / yarn audit (invoqué par check) signale une vulnérabilité, épuisez cette échelle avant de classer le résultat comme Accepté. Ré-exécutez check après chaque étape.

#ÉtapeCommande (pnpm / npm / yarn)
1Mise à jour vers la dernière version compatiblepnpm update <pkg> / npm update <pkg> / yarn upgrade <pkg>
2Correction automatiquepnpm audit --fix / npm audit fix / yarn audit --fix
3Forcer la mise à jour majeure semverpnpm audit --fix --force / npm audit fix --force
4Augmenter la dépendance directe à la version majeure suivante si l'avis répertorie le correctif làpnpm add <pkg>@<major> / npm install <pkg>@<major> / yarn add <pkg>@<major>
5Forcer une version de dépendance transitiveBloc pnpm.overrides / resolutions (yarn) / overrides (npm) dans package.json, puis réinstaller
6Augmenter le CONSOMMATEUR, pas le paquet vulnérablela dépendance directe qui le tire, et le framework lt si le framework l'épingle (@lenne.tech/nest-server / @lenne.tech/nuxt-extensions) — un /lt-dev:maintenance:maintain complet est la forme approfondie
7Patcher le consommateur — uniquement dans les conditions ci-dessouspnpm patch <pkg> → patchedDependencies
8Remplacer le paquetPassez à une alternative maintenue si abandonné

L'étape 6 est l'échelon qui est sauté, et c'est celui qui fonctionne le plus souvent. Les étapes 1 à 5 poussent toutes le paquet vulnérable vers l'avant. Lorsque cela échoue, la raison n'est généralement pas du tout le paquet vulnérable — c'est le consommateur qui le retient, en épinglant une plage vulnérable ou en utilisant une API que la version majeure patchée a supprimée. La question à se poser est donc "qui maintient cette version ici ?" et la réponse est une dépendance directe, ou un framework dont une épingle ne peut pas vaincre l'override. Un override est une épingle, et une épingle est strictement pire qu'un vrai bump de version : elle diverge l'arbre de ce que les tests en amont testent, et elle pourrit silencieusement. Prenez le bump là où il existe.

L'étape 7 (patcher) est étroite à dessein, et l'étroitesse est le point. Lorsque la version majeure patchée ne parvient qu'à charger — un export par défaut supprimé, un point d'entrée renommé — un patch d'une ligne semble fermer correctement l'avis plutôt que de le supprimer. Parfois, c'est le cas. Trois conditions doivent d'abord être remplies, et la troisième est celle qui échoue généralement :

  1. Le patch cible un chemin stable dans le paquet vulnérable et est épinglé à une version exacte. Ce qui casse un patch n'est pas dist/ en tant que tel — les paquets publiés livrent dist/ et rien d'autre — c'est un chemin qui bouge entre les versions. dist/chunks/<hash>.mjs est renommé par la prochaine build et le patch échoue alors pour tout le monde dans l'équipe ; dist/index.mjs est le propre point d'entrée du paquet et reste. Un patch qui nomme un symbole minifié est toujours acceptable avec l'épingle de version, car l'épingle transforme le risque en un échec retentissant de pnpm install au lieu d'un mauvais patch silencieux. Patchez la dépendance vulnérable, pas un consommateur qui l'importe par hasard — voir le cas mesuré ci-dessous, où la première évaluation a regardé le chunk du consommateur et a rejeté l'échelon sur cette base.
  2. Pesez la clôture de production contre le coût de maintenance. Un patch est une obligation permanente à chaque futur bump, donc pour un chemin d'outillage de développement qui ne peut pas atteindre la production, il pourrait bien dépenser plus qu'il n'achète — dans un seul projet. Un MODÈLE inverse cette arithmétique : chaque projet généré hérite d'un patch, alors qu'un résidu devrait être rediscuté dans chacun d'eux. C'est un jugement, pas un veto ; les conditions 1 et 3 sont les dures.
  3. Charger n'est pas la même chose que fonctionner. Une version majeure qui a supprimé un export a généralement aussi changé le comportement, donc un import patché fait importer le module tout en laissant le consommateur s'exécuter contre une API sur laquelle il n'a jamais été testé. Si vous ne pouvez pas dire ce qui a changé d'autre dans cette version majeure et pourquoi cela n'a pas d'importance ici, le patch est une hypothèse déguisée en correctif.

Patchez le paquet VULNÉRABLE, pas le consommateur. C'est la distinction qui décide si l'échelon fonctionne, et il est facile de se tromper, car l'erreur pointe vers le consommateur. Mesuré, lt-crm 2026-10-06 : @nuxt/[email protected] fait import Git from 'simple-git', et l'augmentation de simple-git à la seule ligne corrigée (4.x, qui a supprimé cet export par défaut) a fait échouer nuxt prepare avec does not provide an export named 'default'. La première évaluation a regardé le propre dist/chunks/module-main.mjs de devtools, a trouvé l'import là, et a rejeté le patchage sur la condition 1 — un chunk compilé — ce qui était le bon verdict concernant le mauvais fichier. Le patch appartient un niveau plus bas, dans le propre dist/index.mjs de simple-git, où une seule ligne ajoutée réexporte comme default la fabrique même que le module exporte déjà comme simpleGit. Rien dans le code durci ne change ; seule la surface du module revient.

Ce faisant, les trois conditions sont remplies : c'est le paquet vulnérable plutôt qu'un artefact de consommateur, il est épinglé à une version exacte (patchedDependencies: { '[email protected]': … } plus la cible de l'override), et l'API que devtools appelle réellement — branch, revparse, checkout, fetch, mergeLog, status, diffSummary — n'a pas changé entre 3.x et 4.x (simple-git a supprimé l'export par défaut et le constructeur new SimpleGit mais a conservé toutes les méthodes). Le patch tient.

Étape 5 — Classifier les erreurs résiduelles (blocage uniquement)

Si l'itération est bloquée, en mode Bloquant :

  1. Classez chaque erreur non résolue dans l'une des catégories ci-dessous
  2. Si TOUTES les erreurs sont des résidus Acceptables, vous pouvez passer outre le statut rouge — mais jamais en automatique. Un humain vérifie que l'échelle de l'étape 4 a été correctement suivie.
  3. Si UNE erreur est Verte, Rouge ou un autre Bloqueur, le flux s'arrête. Période.

Catégories résiduelles

CatégorieDéfinitionTraitement en mode Bloquant
VertLa vérification se termine correctement après les étapes (1a), 2, 3, 4.Traité comme VERT à toutes fins utiles. Le workflow continue.
Rouge (imblocable)Erreur réelle du projet : typecheck, build, lint, import manquant, etc.Le workflow s'arrête.
Bloqueur (test)L'échec vient uniquement des tests (unitaires, API, Playwright) — le reste (typecheck, build, lint) est vert.Le workflow s'arrête. (Les tests ont leur propre compétence : /lt-dev:fix-test.)
Vulnérabilité de dépendance (échelle épuisée)L'échelle de l'étape 4 a été épuisée et la vulnérabilité persiste.Peut être outrepassée par un humain. Le rapport de résidu liste l'avis, les étapes tentées et le résultat.
Non reproductibleL'erreur du rapport a disparu lors de la réexécution.Traité comme vert pour cette exécution. Signalé dans le rapport comme "instable — le checker local peut être en décalage".
Erreur d'outillageDysfonctionnement du runner de test, conflit de version Node, module manquant dans l'environnement.Traité comme vert si le projet se construit et que les tests passent avec un outillage alternatif. Signalé comme "problème d'environnement — doit être corrigé avant le prochain cycle".

En mode Consultatif, ignorez la classification : signalez chaque erreur non résolue comme un résultat Critique et continuez.

Étape 6 — Rapport de sortie

Quelle que soit la terminaison, émettez un rapport structuré avec :

  • Projets testés
  • Résultat VERT / ROUGE par projet (y compris le nombre d'itérations nécessaires)
  • Résultats d'audit traités (échelle et résultat)
  • Résidus (avec classification)
  • Fichiers modifiés (si corrigés automatiquement)

Étape 6.5 — Pièges & Dangers

Les tsconfig parasites

Certains projets ont plus d'un tsconfig. L'éditeur en utilise un, la compilation en utilise un autre, et check en utilise un troisième — ou pas. Lorsque vous voyez une erreur de type qui n'a aucun sens à l'emplacement du fichier, le problème n'est généralement pas le type, c'est le fichier tsconfig.json que le check a chargé. Vérifiez avec tsc --showConfig ce que le script de check invoque réellement ; un extends manquant ou un exclude supplémentaire est la cause habituelle.

La version de Node ne correspond pas

Le projet exige >=18 et le shell en a 16. check plante à l'étape de build avec "class private fields are not supported". Vérifiez .node-version, .nvmrc, engines dans package.json ; si l'environnement ne correspond pas, signalez-le et n'essayez pas de le corriger — c'est un résidu d'environnement.

Complétez le fichier, pas le diff

Un typecheck échoue sur un fichier que le diff n'a pas touché. Cela arrive. Voir l'étape 3.2 ci-dessus : les limites de portée ne s'appliquent pas à l'exécutabilité. Lisez le fichier qui échoue, corrigez le type, puis vérifiez ce qu'il importe — parfois l'import est un nouveau fichier qui a supprimé l'export, parfois le fichier était déjà cassé. Les deux sont corrigés.

Échecs de l'étape 4&5

L'étape 4 ne garantit pas que l'étape 5 fonctionne : npm audit fix --force peut casser une dépendance qui n'avait pas de vulnérabilité et faire passer une construction verte à rouge. C'est intentionnel. Lorsque cela se produit, l'échelle continue à l'étape 6 (augmenter le consommateur) ou 7 (patcher).

Les tests Playwright sont délibérément exclus de check

Lorsque includes_tests est unit+api, le script check saute Playwright (voir scripts/check.mjs). Cela ne signifie pas que Playwright est ignoré — il s'exécute via lt dev test / CI. Si un appelant a besoin de la couverture Playwright, il doit l'exécuter séparément.


flux de bout en bout de scripts/discover-check-scripts.sh

(partie de la doc de mise en œuvre — dérive rarement)

  1. find_package_json_files — git ls-files + filtre .github/
  2. resolve_composite_script — résolution à un niveau : si check est un run de quelque chose d'autre, regardez-le une fois
  3. detect_package_manager — vérifie le fichier de verrouillage (priorité : pnpm > npm > yarn > bun > autres)
  4. check_includes_tests — recherche test, vitest, jest, playwright dans la chaîne résolue ; unit+api pour le wrapper lt

Individual skills in this repo

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

Skills associés