Skip to content

Fix(ci,#19643): borne par appel sur gh_json de l'organe B.0 - #20752

Open
jsboige wants to merge 2 commits into
mainfrom
claude/19643-nits-timeout
Open

jsboige wants to merge 2 commits into
mainfrom
claude/19643-nits-timeout

Conversation

@jsboige

@jsboige jsboige commented Oct 14, 2026

Copy link
Copy Markdown
Owner

See #19643

Hors flotte (exemption #17713).

Summary

  • Le residu de picker(#17038 suite): run_gh sans timeout= -- la borne existe chez l'appelant, jamais posee ; belt a froid depasse le timeout des tools #19643 non livre (NOT-DELIVERED ai-01 du 2026-10-12) est sur l'organe B.0 : scripts/check_unaddressed_nits.py ne contenait aucune occurrence de timeout ; ses 11 sites d'appel gh passent tous par gh_json, qui lancait subprocess.run sans borne.
  • gh_json porte maintenant une borne par appel, GH_CALL_TIMEOUT_S = 90. Une expiration n'est jamais avalee : improper_dismissals et _gh_fetch_issue la laissent remonter, et main() la rend en NON MESURE sur stderr avec rc=1 (non-CLEAN, fail-closed).
  • Test de regression : scripts/tests/test_check_unaddressed_nits_19643.py, 5 tests. Les 4 tests de comportement echouent sur origin/main et passent apres correctif ; le 5e est un controle (404) qui passe dans les deux etats.
  • Effet de bord connu, non corrige ici : pick_idle_grain.unaddressed_review_points (except Exception: continue l.3984 autour de analyse_pr) avale desormais l'expiration d'une PR et la sort de la file de reparation sans le dire. Avant ce correctif, l'appel pendait. Suivi a ouvrir apres Fix(picker,#16926): la file de reparation lit le verdict de corps des reviews COMMENTED #20661, qui touche le meme fichier picker.

Changes

Le perimetre annonce par la fiche etait 4 tests ; le controle 404 est le cinquieme. Aucun autre fichier n'est touche : pas de notebook, pas de pick_idle_grain.py.

Verdicts

Constats de la fiche et de l'issue #19643, re-verifies sur origin/main 1cef8a5 (la fiche citait les lignes de ce commit, toutes exactes).

# Constat Verdict Preuve
C1 gh_json lance subprocess.run sans borne CONFIRMED, corrige git show 1cef8a5502:scripts/check_unaddressed_nits.py l.3355-3359 ; grep -c timeout = 0 sur ce fichier ; apres : l.3361 et l.3367
C2 11 sites gh_json nus CONFIRMED, couverts par C1 base l.3407, 3785, 3915, 3930, 4323, 4370, 4371, 5546, 5572, 5613, 5628 (11 sites d'appel, grep -n 'gh_json(' = 12 avec la definition)
C3 improper_dismissals rend set() sur expiration CONFIRMED, corrige base l.4369-4373 (except Exception: return set()) ; consommateur l.5097 if login not in (dismissed_improperly or ()): continue : un ensemble vide lit la reserve d'un tiers comme levee. Avant correctif, test_improper_dismissals_propage_l_expiration : Failed: DID NOT RAISE TimeoutExpired
C4 _gh_fetch_issue met None en cache sur expiration CONFIRMED, corrige base l.3407-3409 ; avant correctif, test_gh_fetch_issue_ne_cache_pas_none_sur_expiration : Failed: DID NOT RAISE TimeoutExpired (la fonction rend None)
C5 gate() et main() ne traitent aucune exception CONFIRMED, corrige base l.5572 (data = gh_json(["pr", "view", ...])) et l.5656 (main) ; avant correctif, test_main_rend_non_mesure_sur_expiration : subprocess.TimeoutExpired: Command '['gh', 'pr', 'view', '123', ...]' timed out after 0 seconds remonte nu
C6 Borne 90 s « a justifier » CONFIRMED comme choix ; queue non mesuree Justification dans le commentaire l.3352-3360. Mesure citee de l'issue : 195 appels sans borne sur 200, environ 0,75 s par appel (commentaire 2026-10-09T09:20:40Z, non reproduit ici)
C7 improper_dismissals avale aussi CalledProcessError (fail-open pre-existant) CONFIRMED, NON traite (hors perimetre de la borne) base l.4372 except Exception: return set() ; suivi a ouvrir
C8 Picker sans borne : appels nus l.717 (sonde _newest_remote_issue_update) et l.935 (fetch_raw, gh issue list) ; except Exception: continue l.3984 CONFIRMED par lecture, NON traite (fichier de #20661) pick_idle_grain.py l.692-717, l.929-935, l.3984. Les lignes citees par l'issue (l.788, l.570) ont bouge sur origin/main ; celles-ci sont a jour
C9 Baseline 764 passed, 1 skipped CONFIRMED (mesure avant edition) sortie ci-dessous

Aucun constat de la fiche n'est FALSE POSITIVE.

Validation

Baseline, worktree sur 1cef8a5, avant toute edition :

$ python -m pytest scripts/tests/test_check_unaddressed_nits*.py -q
======================== 764 passed, 1 skipped in 3.19s ========================

Nouveaux tests sur l'organe NON modifie (git stash de check_unaddressed_nits.py seul, puis pop) :

$ python -m pytest scripts/tests/test_check_unaddressed_nits_19643.py -q
E   AssertionError: gh_json doit passer timeout= a subprocess.run
E   assert 'timeout' in {'capture_output': True, 'text': True, 'encoding': 'utf-8', 'check': True}
E   Failed: DID NOT RAISE TimeoutExpired
E   Failed: DID NOT RAISE TimeoutExpired
E   subprocess.TimeoutExpired: Command '['gh', 'pr', 'view', '123', '--repo', 'jsboige/CoursIA', '--json', 'number,...'] timed out after 0 seconds
FAILED ...::test_gh_json_porte_une_borne_par_appel
FAILED ...::test_improper_dismissals_propage_l_expiration
FAILED ...::test_gh_fetch_issue_ne_cache_pas_none_sur_expiration
FAILED ...::test_main_rend_non_mesure_sur_expiration
========================= 4 failed, 1 passed in 0.26s ==========================

Apres correctif, commit dcb0329 (relance apres le commit) :

$ python -m pytest scripts/tests/test_check_unaddressed_nits_19643.py -q
5 passed in 0.10s

$ python -m pytest scripts/tests/test_check_unaddressed_nits*.py -q
======================== 769 passed, 1 skipped in 2.85s ========================

Le detail par test (-v, meme contenu) : les 4 tests en echec avant correctif passent, et le controle 404 passe dans les deux etats.

Modules qui importent l'organe (test_check_adjoint_prevalidation, test_check_lane_claim, test_pick_idle_grain, test_merge_ready, test_variation_adjacency_guard, test_variation_light_cap) :

FAILED scripts/tests/test_check_lane_claim.py::test_check_claimed_10382_five_disjoint_claims
AssertionError: #13028 fixture guard: MyIA.AI.Notebooks/Sudoku/Sudoku-09-GraphColoring-CSharp.ipynb does not exist on disk
================== 1 failed, 1066 passed, 1 skipped in 18.98s ==================

Cet echec est pre-existant : le meme test echoue sur 1cef8a5 (mesure avant edition). Le carnet Sudoku-09 est absent du sparse checkout de la session ; ce grain ne touche ni check_lane_claim.py ni ce carnet.

Bout en bout, vrai subprocess, gh factice qui dort 30 s dans le PATH, borne reduite a 2 s par le pilote :

NON MESURE : gh n'a pas repondu en 2s (gh pr view 123 --repo jsboige/CoursIA --json number,...) -- aucun verdict, rc=1 (fail-closed)
RC=1 elapsed=2.0s

Ce qui n'a pas pu etre fait dans la session : un vrai check_unaddressed_nits.py <PR> sur GitHub. gh pr view passe par GraphQL, rendu 403 ici.

Lint et structure :

$ git show 1cef8a5502:scripts/check_unaddressed_nits.py | grep -c timeout   -> 0
$ grep -n 'GH_CALL_TIMEOUT_S\|timeout=' scripts/check_unaddressed_nits.py
3361:GH_CALL_TIMEOUT_S = 90
3367:        timeout=GH_CALL_TIMEOUT_S,
$ ruff check --select F scripts/check_unaddressed_nits.py scripts/tests/test_check_unaddressed_nits_19643.py
All checks passed!
$ git diff --stat origin/main
 scripts/check_unaddressed_nits.py                  | 39 +++++++--
 scripts/tests/test_check_unaddressed_nits_19643.py | 96 ++++++++++++++++++++++
 2 files changed, 129 insertions(+), 6 deletions(-)

Collision (scan REST des 100 PR ouvertes, fichiers par PR, 2026-10-14) : scripts/check_unaddressed_nits.py est touche par #20741 seulement (_print_sha_notes, l.5518, +1 -1, et son test test_check_unaddressed_nits_20066.py). Son diff s'applique sans conflit sur cette tete (git apply --check). Aucune autre PR ouverte ne touche l'organe ; pick_idle_grain.py est touche par #20661.

Le sujet de la borne par appel n'est pas teste sous Windows (siege po-2026 de la mesure de l'issue) : le chemin d'expiration de subprocess.run y est different. A verifier au premier passage reel.

Review Checklist

  1. Scope : oui. Deux fichiers (git diff --stat origin/main), aucun carnet, aucun pick_idle_grain.py.
  2. Validation post-fix : oui. Les commandes ci-dessus ont ete relancees apres le commit dcb0329.
  3. Coherence pedagogique : N/A. Aucun carnet ni prose pedagogique ; commentaires et docstring de l'organe et de son test.
  4. Execution reelle : partielle. Le chemin d'expiration est execute par un vrai subprocess avec gh factice (sortie ci-dessus). La gate sur une PR reelle n'a pas pu etre lancee (GraphQL 403 dans la session). Pas de carnet a ré-executer.
  5. Regression check : oui. Symboles touches : gh_json (11 sites de l'organe, aucun autre module ne l'importe), improper_dismissals (un seul appelant, gate), _gh_fetch_issue (via gh_issue_info, passe a analyse). Appelants externes de l'organe : check_adjoint_prevalidation enveloppe toute exception en RuntimeError (non mesure, fail-closed) ; pick_idle_grain l.3984 avale (signale plus haut) ; review_coverage, nit_lift_authorship, pool_review_verdicts n'appellent ni gh_json ni les fonctions modifiees. Les gh_json homonymes de epic_body_staleness.py, check_epic_charter.py, lane_claim_epic_wide.py, check_closure_dossier.py sont des definitions locales.

Hors perimetre (signale, non traite)

  • scripts/pick_idle_grain.py : appels subprocess.run nus l.717 et l.935 ; except Exception: continue l.3984 qui avale maintenant une expiration de PR. A traiter apres merge de Fix(picker,#16926): la file de reparation lit le verdict de corps des reviews COMMENTED #20661 (meme fichier).
  • improper_dismissals : CalledProcessError toujours avalee en set() (fail-open pre-existant, meme classe d'erreur).
  • Total de la chaine B.0 : la borne est par appel. L'issue mesure 296 s sur 22 PR pour le total ; cette borne ne le borne pas.

Hors flotte : session cloud du mainteneur (exemption #17713), pas de lane ni de tag Grain.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LRbWZZHE9jZscr8ya3niWA


Generated by Claude Code

check_unaddressed_nits.gh_json lancait subprocess.run sans timeout= : les
11 sites d'appel de l'organe (grep -c timeout = 0 sur 1cef8a5) pouvaient
bloquer la lecture du merge-gate B.0 sans rendre de verdict.

- gh_json porte timeout=GH_CALL_TIMEOUT_S (90 s, par appel).
- Une expiration n'est jamais avalee : improper_dismissals ne rend plus
  set() (un ensemble vide lirait la reserve d'un tiers comme levee),
  _gh_fetch_issue ne met plus None en cache, main() imprime NON MESURE sur
  stderr et rend 1 (non-CLEAN, fail-closed).
- Tests : scripts/tests/test_check_unaddressed_nits_19643.py (5 tests ;
  4 echouent avant le correctif, le controle 404 passe avant et apres).
- Hors perimetre, signale et non corrige : pick_idle_grain.py (appels nus
  l.717 et l.935, `except Exception: continue` l.3984 autour de analyse_pr) ;
  CalledProcessError toujours avalee par improper_dismissals.

See #19643

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LRbWZZHE9jZscr8ya3niWA
@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #20752 (Fix(ci,#19643): borne par appel sur gh_json de l'organe B.0) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

jsboige commented Oct 15, 2026

Copy link
Copy Markdown
Owner Author

Le check Scripts Tests (CPU) est rouge sur la tête dcb0329a37, mais l'échec ne vient pas de cette PR.


Generated by Claude Code

@github-actions github-actions Bot added the variation-tag-missing PR sans tag Grain: <TIER>/<GENRE> (variation-protocol) label Oct 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

This branch has not been deployed

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

Labels

variation-tag-missing PR sans tag Grain: <TIER>/<GENRE> (variation-protocol)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants