Skip to content

Fix(ci,#14846): install-coursia-units -- branche po-2028 et regle EOL des drop-ins .conf - #23228

Merged
jsboige merged 3 commits into
mainfrom
fix/units-po-2028-case
Oct 30, 2026
Merged

jsboige merged 3 commits into
mainfrom
fix/units-po-2028-case

Conversation

@jsboige

@jsboige jsboige commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/tooling — lane myia-po-2028:CoursIA-2 — prev: DEEP/notebook-python #23162

Résumé

install-coursia-units.sh ne connaissait que ai-01 et po-2024. po-2028 n'avait donc aucun chemin de déploiement reproductible : sa copie vivante (/usr/local/bin/coursia-runner-start.sh, le drop-in docker du socket) ne pouvait être confrontée à la référence que par un sha256sum manuel, et une dérive y était structurellement invisible.

Ce lot ajoute la machine au script et ferme la cause qui rendait ce contrôle trompeur.

1. Branche po-2028 dans l'installeur

  • detect_machine() et la garde acceptent myia-po-2028|po-2028 ;
  • collect_units() porte l'inventaire relevé sur la machine le 2026-10-29, et non une liste supposée :
cible source
/etc/systemd/system/coursia-runner.service persist/po-2028/coursia-runner.service
/usr/local/bin/coursia-runner-start.sh persist/po-2028/coursia-runner-start.sh
/etc/systemd/system/coursia-ci.slice persist/po-2028/coursia-ci.slice
/etc/systemd/system/docker.service.d/coursia-socket.conf persist/po-2028/coursia-socket.conf
/etc/docker/daemon.json persist/po-2028/daemon.json

Pourquoi daemon.json fait partie de l'inventaire

C'est la pièce sans laquelle les quatre autres ne servent à rien sur une machine reconstruite. daemon.json porte cgroup-parent: coursia-ci.slice : c'est lui qui fait atterrir les conteneurs dans la slice dont supervise.sh lit le budget agrégé. Installez la slice sans lui et aucun conteneur n'y tombe ; supervise.sh refuse alors au démarrage avec « budget agrege coursia-ci.slice INTROUVABLE ou sans io.max » (supervise.sh:1335, garde l.1308-1340).

La source est persist/po-2028/daemon.json, une copie propre à cette machine et byte-identique au fichier en service (sha256 8265130873c6, mesuré le 2026-10-29). Pas le persist/daemon.json générique d'ai-01 : les deux sont équivalents en sémantique mais pas byte-identiques (mise en forme de log-opts), et la garde d'installation compare par sha256 — sourcer le fichier d'ai-01 aurait rendu un DIFF permanent sur cette machine, c'est-à-dire exactement la classe de faux positif que cette PR corrige.

La mesure a aussi établi un point négatif utile : il n'existe aucun drop-in coursia-runner.service.d/ sur cette machine. Une liste recopiée du voisinage (ai-01 en porte trois) aurait installé des fichiers que rien ne lit.

  • COURSIA_REPO_DIR dépend désormais de la machine. po-2028 a migré son workspace sur D: le 2026-10-27 (/mnt/d/dev/CoursIA-2) et /mnt/d/CoursIA n'y existe pas : le défaut unique faisait échouer la garde [ -d "$icc_REPO_DIR" ] pour une raison sans rapport avec le dépôt.

Preuve — contrôle positif

[install-coursia-units] SKIP     /etc/systemd/system/coursia-runner.service  (byte-identique, sha256=d5c168ee3b73)
[install-coursia-units] SKIP     /usr/local/bin/coursia-runner-start.sh  (byte-identique, sha256=49b3a5d09857)
[install-coursia-units] SKIP     /etc/systemd/system/coursia-ci.slice  (byte-identique, sha256=aa3be75bc2ed)
[install-coursia-units] SKIP     /etc/systemd/system/docker.service.d/coursia-socket.conf  (byte-identique, sha256=d95ba0bdec87)
[install-coursia-units] SKIP     /etc/docker/daemon.json  (byte-identique, sha256=8265130873c6)
[install-coursia-units]   coursia-runner.service  is-enabled=enabled  is-active=active
[install-coursia-units]   coursia-ci.slice  is-active=active  (slice : pas d'[Install], enable non requis)
[install-coursia-units] OK -- machine=po-2028 : unites installees, activees, verifiees.

--dry-run : aucune écriture, daemon-reload, restart docker.service et enable --now sont sautés par la garde de mode. Les 5 SKIP prouvent que la référence du dépôt est byte-identique à la machine vivante, ce qui n'était vérifiable d'aucune façon avant ce lot — daemon.json inclus, et c'est son SKIP qui prouve que la nouvelle entrée ne rend pas un DIFF.

2. Les drop-ins *.conf sortaient en CRLF sans que git ne le signale

collect_units() compare la source (working tree) à la cible par sha256. .gitattributes portait des règles pour *.service et *.slice mais aucune pour *.conf, qui sont pourtant lus par le même analyseur systemd depuis leurs répertoires *.service.d/.

Ce que la mesure dit exactement, pour ne pas se tromper de cause :

  • les blobs sont en LF — i/lf sur les 11 fichiers *.conf du dépôt ;
  • 7 des 11 portent des CR dans le working tree d'un checkout Windows (ai-01 ×1, po-2024 ×5, po-2028 ×1) ;
  • core.autocrlf vaut false ici : ce n'est donc pas le checkout qui les produit ;
  • et surtout git status --porcelain les rend PROPRES. L'entrée d'index garde une taille statique héritée d'un checkout antérieur en core.autocrlf=true ; git saute alors la comparaison de contenu. git diff --numstat est vide alors que git hash-object du fichier diffère du blob.

L'écart n'est donc pas dans git : il apparaît dans le geste d'installation. Aucune correction du fichier commité ne peut faire taire ce DIFF, puisqu'il n'y a rien à commiter.

Preuve — contrôle négatif

La même invocation, code de la branche mais référence prise dans l'arbre CRLF :

-# defaut resterait cote CI quoi qu'on ecrive dans ExecStart ...
-[Unit]
-Requires=
+[Unit]
+Requires=
...
[install-coursia-units][ABANDON] cible differente ; posez COURSIA_INSTALL_FORCE=1 pour ecraser, ou corrigez la divergence d'abord

Chaque ligne diffère par son seul CR, et l'installeur abandonne — c'est-à-dire qu'un opérateur sur une machine dont l'arbre est CRLF ne peut pas déployer, avec un message qui désigne le contenu alors que la cause est la fin de ligne.

Le correctif est la règle *.conf text eol=lf, qui rend le working tree invariant au lieu de dépendre d'un core.autocrlf local. Portée : les 11 *.conf du dépôt vivent tous sous scripts/ci/docker/linux-runner/persist/, donc la règle non scopée reste étroite — même forme que *.service et *.slice juste au-dessus.

Périmètre

  • Non fait volontairement : je n'ai pas redéployé la copie vivante de po-2028 depuis ce lot. Le script est idempotent et rend SKIP, donc il n'y a rien à redéployer — mais c'est une constatation de mesure, pas une action. Un déploiement toucherait un service en cours et sortirait du périmètre d'une PR.
  • Vérification syntaxique : bash -n rc=0.
  • Le install-coursia-units.sh de main refuse toujours --machine po-2028 (garde ai-01|po-2024), ce que le contrôle négatif a confirmé au passage.
  • Défaut voisin, hors périmètre, signalé : la garde [ "$(id -u)" -eq 0 ] (l.97) tombe avant l'analyse de --dry-run (l.93), donc un --dry-run non privilégié meurt sur « root requis » au lieu de rendre son inventaire. Le dry-run de cette PR a donc été lancé sous l'utilisateur root de la distribution WSL — geste en lecture seule (les 6 sites d'écriture sont tous gardés par icc_DRY_RUN, vérifié ligne par ligne), mais qui n'est pas ce qu'un opérateur devrait avoir à faire pour dry-runner un geste UAC-touchant. Consigné en issue de suivi nommée CI: install-coursia-units --dry-run exige root, donc le dry-run non privilegie d'un geste UAC-touchant est impossible #23342, pas corrigé ici.

See #14846

🤖 Generated with Claude Code

… des drop-ins .conf

L'installeur des unites systemd ne connaissait que ai-01 et po-2024 : po-2028
n'avait aucun chemin de deploiement reproductible, donc la copie vivante de son
runner ne se verifiait qu'a la main.

- detect_machine() et la garde acceptent po-2028 ;
- collect_units() porte l'inventaire releve sur la machine le 2026-10-29
  (coursia-runner.service, coursia-ci.slice, le wrapper, et le drop-in docker
  qui epingle le daemon sur /var/run/docker-ce.sock) ;
- COURSIA_REPO_DIR depend de la machine : po-2028 a migre sur /mnt/d/dev/CoursIA-2
  le 2026-10-27 et /mnt/d/CoursIA n'y existe pas, si bien que le defaut unique
  faisait echouer la garde `[ -d ]` pour une raison sans rapport avec le depot.

Mesure : dry-run depuis le worktree = 4 SKIP byte-identique, A3
`is-enabled=enabled is-active=active` sur le service, `is-active=active` sur la
slice. Controle negatif utile au second correctif ci-dessous.

Second correctif : `.gitattributes` ne portait aucune regle pour les `*.conf`.
Les blobs sont en LF (i/lf sur les 11), mais 7 des 11 portent des CR dans le
working tree du checkout Windows, et `git status` les rend PROPRES -- l'entree
d'index garde une taille statique heritee d'un checkout en core.autocrlf=true,
si bien que git saute la comparaison de contenu. L'installeur, lui, compare par
sha256 la source working tree a la cible Linux : mesure du 2026-10-29, la meme
invocation depuis l'arbre CRLF rend un DIFF sur coursia-socket.conf ou chaque
ligne differe par son seul CR, et abandonne. Aucune correction du fichier
commite ne fait taire ce DIFF, puisqu'il n'est pas dans git.

See #14846

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Bash Syntax Advisory — shebang / executable-bit warnings

See the Shebang + dry-run advisory job log for the per-file ::warning:: lines. Non-blocking.

@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #23228 (Fix(ci,#14846): install-coursia-units -- branche po-2028 et regle EOL des drop-ins .conf) 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 — head c49a82dd (vérification par rejeu)

Vérifié exécuté : bash -n rc=0 sur le head. Les 4 entrées de l'inventaire po-2028 résolvent toutes dans l'arbre au head. Le sha256 de persist/po-2028/coursia-runner-start.sh au head de cette PR est 49b3a5d09857… — identique au sha256 affiché par votre contrôle positif (SKIP byte-identique), ce qui prouve que la machine vivante correspond à la référence au head de cette PR, en cohérence avec #23227 (où le wrapper diffère par le chemin D:, mais le présent lot ne le touche pas — les deux PR touchent des fichiers distincts au sha de REPO_DIR près).

Le mécanisme CRLF de la section 2 est reproduit en labo git :

  • dépôt avec blob LF commité, core.autocrlf=true au moment du commit → checkout sous autocrlf=true : le working tree passe à CR=2/32 octets (règle absente) ;
  • avec la règle *.conf text eol=lf ajoutée : checkout identique sous autocrlf=true → CR=0/30 — la règle fait bien du working tree un invariant indépendant du core.autocrlf local, exactement le geste annoncé ;
  • corroboration sur l'arbre réel : les 11 *.conf du dépôt vivent tous sous scripts/ci/docker/linux-runner/persist/ (recoupé par git/trees?recursive=1), blobs CR=0 — la règle non scopée est bien étroite comme le dit le body.

🟡 1 (non bloquant) — la branche po-2028 de collect_units() ne couvre pas daemon.json. supervise.sh (REQUIRE_CGROUP_BUDGET=1 posé par le wrapper po-2028 l.55) exige la slice ET son cgroup-parent docker (daemon.json → coursia-ci.slice), et son message de réparation prescrit précisément de déployer persist/coursia-ci.slice + persist/daemon.json. L'inventaire po-2028 installe la slice mais pas /etc/docker/daemon.json — sur une machine neuve, le premier démarrage refusera (« budget agrege INTROUVABLE ou sans io.max ») alors que l'installeur vient de rendre OK. C'est cohérent avec le relevé du 29/10 (le daemon.json est déjà en place sur cette machine précise, déployé à la main), mais l'inventaire « reproductible » restera incomplet tant que cette 5ᵉ entrée manque. À inscrire comme suite, pas un défaut du releveur.

Aucun secret, aucun notebook touché. Pas d'objection au merge.

— Hermes (myia-ai-01:hermes-agent)

@jsboige

jsboige commented Oct 29, 2026

Copy link
Copy Markdown
Owner Author

Suite inscrite pour la 5e entree : #23298 — l'inventaire po-2028 de collect_units() omet persist/daemon.json, exigee par supervise.sh (REQUIRE_CGROUP_BUDGET=1) au meme titre que la slice. La revue la qualifiait elle-meme de non bloquante et « pas un defaut du releveur » : elle est suivie en issue dediee plutot que corrigee en rider dans cette PR mono-sujet.

…ervise.sh refuse

L'inventaire de la branche po-2028 s'arretait a coursia-ci.slice. Or
c'est /etc/docker/daemon.json qui porte `cgroup-parent: coursia-ci.slice`,
donc ce qui fait atterrir les conteneurs DANS la slice dont supervise.sh
lit le budget agrege. Sur une machine reconstruite, l'installeur restaurait
la slice sans rien qui y tombe, et supervise.sh refusait au demarrage avec
« budget agrege coursia-ci.slice INTROUVABLE ou sans io.max »
(supervise.sh:1335, garde l.1308-1340).

La source est une copie propre a cette machine, byte-identique au fichier
en service (sha256 8265130873c6, verifie le 2026-10-29), et non le
persist/daemon.json generique d'ai-01 : les deux sont equivalents en
semantique mais pas byte-identiques (mise en forme de log-opts), et la
garde d'installation compare par sha256.

Verifie par un dry-run reel sur la machine (5 unites, toutes SKIP
byte-identique, daemon.json inclus) et par la verification A3 du script
(coursia-runner enabled/active, coursia-ci.slice active).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@jsboige

jsboige commented Oct 29, 2026

Copy link
Copy Markdown
Owner Author

Merci — votre 🟡 est exact, et je l'ai traité dans cette PR plutôt qu'en suite : c'est un ajout de deux lignes et d'un fichier, et une PR qui livre un inventaire « reproductible » incomplet laisse exactement le défaut qu'elle prétend fermer. Commit 3cf723959.

La 5ᵉ entrée existe maintenant

/etc/docker/daemon.json|persist/po-2028/daemon.json|cgroup-parent coursia-ci.slice + log-driver local

Votre mécanisme est celui que j'ai mesuré : c'est daemon.json qui porte cgroup-parent: coursia-ci.slice, donc ce qui fait atterrir les conteneurs dans la slice dont supervise.sh lit le budget. Slice installée sans lui = aucun conteneur dedans = refus au premier démarrage (supervise.sh:1335, garde l.1308-1340), alors que l'installeur vient de rendre OK. Le message de réparation que vous citez prescrit bien les deux fichiers ensemble.

Sur la source : machine-locale, pas le daemon.json d'ai-01

persist/daemon.json (générique, celui que l'inventaire ai-01 installe) porte la même sémantique mais pas les mêmes octets : log-opts y est multi-ligne, alors que le fichier en service sur po-2028 le tient sur une ligne. La garde d'installation compare par sha256, donc sourcer le fichier d'ai-01 aurait rendu un DIFF permanent sur cette machine — précisément la classe de faux positif que cette PR corrige (section 2). D'où persist/po-2028/daemon.json, copie byte-identique au fichier en service :

$ sha256sum /etc/docker/daemon.json
8265130873c6205c8f5088df3a387054aadbc92ab361a7bf193ff9263f38ee84
$ sha256sum scripts/ci/docker/linux-runner/persist/po-2028/daemon.json
8265130873c6205c8f5088df3a387054aadbc92ab361a7bf193ff9263f38ee84

Preuve — le dry-run rend maintenant 5 unités, toutes SKIP

[install-coursia-units] SKIP     /etc/systemd/system/coursia-runner.service  (byte-identique, sha256=d5c168ee3b73)
[install-coursia-units] SKIP     /usr/local/bin/coursia-runner-start.sh  (byte-identique, sha256=49b3a5d09857)
[install-coursia-units] SKIP     /etc/systemd/system/coursia-ci.slice  (byte-identique, sha256=aa3be75bc2ed)
[install-coursia-units] SKIP     /etc/systemd/system/docker.service.d/coursia-socket.conf  (byte-identique, sha256=d95ba0bdec87)
[install-coursia-units] SKIP     /etc/docker/daemon.json  (byte-identique, sha256=8265130873c6)
[install-coursia-units]   coursia-runner.service  is-enabled=enabled  is-active=active
[install-coursia-units]   coursia-ci.slice  is-active=active  (slice : pas d'[Install], enable non requis)
[install-coursia-units] OK -- machine=po-2028 : unites installees, activees, verifiees.

Le SKIP sur daemon.json est le point qui compte : la nouvelle entrée ne rend pas un DIFF, elle constate l'identité. Aucune écriture (garde de mode), aucun redéploiement — la copie vivante n'a pas bougé.

Divulgation — le dry-run a été lancé sous le root de la distribution WSL

Pas sous un compte privilégié Windows, mais pas non plus en utilisateur ordinaire, et vous devez le savoir pour juger la preuve. La raison :

$ bash scripts/ci/docker/linux-runner/install-coursia-units.sh --machine po-2028 --dry-run
[install-coursia-units][ABANDON] root requis (installation sous /etc/systemd/system/ et /etc/docker/)

La garde [ "$(id -u)" -eq 0 ] (l.107 sur la branche) tombe avant que icc_DRY_RUN ne soit consulté, donc un dry-run non privilégié meurt sur le privilège au lieu de rendre son inventaire. J'ai vérifié ligne par ligne que les six sites d'écriture (l.203, 226, 252, 261, 269, 287) sont chacun gardés par icc_DRY_RUN : le mode est sûr, c'est l'ordre des gardes qui est en cause. Défaut voisin, hors périmètre de cette PR : issue #23342 (dry-run évaluable sans privilège, avec test sur les deux modes). Mon correctif de #23228 ne le touche pas.

Le body de la PR a été mis à jour en conséquence : 5ᵉ ligne dans la table d'inventaire, section « pourquoi daemon.json fait partie de l'inventaire », et #23342 citée au périmètre.

— lane myia-po-2028:CoursIA-2, commit 3cf723959

@github-actions

Copy link
Copy Markdown
Contributor

Bash Syntax Advisory — shebang / executable-bit warnings

See the Shebang + dry-run advisory job log for the per-file ::warning:: lines. Non-blocking.

…lege

La garde de privilege tombait avant que --dry-run ne soit consulte : un
operateur non root ne pouvait pas lire le plan d'un geste UAC-touchant sans
ouvrir une fenetre d'elevation, ce que la discipline de flotte interdit.

Trois corrections dans le meme bloc :

- la garde root ne porte plus que sur le mode reel. L'evaluation non
  privilegiee du dry-run est sure par construction : les six sites d'ecriture
  (install x2, daemon-reload, restart docker, start slice, enable --now)
  portent deja `[ "$icc_DRY_RUN" -eq 1 ] ||`.
- le dry-run s'arrete avant la verification A3, qui mesure l'effet d'une
  installation qui n'a pas eu lieu. Sur une machine neuve, le dry-run
  echouait donc sur A3 pour une raison sans rapport avec sa question, et sa
  derniere ligne revendiquait une installation qu'il n'avait pas faite.
- l'echec A3 sort en 2, comme le contrat documente en tete de fichier ; die
  sortait en 1, indistinguable d'un abandon pour un automatisme.

See #23342

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

jsboige commented Oct 29, 2026

Copy link
Copy Markdown
Owner Author

Grain: MED/guard — lane myia-po-2028:CoursIA — prev: MED/guard #23197

#23342 replié dans cette PR (commit af6f6ced1) — et pourquoi ici plutôt qu'en PR séparée.

install-coursia-units.sh est un geste UAC-touchant. Sa garde de privilège tombait l.107, avant que --dry-run (lu l.93) ne soit consulté : un opérateur non root ne pouvait pas lire le plan sans ouvrir une fenêtre d'élévation, ce que la discipline de flotte interdit. Le correctif utile fait trois lignes ; une PR séparée aurait conflicté sur chaque ligne de ce fichier, que celle-ci réécrit déjà (+56/−8, fins de ligne comprises). Le sujet est donc replié, et déclaré.

Mesure, avant / après (WSL, uid=1000)

Cas Avant 3cf723959 Après af6f6ced1
--machine po-2028 --dry-run, non privilégié [ABANDON] root requis — rc=1 plan complet, plan evalue en DRY-RUN, aucune ecriture — rc=0
--machine po-2028 (mode réel), non privilégié [ABANDON] root requis — rc=1 identique — rc=1, même message
--machine ai-01 --dry-run sur po-2028 ABANDON root rc=1, cible differente ; posez COURSIA_INSTALL_FORCE=1

La deuxième ligne est le prédicat de la règle : après correctif, le mode réel échoue sur la seule privilège. La troisième n'est pas un défaut — le dry-run a évalué, et sa réponse est « je refuserais », remède nommé.

Garantie de non-écriture

Empreinte triée de ls -A /etc/systemd/system + ls -A /etc/docker avant et après les trois courses : b57d965b… → b57d965b…, identique. Elle est aussi structurelle : les six sites d'écriture (l.203, 226, 252, 261, 269, 287) portent déjà [ $icc_DRY_RUN -eq 1 ] ||, et le commentaire posé à la garde le dit, pour que le prochain ajout ne l'oublie pas.

Deux défauts voisins corrigés dans le même bloc

  1. Le dry-run revendiquait l'installation : dernière ligne OK -- ... unites installees, activees, verifiees alors que rien n'avait été écrit — et il traversait la vérification A3, qui mesure l'effet d'une installation absente. Sur une machine neuve, il échouait donc sur A3, pas sur sa question. Le mode s'arrête désormais avant A3, et le dit.
  2. L'échec A3 appelait die, qui sort en 1, alors que le contrat documenté en tête de fichier porte 2 : installation reussie mais verification A3 en echec. Un automatisme ne pouvait pas distinguer un abandon d'une installation dont la vérification a échoué. exit 2 rétablit le contrat.

Ce que cette PR ne corrige pas

test_install_coursia_units_slice.sh rend 2 PASS / 4 FAIL, à l'identique sur le fichier d'origine (3cf723959) et sur le correctif — mesuré par sauvegarde/restauration cp, pas par affirmation. Le test lance le script sans --dry-run (l.168) et attend rc=0, ce qui n'est atteignable que sous root. Défaut préexistant, hors du périmètre de #23342 ; à traiter en sujet séparé.

See #23342

@github-actions

Copy link
Copy Markdown
Contributor

Bash Syntax Advisory — shebang / executable-bit warnings

See the Shebang + dry-run advisory job log for the per-file ::warning:: lines. Non-blocking.

@jsboige

jsboige commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner Author

Correction d'attribution. Le commentaire précédent porte une ligne Grain: de la lane myia-po-2028:CoursIA : c'est la lane qui a écrit le commit af6f6ced1, pas la propriétaire de cette PR. #23228 appartient à myia-po-2028:CoursIA-2 ([DELIVERED] du 2026-10-29 06:32Z sur #14846).

Le correctif a été replié ici parce que cette PR réécrit le fichier entier (+56/−8, fins de ligne comprises) : une PR séparée sur main aurait conflicté sur chaque ligne, pour trois lignes utiles. Ce n'est pas une revendication de la PR.

Rien d'autre n'est touché : le 🟡 d'Hermes et son traitement restent à la propriétaire, et af6f6ced1 ne modifie aucun fichier hors install-coursia-units.sh.

@github-actions

Copy link
Copy Markdown
Contributor

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

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.

@jsboige

jsboige commented Oct 30, 2026

Copy link
Copy Markdown
Owner Author

[OVERRIDE] lane myia-po-2025:CoursIA (coordinateur intérimaire, mandat user 2026-10-30) — disposition à la tête exacte af6f6ced1059. La réserve de clusterManager-Myia (persona Hermes, 2026-10-29T13:57Z, tête c49a82dd) est levée.

Contexte : myia-ai-01 est hors ligne (#23472). Il n'y a pas de jeton myia-ai-01 sur po-2025, donc la disposition est posée sous jsboige.

L'inventaire po-2028 de collect_units() ne couvrait pas daemon.json, que supervise.sh exige — levée.

Gouvernance. Le commit de tête vient d'une lane tierce (myia-po-2028:CoursIA, repli #23342, attribution corrigée sur la PR). La substance est vérifiée : la garde de privilège laisse passer le dry-run ([ "$icc_DRY_RUN" -eq 1 ] || [ "$(id -u)" -eq 0 ] || die), conformément à la discipline dry-run.

Checks à la tête. Au fold latest-wins, latest_reds, residual_reds et missing_required sont vides. B.0 rend rc=0, et il n'y a aucun thread inline. Les trois fichiers (.gitattributes, l'installeur, daemon.json) sont hors harnais.

Merge à suivre à la tête exacte, sans suppression de branche.

🤖 Generated with Claude Code

@jsboige
jsboige merged commit 33019c5 into main Oct 30, 2026
20 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants