Skip to content

ci: gate post-gauntlet — réévaluer un second outil Loop MMT après preuve de valeur #15077

Description

@jsboige

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 gauntlet et 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 :

  • sélectionner un second outil Loop MMT pour une issue d'implémentation séparée ;
  • conclure explicitement qu'aucun des 43 autres outils n'apporte assez de valeur nette au harnais actuel.

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 :

  1. d'élargir rétroactivement l'acceptance du pilote ;
  2. de présélectionner un second outil avant d'avoir mesuré la valeur du premier ;
  3. de transformer un audit comparatif en rollout automatique.

Cette fille garde donc la suite visible tout en imposant un gate falsifiable.

Gate A — qualité intrinsèque du pilote gauntlet

Tous les points suivants doivent être satisfaits sur la version intégrée du pilote :

  • PR ci(gauntlet,#15067): pilote de mutation fonctionnelle des guards (HELD/ESCAPED) #15073 mergée avec CI et tests verts ;
  • acceptance de ci: pilote de mutation fonctionnelle des guards — adapter le contrat HELD/ESCAPED de Loop MMT gauntlet #15067 vérifiée contre le code réel, pas seulement déclarée dans le body de PR ;
  • exécution par argv sans shell=True, substitution de {path} en un argument unique et comportement Windows réellement couvert ;
  • cwd sandbox, environnement minimal documenté, timeout contractuel et diagnostics bornés ;
  • cycle de vie temporaire conforme au contrat (TemporaryDirectory ou équivalent prouvé sans résidu/collision à côté de la cible source) ;
  • fichier original byte-identique, y compris après erreur et timeout ;
  • sémantique des verdicts non ambiguë : une baseline fault=none qui échoue ne doit pas être présentée comme un HELD valide ;
  • provenance et licence du dossier amont exactes, avec pins vérifiables ;
  • limitations explicites : HELD prouve 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 un prev: pointant #15070 non mergée. Le diff fournit un runner et 13 tests rapportés, mais plusieurs preuves restent à corriger ou renforcer :

  • le code utilise tempfile.mkdtemp(...) + shutil.rmtree(...), pas TemporaryDirectory comme annoncé dans l'acceptance ;
  • le test « Windows path-with-spaces » place la source dans un chemin avec espaces, mais le sandbox créé par mkdtemp(prefix="gauntlet-") est explicitement sans espaces : il ne prouve pas le cas sandbox annoncé ;
  • fault=none + check non nul est classé HELD, alors que HELD est défini comme la détection d'un défaut injecté ;
  • la preuve smoke utilise uniquement 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 :

  • une baseline NO_FAULT saine ;
  • au moins un défaut canonique correspondant à une promesse réelle du validator ;
  • le verdict attendu et les diagnostics reproductibles ;
  • une conclusion sur la valeur marginale par rapport au selfcheck/test ordinaire déjà présent ;
  • au moins un bénéfice concret : faiblesse ESCAPED dé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/ESCAPED testent 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 :

  • gap réel dans CoursIA ;
  • overlap avec les guards, selfchecks et registres existants ;
  • coût de maintenance et surface de sécurité ;
  • portabilité Windows/Linux ;
  • licence du dossier exact et provenance pin-able ;
  • test positif et test négatif possibles sur un cas réel borné.

Shortlist initiale à réexaminer, non présélectionnée :

  • verify — certificats de contenu par hash, en gardant la nuance FRESH = 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

  • Gates A et B ouverts avec liens vers preuves ;
  • matrice comparative courte des candidats crédibles et de leur overlap ;
  • décision explicite : SECOND_TOOL_JUSTIFIED ou NO_SECOND_TOOL_JUSTIFIED ;
  • si 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 ;
  • aucun code, vendoring ou wiring CI livré dans cette issue de décision.

Hors scope

Activity

  1. added
    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
    and removed
    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
    on Sep 9, 2026
  2. jsboige commented on Sep 18, 2026

    @jsboige
    OwnerAuthor

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

  3. jsboige commented on Sep 18, 2026

    @jsboige
    OwnerAuthor

    [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) et scripts/tests/test_guard_gauntlet.py sur origin/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 → 66887aa3f3 sur main). statusCheckRollup au head 3cbe1166e6 : 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.quote du chemin sandbox avant substitution de {path}, puis shlex.split(rendered, posix=True) → liste argv (l.255-283) — le chemin devient un argument unique, pas une expansion shell. SYSTEMROOT propagé pour Windows (l.291-297). Couverture test : test_sandbox_path_with_spaces (Windows-only, fichier sentinel received_argv_path.txt prouvant 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. cwd sandbox, 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) ; TimeoutExpired attrapé → 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 aucun mkdtemp+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_sidecar le prouve.

    6. Original byte-identique, y compris après erreur et timeout — OK, une nuance. verify_original_intact compare la cible au snapshot d'avant-sandbox, sha256 avant/après émis dans les diagnostics (l.323-339, 446-447) ; sur timeout, _run_check retourne 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_faults couvre 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=none qui é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) ; test test_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 utilise shell=True, hérite cwd/env, n'a pas de quote Windows-safe, laisse remonter le traceback TimeoutExpired — chacun corrigé dans l'adaptation (renvoi aux cases 3-4).

    9. Limitations explicites : HELD prouve 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) et ESCAPED = « le guard n'est pas magicien, il détecte ce qu'il prétend détecter, rien de plus » (l.17-19). Renforcé par BASELINE_FAILED (case 7) qui interdit de lire un échec de baseline comme un HELD, et par le smoke guard_gauntlet_smoke.py qui 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_FAULT saine sur un validator réel — le smoke cible déjà scripts/check_subprocess_encoding.py et 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).

  4. jsboige commented on Sep 18, 2026

    @jsboige
    OwnerAuthor

    [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_FAULT saine — sur un fichier réel du dépôt. Cible scripts/check_unaddressed_nits.py (sha256 8cde213c…, 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=True
    

    2. 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 conforme NO_FAULT/HELD/ESCAPED, sortie scratchpad 15067-gauntlet-smoke-20260918T083035Z.json (3 runs, original_intact=true partout, sandbox TemporaryDirectory jetable, 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 cwd sandbox → Errno 2) : le runner a classé la paire BASELINE_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 — comme check_subprocess_encoding.py depuis #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 pour SECOND_TOOL_JUSTIFIED est réelle : un second outil devra apporter un gap que ni les tests appariés ni le gauntlet pilote ne couvrent déjà.

  5. jsboige commented on Sep 18, 2026

    @jsboige
    OwnerAuthor

    [ACCEPTANCE] Matrice comparative + décision : NO_SECOND_TOOL_JUSTIFIED

    Lane 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_sha du debt-ledger Aucune capacité nouvelle — chaque douleur concrète (ancre de règle périmée, jumeau dérivant) a déjà son organe dédié ; verify n'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 gate agré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érique Le 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 cmd exigerait la même adaptation de sécurité que le pilote (shell=True amont, 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 incidents Marginal : 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, gauntlet existent 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 gauntlet a 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).

  6. jsboige commented on Sep 28, 2026

    @jsboige
    OwnerAuthor

    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-sha256 des 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 UNWITNESSED Structurellement déjà là. Le régime B.0 (une levée porte auteur + heure + témoin), les dossiers (checks: latest-wins-green vérifié à la tête exacte) et les organes qui lisent l'état GitHub sont des claims à témoin. Adopter un tableau .plumb cré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

    1. 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.
    2. 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. »
    3. Le risque commun des 4 est un registre de plus. Chacun vit par un fichier d'état (certificats .verify, board .plumb, badge ward.json, cibles derived) — 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_JUSTIFIED se 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 redevient derived) ; ou (b) une surface du harnais se met à verdir sur intention sans témoin lisible par un organe existant (le candidat redevient plumb/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 redevient verify). 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.

    See #15067
    See #15077

  7. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    [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 #15077 dans une PR mergée — la fermeture revient au coordinateur en lecture G.9. La lane rend la main et poursuit sa file.

  8. jsboige commented on Oct 6, 2026

    @jsboige
    OwnerAuthor

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

  9. jsboige commented on Oct 6, 2026

    @jsboige
    OwnerAuthor

    [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]
  10. myia-ai-01 commented on Oct 12, 2026

    @myia-ai-01
    Collaborator

    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

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

    enhancementNew feature or requestpriority-lowHEALTHY strategies to polish

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions