Skip to content

fix(ci,#15758): pr_gate_missing — le bot s'écrit selon l'API, les deux sites partageaient la mauvaise orthographe - #15759

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/15758-prgate-bot-spelling
Sep 12, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/15758-prgate-bot-spelling

Conversation

@jsboige

@jsboige jsboige commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Grain: MED/tooling — lane myia-po-2023:CoursIA — prev: DEEP/tooling #15725

Summary

Résiduel de #15621, survivant au correctif mergé #15622 (12321c2354). Même classe de défaut — collecteur et consommateur ne partagent pas la même forme — mais sur l'axe de l'auteur bot, que #15622 n'a pas couvert.

Le collecteur lit l'auteur en REST :

"--jq", '.[] | {number, draft: .draft, base: .base.ref, '
        'author: .user.login, labels: [.labels[] | {name}], sha: .head.sha}'

classify_input() range cette valeur sous author_login. Les deux consommateurs comparaient à une constante GraphQL :

BOT_LOGIN = "app/github-actions"                 # l.82 (avant)
if pr.get("author_login") == BOT_LOGIN:          # l.199 (classify) et l.243 (prescribe)

Or les deux API n'épellent pas le bot pareil — mesuré sur #15678 :

Source Valeur
REST gh api repos/jsboige/CoursIA/pulls/15678 --jq '.user.login' github-actions[bot]
GraphQL gh pr view 15678 --json author app/github-actions
GraphQL author.login (brut) github-actions

Le collecteur émet la première, les consommateurs comparaient à la deuxième : l'égalité était fausse pour toute PR du bot. Le verdict bot_missing et la cause bot étaient structurellement inatteignables — la PR du bot était publiée « gate absent, cause inconnue », avec « investigation manuelle » réclamée, au lieu de la cause structurelle nommée (et sans le label pr-gate-missing-bot).

Le correctif

  • BOT_LOGINS + is_bot_author() : les trois orthographes mesurées, et un point de comparaison unique que les deux sites appellent — une quatrième orthographe ne peut pas n'en corriger qu'un seul. C'est la convention des autres organes qui lisent un auteur (ci/guard_comment_upsert.py GUARD_BOT_LOGINS, pick_idle_grain.py AUTOMATION_AUTHORS, review_coverage.py) ; cet organe était le seul à comparer à une chaîne unique.
  • Le détail de la cause nomme désormais l'orthographe mesurée, jamais une chaîne supposée (règle de l'organe : « le commentaire nomme la cause MESURÉE, avec la valeur lue »).

Vérification

$ python -m pytest scripts/tests/test_pr_gate_missing.py -q
34 passed

Contrôle positif — les tests neufs ne sont pas verts par construction. Contre la source d'origine (origin/main@e7eb3fca7d, module chargé depuis git show), le chemin réel rend les verdicts que ce commit corrige :

has is_bot_author?   False
BOT_LOGIN = 'app/github-actions'
  classify('github-actions[bot]') -> missing        # <-- émis par le collecteur
  classify('app/github-actions')  -> bot_missing
  classify('github-actions')      -> missing
prescribe(REST)      -> unknown

L'angle mort que ce commit ferme. Les tests existants pilotaient bien list_open_prs, mais lui passaient author="app/github-actions" à la main — la valeur de la constante du consommateur, jamais celle que le collecteur rend vraiment. Le test neuf énonce le contrat du producteur : il capture les arguments gh du collecteur et exige que le sélecteur d'auteur reste .user.login (REST). Changer de source d'auteur change l'orthographe rendue ; ce test rougit à ce moment-là au lieu de suivre en silence.

Acceptance de l'issue :

  1. les trois orthographes mesurées classent en bot — couvert ;
  2. un auteur humain (jsboige, myia-ai-01, "") n'est pas absorbé — couvert ;
  3. le test épingle la forme du producteur, pas un dict construit à la main — couvert ;
  4. aucune régression des autres verdicts — les 28 tests antérieurs restent verts.

Note de voisinage — #15728

#15728 (fix/15621-prgate-collector-shape, lane po-2023) est une implémentation sœur du même #15621 (PR_ROW_KEYS/normalize_row là où #15622 a retenu classify_input), mergée 81 min après sa création. Elle est donc CONFLICTING et supplantée pour sa partie forme/labels. Elle portait en revanche la quatrième cause dont ce commit est la livraison — reprise ici sur main, dans la conception retenue, et non par une résolution de conflit qui aurait réintroduit un second design. Je ne ferme pas #15728 : la décision est coordinateur.

