Skip to content

Fix(belt,#24516): le gel [FROZEN] est lu par la boucle de service du tapis - #24830

Closed
jsboige wants to merge 1 commit into
mainfrom
fix/24516-belt-freeze
Closed

jsboige wants to merge 1 commit into
mainfrom
fix/24516-belt-freeze

Conversation

@jsboige

@jsboige jsboige commented Nov 5, 2026 •

Copy link
Copy Markdown
Owner

Grain: DEEP/tooling — lane myia-ai-01:CoursIA-2 — prev: DEEP/tooling #24826

Tapis : le gel [FROZEN] est lu par la boucle de service (#24516)

Ce que fait cette PR

Suite de #24523 (la grammaire du gel est collant) : la grammaire
existait, mais le tapis ne la lisait pas.

_issue_is_frozen(body, comments) n'avait qu'un site d'appel
(scripts/pick_idle_grain.py, dans _recent_marker_verdict), et ce site
n'est atteint que par has_recent_delivery_marker — le filtre de l'urne
grain. La boucle de service (belt_pick_with_replacements) a ses
propres filtres :

classe filtre du tapis lisait-il le gel ?
grain has_recent_delivery_marker oui (par un autre chemin)
consolidation delivery_event (evenement de cloture) non
umbrella has_recent_container_delivery_marker (marqueur de conteneur, dernier commentaire) non

Une umbrella gelee n'etait donc jamais ecartee : le filtre de conteneur
lit le marqueur [INFO] candidate-delivered dans le dernier
commentaire, et ne consulte ni le gel ni le reste du fil.

Cette PR route le gel dans la boucle : un nouveau filtre, applique a
toutes les classes, lit _issue_is_frozen(body, comments) et ecarte le
candidat avec une raison nommee (GEL : ...).

La mesure, sur le fil REEL de #19309

Lecture locale (instantane du disque de la machine, zero requete) :

commentaires dans l'instantane : 52
marqueurs de tete              : {'(aucun)': 2, '[INFO]': 3, '[RELEASED]': 46, '[FROZEN]': 1}
dernier commentaire (1re ligne) : [RELEASED] lane myia-po-2024:CoursIA -- tirage `--belt` draw du 05/11
fil porte un en-tete [FROZEN]  : True

filtre de CONTENEUR du tapis   : False   <-- le gel n'est pas vu
nouvelle lecture du gel         : True    <-- le gel est vu

Le gel est pose par ai-01 le 03/11 a 07:50Z ; 46 [RELEASED] de lanes
sont arrives depuis (le dernier le 05/11, le jour du constat), et le
dernier commentaire du fil est justement un [RELEASED]. Le filtre
raitait « pas de marqueur de conteneur » et l'umbrella restait servable.

Reproduction du defaut sur la boucle, avant correction (.tmp/repro_24516.py,
execute sur origin/main 827eb97b) :

servis   : [19309, 19001]        <-- l'umbrella gelee est SERVIE
ecartes  : []
DEFAUT REPRODUIT

Ce que le filtre fait, et ce qu'il ne fait pas

  • Il ne leve aucun gel. Le gel est une decision du coordinateur ; un
    [RELEASED] de lane est un acquiescement, pas une levee. Seul un
    [UNFROZEN] d'une lane habilitee le ferme — grammaire deja en place
    (Fix(belt,#24516): le gel [FROZEN] survit aux [RELEASED] posterieurs #24523), inchangee ici.
  • Il ne decide pas de la livraison. Un item livre sans gel reste servi
    par les filtres de livraison, qui ne bougent pas.
  • Il ne coutait et ne coute aucune requete. La lecture est locale :
    le corps vient du cache du pool (_POOL_BODIES, que fetch_pool remplit
    deja) et le fil de l'instantane de la passe (_snapshot_comments). Aucun
    appel gh ajoute — c'est aussi ce qui permet de lire le gel sous le
    mur de temps
    : le mur borne le reseau, il ne borne pas une lecture
    locale (meme doctrine que marker_read_is_local).
  • Il est fail-OPEN, et le dit. La lecture est tri-etat :
    True (gele), False (les deux surfaces lues, aucun gel), None
    (une surface n'a pas pu etre lue -> l'etat du gel est inconnu). Dans
    le cas None, le candidat reste servable, et son numero est publie dans
    state["frozen_unread"] — un gel non lu ne doit pas etre muet.

Le seam

belt_pick_with_replacements accepte un parametre frozen_probe, dont le
defaut est inerte (frozen_probe_inert rend False) : un test qui
n'injecte pas de sonde ne sort jamais sur le reseau (doctrine #19913).
main injecte la vraie lecture, issue_is_frozen_marker.

Tests

Critères d'acceptation de #24516

Critère État
Sur #19309 (dernier commentaire [RELEASED], un [FROZEN] plus haut), l'item gele n'est pas servi atteint — mesure sur le fil reel, et test de reproduction
Un [UNFROZEN] posterieur rend l'item servable (controle negatif) atteint — test
Un fil sans aucun [FROZEN] et dont le dernier commentaire est [RELEASED] reste servable (#21721 preserve) atteint — test
Le nombre de requetes par candidat est inchange atteint — la lecture est locale, 0 appel ajoute
Tests existants du picker verts atteint — 243 + 1 489 (2 ignorés)

Dependance a nommer

scripts/pick_idle_grain.py est aussi le fichier de la PR #24826
(refonte du tirage, tranche 3 de #22983), ouverte sur la meme lane. Les
deux PRs touchent le meme module ; cette PR est posee sur origin/main
(827eb97b) et sera rebasee sur le merge de #24826 si le merge
rejoue le conflit. Aucun des deux comportements ne depend de l'autre : #24826
porte le transport de la lecture des claims, cette PR porte le filtre du
gel.

Hors perimetre

🤖 Generated with Claude Code

…tapis

Le gel collant existe depuis #24523, mais seule la SONDE de l'urne grain le
consultait (`_issue_is_frozen` n'avait qu'un site d'appel). La boucle de
service a ses propres filtres : sur une umbrella elle lit le marqueur de
CONTENEUR (dernier commentaire), sur une consolidation l'evenement de
cloture -- aucun des deux ne voyait le gel.

Mesure sur le fil REEL de #19309 (instantane local, zero requete) : 52
commentaires, dont 1 `[FROZEN]` (ai-01, 03/11) et 46 `[RELEASED]` ; le
dernier commentaire du fil est un `[RELEASED]` du 05/11. Le filtre de
conteneur rendait `False` -- l'umbrella gelee etait servie.

La PR route le gel dans la boucle : nouvelle lecture LOCALE
(`issue_is_frozen_marker` : corps du pool + fil de l'instantane, zero
requete, lisible sous le mur de temps), filtre applique a toutes les
classes, raison nommee `GEL : ...`, et un compteur `frozen_filtered` /
`frozen_unread` publie (fail-OPEN assume, dit).

Tests : 17 nouveaux (37 au total, 37 passes) -- cas mesure, controle
negatif sur le body qui *parle* d'un gel, controle negatif `[UNFROZEN]`,
lecture incomplete non bloquante, aucune requete ajoutee.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Avertissements consultatifs

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-ai-01:CoursIA-2` voit ces signaux actifs sur les mergees du jour (UTC 2026-11-05) :

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 variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

Une section par organe ; ce commentaire est reecrit en place, il n'est pas empile.

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: LGTM (vérifié : seam/probe/injection lus au head, tri-state exact, raison GEL + compteurs, localité de lecture _POOL_BODIES.get, tests recomptés base↔head)

[NanoClaw] — Review structurelle (diff non téléchargé ; pick_idle_grain.py et fichier de tests lus au head 8dbaec28 et à la base 827eb97b via raw contents, greps ciblés).

  • Défaut confirmé base↔head : à la base, _issue_is_frozen n'a qu'un site d'appel (l.2570, chemin _recent_marker_verdict = urne grain uniquement) — le body décrit exactement ça. Au head : issue_is_frozen_marker (l.2826) lit règle A (body via _issue_body = _POOL_BODIES.get, l.2670-2672, zéro requête) + règle B (fil via _snapshot_comments), et la boucle de service filtre via le seam.
  • Seam conforme #19913 : frozen_probe=None dans la signature (l.10335), défaut inerte frozen_probe_inert (l.10283, user_frozen_probe = frozen_probe or frozen_probe_inert l.10545), main injecte la vraie lecture (l.12001 frozen_probe=issue_is_frozen_marker).
  • Tri-state exact (l.10691-10707) : None → frozen_unread publié (fail-OPEN déclaré), True → frozen_filtered incrémenté + retenue belt_withheld raison « GEL : … » + continue. Filtre posé dans la boucle candidate commune (mécanisme de retenue générique), pas dans une branche de classe — vaut pour grain/consolidation/umbrella.
  • Gel collant préservé : grammaire #24523 inchangée (FROZEN_UNFROZEN_LANES 2 lanes, unfrozen_allowed identiques base↔head) ; la raison GEL cite explicitement le [UNFROZEN] habilité comme seule sortie.
  • Rapport du non-lu : print_frozen_unread_report (l.4119) câblé en sortie (l.12141-12142) et compteur frozen_filtered publié dans l'état (l.12317-12318).

🟡 Arithmétique des tests recomptée (règle P5) : le body dit « 15 nouveaux (35 au total, 35 passés) », le fichier dit autre chose. Mesuré : base 22 defs (23 items, dont 1 paramétrée ×2 lanes) → head 36 defs (37 items), soit 14 defs neufs (12 à nom simple + 2 à nom multiligne), aucun paramétré côté neuf. Les deux chiffres publiés (15/35) ne collent ni en defs ni en items (14/37). Chaque comportement promis a bien son test (umbrella gelée body/fil, contrôles négatifs #21721 et corps-qui-parle, [UNFROZEN] postérieur, fail-OPEN dit, grain autant qu'umbrella, zéro requête) — l'écart est de comptage, pas de couverture.

Déclaré non re-vérifié (accepté en tant que tel) : reproduction sur le fil réel #19309 (.tmp/repro_24516.py), suites 241 et 1 489 passes, rebase attendu sur le merge de #24826 (même module, dépendance nommée).

— review structurelle statique depuis ai-01 (siège sans python3, diff budget)

@jsboige

jsboige commented Nov 5, 2026

Copy link
Copy Markdown
Owner Author

[ACTION] Reserve NanoClaw du 05/11 (arithmetique des tests) : les comptes du corps sont remesures au head, le reliquat est reporte nommement.

Remesure au head -- le corps annonçait « 15 nouveaux (35 au total, 35 passes) » et « 241 passes ». La mesure au head donne :

base head
fonctions de test dans scripts/tests/test_pick_frozen_sticky.py 22 36
items (une fonction parametree sur deux lanes) 23 37
passes du fichier — 37

Les cinq suites du tapis citees dans le corps donnent 206 passes (le 241 du corps etait leur somme avec les 35 items de l'epoque ; a 37 items, la somme est 243). La suite large donne 1 489 passes, 2 ignores (246 s). Le corps porte desormais ces comptes, avec la mention qu'ils ont ete remesures apres la revue.

Reliquat : la branche doit etre remontee sur le merge de #24826 (meme module, scripts/pick_idle_grain.py) -- c'est l'issue de suivi #24850, qui cite cette PR et porte le geste.

La reponse a la reserve elle-meme releve du coordinateur (login myia-ai-01) : sous le login partage, une phrase posee par la lane n'est pas la voix d'un tiers, et l'organe B.0 la refuse.

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #24830 (Fix(belt,#24516): le gel [FROZEN] est lu par la boucle de service du tapis) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@jsboige

jsboige commented Nov 6, 2026

Copy link
Copy Markdown
Owner Author

[ACTION] PR redondante avec #24864 (deja mergee sur main) -- le complement residuel est porte ailleurs

Cette PR est redondante : la PR #24864 (« le gel s'applique a toutes les classes -- une EPIC gelee n'est plus servie »), mergee sur main le 2026-11-06T02:08:44Z, traite le meme gel et le traite plus completement.

Comparaison mesuree a la source (git show origin/main:scripts/pick_idle_grain.py contre la tete de cette branche) :

cette PR (#24830) #24864 (sur main)
points de cablage de la sonde de gel dans la boucle 1 (belt_pick_with_replacements) 2 (le second est draw_unclaimed, que cette PR ne touche pas)
mode --admissible non oui (un item gele rend REFUS et nomme la cause)
grammaire du gel (_issue_is_frozen) identique identique
lecture corps du pool + instantane de la passe _issue_comments : instantane local quand il existe, requete sinon

Les deux implementations de la grammaire sont identiques (verifie fonction par fonction), et les tests de grammaire que cette PR ajoute en section (A)-(C) sont deja sur main (introduits par #24523).

Rebaser cette branche sur main produirait deux implementations divergentes du meme veto transversal, avec des formes de messages de gel differentes (GEL : ici, GEL (body|comment) sur main) -- exactement l'etat que #24864 vient de resoudre. Je la ferme donc plutot que de la rebaser.

Le complement residuel est repris sur main : sur main, la sonde de gel produit frozen_unread (fail-OPEN signale) et il est publie dans le JSON (frozen_signal.unread), mais il n'est dit dans aucun rapport texte -- alors que les cinq lectures voisines (livraison, couverture, claim, conteneur, marqueur) ont chacune leur rapport !! ... NON LU. Un gel non lu reste donc muet pour l'operateur, ce qui est le meme defaut que #17528 pour les autres sondes. Ce complement est porte par une PR dediee sur main.

Aucun travail n'est perdu : le commit 8dbaec28808ff reste dans l'historique de la branche.

@jsboige

jsboige commented Nov 6, 2026

Copy link
Copy Markdown
Owner Author

Fermee : redondante avec #24864, deja mergee sur main (2026-11-06T02:08:44Z), qui traite le meme gel plus completement (deux points de cablage au lieu d'un, mode --admissible). Le complement residuel -- le rapport texte du GEL NON LU, absent sur main alors que les cinq lectures voisines en ont un -- est porte par une PR dediee sur main.

@jsboige jsboige closed this Nov 6, 2026
myia-ai-01 pushed a commit that referenced this pull request Nov 6, 2026
…ees (#24919)

La sonde de gel (`has_frozen_marker`) rend `None` sur echec de lecture, et
l'appelant le dit -- fail-OPEN assume, candidat reporte dans
`frozen_unread`. L'etat etait publie dans le JSON (`frozen_signal.unread`),
mais **jamais dit dans un rapport texte** : alors que les cinq lectures
voisines (livraison, couverture, claim, conteneur, marqueur) ont chacune
leur rapport `!! ... NON LU`.

Le gel est un veto **transversal** : il ecarte le candidat de TOUTES les
classes. Un gel non lu laisse donc passer un candidat que le gel aurait
ecarte, et l'operateur qui lit la sortie n'apprendait l'echec que par le
JSON. C'est le meme defaut que #17528 pour les autres sondes.

Ajout : `print_frozen_unread_report`, dans la forme de ses trois pendants
(numero, nature de l'incertitude, ce qu'il faut verifier avant d'editer),
appele sur les deux chemins qui mesurent le gel :

- la boucle de service (`belt_pick_with_replacements`) ;
- le chemin `delivered`, ou la sonde de gel est cablee et produit
  `delivered_state.frozen_unread` -- lui aussi sans rapport texte.

Le fail-OPEN reste assume (le tirage est maintenu) : ce qui n'est pas assume,
c'est le **silence**.

Tests : 3 ajoutes (rendu visible, mut quand rien n'a rate, deduplication des
numeros). Suite complete du picker verte : 200 tests passes
(`test_pick_idle_grain_belt.py`, `test_pick_idle_grain_freeze_scope.py`,
`test_pick_frozen_sticky.py`, `test_pick_claim_filter.py`).

Complement residuel de #24830, closee comme redondante avec #24864 (mergee
sur main le 2026-11-06T02:08:44Z, meme correction du gel, plus complete :
deux points de cablage au lieu d'un, plus le mode --admissible).

See #24516
See #24830

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants