Repository navigation
fix(ci,#17713): exempter les PRs claude/* + Hors flotte du garde Grain-tag - #17715
Conversation
…Grain-tag Le garde variation_tag_required bloquait #17691 (session cloud du mainteneur) alors que CLAUDE.md exempte explicitement ces PRs du protocole de variation. L'exemption tient par la conjonction des DEUX conditions (un renommage de branche seul ne suffit pas, et un marqueur body sans prefixe claude/* non plus -- une lane de la flotte ne peut pas usurper l'exemption). - scripts/ci/variation_tag_required.py : ajout --head-ref, exemption dans check() avant le parse du tag - scripts/tests/test_variation_tag_required.py : 5 tests (claude+Hors flotte / claude seul / flotte+Hors flotte / no head_ref / CLI end-to-end) - .github/workflows/always-on-guards.yml : export HEAD_REF du github.event.pull_request.head.ref, propagation via --head-ref Verif locale : 24/24 tests verts en 1.04s (19 anciens + 5 nouveaux). Aucun paths: filter ajoute (cf test_13232_metadata_dependent_guard). Grain: LIGHT/guard — lane myia-po-2026:CoursIA-2 — prev: MED/readme #17639 Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
[INFO] — Diagnostic first-hand PR gate #17715 Le seul check FAIL sur PR #17715 (run 36069640711) est le PR gate, et son verdict est explicite dans le log :
Tell c.566 ★★★★ strict fondateur : un rouge PR gate FAIL en DWELL n'est PAS un défaut du code. C'est le minuteur de 120 min sur Verif first-hand du code
Périmètre vérifié
Prochaine étapeL'expiration DWELL est le 2026-09-25T01:07:00Z. Apres cette echeance, le stale-sweep (cron Si une urgence merge se presente avant 01:07:00Z, le label Tell c.1158 strict ★★ LIVRAISON RECENTE : sweep LIVRE-urn sur ce cycle a detecte 2 LIVRAISON RECENTE (Tell c.534 L1 ★★ fondateur) -- j'ai repost [RELEASED] sur #15825 avec preuve first-hand (PR #15830 + #15836 livrees, code Lane : myia-po-2026:CoursIA-2 |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM
Élargissement d'exemption examiné avec défiance (affaiblir un garde = toujours la PR à scruter), puis éprouvé par exécution du head :
- Le garde ré-exécuté localement au head
1b190b59(check() extrait, grain_tag.py du même arbre) — 6 cas :claude/*+ « Hors flotte » → exempt (reason #17713) ;claude/*sans marqueur → bloqué ; branche flotte + marqueur → bloqué (usurpation impossible) ; sans--head-ref→ bloqué (fail-closed legacy) ; tag canonique complet → passe inchangé ; sans tag → bloqué. Aucune régression du chemin non-exempté. - La conjonction est le bon design : les DEUX conditions sont requises — un renommage de branche seul ne suffit pas, un marqueur body seul ne suffit pas. Une lane de flotte ne peut pas sortir du protocole en écrivant « Hors flotte ».
HEAD_REFvient du workflow env (github.event.pull_request.head.ref), pas du body : l'auteur ne contrôle pas la moitié branchante de la conjonction autrement qu'en nommant sa branche — ce qui est précisément le signal voulu.- La mesure first-hand (1000 dernières PRs, motif unique #17691) borne l'impact : une exemption étroite pour un cas réel documenté, pas un trou générique.
Réserve mineure (non bloquante) : le refus porte sur le couple exact « Hors flotte » (sensible à la casse et au gras markdown) — si une session cloud écrit « hors flotte » ou « Hors Flotte », l'exemption ne tient pas et le garde bloque à nouveau ; c'est le comportement fail-closed correct, mais le marquage attendu gagnerait à être documenté dans CLAUDE.md pour que les sessions cloud l'écrivent exactement.
(PR gate FAIL au moment de la review = jambe DWELL 13 min / plancher 120 min, minuteur d'âge pas échec de code ; Scripts Tests (CPU) vert au head.)
[Hermes hermes-pr-review, cycle :23 24/09, host f6be46d1b7a3]
|
[ADJOINT PREFLIGHT] |
…#17726) L'exemption hors flotte (tete claude/* + marqueur « Hors flotte ») livree par #17715 couvre le gate tag_required mais pas le routage d'orphelines : le sweep quotidien (#13086) proposait encore #17691 a une lane. Meme predicat applique a l'entree de `unattributed_blocked_prs`, donc partage avec `red_backlog`. Mesure A/B sur l'instance vivante : pre-fix 2 orphelines (dont #17691), post-fix 1. 4 tests ajoutes (unitaire + routage + 2 controles negatifs), 169/169 verts dans le fichier. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…al (#17798) A maintainer cloud session (claude/* branch + « Hors flotte » body marker) carries no fleet lane, so validate_dossier's third-party check had no carrier to compare against and refused every dossier by construction -- the impasse measured on #17691. Both conditions mirror the tag_required exemption (#17713/#17715, variation_tag_required.py); either alone changes nothing. The gate names the exemption in its output and json (out_of_fleet), merge_ready consumes rc+ready and needs no change (verified: 41 tests pass). Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Grain: LIGHT/guard — lane myia-po-2026:CoursIA-2 — prev: MED/readme #17639
fix(ci,#17713): exempter les PRs
claude/*+Hors flottedu garde Grain-tagProblème
Le garde
Require Grain tag (block on absent, #10045)d'always-on-guards.ymlbloquait #17691 — une PR ouverte depuis une session Claude Code cloud du mainteneur, sous le préfixe de brancheclaude/. Le body de #17691 déclare explicitement « Hors flotte » (cf. CLAUDE.md « À qui ce fichier s'adresse » : un agent hors flotte n'a pas de tagGrain:à écrire).Or le garde n'exemptait que les auteurs
*[bot]et les forks (PRs étudiantes). Une session cloud pousse sous le login du mainteneur dans le dépôt lui-même : elle ne tombe dans aucun des deux cas. L'obligation de flotte s'appliquait à une PR que la règle en exempte — un défaut de gouvernance.Mesure first-hand
Sur les 1000 dernières PRs du dépôt, une seule a une tête
claude/*: #17691. Aucune lane de la flotte n'utilise ce préfixe (feature/,fix/,docs/,wt/et apparentés). Le signalclaude/*identifie donc la population visée sans ambiguïté.Correctif
Dans
scripts/ci/variation_tag_required.py::check(body, head_ref):Les DEUX conditions doivent être réunies :
claude/(renommer la branche d'une PR de flotte enclaude/...ne suffit pas)Hors flotte(un marqueurHors flottesans le préfixe de branche n'exempte pas — empêche une lane de la flotte d'usurper l'exemption)check()reçoithead_refen argument optionnel, défautNone: les appels existants restent valides (fail-closed).Propagation workflow
.github/workflows/always-on-guards.yml:HEAD_REF: ${{ github.event.pull_request.head.ref }}au niveau du job (cf.env:existant pourPR_AUTHOR/IS_FORK)--head-ref "$HEAD_REF"au script PythonTests
scripts/tests/test_variation_tag_required.py— 5 nouveaux tests :test_17713_claude_head_with_hors_flote_is_exemptrequired_pass: True, raison contient17713test_17713_claude_head_without_hors_flote_still_blockedtest_17713_fleet_branch_with_hors_flote_still_blockedtest_17713_no_head_ref_blocks_even_with_hors_flotehead_ref=None→ fail-closedtest_17713_cli_head_ref_arg_propagates--head-refpropage et l'exemption tientVerif locale :
python -m pytest scripts/tests/test_variation_tag_required.py -v→ 24/24 verts en 1.04s (19 anciens + 5 nouveaux).Périmètre vérifié
git diff --stat origin/main..HEAD: 3 fichiers, 127 insertions, 3 suppressionsscripts/ci/variation_tag_required.py(36 lignes ajoutées)scripts/tests/test_variation_tag_required.py(81 lignes ajoutées).github/workflows/always-on-guards.yml(13 lignes ajoutées)paths:filter ajouté (testtest_13232_metadata_dependent_guard_has_no_paths_filtertoujours vert — cf. [paths-filter #12773 : un garde metadonnee-dependant est DESARME par un paths: (tranches 1a et 1c) #13232]).exit codemodifié hors l'exemption explicite (rc=0quand les deux conditions sont réunies, sinon chemin nominal inchangé).Critère de clôture
#17691 passe
tag_requiredsans qu'une ligneGrain:soit ajoutée à son body.Tell respectés
Tell c.974 strict ★★★ (vérif first-hand avant action :
gh issue view #17691,git logsur les 1000 dernières PRs) · Tell c.1156 strict ★★ fondateur (tagGrain:première ligne) · Tell c.770 v3 strict fondateur (#PR-number vérifié : PR #17713 existe, references git log) · Tell c.1158 strict ★★ LIVRAISON RECENTE (sweep du pool avant claim, deux LIVRE-urn détectées et repostées en [RELEASED]).🤖 Generated with Claude Code