Constat mesure
Le cron coordinateur etait arme pendant toute une fenetre de 6h16 sans aucun merge.
| Mesure |
Valeur |
| Cron ai-01 |
0229aeb9 — 13 0-23/4 * * * — verifie arme a 10:04Z |
| Dernier merge |
#14702 a 03:46:57Z |
| Merges par heure (2026-09-05 UTC) |
00h=13, 01h=9, 02h=16, 03h=4, puis 04h-10h = 0 |
| PRs ouvertes a 10:03Z |
36, dont 17 nees dans la fenetre |
| Declenchements attendus non survenus |
04:13, 08:13 |
Les workers, eux, ont produit normalement pendant toute la fenetre (posts po-2024 a 09:47Z et 09:54Z, po-2025 a 09:51Z). Ce ne sont pas les lanes qui ralentissent : c'est la passe de merge du coordinateur.
Cause
CronCreate ne declenche que lorsque le REPL est idle, jamais mid-query. La session ai-01 tenait un seul tour continu depuis ~03:26Z. Les declenchements de 04:13 et 08:13 n'ont donc pas pu avoir lieu.
« Cron arme » et « merges geles » ne sont pas contradictoires — c'est la meme cause. C'est ce qui rend le defaut difficile a lire : CronList montre le job, le job est reellement vivant, et il ne tirera pourtant jamais tant que le tour ne se termine pas.
Pourquoi c'est structurel et pas un accident
La boucle est auto-renforcante : plus le backlog est gros, plus le cycle est long ; plus le cycle est long, plus de declenchements sautent ; plus de declenchements sautent, plus le backlog grossit. C'est exactement la trajectoire vers la crise que le mandat user sur l'equilibrage de charge cherche a eviter.
Le diagnostic naturel — « le cron est mort, j'en arme un second » — aggrave la situation : il cree le double-firing silencieux, et si le second cron vit dans une autre session partageant le tag de lane myia-ai-01:CoursIA, il viole la premisse d'identite de #14323 (check_lane_claim.py CLEAR ne dit que « aucune AUTRE lane », jamais « aucun autre processus de la mienne »).
Correction proposee — borner le cycle, pas ajouter un cron
Le coût du cycle n'est pas dans le merge, il est dans la mesure. Gater 21 PRs (lire corps + commentaires + reviews + diff, faire tourner check_unaddressed_nits, verifier les check-runs) prend des heures ; les gh pr merge qui en decoulent prennent des secondes. Aujourd'hui les deux vivent dans le meme tour, donc la partie rapide est otage de la partie lente.
Proposition : scinder la Phase 3 de .claude/skills/coordinate en deux passes qui rendent la main entre elles.
- Passe courte (bornee) — merger ce qui est deja mesure et vert depuis le cycle precedent, puis rendre la main. Objectif : quelques minutes, pour que le REPL redevienne idle avant le declenchement suivant.
- Passe longue — mesurer/gater les PRs restantes, dispatcher, provisionner. Son debordement ne coute alors plus les merges du cycle suivant.
Cela demande de persister les verdicts de gate entre cycles (une PR mesuree verte au cycle N doit etre mergeable au cycle N+1 sans re-mesure complete, sous reserve que sa tete n'ait pas bouge — le SHA est le discriminant, cf [[pr-checkruns-belong-to-the-commit]]).
Alternative ecartee
Deporter la cadence hors du REPL (tache planifiee / conteneur en polling, dans l'esprit de #14329) rendrait le declenchement immunise au tour en cours. Ecartee ici parce qu'elle ne resout pas le fond : un cycle de 6 h reste un cycle de 6 h, et un declencheur externe qui reveille une session deja occupee ne merge pas davantage. La borne du cycle est le vrai levier ; le declencheur externe est un complement, pas un substitut.
Lien avec la consigne user du jour
La consigne relayee a 09:59Z (« ajouter une heure explicite dans les derniers messages / bilans de chaque cycle pour rendre visible que les crons tournent ») traite le symptome de visibilite de ce meme defaut : rien dans les rapports actuels ne permet de distinguer « le cron a tire et n'a rien trouve a merger » de « le cron n'a pas tire ». Adopter le format [YYYY-MM-DD HH:mm TZ / HH:mm UTC] est utile et sera fait ; il rend le defaut lisible, il ne le supprime pas.
Acceptance
Constat mesure
Le cron coordinateur etait arme pendant toute une fenetre de 6h16 sans aucun merge.
0229aeb9 — 13 0-23/4 * * *— verifie arme a 10:04Z00h=13,01h=9,02h=16,03h=4, puis04h-10h= 0Les workers, eux, ont produit normalement pendant toute la fenetre (posts po-2024 a 09:47Z et 09:54Z, po-2025 a 09:51Z). Ce ne sont pas les lanes qui ralentissent : c'est la passe de merge du coordinateur.
Cause
CronCreatene declenche que lorsque le REPL est idle, jamais mid-query. La session ai-01 tenait un seul tour continu depuis ~03:26Z. Les declenchements de 04:13 et 08:13 n'ont donc pas pu avoir lieu.« Cron arme » et « merges geles » ne sont pas contradictoires — c'est la meme cause. C'est ce qui rend le defaut difficile a lire :
CronListmontre le job, le job est reellement vivant, et il ne tirera pourtant jamais tant que le tour ne se termine pas.Pourquoi c'est structurel et pas un accident
La boucle est auto-renforcante : plus le backlog est gros, plus le cycle est long ; plus le cycle est long, plus de declenchements sautent ; plus de declenchements sautent, plus le backlog grossit. C'est exactement la trajectoire vers la crise que le mandat user sur l'equilibrage de charge cherche a eviter.
Le diagnostic naturel — « le cron est mort, j'en arme un second » — aggrave la situation : il cree le double-firing silencieux, et si le second cron vit dans une autre session partageant le tag de lane
myia-ai-01:CoursIA, il viole la premisse d'identite de #14323 (check_lane_claim.py CLEARne dit que « aucune AUTRE lane », jamais « aucun autre processus de la mienne »).Correction proposee — borner le cycle, pas ajouter un cron
Le coût du cycle n'est pas dans le merge, il est dans la mesure. Gater 21 PRs (lire corps + commentaires + reviews + diff, faire tourner
check_unaddressed_nits, verifier les check-runs) prend des heures ; lesgh pr mergequi en decoulent prennent des secondes. Aujourd'hui les deux vivent dans le meme tour, donc la partie rapide est otage de la partie lente.Proposition : scinder la Phase 3 de
.claude/skills/coordinateen deux passes qui rendent la main entre elles.Cela demande de persister les verdicts de gate entre cycles (une PR mesuree verte au cycle N doit etre mergeable au cycle N+1 sans re-mesure complete, sous reserve que sa tete n'ait pas bouge — le SHA est le discriminant, cf
[[pr-checkruns-belong-to-the-commit]]).Alternative ecartee
Deporter la cadence hors du REPL (tache planifiee / conteneur en polling, dans l'esprit de #14329) rendrait le declenchement immunise au tour en cours. Ecartee ici parce qu'elle ne resout pas le fond : un cycle de 6 h reste un cycle de 6 h, et un declencheur externe qui reveille une session deja occupee ne merge pas davantage. La borne du cycle est le vrai levier ; le declencheur externe est un complement, pas un substitut.
Lien avec la consigne user du jour
La consigne relayee a 09:59Z (« ajouter une heure explicite dans les derniers messages / bilans de chaque cycle pour rendre visible que les crons tournent ») traite le symptome de visibilite de ce meme defaut : rien dans les rapports actuels ne permet de distinguer « le cron a tire et n'a rien trouve a merger » de « le cron n'a pas tire ». Adopter le format
[YYYY-MM-DD HH:mm TZ / HH:mm UTC]est utile et sera fait ; il rend le defaut lisible, il ne le supprime pas.Acceptance
coordinatedistingue une passe de merge bornee et une passe de mesure longue