Notes · Article
Mon générateur de README n’a pas le droit d’inventer
Demandez à un LLM d’écrire un README et vous obtenez un texte long, sûr de lui et en partie inventé : des flags qui n’existent pas, des variables d’environnement que personne ne lit, une étape d’installation tirée d’un autre projet.
Alors dans vibetidy, ce n’est pas le LLM qui décide de ce qui est vrai. Un scanner lit le dépôt, et le modèle se contente de mettre ces faits vérifiés en prose.
Le plus drôle : pendant que je construisais un outil censé ne jamais annoncer ce qui n’existe pas, la CI m’a surpris à faire exactement ça. Deux fois.
Le scanner, c’est le produit
vibetidy readme commence par scanner le dépôt : le manifeste, les scripts, les dépendances, .env.example, les points d’entrée, l’arborescence, le README existant. Seuls ces faits partent vers le modèle, et le prompt le dit sans détour : ne jamais inventer une fonctionnalité, un flag, une variable d’environnement, une dépendance ou une version.
Quand les faits sont maigres, vous obtenez un README court et juste plutôt qu’un long README plausible. Et vous pouvez vérifier ce que le modèle verrait avant de dépenser le moindre token :
npx vibetidy readme --print-context
Pas besoin de clé d’API pour ça. La commande affiche les faits scannés et le prompt complet, puis s’arrête.
Le dépôt
- manifeste
- scripts
- dépendances
- .env.example
- points d’entrée
- arborescence
- README existant
Le scanner
Faits vérifiés
La seule chose que voit le modèle
Le modèle
Les met en prose
Ne jamais inventer
- une fonctionnalité
- un flag
- une variable d’env
- une dépendance
- une version
README.mdUn LLM livré à lui-même
un flag qui n’existe pas
une variable d’env que nul ne lit
une étape tirée d’un autre projet
Long, sûr de lui, en partie inventé
README.mdvibetidy, faits maigres
Court, et juste
Sans clé--print-context affiche les faits scannés et le prompt complet, puis s’arrête.
Premier bug : un flag documenté, jamais enregistré
issue-check --help listait --no-changelog. Le tableau des options du README aussi. L’utiliser se soldait par Unknown option '--no-changelog'.
Le flag n’avait jamais été enregistré dans le parseur. Le parseArgs de Node ne reconnaît un préfixe --no- qu’avec allowNegative, qui demande un Node plus récent que le >=20.10.0 annoncé par le paquet. Il est donc devenu un simple --skip-changelog.
Le correctif tenait en une ligne. Le plus intéressant, c’est que rien ne l’avait repéré : la doc avait l’air juste, le code paraissait plausible, tous les tests passaient. J’ai donc ajouté un test pour toute cette classe de bugs. Il extrait chaque flag de la sortie --help de chaque commande et vérifie que le parseur l’accepte :
for (const flag of flagsIn(help)) {
const res = runCli([command, flag, 'x', '--help']);
assert.notEqual(res.status, 2, `${flag} is documented but rejected`);
}
Pour m’assurer qu’il mord, j’ai glissé un faux --phantom-flag dans le texte d’usage. La suite a échoué avec le message de rejet exact.
issue-check --help
--no-changelog
le listait
Options du README
--no-changelog
le listaient
Le parseur
Unknown option '--no-changelog'
ne l’a jamais enregistré
parseArgsne reconnaît--no-qu’avecallowNegative- Il faut pour ça un Node plus récent que
>=20.10.0 - Il est donc devenu
--skip-changelog
Le nouveau test : chaque flag du --help de chaque commande passe par le parseur
--skip-changelogaccepté
--phantom-flagis documented but rejected
Glissé exprès dans le texte d’usage : la suite a échoué.
Deuxième bug : les tests n’ont jamais tourné sur Node 20
Ouvrir cette PR a fait passer la CI au rouge sur main : 5 jobs sur 9.
npm test lançait node --test "test/**/*.test.js". Les globs ne sont arrivés dans node --test qu’avec Node 21. Sur Node 20, le motif entre guillemets est pris pour un chemin littéral, donc chaque job 20.x échouait avec Could not find .../test/**/*.test.js. La suite n’avait jamais tourné sur la version de Node promise par engines.
Le correctif est presque drôle : un simple node --test, sans aucun motif. La découverte par défaut fonctionne depuis Node 18. La CI est passée au vert sur les neuf jobs (Ubuntu, macOS et Windows, croisés avec Node 20, 22 et 24).
Même classe que le premier bug : quelque chose d’annoncé qui ne marchait pas. C’est grâce à la matrice de 9 jobs que j’ai trouvé les deux.
Comment chaque version de Node lit la commande de test
18
19
20
21
22
23
24
Glob lu comme un chemin littéral
un job de CI
Avant, sur main
node --test "test/**/*.test.js"
5 sur 9 jobs au rouge
Chaque job 20.x : Could not find .../test/**/*.test.js
Après
node --test
9 sur 9 jobs au vert
npm a refusé un nom qui semblait libre
L’outil s’appelait d’abord tidyrepo. npm view tidyrepo renvoyait une 404, donc le nom semblait disponible.
Puis npm publish a échoué avec une 403. Le contrôle de similarité de npm retire la ponctuation, donc tidyrepo entrait en collision avec un tidy-repo existant. Une 404 ne prouve pas qu’un nom est libre : vérifiez aussi les variantes avec tiret et avec underscore.
Il s’appelle vibetidy maintenant, et franchement, ça lui va mieux.
npm view tidyrepo404
Semble libre
npm publish403
Refusé
Le contrôle de similarité de npm retire la ponctuation
Déjà sur npm
tidy-repo
tidyrepo
Le mien
tidyrepo
tidyrepo
Même nom sans ponctuation
Une 404 ne prouve rien. Vérifiez aussi
- tidyrepo
- tidy-repo
- tidy_repo
Désormaisvibetidy
Essayez-le
C’est sous licence MIT, sans aucune dépendance à l’exécution, et ça marche avec OpenAI, OpenRouter, Anthropic, Groq, DeepSeek, Together ou un Ollama local :
npx vibetidy readme --print-context # see the facts, no key needed
npx vibetidy readme # generate, review the diff, confirm
npx vibetidy issue-check --install-hook # nag on feature commits with no issue
-
1Voir les faits
npx vibetidy readme --print-context -
2Générer, relire le diff, confirmer
npx vibetidy readme -
3Rappel à l’ordre sur les commits de fonctionnalité sans issue
npx vibetidy issue-check --install-hook
Marche avec
- OpenAI
- OpenRouter
- Anthropic
- Groq
- DeepSeek
- Together
- Ollama, en local
S’il écrit quelque chose que votre dépôt ne confirme pas, c’est un bug. Ouvrez une issue sur GitHub.
Texte brut: vibetidy-grounded-readme.md · Flux Atom · Toutes les notes