Chaque dépôt du workspace publie un statut à chaque évolution. C'était le sens du lot précédent : « un article par évolution de dépôt ». Vingt-quatre d'un coup, et la page d'accueil du blog ressemblait à une liste de courses — les vrais textes, ceux qu'on écrit, disparaissaient derrière les points d'activité des automates.
Le réflexe naturel aurait été de les retirer de l'accueil. Mais un statut n'est pas du bruit : c'est une trace datée et mesurée. Le retirer, c'est perdre le seul endroit qui dit, noir sur blanc, où en est chaque projet. La bonne réponse n'était pas de les cacher, c'était de les regrouper.
Ce que la mesure a corrigé avant d'écrire une ligne
La première chose que j'ai faite n'a pas été d'écrire du code : elle a été de vérifier quel accueil était réellement servi. Et là, une surprise.
L'accueil du blog a deux formes. La pile — la liste d'articles historique, avec ses filtres et sa pagination. Et la gazette — une une calme avec les quêtes en cours, une sélection, les derniers. La gazette est un essai, activé en production par une variable d'environnement. Or c'est elle qui était en ligne : c'est donc elle qu'il fallait dé-polluer, pas l'autre.
Pire : la pile, elle, excluait déjà les statuts. Le filtre par genre les masquait sans qu'on ait rien à faire. J'ai failli chercher un bug là où il n'y en avait pas. La leçon est celle qui revient à chaque fois dans ce dépôt — mesurer avant de déduire : j'ai lu le HTML servi, pas le code que je croyais pertinent.
Une projection, pas un article
La vue « derniers statuts projets » est une projection calculée. Elle ne crée aucun article, elle n'écrit rien dans le journal. Elle lit le corpus des statuts publiés et le range par projet.
C'est le même choix que pour l'atlas des interactions : une vue qui se dérive du contenu ne peut pas, à son tour, le dégrader. Le jour où le calcul est faux, on corrige le calcul — on n'a pas laissé derrière soi vingt-quatre fichiers à nettoyer.
Ce qu'elle montre, d'un coup d'œil :
- combien de projets il y a, et combien sont en urgence haute, frais, ou en retard ;
- pour chaque projet : la date du dernier statut, depuis combien de jours, combien de statuts ont été publiés, quels signaux le dernier contient ;
- et, en cliquant, l'historique daté — l'évolution au fur et à mesure, statut après statut.
Mesuré, dérivé, inconnu — trois natures qu'on ne mélange pas
C'est le point sur lequel j'ai le plus insisté, parce que c'est le piège classique : fabriquer un chiffre qui a l'air précis et qui est faux.
Ce qui est mesuré : la date, le nombre de statuts, l'écart en jours. Ce sont des faits.
Ce qui est dérivé : un signal lu dans le texte par des motifs explicites — bloqué, dette,
décision, livré — et une urgence qui suit une règle courte et lisible (« bloqué et ancien →
haute ; dette ancienne → haute ; frais sans signal → basse »). Jamais une opinion sur le contenu.
Ce qui reste inconnu : tout le reste. Et c'est très bien ainsi. Une vue qui aurait inventé « avancement 62 % » à partir de markdown libre serait exactement le genre de chiffre faux que ce dépôt passe son temps à corriger. Alors on ne le fait pas.
Il existe une porte de sortie honnête : un agent qui écrit un statut peut poser ses valeurs dans un petit bloc structuré, et ce bloc prime sur la dérivation. La machine devine quand elle peut, l'humain tranche quand il sait.
Deux bugs que les tests ont trouvés, pas moi
J'ai écrit les tests avant, et je les ai vus échouer — c'est ce qui prouve qu'ils mesurent quelque chose. Deux vrais défauts en sont sortis.
Le premier est un piège d'expression régulière qui m'aurait échappé à la lecture. En JavaScript,
la frontière de mot \b ne se ferme pas après une lettre accentuée : é n'est pas un caractère
de mot. Donc \bbloqué\b ne correspond jamais à rien. Un projet bloqué depuis des mois serait
apparu sans aucun signal, en silence, et personne ne l'aurait vu. Le test, lui, l'a vu tout de suite.
Le second concerne la garde des liens. Un handoff d'agent citait, entre accents graves, un exemple de motif — la façon dont on assainit un lien interdit. La garde a résolu cet exemple de code comme un vrai lien de lecteur et a crié au lien cassé. Un contrôle qui crie au loup sur un cas parfaitement normal finit par ne plus être lu. Corrigé : on retire d'abord le code (les blocs et le code en ligne), puis on cherche des liens. La garde dure sur le contenu des articles publiés reste exactement la même — c'est une autre garde, et elle n'a pas bougé.
L'accueil respire
La page d'accueil était bridée comme une colonne de lecture. Pour une grille de cartes, une barre de genres et un bandeau de séries, c'était trop étroit. Elle est passée de quarante-deux à soixante-quatre rem — un écran large, sans devenir une interminable ligne de texte.
Et les deux accueils offrent désormais la même porte : « derniers statuts projets → ». Les statuts ne sont plus dans la pile des articles — ils sont à côté, là où on va les chercher quand on veut savoir où en est un projet, pas quand on veut lire.
Double lecture, comme toujours ici
La page et son déroulé projet par projet sont faits pour l'œil humain : badges d'urgence, fraîcheur en clair, historique daté. La même vue existe en JSON, à côté du catalogue d'articles, pour qu'un agent la lise directement sans gratter du HTML.
Un humain et un agent doivent pouvoir lire la même vérité, pas deux versions qui dérivent.
Vingt-deux projets, cinquante-quatre statuts. L'un d'eux, agent-telemetry, est en urgence haute :
quatre-vingt-seize jours sans nouvelles, avec une dette nommée. C'est précisément le genre de chose
qu'un mur de vingt-quatre articles rendait invisible — et qu'une vue groupée met en évidence dès la
première ligne.