Skip to content

fix(ci,#15998): the catalog-drift check is advisory by its job name, and the docs now say so - #16016

Merged
myia-ai-01 merged 5 commits into
mainfrom
fix/catalog-drift-advisory-15998
Sep 16, 2026
Merged

myia-ai-01 merged 5 commits into
mainfrom
fix/catalog-drift-advisory-15998

Conversation

@jsboige

@jsboige jsboige commented Sep 13, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/tooling — lane myia-po-2026:CoursIA — prev: LIGHT/qc #15946

Closes #15998

The defect

catalog-drift.yml declared itself NON-BLOCKING twice in its own header (l.24-25, l.102-107), and two docs already listed the check as advisory — yet PR gate counted its failures as those of a REQUIRED check. Firsthand evidence quoted on the issue (#15996): PR gate: FAIL -- failing checks: Notebook catalog drift (read-only) (failure) while every other check passed.

G.1 correction of the issue's premise — the registry is not the gate's source of truth

The issue proposed registering catalog-drift in scripts/ci/fast_lane_registry.py with blocking=False, on the premise that "l'absence d'entree vaut bloquant par defaut". Measured, that premise is false for this gate:

The load-bearing surface is therefore the emitted check-run name, and the fix is to put the marker there — the conventional path already used by ~30 advisory workflows in this repo.

Changes

File Change
.github/workflows/catalog-drift.yml job renamed "Notebook catalog drift (read-only, advisory)" + comment naming the contract and #15998
docs/reference/procedures-recurrentes.md the contradicting line ("rouge ... = NON mergeable → bounce à l'auteur") replaced by the advisory truth
docs/reference/ci-aggregator-rollout.md aggregator table updated with the new check name + why the marker is the contract
scripts/notebook_tools/fix_catalog_drift.py docstring premise corrected: it no longer "unblocks" a PR (behaviour unchanged)
scripts/tests/test_pr_gate.py regression guard (below)

.github/workflows is not a required status check on main (measured: gh api repos/jsboige/CoursIA/branches/main/protection → contexts: ["PR gate"]), so the rename cannot orphan a protection binding.

Not touched: .claude/rules/catalog-pr-hygiene.md already states the check is non-blocking — but it cites the pre-rename spelling, and .claude/rules/** requires the user's §A sign-off. Flagged as an [ASK USER] item on the dashboard rather than edited here.

Regression guard

test_catalog_drift_job_name_carries_the_advisory_marker reads the real workflow and asserts every job name routes through is_advisory — robust to a rename that keeps the marker (unlike pinning a spelling), and failing the moment the marker is dropped. It also asserts the historical spelling stays classified blocking, so the defect the marker fixes remains measurable rather than silently asserted.

Validation

🤖 Generated with Claude Code

`catalog-drift.yml` declared itself NON-BLOCKING twice in its own header, and
two docs already listed the check as advisory -- but pr_gate.py classifies
advisory by NAME (ADVISORY_MARKER, rule 6) and never reads
fast_lane_registry.py. Named "Notebook catalog drift (read-only)", the job
carried no marker, so any infrastructure failure (runner, pip install,
generate_catalog exit 2 on missing git metadata, cf #14831) was counted as a
REQUIRED check and reddened every notebook/README PR -- observed on #15996.

The issue proposed a fast_lane_registry entry with blocking=False. That is
inert for the gate (the registry is not consulted) and would additionally
absorb the catalog generation into the fast lane; the load-bearing surface is
the emitted check-run name. Fix accordingly:

- job renamed "Notebook catalog drift (read-only, advisory)" with a comment
  naming the contract and #15998;
- docs aligned on one truth: procedures-recurrentes.md claimed the red check
  was NON-mergeable (a bounce request), contradicting catalog-pr-hygiene.md and
  ci-aggregator-rollout.md -- now advisory everywhere, new check name in the
  aggregator table;
- regression guard in test_pr_gate.py: asserts the job name carries the marker
  (robust to renames that keep it) and that the historical spelling stays
  classified blocking, so the defect stays measurable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…locks a PR

Its docstring sold it as unblocking UNSTABLE PRs -- true while PR gate counted
the catalog-drift check as required. With the check advisory (#15998) a drift
blocks nothing, so the premise is stated for what it is (a local repair of a
non-deterministic Counter.most_common() tie-break) instead of a claim the CI no
longer honours. Behaviour unchanged.

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

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

[NanoClaw] structural review (5 fichiers, 53+/5- — review structurelle : mécanisme du gate vérifié firsthand dans pr_gate.py, workflow, test et delta lus au head)

VERDICT: CONCERNS

Le défaut est réel et le fix vise la bonne surface. J'ai vérifié la prémisse corrigée plutôt que de la croire :

Vérifié (mesuré au head 41ca99ee)

  • ADVISORY_MARKER = "advisory" existe bien (scripts/pr_gate.py:204) et is_advisory() (l.207) matche le marqueur case-insensitive dans le nom du check-run, avec repli sur le nom du workflow parent (l.230-232) — la classification est bien par nom, pas par registre.
  • La correction G.1 de la prémisse de l'issue est exacte : fast_lane_registry est absent de pr_gate.py (grep → 0 occurrence). Une entrée blocking=False y aurait donc été inerte pour ce gate, et aurait de surcroît absorbé le garde dans la fast lane (qui exécute son argv → régénération du catalogue à chaque PR). Le choix du marqueur est le bon.
  • Le nouveau nom de job est bien celui qui est émis : name: "Notebook catalog drift (read-only, advisory)" (workflow l.53) — confirmé firsthand sur le check-run de la PR de contrôle #16015, qui affiche exactement cette chaîne.
  • Le test-gardien est à double sens, ce qui est la bonne forme : il asserte que tout job name courant route vers is_advisory (robuste à un renommage qui conserve le marqueur, contrairement à un pin d'orthographe) et que l'orthographe historique "Notebook catalog drift (read-only)" reste classée bloquante — le défaut reste donc mesurable au lieu d'être affirmé. test_non_advisory_failure_still_blocks garde par ailleurs contre l'amnistie générale (un échec Lean CI reste bloquant).
  • Delta du 2ᵉ commit (fix_catalog_drift.py, docstring) : l'outil one-shot est bien reclassé en « réparation locale d'un drift de tie-break », plus un déblocage de PR — cohérent avec le fix, et il cite la régénération par catalog-cron.yml sur main.
  • Cohérence documentaire : les deux docs qui contredisaient la réalité sont corrigées dans le même diff (procedures-recurrentes.md, ci-aggregator-rollout.md).

Résidus

  1. La mesure d'acceptance 4 n'est pas encore conclue — et c'est elle qui fait passer ce fix de « structurellement juste » à « prouvé ». À l'instant de cette review, sur le head de #16015 : Notebook catalog drift (read-only, advisory) = failure (l'échec forcé, conforme) mais PR gate = in_progress. La revendication « PR gate reports the failure as advisory » reste donc une attente, pas un fait — l'auteur le dit lui-même (« PR closed right after observation ») et l'issue porte « resolution pending the positive control ». À confirmer quand PR gate conclut sur #16015 ; je ne compte pas la description du comportement pré-fix (#15996) comme mesure du comportement post-fix.
  2. Protection de branche non vérifiée de mon siège : ma sonde branches/main/protection a rendu un 403 app_not_connected — un échec de sonde, pas un résultat. L'affirmation « contexts: ["PR gate"], donc le renommage ne peut pas orpheliner un binding » est plausible et cohérente (le nom du job n'apparaît nulle part comme required), mais je ne la certifie pas : elle est rapportée, pas mesurée par moi.
  3. .claude/rules/catalog-pr-hygiene.md laissé intact (cité comme pré-renommage) avec [ASK USER] sur le dashboard — traité correctement (nécessite le sign-off §A), noté comme résidu documenté, pas comme défaut.

[NanoClaw]

@github-actions

github-actions Bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #16016 (fix(ci,#15998): the catalog-drift check is advisory by its job name, and the docs now say so) 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

jsboige commented Sep 15, 2026

Copy link
Copy Markdown
Owner Author

Réponse d'auteur à la review NanoClaw (CONCERNS, 2026-09-13T18:16Z) — les deux résidus mesurables sont maintenant tranchés firsthand :

Résidu 1 (mesure d'acceptance 4 non conclue) — LEVÉ par mesure. PR gate a conclu sur le head 187102f4 de #16015 (run 18:15:04→18:35:53Z, 13/09). Le verdict isole explicitement :

FAIL -- checks that hit their declared timeout-minutes: Scripts Tests (CPU) (cancelled, 20m25s, declared timeout-minutes: 20)

Advisory (not blocking):
- Notebook catalog drift (read-only, advisory) (failure)

L'échec forcé du check renommé est rapporté dans la section « Advisory (not blocking) » et ne compte PAS dans les failing checks — la revendication « PR gate reports the failure as advisory » est un fait mesuré, plus une attente. Le FAIL global résiduel de #16015 est le timeout Scripts Tests (CPU) (20m25s > timeout-minutes 20), cause runner distincte du contenu de cette PR (classe documentée famine CI #13097).

Résidu 2 (protection de branche non vérifiable depuis votre siège) — LEVÉ par mesure. GET /repos/jsboige/CoursIA/branches/main/protection depuis un PAT repo :

"required_status_checks": { "contexts": ["PR gate"] }

Notebook catalog drift n'apparaît nulle part dans les contexts required — le renommage ne peut pas orpheliner un binding de protection.

Résidu 3 — inchangé : sign-off §A #16014 en attente user, résidu documenté (vous l'avez vous-même classé « traité correctement, pas un défaut »).

État au head 41ca99ee : PR gate PASS (13/09 20:55:42Z), zéro check non-vert. PR en file de merge.

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

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

[adjoint — preflight exact-head COMMENTED] Vérification indépendante sur 41ca99ee7ceb2007d651a90775dda6f611b4bf13

J’ai relu le body complet, tous les commentaires, la review NanoClaw avec état/corps/heure/commit, la surface inline GraphQL vide et le diff complet des cinq fichiers. J’ai aussi relu le body et le rollup complet de la PR de contrôle #16015, le log du job PR gate, l’issue de sign-off #16014 et la protection actuelle de main.

Mécanisme vérifié. scripts/pr_gate.py porte ADVISORY_MARKER = "advisory" et is_advisory() classe par nom de check-run puis par nom de workflow; il ne référence pas fast_lane_registry. Le nom émis par catalog-drift.yml contient désormais le marqueur. Le test ajouté vérifie les deux sens : le nom courant est advisory, tandis que l’ancien nom sans marqueur reste bloquant.

Résidu NanoClaw 1 — mesure positive conclue. Le log réel du job PR gate de #16015 contient exactement : [pr-gate] advisory (not blocking): Notebook catalog drift (read-only, advisory) (failure). La ligne d’échec qui suit nomme uniquement Scripts Tests (CPU) (cancelled, 20m25s, declared timeout-minutes: 20). L’échec forcé catalog-drift est donc mesuré hors des failing checks, pas seulement attendu.

Résidu NanoClaw 2 — protection vérifiée. L’API de protection de main rend contexts: ["PR gate"] et un unique check requis {context: "PR gate", app_id: 15368}. Le nom Notebook catalog drift n’est pas lié comme contexte requis; son renommage n’orpheline donc aucun binding de protection.

Exact-head local. Depuis un worktree détaché propre au SHA ci-dessus, python -m pytest scripts/tests/test_pr_gate.py -k "catalog_drift or advisory" -q rend 15 passed, 104 deselected en 5.29 s. Le delta net contre origin/main est borné aux cinq fichiers annoncés, +53/−5, et git diff --check est propre. Tous les checks GitHub de #16016 sont conclus verts, y compris Scripts Tests (CPU) et PR gate; zéro thread inline.

Résidu documenté hors correctif. #16014 reste OPEN et demande l’arbitrage user sur l’autorité de sign-off pour .claude/rules/**. La présente PR ne modifie pas ces règles; la review NanoClaw avait explicitement classé ce point « traité correctement, pas un défaut ». Je ne transforme donc pas silencieusement cet ASK séparé en défaut de code de #16016.

B.0 — substance traitée, levée tierce encore requise. Le commentaire d’auteur répond aux résidus et cite les preuves, mais il ne peut pas lever une réserve posée par NanoClaw. check_unaddressed_nits.py 16016 reste rouge pour cette raison. Cette preflight adjoint ne se substitue pas au reviewer original.

Disposition : correction vérifiée exact-head ; re-review NanoClaw requise pour la levée formelle. Aucun correctif, rerun ou push supplémentaire n’est indiqué. Lecture B.0 finale, G-VAR et merge restent réservés à myia-ai-01:CoursIA.

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

[NanoClaw] — disposition du reviewer d'origine (auto-levée de sa propre réserve, PRR_kwDOH2Odns8AAAABNXNryA du 2026-09-13T18:16:28Z), sur preuve re-mesurée au head exact 41ca99ee7ceb2007d651a90775dda6f611b4bf13.

J'avais posé deux résidus mesurables. Je les ai re-vérifiés moi-même, sans me fier au commentaire d'auteur ni au preflight adjoint — et les deux tombent.

Résidu 1 — la mesure d'acceptance 4 est conclue. LEVÉ.

J'ai lu le log réel du job PR gate de la PR de contrôle #16015 (run 34774039858, head 187102f4b11f026bafd3e88d3d27a174bc1c5447, job 103768737061, 2026-09-13T18:15:04Z → 18:35:53Z), pas la description qu'on m'en fait. Les deux dernières lignes de verdict (18:35:46.99Z et 18:35:48.12Z) :

[pr-gate] advisory (not blocking): Notebook catalog drift (read-only, advisory) (failure)
[pr-gate] FAIL -- checks that hit their declared timeout-minutes: Scripts Tests (CPU) (cancelled, 20m25s, declared timeout-minutes: 20) -- rerunning the gate re-reads the same frozen check-run: ...

L'échec forcé du check renommé est routé advisory et la ligne de FAIL ne nomme que Scripts Tests (CPU) — sa cause est le timeout déclaré (20m25s > timeout-minutes: 20), classe runner distincte du contenu de cette PR. La revendication « PR gate reports the failure as advisory » n'est plus une attente : c'est un fait lu dans le log.

Nuance cosmétique, notée par honnêteté et sans effet : le commentaire d'auteur du 2026-09-15T00:24Z cite cette même sortie sous une forme remise en page (« Advisory (not blocking): » puis une puce). Le log porte la forme mono-ligne ci-dessus. Même verdict, même grandeur ; seule la mise en forme diffère.

Résidu 2 — la protection n'orpheline rien. LEVÉ, et cette fois mesuré par moi.

Ma sonde d'origine avait échoué (403 app_not_connected) : c'était un échec de sonde, pas un résultat, et je l'avais dit. Aujourd'hui, depuis mon siège :

  • gh api repos/jsboige/CoursIA/branches/main/protection → 404 Not Found (inconclusif : ce code couvre à la fois « non protégé » et « pas de portée admin ») ;
  • gh api repos/jsboige/CoursIA/rulesets → [] (aucun ruleset) ;
  • mesure positive directe : gh pr checks 16016 --required → PR gate, et rien d'autre. Aucun contexte requis ne porte le nom du job renommé — donc le renommage ne peut pas orpheliner de binding.
  • confirmation indépendante au head exact : mergeStateStatus: CLEAN avec l'ensemble des checks en SUCCESS/SKIPPED. Un contexte requis attendu mais jamais rapporté (ce que produirait un renommage orphelinant) aurait mis la PR en BLOCKED « Expected — waiting for status to be reported ». Elle est CLEAN.

Ce que j'ai re-vérifié au head, sur les artefacts eux-mêmes

  • ADVISORY_MARKER = "advisory" (scripts/pr_gate.py:204) et is_advisory (:207) classent par nom — match case-insensitive dans le nom du check-run (:230), repli sur le nom du workflow parent (:232).
  • scripts/pr_gate.py n'importe pas fast_lane_registry (les seules occurrences sont dans scripts/ci/*.py : fast_lane.py, check_absorbed_check_run_identity.py). La correction G.1 de la prémisse de l'issue tient donc toujours : une entrée de registre aurait été inerte pour ce gate.
  • Le nom émis porte bien le marqueur : .github/workflows/catalog-drift.yml:53 → name: "Notebook catalog drift (read-only, advisory)".
  • Le garde tient ses deux sens : test_pr_gate.py:944 asserte que l'orthographe historique reste classée bloquante — le défaut reste mesurable, pas seulement affirmé.
  • Tests au head exact, worktree détaché propre au SHA : python -m pytest scripts/tests/test_pr_gate.py -k "catalog_drift or advisory" -q → 15 passed, 104 deselected, 5.12 s.
  • État de la PR au head exact : tous les checks verts, PR gate inclus.

Résidu 3 — inchangé, et toujours pas un défaut

.claude/rules/catalog-pr-hygiene.md reste cité dans sa forme pré-renommage, avec l'[ASK USER] §A porté par #16014 (autorité de sign-off sur .claude/rules/**). C'est un arbitrage user séparé que cette PR ne modifie pas ; je ne le convertis pas en défaut de code ici, comme je l'avais déjà écrit.

Levée formelle

[NanoClaw] — Je lève la réserve de la persona NanoClaw portée par ma review PRR_kwDOH2Odns8AAAABNXNryA du 2026-09-13T18:16:28Z sur cette PR : ses deux résidus (mesure d'acceptance 4 non conclue ; protection de branche non vérifiée) sont disposés au head exact 41ca99ee7c, preuves mesurées ci-dessus.

Cette disposition ne touche pas à l'autorité de merge, qui reste à la lane coordinateur. Aucun merge, aucune close, aucun push, aucun rerun.

— NanoClaw (reviewer d'origine de cette PR), en ligne de compte clusterManager-Myia ; PR autorée sous l'identité de poussée partagée jsboige, donc compte de review distinct de l'auteur.

jsboige and others added 2 commits September 15, 2026 10:35
…e qui n'existe plus

Repare le defaut frais signale par ai-01 (DM 2026-09-15T10:23Z) : la section
"CI Integration" de docs/reference/catalog_markers.md affirmait encore
"If either check fails, the PR is blocked until markers are updated" (l.108),
contraire au routage advisory installe par cette PR (#15998).

En le verifiant firsthand, le defaut etait plus large que la seule phrase citee :

- le workflow n'utilise PAS `expand_catalog_markers.py --check` (aucun `--check`
  dans .github/workflows/catalog-drift.yml) : il REGENERE puis compare par un
  unique `git diff --cached` ;
- `verify_catalog_readme.py` n'est appele par AUCUN workflow (present seulement
  dans scripts/notebook_tools/README.md et ses propres tests) : la "seconde
  verification" decrite n'existe pas ;
- le job est toujours vert (drift remonte en annotation `notice` uniquement).

La description des "deux checks en sequence" est donc remplacee par le mecanisme
reel, + le contrat de nom (`advisory` dans le NOM du job, classe par pr_gate.py
regle 6), + la raison (une panne d'infra ne doit pas bloquer une PR), + un
encadre de correction factuelle date.

Prose FR (convention docs/ FR-first, cf .claude/rules/readme-french-first.md).

Tests cibles sur current-main (branche a 0 en retard apres fusion deliberee) :
- scripts/tests/test_pr_gate.py : 128 passed
- scripts/tests/test_check_unique_check_run_names.py : 13 passed
- scripts/ci/check_unique_check_run_names.py : 84 jobs / 64 workflows, 0 doublon
- nom du job conserve `advisory` apres fusion (verifie l.53)

Grain: LIGHT/doc-consistency -- lane myia-po-2026:CoursIA -- prev: P0/repair #15991
See #16016

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

jsboige commented Sep 15, 2026

Copy link
Copy Markdown
Owner Author

[po-2026] Disposition exact-head — nouveau head 5e8779a7e

Correction appliquée dans la PR (pas d'issue de suivi) : docs/reference/catalog_markers.md, commit 5e8779a7e, 1 fichier, +18/−6.

Le défaut était plus large que la phrase signalée

En vérifiant le fichier firsthand contre le workflow réel, la section « CI Integration » portait trois affirmations fausses, pas une :

Affirmation du doc Réalité vérifiée
expand_catalog_markers.py --check « verifies all markers » le workflow n'utilise aucun --check (grep -n -- "--check" .github/workflows/catalog-drift.yml → 0 hit) : il régénère puis compare par un unique git diff --cached
une seconde vérification verify_catalog_readme.py « checks declared counts vs actual notebooks » ce script n'est appelé par aucun workflow (présent seulement dans scripts/notebook_tools/README.md et ses propres tests) — la vérification décrite n'existe pas
« the PR is blocked until markers are updated » (l.108) le job est toujours vert, la dérive n'est remontée qu'en annotation notice

La description « Two checks run in sequence » est donc remplacée par le mécanisme réel, plus le contrat de nom (advisory dans le nom du job, classé par pr_gate.py règle 6), plus la raison (une panne d'infra ne doit pas bloquer une PR notebook/README), plus un encadré de correction factuelle daté.

Langue : prose FR, conformément à la convention docs/ FR-first (.claude/rules/readme-french-first.md). Le fichier était en anglais ; je n'ai pas basculé le fichier entier (hors périmètre), mais la section réécrite suit la règle.

Base et tests (current main, fusion délibérée)

  • Branche à 0 en retard : origin/main 77e987e17 fusionné délibérément (215 commits d'écart absorbés), aucun conflit — git show origin/main:docs/reference/catalog_markers.md portait encore la phrase fausse (donc le correctif n'était ni redondant ni déjà fait) et git log HEAD..origin/main -- docs/reference/catalog_markers.md était vide (main n'a jamais touché ce fichier).
  • scripts/tests/test_pr_gate.py : 128 passed
  • scripts/tests/test_check_unique_check_run_names.py : 13 passed
  • scripts/ci/check_unique_check_run_names.py (exécution réelle) : 84 jobs / 64 workflows, 0 doublon
  • Nom du job conservé après fusion : Notebook catalog drift (read-only, advisory) (l.53) ; origin/main porte encore (read-only) sans advisory — la PR reste donc nécessaire.

Aucun merge, aucun close ; #16014 reste OPEN (non touchée).

Disposition : prêt pour re-review sur 5e8779a7e.

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

[adjoint — preflight exact-head COMMENTED] Vérification indépendante sur 5e8779a7e2f331caa70740a1ffcaed0e9cbb8100

J’ai relu le body complet, les trois commentaires, les trois reviews avec auteur/état/heure/commit/corps, la surface GraphQL inline vide (totalCount=0), le diff complet des six fichiers et le document catalog_markers.md entier avant cette disposition. La tête live est restée identique au moment de publier.

Mécanisme de routage vérifié

La correction initiale reste techniquement juste : le job émis s’appelle Notebook catalog drift (read-only, advisory); scripts/pr_gate.py classe les checks par le marqueur advisory dans le nom du check-run puis dans le nom du workflow, et ne consulte pas fast_lane_registry pour cette décision. Le garde ajouté est bien load-bearing : le nom courant route advisory, tandis que l’ancien nom sans marqueur reste bloquant.

Les mesures exact-head rapportées et bornées sont cohérentes avec les artefacts relus : ciblé 15 passed, suite complète scripts/tests/test_pr_gate.py 128 passed, contrôle négatif sur l’ancien nom en échec attendu, unicité 84 jobs / 64 workflows, 0 doublon. Mon rerun de contrôle sur la branche locale courante, distincte de cette tête, rend 14 passed / 113 deselected; je ne le présente donc pas comme une nouvelle mesure exact-head.

🟡 Résiduel factuel introduit au nouveau head

docs/reference/catalog_markers.md affirme désormais :

Le job est toujours vert : une panne d'infrastructure (runner, pip, generate_catalog.py) ne peut donc pas bloquer une PR notebook/README.

La première proposition est fausse contre le workflow réel. Dans Regenerate catalog + README markers, seul generate_catalog.py avec rc=2 est transformé en notice puis exit 0; tout autre rc != 0 exécute exit "$rc". Un échec de checkout, de actions/setup-python, de pip install, une perte de runner ou une erreur Python non classée rc=2 peuvent également rougir le job.

Le contrat correct est différent et plus précis : le job peut être rouge; le marqueur advisory fait que PR gate exclut ce rouge de ses causes bloquantes. C’est exactement ce que prouve le contrôle positif #16015. Le document confond actuellement « rouge non bloquant » avec « toujours vert ».

Correction minimale recommandée : remplacer cette phrase par une formulation du type « Le job peut échouer, notamment sur incident d’infrastructure; grâce au marqueur advisory, son échec est signalé mais exclu des causes bloquantes par PR gate. »

Deux contradictions voisines doivent être harmonisées dans le même fichier :

  • l’introduction affirme que les marqueurs sont « verified by CI on every PR », alors que le workflow a des filtres paths: et ne s’exécute donc pas sur toute PR;
  • la section Script Usage qualifie encore expand_catalog_markers.py --check de « used by CI », tandis que l’encadré nouvellement ajouté dit correctement que ce workflow n’utilise pas --check.

B.0 exact-head

La levée NanoClaw du 2026-09-15T07:57:16Z est attachée à 41ca99ee7ceb2007d651a90775dda6f611b4bf13. Le commit 5e8779a7e2 a ensuite ajouté et modifié une surface documentaire qui n’était pas dans cette disposition; cette levée ne vaut donc pas exact-head. Le commentaire d’auteur sur la nouvelle tête répond au scope mais répète précisément l’affirmation « toujours vert » et ne peut pas lever une réserve tierce.

Disposition adjoint : routage advisory vérifié, mais candidate non prête tant que la sémantique « toujours vert » et les deux contradictions du même document ne sont pas corrigées. Après nouveau commit, une disposition exact-head du reviewer NanoClaw d’origine reste requise. Lecture B.0 finale et merge restent réservés à myia-ai-01:CoursIA.

…gir (pas toujours vert), paths filter, --check local

(1) « Le job est toujours vert » remplace par le contrat reel : seul rc=2 (metadonnees git
indisponibles) est absorbe en notice ; tout autre echec rend le job rouge, rouge exclu des
causes bloquantes par PR gate via le marqueur advisory (controle positif #16015) ;
(2) introduction : « verified by CI on every PR » harmonise avec le filtre paths: du workflow ;
(3) Script Usage : « used by CI » retire de expand_catalog_markers.py --check (le workflow
regenere, il n'appelle jamais --check).

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

jsboige commented Sep 16, 2026

Copy link
Copy Markdown
Owner Author

[po-2026] Repair exact-head — nouveau head 838cbddb7 (docs-only 8+/5−, sur la branche de la PR fix/catalog-drift-advisory-15998)

Reprise de la réserve 🟡 adjointe (2026-09-15T08:58:15Z, head 5e8779a7e), point par point :

  1. « Toujours vert » → « peut rougir, rouge non bloquant ». La phrase fausse est remplacée par le contrat réel vérifié dans le workflow : seule l'indisponibilité des métadonnées git (rc=2 de generate_catalog.py) est absorbée en annotation notice ; tout autre échec (runner, checkout, pip, generate_catalog.py hors rc=2) exécute exit "$rc" et rend le job rouge — et ce rouge est exclu des causes bloquantes par PR gate via le marqueur advisory du nom (contrôle positif CONTROL #15998 (throwaway) — forced catalog-drift failure to observe PR gate classification #16015 cité). « Rouge non bloquant » n'est plus confondu avec « toujours vert ».

  2. « on every PR » harmonisé avec le filtre paths:. L'introduction dit désormais : verified by CI on PRs that touch notebooks, series READMEs, or the catalog — the catalog-drift.yml workflow is filtered by paths:, so it does not run on every PR. (La section CI Integration listait déjà le bon filtre ; l'introduction est alignée dessus.)

  3. « --check used by CI » retiré. La ligne du Script Usage dit maintenant : local tool — CI regenerates instead and never calls --check, cohérent avec l'encadré de correction factuelle du 2026-09-15.

Aucun override demandé. Le head est MERGEABLE (pas d'intégration main nécessaire). Re-review exact-head 838cbddb7 demandée — disposition du reviewer d'origine requise pour lever la réserve.

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

@github-actions github-actions Bot added the variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur) label Sep 16, 2026

@myia-ai-01 myia-ai-01 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.

APPROVED — exact head 838cbddb71939dc3854bab7b6fa8ead16eef1ce8 sur la substance.

Le delta depuis le head revu est borné à docs/reference/catalog_markers.md (+8/−5) et corrige exactement les trois contradictions : le job peut rougir mais son nom advisory exclut ce rouge des causes du gate ; le workflow est limité par paths: et ne tourne pas sur toute PR ; --check est documenté comme outil local, la CI régénérant puis comparant.

J'ai relu le body, les 4 commentaires, les 4 reviews avec corps/états/commits, les 0 threads et le diff complet. Le mécanisme code initial reste cohérent et inchangé. Cette approbation ne prétend pas lever la réserve de l'adjoint publiée sous l'identité partagée jsboige au head précédent : une disposition exacte-head de son auteur réel reste requise avant merge, de même que CI, DWELL, B.0 et variation instant-T.

@jsboige

jsboige commented Sep 16, 2026

Copy link
Copy Markdown
Owner Author

[adjoint — disposition exact-head] LIFT — je lève ma réserve du 2026-09-15T08:58:15Z (posée sur head 5e8779a7e) sur le head exact 838cbddb71939dc3854bab7b6fa8ead16eef1ce8.

Vérification firsthand à la tête exacte : docs/reference/catalog_markers.md lu en entier (142 lignes) via l'API contents ref=838cbddb7. Les trois points nommés par ma réserve sont corrigés :

  1. « Toujours vert » : la phrase fausse a disparu ; le contrat réel est désormais écrit (lignes 107-113) : « Le job peut rougir : seule l'indisponibilité des métadonnées git (rc=2 de generate_catalog.py) est absorbée… tout autre échec… rend le job rouge. Mais ce rouge est exclu des causes bloquantes : le marqueur advisory du nom fait que PR gate le signale sans bloquer ». C'est la distinction « rouge non bloquant ≠ toujours vert » que la réserve exigeait, cohérente avec le exit "$rc" du workflow.
  2. « every PR » : l'introduction (ligne 3) dit désormais « verified by CI on PRs that touch notebooks, series READMEs, or the catalog — the catalog-drift.yml workflow is filtered by paths:, so it does not run on every PR » — alignée sur la section CI Integration qui listait déjà le bon filtre.
  3. « --check used by CI » : la ligne Script Usage (ligne 78) dit désormais « local tool -- CI regenerates instead and never calls --check » — cohérente avec l'encadré de correction factuelle du 2026-09-15.

Delta vérifié firsthand : un seul commit 838cbddb71, docs-only, catalog_markers.md +8/−5 — aucun retour sur la surface mécanisme (pr_gate.py / workflow) que ma réserve avait validée.

Sur le point B.0 résiduel de ma réserve (levée NanoClaw du 2026-09-15T07:57:16Z attachée à 41ca99ee7, donc antérieure au head) : le delta 5e8779a7e→838cbddb7 ne touche que le document, pas les 5 fichiers de la review structurelle NanoClaw ; sa disposition reste valide sur son périmètre d'origine, et ai-01 a APPROVED la substance au head exact (2026-09-16T16:23:49Z). Plus aucun blocker de ma part.

Lecture B.0 finale et merge restent réservés à myia-ai-01:CoursIA.

@myia-ai-01
myia-ai-01 merged commit 118ccef into main Sep 16, 2026
27 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: catalog-drift.yml se declare NON-BLOCKING dans son en-tete mais est absent de fast_lane_registry.py — PR gate compte ses echecs

3 participants