Communitygithub.com

lenneTech/maintaining-lt-stack

Maintenance et releases de l'ensemble des dépôts de base lt ("Grund-Repos") : ordre des dépendances, procédure de release par dépôt, et test de fumée comme passerelle de release.

Qu'est-ce que maintaining-lt-stack ?

Ce skill automate la maintenance et les releases coordonnées des sept dépôts de base de lenneTech, en respectant un ordre de dépendances précis. Il est conçu pour les agents IA comme Claude Code, Cursor ou Codex, et s'active sur des commandes comme "maintain stack", "release all repos", "stack release", "Grund-Repos aktualisieren" ou via /lt-dev:publish. Le skill orchestre les releases en deux vagues parallélisables (Wave 1 : nuxt-extensions, nest-server, lt-monorepo, cli ; Wave 2 : nuxt-base-starter, nest-server-starter) suivies d'une validation par un test de fumée fullstack. Il inclut des protocoles de coordination entre sessions (avec un registre de revendication), des vérifications de la résolution des paquets npm via l'endpoint version-spécifique plutôt que `npm view`, et des règles transversales comme la synchronisation des paquets critiques entre les deux frameworks, l'obligation de revue avant publication, et la gestion des canaux de push. Ce skill n'est pas destiné à un seul paquet npm (utiliser maintaining-npm-packages) ni aux mises à jour de nest-server dans les projets clients (utiliser nest-server-updating).

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lenneTech/claude-code/tree/HEAD/plugins/lt-dev/skills/maintaining-lt-stack

Demander à votre IA préférée

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

Documentation

Maintenance de la stack lt (tous les dépôts de base)

Les sept dépôts de base sont maintenus et publiés dans l'ordre des dépendances. La source canonique est github.com/lenneTech ; la publication nécessite un clone local de chacun, et le chemin de checkout diffère par machine — localisez-le plutôt que d'en supposer un :

find "$HOME" -maxdepth 5 -type d -name nest-server-starter -not -path '*/node_modules/*' 2>/dev/null

Si un dépôt n'est pas cloné, clonez-le dans le même répertoire de travail que ses voisins. État final visé : chaque dépôt à jour, check vert partout, paquets npm publiés, templates tagués — prouvé par un test complet /lt-dev:fullstack:smoke-test.

