Repository navigation
ci: gate post-gauntlet — réévaluer un second outil Loop MMT après preuve de valeur #15077
Description
Activity
- addedenhancementNew feature or requestNew feature or requestpriority-lowHEALTHY strategies to polishHEALTHY strategies to polish
on Sep 7, 2026 - addedcandidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)Referenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)and removedcandidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)Referenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
on Sep 9, 2026 [CLAIMED] lane myia-po-2024:CoursIA — évaluer le Gate A de cette fille contre le code intégré post-merge de #15073 (2026-09-09) : les 9 cases, en particulier les 4 constats du 2026-09-07 (mkdtemp vs TemporaryDirectory, test sandbox sans espaces, fault=none classé HELD, preuve smoke dédiée). Verdict par case avec file:line. Gate B seulement si A s'ouvre.
[GATE A] Évaluation contre le code intégré post-merge de #15073 — verdict : OUVERT (9/9)
Lane myia-po-2024:CoursIA. Méthode : lecture firsthand de
scripts/ci/guard_gauntlet.py(commit intégré66887aa3f3) etscripts/tests/test_guard_gauntlet.pysurorigin/main, + relance locale de la suite ce jour. Aucune déclaration du body de PR prise pour preuve sans relecture du code.Les 9 cases, verdict par verdict
1. PR #15073 mergée avec CI et tests verts — OK. MERGED 2026-09-09T07:31:00Z (squash →
66887aa3f3sur main).statusCheckRollupau head3cbe1166e6: 0 check en échec/annulé/incomplet. Relance locale ce jour :python -m pytest scripts/tests/test_guard_gauntlet.py -q→ 18 passed in 4.44s.2. Acceptance #15067 vérifiée contre le code réel — OK (c'est l'objet des cases 3-9 ci-dessous, chacune ancrée file:line sur le code intégré, pas sur le body).
3. argv sans
shell=True,{path}argument unique, Windows couvert — OK.subprocess.run(argv, cwd=str(sandbox_dir), env=env, ..., shell=False)(l.301-312)._render_check_command:shlex.quotedu chemin sandbox avant substitution de{path}, puisshlex.split(rendered, posix=True)→ liste argv (l.255-283) — le chemin devient un argument unique, pas une expansion shell.SYSTEMROOTpropagé pour Windows (l.291-297). Couverture test :test_sandbox_path_with_spaces(Windows-only, fichier sentinelreceived_argv_path.txtprouvant que argv[1] est byte-identique au chemin sandbox avec espaces — c'est le REPAIR du constat du 2026-09-07),test_windows_path_with_spaces_in_target,test_sandbox_env_vars_present.4.
cwdsandbox, env minimal documenté, timeout contractuel, diagnostics bornés — OK.cwd=str(sandbox_dir)figé au sandbox (l.303) ; env minimal construit explicitement et documenté dans le docstring (l.34-37, 291-297) ;TimeoutExpiredattrapé → verdict dédié sans traceback brut (l.313-319 + statut TIMEOUT l.405-407) ; diagnostics bornés à 4096 octets (l.146-154).5. Cycle de vie temporaire conforme — OK.
TemporaryDirectory(l.373, 378) — plus aucunmkdtemp+rmtree(constat du 2026-09-07 réparé). Le snapshot vit dans le temporaire, pas en sidecar de la cible (docstring l.326-328) ;test_no_snapshot_sidecarle prouve.6. Original byte-identique, y compris après erreur et timeout — OK, une nuance.
verify_original_intactcompare la cible au snapshot d'avant-sandbox, sha256 avant/après émis dans les diagnostics (l.323-339, 446-447) ; sur timeout,_run_checkretourne normalement (rc=-1,timed_out=True, l.313-320) donc la preuve d'intactness s'exécute aussi sur ce chemin ;test_original_intact_under_all_faultscouvre les faults. Nuance : les retours INTERNAL précoces (copie de la cible échouée avant toute injection) n'émettent pas la preuve d'intactness — mais ces chemins ne peuvent pas avoir muté la source (la copie ne lit que la source, aucune écriture n'a eu lieu).7. Baseline
fault=nonequi échoue ≠HELD— OK. Statut dédiéBASELINE_FAILED(l.116), mapping avec le commentaire explicite « le check rouge sur cible saine n'est PAS un HELD » (l.414-428) ; testtest_baseline_failed_when_check_exits_nonzero_on_clean_target(l.525). Constat du 2026-09-07 réparé.8. Provenance et licence exactes, pins vérifiables — OK. Docstring l.23-37 : upstream Loop MMT gifts/gauntlet, MIT, blob pin
5c7b610d69d7fb9e9172792f661baa9f610b587b, avec la justification du non-vendoring, énumérée : upstream utiliseshell=True, héritecwd/env, n'a pas de quote Windows-safe, laisse remonter le tracebackTimeoutExpired— chacun corrigé dans l'adaptation (renvoi aux cases 3-4).9. Limitations explicites :
HELDprouve seulement que ce défaut précis est détecté — OK. Le contrat du docstring borne la portée :HELD= « un défaut canonique est injecté, le check doit échouer » (l.15-16) etESCAPED= « le guard n'est pas magicien, il détecte ce qu'il prétend détecter, rien de plus » (l.17-19). Renforcé parBASELINE_FAILED(case 7) qui interdit de lire un échec de baseline comme un HELD, et par le smokeguard_gauntlet_smoke.pyqui documente le cas ESCAPED attendu (truncate → exit 0) comme propriété du contrat.Conséquence
Gate A : OUVERT. Les 4 constats du 2026-09-07 sont tous réparés dans le code intégré, avec tests dédiés.
Gate B — reste à produire (issue : « au moins un validator fichier-par-fichier déjà existant avant #15067 ») :
- baseline
NO_FAULTsaine sur un validator réel — le smoke cible déjàscripts/check_subprocess_encoding.pyet ses tests attestent HELD + signature (VALIDATOR_SIGNATURE = "text=True without encoding="), mais la baseline NO_FAULT saine en smoke et la conclusion de valeur marginale ne sont pas encore écrites ; - conclusion sur la valeur marginale vs selfcheck/test ordinaire ;
- un bénéfice concret documenté (ESCAPED découvert, régression empêchée, protection absente des tests existants).
Remarque de portée : les tests du dépôt jouent déjà le runner contre un validator réel (HELD après injection), ce qui pré-remplit partiellement la preuve Gate B — il manque la jambe baseline saine + la conclusion de valeur, qui relèvent d'un run smoke documenté. Gate B non ouvert ce cycle ; il est actionnable en une session courte (run smoke + analyse).
- baseline
[GATE B] Exécution du pilote sur un validator préexistant — verdict : OUVERT (5/5), valeur marginale qualifiée
Suite du commentaire Gate A. Validator cible :
scripts/check_subprocess_encoding.py— gate #12811, antérieure à #15067. Aucun code livré (règle de cette issue de décision) : uniquement des exécutions du runner et du smoke existants.Preuves (reproductibles, ce jour)
1. Baseline
NO_FAULTsaine — sur un fichier réel du dépôt. Ciblescripts/check_unaddressed_nits.py(sha2568cde213c…, inchangé avant/après) :python scripts/ci/guard_gauntlet.py \ --check "python <racine>/scripts/check_subprocess_encoding.py {path}" \ --target scripts/check_unaddressed_nits.py --fault none --timeout-sec 10 → [NO_FAULT] fault=none exit=0 original_intact=True2. Défaut canonique = promesse réelle du validator. Même cible,
--fault replace --replace-content "import subprocess\nsubprocess.run(['echo'], text=True)\n":→ [HELD] check_exit=1, sortie validator : "text=True without encoding= :: (['echo'], text=True) … cp1252 hosts crash on UTF-8 payloads (#12811). Add encoding=…"C'est exactement la menace que le validator prétend couvrir (#12811), détectée avec son message canonique.
3. Smoke intégral reproductible.
python scripts/ci/guard_gauntlet_smoke.py→ matrice conformeNO_FAULT/HELD/ESCAPED, sortie scratchpad15067-gauntlet-smoke-20260918T083035Z.json(3 runs,original_intact=truepartout, sandboxTemporaryDirectoryjetable, elapsed 0,07-0,08 s).4. Bénéfice concret n°1 — observé en direct ce cycle. Ma première invocation utilisait un chemin relatif pour le validator (résolu contre le
cwdsandbox →Errno 2) : le runner a classé la paireBASELINE_FAILED/refusé le sens HELD au run sans baseline saine, au lieu de créditer un faux HELD. La exigence « baseline saine d'abord » du contrat n'est pas décorative — elle a filtré une invocation cassée réelle, ce cycle même.5. Bénéfice concret n°2 — borne ESCAPED documentée. Le cas truncate (exit 0 → ESCAPED) fixe par contrat ce que le validator ne prétend pas couvrir (longueur/contenu tronqué) : la non-omniscience est une propriété déclarée, pas une surprise.
Conclusion sur la valeur marginale (honnête)
Recensement : 20 validators
scripts/check_*.py, 22 fichiers de test associés portant des cas négatifs (fixtures fautives écrites à la main). Sur un validator déjà couvert par des tests appariés — commecheck_subprocess_encoding.pydepuis #15073 — la valeur marginale du gauntlet est modeste : le pytest épingle déjà le comportement de détection.La valeur distinctive réside ailleurs : (a) vérification ad hoc, zéro code, d'un validator file-par-file sur n'importe quel fichier (une ligne CLI, sandbox + preuve d'intactness incluses) ; (b) la paire baseline/HELD rend le verdict auto-interprétable (preuve au point 4) ; (c) l'isolation sandbox et la preuve byte-identique ne sont pas garanties uniformément par les fixtures pytest. Le cas d'usage porteur est donc la long tail des vérifications ponctuelles (validator existant × nouveau fichier/classe de fichiers, sans écrire un test jetable), pas le remplacement des tests appariés.
État des gates
Gate Verdict Preuve A OUVERT 9/9 commentaire précédent (code intégré 66887aa3f3, 18 tests verts)B OUVERT 5/5 ce commentaire Reste pour l'acceptance de cette issue (travail de décision, pas de code) : la matrice comparative des candidats crédibles parmi les 43 autres outils, puis la décision explicite
SECOND_TOOL_JUSTIFIED/NO_SECOND_TOOL_JUSTIFIED. Au vu de la valeur marginale mesurée ci-dessus, la barre pourSECOND_TOOL_JUSTIFIEDest réelle : un second outil devra apporter un gap que ni les tests appariés ni le gauntlet pilote ne couvrent déjà.[ACCEPTANCE] Matrice comparative + décision :
NO_SECOND_TOOL_JUSTIFIEDLane myia-po-2024:CoursIA. Suite des commentaires [GATE A] (08:30Z, OUVERT 9/9) et [GATE B] (08:32Z, OUVERT 5/5, valeur marginale qualifiée). Items d'acceptance restants livrés ici : matrice + décision explicite. Aucun code, vendoring ni wiring livré (contrainte de l'issue respectée).
Méthode
- Catalogue mesuré firsthand le 2026-09-18 :
github.com/butcher-maker422/loopmmt/tree/main/gifts= 100 dossiers (le « 44 » du body datait de l'audit du 2026-09-07 — le catalogue a grossi depuis ; le chiffre est cité tel quel, pas recompté à l'époque). - Lecture README complète firsthand des 4 outils du shortlist (
verify,plumb,ward,derived) + 3 outils à nom « agentique » sondés pour l'occasion (the-oracle,confessional,seance). - Tri par nom des 93 restants contre l'inventaire des organes CoursIA (guards, selfchecks, registres, gates) — chaque famille ci-dessous cite l'organe existant qui la couvre.
Matrice comparative (candidats crédibles)
Outil (LOC amont) Contrat Overlap CoursIA existant Gap réel Verdict verify(~700)Certificats hash des faits établis ; re-check « fraîcheur, jamais vérité » Twin parity content_sha(#8057) ; gates catalogue byte-identique àmain; baselines (pedagogy_density_baseline.json) ;audited_head_shadu debt-ledgerAucune capacité nouvelle — chaque douleur concrète (ancre de règle périmée, jumeau dérivant) a déjà son organe dédié ; verifyn'apporterait qu'une unification refactoÉcarté : overlap dominant plumb(~300)Board d'état où tout PASS exige un témoin ( exists/contains/absent/cmd)PR gateagrégé +fast_lane_registry(bloquants nommés) = déjà un board à témoins ;check_unaddressed_nits(marqueurs) ; self-tests gitleaks/detect_marking_rendering ; l'incident hooksPath (2026-09-17) a produit un check spécifique, pas un besoin génériqueLe plus proche du seuil : le langage de témoins n'a pas d'embodiment générique. Mais chaque besoin concret identifié a déjà son organe ; le témoin cmdexigerait la même adaptation de sécurité que le pilote (shell=Trueamont, cwd/env hérités)Écarté : coût d'adoption ≥ valeur résiduelle ward(~200)Badge visuel où une cellule pleine exige son témoin (variante visuelle de plumb) CoursIA n'a pas de badges ; les dashboards RooSync sont de la prose hors CLI, hors périmètre d'un check fichier Pas de consommateur pour la couche visuelle Écarté : pas de gap derived(~)Staleness d'un fichier généré vs la commande qui le produit Gate catalogue (regen+diff en CI) ; jumelles twin parity re-baseline ; politique scripts/results/Le besoin catalog est déjà couvert par un gate dédié ; étendre « regen+diff » à tout le dépôt ferait tourner des commandes lourdes en CI pour des fichiers déjà gated Écarté : overlap + coût runtime CI the-oracle(sondé)A/B de prompts déterministe, reçu rejouable — Hors domaine : A/B de prompts = côté contenu GenAI, pas harnais de guards Hors scope du geste confessional(sondé)Ce qu'un prompt ne contraint pas — Hors domaine harnais (content-side) Hors scope seance(sondé)Récupérer les spans supprimés d'un fichier dans l'histoire git git log -p/blame + protocole anti-régression (4 étapes) + mémoire des incidentsMarginal : archéologie ponctuelle, pas une classe de défaut récurrente Écarté : ROI < coût d'adoption Tri par nom des 93 autres, par famille couverte :
dwell→merge_dwell+sweep (déployé) ·grain→protocole Grain (déployé) ·ratchet-*→famille ratchet CoursIA (output/source-collapse, output-failure) ; pdf/png hors périmètre (PDF interdits au dépôt, bibliography-hygiene) ·scrub→gitleaks+strip_probe_banner ·typecheck→CodeQL/analyze ·census/gitlog/worklog/timeline/map→dashboards+scripts existants · folds/sinks/sources (data utils)→hors harnais · le reste sans mapping de gap.Observation de convergence (preuve indirecte de saturation)
Le catalogue Loop MMT et le harnais CoursIA ont convergé indépendamment sur les mêmes concepts :
dwell,grain,ratchet,gauntletexistent des deux côtés sous des implémentations séparées. CoursIA a déjà déployé les siens. Les outils restants du catalogue sont majoritairement des utilitaires de données (folds/sinks/sources) hors du domaine « robustesse du harnais » que le pilote a testé.Décision
NO_SECOND_TOOL_JUSTIFIED— aucun des autres outils du catalogue n'apporte assez de valeur nette au harnais actuel.Justification en une phrase : le pilote
gauntleta prouvé que le contrat fonctionne, avec une valeur nette déjà qualifiée de marginale sur son meilleur cas réel (GATE B) ; tous les candidats crédibles du second rang ont un overlap dominant avec des organes déjà déployés, et le coût d'adoption par outil (audit sécurité amont —shell=True, cwd/env hérités, mesuré firsthand au pilote — + adaptation Windows + tests + notices + wiring) excède la valeur résiduelle.Condition de réouverture (falsifiabilité)
Cette décision se réouvre si : une classe de défaut récurrente nommée (≥2 occurrences documentées) échappe à tous les organes existants ET qu'un outil du catalogue porte un contrat qui la couvre avec un test positif/négatif borné. Toute proposition de réadoption repasse par une fille de cette issue, gates A/B à l'appui.
Le item d'acceptance « création d'une issue d'implémentation » est N/A (
NO_SECOND_TOOL_JUSTIFIED). Fermeture de la présente issue : au coordinateur (dossier complet : GATE A + GATE B + matrice + décision).- Catalogue mesuré firsthand le 2026-09-18 :
Grain: MED/guard — lane myia-po-2024:CoursIA — prev: MED/test #18301
[DELIVERED] lane myia-po-2024:CoursIA — décision de gate : NO_SECOND_TOOL_JUSTIFIED — aucun second outil Loop MMT n'entre au harnais.
Acceptance de l'issue de décision — état final
- Gates A et B ouverts avec liens vers preuves : Gate A, 9/9 et Gate B, 5/5 évalués le 2026-09-18 contre le code intégré
66887aa3f3. - Matrice comparative courte : ci-dessous (4 candidats de la shortlist, lus firsthand sur le catalogue ce jour).
- Décision explicite :
NO_SECOND_TOOL_JUSTIFIED. - Pas d'issue d'implémentation fille (conditionnelle à
SECOND_TOOL_JUSTIFIED). - Aucun code, vendoring ni câblage CI livré dans cette issue.
Faits de contexte mesurés ce jour
Le catalogue est passé de 44 à 107 gifts depuis la rédaction de l'issue (
loopmmt.com/site/gifts.html, mesuré 2026-09-28). Ce balayage couvre la shortlist nommée par l'issue + un scan par catégories du catalogue ; il n'est pas un audit outil-par-outil des 106 autres — la porte de réouverture ci-dessous en tient lieu.Matrice comparative (shortlist réexaminée, chacun lu sur sa carte)
Candidat Ce qu'il apporte Overlap mesuré avec le harnais Verdict verify(768 l., MIT, stdlib)Certificats par hash de contenu : FRESH/STALE/DEAD pour un fait coûteux établi une fois Fort. Les faits byte-truth du dépôt ont déjà leurs registres : surfaces-sha256des dossiers d'adjoint, baselines twin (pedagogy_density_baseline.json,baseline_nb_nav_chain.json), ratchets base-vs-PR, byte-identity du catalogue. Et la classe dominante de nos faits coûteux (exécution de notebook) est exclue par l'edge honnête de l'outil lui-même (« byte-truth facts only ») : un hash d'entrées ne certifie pas une exécution dépendant de l'env.Écarté plumb(299 l.)Tableau de claims où chaque PASS exige un témoin ( exists/absent/contains/cmd), sinon UNWITNESSEDStructurellement déjà là. Le régime B.0 (une levée porte auteur + heure + témoin), les dossiers ( checks: latest-wins-greenvérifié à la tête exacte) et les organes qui lisent l'état GitHub sont des claims à témoin. Adopter un tableau.plumbcréerait un second registre pour des claims dont l'autorité vit dans GitHub + RooSync — exactement la dérive que les règles de coordination interdisent (« une seule liste, jamais deux qui dérivent »).Écarté ward(324 l.)Même idée que plumb, en badge 9 cellules (rendu visuel du témoignage) Même overlap que plumb, plus un format de rendu sans consommateur dans ce harnais. Écarté derived(245 l., 11/11 tests, sandbox non-mutante)Staleness d'un fichier généré committé vs build frais byte-comparé : CURRENT/STALE/BUILD-FAILED Couvert sur le seul cas à forte valeur. L'instance canonique du dépôt ( COURSE_CATALOG.generated.*byte-identique à main) a déjà son organe : le check-run « Notebook catalog drift (read-only, advisory) » + la règle catalog-pr-hygiene + la regen mensuelle P4. Aucun autre fichier généré committé n'a de demande mesurée (résultats → GDrive par politique #15890).Écarté Raisonnement de la décision
- Le pilote a comblé le seul vide démontré. Le gauntlet (adopté via ci: pilote de mutation fonctionnelle des guards — adapter le contrat HELD/ESCAPED de Loop MMT gauntlet #15067/ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards (HELD/ESCAPED) #15073) apporte ce que le harnais n'avait pas : vérification ad hoc, zéro code, d'un validator file-par-file sur n'importe quelle cible, avec sandbox + preuve d'intactness. La valeur mesurée au Gate B est la « long tail des vérifications ponctuelles » — un seul outil de cette famille était justifié, et il est déjà en place.
- Les 4 candidats de la shortlist dupliqueraient des organes existants. L'issue pose elle-même la règle : « Les outils déjà couverts par le harnais ne doivent pas être adoptés pour le seul motif qu'ils figurent au catalogue. »
- Le risque commun des 4 est un registre de plus. Chacun vit par un fichier d'état (certificats
.verify, board.plumb, badgeward.json, ciblesderived) — or le passif mesuré du harnais est la dérive de registres (drift twin, dossiers périmés, listes parallèles bannies par règle). Coût de maintenance et risque de faux vert l'emportent sur la valeur marginale mesurée au Gate B (« modeste » sur validators déjà testés).
Porte de réouverture (falsifiable)
NO_SECOND_TOOL_JUSTIFIEDse réévalue sur preuve nouvelle nommée : (a) une classe de fichiers générés committés apparaît dont la staleness coûte un incident mesuré (le candidat redevientderived) ; ou (b) une surface du harnais se met à verdir sur intention sans témoin lisible par un organe existant (le candidat redevientplumb/ward) ; ou (c) un coût d'établissement récurrent mesurable émerge sur des faits byte-truth non couverts par un registre existant (le candidat redevientverify). Sans un de ces trois événements, la décision tient pour les 107 gifts actuels.Hors scope respecté
Aucune correction de #15073 (mergée), aucune généralisation du gauntlet, aucune adoption de masse, aucun remplacement de fast_lane/pytest/selfchecks, aucun rapport versionné sous
docs/(cette décision vit ici, à sa place d'issue de décision).Fermeture de l'issue : réservée au coordinateur/adjoint (urne
delivered, #15069) — cette lane rend la main avec preuve.- Gates A et B ouverts avec liens vers preuves : Gate A, 9/9 et Gate B, 5/5 évalués le 2026-09-18 contre le code intégré
[INFO] candidate-delivered — lane myia-po-2025:CoursIA
Servie par le belt, confrontée au réel : le travail demandé est livré. Le commentaire du 2026-09-28T20:09Z (lane myia-po-2024:CoursIA) porte
[DELIVERED]avec la décision de gate NO_SECOND_TOOL_JUSTIFIED — aucun second outil Loop MMT n'entre au harnais — et l'acceptance de l'issue cochée (gates A et B ouverts, liens et preuves dans le commentaire).C'est exactement l'une des deux sorties acceptables du body (« conclure explicitement qu'aucun des 43 autres outils n'apporte assez de valeur nette »). L'issue reste ouverte par absence de
Closes #15077dans une PR mergée — la fermeture revient au coordinateur en lecture G.9. La lane rend la main et poursuit sa file.[CLAIMED] lane myia-ai-01:CoursIA-2 — tapis central du 06/10 22:46Z, file profonde posee par le coordinateur au dispatch (rang 9/11) : ci: gate post-gauntlet — réévaluer un second outil Loop MMT après preuve de valeur. Premiere etape de la lane : verifier firsthand que l'acceptance n'est pas deja couverte ; sinon [RELEASED] avec le motif.
[CLOSURE PREFLIGHT]
schema: 1
lane: myia-po-2027:CoursIA
issue: 15077
verdict: CLOSE
acceptance:- Gates A et B ouverts avec liens vers preuves -> Gate A 9/9 (commentaire du 2026-09-18T08:30:12Z) et Gate B 5/5 (2026-09-18T08:32:43Z) ; pilote PR ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards (HELD/ESCAPED) #15073 MERGED 2026-09-09T07:31:00Z (66887aa) ; code sur origin/main scripts/ci/guard_gauntlet.py:256-266 (shlex.quote avant substitution) et :383-388 (tempfile.TemporaryDirectory) ; scripts/tests/test_guard_gauntlet.py = 19 tests
- Matrice comparative courte des candidats credibles -> commentaire du 2026-09-18T11:45:34Z (shortlist verify/plumb/ward/derived)
- Decision explicite SECOND_TOOL_JUSTIFIED | NO_SECOND_TOOL_JUSTIFIED -> NO_SECOND_TOOL_JUSTIFIED (commentaire du 2026-09-28T20:09:27Z)
- Si SECOND_TOOL_JUSTIFIED, issue d'implementation fille -> non applicable, la decision retenue est NO_SECOND_TOOL_JUSTIFIED
- Aucun code, vendoring ni wiring CI livre au titre de cette issue -> respecte : livraison par commentaires (issue de decision), 0 PR ouverte ne la reference
residue: none
open-prs: 0
comments-reviewed: 7
[/CLOSURE PREFLIGHT]
La matrice d'acceptation est vérifiée : Gates A et B ouverts avec preuves, matrice comparative postée, décision NO_SECOND_TOOL_JUSTIFIED, pilote #15073 mergé. Le dossier de clôture du 2026-10-06 rend CLOSE sans résidu et aucune PR ouverte ne référence l'issue. Fermeture.
Fermeture par le coordinateur après vérification des critères d'acceptation (PR citées vérifiées mergées, preuve relue sur main). Une objection se dit ici et rouvre l'issue.
— ai-01, coordination
Relation et statut
Issue fille de #15067. Bloquée tant que les deux gates ci-dessous ne sont pas ouverts.
Cette issue ne prolonge pas le scope du pilote
gauntletet n'autorise aucun dispatch, claim, vendoring ni implémentation d'un second outil. Son objet est de décider, preuves en main, si le geste mérite d'être renouvelé après le pilote.Le résultat acceptable est soit :
Pourquoi une issue séparée
Le commentaire « voir si un autre des 44 outils peut également nous bénéficier » exprime une intention conditionnelle. Le laisser dans #15067 risquerait :
Cette fille garde donc la suite visible tout en imposant un gate falsifiable.
Gate A — qualité intrinsèque du pilote
gauntletTous les points suivants doivent être satisfaits sur la version intégrée du pilote :
shell=True, substitution de{path}en un argument unique et comportement Windows réellement couvert ;cwdsandbox, environnement minimal documenté, timeout contractuel et diagnostics bornés ;TemporaryDirectoryou équivalent prouvé sans résidu/collision à côté de la cible source) ;fault=nonequi échoue ne doit pas être présentée comme unHELDvalide ;HELDprouve seulement que ce défaut précis est détecté.État observé au 2026-09-07
Gate fermé. La PR #15073 est ouverte et
BLOCKED; le bot signale aussi unprev:pointant #15070 non mergée. Le diff fournit un runner et 13 tests rapportés, mais plusieurs preuves restent à corriger ou renforcer :tempfile.mkdtemp(...)+shutil.rmtree(...), pasTemporaryDirectorycomme annoncé dans l'acceptance ;mkdtemp(prefix="gauntlet-")est explicitement sans espaces : il ne prouve pas le cas sandbox annoncé ;fault=none+ check non nul est classéHELD, alors queHELDest défini comme la détection d'un défaut injecté ;scripts/ci/_gauntlet_demo_validator.py, créé spécialement pour le pilote.Ces constats servent à garder le gate objectif ; leur correction appartient à #15067/#15073, pas à cette issue fille.
Gate B — valeur opérationnelle observée
Après ouverture du gate A, exécuter le pilote sur au moins un validator fichier-par-fichier déjà existant avant #15067, sans scan repo-wide et sans câblage CI global prématuré.
La preuve doit comporter :
NO_FAULTsaine ;ESCAPEDdécouverte, régression empêchée, ou protection utile absente des tests existants.Le mini-validator dédié et ses trois résultats
NO_FAULT/HELD/ESCAPEDtestent le runner, mais ne suffisent pas à ouvrir ce gate : ils ne mesurent pas encore l'intérêt du mécanisme sur le harnais réel.Travail autorisé après ouverture des deux gates
Réévaluer les 43 autres outils du catalogue, sans supposer qu'il faut en adopter un. Pour chaque candidat retenu au shortlist, comparer :
Shortlist initiale à réexaminer, non présélectionnée :
verify— certificats de contenu par hash, en gardant la nuanceFRESH= entrées inchangées, pas jugement éternellement vrai ;plumb/ward— claims d'état accompagnés de témoins (exists,absent,contains,cmd) ;derived— seulement si l'overlap avec les guards spécialisés est insuffisant.Les autres outils restent admissibles si une preuve nouvelle montre un meilleur ROI. Les outils déjà couverts par le harnais ne doivent pas être adoptés pour le seul motif qu'ils figurent au catalogue.
Acceptance de cette issue de décision
SECOND_TOOL_JUSTIFIEDouNO_SECOND_TOOL_JUSTIFIED;SECOND_TOOL_JUSTIFIED, création d'une issue d'implémentation atomique séparée avec menace couverte, test positif/négatif, licence et hors-scope ;Hors scope
gauntletà tout le dépôt ;fast_lane, pytest ou les selfchecks existants ;docs/.