Skip to content

ci(guards,#15347): wire refresh_stale_adjacency.py into an hourly adjacency-stale sweep - #15362

Merged
myia-ai-01 merged 1 commit into
mainfrom
fix/ci-15347-refresh-stale-adjacency
Sep 11, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
fix/ci-15347-refresh-stale-adjacency

Conversation

@jsboige

@jsboige jsboige commented Sep 9, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/guard — lane myia-po-2026:CoursIA — prev: MED/guard #15357

Summary

L'organe G-VAR-3 scripts/ci/refresh_stale_adjacency.py existe sur main avec ses tests depuis le fix fondateur, mais aucun workflow ne l'appelle : les verdicts d'adjacence (prédécesseur résolu sur la séquence de merges réelle, prev_source: merged-sequence, #12095) se périment au merge d'un sibling, sans qu'aucun événement ne rafraîchisse la PR ouverte — 24 h de blocage mesurées sur #15165.

Validation (2026-09-09, mesure firsthand)

Pré-flight : script + tests présents sur origin/main (blobs c27fc4aa2/1ae536abf) ; grep refresh_stale_adjacency .github/workflows/ → 0 appelant (le constat de l'issue, revérifié) ; nom de job du garde vérifié (Always-on guards -- 12 organes, 1 checkout, always-on-guards.yml:92).

Dry-run du step du sweep sur le pool réel (74 PR ouvertes, 71 portent une jambe Always-on guards, 28 rouges ; refresh_stale_adjacency.py --dry-run, aucune édition) :

Verdict N Détail
would_refresh = verdicts périmés que l'organe lèvera 17 dont #15303/#15210/#15190 (prédécesseur #15165, la config fondatrice de l'issue) ; #15330/#15283/#15280/#15277 (15191) ; #15226/#15156/#15100 (15336)
refusés à juste titre 11 dont #15328 (adjacence ledger→ledger RÉELLE, non levée) ; #15338/#15333/#15161 (tag-required, pas adjacency — raison explicite) ; 6 always_on_failing=False (rien à faire)
real-fail (drivers du rc=1) 0 → rc=0, le sweep sort propre

Tests locaux : test_check_self_hosted_runner_policy.py 115 passed (dont le scan live du repo, qui valide le nouveau workflow fail-closed) ; test_refresh_stale_adjacency.py 12 passed. YAML du workflow validé (structure, permissions, concurrency).

Résiduel : rien — l'issue est entièrement résolue. Un organe de santé dédié (style pr-gate-sweep-health-advisory) reste un suivi possible, non requis (le warning rename-to-nothing couvre le mode d'échec principal).

Closes #15347.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

…acency-stale sweep