Closes #15758. See #15621, See #15622.

🤖 Generated with Claude Code

…ux sites partageaient la mauvaise orthographe

Residuel de #15621, survivant au correctif merge #15622 : le collecteur lit
l'auteur en REST (`github-actions[bot]`), le consommateur comparait la constante
GraphQL `app/github-actions`. L'egalite etait fausse pour TOUTE PR du bot, donc
`bot_missing` (verdict) et `bot` (cause) etaient structurellement inatteignables
-- la PR du bot etait publiee « gate absent, cause inconnue » avec
« investigation manuelle » reclamee.

- `BOT_LOGINS` + `is_bot_author()` : point de comparaison UNIQUE, les trois
  orthographes mesurees sur #15678, comme les autres organes qui lisent un
  auteur (`guard_comment_upsert.py`, `pick_idle_grain.py`, `review_coverage.py`).
- Les deux sites de comparaison (`classify`, `prescribe`) l'appellent.
- Le detail nomme l'orthographe MESUREE, jamais une chaine supposee.
- Tests : les trois orthographes ; le chemin collecteur -> consommateur avec la
  valeur REST reelle ; et un contrat du PRODUCTEUR (le collecteur lit
  `.user.login`) -- c'est ce contrat qui manquait, les tests passaient la valeur
  de la constante du consommateur a la main.

Controle positif : contre la source d'origine, `github-actions[bot]` rend
`missing` et `prescribe` rend `unknown` ; les deux verdicts attendus sont donc
bien absents avant ce commit.

Closes #15758. See #15621, See #15622.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uree »

`_comment_body` compose le commentaire dans l'ordre : texte du remede d'abord,
puis « Cause mesuree : <detail> ». Le login du bot est donc nomme SOUS le texte,
pas au-dessus -- « ci-dessus » etait faux dans le rendu reel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #15759 (fix(ci,#15758): pr_gate_missing — le bot s'écrit selon l'API, les deux sites partageaient la mauvaise orthographe) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signifie que la substance est deja sur main : le cote merge n'est plus une collision a arbitrer, c'est du travail deja integre.

@myia-ai-01
myia-ai-01 merged commit f6fbec3 into main Sep 12, 2026
17 of 21 checks passed
myia-ai-01 added a commit that referenced this pull request Sep 14, 2026
…s le silence (#15778)

blocking_causes() filtrait un check requis CANCELLED/STALE/SKIPPED/NEUTRAL
exactement comme un advisory vert : le `continue` sur `verdict not in
CHECK_FAILED` s'executait AVANT le test `isRequired`. La PR etait BLOCKED
sans aucune cause rendue -- mesure ai-01 du 2026-09-12 : 7 PRs simultanees
dans cet etat, et c'est le regime nominal sous file chargee : le slot
`--timeout-min 45` rend `cancelled`, jamais `failure`.

Correctif : CHECK_UNCONCLUDED = {CANCELLED, STALE, SKIPPED, NEUTRAL} rendu
comme cause DISTINCTE d'un echec -- "check requis non conclu : <nom>
(<ETAT>)" -- parce que le geste attendu n'est pas le meme : la lane ne peut
rien, la reprise est coordinateur. CHECK_FAILED reste intact
(impute_base_reds, _has_failed_check, file_saturation_cause inchanges) :
imputer un CANCELLED a la lane l'enverrait chercher un rouge qui n'existe
pas -- le cycle brule que la R0 de coordinator-discipline interdit.

L'assertion qui epinglait le comportement defaut (requis CANCELLED ->
aucune cause) est remplacee par l'acceptance 1-4 de l'issue : cause non
vide nommant l'etat, jamais confondue avec "en echec", controle positif
(meme entree FAILURE -> "en echec" survit), controle negatif (requis
SUCCESS -> aucune cause), advisory non conclu silencieux.

Suites : test_pick_idle_grain 116 passed (113 + 3 neufs) ; familles
picker/perimeter/fast_lane/lane_claim : 481 passed + 312 passed.

Instance vivante du jour : #15759 -- PR gate requis CANCELLED a 48 min +
Scripts Tests CANCELLED, PR BLOCKED sans cause rendue par le picker.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: myia-ai-01 <myia.ai.01.myia@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane-claim-absent Closing issue carries no claim at all (#10223)

Projects

None yet

2 participants