ci: guard the windows-sys 0.61.2 pin in check-rust #415

Merged
maximus merged 2 commits from issue-345-windows-sys-guard into main 2026-10-12 19:32:33 +00:00
Owner

Resolves #345

Generated autonomously by /autopilot run of 2026-10-10

PR empilée sur #414 (#376, base main) : elle ne montre que son propre diff.

Ce qui change

  • .forgejo/workflows/check-rust.yml : nouvelle étape bloquante Verify windows-sys pinning, après cargo check et le garde des suppressions, avant cargo test. Elle lit src-tauri/Cargo.lock avec awk et échoue si une arête windows-sys des sept crates à borne large (colored, dirs-sys, errno, rustix, rustls-platform-verifier, tempfile, winapi-util) quitte 0.61.2, si l'un d'eux n'a plus de bloc dans le lock, ou si l'ensemble des versions de windows-sys du 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) : pourquoi 0.61.2 (tag v0.14.0, run 322, puis chaque release jusqu'à v0.17.1), le coût mesuré (3 versions de windows-sys compilées pour Windows contre 5), les déclencheurs mesurés, la condition de sortie (passage à 0.62, convergence vers un seul windows-sys) et la procédure quand l'étape rougit.
  • CLAUDE.md (section CI/CD) et docs/architecture.md (section check-rust.yml, table des ADR) citent le garde à côté de celui des suppressions.
  • Intouchés : src-tauri/Cargo.lock, .cargo/audit.toml et le garde des suppressions (diff vide contre main pour les deux fichiers). Pas d'entrée CHANGELOG (CI seulement).

Technique

  • Lecture et décision séparées. awk ne 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'awk est testé avant toute utilisation de sa sortie (facts=$(awk …) && awk_rc=0 || awk_rc=$?) : une panne de lecture sort en 1 avec 0 checks.
  • Règle 1 : chaque arête windows-sys de chaque bloc d'un crate gardé doit nommer 0.61.2 ; aucun bloc pour un nom, ou un bloc sans arête, fait échouer. Le suffixe (registry+…) est toléré.
  • Règle 2 : une arête nue ne passe que si le lock ne contient qu'un windows-sys, en 0.61.2.
  • Règle 3 : la liste triée des versions, doublons compris, est comparée à EXPECTED passé par le même sort (l'ordre d'EXPECTED est donc indifférent).
  • Canari : tempfile doit avoir été lu et vérifié par la boucle, pas seulement présent dans le lock, pour qu'une liste CRATES vidée ou amputée échoue au lieu de passer.
  • Script en ligne dans le run:, comme le garde des suppressions : aucun fichier sous scripts/, qui aurait dû entrer dans les paths de check-rust.yml et aurait déclenché check-frontend. Les mutations exécutent le texte exact du run:, extrait du YAML par PyYAML, avec bash --noprofile --norc -e -o pipefail, depuis un dossier qui contient la copie du lock en src-tauri/Cargo.lock.
  • Pas d'appel à cargo : ni l'index chaud ni --locked ne s'appliquent ; l'étape lit le lock tel que cargo check l'a laissé.

Preuves

Toutes sur des copies, jamais sur le lock du worktree. awk local = mawk 1.3.4, celui d'ubuntu:22.04.

Cas nominal (lock de la base, identique à celui de main) :

ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2
ok: colored 3.1.1 -> windows-sys 0.61.2
ok: dirs-sys 0.5.0 -> windows-sys 0.61.2
ok: errno 0.3.14 -> windows-sys 0.61.2
ok: rustix 1.1.3 -> windows-sys 0.61.2
ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2
ok: tempfile 3.24.0 -> windows-sys 0.61.2
ok: winapi-util 0.1.11 -> windows-sys 0.61.2
ok: canary 'tempfile' found, its windows-sys edge read and checked above
windows-sys pinning: 9 checks, exit 0
exit=0

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 :

    Updating crates.io index
     Locking 2 packages to latest compatible versions
    Updating hyper v1.8.1 -> v1.12.0
    Updating want v0.3.1 -> v0.3.2
note: pass `--verbose` to see 225 unchanged dependencies behind latest

Arêtes windows-sys modifiées dans le lock (comparaison bloc par bloc de toutes les arêtes windows-sys du fichier : seules les sept gardées ont bougé, et le lock garde 666 paquets) :

colored 3.1.1: windows-sys 0.61.2 -> windows-sys 0.48.0
dirs-sys 0.5.0: windows-sys 0.61.2 -> windows-sys 0.59.0
errno 0.3.14: windows-sys 0.61.2 -> windows-sys 0.52.0
rustix 1.1.3: windows-sys 0.61.2 -> windows-sys 0.52.0
rustls-platform-verifier 0.6.2: windows-sys 0.61.2 -> windows-sys 0.52.0
tempfile 3.24.0: windows-sys 0.61.2 -> windows-sys 0.52.0
winapi-util 0.1.11: windows-sys 0.61.2 -> windows-sys 0.48.0

Garde :

ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2
FAIL: colored 3.1.1 -> windows-sys 0.48.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
FAIL: dirs-sys 0.5.0 -> windows-sys 0.59.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
FAIL: errno 0.3.14 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
FAIL: rustix 1.1.3 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
FAIL: rustls-platform-verifier 0.6.2 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
FAIL: tempfile 3.24.0 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
FAIL: winapi-util 0.1.11 -> windows-sys 0.48.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md.
ok: canary 'tempfile' found, its windows-sys edge read and checked above
windows-sys pinning: 9 checks, exit 1
exit=1

Mutation 2 : bloc [[package]] name = "windows-sys" version = "0.53.0" ajouté après 0.52.0 :

FAIL: windows-sys versions in the lockfile are "0.45.0 0.48.0 0.52.0 0.53.0 0.59.0 0.60.2 0.61.2", expected exactly "0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2". A version was added or removed: follow docs/adr/0023-windows-sys-pinning.md before editing EXPECTED.
ok: colored 3.1.1 -> windows-sys 0.61.2
ok: dirs-sys 0.5.0 -> windows-sys 0.61.2
ok: errno 0.3.14 -> windows-sys 0.61.2
ok: rustix 1.1.3 -> windows-sys 0.61.2
ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2
ok: tempfile 3.24.0 -> windows-sys 0.61.2
ok: winapi-util 0.1.11 -> windows-sys 0.61.2
ok: canary 'tempfile' found, its windows-sys edge read and checked above
windows-sys pinning: 9 checks, exit 1
exit=1

Mutation 3 : name = "colored" renommé name = "colored-renamed" :

ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2
FAIL: no [[package]] block named colored in src-tauri/Cargo.lock (renamed, or gone from the graph?). See docs/adr/0023-windows-sys-pinning.md.
ok: dirs-sys 0.5.0 -> windows-sys 0.61.2
ok: errno 0.3.14 -> windows-sys 0.61.2
ok: rustix 1.1.3 -> windows-sys 0.61.2
ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2
ok: tempfile 3.24.0 -> windows-sys 0.61.2
ok: winapi-util 0.1.11 -> windows-sys 0.61.2
ok: canary 'tempfile' found, its windows-sys edge read and checked above
windows-sys pinning: 9 checks, exit 1
exit=1

Mutation 4 : lock absent (awk en erreur) :

awk: cannot open "src-tauri/Cargo.lock" (No such file or directory)
FAIL: awk exited 2 reading src-tauri/Cargo.lock, so nothing was checked.
windows-sys pinning: 0 checks, exit 1
exit=1

Cas complémentaires (même script, mêmes options) :

lock ou script sortie
suffixe (registry+…) sur l'arête de colored exit 0, 9 checks
arête nue "windows-sys" sur winapi-util alors que six versions coexistent exit 1 (windows-sys with no version, while the lockfile holds …)
second bloc rustix 0.38.44 pointant 0.59.0 exit 1 sur ce bloc seul, 10 checks
bloc colored sans arête windows-sys exit 1 (has no windows-sys edge left)
lock convergé (un seul windows-sys, 0.61.2, arêtes nues) exit 1 par la seule règle 3 ; les 7 arêtes nues passent (règle 2)
lock vide exit 1 : ensemble, 7 blocs introuvables, canari
tempfile retiré de CRATES (copie du script) exit 1, canari, 8 checks
CRATES="" (copie du script) exit 1, canari, 2 checks
locks des tags v0.14.0, v0.15.0, v0.16.0, v0.17.0, v0.17.1 exit 0 chacun, 9 checks

Mesures refaites pour l'ADR (2026-10-10) :

  • coût : cargo tree --target x86_64-pc-windows-msvc -e normal,build donne 3 versions de windows-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 sur windows-sys couvre plusieurs mineures, toutes les autres sont des ^0.x (qui ne peuvent pas dériver) ;
  • procédure de réparation : sur la copie dérivée, les 7 arêtes remises à la main ; le diff contre la base se réduit aux strophes hyper et want, cargo metadata --locked accepte le lock sans le réécrire, et le garde repasse (exit 0) ;
  • les runs 322, 402, 451, 491 et 508 sont les releases v0.14.0 à v0.17.1, toutes success (/actions/tasks) ;
  • le commit de #310 (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-rust tourne (le workflow est dans ses propres paths) sur le lock de main, que la PR ne modifie pas. L'étape Verify windows-sys pinning doit montrer les 7 lignes ok: <crate> <version> -> windows-sys 0.61.2, la ligne de l'ensemble, le canari et windows-sys pinning: 9 checks, exit 0. C'est la preuve du critère « Sur main, l'étape logge… », d'où Resolves. check-frontend ne tourne pas : les quatre fichiers sont dans son paths-ignore.

Pour relire en priorité

  1. Le script du run: sous -e -o pipefail : la capture du code de sortie d'awk, la boucle while read … done <<<"$blocks" (exécutée dans le shell courant, donc rc, checks et canary_checked sont conservés), le canari lié à la boucle.
  2. La règle 3 compte toutes les cibles : une version non compilée pour Windows qui apparaît ou disparaît rougit aussi l'étape. Assumé dans l'ADR (Conséquences négatives), parce que le lock ne dit pas ce qui est compilé pour quelle cible.
  3. La formulation du déclencheur dans l'ADR, plus large que « hyper et ce qu'il tire » du plan : #310 a dérivé sur rustls-webpki et tar, qui ne viennent pas de hyper. 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.
  4. La date de la mesure rustls : 2026-09-21, heure locale du commit 8ea3410 et du commentaire de #345, et non 2026-09-22, horodatage UTC.

🤖 Generated with Claude Code

Resolves #345 Generated autonomously by /autopilot run of 2026-10-10 > PR empilée sur #414 (#376, base `main`) : elle ne montre que son propre diff. ## Ce qui change - **`.forgejo/workflows/check-rust.yml`** : nouvelle étape bloquante `Verify windows-sys pinning`, après `cargo check` et le garde des suppressions, avant `cargo test`. Elle lit `src-tauri/Cargo.lock` avec `awk` et échoue si une arête `windows-sys` des sept crates à borne large (`colored`, `dirs-sys`, `errno`, `rustix`, `rustls-platform-verifier`, `tempfile`, `winapi-util`) quitte `0.61.2`, si l'un d'eux n'a plus de bloc dans le lock, ou si l'ensemble des versions de `windows-sys` du 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) : pourquoi `0.61.2` (tag v0.14.0, run 322, puis chaque release jusqu'à v0.17.1), le coût mesuré (3 versions de `windows-sys` compilées pour Windows contre 5), les déclencheurs mesurés, la condition de sortie (passage à 0.62, convergence vers un seul `windows-sys`) et la procédure quand l'étape rougit. - **`CLAUDE.md`** (section CI/CD) et **`docs/architecture.md`** (section `check-rust.yml`, table des ADR) citent le garde à côté de celui des suppressions. - Intouchés : `src-tauri/Cargo.lock`, `.cargo/audit.toml` et le garde des suppressions (diff vide contre `main` pour les deux fichiers). Pas d'entrée CHANGELOG (CI seulement). ## Technique - **Lecture et décision séparées.** `awk` ne 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'`awk` est testé avant toute utilisation de sa sortie (`facts=$(awk …) && awk_rc=0 || awk_rc=$?`) : une panne de lecture sort en 1 avec `0 checks`. - **Règle 1** : chaque arête `windows-sys` de chaque bloc d'un crate gardé doit nommer `0.61.2` ; aucun bloc pour un nom, ou un bloc sans arête, fait échouer. Le suffixe ` (registry+…)` est toléré. - **Règle 2** : une arête nue ne passe que si le lock ne contient qu'un `windows-sys`, en `0.61.2`. - **Règle 3** : la liste triée des versions, doublons compris, est comparée à `EXPECTED` passé par le même `sort` (l'ordre d'`EXPECTED` est donc indifférent). - **Canari** : `tempfile` doit avoir été lu *et vérifié par la boucle*, pas seulement présent dans le lock, pour qu'une liste `CRATES` vidée ou amputée échoue au lieu de passer. - **Script en ligne dans le `run:`**, comme le garde des suppressions : aucun fichier sous `scripts/`, qui aurait dû entrer dans les `paths` de `check-rust.yml` et aurait déclenché `check-frontend`. Les mutations exécutent le texte exact du `run:`, extrait du YAML par PyYAML, avec `bash --noprofile --norc -e -o pipefail`, depuis un dossier qui contient la copie du lock en `src-tauri/Cargo.lock`. - **Pas d'appel à cargo** : ni l'index chaud ni `--locked` ne s'appliquent ; l'étape lit le lock tel que `cargo check` l'a laissé. ## Preuves Toutes sur des copies, jamais sur le lock du worktree. `awk` local = mawk 1.3.4, celui d'`ubuntu:22.04`. **Cas nominal** (lock de la base, identique à celui de `main`) : ``` ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2 ok: colored 3.1.1 -> windows-sys 0.61.2 ok: dirs-sys 0.5.0 -> windows-sys 0.61.2 ok: errno 0.3.14 -> windows-sys 0.61.2 ok: rustix 1.1.3 -> windows-sys 0.61.2 ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2 ok: tempfile 3.24.0 -> windows-sys 0.61.2 ok: winapi-util 0.1.11 -> windows-sys 0.61.2 ok: canary 'tempfile' found, its windows-sys edge read and checked above windows-sys pinning: 9 checks, exit 0 exit=0 ``` **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 : ``` Updating crates.io index Locking 2 packages to latest compatible versions Updating hyper v1.8.1 -> v1.12.0 Updating want v0.3.1 -> v0.3.2 note: pass `--verbose` to see 225 unchanged dependencies behind latest ``` Arêtes `windows-sys` modifiées dans le lock (comparaison bloc par bloc de toutes les arêtes `windows-sys` du fichier : seules les sept gardées ont bougé, et le lock garde 666 paquets) : ``` colored 3.1.1: windows-sys 0.61.2 -> windows-sys 0.48.0 dirs-sys 0.5.0: windows-sys 0.61.2 -> windows-sys 0.59.0 errno 0.3.14: windows-sys 0.61.2 -> windows-sys 0.52.0 rustix 1.1.3: windows-sys 0.61.2 -> windows-sys 0.52.0 rustls-platform-verifier 0.6.2: windows-sys 0.61.2 -> windows-sys 0.52.0 tempfile 3.24.0: windows-sys 0.61.2 -> windows-sys 0.52.0 winapi-util 0.1.11: windows-sys 0.61.2 -> windows-sys 0.48.0 ``` Garde : ``` ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2 FAIL: colored 3.1.1 -> windows-sys 0.48.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. FAIL: dirs-sys 0.5.0 -> windows-sys 0.59.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. FAIL: errno 0.3.14 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. FAIL: rustix 1.1.3 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. FAIL: rustls-platform-verifier 0.6.2 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. FAIL: tempfile 3.24.0 -> windows-sys 0.52.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. FAIL: winapi-util 0.1.11 -> windows-sys 0.48.0, pinned at 0.61.2. See docs/adr/0023-windows-sys-pinning.md. ok: canary 'tempfile' found, its windows-sys edge read and checked above windows-sys pinning: 9 checks, exit 1 exit=1 ``` **Mutation 2** : bloc `[[package]] name = "windows-sys" version = "0.53.0"` ajouté après 0.52.0 : ``` FAIL: windows-sys versions in the lockfile are "0.45.0 0.48.0 0.52.0 0.53.0 0.59.0 0.60.2 0.61.2", expected exactly "0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2". A version was added or removed: follow docs/adr/0023-windows-sys-pinning.md before editing EXPECTED. ok: colored 3.1.1 -> windows-sys 0.61.2 ok: dirs-sys 0.5.0 -> windows-sys 0.61.2 ok: errno 0.3.14 -> windows-sys 0.61.2 ok: rustix 1.1.3 -> windows-sys 0.61.2 ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2 ok: tempfile 3.24.0 -> windows-sys 0.61.2 ok: winapi-util 0.1.11 -> windows-sys 0.61.2 ok: canary 'tempfile' found, its windows-sys edge read and checked above windows-sys pinning: 9 checks, exit 1 exit=1 ``` **Mutation 3** : `name = "colored"` renommé `name = "colored-renamed"` : ``` ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2 FAIL: no [[package]] block named colored in src-tauri/Cargo.lock (renamed, or gone from the graph?). See docs/adr/0023-windows-sys-pinning.md. ok: dirs-sys 0.5.0 -> windows-sys 0.61.2 ok: errno 0.3.14 -> windows-sys 0.61.2 ok: rustix 1.1.3 -> windows-sys 0.61.2 ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2 ok: tempfile 3.24.0 -> windows-sys 0.61.2 ok: winapi-util 0.1.11 -> windows-sys 0.61.2 ok: canary 'tempfile' found, its windows-sys edge read and checked above windows-sys pinning: 9 checks, exit 1 exit=1 ``` **Mutation 4** : lock absent (`awk` en erreur) : ``` awk: cannot open "src-tauri/Cargo.lock" (No such file or directory) FAIL: awk exited 2 reading src-tauri/Cargo.lock, so nothing was checked. windows-sys pinning: 0 checks, exit 1 exit=1 ``` **Cas complémentaires** (même script, mêmes options) : | lock ou script | sortie | |---|---| | suffixe ` (registry+…)` sur l'arête de `colored` | exit 0, 9 checks | | arête nue `"windows-sys"` sur `winapi-util` alors que six versions coexistent | exit 1 (`windows-sys with no version, while the lockfile holds …`) | | second bloc `rustix 0.38.44` pointant 0.59.0 | exit 1 sur ce bloc seul, 10 checks | | bloc `colored` sans arête `windows-sys` | exit 1 (`has no windows-sys edge left`) | | lock convergé (un seul `windows-sys`, 0.61.2, arêtes nues) | exit 1 par la seule règle 3 ; les 7 arêtes nues passent (règle 2) | | lock vide | exit 1 : ensemble, 7 blocs introuvables, canari | | `tempfile` retiré de `CRATES` (copie du script) | exit 1, canari, 8 checks | | `CRATES=""` (copie du script) | exit 1, canari, 2 checks | | locks des tags v0.14.0, v0.15.0, v0.16.0, v0.17.0, v0.17.1 | exit 0 chacun, 9 checks | **Mesures refaites pour l'ADR (2026-10-10)** : - coût : `cargo tree --target x86_64-pc-windows-msvc -e normal,build` donne 3 versions de `windows-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 sur `windows-sys` couvre plusieurs mineures, toutes les autres sont des `^0.x` (qui ne peuvent pas dériver) ; - procédure de réparation : sur la copie dérivée, les 7 arêtes remises à la main ; le diff contre la base se réduit aux strophes `hyper` et `want`, `cargo metadata --locked` accepte le lock sans le réécrire, et le garde repasse (exit 0) ; - les runs 322, 402, 451, 491 et 508 sont les releases v0.14.0 à v0.17.1, toutes `success` (`/actions/tasks`) ; - le commit de #310 (`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-rust` tourne (le workflow est dans ses propres `paths`) sur le lock de `main`, que la PR ne modifie pas. L'étape `Verify windows-sys pinning` doit montrer les 7 lignes `ok: <crate> <version> -> windows-sys 0.61.2`, la ligne de l'ensemble, le canari et `windows-sys pinning: 9 checks, exit 0`. C'est la preuve du critère « Sur `main`, l'étape logge… », d'où `Resolves`. `check-frontend` ne tourne pas : les quatre fichiers sont dans son `paths-ignore`. ## Pour relire en priorité 1. Le script du `run:` sous `-e -o pipefail` : la capture du code de sortie d'`awk`, la boucle `while read … done <<<"$blocks"` (exécutée dans le shell courant, donc `rc`, `checks` et `canary_checked` sont conservés), le canari lié à la boucle. 2. La règle 3 compte toutes les cibles : une version non compilée pour Windows qui apparaît ou disparaît rougit aussi l'étape. Assumé dans l'ADR (Conséquences négatives), parce que le lock ne dit pas ce qui est compilé pour quelle cible. 3. La formulation du déclencheur dans l'ADR, plus large que « `hyper` et ce qu'il tire » du plan : #310 a dérivé sur `rustls-webpki` et `tar`, qui ne viennent pas de `hyper`. 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. 4. La date de la mesure `rustls` : 2026-09-21, heure locale du commit `8ea3410` et du commentaire de #345, et non 2026-09-22, horodatage UTC. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
maximus added 1 commit 2026-10-11 00:16:05 +00:00
ci: guard the windows-sys 0.61.2 pin in check-rust
All checks were successful
PR Check — Rust / rust (pull_request) Successful in 5m12s
8d9a3ca9e9
Seven crates in Cargo.lock accept windows-sys through a wide bound
(colored, dirs-sys, errno, rustix, rustls-platform-verifier, tempfile,
winapi-util), so cargo may point them at any windows-sys version already in
the graph. All seven point at 0.61.2, the state every Windows release has
shipped with since v0.14.0. Some updates re-resolve them (cargo update -p
hyper, -p h2, -p rustls-webpki -p tar did) down to 0.48/0.52/0.59 while
cargo only reports the packages it bumped: the Windows build then compiles
five windows-sys versions instead of three, and nothing says so.

A new blocking step, "Verify windows-sys pinning", reads the lockfile with
awk right after the suppression guard and fails if any edge of the seven
crates leaves 0.61.2 (a bare edge only passes when the lockfile holds a
single windows-sys, at 0.61.2), if a guarded crate has no block, or if the
set of windows-sys versions changes. awk's exit code is tested apart from
its output, every check is logged with a summary line, and a canary
(tempfile) must be read and checked by the loop.

The step text was extracted from the YAML and run as is, with the runner's
bash options, on copies of the lockfile: main's and the five release tags'
locks pass (9 checks, exit 0); the hyper-bumped lock, an added
windows-sys 0.53.0, a renamed guarded crate, a missing lockfile and a
guarded list without the canary all exit 1.

ADR 0023 records why 0.61.2, the measured cost (3 versions compiled for
Windows instead of 5), the triggers, the exit condition (windows-sys 0.62,
or convergence on a single version) and the repair when the step fails.
CLAUDE.md and docs/architecture.md cite the guard next to the suppression
check. Cargo.lock and .cargo/audit.toml are untouched.

Resolves #345

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maximus added 1 commit 2026-10-11 00:17:14 +00:00
docs: fix two sentences of ADR 0023 after self-review
All checks were successful
PR Check — Rust / rust (pull_request) Successful in 3m36s
3b8105c253
"Ce sous-arbre" lost its referent once the trigger paragraph stopped
naming a subtree: the sentence now says what is measured, that both past
drifts (#310, #344) came with RustSec advisory fixes. Rule 1's sentence on
a missing block is reworded.

Refs #345

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

Auto-revue du worker /autopilot : APPROVE

Auto-revue de l'auteur, pas une revue indépendante. Le label status:approved reste à poser par un /pr-review de la session principale.

Tentative 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ête 3b8105c.

Critères de planification

critère preuve
Sur le lock de main : 7 lignes ok:, une ligne ok: pour l'ensemble, le bilan local : 9 checks, exit 0 (7 arêtes, ensemble, canari), sortie collée dans la description. Lock de la branche identique à celui de main (diff vide). CI : à lire dans 516/517
Mutation 1 (cargo update -p hyper) → sort en 1 hyper 1.8.1 → 1.12.0, want 0.3.1 → 0.3.2, « Locking 2 packages », les 7 arêtes (et elles seules) déplacées, 666 paquets ; garde exit 1, 7 FAIL:. Pas de repli nécessaire
Mutation 2 (bloc windows-sys 0.53.0) exit 1 par l'ensemble des versions, message qui renvoie à l'ADR 0023
Mutation 3 (crate gardé renommé) exit 1, no [[package]] block named colored
Mutation 4 (lock absent) mawk sort en 2, l'étape sort en 1 avec 0 checks
Script lancé tel quel en local texte du run: extrait du YAML par PyYAML, bash --noprofile --norc -e -o pipefail, mawk 1.3.4 comme dans ubuntu:22.04, rejoué sur la tête poussée
ADR 0023 (en-tête, pourquoi 0.61.2, coût 3/5, déclencheur, sortie, procédure) toutes les sections présentes ; mesures refaites le 2026-10-10 (cargo tree 3 contre 5, cargo metadata pour les 7 bornes larges, runs de release 322/402/451/491/508, procédure de réparation éprouvée avec cargo metadata --locked)
Commentaire de renvoi vers l'ADR en tête de la liste gardée au-dessus de CRATES= dans le run:
.cargo/audit.toml et le garde des suppressions intouchés diff : ajouts seulement, après le exit $rc du garde des suppressions ; audit.toml absent du diff

Relu en plus

  • Justesse sous -e -o pipefail : le code de sortie d'awk est capturé par && awk_rc=0 || awk_rc=$? ; les pipelines printf | awk | sort | paste ne peuvent échouer qu'en tuant l'étape, donc en rouge ; paste sur une entrée vide sort en 0 (vérifié) ; la boucle while read … <<<"$blocks" tourne dans le shell courant, rc, checks et canary_checked sont conservés ; aucun cmd && x en fin de corps de boucle.
  • Échec fermé : lock vide, bloc sans arête, arête nue ambiguë, second bloc d'un crate gardé, CRATES vide ou sans le canari, tous en exit 1 (tableau des cas complémentaires dans la description).
  • Sécurité : aucune interpolation ${{ }} dans le script, aucun eval, aucun accès réseau ; les valeurs lues dans le lock ne sont que comparées et affichées.
  • Conventions : commentaires en anglais dans le workflow, doc en français, commits conventionnels en anglais avec le trailer ; pas d'entrée CHANGELOG (CI seulement) ; docs/architecture.md (section check-rust.yml et table des ADR) et CLAUDE.md à jour.

Écarts assumés au plan (consignés dans le journal du run)

  • Les lignes portent la version du crate (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 checks aujourd'hui).
  • Le canari doit être lu et vérifié par la boucle, pas seulement présent dans le lock.
  • Le déclencheur est formulé plus largement que « hyper et ce qu'il tire » : le commit de #310 (f4b09b0, -p rustls-webpki -p tar) a déplacé les mêmes 7 arêtes.
  • La mesure rustls est datée du 2026-09-21 (heure locale), non du 2026-09-22 (horodatage UTC).

Ce que la CI doit encore montrer

Runs check-rust 516 (8d9a3ca) et 517 (3b8105c), en file au moment de ce commentaire ; pas de check-frontend (les quatre fichiers sont dans son paths-ignore). Dans l'étape Verify windows-sys pinning : la ligne ok: 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 lignes ok: <crate> <version> -> windows-sys 0.61.2, la ligne du canari et windows-sys pinning: 9 checks, exit 0. Le garde des suppressions doit rester à Suppression guard: 2 checks, exit 0, et cargo test vert.

À relire en priorité

  1. Le script du run:, lignes de la capture d'awk et de la boucle.
  2. La règle 3 compte toutes les cibles : une version non compilée pour Windows qui change la fait rougir aussi (assumé dans l'ADR).
  3. Le paragraphe « Le déclencheur, mesuré » de l'ADR, qui s'écarte de la formulation du plan.
## Auto-revue du worker `/autopilot` : APPROVE > Auto-revue de l'auteur, **pas une revue indépendante**. Le label `status:approved` reste à poser par un `/pr-review` de la session principale. **Tentative 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ête `3b8105c`. ### Critères de planification | critère | preuve | |---|---| | Sur le lock de `main` : 7 lignes `ok:`, une ligne `ok:` pour l'ensemble, le bilan | local : `9 checks, exit 0` (7 arêtes, ensemble, canari), sortie collée dans la description. Lock de la branche identique à celui de `main` (diff vide). **CI : à lire dans 516/517** | | Mutation 1 (`cargo update -p hyper`) → sort en 1 | hyper 1.8.1 → 1.12.0, want 0.3.1 → 0.3.2, « Locking 2 packages », les 7 arêtes (et elles seules) déplacées, 666 paquets ; garde exit 1, 7 `FAIL:`. Pas de repli nécessaire | | Mutation 2 (bloc `windows-sys` 0.53.0) | exit 1 par l'ensemble des versions, message qui renvoie à l'ADR 0023 | | Mutation 3 (crate gardé renommé) | exit 1, `no [[package]] block named colored` | | Mutation 4 (lock absent) | mawk sort en 2, l'étape sort en 1 avec `0 checks` | | Script lancé tel quel en local | texte du `run:` extrait du YAML par PyYAML, `bash --noprofile --norc -e -o pipefail`, mawk 1.3.4 comme dans `ubuntu:22.04`, rejoué sur la tête poussée | | ADR 0023 (en-tête, pourquoi `0.61.2`, coût 3/5, déclencheur, sortie, procédure) | toutes les sections présentes ; mesures refaites le 2026-10-10 (`cargo tree` 3 contre 5, `cargo metadata` pour les 7 bornes larges, runs de release 322/402/451/491/508, procédure de réparation éprouvée avec `cargo metadata --locked`) | | Commentaire de renvoi vers l'ADR en tête de la liste gardée | au-dessus de `CRATES=` dans le `run:` | | `.cargo/audit.toml` et le garde des suppressions intouchés | diff : ajouts seulement, après le `exit $rc` du garde des suppressions ; `audit.toml` absent du diff | ### Relu en plus - **Justesse sous `-e -o pipefail`** : le code de sortie d'`awk` est capturé par `&& awk_rc=0 || awk_rc=$?` ; les pipelines `printf | awk | sort | paste` ne peuvent échouer qu'en tuant l'étape, donc en rouge ; `paste` sur une entrée vide sort en 0 (vérifié) ; la boucle `while read … <<<"$blocks"` tourne dans le shell courant, `rc`, `checks` et `canary_checked` sont conservés ; aucun `cmd && x` en fin de corps de boucle. - **Échec fermé** : lock vide, bloc sans arête, arête nue ambiguë, second bloc d'un crate gardé, `CRATES` vide ou sans le canari, tous en exit 1 (tableau des cas complémentaires dans la description). - **Sécurité** : aucune interpolation `${{ }}` dans le script, aucun `eval`, aucun accès réseau ; les valeurs lues dans le lock ne sont que comparées et affichées. - **Conventions** : commentaires en anglais dans le workflow, doc en français, commits conventionnels en anglais avec le trailer ; pas d'entrée CHANGELOG (CI seulement) ; `docs/architecture.md` (section `check-rust.yml` et table des ADR) et `CLAUDE.md` à jour. ### Écarts assumés au plan (consignés dans le journal du run) - Les lignes portent la version du crate (`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 checks` aujourd'hui). - Le canari doit être lu **et vérifié par la boucle**, pas seulement présent dans le lock. - Le déclencheur est formulé plus largement que « `hyper` et ce qu'il tire » : le commit de #310 (`f4b09b0`, `-p rustls-webpki -p tar`) a déplacé les mêmes 7 arêtes. - La mesure `rustls` est datée du 2026-09-21 (heure locale), non du 2026-09-22 (horodatage UTC). ### Ce que la CI doit encore montrer Runs `check-rust` 516 (`8d9a3ca`) et 517 (`3b8105c`), en file au moment de ce commentaire ; pas de `check-frontend` (les quatre fichiers sont dans son `paths-ignore`). Dans l'étape `Verify windows-sys pinning` : la ligne `ok: 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 lignes `ok: <crate> <version> -> windows-sys 0.61.2`, la ligne du canari et `windows-sys pinning: 9 checks, exit 0`. Le garde des suppressions doit rester à `Suppression guard: 2 checks, exit 0`, et `cargo test` vert. ### À relire en priorité 1. Le script du `run:`, lignes de la capture d'`awk` et de la boucle. 2. La règle 3 compte toutes les cibles : une version non compilée pour Windows qui change la fait rougir aussi (assumé dans l'ADR). 3. Le paragraphe « Le déclencheur, mesuré » de l'ADR, qui s'écarte de la formulation du plan.
maximus added the
autopilot:pending-human
label 2026-10-11 00:18:01 +00:00
Author
Owner

CI lue par la session principale du run autopilot (pas une revue)

Run Commit Résultat Lu dans le journal
516 8d9a3ca vert, 5 min 12 s garde des suppressions 2 vérifications exit 0 ; windows-sys pinning: 9 checks, exit 0 ; 255 tests Rust
517 3b8105c (tête) vert, 3 min 36 s idem

Sortie du garde sur la tête (run 517) :

ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2
ok: colored 3.1.1 -> windows-sys 0.61.2
ok: dirs-sys 0.5.0 -> windows-sys 0.61.2
ok: errno 0.3.14 -> windows-sys 0.61.2
ok: rustix 1.1.3 -> windows-sys 0.61.2
ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2
ok: tempfile 3.24.0 -> windows-sys 0.61.2
ok: winapi-util 0.1.11 -> windows-sys 0.61.2
ok: canary 'tempfile' found, its windows-sys edge read and checked above
windows-sys pinning: 9 checks, exit 0

Fait vérifié au passage, à l'appui de l'élargissement du déclencheur dans l'ADR 0023 (le plan disait « hyper et ce qu'il tire ») : le commit f4b09b0 de #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).

**CI lue par la session principale du run autopilot (pas une revue)** | Run | Commit | Résultat | Lu dans le journal | |---|---|---|---| | 516 | `8d9a3ca` | vert, 5 min 12 s | garde des suppressions 2 vérifications exit 0 ; `windows-sys pinning: 9 checks, exit 0` ; 255 tests Rust | | 517 | `3b8105c` (tête) | vert, 3 min 36 s | idem | Sortie du garde sur la tête (run 517) : ``` ok: windows-sys versions in the lockfile: 0.45.0 0.48.0 0.52.0 0.59.0 0.60.2 0.61.2 ok: colored 3.1.1 -> windows-sys 0.61.2 ok: dirs-sys 0.5.0 -> windows-sys 0.61.2 ok: errno 0.3.14 -> windows-sys 0.61.2 ok: rustix 1.1.3 -> windows-sys 0.61.2 ok: rustls-platform-verifier 0.6.2 -> windows-sys 0.61.2 ok: tempfile 3.24.0 -> windows-sys 0.61.2 ok: winapi-util 0.1.11 -> windows-sys 0.61.2 ok: canary 'tempfile' found, its windows-sys edge read and checked above windows-sys pinning: 9 checks, exit 0 ``` Fait vérifié au passage, à l'appui de l'élargissement du déclencheur dans l'ADR 0023 (le plan disait « `hyper` et ce qu'il tire ») : le commit `f4b09b0` de #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).
Author
Owner

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 sur main et 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ête 3b8105c (PyYAML), lancé avec bash --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 et windows-sys pinning: 9 checks, exit 0. cargo check n'a pas réécrit le lock (aucune ligne Locking) : le garde a lu le lock commité, identique à celui de main (git diff main 3b8105c -- src-tauri/Cargo.lock .cargo/audit.toml vide).

Mutations du relecteur, lock et outil :

cas résultat
lock de main, puis ceux des tags v0.14.0 à v0.17.1 (témoins) exit 0, 9 checks chacun
vraie dérive : export de src-tauri/ par git archive, cargo update -p hyper le 2026-10-11 (hyper 1.8.1 → 1.12.0, want 0.3.1 → 0.3.2, 666 paquets avant et après) les 7 arêtes gardées bougent, et elles seules (diff de toutes les arêtes windows-sys du lock) ; 7 FAIL, exit 1
une seule arête à la main (winapi-util → 0.48.0) 1 FAIL, exit 1
mauvaise version avec suffixe de source (colored → 0.52.0 (registry+…)) FAIL, exit 1
arête dérivée indentée par une tabulation (errno) FAIL, exit 1
seconde arête windows-sys 0.52.0 dans le bloc tempfile FAIL sur elle, 10 checks
bloc windows-sys 0.61.2 retiré, arêtes intactes règle 3, exit 1
échange à compte constant (0.45.0 → 0.44.0) règle 3, exit 1
lock en CRLF échec fermé (ensemble, 7 blocs introuvables, canari)
awk muet (shim qui sort en 0 sans rien imprimer) échec fermé, 9 FAIL

Mutations du relecteur, script :

mutation résultat
canary_checked=1 neutralisé, lock de main exit 1 sur le canari : il est bien câblé
boucle while passée dans un sous-shell (printf … | while), lock dérivé rc perdu dans le sous-shell, mais le canari rougit : exit 1 (2 checks). Le canari attrape la régression classique
awk imprime tous ses faits puis sort en 2 (shim) garde de la PR : FAIL: awk exited 2, exit 1. Sans le test de awk_rc : exit 0. Ce test, et lui seul, tue cette mutation

Procé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 hyper et want (dont l'arête pin-utils que hyper 1.12 abandonne), cargo metadata --locked sort en 0 sans toucher au fichier (empreinte identique), le garde repasse. Contre-épreuve : une remise hors borne (colored → 0.45.0) est refusée par cargo metadata --locked (rc 101). La vérification de la procédure attrape donc une mauvaise réparation.

Faits de l'ADR recoupés.

  • Coût : cargo tree --target x86_64-pc-windows-msvc, en -e normal,build comme 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é.
  • Bornes : la commande cargo metadata de l'ADR sort 35 exigences sur windows-sys ; hors ^0.x, exactement les sept de CRATES.
  • Historique : le garde rejoué sur chaque commit de main (first-parent) qui touche le lock depuis février. La seule fenêtre hors 0.61.2 va de f4b09b0 (#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 strophe h2.
  • Runs 322, 402, 451, 491 et 508 : build-and-release des tags v0.14.0 à v0.17.1, tous success (/actions/tasks).
  • Date de la mesure rustls : 2026-09-21 en heure locale (commit 8ea3410 à 20:09 EDT, commentaire de #345 à 20:11 EDT), conforme à la convention du dépôt.

Fermeture. La timeline de #345 porte un pull_ref closes venant de #415, et le premier commit porte Resolves #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)

  1. Prémisse fausse : le conteneur a Python au moment de l'étape. Le commentaire du workflow (« since the ubuntu:22.04 container has no Python ») et l'ADR (« le conteneur ubuntu:22.04 n'a pas Python ») le disent ; l'erreur vient du corps de #345. Le log du run 517 montre Setting 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 paquets apt de cette étape. Le choix d'awk reste 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.
  2. ADR, ligne « Issues » : « #344 (troisième dérive ». Le tableau de l'ADR et sa phrase « les deux dérives passées » font de #344 la deuxième dérive ; le corps d'origine de #345 parlait de « troisième rencontre » (#310, #321, #344). Et #344 est la PR qui ferme #343 : écrire « PR #344 ».
  3. ADR, « Procédure quand le garde échoue » : deux échecs sans conduite à tenir.
    • 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 de windows-sys dans cette version : même traitement que « bloc introuvable »).
    • Un second bloc d'un nom gardé dont la borne exclut 0.61.2 (par exemple un tempfile plus 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 --locked refuse 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.
  4. Commentaire du workflow sur le code de sortie d'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 un awk qui échoue après avoir tout imprimé. Reformulation optionnelle.
  5. Corps de la PR, pas le dépôt : « pour qu'une liste CRATES vidée ou amputée échoue ». Le canari n'attrape qu'une liste vidée ou privée de tempfile ; 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.
  6. Optionnel, faible priorité. Le commit de /release modifie Cargo.lock directement sur main, 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 par cargo 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 /release fermerait le trou.

Actions faites

  • Revue avec exécution : script extrait et rejoué, 12 mutations du relecteur (9 sur le lock ou l'outil, 3 sur le script), réparation de l'ADR et sa contre-épreuve, coût, bornes, historique du lock et runs de release vérifiés, log du run 517 lu.
  • Aucun fichier du dépôt modifié (lectures git show, git log et git archive seulement). Copie hors dépôt /tmp/pr415-review (export de src-tauri/, locks, log de CI) supprimée.
  • Label de #345 : status:review → status:approved.
## 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 sur `main` et 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ête `3b8105c` (PyYAML), lancé avec `bash --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 et `windows-sys pinning: 9 checks, exit 0`. `cargo check` n'a pas réécrit le lock (aucune ligne `Locking`) : le garde a lu le lock commité, identique à celui de `main` (`git diff main 3b8105c -- src-tauri/Cargo.lock .cargo/audit.toml` vide). **Mutations du relecteur, lock et outil :** | cas | résultat | |---|---| | lock de `main`, puis ceux des tags v0.14.0 à v0.17.1 (témoins) | exit 0, 9 checks chacun | | vraie dérive : export de `src-tauri/` par `git archive`, `cargo update -p hyper` le 2026-10-11 (hyper 1.8.1 → 1.12.0, want 0.3.1 → 0.3.2, 666 paquets avant et après) | les 7 arêtes gardées bougent, et elles seules (diff de toutes les arêtes `windows-sys` du lock) ; 7 FAIL, exit 1 | | une seule arête à la main (`winapi-util` → 0.48.0) | 1 FAIL, exit 1 | | mauvaise version avec suffixe de source (`colored` → `0.52.0 (registry+…)`) | FAIL, exit 1 | | arête dérivée indentée par une tabulation (`errno`) | FAIL, exit 1 | | seconde arête `windows-sys 0.52.0` dans le bloc `tempfile` | FAIL sur elle, 10 checks | | bloc `windows-sys 0.61.2` retiré, arêtes intactes | règle 3, exit 1 | | échange à compte constant (0.45.0 → 0.44.0) | règle 3, exit 1 | | lock en CRLF | échec fermé (ensemble, 7 blocs introuvables, canari) | | `awk` muet (shim qui sort en 0 sans rien imprimer) | échec fermé, 9 FAIL | **Mutations du relecteur, script :** | mutation | résultat | |---|---| | `canary_checked=1` neutralisé, lock de `main` | exit 1 sur le canari : il est bien câblé | | boucle `while` passée dans un sous-shell (`printf … \| while`), lock dérivé | `rc` perdu dans le sous-shell, mais le canari rougit : exit 1 (2 checks). Le canari attrape la régression classique | | `awk` imprime tous ses faits puis sort en 2 (shim) | garde de la PR : `FAIL: awk exited 2`, exit 1. **Sans le test de `awk_rc` : exit 0.** Ce test, et lui seul, tue cette mutation | **Procé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 `hyper` et `want` (dont l'arête `pin-utils` que hyper 1.12 abandonne), `cargo metadata --locked` sort en 0 sans toucher au fichier (empreinte identique), le garde repasse. Contre-épreuve : une remise hors borne (`colored` → 0.45.0) est refusée par `cargo metadata --locked` (rc 101). La vérification de la procédure attrape donc une mauvaise réparation. **Faits de l'ADR recoupés.** - Coût : `cargo tree --target x86_64-pc-windows-msvc`, en `-e normal,build` comme 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é. - Bornes : la commande `cargo metadata` de l'ADR sort 35 exigences sur `windows-sys` ; hors `^0.x`, exactement les sept de `CRATES`. - Historique : le garde rejoué sur chaque commit de `main` (first-parent) qui touche le lock depuis février. La seule fenêtre hors `0.61.2` va de `f4b09b0` (#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 strophe `h2`. - Runs 322, 402, 451, 491 et 508 : `build-and-release` des tags v0.14.0 à v0.17.1, tous `success` (`/actions/tasks`). - Date de la mesure `rustls` : 2026-09-21 en heure locale (commit `8ea3410` à 20:09 EDT, commentaire de #345 à 20:11 EDT), conforme à la convention du dépôt. **Fermeture.** La timeline de #345 porte un `pull_ref` `closes` venant de #415, et le premier commit porte `Resolves #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) 1. **Prémisse fausse : le conteneur a Python au moment de l'étape.** Le commentaire du workflow (« since the ubuntu:22.04 container has no Python ») et l'ADR (« le conteneur `ubuntu:22.04` n'a pas Python ») le disent ; l'erreur vient du corps de #345. Le log du run 517 montre `Setting 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 paquets `apt` de cette étape. Le choix d'`awk` reste 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. 2. **ADR, ligne « Issues » : « #344 (troisième dérive ».** Le tableau de l'ADR et sa phrase « les deux dérives passées » font de #344 la deuxième dérive ; le corps d'origine de #345 parlait de « troisième rencontre » (#310, #321, #344). Et #344 est la PR qui ferme #343 : écrire « PR #344 ». 3. **ADR, « Procédure quand le garde échoue » : deux échecs sans conduite à tenir.** - `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 de `windows-sys` dans cette version : même traitement que « bloc introuvable »). - Un second bloc d'un nom gardé dont la borne exclut 0.61.2 (par exemple un `tempfile` plus 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 --locked` refuse 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. 4. **Commentaire du workflow sur le code de sortie d'`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 un `awk` qui échoue après avoir tout imprimé. Reformulation optionnelle. 5. **Corps de la PR, pas le dépôt** : « pour qu'une liste `CRATES` vidée ou amputée échoue ». Le canari n'attrape qu'une liste vidée ou privée de `tempfile` ; 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. 6. **Optionnel, faible priorité.** Le commit de `/release` modifie `Cargo.lock` directement sur `main`, 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 par `cargo 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 `/release` fermerait le trou. ### Actions faites - Revue avec exécution : script extrait et rejoué, 12 mutations du relecteur (9 sur le lock ou l'outil, 3 sur le script), réparation de l'ADR et sa contre-épreuve, coût, bornes, historique du lock et runs de release vérifiés, log du run 517 lu. - Aucun fichier du dépôt modifié (lectures `git show`, `git log` et `git archive` seulement). Copie hors dépôt `/tmp/pr415-review` (export de `src-tauri/`, locks, log de CI) supprimée. - Label de #345 : `status:review` → `status:approved`.
maximus changed target branch from issue-376-node24 to main 2026-10-12 19:32:28 +00:00
maximus merged commit 3b8105c253 into main 2026-10-12 19:32:33 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#415
No description provided.