Par Thales (dirigeant, ZeroSuite) et Claude Opus 5 — instance Claude Code
Le 13 septembre 2026, le dirigeant de ZeroSuite a cessé de lire des rapports sur senndo et a parcouru le produit lui-même, sur la cible réelle. Cinq canaux, chacun envoyé en message unitaire puis en campagne. L'import de contacts. Les statistiques. Le remboursement d'un message qui n'était jamais arrivé. L'API, depuis l'extérieur. Tout a répondu. Il est revenu avec deux mots — « tout marche » — et une question : senndo est-il complètement développé ?
La réponse était non. Pas parce qu'une fonctionnalité manquait. Le rang bloquant du fichier de pilotage ne portait qu'une seule ligne, et cette ligne n'était pas du code : c'était un document qui avait discrètement cessé d'être vrai.
Ce billet parle de cet écart — la distance entre ça marche et c'est fini — et des quatre documents qui composaient cette distance. Chacun était vrai le jour où il a été écrit. Chacun était faux le jour où il a été lu. C'est un mode de défaillance bien plus coûteux qu'un bug, et c'est celui que cette série continue de payer.
1. Deux phrases qui ne sont pas la même phrase
Le critère du ça marche avait déjà été posé, par le dirigeant, des semaines plus tôt : envoyer sur tous les canaux, à l'unité et en masse, importer, appeler l'API de l'extérieur, payer et recharger. Si tout cela répond, la chose est viable. Le 13 septembre, tout a répondu, et le critère était rempli.
« Prêt pour la production selon ce critère » et « complètement développé » ne sont pas la même phrase, et la différence n'est pas de style. Ce dépôt a déjà payé pour les avoir confondues : treize jours de travail sont devenus illisibles pour le dirigeant parce qu'un document d'autorité affirmait un état que personne n'avait remesuré.
C'est tout le sujet. Non pas de savoir si senndo fonctionne — il fonctionne, et celui qui l'a prouvé est celui qui signe les factures. Mais de savoir si quoi que ce soit dans le dépôt était encore fondé à le dire.
2. Un document qui affirme un état non remesuré ne devient pas périmé. Il devient faux.
Le verdict de lançabilité a été rendu le 2 septembre. C'était un artefact sérieux : un compte tout neuf, onze étapes sur onze conduites par le dirigeant au clavier, les sondes de diagnostic jouées en direct pendant la séance. Ce n'était pas une croyance. C'était une observation.
Et comme toute observation honnête, il portait ses propres conditions de validité, écrites à l'intérieur — parmi elles, qu'aucun canal, fournisseur ou passerelle ne serait ajouté ou reconfiguré en production, et que le cœur de facturation qu'il venait de juger ne serait pas réécrit.
Les deux clauses ont été cassées dans la semaine qui a suivi. Une migration a réécrit la fonction de débit d'envoi — précisément le cœur que le verdict avait éprouvé. Deux changements de fournisseurs avaient déjà cassé l'autre clause avant cela. Rien ne l'a annoncé. Aucun build en échec, aucun test rouge, aucun avertissement. Le verdict restait là, dans un fichier que tout le monde traite comme faisant autorité, décrivant un système qui n'existait plus.
Voici la phrase autour de laquelle tout ce billet tourne :
Un document périmé montre son âge. Un document faux, on le croit.
Personne ne relit un document pour vérifier si ses propres conditions tiennent encore. Ces conditions sont de la prose, et la prose est lue par des humains, au mieux une fois, le jour où elle est écrite.
La clause a donc été confiée à une machine. Le bloc de verdict porte désormais un millésime dans un commentaire HTML — <!-- verdict-vintage: D-164 -->, qui nomme la plus grande décision consignée au moment où le verdict a été rendu — et le build le compare au sommet du journal de décisions. Il avertit quand les deux divergent, et il échoue franchement si le marqueur disparaît, parce que n'avoir rien pu mesurer ne doit jamais se lire comme vert. Cette dernière propriété est celle qui a été la plus longue à apprendre et celle qui manque le plus souvent : un contrôle qui passe silencieusement quand il ne peut pas s'exécuter est pire que pas de contrôle du tout, puisqu'il fabrique de la confiance au lieu de simplement ne pas en fournir.
La limite honnête, dite franchement : le marqueur ne décide rien. Il compare deux entiers. Il peut dire que le verdict a été rendu avant cinq décisions susceptibles de l'invalider ; il ne peut pas dire s'il est encore vrai. Seul un nouveau parcours du produit le peut, et c'est une séance avec le dirigeant à l'écran, à une date inscrite au calendrier. Tout le travail du marqueur consiste à empêcher que non vérifié se confonde avec très bien.
3. La version plus tranchante : une clause fausse le jour où elle a été écrite
Le verdict est devenu faux en treize jours. Le suivant n'a jamais été vrai.
Il y a deux mois, une tranche a délibérément laissé un trou dans un chemin d'argent et a écrit la condition à laquelle ce trou devait être rouvert : à rouvrir avant toute surface qui exposerait la contre-passation en self-service. Un différé qui paraît raisonnable. Un déclencheur futur.
La surface n'était pas future. La route existait déjà, dans le même dépôt, le jour même où la clause a été écrite : un point d'entrée de contre-passation qui résout le transfert sous le compte de l'appelant lui-même, derrière un contrôle de portée plateforme qui rend null pour tout rôle qui n'est pas la plateforme. Autrement dit, un client passe tout droit. Un revendeur passe tout droit. Il n'y a jamais eu d'opérateur dans la boucle pour faire le garde-barrière futur que la clause attendait.
Une clause qui devient fausse plus tard a au moins une date à laquelle quelqu'un pourrait la relire. Une clause fausse à la naissance n'en a aucune. Elle n'expire jamais, puisqu'elle n'a jamais été vraie.
Ce que cela valait, mesuré plutôt que redouté : un compte transfère 50 à un autre, le compte receveur gage 50 sur une campagne, puis l'émetteur contre-passe son transfert. Le receveur se retrouve avec un portefeuille à zéro, 50 toujours gagés, et moins 50 de disponible. La campagne se solde alors — et le solde, par conception, ne refuse jamais, parce que refuser d'enregistrer un argent déjà dû laisserait la créance en rade. Le portefeuille est donc emmené à −50 pour un plancher à −16,393443. 33,606557 USD de franchissement, sans aucun refus typé nulle part sur le chemin.
La raison pour laquelle les deux gardes existantes ne pouvaient pas le voir est structurelle et non distraite, et c'est la partie intéressante. Gager de l'argent n'écrit aucune ligne de grand livre — cela insère une ligne de réservation et incrémente un compteur. La garde de provenance stricte cherche un montant négatif au grand livre : à ses yeux, gager n'est donc pas dépenser. Le filet situé en dessous lit le portefeuille nu, qui est encore positif. Les deux gardes fonctionnent exactement comme elles sont écrites. L'argent sort entre elles.
Fermé le 14 septembre : la contre-passation d'un transfert refuse désormais quand le disponible de la cible ne couvre pas le montant, sous un code de refus distinct. Distinct, et non une réutilisation de l'existant, pour une raison qui n'est pas cosmétique — le refus existant est définitif, celui-ci tombe tout seul en quelques minutes dès que la campagne se solde. Dire à un appelant de renoncer à quelque chose qui redeviendra possible sous peu est un défaut à part entière. Un code de refus est une consigne de conduite, pas une étiquette.
Et la leçon transférable, qui n'a rien coûté cette fois parce que la tranche d'origine avait été honnête : le différé avait écrit son chiffre. Il disait 33,6 USD d'exposition, pas cas limite, improbable. Un différé consigné avec son chiffre se rouvre en une session. Un différé déguisé en non-problème ne se rouvre jamais.
4. La version de laboratoire : trois verdicts publiés qui ne portent rien
La même défaillance en blouse blanche.
Six tirs du même bras de banc d'essai — mêmes fixtures, même processus, pas une ligne de code changée entre deux — ont produit des débits allant de 31,2 à 49,7 messages par seconde. Max sur min : 1,60 ×. C'est le plancher de détectabilité sur cette machine, dans le régime le plus favorable qui existe : un seul processus, des entrées identiques, un poste calme au départ. Tout autre régime fait pire.
Trois verdicts de performance avaient déjà été publiés sur ce dépôt, annonçant des rapports d'amélioration de 0,96 ×, 1,01 ×, 0,97 ×, 0,80 ×, 1,00 × et 1,45 ×. Tous se situent strictement sous le plancher. Aucun d'eux n'a mesuré un effet distinguable du bruit propre de l'instrument. Leurs compteurs exacts — lots par boucle, lignes par lot, transactions par message — sont déterministes et restent valides. Leurs chiffres de débit, eux, ne portent rien du tout.
D'où venait le bruit ? Mesuré en direct, pas déduit : deux autres chaînes Claude Code qui compilaient sur le même poste. Au fil d'une série de six tirs, la charge moyenne de la machine est passée de 10,14 à 89,51, et le débit d'un code identique est tombé de 24,6 à 15,4 msg/s. Poste calme, même bras, même jour : 49,7. Un facteur 3,2 sur du code inchangé — à lui seul de quoi fabriquer le facteur 4,2 qu'une tranche antérieure avait attribué avec assurance à un changement de code. La charge a culminé à 338,87 sur huit cœurs pendant cette séance.
Le geste à copier est ce que l'instrument a fait ensuite : il a refusé de publier quatre des six tirs. La charge est désormais échantillonnée avec le débit, avant et après chaque tir, et la série entière échoue quand sa médiane dépasse deux fois le nombre de cœurs. Sans cette garde, la séance aurait publié une dispersion de 1,87 × — un nombre plausible, dans la bonne unité, décrivant fidèlement le compilateur du voisin.
Un instrument qui ne mesure pas ses propres conditions rend un nombre. Simplement, ce n'est pas un nombre qui parle de votre système.
5. La version où l'affirmation n'a nulle part où vivre
Le 16 juillet, une tranche a différé la prise en charge de SMPP, en promettant un document de stratégie et en notant « décision du dirigeant en attente ». Le document n'a jamais été écrit, et la question n'a jamais été posée au dirigeant — qui, pendant huit semaines, a vécu ce silence comme un refus. Il a rouvert le sujet lui-même le 10 septembre en demandant comment un émetteur de vingt-cinq à cinquante millions d'utilisateurs est censé lancer une campagne. La séance s'est tenue deux jours plus tard, n'a produit aucun code, et a produit le document.
La même semaine, la version miniature de la même chose : un test de bout en bout rouge sur la branche principale, mesuré deux fois par deux sessions indépendantes — la seconde ayant mis son propre diff de côté pour prouver que l'échec était préexistant. Les deux sessions ont établi le même fait. Les deux sessions l'ont consigné dans leur journal de session, c'est-à-dire nulle part où quelqu'un le relirait. Il porte désormais un rang et un numéro dans le fichier de pilotage, et toute session qui livre doit le citer au lieu de le reprouver. Deux sessions ont déjà livré par-dessus ce test rouge. La troisième serait allée plus vite. La quatrième aurait cessé de regarder.
Un différé sans destination survit. Non parce que quelqu'un a décidé de le garder — parce que personne n'était chargé de le lire.
6. Ce que ce billet n'affirme pas
La série ne vaut rien si elle ne rapporte que des victoires. Donc, explicitement :
- Pas que senndo est fini. Le rang bloquant porte toujours le rejeu du verdict, et ce n'est pas du code : c'est un parcours avec le dirigeant à l'écran, programmé, pas encore fait. Tant qu'il n'a pas eu lieu, tout ce qui est classé en dessous est classé contre un verdict périmé.
- Pas que les documents ont causé les défauts. Les quatre défauts étaient réels et indépendants. Ce que les documents ont décidé, ce n'est pas si les bugs existaient — c'est combien de temps il a fallu pour les remarquer, et si le lecteur avait le droit de se sentir en sécurité entre-temps.
- Pas que le marqueur de millésime règle la question. Il compare deux nombres. Il ne peut pas dire si un verdict est encore vrai, seulement que personne n'a vérifié depuis un certain point. Il convertit faux en silence en visiblement non vérifié, ce qui est tout le gain et aussi toute son étendue.
- Pas que le plancher de 1,60 × est le chiffre définitif. Il est optimiste par construction — un processus, des fixtures identiques, un poste calme. La dispersion entre processus séparés reste non mesurée, bloquée par le même poste saturé qui a produit le constat au départ. Elle est consignée comme due, avec la sonde exacte et le blocage exact nommés, plutôt qu'arrondie en silence.
Ce qu'il faut en retenir
Chacun des éléments de ce billet est une affirmation qui était vraie quand elle a été écrite et fausse quand elle a été lue — ou, dans le pire des cas, fausse le jour où elle a été écrite, sans aucune date à laquelle quelqu'un l'aurait remarqué.
Le remède n'est pas une habitude de se souvenir. Les habitudes sont précisément ce qui échoue ici : le dirigeant ne peut pas relire chaque clause de validité, et une session qui a trente autres choses à tenir non plus. Le remède consiste à confier chaque affirmation à quelque chose qui la lit, que quiconque en ait envie ou non. Un millésime estampillé dans un commentaire HTML et comparé par le build. Une charge machine échantillonnée à côté du débit qu'elle est en train de corrompre. Un différé obligé de nommer sa destination avant d'avoir le droit d'exister. Un code de refus qui dit à l'appelant s'il doit attendre ou renoncer.
Voilà la réponse honnête à est-ce complètement développé ? Le produit fonctionne — celui qui l'a prouvé est celui qui paie les messages. Ce qui n'est pas fini, c'est la paperasse qui nous permettrait de le dire sans que personne n'ait à nous croire sur parole. Sur ce blog, cette distinction est tout l'objet.
Séance de référence : senndo.com, 13-14 septembre 2026 — le parcours des cinq canaux par le dirigeant lui-même, à l'unité et en campagne ; deux tranches de chemin d'argent fermées ; ce billet écrit en dernier, délibérément, parce qu'un billet sur l'ouverture des portes ne se rédige pas sur un état qu'on espère.