Graphe de dépendances (dicté par l'ordre)

Vague 1 (parallélisable) :   nuxt-extensions   nest-server   lt-monorepo   cli
                                 │                │
                                 ▼ (attendre la publication npm !)
Vague 2 (parallélisable) :   nuxt-base-starter  nest-server-starter
                                 │
                                 ▼
Validation :                /lt-dev:fullstack:smoke-test  (utilise TOUS les dépôts en live)
                                 │
                                 ▼
Vague 3 (uniquement si constaté) : correctifs → re-publier les dépôts affectés (nest-server-starter: push uniquement)

Règle : Un starter n'est mis à jour que lorsque son paquet npm est réellement résoluble sur npm, pas lorsque la release GitHub existe — l'action publish.yml prend des minutes.

Interrogez le point de terminaison version-spécifique, pas npm view. npm view et https://registry.npmjs.org/<pkg> lisent le même packument mis en cache par CDN, et il retarde de plusieurs minutes par rapport à une publication :

curl -s -o /dev/null -w '%{http_code}' https://registry.npmjs.org/<pkg>/<version>
# 200 = résoluble maintenant. Alternative : invalider le cache avec -H 'Cache-Control: no-cache' et un paramètre de requête.

Mesuré le 2026-09-04 : une session a interrogé npm view pendant dix minutes et a lu "pas encore publié" alors que @lenne.tech/[email protected] était déjà disponible — le point de terminaison version-spécifique a répondu 200 immédiatement. Du côté de l'appelant, "pas encore là" et "l'instrument lit un cache" se ressemblent, c'est pourquoi c'est le point de terminaison à interroger.

Exécution des vagues sur des sessions parallèles

Les vagues ci-dessus sont dites "parallélisables" et c'est littéral : une session Claude Code par dépôt, dans son propre terminal, c'est ainsi qu'une release de stack va vraiment vite. La vague 1 contient quatre dépôts indépendants et la vague 2 deux de plus, donc le temps réel minimum est d'une release par dépôt, pas six en séquence.

Cela ne fonctionne que si les sessions se coordonnent sur quatre points. Tout cela repose sur le protocole coordinating-peer-sessions, et la répartition par dépôt est exactement la limite que ce protocole demande : jamais deux sessions ne touchent le même arbre de travail.

1. Revendiquer un dépôt avant de commencer. Enregistrez-le d'abord dans le registre, puis annoncez-le :

bash "${CLAUDE_PLUGIN_ROOT}/scripts/peer-ledger.sh" read                          # qui possède quoi
bash "${CLAUDE_PLUGIN_ROOT}/scripts/peer-ledger.sh" claim "repo:nest-server" "Vague 1 release"

La partie registre est plus importante ici qu'ailleurs : un cycle de release dure des heures, les sessions vont et viennent, et une revendication qui vit uniquement dans un message est perdue dès que son terminal se ferme. claim refuse un dépôt qu'une autre session active détient et le nomme ; une revendication dont la session est morte apparaît comme [stale] et est libre à prendre, donc un crash ne bloque jamais un dépôt. Libérez avec peer-ledger.sh release "repo:nest-server" "<version>" lorsque le dépôt est terminé. Sans cela, deux sessions publient nest-server et la deuxième crée une version par-dessus la première.

[CLAIM] nest-server — je prends la release Vague 1 pour ce dépôt.
Concerne : la release de la stack ; personne d'autre ne doit le versionner ou le publier.
Nécessaire : choisir un autre dépôt de la Vague 1.
Libre : quand je signale READY avec la version publiée.

2. Signaler la Vague 2 avec READY, ne pas la faire scruter. L'attente entre les vagues est un véritable délai de propagation npm, et la session qui attend n'a aucun moyen de savoir le moment exact où il se termine, sauf en interrogeant le registre encore et encore. La session qui publie sait exactement quand. Elle envoie un READY avec la version :

[READY] @lenne.tech/[email protected] est publié et résoluble sur le registre.
Concerne : nuxt-base-starter — la mise à jour de dépendance Vague 2 peut commencer.
Nécessaire : pnpm add @lenne.tech/[email protected] et continuer.

La session Vague 2 peut également s'abonner avec notify_when_idle sur la session Vague 1 au lieu de scruter. Dans les deux cas, personne ne reste dans une boucle sleep contre le registre.

3. Envoyer SOLVED pour tout ce qui est environnemental. Les pièges empiriques de ce skill sont presque tous liés à la machine, pas au dépôt : une lecture distante qui a silencieusement rien renvoyé, un registre qui n'a pas propagé, une file d'attente de CI qui s'accumule, une version d'outils qui a cassé. La première session à diagnostiquer un problème l'a déjà payé, et les cinq autres se heurtent au même mur. Un SOLVED et elles ne le font pas.

[SOLVED] `git ls-remote` échoue sur stderr avec une sortie vide, donc les vérifications de tag lisent "aucun tag".
Concerne : tous les dépôts de ce cycle de release ; votre vérification de tag ment de la même manière.
Nécessaire : vérifier le code de sortie, ou lire via HTTPS — voir la règle du canal de push.

4. Signaler la fin avec LANDED, pour que le test de fumée commence une seule fois. La passerelle de validation s'exécute après que chaque dépôt est publié. Celui qui termine le dernier le lance ; les autres le signalent et s'arrêtent.

Ce qui ne passe pas par les messages : quels dépôts existent et dans quel ordre (ce skill le dit), et quelle version un dépôt a (le registre et les tags le disent). Et aucune session n'assigne un dépôt à une autre. L'utilisateur décide qui prend quoi, ou chaque session en revendique un libre et le dit.

Règles transversales (tous les dépôts)

  • Les paquets critiques pour le câblage bougent dans les DEUX dépôts de framework, en une seule fois. Certaines dépendances ne concernent pas un seul dépôt — ce sont un protocole avec deux extrémités, et nest-server et nuxt-extensions en possèdent chacun une. better-auth est le cas qui nous a appris ; traitez tout paquet que les deux frameworks importent de la même manière.

    Les deux le déclarent comme peer avec une plage qui est identique octet par octet dans les deux manifests, et étroite : >=<plus basse version connue bonne> <<prochaine mineure>, jamais ^. better-auth casse dans les releases MINEURES, donc un caret invite la même division une release plus tard. Lisez la plage actuelle dans les manifests plutôt que depuis ici — elle bouge, et une version écrite dans ce skill devient obsolète :

    node -e 'for (const p of ["nest-server","nuxt-extensions"]) console.log(p, require(`${process.env.HOME}/code/lenneTech/${p}/package.json`).peerDependencies["better-auth"])'
    

    L'augmenter signifie : relever la plage dans nest-server ET nuxt-extensions, épingler la nouvelle version dans nest-server-starter ET nuxt-base-starter, publier les quatre. Jamais la moitié, même "juste pour débloquer le frontend". Augmenter uniquement la BORNE INFÉRIEURE est aussi une augmentation — c'est elle qui dit quel correctif est connu comme bon, et une borne inférieure qui diffère entre les deux dépôts est le même défaut qu'une division de version, une release plus tôt.

    Le seuil n'est pas une question de goût : il doit satisfaire les pairs FRÈRES aussi. Un paquet comme better-auth est livré avec des compagnons (@better-auth/passkey, @better-auth/core) qui exigent à leur tour une version de celui-ci en peer. Un seuil en dessous de ce qu'un compagnon exige bénit un appariement qui ne peut pas réellement s'installer — >=1.7.0 permettait better-auth 1.7.0 à côté de passkey 1.7.1, que passkey lui-même rejette (^1.7.1). La plage n'était pas fausse en général ; elle admettait exactement une combinaison croisée invalide, qui est précisément le genre qu'aucune installation dans l'un ou l'autre dépôt ne rencontrerait jamais. Dérivez le seuil du manifeste du compagnon, pas de l'intuition :

    node -e 'console.log(require("./node_modules/@better-auth/passkey/package.json").peerDependencies)'
    

    nuxt-extensions vérifie cela mécaniquement dans test/peer-dependency-ranges.test.ts (seuil par rapport à l'exigence du compagnon, et chaque plage par rapport à la devDependency effectivement testée). Cela vaut la peine d'être copié partout où une plage peer a des compagnons.

    Ce qu'une division coûte, mesuré : nest-server a épinglé better-auth 1.6.26 comme dépendance dure tandis que nuxt-extensions déclarait un peer, donc l'application est passée à 1.7.1 et l'API n'a pas pu suivre. 1.7 donne twoFactor.enable un résultat discriminé portant method, que 1.6.26 n'envoie jamais — chaque activation 2FA dans chaque projet fullstack a échoué, avec une erreur client générique et rien d'inhabituel dans le journal du serveur. Les check des deux dépôts étaient verts tout le temps : chacun était cohérent en interne, et seul l'espace de travail assemblé a les deux moitiés.

    Trois gardes le détectent aujourd'hui, et aucun ne remplace cette règle — ils attrapent l'erreur, la règle l'empêche :

    • Quand les manifests sont fusionnés (lt CLI hoist-workspace-pnpm-config.ts, depuis 1.45.0). La fusion est dernier-écrit-gagne, ce qui est correct pour racine-vs-sous et un piège entre frères. Signalé : deux sous-projets définissant une clé différemment dans la même exécution ; le cas incrémental (add-api puis add-app, où l'exécution précédente avait déjà fusionné et vidé sa source) ; et un dépôt se contredisant LUI-MÊME à travers package.json#pnpm et son propre pnpm-workspace.yaml. allowBuilds n'est pas seulement signalé mais fusionné perd-gagne — un avertissement n'arrête pas un script d'installation qu'un projet a explicitement refusé, et overrides reste en lecture seule car il n'y a pas de direction sûre pour une version.

    • Dans l'espace de travail assemblé (lt-monorepo/scripts/check-workspace-consistency.mjs, depuis 3.10.0). Échoue quand api et app résolvent un paquet critique pour le câblage différemment, quand les deux frameworks promettent des plages peer différentes, ou quand un membre a le paquet installé mais ne l'épingle nulle part — autoInstallPeers est par défaut à true, donc un peer non épinglé est d'accord aujourd'hui et libre de dériver à la prochaine installation.

    • Dans le comportement (nuxt-base-starter/.github/workflows/test.yml, job e2e-auth, vert depuis 2.22.3). Démarre MongoDB et nest-server-starter et exécute la suite d'authentification contre une vraie API. La seule couche qui voit un contrat cassé plutôt qu'une différence de version — l'autre compare les déclarations, et les déclarations étaient vertes pendant toute la division.

      Deux choses dont il a besoin et qui sont faciles à manquer, toutes deux trouvées par ses propres premières exécutions : les dépendances du template doivent être installées séparément (il a son propre verrou, et sa chaîne de vérification commence avec cross-env — l'une de ses propres devDependencies), et une base de données vide dirige chaque visiteur vers /auth/setup, donc le premier administrateur doit être créé via POST /system-setup/init avant que la suite s'exécute.

    Le test de fumée est la passerelle de bout en bout : il construit un vrai projet fullstack, donc c'est l'endroit où une division de câblage se manifeste comme un flux échoué plutôt que comme une différence de version.

  • Rien n'est publié avant que /lt-dev:review ait été exécuté sur le diff de release de ce dépôt (/lt-dev:review --base=<dernier tag de release>, qui inclut les fichiers non commités et non suivis), après sa maintenance et avant son incrémentation de version. Prenez le tag de origin/main : git describe --tags --abbrev=0 origin/main. Les tags de release se trouvent sur main dans chaque dépôt de base, et ceux de nest-server sont des commits de fusion que develop ne contient jamais, donc une recherche à partir de HEAD retourne un tag vieux de plusieurs releases (mesuré le 2026-10-27 sur nest-server develop : 11.33.1 au lieu de 12.0.0, une revue de 851 fichiers au lieu de 14). Chaque dépôt d'une chaîne le passe sur son propre diff ; un constat que la revue n'a pas pu corriger arrête la release de ce dépôt et tout ce qui est en aval. Décidé par Kai le 2026-10-21, pour qu'une chaîne de release automatisée ne publie jamais de code que personne n'a revu.

  • Pas de changement → pas de release. Le SEUL cas qui saute une release est un dépôt où il n'y a vraiment RIEN qui a changé (arbre de travail propre ET aucun commit depuis la dernière version publiée) — ne créez jamais une version qui ne contient aucun changement. TOUT changement réel du dépôt — mises à jour de dépendances, code, scripts, verrou, épinglage d'outils — justifie une nouvelle version ; ne remettez pas en question si un changement est "digne d'une release". Un dépôt inchangé est signalé comme "déjà à jour — pas de release" et ignoré. La seule exception est nest-server-starter : sa version ne change qu'avec une version de nest-server, donc ses propres modifications sont commitées et poussées sans release et sont livrées sous la suivante (recipes.md, nest-server-starter). La référence est L'ARTEFACT PUBLIÉ : pour les paquets npm, les commits qui ne peuvent pas atteindre l'archive (en dehors de l'ensemble files de package.json — par exemple .claude/agent-memory/**, la configuration CI) ne déclenchent pas leur propre release ; vérifiez avec npm pack --dry-run en cas de doute. Ces commits accompagnent simplement la prochaine release réelle. Pour les templates, l'artefact est le dépôt lui-même, donc chaque commit compte.

  • Canal de push : demandez au script, qui le décide fonctionnellement :

    bash "${CLAUDE_PLUGIN_ROOT}/scripts/check-push-channel.sh" [<racine-du-dépôt>]   # omettre à l'intérieur du dépôt ; ne jamais passer "$(pwd)"
    # -> ssh<TAB>github.com<TAB>authentifié en tant que : Hi kaihaase! …
    # -> https<TAB>github.com<TAB>pas d'authentification SSH (…)
    

    Sur https, push via HTTPS : git -c credential.helper='!gh auth git-credential' push https://github.com/lenneTech/<repo>.git <branche>. gh release create n'est pas affecté dans les deux cas.

    Exécutez la vérification quand un push échoue pour ce qui semble être un problème de droits. Mesuré le 2026-09-08 sur nest-server-starter : git push origin main a échoué avec Please make sure you have the correct access rights and the repository exists, alors qu'un push vers nest-server via SSH a fonctionné dans les mêmes minutes. Rien n'allait avec le compte, le statut de collaborateur ou l'URL distante — SSH vers github.com était mort pour ce chemin uniquement, la vérification a dit https<TAB>github.com<TAB>pas de réponse du serveur. https://github.com/lenneTech/nest-server-starter a répondu 200, donc le push HTTPS a fonctionné. Le diagnostic n'est pas un problème de droits tant que la vérification n'a pas été exécutée.

Procédure de release : vue d'ensemble

Chaque dépôt de base suit recipes.md (à la racine de ce dossier, qui fait partie de lt-cli) pour les détails de maintenance et de release. Utilisez-le comme guide procédural.

Avant de commencer : confirmez avec l'utilisateur qu'une release de stack est souhaitée, ce qui est déjà fait si ce skill est activé. Signalez à l'utilisateur que les sessions parallèles vont commencer et que le temps total est le temps d'un seul dépôt plus la propagation.

Récapitulatif de la coordination

  1. Revendiquer un dépôt avec peer-ledger.sh claim
  2. Attendre que la Vague 1 soit terminée (READY pour chaque dépôt)
  3. Commencer la Vague 2
  4. Exécuter le test de fumée lorsque tout est publié
  5. Signaler LANDED lorsque le test réussit

Aucune session ne doit publier un paquet sans que la revue n'ait été exécutée.

Aucune session ne doit publier une version vide.

Aucune session ne doit assigner un dépôt à une autre session.

Le dernier dépôt de la Vague 2 lance le test de fumée.

Individual skills in this repo

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

Skills associés