Skip to content

ci: pr-path-collision advisory muet depuis #14343 (tranche 4 self-hosted) -- 32/34 writes 404, labels non appliques ~10h #14421

Description

@jsboige

Symptome

PR path-collision advisory echoue 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 :

advisory: 32 write(s) failed -- planned 34, confirmed 2
##[error]32 write(s) failed -- planned 34, confirmed 2

Timeline (correlation forte)

Heure (UTC) Evenement
02/09 17:22 merge #14343 (tranche 4) : route les 32 crons pur-Python vers le pool self-hosted coursia-ephemeral/coursia-linux
02/09 17:41 merge #14246 : write-loss rendu visible + routing REST pour gh pr comment (corrigeait 30/33 writes 404 du run 33597345910)
02/09 15:10 dernier run SUCCESS de l'organe (avant les deux merges ci-dessus)
02/09 18:50 premier echec : 32/34 writes 404
03/09 01:29 toujours en echec, meme signature

Donnees du dernier run (33703849843, 01:29Z)

Impact

  • L'organe de coordination est muet depuis ~10h : la queue 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).
  • Les runs etant rouges mais non-gates, aucune PR n'est bloquee -- le signal est purement perdu, pas bruyant.

Pistes (a verifier par la lane CI)

  1. Token du runner self-hosted : les POSTS (REST, fix(guard,#14236): route collision verdicts through REST and let a mute organ go red #14246) passent avec GH_TOKEN=github.token mais les labels via gh CLI 404. Verifier si label_strong_pairs / le chemin d'update utilisent encore gh CLI (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 renvoie NOT_FOUND en lieu et place d'un 403 permission.
  2. Version gh sur le runner self-hosted : si le pool coursia-ephemeral embarque une gh ancienne, le fallback GraphQL du fix peut se comporter differemment que sur ubuntu-latest.
  3. Reproduire en workflow_dispatch dry_run=true depuis le pool self-hosted vs ubuntu-latest pour isoler code vs environnement.

Contexte

  • Decouvert au tour de sante Hermes 04:30Z le 03/09 lors de la cloture du watch "runs schedule du 03/09" (les runs schedule ont bien tire cette nuit : 00:08 -> 01:29Z ; ce probleme est distinct du retard quotidien de la fenetre 03:07-03:22Z, attendu vers ~07:50Z comme hier).
  • Run apparente sans lien etabli : PR gate sweep health advisory rouge 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

Activity

  1. jsboige commented on Sep 3, 2026

    @jsboige
    OwnerAuthor

    [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); summary 32 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.

  2. jsboige commented on Sep 3, 2026

    @jsboige
    OwnerAuthor

    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 :

    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 chemin label_strong_pairs/update, NOT_FOUND documenté 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

  3. jsboige commented on Sep 3, 2026

    @jsboige
    OwnerAuthor

    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 via gh pr view --json comments → le champ id y est le node ID GraphQL base64.
    • edit_comment (l.595) PATCH repos/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 lit find_marker) IC_kwDOH2Odns8AAAABRvJF1A
    gh api repos/jsboige/CoursIA/issues/13891/comments (ce qu'attend le PATCH) 5485250004

    Mê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_marker en 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-loss met le run rouge. Les échecs ne peuvent que croître à mesure que les POST réussissent.

    Fix proposé (une fonction)

    find_marker : remplacer le gh pr view --json comments par un read REST cohérent avec les writes REST :

    gh api repos/{repo}/issues/{number}/comments --paginate
    

    (les items portent nativement l'id numérique que edit_comment adresse ; body/find_marker_entry inchangés). Alternative GraphQL (demander databaseId dans 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.

  4. jsboige commented on Sep 3, 2026

    @jsboige
    OwnerAuthor

    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_marker fournit un node ID GraphQL à edit_comment qui 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 queue pr-overlap reste figée. Le correctif prescrit (ID REST numérique via gh api .../issues/NNN/comments, ou basculer edit_comment sur la route GraphQL node) est prêt à être porté par la lane CI.

    — Hermes (po-2026, cycle 19:20Z)

  5. jsboige commented on Sep 3, 2026

    @jsboige
    OwnerAuthor

    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)

  6. jsboige commented on Sep 4, 2026

    @jsboige
    OwnerAuthor

    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_marker lisait les commentaires par gh pr view N --json comments — une projection GraphQL. edit_comment depense l'id obtenu sur PATCH /repos/{repo}/issues/comments/{id} — une route REST. Les deux ne rendent pas le meme genre d'id :

    Route Appel id rendu
    GraphQL gh pr view N --json comments IC_kwDOH2Odns8AAAABSfMUxw (node id)
    REST gh api repos/{O}/{R}/issues/{N}/comments 5535634631 (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 par find_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_comment de -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_entry est pure et rend str(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 regressant find_marker vers 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 : update et retract doivent cesser d'etre nuls.

  7. added a commit that references this issue on Sep 4, 2026
  8. added
    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
    on Sep 4, 2026
  9. removed
    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
    on Sep 8, 2026
  10. jsboige commented on Sep 8, 2026

    @jsboige
    OwnerAuthor

    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…, branche fix/14421-pr-path-collision-id-route)
    • Fix : substitution directe de l'ID numerique + --paginate + --slurp pour 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 label candidate-delivered sur 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 classer candidate-delivered comme honnete. Pattern documente 3 fois en c.304.

    Label candidate-delivered retire AVANT close (c.302-L4 ★★, label visible 0s evite double edit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions