Skip to content

picker: un PR gate rouge par DWELL est assigne comme grain reparable — 4e surface de #15726 #15910

Description

@jsboige

Le defaut

Un PR gate rouge par DWELL (plancher de 120 min, aucun check fils en echec) est assigne a une lane comme grain de reparation en premiere action. La lane brule son cycle a chercher dans son diff un defaut qui n'y est pas — et qui n'existe pas : la cause est un minuteur, que seul l'ecoulement du temps leve.

C'est la quatrieme surface du meme mecanisme que #15726 (apres #15748, #15763 et #15769). #15763 la nomme et la met explicitement hors de son perimetre :

« Il ne traite pas non plus le DWELL — l'autre cause non-reparable qu'un PR gate rouge peut porter (un minuteur, pas un defaut). pr_gate.py la phrase deja correctement dans son message ; la rendre lisible cote picker demande de lire le texte du check-run, pas sa conclusion. A traiter separement. »

Cette issue est ce traitement separe.

Mesure firsthand — 2026-09-13, cycle myia-po-2024:CoursIA

Trois PRs de la lane, toutes verts hors PR gate, toutes en DWELL :

PR Tete (check-runs complet) Annotation PR gate Non-verts hors gate
#15888 80 checks DWELL -- tete du 2026-09-13T01:43:55Z, 9 min -- plancher 120 min, reste 111 min 0
#15895 30 checks DWELL -- tete du 2026-09-13T02:32:00Z, 8 min -- ... reste 112 min 0
#15902 81 checks DWELL -- tete du 2026-09-13T03:45:13Z, 8 min -- ... reste 112 min 0

Ce que le picker a rendu (sortie 0) :

GRAIN DU CYCLE -- lane myia-po-2024:CoursIA : reparer ses propres PRs.
Motif : la lane porte 3 PR(s) bloquee(s) simultanees (seuil 3).

  #15888  ouverte depuis 2 h  -- ...
       check requis en echec : PR gate
  #15902  ouverte depuis 1 h  -- ...
       check requis en echec : PR gate
  #15895  ouverte depuis 1 h  -- ...
       check requis en echec : PR gate

Et, dans la meme sortie :

ROUGE IMPUTE A LA BASE -- pas le votre, pas reparable par la lane :
  - PR gate : organe non lisible sur #15866, #15869, #15877, #15886, #15887, #15888
    -- pas pu trancher, le rouge RESTE a la lane

Le controle negatif est dans la meme journee. Le plancher de #15888 est ecoule a 03:43:55Z ; un gh run rerun <run gate> (pas un push — il ne cree pas de tete) a rendu success immediatement, et mergeStateStatus est passe BLOCKED -> CLEAN. Sur la seconde execution du picker, #15888 a disparu de la liste « organe non lisible » (#15866 y a disparu aussi, un autre plancher ayant expire entre-temps). Le seul changement etait l'ecoulement du temps : la liste se vide toute seule.

Le mecanisme, ligne a ligne

  1. AGGREGATOR_CHECK_NAMES = {"PR gate"} (l.1093) fait de PR gate un agregateur.
  2. Pour un agregateur, failed_check_keys (l.1224-1242) ne rend pas le nom du check mais les organes nommes par la banniere ::error::Organes bloquants en echec : ..., lue par fetch_check_organs (l.1196-1221) via _ORGAN_BANNER_RE (l.1097).
  3. Un DWELL n'a aucun organe en echec, donc aucune banniere : fetch_check_organs rend [] (l.1214-1221), et failed_check_keys rend [] pour cet agregateur. Le fail-closed de l.1230-1232 est correct dans son intention (« un agregateur ne peut pas corroborer sur la seule foi de son nom ») mais il ne distingue pas « je n'ai pas pu lire » de « il n'y avait rien a lire ».
  4. Consequence 1 — la ligne « organe non lisible … le rouge RESTE a la lane » (print_base_reds, l.1885). Le message est litteralement vrai et semantiquement faux : l'absence de banniere est le signal, pas une panne d'instrument.
  5. Consequence 2 — blocking_causes compte le FAILURE requis comme reparable par la lane, donc la PR entre dans red et le declencheur count (« rouges simultanees », l.2010, seuil RED_COUNT_DEFAULT) fait basculer tout le cycle sur une reparation inexistante. Trois PRs poussees dans la meme fenetre de 2 h suffisent a declencher P0 par le seul minuteur de dwell.

Pourquoi ce n'est aucune des surfaces deja traitees

Issue Ce qu'elle couvre En quoi c'est un autre etage
#15763 / PR #15764 agregateur rouge par constituants cancelled la cause est dans les enfants ; ici il n'y a aucun enfant non-vert
#15769 / PR #15778 conclusion propre de l'agregateur a CANCELLED ici la conclusion est FAILURE, avec un motif ecrit
#15905 pr_gate.py phrase mal un depassement de timeout ici pr_gate.py phrase juste ; c'est le picker qui ne lit pas son texte
#15825 output.title = null sur conclusion en echec instrument d'acces ; n'explique pas l'attribution a la lane
#15859 un plancher remis a zero par update-branch geste de la lane ; ici le plancher court normalement

pr_gate.py dit deja le bon verdict — <pr-gate> DWELL -- tete du ..., N min -- plancher 120 min, reste M min (merge_dwell.py, l.142-148), et le rend dans l'annotation du check-run. Le texte existe, il est date, il porte l'echeance. Le picker ne le consomme pas.

Le precedent, dans le picker lui-meme

file_saturation (#12830) est exactement la meme forme : un troisieme etat de mergeStateStatus: BLOCKED qui n'est pas un rouge reparable, diagnostique comme tel (l.1387-1398, avec son geste « commenter la PR + --ignore-red ») et distingue des rouges de substance. Le DWELL demande la meme chose — un quatrieme etat, avec l'echeance pour information au lieu d'un geste de reparation.

Acceptance

Note de sequencement

Le fichier scripts/pick_idle_grain.py est tenu par trois PRs ouvertes au moment de la redaction (#15764 ai-01, #15778 po-2023, #15813 po-2023) : un fix de cette surface doit etre sequence apres elles, ou porte par le titulaire du claim.

Mesure faite au 2026-09-13T04:05Z — lane myia-po-2024:CoursIA.

No activity

Activity on this issue will appear here.

Activity

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