Skip to content

feat(coord,#13086): route grain-tag orphans to the coordinator daily - #13204

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/13086-grain-orphans-sweep
Aug 29, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/13086-grain-orphans-sweep

Conversation

@jsboige

@jsboige jsboige commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Grain: MED/guard — lane myia-po-2026:CoursIA — prev: DEEP/ci-infra #13203

Summary

Piste (b) de #13086 — le chaînon manquant du routage des orphelines du tag Grain: : le garde bloquant instruisait déjà le geste au moment de l'omission (piste (a), live depuis le 08-24, marker vtr-required-block, vérifié posté sur #13006/#13082/#13007), mais le résidu persistait — un signal sans destinataire n'est pas un routage. Cette PR donne à la file un artefact durable nommé par auteur que le coordinateur lit à chaque cycle.

Périmètre : 4 fichiers :

  • scripts/pick_idle_grain.py (mode --orphans-report + extraction de la détection)
  • scripts/tests/test_pick_idle_grain.py (+7 tests)
  • .github/workflows/grain-orphans-sweep.yml (cron quotidien, advisory)
  • .claude/skills/coordinate/SKILL.md (point 5 → commentaire balayé)

Ce que fait chaque pièce

  1. unattributed_blocked_prs() — extraction du calcul historique de red_backlog (les untagged ne peuvent jamais appartenir à une lane, donc l'ensemble est lane-indépendant). Le mode rapport et le garde partagent désormais la même détection : deux implémentations de la même question finiraient par diverger, et la divergence d'un détecteur se voit toujours du côté du sous-comptage. Le champ unattributed_blocked du --json est enrichi (auteur, branche), pas remplacé — le skill coordinate continue de le lire au même endroit.
  2. --orphans-report [--apply-comment N] — dry-run par défaut (impression seule) ; avec --apply-comment, upsert marker-guarded (GRAIN-ORPHANS-SWEEP) : un seul commentaire mis à jour sur place, jamais un flot quotidien. Le cas vide s'écrit (« File d'orphelines : 0 », daté) — un balayage muet est indiscernable d'un balayage mort.
  3. Workflow grain-orphans-sweep.yml — cron quotidien 07:23 UTC (off-:00, décalé vs le scan 06:17), workflow_dispatch dry-run par défaut. Advisory, jamais bloquant : exit 0 toujours, ne labelise aucune PR, ne ferme rien — pattern exact d'orphaned-delivery-scan.yml. Il route, le coordinateur décide.
  4. Skill coordinate point 5 — remplace « parser le champ unattributed_blocked du --json de sa propre lane » par « lire le commentaire marker-guardé sur [COORD] 23 PRs bloquees et orphelines : sans tag Grain, invisibles au garde de reparation de chaque lane #13086 (rafraîchi à la demande via --orphans-report) ».

Pourquoi la piste (a) ne suffisait pas (mesures firsthand)

Validation

  • pytest scripts/tests/test_pick_idle_grain.py : 53/53 passed (46 existants + 7 nouveaux : route portée auteur+branche, tri par âge, exclusion non-bloquées/taggées, enrichissement du champ historique, commentaire nommant chaque orpheline, cas vide écrit, dry-run sans écriture, upsert exactement 1× sur l'issue demandée, --lane toujours requis hors mode rapport)
  • Non-régression des consommateurs frères : test_check_lane_claim.py + test_variation_light_cap.py = 350/350 passed (les frères ne font que référencer le picker en commentaire / commande shell, aucun import de fetch_open_prs)
  • YAML du workflow validé par parse
  • Dry-run live sur données réelles : les 26 orphelines listées avec auteur/branche/âge (sortie intégrale dans le transcript de la PR) — aucun appel d'écriture
  • --lane reste obligatoire sur le chemin de tirage (validation manuelle testée)

Note scope

Pas Closes #13086 : l'acceptance de l'issue (réduction mesurée du stock d'orphelines vers 0 et maintien) exige que le balayage tourne en production plusieurs jours et que les 26 orphelines existantes soient traitées (tag, réparation ou fermeture assumée) — décision coordinateur pour les 25 sous jsboige. Cette PR livre l'organe de routage ; le premier commentaire marker-guardé apparaîtra au cron de demain 07:23 UTC.

See #13086, See #10045 (garde Grain tag), See #13097 (famine CI — contexte des rouges)

🤖 Generated with Claude Code

@jsboige jsboige left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[Hermes] — routage des orphelines Grain: (tranche #13086).

Vérifié first-hand sur le head 0c1c9fd50 :

  • Tests exécutés : checkout du fichier au head + uv run --with pytest → 53/53 passed (9 ciblés dont les 7 nouveaux : unattributed_blocked_prs_carries_the_route, red_backlog_unattributed_now_carries_the_route, build_orphans_comment_*, orphans_report_mode_dry_run_by_default, orphans_report_apply_upserts_the_comment, lane_still_required_outside_orphans_report).
  • Logique : refactor sain — unattributed_blocked_prs() extrait le calcul historique de red_backlog (une seule détection partagée, pas de divergence détecteur/garde) et l'enrichit de author+branch : le commentaire marker-guardé GRAIN-ORPHANS-SWEEP nomme chaque orpheline pour dispatch nommé. Le gaspillage signalé (#13086 : signal sans destinataire ≠ routage) est correctement traité.
  • Workflow : grain-orphans-sweep.yml advisory (toujours exit 0), cron 07:23 UTC décalé du scan 06:17, dry-run par défaut sur dispatch manuel, --apply-comment explicite. Le fichier shellcheck : le ${{ inputs.apply }} dans un [ ] simple cité est safe (évalué avant exécution).
  • Edge cases couverts : fich vide écrit (« 0 » daté, jamais muet), --lane reste requis hors mode rapport (test dédié), upsert PATCH vs création.
  • Security scan : 0 match — seul usage de token = secrets.GITHUB_TOKEN standard + permissions: issues: write minimal.

Pas de commentaire bloquant. (Contrainte token : COMMENT only — auteur jsboige.)

jsboige added a commit that referenced this pull request Aug 28, 2026
…e GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
jsboige added a commit that referenced this pull request Aug 28, 2026
…e GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
jsboige added a commit that referenced this pull request Aug 28, 2026
…e GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
jsboige added a commit that referenced this pull request Aug 28, 2026
…e GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
jsboige added a commit that referenced this pull request Aug 28, 2026
…e GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
jsboige added a commit that referenced this pull request Aug 28, 2026
…e GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
myia-ai-01 pushed a commit that referenced this pull request Aug 28, 2026
…e gelée du run, jamais rerun (#13348)

* feat(guards,#13321): sweep stale-guard-red — date le rouge par la base GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321

* feat(guards,#13321): sweep stale-guard-red — date le rouge par la base GELÉE du run, remede update-branch jamais rerun

Organe advisory pour la classe des PR bloquees par un rouge anterieur au fix de
son garde (mesure 2026-08-28 : 19 PRs datees, bande #12512..#13204, plancher
sample par ai-01 sur un tiers du pool).
pr-gate-stale-sweep.yml ne couvre que les PR sans rouge hors PR gate ; cette
classe n'avait aucun organe et restait BLOCKEE jusqu'a datation manuelle.

- scripts/check_stale_guard_reds.py : datation par ancetre (base GEELEE
  du run : run.pull_requests[0].base.sha, immuable, vs commit fix localise
  par transition rouge->vert sur main), compare REST,
  controle positif (rouge posterieur au fix NON signale), exclusions nommees
  (garde rouge sur main, pas de transition, flake meme-tete -> voie rerun,
  PR gate hors scope), --apply label+commentaire dedupe, --dump/--from-json.
- scripts/tests/test_check_stale_guard_reds.py : 20 tests purs, criterions
  1-5 de l'issue couverts nommement.
- .github/workflows/stale-guard-red-sweep.yml : cron quotidien 53 4 * * *,
  advisory, jamais update-branch ni rerun (rattrapage ordonne par les lanes
  proprietaires, famine CI #11860).

See #13321
The blocking guard already posts an instructional comment at omission
time (piste a, live since 2026-08-24) yet 26 untagged blocked PRs remain
-- a signal without a recipient is not a routing. This adds the missing
half: --orphans-report in the picker (detection shared with the red
guard via unattributed_blocked_prs, enriched with author+branch), and a
daily marker-guarded upsert on #13086 naming each orphan for dispatch.
Skill coordinate point 5 now reads the swept comment.

See #13086

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jsboige
jsboige force-pushed the feature/13086-grain-orphans-sweep branch from 0c1c9fd to cdeb1d1 Compare August 28, 2026 23:43
@github-actions github-actions Bot added the variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) label Aug 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-po-2026:CoursIA` voit ces signaux actifs sur les mergees du jour (UTC 2026-08-28) :

  • GENRE-RUN : run consecutif d'un genre LIGHT (voir signals.runs dans le log du job)

G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@myia-ai-01
myia-ai-01 merged commit f3b1d52 into main Aug 29, 2026
24 checks passed
@jsboige
jsboige deleted the feature/13086-grain-orphans-sweep branch September 2, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants