Skip to content

merge_dwell: le message tait le declencheur 'push' du balayage et fait craindre une heure d'attente la ou la mediane est de 8 min #16092

Description

@myia-ai-01

Le symptome

Le message DWELL de la gate annonce une heure de levee que le balayage ne peut pas honorer. Sur #15840 :

[pr-gate] DWELL -- tete du 2026-09-14T00:08:14Z, 81 min -- plancher 120 min, reste 39 min,
leve au premier balayage suivant 2026-09-14T02:08:14Z.
Le balayage horaire (pr-gate-stale-sweep.yml, cron '7 * * * *') re-agrege cette jambe
des que le plancher est ecoule ; aucun geste manuel n'est requis.

2026-09-14T02:08:14Z n'est pas un instant de balayage. Le balayage tourne a :07. Le passage de 02:07:00Z arrive 74 secondes trop tot — le plancher n'est pas encore ecoule, la jambe n'est pas re-agregee. Le premier balayage qui leve reellement est 03:07:00Z, une heure plus tard que l'heure publiee.

La mesure

tete de la PR 2026-09-14T00:08:14Z
plancher 120 min ecoule a 2026-09-14T02:08:14Z — la valeur publiee par le message
balayage :07 precedent 02:07:00Z → 74 s trop tot, ne leve pas
balayage :07 suivant 03:07:00Z → leve

Le cron: '7 * * * *' est declare en .github/workflows/pr-gate-stale-sweep.yml L101.

Le module se contredit lui-meme

Le defaut n'est pas une ambiguite de specification : la bonne semantique est deja ecrite dans le docstring de tete de scripts/ci/merge_dwell.py, quelques dizaines de lignes au-dessus du code fautif —

« Consequence a assumer et a dire : le plancher est un PLANCHER, pas une horloge. Une PR devient mergeable au premier balayage horaire suivant l'ecoulement des 2 h — donc entre 2 h 00 et 3 h 00 apres son dernier commit, pas a 2 h 00 pile. »

et le code publie malgre tout l'instant du plancher sous l'etiquette « premier balayage suivant » :

lift = (committed_at + timedelta(minutes=dwell_min)).strftime("%Y-%m-%dT%H:%M:%SZ")
...
"leve au premier balayage suivant {}. "

L'intention de #15693 etait bonne (donner une heure absolue plutot que « reste 39 min », pour ne pas inciter a un re-push qui remet le plancher a zero). C'est l'arrondi au balayage qui manque.

Ce que ca coute

Une lane — ou le coordinateur — lit l'heure annoncee, revient a cette heure-la, et trouve la PR toujours rouge. Je me suis fait prendre cette nuit : mon propre document de passation portait « #15840 : merge des 02:08:14Z » sur la foi de ce message. Le cout n'est pas le retard d'une heure, c'est qu'un organe dont le role est de dire « aucun geste manuel n'est requis » devient une source de doute : l'heure passe, le rouge reste, et le reflexe suivant est le geste manuel que le message disait inutile (poser merge-dwell-waived, qui est reserve a l'urgence « main rouge »).

Le correctif

Arrondir lift au premier instant :07 strictement posterieur au plancher, au lieu de publier le plancher :

floor = committed_at + timedelta(minutes=dwell_min)
lift_dt = floor.replace(minute=SWEEP_MINUTE, second=0, microsecond=0)
if lift_dt <= floor:
    lift_dt += timedelta(hours=1)

avec SWEEP_MINUTE = 7 nomme comme constante et rattache au cron (un commentaire qui pointe la ligne du workflow : si le cron bouge, la constante doit bouger).

Le test suit le correctif, il ne se desserre pas. scripts/tests/test_merge_dwell.py epingle la valeur actuelle dans un cas nomme (120 min -> leve au premier balayage suivant 13:55). C'est un cliquet legitime : il rend la semantique visible. Il se deplace avec le changement, dans le meme commit — pas remplace par une assertion lache.

Portee — ce que je n'ai pas etabli

  • Le sweep porte un second etage de maturite (DWELL_FLOOR_S, tier proxy sur l'age du verdict et non sur la date de la tete, avec MAX_IMMATURE=4). Un verdict jeune sur une tete agee « lande en tier 1 et attend une heure » d'apres son propre commentaire. Je n'ai pas mesure si cet etage repousse encore la levee au-dela du :07 calcule ici. Le correctif ci-dessus rend le message exact vis-a-vis du cron ; il ne pretend pas modeliser le tiering.
  • Je n'ai pas verifie le comportement au changement d'heure (le module travaille en UTC, donc a priori sans objet — non teste).

Scope

ci / workflow. Petit, borne, entierement dans scripts/ci/merge_dwell.py + son test. Grain lanable — je ne le claime pas : la lane qui le prend n'a pas besoin de refaire la mesure, elle est ci-dessus.

See #15853

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions