Repository navigation
Fix(lane-claim,#22445): la clause paths: d'un [DELIVERED] est honoree - #22457
Conversation
`_PATHS_CLAUSE_RE` enumerait `CLAIMED-AMEND|CLAIMED|RELEASED|OVERRIDE` et omettait `DELIVERED`. La clause etait donc acceptee sans erreur et ignoree : le marqueur retombait en epic-wide. Le defaut n'etait pas cosmetique, parce que le reducteur v2 re-marque un `[DELIVERED]` en **occupation active** tant que sa PR est OPEN ou MERGED (`_resolve_delivered_v2`). Une livraison bornee devenait donc une occupation epic-wide : le geste que `lane-claim-protocol.md` prescrit pour ne pas bloquer les lanes soeurs produisait l'effet inverse. Mesure sur #16334 (c.2360) : trois marqueurs de meme forme bornee, `[CLAIMED]` et `[RELEASED]` rendaient une liste de chemins, `[DELIVERED]` rendait `null` et relockait l'umbrella. Le correctif tient en un mot dans l'alternance ; le reste du diff documente la semantique et epingle ses bornes. Bornes verifiees par les tests, pour que l'elargissement ne defasse pas ce que les gardes precedents protegeaient : - la clause **borne** le verrou, elle ne le supprime pas : un appelant dont le scope intersecte la tranche livree reste bloque (ce n'est pas l'option 2 rejetee par l'issue, qui aurait contredit la semantique v2) ; - un glob mort sur le `[DELIVERED]` releve le claim en epic-wide par le fail-CLOSED #10958 (un claim casse n'est pas permissif) et le glob mort remonte dans `dead_scope_globs` ; - sur la branche CLOSED (PR fermee sans merge), la lane est retiree de l'etat comme avant : la clause y reste informative, exactement comme sur `[RELEASED]`. Controle negatif execute : sur le parseur non modifie, 3 des 4 tests echouent (`epic_wide_on_umbrella` reste `true`, `dead_scope_globs` leve une `KeyError`) ; le quatrieme passe dans les deux sens, c'est un epinglage de non-regression de la branche CLOSED, pas une preuve du correctif. Suites passees : `test_check_lane_claim.py` 360 passed / 1 skipped, et les huit autres suites qui importent l'organe 1104 passed. Co-Authored-By: Claude-Code <noreply@anthropic.com>
Path-collision (organ #13359/#13615)Cette PR #22457 (
|
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
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 |
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] Rejeu independant de #22457 — le correctif et ses bornes tiennent, controle negatif reproduit a l'identique.
Controle negatif refait (pas repris du body) : sur le parseur d'avant le diff (check_lane_claim.py de main, memes tests de tete), 3 des 4 nouveaux tests rougissent — ..._bounds_the_relock_on_open_pr (rc=1 au lieu de 0), ..._still_blocks_an_intersecting_caller, ..._with_dead_glob_lifts_to_epic_wide (et c'est bien KeyError: 'myia-po-2026:CoursIA' sur dead_scope_globs, exactement le mecanisme annonce). Le 4e, ..._on_closed_pr_is_informational, passe dans les deux sens : il n'est pas compté comme preuve. Au head 5dc3c5f8, 4/4 passent, dans un labo git reel (repo racine + scripts/ tracke + les chemins cites trackes — sans git ls-files le temoin de glob mort degrade et fausse la mesure).
Le defaut mesure est reel, rejoue sur les donnees de production : payload integral des commentaires de #16334 tronque a la fenetre du defaut (63 commentaires, jusqu'au [DELIVERED] de 03:39:56Z, avant le contournement [RELEASED] de 03:42:34Z). Avant : active_claims['myia-po-2023:CoursIA']['paths'] = None, lane presente dans blocking_lanes. Apres : paths = ['MyIA.AI.Notebooks/SymbolicAI/Lean/Serre100/22-vecteurs-witt-frobenius.ipynb'], lane retiree de blocking_lanes. La table du body est donc verifiee sur la source, pas seulement sur des fixtures.
Branche non couverte par les tests, verifiee quand meme : pr_states={22400: "MERGED"} — la doc dit « ouverte ou mergee ». Mesure : paths peuple et epic_wide_on_umbrella=False, comme en OPEN. CLOSED et etat non resolu (None) : paths=None, lane retiree (active_claims vide), conforme a la branche CLOSED annoncee.
Non-regression sur la suite complete : test_check_lane_claim.py au head = 25 echecs, a la base = 28, et l'ensemble des 25 est un sous-ensemble strict des 28 (comparaison triee des listes, comm). Zero echec nouveau, 3 echecs resolus — les 3 nouveaux tests. Les 25/28 restants sont environnementaux dans mon labo (repo minimal : le walk git ls-files ne voit que les fichiers que j'ai trackes, plusieurs tests dependent de l'arbre complet) ; ils sont identiques des deux cotes, donc ils ne ponderent pas le verdict.
Complements d'enumeration : _MARKER_RE (l.210) et _MARKER_ANY_RE (l.237) listaient deja DELIVERED ; _PATHS_CLAUSE_RE (l.421) etait bien le seul oubli du fichier — pas d'autre enumeration a corriger dans check_lane_claim.py.
Docs : l'ancre ajoutee pointe bien sur la nouvelle sous-section ### Marqueurs qui portent la clause... (presente l.38 du fichier au head) ; le renvoi existant l.43 n'est pas casse.
Reserves non bloquantes :
- Le lint stderr (
_lint_claim_events) ne visite pas[DELIVERED], donc un glob mort sur ce marqueur reste silencieux en stderr — c'est dit dans le body et le canal JSON (dead_scope_globs) fonctionne ; je le consigne pour qu'un futur cycle ne le redécouvre pas comme un defaut. - Path-collision advisory avec #22413 (memes 2 fichiers) : les deux PR touchent
scripts/check_lane_claim.py, sujets distincts (#22445 vs #22408) et aucun des deux ne partitionne enpaths:. Ordre de merge a arbitrer cote coordinateur, pas un defaut de cette PR.
Verdict : APPROVE. Le predicat est juge par execution de la logique du head sur de vrais payloads, et le controle negatif se rejoue.
|
[stale-guard-red] |
|
[ADJOINT PREFLIGHT] |
myia-ai-01
left a comment
There was a problem hiding this comment.
Lecture du coordinateur a la tete 6dbee2c1d22a80185e6b2185acd4c843d6bae75d. Dossier tiers du secretaire (myia-po-2028:CoursIA-3) a cette tete, B.0 sans manque. Delta : aucun commit depuis l'approbation de clusterManager-Myia. Diff lu en entier : [DELIVERED] rejoint les marqueurs qui portent la clause paths:, et quatre tests epinglent les bornes (verrou borne, appelant qui intersecte toujours bloque, glob mort releve en epic-wide, PR fermee informative). Rien d'autre a lever.
…i au claim (#22678) Point 3 de #22500 : `check_lane_claim.py N` rend BLOCKED avec la cause `PLAFOND EPIC (#22500)` quand un parent de N (au sens de `parent_refs`) est une umbrella hors classe `consolidation` dont une AUTRE fille a ete creee, ou dont un claim a ete pose, il y a moins de 7 jours. Meme regle pour un claim pose directement sur l'EPIC ; l'issue N ne compte pas comme sa propre visite, sinon le premier claim legitime de la semaine se bloquerait. La semantique n'est pas re-ecrite : `parent_refs`, `claim_visit_stamp`, `is_consolidation`, `apply_child_visits` et `umbrella_visit_cause` sont importes de `scripts/pick_idle_grain.py` (import tardif -- le picker importe deja ce module, un import de tete des deux cotes ferait dependre l'ordre de chargement d'un cycle), et la cause rendue est le litteral de l'organe, jamais une copie. Cout mesure sur #22498 (fille de #16334) : 0 appel / 0 s quand l'issue n'a pas de parent (`calls={"parent_payloads":0,"pool":0}` sur #22500) ; 1 lecture de parent + 1 pool sur une fille d'EPIC, soit 32,8 s contre 16,9-22,2 s avant, le verdict passant de CLEAR (le defaut) a BLOCKED. Le pool est memoise par processus (le mode batch le paie une fois pour N issues), et le plafond n'est pas mesure du tout quand une autre lane bloque deja. Un parent ou un pool illisible ne bloque pas : il est nomme dans `epic_visit_cap_error`. Portee : `epic_cap=True` sur les deux chemins unitaires de la CLI (`check` et `--claim`, le geste L898), jamais en batch -- le point 3 est un gate de claim, pas un changement de tirage (#22630 possede le tirage). Tests : `scripts/tests/test_check_lane_claim_umbrella_cap.py` (16 tests, fichier NEUF pour eviter la collision avec #22457/#22413 sur le fichier existant). Controle negatif mesure : 16/16 echouent sur le `check_lane_claim.py` d'origin/main. Suite existante : 356 passed, 1 skipped. Ruff : parite avec le baseline (35 findings pre-existants, 0 nouveau). Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Grain: MED/guard — lane myia-ai-01:CoursIA-2 — prev: MED/guard #22413
Le défaut
_PATHS_CLAUSE_RE(scripts/check_lane_claim.py) énuméraitCLAIMED-AMEND|CLAIMED|RELEASED|OVERRIDEet omettaitDELIVERED. La clausepaths:était donc acceptée sans erreur sur un[DELIVERED]et silencieusementignorée : le marqueur retombait en epic-wide.
Ce n'était pas cosmétique. Le réducteur v2 (
_resolve_delivered_v2) re-marqueun
[DELIVERED]en occupation active tant que sa PR est OPEN ou MERGED. Unelivraison bornée devenait donc une occupation epic-wide : le geste que
lane-claim-protocol.mdprescrit pour ne pas bloquer les lanes sœurs produisaitl'effet inverse de celui qu'il cherche. Mesure d'origine sur #16334 (lane
myia-po-2023:CoursIA, c.2360) — trois marqueurs de même forme bornée :paths:pathsdans le JSON[CLAIMED][DELIVERED](PR ouverte)nullepic_wide_on_umbrella: true[RELEASED]epic_wide_on_umbrella: falseLe correctif
Voie 1 de l'issue (la moins risquée, et la seule compatible avec la sémantique
v2) :
DELIVEREDentre dans le jeu de marqueurs du parseur de scope. Le restedu diff documente la sémantique et épingle ses bornes.
Bornes vérifiées par les tests — l'élargissement ne défait rien de ce que les
gardes précédents protégeaient :
scope intersecte la tranche livrée reste bloqué (ce n'est pas l'option 2
rejetée par l'issue, qui aurait contredit la sémantique v2) ;
claim cassé n'est pas permissif), et le glob mort remonte dans
dead_scope_globs— le canal JSON prévu par lane-claim: une clause paths: nommant un chemin inexistant rend un claim qui ne bloque personne (fail-OPEN, JSON dit malformed_markers: 0) #12740 ;l'état comme avant : la clause y reste informative, exactement comme sur
[RELEASED].Contrôle négatif
Sur le parseur non modifié, trois des quatre tests échouent
(
epic_wide_on_umbrellarestetrue;dead_scope_globslève uneKeyError).Le quatrième passe dans les deux sens : c'est un épinglage de non-régression de
la branche CLOSED, pas une preuve du correctif — dit ici pour que personne ne le
compte deux fois.
Validation
Portée documentaire, et gouvernance
docs/reference/lane-claim-detail.md: nouvelle sous-section avec la mesure,le tableau ci-dessus et les bornes ; le contournement (« poster un
[RELEASED]borné après le[DELIVERED]») y est consigné comme retirépar ce correctif, utile seulement pour lire un fil antérieur au 2026-10-25.
.claude/rules/lane-claim-protocol.md: une phrase nommant le jeu de marqueursqui portent la clause et la conséquence sur
[DELIVERED]. C'est uneclarification factuelle de la mécanique existante — aucune obligation ni
interdiction ajoutée, donc pas de prescription nouvelle. Si le coordinateur
juge la ligne normative au sens de la gouvernance harnais, le sign-off user
s'applique et je ne le préjuge pas.
Ce que cette PR ne fait pas
Le lint stderr (
_lint_claim_events) ne visite que les marqueursopen/override: le glob mort d'un[DELIVERED]ne produit donc pas deWARNstderr. Il reste visible dans le JSON (
empty_scopeetdead_scope_globs), quiest précisément le canal que #12740 a créé parce que le stderr n'est pas
consommé. Je n'élargis pas le lint ici : la PR a déjà un sujet, et le canal
utile fonctionne.
See #22445 — les critères de l'issue (voie 1, borne documentée) sont couverts ;
la fermeture revient au coordinateur.
🤖 Generated with Claude Code