Skip to content

Fix(ci,#23353): seam de plateforme a la place du patch os.name global dans test_prune_merged_worktrees - #23403

Merged
jsboige merged 1 commit into
mainfrom
fix/osname-patch-seam
Oct 31, 2026
Merged

jsboige merged 1 commit into
mainfrom
fix/osname-patch-seam

Conversation

@jsboige

@jsboige jsboige commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/test — lane myia-po-2028:CoursIA — prev: MED/guard #23366

Defaut

Sept tests du meme organe posaient la plateforme en mutant le module os de la stdlib :

monkeypatch.setattr(pmw.os, "name", "nt", raising=True)     # x5
monkeypatch.setattr(pmw.os, "name", "posix", raising=True)  # x2

pmw.os est le module os : le patch est une mutation globale au process, pas une propriete du module testee.

Le mecanisme, et pourquoi il coute plus qu'un test rouge

Sur un hote POSIX, tant que os.name vaut "nt", tout Path(...) leve
NotImplementedError: cannot instantiate 'WindowsPath'. Or pytest en appelle un exactement au moment ou un test echoue :

pytest/nodes.py:444   abspath = Path(os.getcwd())
pathlib.py:873        NotImplementedError: cannot instantiate 'WindowsPath' on your system

C'est le traceback releve sur #23353 (jambe Scripts Tests (CPU), log du job 123775340128, 4654 passed puis INTERNALERROR). Consequence : un assert qui echoue devient une perte du worker xdist avec l'echec reel jamais affiche. Le cout n'est pas le test rouge, c'est le diagnostic qu'il faut refaire a la main — #23353 l'a coute en entier.

Le correctif

Le module lisait os.name en un seul point (pid_is_alive, l. 1125). Il lit desormais _on_windows(), une indirection de module, et les tests patchent cette fonction au lieu de la plateforme :

def _on_windows() -> bool:
    return os.name == "nt"

C'est le meme seam que celui introduit par #23353 dans notebook_tools/_dotnet_env.py : la meme classe de defaut se repare de la meme facon.

Verification que la classe est close et non deplacee : grep -rn 'os, *"name"' --include=*.py . rend zero occurrence dans le depot.

Effet de bord favorable, mesure

Sous Windows, setattr(os, "name", "nt") etait un no-op : les cinq tests « windows » reussissaient quelle que soit la branche reellement prise. Ils exercent maintenant la branche Windows pour de vrai, deterministiquement, avec des Path de l'hote.

Verification

python -m pytest scripts/tests/test_prune_merged_worktrees.py -q -p no:cacheprovider
-> 208 passed, 1 skipped in 334.00s

Ce que ce run ne prouve pas, et je ne le presente pas comme tel : il tourne sous Windows, ou le patch "nt" etait inoffensif. Aucun run local ne peut reproduire l'effondrement (PosixPath s'instancie sans erreur sous Windows, WindowsPath non sous Linux). La preuve attendue est le check Scripts Tests (CPU) de cette branche.

Difference assumee avec #23353 : la, le Path fautif etait dans la fonction testee (le test echouait donc systematiquement sous Linux) ; ici il n'est que dans le formateur de rapport d'echec. Le defaut est latent tant que les tests passent — et frappe le jour ou l'un d'eux echoue, precisement le moment ou on a besoin de son message.

Tier du grain

Le tier de ce grain est MED, et non LIGHT.

Le litmus MED : « etend de la substance existante avec re-execution/verification, et
change quelque chose ». Cette PR ne touche pas seulement la suite de tests : elle
change le script de production scripts/ci/prune_merged_worktrees.py, qui
n'avait pas de seam de plateforme et testait os.name directement. La seam
_on_windows() n'existait pas avant ; elle existe apres, et les tests de la
branche sont verts (208 passed, 1 skipped). C'est le « refactor avec tests verts »
du tableau des tiers, pas le « scan de l'instance suivante » du litmus LIGHT.

Le tag porte initialement LIGHT : il etait sous-declare, et je le
re-qualifie ici. Le genre test reste le bon : le livrable est la correction
d'une suite de tests et du script qu'elle exerce, pas un gate de CI susceptible
de rougir (donc pas guard), et pas une conversion sans statut d'echec propre
(donc pas tooling).

Predecesseur fusionne de la lane : #22559 (LIGHT/test,
scripts/tests/test_prosody_long_form.py). Les deux PRs ne partagent aucun
fichier
(scripts/ci/prune_merged_worktrees.py et
scripts/tests/test_prune_merged_worktrees.py d'un cote,
scripts/tests/test_prosody_long_form.py de l'autre) — c'est la condition (ii)
de l'exception #14357, dont la condition (i) est remplie par le tier MED.

Hors perimetre

scripts/tests/test_prune_merged_worktrees_unpushed.py et tests/test_prune_merged_worktrees.py ont ete verifies : aucune mutation de os.name (grep vide). Rien d'autre a reprendre dans cette famille.

See #23353

🤖 Generated with Claude Code

…l dans les tests de prune

Les sept tests `pid_is_alive` de `test_prune_merged_worktrees.py` posaient
`monkeypatch.setattr(pmw.os, "name", "nt"/"posix")`. `pmw.os` est le module `os`
de la stdlib : le patch est global au process. Sous Linux, tant qu'il est actif,
tout `Path(...)` leve `NotImplementedError: cannot instantiate 'WindowsPath'` --
y compris celui que pytest appelle pour formater le rapport d'un test en echec.
Un echec de test devient alors une perte de worker xdist avec l'echec reel
invisible. C'est exactement le mecanisme diagnostique sur #23353.

Le module lisait `os.name` en un seul point (`pid_is_alive`, l. 1125). Il lit
desormais `_on_windows()`, une indirection de module, et les tests patchent
cette fonction au lieu de la plateforme. Plus aucune mutation de `os.name` dans
le depot (`grep -rn 'os, *"name"'` : zero occurrence).

Le patch etait un no-op sous Windows pour les tests "nt" : ils sortent d'une
reussite par accident et exercent maintenant la branche Windows pour de vrai,
avec des `Path` de l'hote.

Verifie : `pytest scripts/tests/test_prune_merged_worktrees.py` -> 208 passed,
1 skipped. Ce run est sous Windows, ou le patch "nt" etait inoffensif : ce n'est
pas une preuve Linux, et je ne le presente pas comme telle. La preuve attendue
est le check de la branche.

See #23353

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

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 added the variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) label Oct 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2028:CoursIA a deja consomme son budget LIGHT du jour (#22458 (merge a 2026-10-29T10:09:54Z)).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour,
toutes categories LIGHT confondues
(guard, doc, refs, ... partagent un seul budget) :
c'est un RATIO, pas un plafond plat. La decision de merge reste au coordinateur.

@github-actions github-actions Bot added variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) labels Oct 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

  • GENRE-RUN : run consecutif d'un genre LIGHT (voir signals.runs dans le log du job)
  • CAP-EXCEEDED-BY-GENRE : light_genre > cap partage G-VAR-2 (tally : declared=3 genre=4 cap=2)

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.

@github-actions github-actions Bot added the trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740) label Oct 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Trivial-diff advisory (#15740, non bloquant).
genre test dans la famille META (docs/guard/ledger/readme/test) + diff de 31 lignes changees (<= 100) + aucune exception ecrite dans le body : le litmus de la trivialite (une douzaine d'instances scannees a la suite) est credible. Le verdict est ADVISORY -- fournir une fournée ou citer une exception de la forme #15719 l'eteint.
La demande : une fournee (le geste pourrait comprendre ~10x plus d'instances), OU une exception ecrite dans le body de la forme « exception seulement residu final mesure » (#15719). Editer le body re-deroule cet organe et retire le label.

@github-actions github-actions Bot added the variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur) label Oct 29, 2026
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

prev: genre mot-clé fermant (#10093) — LEVÉ (2026-10-30T04:03:48Z).

pas d'adjacence LIGHT de meme genre au re-passage.

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 Always-on guards de la PR.

@jsboige

jsboige commented Oct 29, 2026

Copy link
Copy Markdown
Owner Author

[INFO] lane myia-po-2028:CoursIA — la question posee dans le corps a sa reponse : Scripts Tests (CPU) est vert (success @2026-10-29T23:22:11Z, lecture latest-wins par nom de jambe).

C'est la seule chose que le run local ne pouvait pas prouver — il tourne sous Windows, ou le patch "nt" etait inoffensif. Sur un hote POSIX, le seam _on_windows() fait son travail : les sept tests sortent de leur reussite par accident.

Etat mesure : toutes les jambes vertes sauf PR gate (failure @2026-10-29T23:22:11Z), qui est le minuteur DWELL de 120 minutes arme par la tete, pas un defaut. Rien de lane-side ne reste ici.

@jsboige

jsboige commented Oct 30, 2026

Copy link
Copy Markdown
Owner Author

[INFO] lane myia-po-2028:CoursIA -- cause du rouge Always-on guards -- body (run 40972658190), mesuree et reproduite en local

Rejeu local de la chaine complete de always_on_body_organs.sh sur le body live, avec --merged-prs-file (la vraie sequence mergee, comme en CI) :

Ma passe locale d'hier passait parce qu'elle omettait --merged-prs-file : l'organe retombait sur le champ prev: declare (MED/guard #23366), qui n'est source de verite qu'en repli. En CI, la sequence reelle compte, et le dernier grain merge de la lane est un LIGHT/test.

Ce blocage n'est pas un defaut de la PR : c'est la loi de sequence G-VAR-3 (ban absolu, le garde interdit explicitement de retaguer le meme travail). Deux sorties :

  1. tout merge d'une PR de la lane dans un autre genre (il en existe plusieurs en attente : Add(#23140): Complexity-03e -- barrieres d'exposants et word RAM (temoin ferme, renvoi 07c) #23159 DEEP/notebook-python, Feat(genai,#14499): pilote identique P1+P2+P3 (SK/MAF/ADK) sur charge figee + cout pour le depot (pts 3 et 5) #23197, Add(oversight,#23263): tournoi reel entre quatre modeles servis sur le jeu de Nim #23273, Add(oversight,#23263): section 2bis -- rejeu reel de Backdoor Code #23275, Fix(twin,#22493): re-baseline GameTheory-3 apres derive markdown-only heritee de main #23226...) change la fin de sequence -- puis rejouer la jambe (gh run rerun), aucun push requis ;
  2. apres 24 h, override coordinateur [G-VAR-3 OVERRIDE] lane myia-po-2028:CoursIA -- next: <genre>.

Rien a reparer cote lane tant que la sequence n'a pas bouge.

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #23403 (Fix(ci,#23353): seam de plateforme a la place du patch os.name global dans test_prune_merged_worktrees) 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.

@github-actions github-actions Bot removed the variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur) label Oct 30, 2026
@jsboige
jsboige merged commit 55cc8f3 into main Oct 31, 2026
26 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant