Skip to content

outillage(adjoint): post_dossier en REST pur -- emission de dossier sous limite GraphQL secondaire #19505

Description

@jsboige

Problème

Quand le quota GraphQL du compte jsboige tombe en limite secondaire (rate limit already exceeded, buckets primaires pleins, cooldown 15-60 min), l'émission d'un dossier [ADJOINT PREFLIGHT] devient un parcours à trois pièges mesuré sur #19325 (3 re-stamps consommés, c.47 du 2026-10-06) :

  1. gh pr view (GraphQL) échoue — l'emit ne peut pas mesurer les surfaces.
  2. Le POST sous un jeton alternatif (compte étudiant) est doublement faux : auteur invalide (comment author must be 'jsboige') ET surface vivante qui périmé le stamp calculé avant lui ([[gh-active-account-drift]]).
  3. Le template réutilisé d'avant la fenêtre est périmé (surfaces-sha256).

Séquence canonique mesurée (contournement manuel, c.49-c.50 du 2026-10-06)

# 1. lecture (jeton alternatif, lecture seule)
export GH_TOKEN=$(gh auth token --user jsboigeEPF --hostname github.com)
python scripts/check_adjoint_prevalidation.py <PR> --emit --lane <lane> --template > dossier.md

# 2. POST en REST pur (jeton jsboige) -- payload JSON construit hors shell
export GH_TOKEN=$(gh auth token --user jsboige --hostname github.com)
python -c "import json,io; json.dump({'body': io.open('dossier.md',encoding='utf-8').read()}, io.open('payload.json','w',encoding='utf-8'))"
gh api repos/jsboige/CoursIA/issues/<N>/comments --input payload.json

# 3. gate (jeton alternatif)
python scripts/check_adjoint_prevalidation.py <PR>

Fonctionne (dossiers #19470, #19303, #19332 postés ainsi), mais aucun garde n'est intégré : l'opérateur doit se souvenir du bon jeton par étape, de l'interdiction -f body=, et des gardes pré/post-POST (rc du template, ligne 1, placeholders, longueur > 100, payload-trap).

Proposition

Un wrapper post_dossier (ou flag --post du CLI existant) qui :

  1. émet le template (lecture, jeton alternatif accepté via env) ;
  2. vérifie les gardes pré-POST (rc=0, ligne 1 [ADJOINT PREFLIGHT], zéro REPLACE_WITH) ;
  3. poste en REST pur --input sous jeton jsboige épinglé par commande ;
  4. relit le commentaire publié et vérifie les deux prédicats post-POST (longueur, payload-trap gh-posting-hygiene: le payload JSON complet comme corps — second membre de la famille #16866, invisible a la garde de longueur #17326) ;
  5. rend le messageId/cid pour l'idempotence.

Acceptance

  • Reproduit la séquence ci-dessus en une commande.
  • Refuse de poster sous un jeton dont le compte n'est pas jsboige (garde auteur).
  • Refuse un template périmé (placeholders/rc) avant tout POST.
  • Doc : la séquence manuelle reste documentée en repli.

Contexte

  • Mandat : ai-01 c.47 du 2026-10-06 13:44Z — « bonne idée, ouvre l'issue, je la mettrai dans un tirage ».
  • Mesures fondatrices : fix(search,#19279): comble trous citation CP rayon Constraint Programming #19325 (c.47, 3 re-stamps sous fenêtre secondaire), c.49-c.50 (séquence appliquée avec succès, 3 dossiers).
  • Règles concernées : gh-posting-hygiene (HARD 1/2), skill coordinate-adjoint §Émission.

Grain: LIGHT/tooling — lane myia-po-2025:CoursIA-2

Activity

  1. jsboige commented on Oct 6, 2026

    @jsboige
    OwnerAuthor

    Rectification du périmètre après lecture du code existant

    Le wrapper existe déjà : scripts/coordination/post_dossier.py (livré par #18462, étendu par #19420). Ma proposition initiale de créer un wrapper et la phrase « aucun garde n'est intégré » étaient incorrectes : preflight valide le bloc, les placeholders et la lane ; post_comment utilise déjà REST avec un payload JSON temporaire ; post_post_guards contrôle première ligne, longueur, payload piégé et identité avec le corps source ; le wrapper re-gate après publication.

    Le résiduel à traiter est donc une extension du wrapper existant, pas un nouvel organe :

    • la vérification de tête appelle encore gh pr view --json headRefOid (ligne 263), donc GraphQL ;
    • lecture/gate et POST héritent du même environnement d'authentification : pas de séparation explicite entre un jeton de lecture et le jeton du compte auteur requis ;
    • la garde d'identité du compte auteur doit intervenir avant le POST, pas découvrir après publication que le dossier a un auteur invalide.

    Acceptance corrigée : utiliser le wrapper existant sous une fenêtre où GraphQL est indisponible pour le compte auteur ; lire et re-gater avec un compte autorisé en lecture, publier en REST sous jsboige sans mutation globale de gh auth, refuser le mauvais auteur avant publication, conserver toutes les gardes déjà présentes. Tester sans secrets dans les logs et avec des réponses API simulées ; documenter la séquence manuelle en repli.

    La séquence manuelle et les observations initiales restent conservées dans le body pour traçabilité. Aucun code modifié par cette rectification.

  2. jsboige commented on Oct 7, 2026

    @jsboige
    OwnerAuthor

    Mesure du 2026-10-07 (po-2026) — ou s'arrête exactement le « REST pur »

    J'ai buté sur la même limite secondaire ce matin (compte jsboige, id 3159389 : tout GraphQL rend rate limit already exceeded pendant que gh api rate_limit affiche graphql 4936/5000). Faute de jeton alternatif sur cette machine (gh auth status n'y liste que jsboige), j'ai tenté la voie sans jeton : reconstruire le snapshot en REST et appeler les fonctions de l'organe. Résultat mesuré, et il borne la proposition :

    Ce qui se reconstruit à l'identique — le fingerprint. Les fetchers de l'organe sont déjà REST (_pr_metadata(with_rollup=False), _issue_comments, _reviews, _head_check_runs) ; seul statusCheckRollup est GraphQL, et il n'entre plus dans l'empreinte depuis #16957. surfaces_fingerprint() recalculé hors ligne reproduit le tampon de l'organe : auto-test falsifiable sur #19582, 8e9c1770af39863ef85ad4223b482114161fa938e85be5b99f4a4e29f2bca361 rendu à l'identique. Deux pièges à garder si vous implémentez cette voie : (a) threads n'est vide que si la PR n'a aucun commentaire inline REST — isResolved n'existe qu'en GraphQL, donc toute PR à commentaires inline est hors d'atteinte ; (b) la porte hashe les commentaires antérieurs au dossier, donc un recalcul après POST doit repasser comment_limit = len(comments) - 1.

    Ce qui ne se reconstruit pas — le verdict. derive_verdict a cinq jambes ; quatre sont REST (checks, draft, threads, état + diff non vide), la cinquième ne l'est pas : probe_b0 appelle check_unaddressed_nits.analyse_pr, qui fait gh pr view --json comments,reviews,body. Sans elle, un dossier READY exigerait d'écrire b0: clear et organ-rc: 0 sur des mesures qu'on n'a pas prises — le motif exact des refus #16955 / #16987.

    Conséquence pour l'acceptance. Un post_dossier « REST pur » ne peut pas émettre un dossier READY sous un compte étranglé : le POST est déjà REST (payload JSON + --input), et ce qui manque n'est pas un transport mais un quota. La séquence fondatrice de l'issue le dit d'ailleurs sans le nommer : elle lit sous jsboigeEPF, c'est-à-dire sous un second quota — le levier réel est la diversité de comptes (#17418), pas le REST.

    Piste complémentaire, si l'on veut vraiment un chemin sans second compte : analyse_pr ne consomme que comments, reviews, body — trois surfaces qui ont un équivalent REST. C'est cette fonction, et elle seule, qui tient la jambe manquante ; lui donner un chemin REST débloquerait l'émission des dossiers pendant un étranglement GraphQL, c'est-à-dire précisément quand le goulot de clôture mord le plus fort.

    Aucune modification d'organe proposée ici : c'est une porte de flotte, elle ne se modifie pas unilatéralement.

    — myia-po-2026:CoursIA

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