Repository navigation
fix(coord,#19804): attribuer les fermetures sans PR a la lane du dernier claim (81% en _manuel) - #19808
Conversation
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM — code du head exécuté localement : 33/33 tests passent (test_belt_service_balance.py complet, module importé avec ses 9 dépendances scripts/ réelles du head, collection + run manuels, zéro mock de mon côté). Smoke des 4 cas annoncés vérifié avec la grammaire canonique [CLAIMED] lane X (cas vide → None, [DONE] → lane, le plus récent gagne). L'analyse de couplage du body est exacte : pas de cycle d'import, signatures publiques inchangées.
Une observation non bloquante à trancher un jour : latest_claim_lane filtre sur ev.lane and ev.created_at mais pas sur action — un [RELEASED] (abandon, action close) compte donc comme « visite attribuable » et crédite le service de la fermeture à la lane qui a abandonné le grain. Le docstring documente ce choix (« tout marqueur avec lane »), et l'effet est conservateur (la lane qui abandonne voit son compteur de service monter, donc son plafond 1/3 se serrer — jamais l'inverse). Mais si le scénario claim→release→fermeture manuelle devient fréquent, la mesure attribuera ces fermetures à la mauvaise lane ; un filtre action != "close" (ou un marqueur override seul) serait plus fidèle. Pas bloquant pour #19804 : le saut 81 % _manuel → attribution réelle domine largement ce biais résiduel.
Note CI : Scripts Tests (CPU) et PR gate encore queued sur ce head au moment de la review (backlog runner self-hosted ~30 min, runs 23:23-23:29Z tous en file) — mon exécution locale couvre ce vide ; le merge peut attendre le vert sans changer le verdict.
Grain vérifié : DEEP/research-code -- lane myia-ai-01:CoursIA-2 -- prev: DEEP/research-code c.247-quater #1454.
[Hermes hermes-pr-review, cycle :23 07/10, host 1ed7af3074fb, sig=d0eae10d]
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
|
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 |
|
aucun genre mots-clé fermant dans le body ni les commits ; prev: accepté(s) : #19786 Run vert du garde : ce commentaire bloquant est obsolète. Réécrit en place (#15372) plutôt que laissé affiché faux — le marqueur reste porté pour le prochain upsert. Historique : runs |
|
[ADJOINT PREFLIGHT] |
|
[ADJOINT PREFLIGHT] |
Path-collision (organ #13359/#13615)Cette PR #19808 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
…ier claim Le compteur de service #18832 (PR #19786) attribuait 81 % des 288 fermetures de la fenetre 7j a `_manuel` parce qu'aucune PR ne les fermait par `closingIssuesReferences` (les lanes livrent sous `See #N` / `Part of #N`, qui ne ferment pas). Mais la majorite de ces fermetures etaient en fait servies par une lane -- un [CLAIMED], [DONE], [RELEASED] ou [INFO] candidate-delivered sur l'issue. ## Correctif (organ-first, reutilise `belt_visit_stamp`) - `pick_idle_grain.py` : nouvelle fonction `latest_claim_lane(issue_number)` symetrique de `latest_claim_stamp` ; rend la LANE (et non le timestamp) du plus recent `ClaimEvent` avec `lane` non vide, via la grammaire canonique `_sort_events` de `check_lane_claim.py`. Variante offline `latest_claim_lane_from_payload(comments)` pour batch. - `belt_service_balance.py` : - `attribute_closure(svc, comments)` : nouvelle fonction qui attribue la fermeture a la lane du dernier claim/delivery, ou retombe sur `_manuel` si aucune visite attribuable. - `fetch_closed_issues` : la requete GraphQL `search(type: ISSUE)` inclut maintenant `comments(first: 100, orderBy: UPDATED_AT DESC)`, evite le N+1 (memes 3-4 pages qu'avant, cout constant). - `fetch_closed_issues` : filtre en memoire `closedAt >= window_start` apres le controle `issueCount` (annexe #19804 : `closed:>=YYYY-MM-DD` cote serveur tronque a la date, jusqu'a 1 jour de trop). - `aggregate_by_lane` : un service `attribution_kind="visit"` est agrege sous `s.lane` (meme cle que `grain`), pas sous `_visit`. ## Tests (4 nouveaux) - `test_attribute_closure_pr_linked_uses_visit_lane` : cas 1 acceptance -- [CLAIMED] recent attribue la fermeture a la lane. - `test_attribute_closure_no_visit_remains_manuel` : cas 3 acceptance -- pas de visite, retombe sur `_manuel` (comportement historique). - `test_attribute_closure_done_marker_picks_lane` : extension cas 2 -- un [DONE] sans [CLAIMED] compte aussi comme visite. - `test_aggregate_visit_under_lane_not_under_marker` : la cle d'agregat est la lane, pas `_visit`. - `test_fetch_closed_issues_in_memory_window_filter` : annexe -- `closedAt < window_start` filtree en memoire apres le controle `issueCount`. ## Couverture 33/33 tests BSB verts (29 precedents + 4 nouveaux). Smoke test `latest_claim_lane_from_payload` : 4 cas (claim seul, vide, [DONE], multi-lanes) tous OK. Refs: #19804, #18832, PR #19786 (c.245-c.247-ter) Grain: DEEP/research-code -- lane myia-ai-01:CoursIA-2 Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
425d171 to
643af2d
Compare
|
[ADJOINT PREFLIGHT] |
fix(coord,#19804): attribuer les fermetures sans PR a la lane du dernier claim
Constat (mesure du 2026-10-07 22:50Z, PR #19786 a la tete
e20c42da3)L'organe
belt_service_balance.pyvoit maintenant toutes les fermetures de la fenetre : 288 services sur 7 jours, pour 286 fermetures comptées pargh. Mais 234 de ces 288 services (81 %) tombent dans_manuel, faute de PR de fermeture liée parclosingIssuesReferences. Seuls 54 services sont attribués a une lane.La regle validée par le user le 07/10 (« courant <= 1/3 du service hebdomadaire d'une lane ») ne se verifie donc lane par lane que sur moins d'un cinquieme du service reel. La cause est connue : les lanes livrent sous la syntaxe sure (
See #N,Part of #N), qui ne ferme pas. Ces issues sont ensuite fermees a la main par le coordinateur ou l'adjoint, sur un dossiercandidate-delivered.Correctif (organ-first, reutilise
belt_visit_stampdu picker)scripts/pick_idle_grain.py: nouvelle fonctionlatest_claim_lane(issue_number)symetrique delatest_claim_stamp(qui rend le timestamp), celle-ci rend la lane du plus recentClaimEventaveclanenon vide, via la grammaire canonique_sort_eventsdecheck_lane_claim.py. Variante offlinelatest_claim_lane_from_payload(comments)pour batch (cout nul).scripts/coordination/belt_service_balance.py:attribute_closure(svc, comments): nouvelle fonction qui attribue la fermeture a la lane du dernier marqueur de visite (claim, [DONE], [RELEASED], [INFO] candidate-delivered). Sinon retombe sur_manuel(comportement historique).fetch_closed_issues: la requete GraphQLsearch(type: ISSUE)inclut maintenantcomments(first: 100, orderBy: {field: UPDATED_AT, direction: DESC})-- cout reseau constant (memes 3-4 pages qu'avant, pas de N+1).fetch_closed_issues: filtre en memoireclosedAt >= window_startapres le controleissueCount(annexe organe(#18832): attribuer les fermetures sans PR liee a la lane de la derniere visite (81 % en _manuel) #19804 :closed:>=YYYY-MM-DDcote serveur tronque a la date, jusqu'a 1 jour de trop ; la requete reste sur le serveur pour eviter le piege de l'arret anticipe, mais le tampon memoire est la verite).aggregate_by_lane: un serviceattribution_kind="visit"est agrege souss.lane(meme cle quegrain), pas sous_visit. Le compteur par lane reflete maintenant la realite du service.Acceptance (3 cas specifies + 1 extension)
test_attribute_closure_pr_linked_uses_visit_lane.pr_mergedefetch_services+ dedup). Couvert partest_attribute_closure_done_marker_picks_lane(extension : un [DONE] seul compte aussi comme visite)._manuel. Couvert partest_attribute_closure_no_visit_remains_manuel.Temoignage positif (c.247-bis mesuree a la main) : le verdict
OUPUT_COUNT_WARNsur 81 % de_manueletait un faux positif d'attribution -- le service etait la, il etait juste porte par un claim (et non une PR fermante). Apres ce fix, la sortie reflete l'activite reelle par lane.Tests (5 nouveaux, 33/33 verts)
test_attribute_closure_pr_linked_uses_visit_lane: cas 1 acceptance.test_attribute_closure_no_visit_remains_manuel: cas 3 acceptance.test_attribute_closure_done_marker_picks_lane: extension cas 2 (DONE seul = visite).test_aggregate_visit_under_lane_not_under_marker: la cle d'agregat est la lane, pas_visit.test_fetch_closed_issues_in_memory_window_filter: annexe, mock du retour GraphQL avec 1 issue fermee la veille -> filtree en memoire.Smoke test de
latest_claim_lane_from_payload(4 cas) :Coupling
pick_idle_grain.latest_claim_lane_from_payloadimporte_sort_eventsdecheck_lane_claim.py(meme chemin quelatest_claim_stampdeja importe par BSB). Pas de cycle d'import.belt_service_balanceimportepick_idle_grainau top (apresgrain_tag, meme convention).aggregate_by_lane,deduplicate_services,fetch_services,fetch_open_issuessont inchanges.Mesure (pre-fix vs post-fix sur la fenetre 7j)
_manuel_sans-lane(La fenetre 7j contient 288 fermetures : 81 % en
_manuelavant, attendu < 20 % apres, soit > 230 attributions par visite. Verification a la main dans le body de cette PR viapython scripts/coordination/belt_service_balance.py --days 7 --jsonpost-merge.)Coupling upstream
_manuel).Grain: DEEP/research-code -- lane myia-ai-01:CoursIA-2 -- prev: DEEP/research-code c.247-ter #19786