@eqs/testing conseille git push --no-verify quand Docker est éteint — un agent de codage le lit comme une autorisation #50

Closed
opened 2026-09-10 10:58:33 +00:00 by nicolas-fryder · 3 comments

Le message d'erreur de parCompose, quand le démon Docker ne répond pas, recommande explicitement de contourner la porte.

Le texte exact

node_modules/@eqs/testing/dist/base.js:96-101, rencontré tel quel en jouant pnpm --filter api test:integration avec Docker Desktop arrêté :

Error: Docker ne répond pas : la base jetable ne peut pas être levée.
  L'étage d'intégration monte un vrai PostgreSQL en tmpfs, détruit à la fin.
  Démarrer Docker, puis relancer. Pour pousser malgré tout, et le dire dans
  le message de commit : git push --no-verify

Reproduction

Dans n'importe quel satellite, Docker Desktop arrêté :

pnpm --filter api test:integration

Ce que ça coûte

Pour une personne, c'est un conseil raisonnable et honnêtement formulé — il demande même de le dire dans le message de commit.

Pour un agent de codage, c'est autre chose. Un agent lit ce message comme une instruction outillée : la ligne à jouer est écrite, la justification est fournie, et elle vient du socle lui-même. Or AGENTS.md des satellites pose l'interdiction en absolu (D-013 : le hook pre-push est la porte, --no-verify ne s'utilise jamais). L'agent se retrouve donc avec deux consignes contradictoires, dont la plus opérationnelle est celle qui ouvre la porte — et --no-verify ne saute pas que les tests : il saute aussi gitleaks.

C'est exactement la position qu'a formulée EQS/CODEX#13 ce matin, à propos d'un hook dont le message n'aidait pas : « un refus qui ne nomme pas sa cause fait perdre du temps, puis fait prendre l'habitude du --no-verify — et c'est une porte de sécurité. » Ici le message nomme très bien sa cause ; il enchaîne simplement sur le contournement.

Non bloquant : le message est juste sur le fond, Docker relancé règle tout. C'est le conseil qui pose problème, pas le diagnostic.

Ce que je proposerais

Retirer les deux dernières lignes, et s'arrêter à « Démarrer Docker, puis relancer. » Le diagnostic est déjà excellent — il dit ce qui manque et quoi faire. La suite ne fait qu'offrir une sortie qu'on ne souhaite pas voir prise.

Si l'intention était d'aider quelqu'un à pousser un travail en cours sans Docker, la même phrase peut le dire sans écrire la commande : « sans Docker, l'étage d'intégration ne peut pas être joué — ne poussez pas en le contournant sans en parler ». Une personne qui connaît --no-verify n'a pas besoin qu'on le lui rappelle ; un agent, si.

Trouvé en développant le premier satellite réel (Pilotage), Docker Desktop s'étant arrêté en cours de session.

Versions

  • @eqs/testing : 0.8.1
  • eqs --version : 0.8.1
  • Node : v24.15.0, Windows 11 Pro 26200
Le message d'erreur de `parCompose`, quand le démon Docker ne répond pas, recommande explicitement de contourner la porte. ## Le texte exact `node_modules/@eqs/testing/dist/base.js:96-101`, rencontré tel quel en jouant `pnpm --filter api test:integration` avec Docker Desktop arrêté : ``` Error: Docker ne répond pas : la base jetable ne peut pas être levée. L'étage d'intégration monte un vrai PostgreSQL en tmpfs, détruit à la fin. Démarrer Docker, puis relancer. Pour pousser malgré tout, et le dire dans le message de commit : git push --no-verify ``` ## Reproduction Dans n'importe quel satellite, Docker Desktop arrêté : ``` pnpm --filter api test:integration ``` ## Ce que ça coûte Pour une personne, c'est un conseil raisonnable et honnêtement formulé — il demande même de le dire dans le message de commit. **Pour un agent de codage, c'est autre chose.** Un agent lit ce message comme une instruction outillée : la ligne à jouer est écrite, la justification est fournie, et elle vient du socle lui-même. Or `AGENTS.md` des satellites pose l'interdiction en absolu (D-013 : le hook `pre-push` est la porte, `--no-verify` ne s'utilise jamais). L'agent se retrouve donc avec deux consignes contradictoires, dont la plus opérationnelle est celle qui ouvre la porte — et `--no-verify` ne saute pas que les tests : il saute aussi `gitleaks`. C'est exactement la position qu'a formulée [EQS/CODEX#13](https://git.equilibre-structures.fr/EQS/CODEX/issues/13) ce matin, à propos d'un hook dont le message n'aidait pas : « un refus qui ne nomme pas sa cause fait perdre du temps, puis fait prendre l'habitude du `--no-verify` — et c'est une porte de sécurité. » Ici le message nomme très bien sa cause ; il enchaîne simplement sur le contournement. Non bloquant : le message est juste sur le fond, Docker relancé règle tout. C'est le conseil qui pose problème, pas le diagnostic. ## Ce que je proposerais Retirer les deux dernières lignes, et s'arrêter à « Démarrer Docker, puis relancer. » Le diagnostic est déjà excellent — il dit ce qui manque et quoi faire. La suite ne fait qu'offrir une sortie qu'on ne souhaite pas voir prise. Si l'intention était d'aider quelqu'un à pousser un travail en cours sans Docker, la même phrase peut le dire sans écrire la commande : « sans Docker, l'étage d'intégration ne peut pas être joué — ne poussez pas en le contournant sans en parler ». Une personne qui connaît `--no-verify` n'a pas besoin qu'on le lui rappelle ; un agent, si. Trouvé en développant le premier satellite réel (Pilotage), Docker Desktop s'étant arrêté en cours de session. ## Versions - `@eqs/testing` : 0.8.1 - `eqs --version` : 0.8.1 - Node : v24.15.0, Windows 11 Pro 26200
Author
Owner

Vrai, et corrigé. Votre distinction personne / agent est la bonne, et il y a deux choses à y ajouter — dont une qui ne vous fait pas plaisir, ni à moi.

La classe avait déjà été corrigée une fois

ETAT.md et le CHANGELOG de quatre packages portent cette phrase :

Le hook pre-commit conseillait --no-verify devant un avis sans correctif — c'est-à-dire d'éteindre la porte, exactement ce que MCP/scripts/audit.mjs avait été écrit pour éviter.

L'argument était donc déjà formulé, dans ce dépôt, avec les mêmes mots. Corrigé là, et nulle part ailleurs. C'est exactement le motif que reference/chasses.md existe pour casser, et il a fallu que vous le retrouviez à la main.

--no-verify saute aussi gitleaks

Le message ne proposait pas seulement de sauter les tests. Le même drapeau saute le scan de secrets — et le pre-push écrit lui-même, quarante lignes plus bas :

Il n'y a PAS de contournement legitime ici : --no-verify enverrait le secret au serveur, et un secret pousse est un secret a revoquer.

Un démon Docker arrêté n'a aucun rapport avec le scan de secrets. Le message empruntait une porte de sortie à un problème qui n'était pas le sien.

La correction

Votre proposition, avec la phrase de remplacement que vous suggériez :

Docker ne répond pas : la base jetable ne peut pas être levée.
  L'étage d'intégration monte un vrai PostgreSQL en tmpfs, détruit à la fin.
  Démarrer Docker, puis relancer.
  Sans Docker, cet étage ne peut pas être joué du tout : ce qu'il éprouve
  reste inconnu. Ne poussez pas en le tenant pour vert.

Le diagnostic reste entier. Ce qui part, c'est la commande.

Le garde-fou balaie tout le package

Pas la ligne signalée : un cas de @eqs/testing parcourt tout son src/ et rougit si --no-verify, --ignore-scripts ou HUSKY=0 reparaît dans du code. Éprouvé en remettant la commande — il la trouve et nomme le fichier :

AssertionError: packages/testing/src/base.ts → --no-verify

Les commentaires sont écartés avant de chercher, et ce n'est pas un détail : le commentaire qui explique pourquoi la commande n'est plus là la cite six fois. Sans ça le cas serait rouge en permanence, donc retiré dans la semaine — c'est la classe de #47, rencontrée une septième fois, cette fois par anticipation.

Cherché ailleurs

Une seule autre occurrence de la commande dans les dix packages : un commentaire de @eqs/cli qui explique justement pourquoi il ne faut pas la passer. Rien d'autre — ni --ignore-scripts, ni HUSKY=0. Le --force d'eqs auth roles --init est le drapeau propre de l'outil, pas le contournement d'une porte : je l'ai laissé.

Ce que je n'ai pas fait, et pourquoi

Les hooks continuent d'écrire git push --no-verify. docs/cadre-tests-qualite.md le demande explicitement :

Chaque hook explique comment le contourner. Un hook incontournable finit désactivé globalement, donc supprimé pour toujours.

Cet argument tient pour un hook : c'est lui qui vous bloque, et la sortie écrite évite qu'on l'arrache une fois pour toutes. Il ne tient pas pour une bibliothèque qui constate qu'un démon est arrêté — là, rien ne bloque un push. C'est la ligne que j'ai tracée, et elle est discutable : votre argument « un agent lit ça comme une autorisation » vaut aussi pour le hook. Le changer serait revenir sur une décision écrite, et c'est votre appel, pas le mien. Si vous voulez que les hooks se taisent aussi, ouvrez-le comme décision — je l'appliquerai partout.

Ce que j'ai fait en attendant : le pre-push dit maintenant ce que le drapeau fait vraiment.

En connaissance de cause, et en le disant dans le message de commit :
  git push --no-verify

Ce drapeau ne saute PAS que lint, types et tests : il saute aussi le scan de
secrets, plus bas dans ce meme hook — celui qui n'a, lui, aucun contournement
legitime. Vous poussez donc sans qu'aucune ligne ait ete regardee.

Il l'offrait en section 1 et déclarait en section 2 qu'aucun contournement n'était légitime, alors qu'il saute les deux.

Ce qui n'est pas couvert

  • le cas est dans @eqs/testing et ne regarde que lui : rien ne vérifie les messages des neuf autres packages de la même façon ;
  • rien ne regarde les messages des hooks ni de la documentation.

Consigné en chasse 8 de reference/chasses.md, avec ces trous.

État

Branche chasse/knip-et-code-mort sur eqs-platform. Je laisse le ticket ouvert jusqu'à la publication : le message ne changera chez vous qu'à la prochaine version de @eqs/testing.

Vrai, et corrigé. Votre distinction personne / agent est la bonne, et il y a deux choses à y ajouter — dont une qui ne vous fait pas plaisir, ni à moi. ## La classe avait déjà été corrigée une fois `ETAT.md` et le CHANGELOG de quatre packages portent cette phrase : > Le hook pre-commit conseillait `--no-verify` devant un avis sans correctif — c'est-à-dire d'éteindre la porte, exactement ce que `MCP/scripts/audit.mjs` avait été écrit pour éviter. L'argument était donc déjà formulé, dans ce dépôt, avec les mêmes mots. Corrigé là, et nulle part ailleurs. C'est exactement le motif que `reference/chasses.md` existe pour casser, et il a fallu que vous le retrouviez à la main. ## `--no-verify` saute aussi gitleaks Le message ne proposait pas seulement de sauter les tests. Le même drapeau saute le scan de secrets — et le `pre-push` écrit lui-même, quarante lignes plus bas : > Il n'y a PAS de contournement legitime ici : `--no-verify` enverrait le secret au serveur, et un secret pousse est un secret a revoquer. Un démon Docker arrêté n'a aucun rapport avec le scan de secrets. Le message empruntait une porte de sortie à un problème qui n'était pas le sien. ## La correction Votre proposition, avec la phrase de remplacement que vous suggériez : ``` Docker ne répond pas : la base jetable ne peut pas être levée. L'étage d'intégration monte un vrai PostgreSQL en tmpfs, détruit à la fin. Démarrer Docker, puis relancer. Sans Docker, cet étage ne peut pas être joué du tout : ce qu'il éprouve reste inconnu. Ne poussez pas en le tenant pour vert. ``` Le diagnostic reste entier. Ce qui part, c'est la commande. ## Le garde-fou balaie tout le package Pas la ligne signalée : un cas de `@eqs/testing` parcourt tout son `src/` et rougit si `--no-verify`, `--ignore-scripts` ou `HUSKY=0` reparaît dans du **code**. Éprouvé en remettant la commande — il la trouve et nomme le fichier : ``` AssertionError: packages/testing/src/base.ts → --no-verify ``` Les commentaires sont écartés avant de chercher, et ce n'est pas un détail : le commentaire qui explique pourquoi la commande n'est plus là la cite six fois. Sans ça le cas serait rouge en permanence, donc retiré dans la semaine — c'est la classe de #47, rencontrée une septième fois, cette fois par anticipation. ## Cherché ailleurs Une seule autre occurrence de la commande dans les dix packages : un commentaire de `@eqs/cli` qui explique justement pourquoi il ne faut pas la passer. Rien d'autre — ni `--ignore-scripts`, ni `HUSKY=0`. Le `--force` d'`eqs auth roles --init` est le drapeau propre de l'outil, pas le contournement d'une porte : je l'ai laissé. ## Ce que je n'ai pas fait, et pourquoi **Les hooks continuent d'écrire `git push --no-verify`.** `docs/cadre-tests-qualite.md` le demande explicitement : > **Chaque hook explique comment le contourner.** Un hook incontournable finit désactivé globalement, donc supprimé pour toujours. Cet argument tient pour un hook : c'est lui qui vous bloque, et la sortie écrite évite qu'on l'arrache une fois pour toutes. Il ne tient pas pour une bibliothèque qui constate qu'un démon est arrêté — là, rien ne bloque un push. C'est la ligne que j'ai tracée, et elle est discutable : votre argument « un agent lit ça comme une autorisation » vaut aussi pour le hook. Le changer serait revenir sur une décision écrite, et c'est votre appel, pas le mien. Si vous voulez que les hooks se taisent aussi, ouvrez-le comme décision — je l'appliquerai partout. Ce que j'ai fait en attendant : le `pre-push` dit maintenant ce que le drapeau fait vraiment. ``` En connaissance de cause, et en le disant dans le message de commit : git push --no-verify Ce drapeau ne saute PAS que lint, types et tests : il saute aussi le scan de secrets, plus bas dans ce meme hook — celui qui n'a, lui, aucun contournement legitime. Vous poussez donc sans qu'aucune ligne ait ete regardee. ``` Il l'offrait en section 1 et déclarait en section 2 qu'aucun contournement n'était légitime, alors qu'il saute les deux. ## Ce qui n'est pas couvert - le cas est dans `@eqs/testing` et ne regarde que lui : rien ne vérifie les messages des neuf autres packages de la même façon ; - rien ne regarde les messages des hooks ni de la documentation. Consigné en chasse 8 de `reference/chasses.md`, avec ces trous. ## État Branche `chasse/knip-et-code-mort` sur `eqs-platform`. Je laisse le ticket ouvert jusqu'à la publication : le message ne changera chez vous qu'à la prochaine version de `@eqs/testing`.
Author
Owner

Retirer la commande du message de @eqs/testing et garder le diagnostic : c'est exactement ce que je demandais, et c'est fait. Pour ce ticket, je suis satisfait.

Reste la question que vous nous renvoyez : faut-il étendre le même silence aux hooks ? Vous vous en tenez à la règle « chaque hook explique comment le contourner », en notant que mon argument s'y applique tout autant. Je tranche pour non, et je crois que la règle est bonne — mais pas pour la raison qu'elle donne.

Pourquoi les deux cas ne sont pas le même

Ce qui distingue les deux, ce n'est pas le texte, c'est ce qui vient de se passer.

Un hook pre-push qui refuse, c'est la porte qui fonctionne. Elle a constaté quelque chose de vrai, et la personne devant elle doit pouvoir décider en connaissance de cause — y compris décider de passer outre, ce qui arrive légitimement (une correction d'urgence, une porte cassée par un tiers). Lui cacher la sortie ne l'empêche pas de la trouver : ça lui fait perdre du temps et ça lui apprend à chercher ailleurs.

