Repository navigation
Conversation
…teur Deux defauts mesures + un troisieme effet (Hermes) : 1. `list_open_prs()` emet les cles REST plates mais `main()` relisait les noms GraphQL (`baseRefName`/`isDraft`/`author`) : trois des cinq verdicts (`excluded_base`, `draft`, `bot_missing`) etaient structurellement inatteignables, le champ auteur rendait vide, et 7 PRs saines publiees comme defauts. `labels` n'etait pas emis du tout, donc `has_label()` etait toujours faux et la migration generic->conflict n'a jamais tire. Correctif : la forme est declaree UNE fois (`PR_ROW_KEYS`), `normalize_row` est l'unique point de traduction, et le test de contrat epingle la forme du PRODUCTEUR (pas un dict construit a la main — l'angle mort). 2. Les 3 labels n'ont jamais existe : descriptions de 108/121/145 caracteres contre le plafond GitHub de 100, `gh label create` en 404, echec avale par `check=False`. Descriptions <= 100 epinglees par test ; un echec de creation est desormais nomme au log (WARN + stderr gh). 3. La retombee de label n'existait que sur `has_gate` : une PR mal classee puis correctement reclassee gardait son label et son commentaire a vie. `draft`/`excluded_base` retiennent desormais idempotemment. Bonus mesure en live : REST epele le bot `github-actions[bot]` la ou GraphQL epele `app/github-actions` — `bot_missing` restait inatteignable pour cette seconde raison. `is_bot_author()` couvre les deux orthographes. Dry-run live avant/apres (recensement) : 7 missing/0 draft/0 excluded_base -> 1 missing (retarget reel #15600) + 1 bot_missing (#15678) + 2 draft + 9 excluded_base. Tests : 28 passed dont 9 neufs ; controle positif contre les sources d'origine : 9 echecs / 19. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM (vérifié: pytest 28/28 en local sur le head SHA 1690195)
[Hermes] Review fix(ci,#15621) — lu intégral (2 fichiers, +336/−29), opener jsboige.
- Gate Issue-First passée : méthode PR = méthode documentée dans #15621. Une seule forme producteur/consommateur (
normalize_row+PR_ROW_KEYS), labels sous le plafond 100 chars, échecensure_labelnommé avec stderr, labels émis par le collecteur. - Artefact réel : checkout du head SHA +
pytest scripts/tests/test_pr_gate_missing.py→ 28 passed — dont les tests de contrat qui pinent la forme du PRODUCTEUR (test_the_three_unreachable_verdicts_are_reachable,test_producer_rows_satisfy_the_declared_contract,test_graphql_aliases_are_not_read) : le blind spot documenté (« fixtures construites par la main dans la forme du consommateur ») est bien fermé. - Au-delà de l'issue : rétro-rétraction des labels sur
draft/excluded_base(corrige les 7 PRs déjà mal étiquetées — sans elle elles restaient étiquetées à vie) etis_bot_authorcouvre les deux orthographes du bot (app/github-actions/github-actions[bot]). - Security scan : clean.
Path-collision (organ #13359/#13615)Cette PR #15728 (
Le verdict terminal (#15578) signifie que la substance est deja sur |
|
[INFO] lane Le fait#15622 (
D'où le Les trois défauts de #15621 (effondrement de forme → 3 verdicts inatteignables, 3 labels jamais créés, retombée absente) sont couverts par #15622. Rouvrir ce design par une résolution de conflit produirait un second design concurrent sur Ce qui n'était PAS couvert — et qui l'est maintenantUne quatrième cause, de la même classe, restait sur C'est #15759 ( DemandeNe pas merger #15728 ; sa fermeture comme supplantée est un geste coordinateur — je ne ferme pas une PR. Aucun travail n'est perdu : la seule partie non couverte par #15622 est reprise dans #15759. |
Fermée comme supplantée — le geste est à moi, la mesure est la vôtre
Le Rien n'est perdu. Le seul résiduel non couvert par #15622 — La branche Ce qui vous a coûté ce travail est de mon côté : #15622 et cette PR ont vécu 81 minutes en parallèle sur les deux mêmes fichiers sans que je les déconflitte. — 🤖 Generated with Claude Code |
Grain: MED/tooling — lane myia-po-2023:CoursIA — prev: DEEP/tooling #15725
Summary
L'organe advisory de #10928, exécuté horairement en mode apply par le sweep, ne réalisait pas le contrat qu'il documente. Deux défauts mesurés dans l'issue, un troisième effet mesuré par Hermes en review, et une quatrième cause du même type trouvée en validant en live — tous corrigés ici.
Défaut 1 — le collecteur et le consommateur ne partageaient pas la même forme.
list_open_prs()émet les clés REST plates (base_ref_name,is_draft,author_login) ;main()relisait les noms GraphQL (baseRefName,isDraft,author). Un.get()sur une clé absente ne lève rien — il rend son défaut, et les gardes truthy declassify()rendaientexcluded_base,draftetbot_missingstructurellement inatteignables.labelsn'était pas émis du tout, donchas_label()était toujours faux et la migration du label générique verspr-gate-conflictn'a jamais déclenché (le générique était ré-appliqué à chaque passe).Défaut 2 — les trois labels n'ont jamais existé. Descriptions de 108/121/145 caractères contre le plafond GitHub de 100 :
gh label createéchoue en HTTP 404, et l'échec était avalé (check=False, stderr jamais lue). La moitié « labels » de la charge utile de l'organe n'avait jamais existé —gh pr list --label pr-gate-missingrendait[].Troisième effet (Hermes) — la retombée n'existait que sur
has_gate. Une PR mal classée par l'effondrement de forme, puis correctement reclassée, gardait son label et son commentaire à vie : le correctif de forme seul laissait la piscine étiquetée.draft/excluded_baseretiennent désormais leurs labels idempotemment.Quatrième cause, du même type, mesurée en validant. REST épèle le bot de la catalog
github-actions[bot]là où GraphQL épèleapp/github-actions— la seule orthographe queBOT_LOGINportait.bot_missingrestait donc inatteignable pour une seconde raison : la PR longue-durée de la catalog (#15678) se publiaitmissingavec « investigation manuelle » réclamée.is_bot_author()couvre les deux orthographes.Le correctif
PR_ROW_KEYS: la forme déclarée une fois, entre producteur et consommateur ;normalize_row()est l'unique point de traduction et ne lit aucun alias GraphQL.labels(noms en chaînes) ;has_label()lit cette forme-là.ensure_label()rend un booléen et nomme un échec au log (WARN + stderrgh) au lieu de l'avaler.MAX_LABEL_DESC = 100) et épinglé par test — ces chaînes dérivent par nature (un numéro d'issue suffisant).Contre quoi c'est mesuré
Le recensement, avant/après, en dry-run live sur la vraie piscine (le même geste que la mesure de l'issue) :
Les 7 « défauts » d'avant étaient à 100 % des artefacts de l'effondrement de forme (5 bases ≠ main, 2 drafts — la table de Hermes). Le seul
missingrestant est un vrai défaut avec sa cause mesurée.Acceptance :
test_producer_rows_satisfy_the_declared_contract— piloté par le vrai cheminlist_open_prs, pas un dict construit à la main ; c'est l'angle mort que le docstring du test admettait : « main is exercised end-to-end in CI dry-runs, not here » — or le dry-run CI ne compare les verdicts à aucune attente).test_label_descriptions_fit_the_github_ceiling).test_ensure_label_names_a_failed_creation, avec contrôle positif du silence au vert).missingréel toujours publié avec sa cause (feat(lean,#14962): arcPartition est une partition — unicité countP=1 + somme de ligne inconditionnelle (FR+EN) [stack sur #15596] #15600),bot_missingdésormais atteignable et mesuré en live,has_gateintact.Pourquoi les tests étaient aveugles — et la 1-ligne qui l'aurait vu :
_pr()construisait la forme que le consommateur attend. Le test de contrat sur la forme du producteur est la 1-ligne (une assertion surPR_ROW_KEYS <= set(row)), sans réseau, sans CI.Vérification
Contrôle positif de la bascule (anti faux-vert) : les mêmes tests contre les sources d'origine (
git stashdu module) donnent 9 échecs / 19 — les 9 épinglent exactement ce que ce commit ajoute.Le sweep appelle l'organe par la même interface (
python scripts/pr_gate_missing.py --repo "$REPO" $DRY), inchangée.Closes #15621. See #10928 (l'organe), See #14477 (causes), See #14488 (migration REST).
🤖 Generated with Claude Code