unlazy : imposer des preuves exécutables à un agent qui déclare avoir fini
Anti-laziness skill for AI agents. Core: the Depth Tree method, which splits a task N layers deep and gives every leaf the full time budget of the whole task, so effort multiplies with depth. Grounded in 2025-2026 research on model laziness, underthinking and premature completion.
En bref
- De quoi s’agit-il ?
- unlazy est une skill pour agents de codage qui transforme la fin d'une tâche en un registre de portes vérifiables. Le principe est solide, la mécanique d'approbation est lourde, et le README dit lui-même ce que l'outil ne peut pas prouver.
- À qui s’adresse-t-il ?
- À adopter si vous confiez à un agent des tâches dont la fin se prouve par une commande, et si vous acceptez de maintenir un GATES.md par tâche. À éviter si vous voulez une vérification automatique de bout en bout : unlazy ne contrôle que l'oracle que vous déclarez, et l'approbation ne couvre ni les scripts appelés ni les fixtures.
- Puis-je l’utiliser commercialement ?
- Oui. MIT est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 12 jours.
- En quel langage est-il écrit ?
- Principalement JavaScript, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
Le problème visé : un agent qui annonce la fin sans la prouver
Le README décrit l'objectif en une phrase : écrire d'abord le registre d'acceptation, exécuter des contrôles relus, re-vérifier le travail rendu, et ne rapporter que ce que les preuves soutiennent. La cible n'est donc pas l'agent qui code mal, mais celui qui conclut trop tôt. Le dépôt parle de discipline d'achèvement pour un travail substantiel, et la description le rattache à des travaux 2025-2026 sur la paresse des modèles et la complétion prématurée. Ce cadrage a une conséquence pratique : unlazy ne vous aide pas à trouver quoi construire. Il vous aide à refuser une déclaration de victoire qui ne s'appuie sur rien. Le public visé est celui qui lance un agent sur une refactorisation, une migration ou une vérification de chemins multiples, et qui veut un artefact lisible par un humain avant de croire au résultat.
Deux niveaux, deux natures : la méthode d'arbre et le contrat de portes
Le dépôt mélange deux choses qu'il faut séparer. D'un côté une méthode de découpage, appelée Depth Tree, décrite comme une division d'une tâche sur N niveaux où chaque feuille reçoit le budget de temps complet de la tâche entière. C'est une heuristique de répartition de l'effort, invoquée dans le README par l'exemple `/unlazy tree 5 refactor the payment module and verify every migration path`. Le nombre 5 fixe la profondeur. De l'autre côté, et c'est la partie qu'on peut réellement inspecter, un format de registre Markdown et un vérificateur Node. Le fichier central est SKILL.md, et le vérificateur vit dans scripts/gate-check.mjs. La méthode d'arbre n'a pas de traceur ni de sortie mesurable dans le matériel fourni : elle se juge à l'usage, pas au contenu du dépôt. Le contrat de portes, lui, est spécifié, avec un parseur, des règles de rejet et un format de preuve.
Anatomie d'une porte : CHECK, EXPECT, CWD, EVIDENCE
Une porte est un bloc Markdown numéroté avec une case à cocher. Le README donne cet exemple : `- [ ] G1: pricing fixtures render the expected tiers`, suivi de `CHECK: node scripts/verify-pricing.mjs`, de `EXPECT: pricing verification passed`, puis de `EVIDENCE: pending`. Une seconde porte ajoute `CWD: packages/checkout`, ce qui montre que le répertoire de travail fait partie de la définition. La règle de réussite est double : le processus doit sortir avec le code 0 et `EXPECT:` doit correspondre à la sortie combinée. Le README précise une limite de 1 MiB sur la charge capturée et sur la chaîne UTF-8 canonique utilisée par `EXPECT:` et son empreinte, et affirme que le vérificateur ne tronque jamais une chaîne de correspondance plus grande pour la transformer en succès. Les preuves automatiques commencent par un digest SHA-256 complet et versionné de la définition analysée, suivi du code de sortie et de l'empreinte de sortie, avant des détails d'environnement plafonnés. Cette liaison n'est pas signée : le README écrit noir sur blanc que quiconque peut modifier un registre peut fabriquer une preuve d'apparence canonique.
Mise en route : installer, copier un modèle, inspecter avant d'exécuter
L'installation passe par la CLI skills : `npx skills add Leonxlnx/unlazy`, avec `-g` pour un niveau utilisateur ou `--all` pour tous les agents détectés. En manuel, le README indique `~/.claude/skills/unlazy` pour Claude Code et `~/.codex/skills/unlazy` pour Codex CLI. L'invocation se fait par `/unlazy` là où les slash skills existent, `$unlazy` dans Codex, ou par déclenchement en langage naturel. Pour une tâche solo, on copie `templates/gates-leaf.md` vers `GATES.md`, on remplace chaque emplacement, puis on inspecte sans exécuter : `node <path-to-skill>/scripts/gate-check.mjs --status GATES.md`. Le README insiste sur un point : `--status` est le seul mode toujours non exécutant. Un appel normal, sur un oracle sans enregistrement d'approbation exact, affiche la commande résolue, l'attente, le répertoire de travail, le shell et le `PATH` sans rien lancer. Mais dès que l'oracle exact est approuvé, le mode normal peut exécuter. Le passage à l'exécution se fait par `--approve`, et la reprise complète par `--reverify`, qui relance toutes les portes exécutables, y compris celles déjà marquées terminées. Le vérificateur et le hook optionnel demandent Node 16 ou plus et n'utilisent aucun paquet tiers à l'exécution.
Le shell et le PATH sont une source de faux négatifs
Le README consacre une section entière à ce point, ce qui indique qu'il a été rencontré. L'ordre de résolution est : `--shell`, puis la variable `UNLAZY_SHELL`, puis le shell par défaut de la plateforme, soit `/bin/sh` sur Unix et `process.env.ComSpec` sous Windows. Les contrôles héritent de l'environnement de lancement, `PATH` compris. L'exemple donné est concret : un vérificateur lancé depuis Git Bash peut voir des outils de type Unix que le même vérificateur lancé depuis PowerShell ne voit pas. Et `--shell` ne fait que changer l'interpréteur ; il n'installe ni `grep`, ni `tail`, ni `tr`. D'où la recommandation du dépôt : les exemples portables appellent des scripts Node appartenant au dépôt. Pour la re-vérification par un parent, il faut réutiliser le shell déclaré et la chaîne d'outils requise. Un écart de shell ou de `PATH` doit être traité comme une vérification échouée, pas comme une preuve de succès. C'est une position sévère mais cohérente avec le reste : l'incertitude n'est jamais convertie en réussite.
L'approbation : consentement, pas bac à sable
Les enregistrements d'approbation vivent par défaut sous `~/.unlazy/approved`. La variable `UNLAZY_APPROVAL_DIR` peut désigner un autre répertoire, à condition que sa cible canonique reste en dehors du dépôt vérifié. Les magasins liés par symlink, les enregistrements liés, remplacés ou non privés échouent en mode fermé. Chaque enregistrement est propre au registre absolu et à la porte, au `CHECK:` et à l'`EXPECT:` exacts, au `CWD:` résolu, au shell, au délai d'expiration, aux limites de sortie et de regex, aux limites de workers de regex, à la plateforme et au `PATH` hérité complet. Modifier une seule entrée liée oblige à réapprouver. Le README formule la limite sans détour : l'approbation est un consentement, pas un bac à sable. Elle ne hache ni les scripts appelés, ni les fixtures, ni les dépendances, ni les autres entrées transitives. `--status` et le hook Stop valident la liaison de définition enregistrée mais n'inspectent pas ces artefacts. Si un script appelé change, il faut le réexaminer et lancer `--reverify`. Le README renvoie à SECURITY.md pour un motif de digest borné quand une identité de dépendance conçue par l'utilisateur est nécessaire.
Ce que le vérificateur ne peut pas décider
La phrase la plus utile du README est aussi la plus honnête : le vérificateur ne peut prouver que l'oracle de commande que vous déclarez, et il ne peut pas déduire qu'un titre en anglais et du code shell arbitraire veulent dire la même chose. Autrement dit, `G1: pricing fixtures render the expected tiers` et `EXPECT: pricing verification passed` n'ont aucun lien logique vérifié par l'outil. Le lien, c'est vous qui l'affirmez. Le dépôt en tire des règles de qualité : lire l'artefact ou le service nommé par le résultat, imprimer un marqueur de succès seulement après toutes les assertions, tester une vérification d'absence contre un contrôle positif connu, mesurer les chiffres fournis au lieu de les recopier dans `EXPECT:`, et revoir les résultats manuels conséquents avec une preuve proportionnée au risque. Un linter consultatif et non exécutant, `scripts/gate-lint.mjs`, attrape les motifs mécaniquement faibles, avec `--strict` quand un avertissement doit faire échouer. Cela reste un conseil : une porte bien formée peut prouver exactement la mauvaise chose. Le parseur, lui, rejette les registres sans porte, les identifiants dupliqués, les portes exécutables incomplètes, les attentes invalides, et un abandon sans raison ou avec un identifiant de porte inconnu. Un abandon valide n'est pas un succès : le vérificateur sort avec le code 1 et le message `HANDOFF REQUIRED`.
Version, licence et coût de maintenance
Le README indique que la source courante cible la version `2.1.0`, sans qu'elle soit identifiée comme une release GitHub étiquetée, et renvoie à CHANGELOG.md pour le jeu de changements non publié. Pour une installation immuable, il faut épingler un commit exact. C'est un point de maintenance réel : sans tag, la référence bouge. La licence est MIT, ce qui autorise la réutilisation et la modification avec conservation de l'avis de licence ; ce n'est pas un avis juridique, et les implications pour un usage interne dépendent de votre propre politique. Le coût d'exploitation, lui, est visible dans le contrat : un `GATES.md` par tâche, des enregistrements d'approbation qui se périment dès qu'une entrée liée change, et des re-vérifications à relancer quand une dépendance transitive évolue. Sur des tâches courtes, écrire les portes coûte plus cher que le travail lui-même. unlazy est un outil de fin de tâche, pas de début.
Conclusion éditoriale
À adopter si vous confiez à un agent des tâches dont la fin se prouve par une commande, et si vous acceptez de maintenir un GATES.md par tâche. À éviter si vous voulez une vérification automatique de bout en bout : unlazy ne contrôle que l'oracle que vous déclarez, et l'approbation ne couvre ni les scripts appelés ni les fixtures. Avant tout usage réel, lancez node scripts/gate-check.mjs --status GATES.md sur un registre copié depuis templates/gates-leaf.md, puis vérifiez que votre CHECK: reste portable entre le shell de lancement et celui de la re-vérification parente.
Notes de la communauté