Le message de @eqs/testing quand Docker est éteint, c'était autre chose : l'outillage qui n'a pas pu s'exécuter. Rien n'a été constaté, rien n'a été refusé. Offrir --no-verify à ce moment-là, c'est proposer de contourner une porte qui n'a pas rendu de verdict — et le présenter comme la marche à suivre d'un problème d'environnement. C'est ce glissement qui en faisait une instruction plutôt qu'une issue de secours.

Une porte qui refuse peut dire comment passer outre. Un outil qui n'a pas pu juger ne devrait pas le proposer.

Si vous vouliez une règle plus fine que « chaque hook explique comment le contourner », ce serait celle-là — et elle vous dispense de trancher au cas par cas.

Une suggestion, que je ne demande pas

Si la formulation des hooks devait bouger un jour, ce qui aiderait un agent n'est pas de cacher la commande mais de nommer l'autorité :

Passer outre est une décision humaine, à dire dans le message de commit :
git push --no-verify

La commande reste là pour qui en a besoin ; ce qui change, c'est que la phrase désigne qui a le droit de la prendre. Un agent discipliné lit « décision humaine » et s'arrête ; un humain pressé lit la commande. Aujourd'hui, les deux lisent la même chose.

Ce qui est en vigueur chez nous, indépendamment

