Skip to content

ci: pilote de mutation fonctionnelle des guards — adapter le contrat HELD/ESCAPED de Loop MMT gauntlet #15067

Closed

Description

@jsboige

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-test injecte un secret factice et vérifie que gitleaks le refuse ;
  • detect_markdown_rendering.py --selfcheck porte 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.

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 :

  1. argv explicite, sans shell=True ;
  2. placeholder {path} explicite et injecté comme un argument unique ;
  3. cwd fixé au sandbox et environnement minimal/documenté ;
  4. timeout configurable et verdict dédié, sans traceback brut ;
  5. sandbox TemporaryDirectory, cible source jamais modifiée ;
  6. faults minimum : truncate, bitflip, replace ;
  7. sorties humaine + JSON comprenant status, fault, check_exit et diagnostics bornés ;
  8. 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-tests verts ;
  • body PR : tableau validator → fault → expected → observed, limites explicites (HELD sur 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

  1. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    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.

  2. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    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, donc unparseable_scope. Le glob canonique ci-dessus le remplace. Les deux fichiers Python sont nouveaux et resteront signalés empty_scope jusqu'à leur création ; c'est attendu pour ce grain de création.

    Scope, acceptance et restrictions inchangés.

  3. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    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

  4. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    [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.

  5. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    [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).

  6. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    [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 :

    1. qualité intrinsèque de ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards (HELD/ESCAPED) #15073 réellement validée contre le code et la CI ;
    2. valeur opérationnelle démontrée sur au moins un validator fichier-par-fichier qui existait déjà avant ci: pilote de mutation fonctionnelle des guards — adapter le contrat HELD/ESCAPED de Loop MMT gauntlet #15067.

    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.

  7. jsboige commented on Sep 7, 2026

    @jsboige
    OwnerAuthor

    [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*.py couvre les trois fichiers Python actuels ; le chemin docs/ci/15067-gauntlet-smoke-*.json reste 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.

  8. added a commit that references this issue on Sep 9, 2026
  9. added
    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
    on Sep 9, 2026
  10. jsboige commented on Sep 18, 2026

    @jsboige
    OwnerAuthor

    [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 :

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)enhancementNew feature or requestpriority-mediumNEEDS_IMPROVEMENT strategies

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions