ci: guard the windows-sys 0.61.2 pin in check-rust #415
No reviewers
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#415
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-345-windows-sys-guard"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Resolves #345
Generated autonomously by /autopilot run of 2026-10-10
Ce qui change
.forgejo/workflows/check-rust.yml: nouvelle étape bloquanteVerify windows-sys pinning, aprèscargo checket le garde des suppressions, avantcargo test. Elle litsrc-tauri/Cargo.lockavecawket échoue si une arêtewindows-sysdes sept crates à borne large (colored,dirs-sys,errno,rustix,rustls-platform-verifier,tempfile,winapi-util) quitte0.61.2, si l'un d'eux n'a plus de bloc dans le lock, ou si l'ensemble des versions dewindows-sysdu lock change. Un commentaire de renvoi vers l'ADR est en tête de la liste gardée.docs/adr/0023-windows-sys-pinning.md(nouveau) : pourquoi0.61.2(tag v0.14.0, run 322, puis chaque release jusqu'à v0.17.1), le coût mesuré (3 versions dewindows-syscompilées pour Windows contre 5), les déclencheurs mesurés, la condition de sortie (passage à 0.62, convergence vers un seulwindows-sys) et la procédure quand l'étape rougit.CLAUDE.md(section CI/CD) etdocs/architecture.md(sectioncheck-rust.yml, table des ADR) citent le garde à côté de celui des suppressions.src-tauri/Cargo.lock,.cargo/audit.tomlet le garde des suppressions (diff vide contremainpour les deux fichiers). Pas d'entrée CHANGELOG (CI seulement).Technique
awkne fait que lire le lock et imprimer des faits (wsys <version>,block <crate> <version> [<cible>...]) ; bash applique les quatre règles de la planification et logge chaque vérification, succès compris. Le code de sortie d'awkest testé avant toute utilisation de sa sortie (facts=$(awk …) && awk_rc=0 || awk_rc=$?) : une panne de lecture sort en 1 avec0 checks.windows-sysde chaque bloc d'un crate gardé doit nommer0.61.2; aucun bloc pour un nom, ou un bloc sans arête, fait échouer. Le suffixe(registry+…)est toléré.windows-sys, en0.61.2.EXPECTEDpassé par le mêmesort(l'ordre d'EXPECTEDest donc indifférent).tempfiledoit avoir été lu et vérifié par la boucle, pas seulement présent dans le lock, pour qu'une listeCRATESvidée ou amputée échoue au lieu de passer.run:, comme le garde des suppressions : aucun fichier sousscripts/, qui aurait dû entrer dans lespathsdecheck-rust.ymlet aurait déclenchécheck-frontend. Les mutations exécutent le texte exact durun:, extrait du YAML par PyYAML, avecbash --noprofile --norc -e -o pipefail, depuis un dossier qui contient la copie du lock ensrc-tauri/Cargo.lock.--lockedne s'appliquent ; l'étape lit le lock tel quecargo checkl'a laissé.Preuves
Toutes sur des copies, jamais sur le lock du worktree.
awklocal = mawk 1.3.4, celui d'ubuntu:22.04.Cas nominal (lock de la base, identique à celui de
main) :Mutation 1 (réseau) : copie de
src-tauri/,cargo update --manifest-path …/src-tauri/Cargo.toml -p hyper. Pas besoin du repli, la commande fait toujours dériver :Arêtes
windows-sysmodifiées dans le lock (comparaison bloc par bloc de toutes les arêteswindows-sysdu fichier : seules les sept gardées ont bougé, et le lock garde 666 paquets) :Garde :
Mutation 2 : bloc
[[package]] name = "windows-sys" version = "0.53.0"ajouté après 0.52.0 :Mutation 3 :
name = "colored"renomméname = "colored-renamed":Mutation 4 : lock absent (
awken erreur) :Cas complémentaires (même script, mêmes options) :
(registry+…)sur l'arête decolored"windows-sys"surwinapi-utilalors que six versions coexistentwindows-sys with no version, while the lockfile holds …)rustix 0.38.44pointant 0.59.0coloredsans arêtewindows-syshas no windows-sys edge left)windows-sys, 0.61.2, arêtes nues)tempfileretiré deCRATES(copie du script)CRATES=""(copie du script)Mesures refaites pour l'ADR (2026-10-10) :
cargo tree --target x86_64-pc-windows-msvc -e normal,builddonne 3 versions dewindows-sys(0.59.0, 0.60.2, 0.61.2) sur le lock de la base et 5 sur la copie dérivée (plus 0.48.0 et 0.52.0) ;cargo metadata: les sept crates gardés sont exactement ceux dont l'exigence surwindows-syscouvre plusieurs mineures, toutes les autres sont des^0.x(qui ne peuvent pas dériver) ;hyperetwant,cargo metadata --lockedaccepte le lock sans le réécrire, et le garde repasse (exit 0) ;success(/actions/tasks) ;f4b09b0,cargo update -p rustls-webpki -p tar) avait déplacé les mêmes 7 arêtes, avec la même répartition (2 vers 0.48.0, 4 vers 0.52.0, 1 vers 0.59.0).À lire dans la CI de cette PR :
check-rusttourne (le workflow est dans ses proprespaths) sur le lock demain, que la PR ne modifie pas. L'étapeVerify windows-sys pinningdoit montrer les 7 lignesok: <crate> <version> -> windows-sys 0.61.2, la ligne de l'ensemble, le canari etwindows-sys pinning: 9 checks, exit 0. C'est la preuve du critère « Surmain, l'étape logge… », d'oùResolves.check-frontendne tourne pas : les quatre fichiers sont dans sonpaths-ignore.Pour relire en priorité
run:sous-e -o pipefail: la capture du code de sortie d'awk, la bouclewhile read … done <<<"$blocks"(exécutée dans le shell courant, doncrc,checksetcanary_checkedsont conservés), le canari lié à la boucle.hyperet ce qu'il tire » du plan : #310 a dérivé surrustls-webpkiettar, qui ne viennent pas dehyper. L'ADR en conclut qu'aucune règle simple ne prédit la dérive, ce qui justifie un garde sur la version résolue.rustls: 2026-09-21, heure locale du commit8ea3410et du commentaire de #345, et non 2026-09-22, horodatage UTC.🤖 Generated with Claude Code
Auto-revue du worker
/autopilot: APPROVETentative 1 : REQUEST_CHANGES sur mon propre texte de l'ADR. Après la réécriture du paragraphe du déclencheur, « Or ce sous-arbre est celui où tombent les advisories » n'avait plus de référent ; la phrase de la règle 1 sur un bloc absent était bancale. Corrigé dans
3b8105c(Refs #345, deux phrases de l'ADR, rien d'autre). Tentative 2 : APPROVE sur le diff complet relu à la tête3b8105c.Critères de planification
main: 7 lignesok:, une ligneok:pour l'ensemble, le bilan9 checks, exit 0(7 arêtes, ensemble, canari), sortie collée dans la description. Lock de la branche identique à celui demain(diff vide). CI : à lire dans 516/517cargo update -p hyper) → sort en 1FAIL:. Pas de repli nécessairewindows-sys0.53.0)no [[package]] block named colored0 checksrun:extrait du YAML par PyYAML,bash --noprofile --norc -e -o pipefail, mawk 1.3.4 comme dansubuntu:22.04, rejoué sur la tête poussée0.61.2, coût 3/5, déclencheur, sortie, procédure)cargo tree3 contre 5,cargo metadatapour les 7 bornes larges, runs de release 322/402/451/491/508, procédure de réparation éprouvée aveccargo metadata --locked)CRATES=dans lerun:.cargo/audit.tomlet le garde des suppressions intouchésexit $rcdu garde des suppressions ;audit.tomlabsent du diffRelu en plus
-e -o pipefail: le code de sortie d'awkest capturé par&& awk_rc=0 || awk_rc=$?; les pipelinesprintf | awk | sort | pastene peuvent échouer qu'en tuant l'étape, donc en rouge ;pastesur une entrée vide sort en 0 (vérifié) ; la bouclewhile read … <<<"$blocks"tourne dans le shell courant,rc,checksetcanary_checkedsont conservés ; aucuncmd && xen fin de corps de boucle.CRATESvide ou sans le canari, tous en exit 1 (tableau des cas complémentaires dans la description).${{ }}dans le script, aucuneval, aucun accès réseau ; les valeurs lues dans le lock ne sont que comparées et affichées.docs/architecture.md(sectioncheck-rust.ymlet table des ADR) etCLAUDE.mdà jour.Écarts assumés au plan (consignés dans le journal du run)
ok: rustix 1.1.3 -> windows-sys 0.61.2), pour distinguer deux blocs d'un même crate ; le bilan compte toutes les vérifications loggées (9 checksaujourd'hui).hyperet ce qu'il tire » : le commit de #310 (f4b09b0,-p rustls-webpki -p tar) a déplacé les mêmes 7 arêtes.rustlsest datée du 2026-09-21 (heure locale), non du 2026-09-22 (horodatage UTC).Ce que la CI doit encore montrer
Runs
check-rust516 (8d9a3ca) et 517 (3b8105c), en file au moment de ce commentaire ; pas decheck-frontend(les quatre fichiers sont dans sonpaths-ignore). Dans l'étapeVerify windows-sys pinning: la ligneok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2, les 7 lignesok: <crate> <version> -> windows-sys 0.61.2, la ligne du canari etwindows-sys pinning: 9 checks, exit 0. Le garde des suppressions doit rester àSuppression guard: 2 checks, exit 0, etcargo testvert.À relire en priorité
run:, lignes de la capture d'awket de la boucle.CI lue par la session principale du run autopilot (pas une revue)
8d9a3cawindows-sys pinning: 9 checks, exit 0; 255 tests Rust3b8105c(tête)Sortie du garde sur la tête (run 517) :
Fait vérifié au passage, à l'appui de l'élargissement du déclencheur dans l'ADR 0023 (le plan disait «
hyperet ce qu'il tire ») : le commitf4b09b0de #310 fait bien descendre les 7 arêtes (git show f4b09b0 -- src-tauri/Cargo.lock: 2 vers 0.48.0, 4 vers 0.52.0, 1 vers 0.59.0).Revue adversariale — PR #415 (#345)
Verdict : APPROVE
Résumé. Le garde fait ce qu'il annonce : il rougit sur la vraie dérive produite par
cargo update -p hyper, passe surmainet sur les cinq tags de release, et échoue fermé sur toutes les pannes de lecture que j'ai pu fabriquer. Les faits de l'ADR que j'ai recoupés tiennent, sauf une prémisse (« pas de Python dans le conteneur ») et un décompte (« troisième dérive »). Aucun bloquant ; suggestions ci-dessous, à appliquer en tête de pile de préférence.Ce que j'ai exécuté
Texte exact du
run:extrait du YAML de la tête3b8105c(PyYAML), lancé avecbash --noprofile --norc -e -o pipefail(l'invocation du runner, ligne 15 du log du run 517), sur des copies hors dépôt, mawk 1.3.4.CI de la tête (run 517, lu dans le log). L'étape logge l'ensemble des versions, les 7 lignes
ok: <crate> <version> -> windows-sys 0.61.2, le canari etwindows-sys pinning: 9 checks, exit 0.cargo checkn'a pas réécrit le lock (aucune ligneLocking) : le garde a lu le lock commité, identique à celui demain(git diff main 3b8105c -- src-tauri/Cargo.lock .cargo/audit.tomlvide).Mutations du relecteur, lock et outil :
main, puis ceux des tags v0.14.0 à v0.17.1 (témoins)src-tauri/pargit archive,cargo update -p hyperle 2026-10-11 (hyper 1.8.1 → 1.12.0, want 0.3.1 → 0.3.2, 666 paquets avant et après)windows-sysdu lock) ; 7 FAIL, exit 1winapi-util→ 0.48.0)colored→0.52.0 (registry+…))errno)windows-sys 0.52.0dans le bloctempfilewindows-sys 0.61.2retiré, arêtes intactesawkmuet (shim qui sort en 0 sans rien imprimer)Mutations du relecteur, script :
canary_checked=1neutralisé, lock demainwhilepassée dans un sous-shell (printf … | while), lock dérivércperdu dans le sous-shell, mais le canari rougit : exit 1 (2 checks). Le canari attrape la régression classiqueawkimprime tous ses faits puis sort en 2 (shim)FAIL: awk exited 2, exit 1. Sans le test deawk_rc: exit 0. Ce test, et lui seul, tue cette mutationProcédure de réparation de l'ADR, rejouée. Sur le lock dérivé, les 7 arêtes remises à la main : le diff contre la base se réduit aux strophes
hyperetwant(dont l'arêtepin-utilsque hyper 1.12 abandonne),cargo metadata --lockedsort en 0 sans toucher au fichier (empreinte identique), le garde repasse. Contre-épreuve : une remise hors borne (colored→ 0.45.0) est refusée parcargo metadata --locked(rc 101). La vérification de la procédure attrape donc une mauvaise réparation.Faits de l'ADR recoupés.
cargo tree --target x86_64-pc-windows-msvc, en-e normal,buildcomme en-e normal: 0.59.0, 0.60.2 et 0.61.2 sur la base, plus 0.48.0 et 0.52.0 sur la copie dérivée. 3 contre 5, confirmé.cargo metadatade l'ADR sort 35 exigences surwindows-sys; hors^0.x, exactement les sept deCRATES.main(first-parent) qui touche le lock depuis février. La seule fenêtre hors0.61.2va def4b09b0(#310, 2026-07-27) à2d4caec(PR #321, commité le 2026-08-15), avec la répartition 2/4/1 annoncée, et aucun tag entre les deux.5154c52(#344) ne touche que la stropheh2.build-and-releasedes tags v0.14.0 à v0.17.1, toussuccess(/actions/tasks).rustls: 2026-09-21 en heure locale (commit8ea3410à 20:09 EDT, commentaire de #345 à 20:11 EDT), conforme à la convention du dépôt.Fermeture. La timeline de #345 porte un
pull_refclosesvenant de #415, et le premier commit porteResolves #345: l'issue se ferme par l'une ou l'autre voie de merge. Commits au format conventionnel (ci:,docs:). Rien de sensible dans le diff.Suggestions (non bloquantes)
ubuntu:22.04n'a pas Python ») le disent ; l'erreur vient du corps de #345. Le log du run 517 montreSetting up python3 (3.10.6-1~22.04.1)(ligne 2270) dans l'étape « Install system dependencies, Node.js and Rust », tiré par les dépendances des paquetsaptde cette étape. Le choix d'awkreste le bon, pour une raison vraie : mawk fait partie de l'image de base, alors que python3 n'est là que par une dépendance transitive que rien ne garantit. À reformuler aux deux endroits, de préférence en tête de pile avant le merge : un ADR ne devrait pas porter une prémisse démentie par le log de sa propre PR.FAIL: <crate> <version> has no windows-sys edge left. See …renvoie à l'ADR, qui n'a pas de puce pour ce cas (le crate a cessé de dépendre dewindows-sysdans cette version : même traitement que « bloc introuvable »).tempfileplus ancien, d'avant les bornes larges, tiré par une autre dépendance) fait échouer la règle 1, conformément à la décision de planification « chaque bloc ». La réparation documentée est alors impossible :cargo metadata --lockedrefuse une arête hors borne (rc 101 ci-dessus). Une puce suffit : décision dans la PR (garder ce bloc par nom et version, par exemple), avec amendement de l'ADR.awk: « so a read failure fails the step instead of passing for a clean, empty result ». Un résultat vide échoue déjà (shim muet ci-dessus : règle 3, 7 blocs introuvables, canari). Ce que le test attrape seul, c'est unawkqui échoue après avoir tout imprimé. Reformulation optionnelle.CRATESvidée ou amputée échoue ». Le canari n'attrape qu'une liste vidée ou privée detempfile; retirer un autre nom passe avec un check de moins (9 → 8), et seul le bilan en garde la trace. Acceptable, puisqu'une telle édition est un diff visible sous le commentaire de renvoi à l'ADR./releasemodifieCargo.lockdirectement surmain, sans PR : le garde ne le voit qu'au run du lundi, après le build du tag. L'édition est faite à la main et vérifiée parcargo metadata --locked, donc le risque est faible, mais la phrase de l'ADR « exactement là où le lock change » est un peu trop forte. Rejouer le garde au pré-vol de/releasefermerait le trou.Actions faites
git show,git logetgit archiveseulement). Copie hors dépôt/tmp/pr415-review(export desrc-tauri/, locks, log de CI) supprimée.status:review→status:approved.