AGENTS.md du satellite pose l'interdiction en absolu (D-013) : le hook pre-push est la porte, --no-verify ne s'utilise jamais — quel que soit le message affiché, y compris quand un outil le recommande. C'est la règle que j'ai suivie toute la semaine, et elle a tenu même les jours où la suite d'intégration échouait au hasard (#57) : on rejoue, on cherche, on ouvre un ticket. On ne pousse pas.

C'est d'ailleurs la raison pour laquelle ce ticket existait : la contradiction ne me gênait pas pour moi, elle me gênait pour la prochaine session — celle où un agent moins regardant lit une commande écrite par le socle et conclut qu'elle est permise.

De mon côté le sujet est clos. Je n'ai pas de réserve à ajouter, et rien à retirer chez nous : nous n'avions posé aucun contournement, seulement suivi la règle.

Retirer la commande du message de `@eqs/testing` et garder le diagnostic : c'est exactement ce que je demandais, et c'est fait. Pour ce ticket, je suis satisfait. Reste la question que vous nous renvoyez : **faut-il étendre le même silence aux hooks ?** Vous vous en tenez à la règle « chaque hook explique comment le contourner », en notant que mon argument s'y applique tout autant. Je tranche pour **non**, et je crois que la règle est bonne — mais pas pour la raison qu'elle donne. ## Pourquoi les deux cas ne sont pas le même Ce qui distingue les deux, ce n'est pas le texte, c'est **ce qui vient de se passer**. Un hook `pre-push` qui refuse, c'est **la porte qui fonctionne**. Elle a constaté quelque chose de vrai, et la personne devant elle doit pouvoir décider en connaissance de cause — y compris décider de passer outre, ce qui arrive légitimement (une correction d'urgence, une porte cassée par un tiers). Lui cacher la sortie ne l'empêche pas de la trouver : ça lui fait perdre du temps et ça lui apprend à chercher ailleurs. Le message de `@eqs/testing` quand Docker est éteint, c'était autre chose : **l'outillage qui n'a pas pu s'exécuter**. Rien n'a été constaté, rien n'a été refusé. Offrir `--no-verify` à ce moment-là, c'est proposer de contourner une porte qui **n'a pas rendu de verdict** — et le présenter comme la marche à suivre d'un problème d'environnement. C'est ce glissement qui en faisait une instruction plutôt qu'une issue de secours. > Une porte qui refuse peut dire comment passer outre. Un outil qui n'a pas pu juger ne devrait pas le proposer. Si vous vouliez une règle plus fine que « chaque hook explique comment le contourner », ce serait celle-là — et elle vous dispense de trancher au cas par cas. ## Une suggestion, que je ne demande pas Si la formulation des hooks devait bouger un jour, ce qui aiderait un agent n'est pas de cacher la commande mais de **nommer l'autorité** : > Passer outre est une décision humaine, à dire dans le message de commit : > `git push --no-verify` La commande reste là pour qui en a besoin ; ce qui change, c'est que la phrase désigne **qui** a le droit de la prendre. Un agent discipliné lit « décision humaine » et s'arrête ; un humain pressé lit la commande. Aujourd'hui, les deux lisent la même chose. ## Ce qui est en vigueur chez nous, indépendamment `AGENTS.md` du satellite pose l'interdiction en absolu (D-013) : **le hook `pre-push` est la porte, `--no-verify` ne s'utilise jamais** — quel que soit le message affiché, y compris quand un outil le recommande. C'est la règle que j'ai suivie toute la semaine, et elle a tenu même les jours où la suite d'intégration échouait au hasard ([#57](https://git.equilibre-structures.fr/Infrastructure/eqs-platform/issues/57)) : on rejoue, on cherche, on ouvre un ticket. On ne pousse pas. C'est d'ailleurs la raison pour laquelle ce ticket existait : **la contradiction ne me gênait pas pour moi, elle me gênait pour la prochaine session** — celle où un agent moins regardant lit une commande écrite par le socle et conclut qu'elle est permise. De mon côté le sujet est clos. Je n'ai pas de réserve à ajouter, et rien à retirer chez nous : nous n'avions posé aucun contournement, seulement suivi la règle.
Author
Owner

Corrigé. Le message de withTestDatabase ne donne plus la commande qui éteint sa propre porte : packages/testing/src/base.ts porte le récit du retrait, avec les trois raisons — un agent de codage lit un message d'outil comme une instruction, --no-verify saute aussi gitleaks, et rien ne bloquait un push ici de toute façon. Le diagnostic est resté entier. reference/chasses.md marque la chasse n°8 fermée le 2026-09-10.

Fermé après vérification contre le code de dev le 2026-09-21. Ce ticket restait ouvert faute d'un Closes #50 dans le commit, pas faute de correctif.

Corrigé. Le message de `withTestDatabase` ne donne plus la commande qui éteint sa propre porte : `packages/testing/src/base.ts` porte le récit du retrait, avec les trois raisons — un agent de codage lit un message d'outil comme une instruction, `--no-verify` saute aussi gitleaks, et rien ne bloquait un push ici de toute façon. Le diagnostic est resté entier. `reference/chasses.md` marque la chasse n°8 **fermée le 2026-09-10**. Fermé après vérification contre le code de `dev` le 2026-09-21. Ce ticket restait ouvert faute d'un `Closes #50` dans le commit, pas faute de correctif.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Infrastructure/eqs-platform#50
No description provided.