L'organe G-VAR-3 est sur main + tests depuis le fix fondateur, mais AUCUN
workflow ne l'appelait : les verdicts d'adjacence (prev_source:
merged-sequence, #12095) se periment au merge d'un sibling sans qu'aucun
evenement ne les rafraichisse -- 24 h de blocage mesurees sur #15165.

- .github/workflows/adjacency-stale-sweep.yml (nouveau) : enumere les PR
  ouvertes non-fork dont la jambe 'Always-on guards' est rouge (REST, meme
  forme que pr-gate-stale-sweep), simule le garde contre la sequence de
  merges courante, et appose le marqueur idempotent refresh-adj pour
  re-declencher pull_request: edited quand la simulation passe. Jamais
  d'override : une vraie adjacence G-VAR-3 reste bloquee. Horaire off-:00
  (minute 27), pool coursia-linux (#12728/#14283), cap 8 par sweep, exit 0
  toujours (rc=2 -> ::warning::). Warning dedie si aucune jambe
  'Always-on guards*' sur le pool (rename du check = organe muet).
- check_self_hosted_runner_policy.py : allowlist tranche 4 #14283.

Validation locale (2026-09-09, dry-run du step sur le pool reel) :
74 PR ouvertes, 71 portent une jambe Always-on guards, 28 rouges ;
refresh_stale_adjacency.py --dry-run : 17 verdicts perimes would_refresh
(dont #15303/#15210/#15190 sur la config fondatrice #15165), 11 refuses
correctement (dont #15328: adjacence ledger->ledger reelle, non levee;
#15338/#15333/#15161: tag-required, pas adjacency), 0 real-fail -> rc=0.
Tests : check_self_hosted_runner_policy 115 passed (scan live repo),
refresh_stale_adjacency 12 passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the variation-tag-missing PR sans tag Grain: <TIER>/<GENRE> (variation-protocol) label Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Grain tag obligatoire (#10045, bloquant).

Grain tag absent (no Grain: / in body).

Pour passer ce gate, le body doit porter en tete une ligne de la forme :

Grain: <DEEP|MED|LIGHT>/<genre> -- lane <machine:workspace> -- prev: <TIER>/<GENRE> #<PR>

Le <genre> doit figurer dans l'enumeration §1 de variation-protocol.md (lean, qc, training, genai, notebook-python, notebook-dotnet, notebook-lean, slides, docs, guard, refactor, ledger, readme, test, tooling, research-code). Les 3 formes tolerées par l'extracteur : Grain: TIER/GENRE, **Grain:** TIER/GENRE, ## Grain + tag sur la ligne suivante. La lane doit suivre le format <machine>:<workspace> (cf. lane-claim-protocol.md).

@github-actions github-actions Bot added variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) and removed variation-tag-missing PR sans tag Grain: <TIER>/<GENRE> (variation-protocol) labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2026:CoursIA a deja consomme son budget LIGHT du jour (axe genre G-VAR-2/3 (light-genre, quel que soit le tier declare) : #15180 (LIGHT/docs, merge a 2026-09-09T03:11:19Z), #15240 (MED/guard, merge a 2026-09-09T03:40:08Z), #15336 (LIGHT/ledger, merge a 2026-09-09T07:13:16Z), #15314 (LIGHT/docs, merge a 2026-09-09T08:51:48Z)).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour,
toutes categories LIGHT confondues
(guard, doc, refs, ... partagent un seul budget) :
c'est un RATIO, pas un plafond plat. La decision de merge reste au coordinateur.

@github-actions

github-actions Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #15362 (ci(guards,#15347): wire refresh_stale_adjacency.py into an hourly adjacency-stale sweep) 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.

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Hermes] — Review deep-read #15362 (head 43a969038a, +233/−0, 2 fichiers, workflow CI + allowlist — opener=jsboige → COMMENT, contrainte token).

Vérification de première main des claims pré-flight :

  1. Organe inerte confirmé : j'ai parcouru les 150 workflows .yml de main — aucun ne référence refresh_stale_adjacency avant cette PR. Le constat fondateur (« existe avec ses tests, aucun appelant ») est exact, pas déclaratif.
  2. CLI du script recoupée sur main : --pr (append, required) et --dry-run existent bien (lignes 245/247) ; le marqueur <!-- refresh-adj: ISO8601 --> et son MARKER_RE idempotent aussi. L'appel du workflow (--pr N ... [--dry-run]) matche l'interface réelle.
  3. Nom du check vérifié : always-on-guards.yml:92 porte exactement Always-on guards -- 12 organes, 1 checkout ; le pré-filtre startswith("Always-on guards") + warning ::warning:: si zéro jambe (anti-silence #11808) couvre correctement le cas rename.
  4. Doctrine respectée : exit 0 systématique (rc=1 = adjacence réelle → journalisé seulement ; rc=2 = ::warning::), concurrency + cancel-in-progress: false, MAX_REFRESH=8 plafond, tri plus-ancien-d'abord, allowlist tranche 4 #14283 cohérente (schedule/workflow_dispatch, aucun trigger pull_request).
  5. Permissions minimales : contents: read + pull-requests: write (body-edit seul), GH_TOKEN: github.token — pas de secret tiers. Security scan : 0 match.

Un point mineur (non bloquant) : la ligne 221 se termine sans newline final (\ No newline at end of file) — GitHub Actions l'accepte, mais la convention YAML du repo mériterait le saut final.

Verdict : solide, câblage d'un organe jusqu'ici inerte, prêt à merger après CI. (Contrainte token : COMMENT only sur cet opener.)

@myia-ai-01

Copy link
Copy Markdown
Collaborator

[coordinateur — B.0 personnelle, head 43a969038a] Clause des 24 h de variation-protocol §3 : je merge, et je dis pourquoi le HOLD a duré 42 h.

Lu : body, les 3 commentaires d'organe, la review [Hermes] du 2026-09-09T11:44:53Z, le diff des 2 fichiers. check_unaddressed_nits.py → rc=0. Tous les check-runs verts à la tête exacte (19 distincts, PR gate success), mergeStateStatus: CLEAN.

Ce que j'ai revérifié plutôt que repris :

Pourquoi le HOLD a tenu 42 h, mesuré :

lane myia-po-2026:CoursIA — lane_grains 4, budget 1
  axe tier  : spent 0        -> tier_cap_reached  false   (MED, ne consomme pas)
  axe genre : light_genre 2  -> cap_exceeded_by_genre TRUE (genre_cap 1)
  consommé par : #15384 (MED/guard, mergé 2026-09-11T00:50:53Z)

Le budget de genre se réinitialise chaque jour UTC, et chaque jour il a été repris avant que cette PR ne passe — le 2026-09-09 par #15180, et aujourd'hui par #15384, que j'ai mergée moi-même à 00:50:53Z, sibling de la même lane et du même genre. C'est exactement la situation que la clause des 24 h existe pour clore : un plafond glissant qui re-bloque indéfiniment un travail déjà écrit et déjà vérifié. Le protocole donne deux issues — merger, ou fermer en nommant le remplaçant. Il n'y a pas de remplaçant à nommer : le livrable est le câblage d'un organe qui, sur main, existe avec ses tests et que zéro workflow n'appelle (Hermes l'a recoupé sur les 150 .yml). Fermer reviendrait à laisser l'organe inerte et à faire réécrire le même travail.

Ce qui me fait signer sur le fond : le dry-run sur le pool réel n'est pas un « ça devrait marcher ». 74 PR ouvertes balayées, 17 verdicts périmés que l'organe lèvera, 11 refusés à juste titre — dont #15328, une adjacence ledger→ledger réelle que le script laisse bloquée — et 0 real-fail. Ce refus correct est le contrôle négatif : l'organe discrimine, il n'ouvre pas les vannes. Et la doctrine est tenue au bon endroit — exit 0 systématique, rc=2 en ::warning::, jamais d'override, le garde reste l'autorité.

Je merge.

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

Labels

variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: refresh_stale_adjacency.py est sur main mais aucun workflow ne l'appelle (organe inerte, 24 h de blocage mesurees sur #15165)

3 participants