Skip to content

Fix(ci,#24676): les controles reels de list_closed_unmerged lisent un snapshot epingle, sans reseau - #25110

Open
jsboige wants to merge 1 commit into
mainfrom
claude/24676-p6-closed-unmerged-hermetic
Open

jsboige wants to merge 1 commit into
mainfrom
claude/24676-p6-closed-unmerged-hermetic

Conversation

@jsboige

@jsboige jsboige commented Nov 7, 2026

Copy link
Copy Markdown
Owner

See #24676
Hors flotte (exemption #17713).

Summary

  • Les trois contrôles réels de scripts/ci/tests/test_list_closed_unmerged_prs.py lisent un snapshot épinglé, scripts/ci/tests/fixtures/list_closed_unmerged_prs_snapshot.json, au lieu du dépôt vivant. test_real_20374_is_accidental_empty_close et test_real_24196_is_superseded gardent leurs assertions ; seules leurs données sont épinglées.
  • Le contrôle négatif test_a_real_deliberate_close_is_not_orphaned porte désormais une fenêtre de 72 h avant la capture (WINDOW_SINCE = 2026-11-04T17:00Z). Il est non trivial : deux assertions font rougir le test si la fenêtre n'a aucune fermeture à successeur nommé ou aucune à raison d'abandon.
  • Fixture de 291 Ko (ls -l ci-dessous), limitée aux pages et aux PRs que les trois contrôles lisent : voir « Taille ».
  • Le produit scripts/ci/list_closed_unmerged_prs.py n'est pas modifié. Les bodies et commentaires conservés ne sont pas tronqués.
  • Aucun skip ni xfail. Le repli UNKNOWN toléré dans test_real_20374 est supprimé.

Changes

  • scripts/ci/tests/test_list_closed_unmerged_prs.py : section 5 réécrite. La fixture pinned remplace timeline, comments, obs.remote_branches, obs.content_diff et le seul git merge-base attendu ; tout autre appel git ou donnée non épinglée lève une erreur, sans repli réseau. Commande et date de capture dans le commentaire de section 5.
  • scripts/ci/tests/fixtures/list_closed_unmerged_prs_snapshot.json : _meta décrit la fenêtre (window_since), les pages lues (pages_read : 1 à 15, arrêt par closed_unmerged), la projection et la capture. Contenu : 15 pages de l'API (items compacts), 22 PR de la fenêtre et 20374, 24196 (timeline réduite aux événements closed et head_ref_force_pushed, commentaires à ±1800 s de la fermeture, logins remplacés par actor-NN), têtes de branches, merge-base et content_diff contre origin/main = e6397230f43765afa9612bc8f4935f53409d3eaa.

Fenêtre et contrôle non trivial

Mesuré sur le snapshot, closed_unmerged puis evaluate_pr, fenêtre 2026-11-04T17:00Z :

rows 25 unique PRs 22
{'ORPHANED_CONTENT': 16, 'INTEGRATED': 1, 'SUPERSEDED': 8}
successeur [24809] 1          # une ligne, un numéro
abandon [24486, 24506, 24621, 24680, 24716, 24858] 7   # six numéros, sept lignes

Mutation de contrôle : fenêtre déplacée au 2026-11-07T12:00Z (vide de cas), copie temporaire du test, supprimée ensuite :

E   AssertionError: fenetre sans fermeture a successeur nomme : controle trivial
======================= 1 failed, 45 deselected in 0.08s =======================

Taille

$ ls -l scripts/ci/tests/fixtures/list_closed_unmerged_prs_snapshot.json
-rw-r--r-- 1 root root 290653 Nov  7 17:53 scripts/ci/tests/fixtures/list_closed_unmerged_prs_snapshot.json

Répartition : pages d'API 125 Ko (15 × 100 items : il faut les 100 items par page pour reproduire la pagination et la règle d'arrêt), bodies 100 Ko et commentaires 42 Ko conservés tels quels, contenu git 10 Ko. Descendre sous 150 Ko imposerait soit de réduire les pages (changement de ce que le produit lit), soit de tronquer les bodies que l'oracle lit (interdit). Le plafond de 300 Ko est respecté.

Validation

Commande demandée, sans réseau (GH_TOKEN=invalid HTTPS_PROXY=http://127.0.0.1:9), sur le commit de cette PR :

$ GH_TOKEN=invalid HTTPS_PROXY=http://127.0.0.1:9 python -m pytest scripts/ci/tests/test_list_closed_unmerged_prs.py -q
........................                                                 [100%]
============================== 46 passed in 0.12s ==============================

Avant modification, sans réseau : 43 passed, 3 skipped (les trois contrôles réels en SKIPPED, garde needs_gh). Garde levée sur le HEAD d'origine, hors réseau : 3 failed (RuntimeError: gh failed ... connection refused). En ligne, les deux contrôles nommés de la version d'origine passent (2 passed in 7.44s) avec les mêmes verdicts que le snapshot.

Comparaison de la fenêtre au dépôt vivant : non effectuée. Un calcul en ligne sur la fenêtre initiale du 2026-10-09 a été interrompu sans résultat ; aucun chiffre vivant n'est revendiqué.

Contrôles d'hygiène : aucun émoji littéral dans la fixture (échappés en JSON) ni dans le test ; chemins de profil Windows ramenés à C:\Users\<utilisateur> ; l'identifiant restant est le login public du mainteneur, dans les URL et les textes de PR.

Captures : lectures GET uniquement (pages de PR, timelines, commentaires, ls-remote, fetch des têtes de branches par SHA). La réduction de cette PR n'a fait aucune lecture réseau. Le token a été lu via gh auth token ; une PR (#21261) était refusée par le proxy sur gh api, elle a été relue par GET HTTP direct. Aucune écriture vers GitHub.

Verdicts

Constat Verdict Preuve
Les trois contrôles test_real_* dépendent de l'état vivant du dépôt CONFIRMED Hors réseau : SKIPPED (garde needs_gh). Garde levée, HEAD d'origine : 3 failed. Le contrôle 20374 acceptait UNKNOWN pour un clone superficiel. La tête distante de feature/20316-dynamics-t3 est 0d6b2d08, la tête de PR est 1b23a54a.
Verdicts attendus identiques avec données figées CONFIRMED En ligne, contrôles d'origine : test_real_20374 et test_real_24196 passent (2 passed in 7.44s). Snapshot : ACCIDENTAL_EMPTY_CLOSE (19 fichiers, 33 s après un force-push du même acteur), SUPERSEDED (successeur #24354 puis #24361).
Fenêtre : mêmes verdicts que le dépôt vivant NON VÉRIFIÉ en ligne Voir « Validation ».
obs.content_diff dépend du répertoire courant (scripts/orphan_branch_scan.py) CONFIRMED, hors périmètre, non corrigé (suivi : #25109) Le pathspec de git diff -- <chemin> est relatif au cwd. Depuis scripts/, content_diff rend SAME pour GameTheory-16h-Cooperation-LLM-Python.ipynb (fix/gt16h-counteraudit) alors que la racine rend 3 insertions / 3 deletions ; pour feature/20316-dynamics-t3 (tête 0d6b2d08) : 12 fichiers depuis scripts/, 19 depuis la racine. Traitement dans une PR séparée.
La pagination de closed_unmerged (plafond à 50 pages) peut manquer des PR CONFIRMED, hors périmètre (suivi : #25109) Pour la fenêtre du 2026-10-09, la page 50 se termine à updated_at = 2026-10-16T12:27:01Z, après le début de la fenêtre : les pages suivantes ne sont jamais lues. La fenêtre réduite (15 pages) n'est pas concernée.

Review Checklist

  1. Scope : deux fichiers (test, fixture), aucun changement de produit. Les trois contrôles gardent leur nom et leurs assertions ; le contrôle négatif gagne deux assertions de non-trivialité.
  2. Validation post-fix : relancée après le commit final (sortie ci-dessus).
  3. Cohérence pédagogique : N/A (aucun notebook touché).
  4. Exécution réelle : N/A pour les notebooks ; tests exécutés (pytest, sortie ci-dessus).
  5. Regression check : grep -c "needs_gh\|_gh_ready\|_fetch_pr_head\b\|_local_object_present" scripts/ci/tests/test_list_closed_unmerged_prs.py rend 0 ; le produit scripts/ci/list_closed_unmerged_prs.py n'est pas modifié.

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


Generated by Claude Code

Les controles test_real_* lisaient le depot vivant (API, timeline,
ls-remote, objets git) : leur verdict changeait avec le depot, sans
qu'une ligne du produit change, et ils sortaient en skip hors reseau.

Ils lisent desormais scripts/ci/tests/fixtures/list_closed_unmerged_prs_snapshot.json
(capture GET du 2026-11-07 ; projection, regles d'absence et main de
reference dans le bloc _meta). Seules les fonctions d'acces sont
remplacees (monkeypatch) ; l'oracle tourne tel quel. Le produit
scripts/ci/list_closed_unmerged_prs.py n'est pas modifie.

Verdicts attendus inchanges : test_real_20374 -> ACCIDENTAL_EMPTY_CLOSE,
test_real_24196 -> SUPERSEDED. test_real_20374 n'accepte plus le repli
UNKNOWN.

Le controle negatif de fenetre lit une fenetre courte (depuis
2026-11-04T17:00Z, environ 72 h avant la capture) : seules les pages que
closed_unmerged lit pour cette fenetre (1 a 15) et les PR de la fenetre
sont epinglees, plus 20374 et 24196. Bodies et commentaires conserves
sans troncature. Deux assertions font rougir le test si la fenetre
devient vide ou ne contient plus de fermeture a successeur nomme ou a
raison d'abandon. Fixture de 291 Ko.

See #24676

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

github-actions Bot commented Nov 7, 2026

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

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

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #25110 (Fix(ci,#24676): les controles reels de list_closed_unmerged lisent un snapshot epingle, sans reseau) 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.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

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