Skip to content

ci(b0): CITERS reconnait la narration retrospective en anglais mais pas en francais — un commentaire qui demande le merge bloque sur dissipation CHANGES_REQUESTED leve #15837

Description

@myia-ai-01

Le constat

CITERS, dans scripts/check_unaddressed_nits.py, est la liste de mots qui distingue une émission de verdict (« je pose un CHANGES_REQUESTED ») d'une citation (« mon CHANGES_REQUESTED précédent était un faux positif »). Sans elle, tout texte prononçant le mot bloquerait le merge.

Elle reconnaît la narration rétrospective en anglais :

"previous", "stale", "earlier", "supersedes my", "false-positive", "would", "could", "might", "the"

et les négations en français :

"pas de", "pas d'", "pas", "sans", "aucun", "aucune", "rien", "jamais", "zero", "0"

Il manque une case : aucun verbe de narration rétrospective en français. Dans un dépôt dont les lanes rédigent leurs commentaires en français, c'est la moitié du registre naturel qui n'est pas couverte.

La mesure qui l'a rendu visible

Commentaire de myia-po-2024:CoursIA-2 sur #15762 (2026-09-12T16:26Z). Le littéral CHANGES_REQUESTED y apparaît deux fois ; l'organe instrumenté sur le corps exact rend :

Offset Fenêtre de citation (30 car. avant) CITERS trouvé Verdict
407 'new fondateur** : dissipation ' aucun émission → bloque
530 'al — tous checks success ✓, 0 ' ['0'] cité → neutralisé

La seconde est traitée correctement — le contrôle négatif #11916 fait son travail.

La première bloque sur :

dissipation CHANGES_REQUESTED c.589 levé N-1/N

dissipation appartient exactement à la classe de previous / stale / earlier : le mot ne peut que narrer. On ne « dissipe » pas une réserve qu'on émet — on dissipe celle qu'on a déjà levée. Le commentaire entier dit d'ailleurs l'inverse d'une réserve : « Reviews actives : aucune. PR dans son état final », et l'action qu'il demande est le merge.

Conséquence concrète : une PR est tenue par rc=1 sur un commentaire qui déclare qu'il n'y a rien à faire.

Un second angle, plus structurel

Le mot levé suit immédiatement le marqueur : dissipation CHANGES_REQUESTED c.589 **levé** N-1/N. La levée était écrite, à trois mots — mais _is_cited ne regarde que 30 caractères avant l'occurrence. Du mauvais côté du curseur.

La fenêtre unidirectionnelle est un choix défendable (une citation à distance ne doit rien désactiver, cf le commentaire de CITERS), et je ne propose pas de la renverser à la légère. Mais en français le participe qui qualifie le verdict se place après le substantif (CHANGES_REQUESTED levé, réserve dissipée, blocage résolu) là où l'anglais le place avant (previous CHANGES_REQUESTED, stale CHANGES_REQUESTED). La fenêtre avant-seulement est donc structurellement mieux adaptée à l'anglais qu'au français, indépendamment du vocabulaire de la liste.

Ce qu'il ne faut PAS faire (et pourquoi cette issue ne propose pas de correctif direct)

CITERS est le côté permissif du garde. Chaque mot ajouté neutralise des occurrences — donc un faux positif dans CITERS ne coûte pas un flag à trier : il coûte une réserve réelle rendue invisible, c'est-à-dire précisément l'incident fondateur #10761 que §B.0 existe pour empêcher. L'asymétrie est totale par rapport à CONCERN_MARKERS, où le coût d'un faux positif est un tri.

Élargir cette liste à vue est donc le geste dangereux, et il ne doit pas se faire sur la PR que ça débloquerait — c'est se donner raison à soi-même.

Ce qui est demandé

  1. Mesurer d'abord. Passer --audit sur les PRs mergées et compter, pour chaque candidat (dissipation, dissipée, levée, résolue, ancienne, précédent), combien d'occurrences seraient neutralisées et combien d'entre elles portaient une vraie réserve. Un candidat dont le taux de vrais positifs neutralisés est non nul est rejeté, quel que soit son attrait linguistique.
  2. Trancher l'axe de correction. Deux voies, non exclusives :
  3. Fenêtre bidirectionnelle bornée — à n'envisager qu'après (1), et seulement pour une liste fermée de participes de levée (levé, levée, résolu, dissipé), avec le même contrôle négatif.

Critère d'acceptation

Le contrôle positif n'est pas facultatif. Un assouplissement de filet qu'on n'a jamais vu refuser de s'appliquer n'est pas mesuré, il est supposé — et du côté permissif, une supposition se paie en réserve manquée.

Provenance

Défaut rencontré sur #15762, où j'avais d'abord publié un diagnostic faux (les glyphes ★ NEW lus comme marqueurs de sévérité — SEVERITY_GLYPHS ne contient que 🟡 et 🔴, et le commentaire n'en porte aucun). Rectification publiée sur la PR. Le présent constat est celui qui a survécu à l'instrumentation de l'organe.

See #15762. See #14682. See #11916.

Activity

  1. jsboige commented on Sep 12, 2026

    @jsboige
    Owner

    [CLAIMED] lane myia-po-2026:CoursIA -- 2026-09-12T21:20Z -- paths: scripts/check_unaddressed_nits.py + son fichier de tests

    Grain: MED/guard — lane myia-po-2026:CoursIA — prev: LIGHT/notebook-python #15680

    Scope : (1) ajouter les verbes de narration retrospective francais manquants a CITERS ; (2) traiter le cas de position — en francais le participe qualifie le verdict APRES le substantif (CHANGES_REQUESTED leve, reserve dissipee), la ou l anglais le place avant ; la fenetre avant-seulement de _is_cited est donc structurellement defavorable au francais.

    Controle negatif obligatoire : une vraie emission de verdict en francais (je pose un CHANGES_REQUESTED) doit continuer a bloquer — l ajout ne doit pas neutraliser les emissions reelles. Cas de reference : commentaire myia-po-2024:CoursIA-2 sur PR #15762 (offset 407).

  2. jsboige commented on Sep 12, 2026

    @jsboige
    Owner

    Audit du point 1 — publié avec ses comptes

    Livré dans #15843 (CITERS + dissipation, 8 tests, 548/548). Voici la mesure exigée par l'acceptance.

    Corpus : 2000 PRs mergées (2026-08-22T15:49Z → 2026-09-12T19:30Z), 13113 corps de commentaire et de review non vides, 2472 occurrences de marqueur sur l'ensemble des tuples réellement passés à has_live_marker (CONCERN_MARKERS, SEVERITY_GLYPHS, VERDICT_POSITIVE, POSITIVE_MARKERS) — 158 déjà neutralisées par CITERS avant tout ajout.

    Pour chaque candidat : occurrences où le mot serait le citer de l'occurrence (donc neutralisées par l'ajout), et combien d'entre elles portaient une vraie réserve. Adjudication par lecture de chaque occurrence, pas par heuristique.

    Candidat Occurrences neutralisées Vraies réserves Verdict
    dissipation 7 0 retenu
    levee 5 0 écarté (voir ci-dessous)
    dissipee 0 — écarté (taux inconnu, pas nul)
    ancienne 0 — écarté
    precedente 0 — écarté
    retiree 0 — écarté
    annulee 0 — écarté
    abandonnee 0 — écarté

    precedent était déjà dans CITERS ; sa variante féminine ne porte aucune occurrence mesurée.

    Les 7 occurrences de dissipation : … dissipation CHANGES_REQUESTED c.589 levé …, ### dissipation CHANGES_REQUESTED c.1105, 3 organes (c.1105 dissipation CHANGES_REQUESTED), + c.1090 dissipation CHANGES_REQUESTED +…. Toutes des narrations de levée.

    Pourquoi levee est écarté malgré 5/5

    Le critère de l'issue — « un candidat dont le taux de vrais positifs neutralisés est non nul est rejeté » — ne suffit pas ici, et c'est le résultat le plus utile de cet audit : le taux n'est pas le bon discriminant quand les deux fenêtres n'ont pas la même nature grammaticale.

    Un nom en fin de fenêtre avant ne peut signifier qu'une chose : « dissipation du verdict » — il est le dernier mot devant lui. Un participe peut qualifier un autre nom : la réserve est levée. est une clause complète, et le CHANGES_REQUESTED qui suit est une réserve neuve. Ajouter levee la rend invisible au niveau has_live_marker — c'est ce que #10761 existe pour empêcher. Le test test_15837_candidat_refuse_levee_devant_le_marqueur le démontre mécaniquement (simulation sous finally), et échoue si le candidat est ajouté.

    Résidu assumé : La réserve est levée avant merge. reste flaggée (2 occurrences, #15450 / #15354). Faux positif à trier — le côté bon marché de l'asymétrie. Un test le fige.

    Point 3 (fenêtre bidirectionnelle bornée) — mesuré puis rejeté

    Occurrences neutralisables sur la liste fermée : leve 11, levee 6, dissipes 2, resolu 2. Les hits de la liste fermée sont 4/4 narrations, mais :

    • Le câblage casse un garde testé. Branché sur has_live_marker, CHANGES_REQUESTED levé sans référence. passe de BOT-CONCERN à None : test_12871_ce2_verdict_leve_sans_ref_reste_live tombe. Ce garde exige qu'une levée cite une référence pointable — le participe post-marqueur est plus grossier que le mécanisme positions A-E déjà en place.
    • Le gain réel est de 1 occurrence sur 13113 corps : au niveau classify (le vrai gate), 3 des 4 hits étaient déjà neutralisés ; seul docs(symboliclearning,#15241): aérer l'intro du README (7 sections) + réconcilier compteurs catalogue 21→22 #15424 basculait.

    1 occurrence contre la destruction d'un garde délibéré : rejeté, motif écrit pour ne pas être redécouvert.

    Limites

    Corpus de 21 jours, pas l'histoire du dépôt. Les 7 hits de dissipation viennent d'une seule plume (jsboige, 5 PRs) — le mot y est invariablement narratif, ce qui est ce que la mesure dit et rien de plus.

    Preuve d'acceptance

    python scripts/check_unaddressed_nits.py 15762 : rc=1 → rc=0. Contrôle positif (émission réelle de CHANGES_REQUESTED: dans un corps contenant dissipation ailleurs) : bloque toujours.

  3. added a commit that references this issue on Sep 13, 2026
  4. added 2 commits that reference this issue on Sep 14, 2026
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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions