Repository navigation
ci: pilote de mutation fonctionnelle des guards — adapter le contrat HELD/ESCAPED de Loop MMT gauntlet #15067
Description
Constat
CoursIA possède de nombreux guards et quelques contrôles positifs ciblés, mais pas d'organe générique permettant de prouver qu'un guard rougit encore lorsqu'on injecte une forme de défaut qu'il est censé détecter.
Exemples déjà solides mais ponctuels :
scripts/setup_hooks.py --self-testinjecte un secret factice et vérifie que gitleaks le refuse ;detect_markdown_rendering.py --selfcheckporte des contrôles positifs/négatifs embarqués ;- plusieurs scripts de dérivation ont un contrôle positif propre.
Le motif n'est pas mutualisé. Un guard nouvellement câblé peut donc rester présent, vert et néanmoins muet sur sa classe de défaut.
Source étudiée
Le gift MIT gauntlet de Loop MMT fournit le modèle minimal suivant : copier une cible dans un sandbox, injecter un défaut typé, exécuter le check, puis rendre HELD si le check échoue et ESCAPED s'il passe.
- catalogue : https://loopmmt.com/site/gifts.html
- source auditée : https://github.com/butcher-maker422/loopmmt/tree/main/gifts/gauntlet
- source pin observé le 2026-09-07 :
gauntlet.pyblob4341052ee3ffc7c728ae31ecbc25b987e0906de9 - licence du dossier vérifiée firsthand : MIT (
gifts/gauntlet/LICENSE, blob5c7b610d69d7fb9e9172792f661baa9f610b587b)
Ne pas copier le script tel quel. L'upstream utilise shell=True, hérite du cwd/env, ne quote pas sûrement le chemin sandbox sous Windows et laisse TimeoutExpired sortir hors du contrat d'exit codes.
Grain pilote borné
Implémenter dans scripts/ci/ un runner inspiré du contrat HELD/ESCAPED, adapté aux contraintes CoursIA :
- argv explicite, sans
shell=True; - placeholder
{path}explicite et injecté comme un argument unique ; cwdfixé au sandbox et environnement minimal/documenté ;- timeout configurable et verdict dédié, sans traceback brut ;
- sandbox
TemporaryDirectory, cible source jamais modifiée ; - faults minimum :
truncate,bitflip,replace; - sorties humaine + JSON comprenant
status,fault,check_exitet diagnostics bornés ; - provenance MIT documentée dans le mécanisme de notices déjà utilisé par le dépôt, sans importer le dépôt AGPL racine.
Acceptance
- tests unitaires couvrant au minimum : HELD, ESCAPED, NO_FAULT, USAGE, TIMEOUT, déterminisme, original byte-identique, chemin avec espaces sous Windows ;
- contrôle positif sur un validator fichier-par-fichier existant avec un défaut canonique qui doit être HELD ;
- contrôle négatif avec un check volontairement faible qui doit être ESCAPED ;
- au plus deux validateurs pilotes ; exclure les guards repo-wide, base-vs-head, réseau/GitHub ou mutateurs du working tree ;
- aucun câblage dans tous les workflows avant que le pilote ait produit les deux preuves HELD + ESCAPED ;
- tests existants ciblés et
scripts-testsverts ; - body PR : tableau
validator → fault → expected → observed, limites explicites (HELDsur un défaut ne prouve pas la correction générale).
Hors scope
- adoption des 44 gifts Loop MMT ;
- remplacement de
fast_lane.py, des tests pytest ou des selfchecks existants ; - exécution de commandes provenant d'une issue, d'un dashboard ou d'un fichier non approuvé ;
- orchestration générale de pipelines (
conductor) ; - nouvelle politique de flotte.
Grain attendu : MED/test (META, pilote de robustesse du harnais).
Activity
jsboige commentedon Sep 7, 2026
Grain: MED/test — lane myia-po-2023:CoursIA-2 — prev: MED/slides #14889
[CLAIMED] lane myia-po-2023:CoursIA-2 -- paths: scripts/ci/guard_gauntlet.py, scripts/tests/test_guard_gauntlet.py, THIRD_PARTY_NOTICES.md
Pilote borné uniquement. Aucun PR ou claim concurrent détecté sur #15067 ni sur ces chemins au moment du dispatch. Adapter le contrat HELD/ESCAPED ; ne pas vendor le script upstream tel quel (
shell=True, cwd/env hérités, quoting Windows et timeout hors contrat).Acceptance et hors-scope : body de #15067. Cette PR META ne prétend pas tenir à elle seule G-VAR-1 ; la lane conserve ses grains CONTENU en parallèle.
jsboige commentedon Sep 7, 2026
Grain: MED/test — lane myia-po-2023:CoursIA-2 — prev: MED/slides #14889
[CLAIMED-AMEND] lane myia-po-2023:CoursIA-2 -- paths: scripts/ci/guard_gauntlet.py, scripts/tests/test_guard_gauntlet.py, THIRD_PARTY_NOTICES*.md
Correction mécanique du claim précédent :
THIRD_PARTY_NOTICES.mdétait un fragment littéral sans/ni métacaractère, doncunparseable_scope. Le glob canonique ci-dessus le remplace. Les deux fichiers Python sont nouveaux et resteront signalésempty_scopejusqu'à leur création ; c'est attendu pour ce grain de création.Scope, acceptance et restrictions inchangés.
jsboige commentedon Sep 7, 2026
A l'issue de cet Epic, voir si un autre des 44 outils peut également nous bénéficier et renouveller le geste si c 'est le cas
jsboige commentedon Sep 7, 2026
[RELEASED] lane myia-po-2023:CoursIA-2 -- paths: scripts/ci/guard_gauntlet.py, scripts/tests/test_guard_gauntlet.py, THIRD_PARTY_NOTICES.md
Grain: MED/test — lane myia-po-2023:CoursIA-2 — prev: MED/slides #14889
[CLAIMED] lane myia-po-2023:CoursIA-2 -- paths: scripts/ci/guard_gauntlet.py, scripts/tests/test_guard_gauntlet.py, THIRD_PARTY_NOTICES*.md
Réparation atomique du registre : le premier événement ferme le claim initial mal formé ; le second repose immédiatement le même ownership avec un glob de notice parseable.
[CLAIMED-AMEND]n'est pas un marqueur reconnu par le réducteur actuel. Acceptance et hors-scope du body inchangés.jsboige commentedon Sep 7, 2026
[INFO] lane myia-po-2023:CoursIA-2 — pilote HELD/ESCAPED livre.
PR : #15073 (ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards)
Branch : feature/15067-guard-gauntlet depuis origin/main
Commit : 228434a
Statut : OPEN, CI en cours (Scripts Tests CPU planifie)
Acceptance verbatim du dispatch verifiee 17/17 (argv sans shell=True / token {path} single arg via shlex.quote / cwd sandbox / env minimal / timeout dedie / TemporaryDirectory / diagnostics bornes / faults truncate+bitflip+replace / sorties humaine+JSON / tests HELD/ESCAPED/NO_FAULT/USAGE/TIMEOUT / determinisme / original byte-identique / Windows path-with-spaces / preuve HELD positive / preuve ESCAPED negative / pilote sur 1 validateur cible / pas repo-wide).
13/13 pytest verts. 3/3 preuves NO_FAULT+HELD+ESCAPED sur un mini-validator dedie (scripts/ci/_gauntlet_demo_validator.py), outputs dans docs/ci/15067-gauntlet-smoke-20260907T144635Z.json.
Adaptation non-vendor de l'upstream Loop MMT (MIT, blob 5c7b610d6...) — argv explicite, sandbox isole, pas de shell=True, quote-escape Windows-safe. Source consignee en §8 de THIRD_PARTY_NOTICES.md.
Pas de cablage CI global dans cette PR (pilote = runner unitaire, tranche ulterieure).
jsboige commentedon Sep 7, 2026
[INFO] La suite conditionnelle est désormais suivie dans #15077, sans élargir le scope de ce pilote.
#15077 reste bloquée par deux preuves distinctes :
Le mini-validator dédié teste le runner, mais n'ouvre pas à lui seul le second gate. Une fois les deux gates ouverts, #15077 pourra réévaluer les 43 autres outils ; « aucun second outil justifié » y reste une conclusion pleinement acceptable. Aucun claim ni dispatch n'est posé sur cette fille à ce stade.
jsboige commentedon Sep 7, 2026
[RELEASED] lane myia-po-2023:CoursIA-2 -- paths: scripts/ci/guard_gauntlet.py, scripts/tests/test_guard_gauntlet.py, THIRD_PARTY_NOTICES*.md
Grain: MED/test — lane myia-po-2023:CoursIA-2 — prev: MED/notebook-python #15057
[CLAIMED] lane myia-po-2023:CoursIA-2 -- paths: scripts/ci/gauntlet.py, scripts/tests/test_guard_gauntlet.py, docs/ci/15067-gauntlet-smoke-.json, THIRD_PARTY_NOTICES.md
Réparation atomique de couverture après lecture du diff de la PR #15073 : le claim précédent ne couvrait que le runner principal, le test et la notice, tandis que la PR ajoute aussi le smoke, le mini-validator et une preuve JSON datée. Le glob
scripts/ci/*gauntlet*.pycouvre les trois fichiers Python actuels ; le chemindocs/ci/15067-gauntlet-smoke-*.jsonreste couvert jusqu'à son retrait effectif demandé par le préflight. Cette extension du registre ne change pas l'acceptance ni le hors-scope de #15067 et n'ouvre pas le gate #15077.ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards (HEL…
jsboige commentedon Sep 18, 2026
[ADJOINT CLOSE] Adjugée CLOSE_WITH_FOLLOWUP — campagne de consolidation du 2026-09-18 (mandat ai-01 2026-09-18T03:12Z, fermeture déléguée, fille déjà ouverte).
Acceptance vérifiée firsthand contre main :
scripts/ci/guard_gauntlet.py+scripts/tests/test_guard_gauntlet.py(PR ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards (HELD/ESCAPED) #15073, MERGED 2026-09-09) — verdicts HELD/ESCAPED/TIMEOUT, 13/13 tests.Résidu tracé par la fille existante #15077 (OPEN) : contrôle positif sur un validator existant fichier-par-fichier antérieur + réévaluation du second gift Loop MMT (demande user 2026-09-09 en commentaire). La preuve de valeur du pilote avait été faite sur un mini-validator dédié, depuis retiré de main.
Réouvrir en citant le critère manquant si contestation.