Observation (mesure firsthand, 2026-09-13)
Un [RELEASED] de réconciliation sur #15798 (po-2026, 04:50:09Z) a été attribué à la lane citée au lieu de la lane libérante. Conséquence mesurée : lane_claim_required.py rend
{"guard_pass": false, "reason": "#15798: lane myia-po-2026:CoursIA holds an active claim (since 2026-09-13T04:25:31Z)"}
…et bloque la PR #15878 (Closes #15798) alors que po-2026 a explicitement libéré le grain (sa PR #15914 fermée superseded) 34 secondes avant le push.
Reproduction
import check_lane_claim as clc
comment = {'body': '[RELEASED] Claim de myia-po-2026:CoursIA retiré — réconcilié : la PR #15878 (lane myia-po-2023:CoursIA, ouverte 00:19Z) couvre le grain en surensemble.', 'author': {'login': 'jsboige'}, 'createdAt': '2026-09-13T04:50:09Z'}
print(clc._parse_claim_events(comment))
# → marker: RELEASED | action: close | lane: myia-po-2023:CoursIA ← FAUX
Cause racine
grain_tag.extract_lane (celle du #10395 Variante 1) teste dans cet ordre :
- primaire
_LANE_RE = lane\s*:?\s+<token> (mot-clé lane exigé) — sur la ligne, puis sur le body entier ;
- fallback
_LANE_FALLBACK_RE = token nu — sur la ligne de marker seulement.
Dans la ligne du marker, le token du sujet (« Claim de myia-po-2026:CoursIA retiré ») est nu (pas de mot-clé devant), tandis que la citation de l'autre lane (« (lane myia-po-2023:CoursIA, ouverte 00:19Z) ») porte le mot-clé. Le primaire matche la citation → le close est attribué à la lane citée (no-op si elle n'a pas de claim), le claim du sujet reste OPEN.
Pourquoi c'est structurel
Une réconciliation de collision mentionne par nature la lane gagnante — souvent au format « lane X » (le format des claims eux-mêmes). Tout [RELEASED]/[DELIVERED] de réconciliation dont le propre token est nu est donc à risque d'attribution croisée. Le cas #15864 (point final, PR #15866) est un bug voisin de la même fonction mais distinct (résidu de période dans le token vs ordre primaire/fallback).
Fix proposé
Dans extract_lane, quand marker_line est fourni : si un token nu matche sur la ligne avant le token du premier match mot-clé de la même ligne (comparaison sur start(1) du groupe token, pas sur le début du mot-clé), le token nu prime — proximité au marker = intention du rédacteur (#10881 étendu au conflit primaire/fallback). Égalité de position (le nu EST le token keyworded) → primaire, comportement inchangé.
Observation (mesure firsthand, 2026-09-13)
Un
[RELEASED]de réconciliation sur #15798 (po-2026, 04:50:09Z) a été attribué à la lane citée au lieu de la lane libérante. Conséquence mesurée :lane_claim_required.pyrend{"guard_pass": false, "reason": "#15798: lane myia-po-2026:CoursIA holds an active claim (since 2026-09-13T04:25:31Z)"}…et bloque la PR #15878 (
Closes #15798) alors que po-2026 a explicitement libéré le grain (sa PR #15914 fermée superseded) 34 secondes avant le push.Reproduction
Cause racine
grain_tag.extract_lane(celle du #10395 Variante 1) teste dans cet ordre :_LANE_RE=lane\s*:?\s+<token>(mot-clélaneexigé) — sur la ligne, puis sur le body entier ;_LANE_FALLBACK_RE= token nu — sur la ligne de marker seulement.Dans la ligne du marker, le token du sujet (« Claim de myia-po-2026:CoursIA retiré ») est nu (pas de mot-clé devant), tandis que la citation de l'autre lane (« (lane myia-po-2023:CoursIA, ouverte 00:19Z) ») porte le mot-clé. Le primaire matche la citation → le close est attribué à la lane citée (no-op si elle n'a pas de claim), le claim du sujet reste OPEN.
Pourquoi c'est structurel
Une réconciliation de collision mentionne par nature la lane gagnante — souvent au format « lane X » (le format des claims eux-mêmes). Tout
[RELEASED]/[DELIVERED]de réconciliation dont le propre token est nu est donc à risque d'attribution croisée. Le cas #15864 (point final, PR #15866) est un bug voisin de la même fonction mais distinct (résidu de période dans le token vs ordre primaire/fallback).Fix proposé
Dans
extract_lane, quandmarker_lineest fourni : si un token nu matche sur la ligne avant le token du premier match mot-clé de la même ligne (comparaison surstart(1)du groupe token, pas sur le début du mot-clé), le token nu prime — proximité au marker = intention du rédacteur (#10881 étendu au conflit primaire/fallback). Égalité de position (le nu EST le token keyworded) → primaire, comportement inchangé.