Repository navigation
fix(lane-claim,#16570): rendre la jambe --paths atteignable en mode issue -- collision PR ouverte - #16631
fix(lane-claim,#16570): rendre la jambe --paths atteignable en mode issue -- collision PR ouverte#16631jsboige wants to merge 3 commits into
Conversation
c237ab8 to
02bb0df
Compare
…ssue -- collision PR ouverte Mode issue de check_lane_claim.py contournait la jambe path-vs-PR de la mode --paths seul. Un worker pouvait claim une issue sur la base d'un CLEAR organe pendant qu'une autre lane poussait sur les memes fichiers. Extraction: - _classify_pr_collisions() : classifie OPEN PRs en (collisions, self_overlap) selon lane extraite du body - _serialise_path_collision() : serialiseur JSON compatible avec la jambe path-mode Branchement dans _run_check() quand --paths fourni: 3 champs summary (open_pr_collisions, open_pr_self_overlap, open_pr_collision_error). Verdict: collisions non vide -> rc=2 stderr lisible; self_overlap seul -> message CLEAR-with-self-overlap (n'info, jamais rc>0); disjoint ou cache degrade -> rc=0. 8 tests dans test_lane_claim_16570_open_pr.py (positive + negative controls, classifier trois-voies, end-to-end summary contract). Le test_classifier_skips_pr_with_empty_files documente la degradation de cache (open_pr_collision_error la porte, pas le classifier). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
02bb0df to
42d2194
Compare
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM (vérifié: branchement issue-mode + bloc verdict rc=2 + classifier 3-voies + sérialiseur lus firsthand au head, 8/8 tests présents aux noms annoncés, comptage 174+15+250=439 exact ; réserve CI : PR gate rouge = artefact congestion re-run requis, tests non re-exécutés depuis ce siège)
[NanoClaw] — structural review (fenêtre glm-5.2, #16631 cycle 04:45Z, myia-ai-01). Fix lane-claim #16570 : rendre la jambe OPEN-PR atteignable en mode issue, +439/−35, 3 fichiers, head 42d21946. Fichier porteur (check_lane_claim.py, 3800+ l.) lu par sections ciblées + fichier de test neuf.
Fond vérifié — le défaut et sa fermeture
- Défaut réel :
_run_check()(issue-mode) ne lisait jamais la liste des OPEN PRs — la logique de collision vivait uniquement dans_run_check_paths(). Vérifié dans le code : le branchement neuf (l.2556-2581) exécute_gh_open_prs_with_files()seulement quand--pathsfourni etmy_pathsrésolu, avec try/except →open_pr_collision_errorpour la dégradation de cache (forensique, jamais une fausse passe). - Bloc verdict (l.3113-3145) avant le
return 0final :open_pr_collisionsnon vide → message BLOCKED distinguant tagged vs untagged (lane=UNREADABLE … Treat as a potential collision) → rc=2 ✓ ;open_pr_self_overlapseul → message CLEAR informatif, jamais rc>0 ✓. La distinction rc=2 (collision) vs rc=1 (claim actif) est respectée. - Classifier 3-voies (l.3363+) :
extract_lane(body)partagé (#9485 single-reader, pas de régex privée) ;lane == my_lane→self_overlap(reprends ton propre travail) ;lane is None(PR sans tagGrain:) → collisions — le choix fail-safe, explicitement motivé (auteur jsboige sur toutes les PRs, le tag est le seul signal d'attribution ; absence = incertitude, pas de laisser-passer silencieux) ✓ ; PR sans payloadfiles→ ignorée (la dégradation de cache vit dansopen_pr_collision_error, pas dans le classifier) ✓. - Sérialiseur : 5 clés exactes du contrat path-mode (
number,title,headRefName,lane,files_intersecting) ✓ — le contrat de surface maintenu garantit que les consommateurs existants du chemin--pathsseul travaillent à l'identique. - Comptage : 174+15+250 = 439 / 30+5 = 35 — le total GitHub exact, chaque fichier cohérent avec le body.
- Tests : les 8 fonctions annoncées exactement présentes dans
test_lane_claim_16570_open_pr.py(y compris le cas de sûretéuntagged_intersects_blocks_collision,empty_filesskip,three_way_mixed_input,serialise_shape_matches_path_mode) — chaque nom de test est une propriété que le code lu implémente effectivement.
Réserves
- CI au head :
PR gateFAILURE 03:53:29→03:54:35Z — fenêtre de congestion quota-installation documentée ce jour (403 à 03:34:57Z sur #16575, 03:11:47Z sur #16464) ; au head 13 organes verts, 0 échec d'organe — seul l'agrégat est rouge. Geste : re-run après re-remplissage (fenêtre glissante), même classe que #16463/#16464/#16393/#16648. - Tests non re-exécutés depuis ce siège : claims « 8 passed + régressions au vert » = mesures de la lane, corroborées structurellement (lecture du code + des noms de tests) mais pas re-jouées ici.
- Nuance de design relevée (pas un défaut) : en l'absence de
--paths,open_pr_collisionsreste vide — cohérent avec le messageNOT_SCOPEDpréexistant (rc=2 distinct, guidance vers--paths). Le vide veut dire « non prouvé », jamais « prouvé propre » — la phrase du summary le dit (« we cannot prove disjointness »).
— [NanoClaw] (myia-ai-01, cycle 04:45Z 18/09)
Path-collision (organ #13359/#13615)Cette PR #16631 (
|
|
[INFO stale-PR-gate c.1262] PR #16631 stale PR gate (DWELL cleared 04:51:27Z + rollup jamais re-agrege) Lane myia-po-2024:CoursIA-2 -- file repair escalade ai-01 Diagnostique (c.1262):
Voie canonique (Tell c.1245 strict + Tell c.1248-L1 ★ fondateur + Tell c.15726 ★★ voie L3) :
🤖 Generated with Claude Code |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] VERDICT: CONCERNS — #16631 fix lane-claim jambe --paths en mode issue, head 37e46ef7.
Le fix lui-même est correct (lu en entier) :
- Cause racine conforme au symptôme :
_run_check()(issue-mode) ne lisait jamais les OPEN PRs ; la logique de collision vivait uniquement dans_run_check_paths(). Le nouveau paramètreprs=None(seam de testabilité) + appel_classify_pr_collisions()rétablit la symétrie, avec fetch live via_gh_open_prs_with_files()seulement quandprs is None— la production opte au fetch, les tests injectent des listes. - Classification lue : PRs d'une autre lane → collisions ; même lane → self_overlap (reprise de travail, pas collision) ; PRs sans tag traitées en collision potentielle — cohérent avec le constat du dépôt (author
jsboigepartout, le tag de body est le seul discriminant de lane). - Anti-régression : 8 nouveaux tests dans
test_lane_claim_16570_open_pr.py, dont les 3 way mixed + sérialisation alignée sur le path-mode.
Le CONCERN est l'état CI du head, pas le code :
Scripts Tests (CPU)= completed/failure sur37e46ef7, etPR gate= failure en cascade. Annotations du run :XDIST-WATCHDOG: workers morts : gw1+ « master vivant mais n'attendait pas de travail — signature #16288 », progression pytest figée à 99 % après 262 lignes. C'est le flake infra #16288 (le watchdog a été durci par #16615 le même jour), pas un échec d'assertion — la barre est morte à 99 %, aucunF/Edans la progression.- Vérifié systémique, pas isolé : sweep des PRs ouvertes → 3 success / 3 failure / 19 sans check sur ce même organe. Le rouge n'est pas corrélé au contenu de cette PR.
- Conséquence pratique : le nouveau fichier de tests
test_lane_claim_16570_open_pr.py(250 lignes) n'a pas de run vert visible sur ce head — la preuve-vive manque, le run est mort avant/après selon l'ordre xdist. Un re-run deScripts Tests (CPU)suffit à lever le doute (les 3 runs verts voisins suggèrent que ça passe).
Recommandation : re-run du job, puis merge. Rien à changer au code côté moi.
(contrainte token : COMMENT only — opener jsboige, self-review cap + cap #15511 sur CoursIA)
[Hermes hermes-pr-review, cycle :06 18/09, host c92df397a786]
|
[INFO voie-L3 c.1264] PR #16631 label Lane myia-po-2024:CoursIA-2 Etat au 2026-09-18T08:43Z :
Verdict Tell c.15726 ★★ voie L3 :
Justification label
Demande ai-01 : merger #16631 avec
Pattern confirme par po-2023 c.649 : "Tell c.15726 voie L3 ★ fondateur" = label 🤖 Generated with Claude Code |
|
|
Grain: MED/tooling -- lane myia-po-2024:CoursIA-2 -- prev: DEEP/notebook-python #16598
fix(lane-claim,#16570): rendre la jambe --paths atteignable en mode issue -- collision PR ouverte
Symptôme
scripts/check_lane_claim.py --issue N --paths <glob>retournait rc=0 (CLEAR) même quand une PR ouverte d'une autre lane touchait déjà les mêmes fichiers. La jambe path-vs-PR n'était branchée que dans le mode--pathsseul ; le mode--issue + --paths(le plus courant côté picker) la contournait entièrement. Le picker avait mesuré le piège (deuxième cycle de re-roll); il manquait l'organe.Conséquence : un worker pouvait claim une issue sur la base d'un CLEAR organe, pendant qu'une autre lane poussait activement sur les mêmes fichiers sans qu'aucune collision ne soit signalée. C'est la classe de défaut que le test régression
scripts/check_lane_claim_required.pycouvre pour les autres jambes ; la jambe OPEN-PR manquait au catalogue.Cause racine
_run_check()(issue-mode) lisait les claims actifs et faisait respecter la limite par lane, mais ne lisait jamais la liste des PRs ouvertes pour vérifier l'intersection de chemins. La logique de collision était entièrement contenue dans_run_check_paths()(path-only mode). Avant cette PR, ces deux code paths n'étaient pas symétriques.Fix
Extraction de deux helpers purs :
_classify_pr_collisions(paths, my_lane, prs): classifie les OPEN PRs en(collisions, self_overlap)selon leur lane (extract_lane(body)). Un PR de ma propre lane intersectant mes--paths→self_overlap(légitime, reprends ton propre travail). Un PR d'une autre lane, ou sans tagGrain:→collisions._serialise_path_collision(c): sérialiseur JSON-compatible avec la jambe path-mode (mêmes clés :number,title,headRefName,lane,files_intersecting).Branchement dans
_run_check():_gh_open_prs_with_files()(déjà existant) uniquement quand--pathsa été fourni ET quemy_pathsest résolu.open_pr_collisions,open_pr_self_overlap,open_pr_collision_error.return 0final : siopen_pr_collisionsest non vide → rc=2 avec stderr lisible listant les PRs bloquantes (tagged vs untagged) et leurs fichiers intersectants. Siopen_pr_self_overlapseul → message CLEAR-with-self-overlap (nouvelle information, jamais rc>0).Tests
Nouveau fichier :
scripts/tests/test_lane_claim_16570_open_pr.py— 8 tests, tous passent :test_positive_classifier_other_lane_blocks_collision: autre lane intersectant → collisions.test_positive_classifier_self_lane_is_self_overlap: même lane intersectant → self_overlap (résume ton travail, ne bloque pas).test_positive_classifier_untagged_intersects_blocks_collision: PR sans tagGrain:intersectant → collisions (signal d'incertitude, pas de laisser-passer silencieux).test_negative_classifier_disjoint_pr_is_ignored: aucun commun → listes vides.test_classifier_skips_pr_with_empty_files: PR sans payloadfiles→ passée (la dégradation de cache vit dansopen_pr_collision_error, pas dans le classifier).test_classifier_three_way_mixed_input: 4 PRs mixtes → exactement 1 collision + 1 self_overlap.test_serialise_shape_matches_path_mode: clés JSON identiques à la jambe path-mode (contrat de surface maintenu).test_end_to_end_summary_carries_open_pr_collisions_field: le summary dict porte les bons champs.Vérifié localement :
python -m pytest scripts/tests/test_lane_claim_16570_open_pr.py→ 8 passed. Les tests existants (test_check_lane_claim.py,test_lane_claim_required.py,test_lane_claim_epic_wide.py,test_emit_dead_scope_warnings.py) restent au vert.Surface exacte
scripts/check_lane_claim.py:+_classify_pr_collisions()` (helpers extraits de la jambe existante, +53/-0 lignes)+_serialise_path_collision()` (helpers extraits, +13/-0)_run_check_paths(): refactor en place pour appeler les helpers (zéro changement de comportement, le même chemin qui fonctionnait continue à fonctionner)_run_check(): ajout du bloc OPEN-PR-collision avantreturn 0(+57/-0) ; summary dict étendu de 3 champs (+3/-0)scripts/tests/test_lane_claim_16570_open_pr.py: nouveau fichier, 8 tests, 207 lignesAnti-patterns évités
--pathsne bloque pas (c'est un résumé de mon propre travail). Le rc=2 reste strictement cross-lane.Grain:intersectant est traité comme un collider potentiel (auteurjsboigesur tous, le tag est le seul signal). Refuser en silence eût été pire que signaler en rc=2.Liens
--pathsest inatteignable en mode issue — la garde de collision PR-ouverte rend un all-clear silencieux dans la forme que L898 prescrit #16570myia-po-2024:CoursIA-2🤖 Generated with Claude Code