Repository navigation
ci: pr-path-collision advisory muet depuis #14343 (tranche 4 self-hosted) -- 32/34 writes 404, labels non appliques ~10h #14421
Description
Activity
[REFINEMENT 05:20Z — Hermes, live log evidence] Run 33703849843 (01:29Z, failure) parsed: labels pr-overlap SUCCEED (14 applied 01:35Z: #14073→#14313) while comment WRITES 404 (
WARN: write failed for #13831/#13891/#13913/#13922/#13932 — gh: Not Found (HTTP 404); summary32 write(s) failed -- planned 34, confirmed 2).This narrows the 3 pistes: gh CLI auth works for the label endpoint (PR edit) but the comment REST write path 404s — consistent with piste (3) routing REST #14246 rather than a global token/CLI gap. All 5 visible failing targets are older PRs — worth checking if they're merged/closed (comment-on-closed should still 200; if these PR numbers were deleted/migrated that would explain 404 individually, but 32/34 failing is broader).
Still failing as of 01:29Z (4 consecutive red runs). Next scheduled run imminent (~05:30Z). Issue remains valid; diagnosis refined.
Datapoint run 361 (06:30Z, 03/09) — 5e échec consécutif + discrimination route write vs label
Run 33723501803 (schedule, runner myia-ai-01-wsl-8 = self-hosted tranche 4), échec au même step,
07:17:48Z:21 write(s) failed -- planned 26, confirmed 5(post=5 update=0 retract=0).Nouveau et décisif — le contraste label/write dans le MÊME run :
07:17:15-19Z: WARN write failed ×21 (gh: Not Found (HTTP 404)) sur fix(pt11c,#13871): re-route OUTPUT_DIR under _measurements/ to preserve #13738 relocation #13891, docs(curriculum,#13845): triage embryons parcours - Phase 0 EPIC #13844 #13913, fix(guard,#13475): prev: reference invariants PREV-SELF/NOT-MERGED/NOT-PR #13922, feat(sc04,#13929): extend z3 bench to 4 alternatives x 2 voters (UNSAT 17s) #13932, feat(adk): valider Google ADK réel avec Qwen Cloud #13964, feat(search): distill M2 sparse index tracking walk-forward #14046, fix(gate): la forme etiquetee 'Concern:' devient une reserve, casse et nombre relaches #14060, refactor(qc-py-cloud): resolve Cloud-05 collision (MLP-Forecasting vs RegimeSwitching) #14083, refactor(qc-py-cloud): resolve Cloud-02 collision (ML-Classification vs SectorRotation-Momentum) #14084, Enrich CSP-8-Temporal-Csharp.ipynb: density 561 -> 2288 c/code-cell #14125, ...07:17:32-48Z: labels pr-overlap appliqués avec SUCCÈS sur feat(sc04,#13929): extend z3 bench to 4 alternatives x 2 voters (UNSAT 17s) #13932, refactor(qc-py-cloud): resolve Cloud-05 collision (MLP-Forecasting vs RegimeSwitching) #14083, refactor(qc-py-cloud): resolve Cloud-02 collision (ML-Classification vs SectorRotation-Momentum) #14084, fix(notebook,#14211): Tweety-7a Python jumeau Note-de-parite perimee -- 23->34 cells, 8->17 code, ajout tranche 2 IKVM #14220, fix(search,#14061): Search-15/16 stale refs in code comments -> 02b/02c #14225, fix(tweety-7a,#14211): actualiser la Note-de-parite cross-langage (tranche 2 IKVM) #14244, fix(search,#14061): renommer Search-15/16 -> Search-02b/02c (residu rename #13797) #14313, feat(socialchoice,#13929): SC-04 benchmarks 4 alternatives mesurés (SAT ~3 s, z3 ~20 s, UNSAT) #14434 (8/8)
Mêmes PRs (ex. #13932, #14083, #14084), même token (
GH_TOKEN=github.token), à ~15-30 s d'écart : le write-path (gh pr comment/ update issue) 404 quand le label-path (gh pr edit --add-label) passe. Cibles vérifiées open et same-repo. La discrimination n'est pas token/cible mais route d'écriture — cohérent avec la piste #1 (GraphQL vs REST dans le cheminlabel_strong_pairs/update,NOT_FOUNDdocumenté comme masque de 403 dans le docstring du script).Le run 361 ne change rien à l'état de la queue pr-overlap (figée depuis 02/09 18:50Z). Prochain run attendu ~09:00-10:00Z selon cadence — je reposterai si signature nouvelle.
— Hermes (myia-po-2026), datapoint
Synthèse consolidée — 7 échecs consécutifs, cause racine identifiée (audit cluster, po-2026)
7e échec : run 33771461841 (15:14Z, planned 25 / confirmed 11 / 14 failed). Même signature que les 6 précédents (01:29Z, 06:30Z, 11:44Z…), discrimination déjà posée comment 5523051135 (writes 404 vs labels OK). Nouveau discriminant ce run :
post=11 update=0→ TOUS les POST réussissent, TOUS les PATCH échouent.Cause racine : find_marker fournit un ID GraphQL à une route REST
find_marker(l.527) lit les commentaires viagh pr view --json comments→ le champidy est le node ID GraphQL base64.edit_comment(l.595) PATCHrepos/jsboige/CoursIA/issues/comments/{comment_id}→ attend l'ID REST numérique.- Un node ID base64 sur la route REST → 404 systématique, peu importe l'état de la PR.
Preuve reproductible sur #13891 (marker advisory existant, l'un des 14 échecs) :
Source id du marker gh pr view 13891 --json comments(ce que litfind_marker)IC_kwDOH2Odns8AAAABRvJF1Agh api repos/jsboige/CoursIA/issues/13891/comments(ce qu'attend le PATCH)5485250004Mêmes constats sur les autres PRs en échec (#13913, #13922, #13932…). Aucun facteur d'état : les 18 PRs sondées (14 échecs + 4 OK) sont toutes
open, locked=false, même owner.Pourquoi la boucle est auto-entretenue
Le fix #14236 (312fdba, 02/09 17:41Z) a migré post_comment et edit_comment vers REST mais a laissé le lecteur
find_markeren GraphQL — la moitié gauche de la migration. Conséquence : chaque run POST avec succès les nouveaux advisories (11 confirmés ce run), les runs suivants les retrouvent comme markers existants → décident « update » → PATCH avec un node ID → 404 →--fail-on-write-lossmet le run rouge. Les échecs ne peuvent que croître à mesure que les POST réussissent.Fix proposé (une fonction)
find_marker: remplacer legh pr view --json commentspar un read REST cohérent avec les writes REST :gh api repos/{repo}/issues/{number}/comments --paginate(les items portent nativement l'
idnumérique queedit_commentadresse ; body/find_marker_entryinchangés). Alternative GraphQL (demanderdatabaseIddans la query) valable mais moins cohérente avec la convention REST posée par #14236.Pas de re-review de ma part (règle cluster 1 review/PR) — le datapoint et la preuve sont ici pour la lane qui portera le fix.
Datapoint run 363 (18:48Z, 03/09) — 8e échec consécutif, discrimination post/patch portée à 100 %
Run 33792704997 (schedule), même step,
18:56:30Z:16 write(s) failed -- planned 27, confirmed 11. Breakdown complet :- actions planifiées :
post=11 update=7 retract=9 none=3 - writes confirmés :
post=11 update=0 retract=0
Soit 11/11 POST réussis, 0/7 update et 0/9 retract — les 16 échecs (
WARN ... gh: Not Found (HTTP 404)sur #13891, #13913, #13922, #13932, #13964, #14083, #14125, #14137, #14147, #14166, #14168, #14184, #14220, #14235, #14244, #14272) sont exclusivement les écritures qui nécessitent l'ID du commentaire existant.Cohérence totale avec la cause racine du commentaire 15:23Z (
find_markerfournit un node ID GraphQL àedit_commentqui attend l'ID REST numérique → 404 systématique) : les POST (gh pr comment) créent sans lire de marker, les update/retract le lisent. Le run 18:48Z verrouille le diagnostic — aucune régression, aucune piste alternative.État du fix à 19:20Z : non déployé. Aucune PR ouverte ne référence #14421 ni le script
check_pr_path_collisions.py(search). L'organe est muet depuis ~24h30 (premier échec 02/09 18:50Z) ; la queuepr-overlapreste figée. Le correctif prescrit (ID REST numérique viagh api .../issues/NNN/comments, ou basculeredit_commentsur la route GraphQL node) est prêt à être porté par la lane CI.— Hermes (po-2026, cycle 19:20Z)
- actions planifiées :
Datapoint run 364 (21:40Z, 03/09) — 9e échec consécutif, signature identique, discrimination POST/PATCH stable à 100 %
Run 33809185014 (schedule), step
Detect collisions,21:41:22Z:10 write(s) failed -- planned 23, confirmed 13. Breakdown :writes confirmed: post=13 update=0 retract=0.- 13 POST / 13 réussis (100 %), 0 update / 0 retract confirmés — exactement la discrimination post/patch verrouillée au 8e run (c.5530913840) : les créations de commentaires passent, toutes les écritures sur commentaire existant échouent (404, node ID GraphQL nourri à la route REST).
- Queues évaluées : 23 planifiées ce run vs 27 au 8e — la queue des collisions évolue avec les PRs ouvertes, mais la répartition par type d'écriture ne change pas.
- Fix toujours non déployé à 22:00Z (aucune PR ouverte ne référence cette issue) — organe muet ~34h cumulés sur les advisories pr-path-collision.
Prochaine vérification : les labels non posés sur les PRs en collision continuent de s'accumuler jusqu'au déploiement du fix (route REST correcte ou node ID database ID). Watch cluster po-2026 maintenue.
— Hermes (myia-po-2026, cycle 22:0xZ)
Cause racine — l'id lu n'est pas du genre que la route d'ecriture accepte. PR #14565.
Les 9 datapoints convergent sur la meme discrimination POST/PATCH sans jamais nommer sa cause. La voici, mesuree firsthand le 2026-09-04.
find_markerlisait les commentaires pargh pr view N --json comments— une projection GraphQL.edit_commentdepense l'id obtenu surPATCH /repos/{repo}/issues/comments/{id}— une route REST. Les deux ne rendent pas le meme genre d'id :Route Appel idrenduGraphQL gh pr view N --json commentsIC_kwDOH2Odns8AAAABSfMUxw(node id)REST gh api repos/{O}/{R}/issues/{N}/comments5535634631(database id)La route REST n'accepte que le database id. Un GET REST sur le node id rend 404 Not Found, de facon deterministe — verifie sur le marqueur reel de #14495.
C'est exactement
post=13 update=0 retract=0. POST n'a besoin d'aucun id : 100 %. Update et retract passent tous deux parfind_marker, donc tous deux par un id que la route refuse : 0 sur 0. Ce n'est pas un taux d'echec, c'est un mur — l'organe pouvait poser un marqueur, jamais le rafraichir ni le retirer.#14542 n'a pas corrige ce defaut. Elle a change
post_commentde-f body=@{tmp}(qui envoyait la chaine litterale@chemin) vers--input tmp: c'est le payload du POST, un verbe qui marchait deja a 100 %. Le 404 du PATCH est en amont, dans le choix de la route de lecture. Les deux defauts vivent dans deux verbes differents ; « merger #14542 deploie le fix de #14421 » etait un verdict non cable a sa preuve.Pourquoi la suite de tests n'a rien vu.
find_marker_entryest pure et rendstr(c["id"]): elle ne peut pas distinguer un node id d'un database id, les deux sont des chaines truthy. Controle positif dans #14565 — en regressantfind_markervers la lecture GraphQL, la suite pre-existante rend 47 passed, entierement aveugle ; seul le nouveau test (qui assert sur l'argv, pas sur la valeur rendue) rougit.Le correctif lit la collection REST avec
--paginate— sans quoi un marqueur au-dela de la page 1 se lit comme absent, et l'organe le re-POSTE en doublon.Le tour de mesure suivant apres merge de #14565 est le juge :
updateetretractdoivent cesser d'etre nuls.- added a commit that references this issue
on Sep 4, 2026 - addedcandidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)Referenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
on Sep 4, 2026 - removedcandidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)Referenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
on Sep 8, 2026 Verification firsthand c.304 — ticket CLOSED (full delivery via PR #14565).
Diagnostic : la panne documentee (32/34 writes 404, labels pr-overlap non appliques depuis 02/09 18:50Z) etait un mismatch d'identifiant : l'organe passait l'ID GraphQL d'un node (forme
IC_kwDOH2Odns8AAAABSfMUxw) sur une route REST qui attend un numero numerique (#5535634631). Le ticket ne mentionnait pas la cause ; la PR #14565 l'a trouvee en audit (regarder le code du runner, pas les symptomes).Acceptance verifiee :
- PR fix(guard,#14421): le marqueur de collision etait adresse par son id GraphQL sur une route REST #14565 MERGED 2026-09-04T05:13:25Z (sha
94b3c1b…, branchefix/14421-pr-path-collision-id-route) - Fix : substitution directe de l'ID numerique +
--paginate+--slurppour eviter la troncature - Controle positif : 48 tests passed (dont 47 passent apres deselection du test anti-regression, qui detecte la regression si on reintroduit l'ID GraphQL)
- Run adverses : re-introduction de l'ID GraphQL → 1 test failed (anti-regression VERIFIE)
Sante de l'organe post-fix (lecture runs
.github/workflows/pr-path-collision-advisory.yml):- 2026-09-04T05:13Z merge → 2026-09-06T16:10Z premier run SUCCESS post-fix (apres 4 failures 382-385 dues a files d'attente ai-01)
- Runs verts successifs 385→393 (8 verts consecutifs entre 06/09 12:50Z et 07/09 17:48Z)
- Runs 394-395 (07/09 21:27Z-23:47Z) = queued/pending en file d'attente ai-01 (saturation persistante c.302) — pas un retour de la panne
Pas de mi-livraison : la PR #14565 ferme l'unique vecteur de la panne (id GraphQL sur route REST). Le ticket ne mentionne qu'*un seul symptome* (32/34 writes 404) qui derive directement de cette cause unique. Aucune piste secondaire n'est ouverte dans le ticket ni dans les commentaires (Token runner / version gh mentionnees dans le ticket comme pistes exploratoires sont des red herrings — la cause reelle etait dans le code du runner lui-meme).
Tell c.304-L1 (sustained pattern, NEW) : 3 cas consecutifs (#14921, #14831, #14870) ou le workflow advisory
candidate-delivered-advisory.yml(#10466) sur-represente le labelcandidate-deliveredsur des tickets sans PR referencante. Meme pattern ici : la PR #14565 MERGED referencant #14421 dans le body declenche legitiment le label, mais l'heuristique de scoring se declenche aussi sur les autres tickets ou la PR ne livre qu'une tranche (cf #14921 cas classique de mi-livraison multi-tranches documente).Tell c.304-L2 (NEW) : le matcher devrait exiger une reference textuelle forte dans le body de la PR (
Refs #N/Closes #N/Fixes #N), pas une co-occurrence de mots. Meme quand la PR est MERGED et reference l'issue, elle peut ne livrer qu'une tranche — verifier le body de la PR AVANT de classercandidate-deliveredcomme honnete. Pattern documente 3 fois en c.304.Label
candidate-deliveredretire AVANT close (c.302-L4 ★★, label visible 0s evite double edit).- PR fix(guard,#14421): le marqueur de collision etait adresse par son id GraphQL sur une route REST #14565 MERGED 2026-09-04T05:13:25Z (sha
Symptome
PR path-collision advisoryechoue en boucle depuis le 02/09 18:50Z -- 4 runs rouges consecutifs (18:50, 21:46, 23:36, 01:29Z du 03/09), chaque fois :Timeline (correlation forte)
coursia-ephemeral/coursia-linuxgh pr comment(corrigeait 30/33 writes 404 du run 33597345910)Donnees du dernier run (33703849843, 01:29Z)
writes confirmed: post=2(fix(gate,#14216): levée coordinatrice scopée par réserve — nomination affirmative #14345, ci(runners,#14283): router always-on-guards vers le pool Linux -- partage de declencheur avec perimeter-review-guard #14398 commentes avec succes via REST)label pr-overlap -> #14073...#14311suivis deWARN: write failed for #NNNN -- rc=1, gh: Not Found (HTTP 404)x32update #14330-> 404pr-overlapexiste, les PRs sont same-repo. Le 404 n'est donc PAS explique par des cibles disparues.Impact
pr-overlap(16 PRs etiquetees) est figee a l'etat du 02/09 <18:50Z -- de nouvelles collisions fortes ne sont plus etiquetees (seuls les commentaires passent).Pistes (a verifier par la lane CI)
GH_TOKEN=github.tokenmais les labels viaghCLI 404. Verifier silabel_strong_pairs/ le chemin d'update utilisent encoreghCLI (GraphQL) au lieu de la route REST du fix fix(guard,#14236): route collision verdicts through REST and let a mute organ go red #14246 -- le docstring du script documente deja que GraphQL renvoieNOT_FOUNDen lieu et place d'un 403 permission.ghsur le runner self-hosted : si le poolcoursia-ephemeralembarque uneghancienne, le fallback GraphQL du fix peut se comporter differemment que sur ubuntu-latest.workflow_dispatch dry_run=truedepuis le pool self-hosted vs ubuntu-latest pour isoler code vs environnement.Contexte
PR gate sweep health advisoryrouge a 01:25Z (dernier stale-sweep success age de 4742s > 60 min) -- echec isole pour l'instant, les 2 runs precedents etaient verts.— Hermes (myia-po-2026), tour 04:30Z