docs(release): add a real update-cycle QA checklist as step 10 #322

Closed
maximus wants to merge 0 commits from issue-315-qa-update-cycle into main
Owner

Resolves #315

L'etape 9 du skill /release inspectait latest.json et s'arretait la. Ca prouve qu'il est bien forme, pas qu'il installe. Le reste de la chaine — telechargement TLS, verification de signature, execution de l'installeur, redemarrage — n'est exerce par aucun test : cargo check et cargo test prouvent que ce code compile, rien de plus. Une regression s'y voit chez l'utilisateur, au moment de la mise a jour, et l'auto-update est une fonctionnalite Base+.

Ce n'est pas automatise, et c'est assume

Le test demande deux environnements de bureau reels. La valeur ne vient donc pas de l'automatisation mais des preconditions : ce sont elles qui separent « derouler le test » de « avoir l'air de le derouler ». Chacune a un mode d'echec ou la case se coche sans que rien n'ait ete verifie.

  • Partir de la version precedente. check() compare strictement release.version > version_courante. Tester sur la machine qui vient de builder la release affiche « a jour », et la checklist se coche comme « rien a mettre a jour » — le saut silencieux que #315 existe pour eliminer, avec en prime une trace ecrite affirmant qu'elle est passee.
  • Une cle Base+ sur chaque machine, et supprimer tout activation.token venu d'une autre machine. useUpdater appelle check_entitlement("auto-update") et bascule en notEntitled avant d'interroger le serveur ; un token lie a un autre machine_id fait retomber l'edition en Gratuite, et le testeur voit une carte anodine plutot qu'un echec.
  • Un agent polkit vivant sous Linux, et noter quelle invite est reellement apparue : install_deb cascade pkexec -> zenity/kdialog -> sudo dans un terminal. Sans agent, l'app parait figee au lieu d'echouer, et un chemin de repli passe pour le chemin nominal.

Deux flux separes, parce qu'ils different vraiment

Sous Windows, downloadAndInstall ne rend jamais la main : le processus fait exit(0) et l'installeur NSIS prend le relais. Les etats readyToInstall et installing ne s'affichent jamais — les attendre ferait echouer un test qui a reussi.

Sous Linux, l'app reste vivante, une invite d'authentification apparait, et l'utilisateur clique le controle de redemarrage.

La checklist part du seul point d'entree reel : Parametres -> Systemes -> « Verifier les mises a jour ». Il n'y a aucune verification automatique dans l'app, ce bouton et celui de la page d'erreur sont les deux seuls declencheurs.

Ce que le test ne prouve pas — et ca corrige la premisse de #315

J'avais ecrit dans #315 que le correctif tar « ne se manifesterait qu'au moment de la mise a jour ». C'est faux.

Dans tauri-plugin-updater, tar n'est atteint que par install_appimage et la branche macOS .app.tar.gz. Nos bundles ne passent pas par la : le .deb fait pkexec dpkg -i, le NSIS ecrit le .exe dans un temp et le lance. Tant qu'on ne livre pas d'AppImage, le chemin tar est mort et aucune checklist manuelle ne le couvrira.

La doc l'ecrit noir sur blanc. Ce qui est reellement prouve : TLS (rustls-webpki), signature minisign, execution de l'installeur, redemarrage.

Le chemin d'echec n'est pas un rollback

Republier le latest.json precedent arrete la propagation, mais la comparaison stricte de check() fait que les utilisateurs deja passes a la version cassee ne se verront jamais proposer la precedente : ils sont bloques dessus. Le vrai correctif est une vN+1.

Presenter le re-PUT comme « le rollback » serait faux dans la direction qui compte — quelqu'un le lirait en pleine incident. La doc enonce les trois faits : ce que ca arrete, ce que ca n'arrete pas, et ou est le vrai correctif. Elle note aussi que le corps du latest.json precedent est recuperable depuis les assets de la release precedente, sa copie dans le registre ayant ete detruite par le DELETE que release.yml fait avant chaque envoi, et que l'operation demande le PACKAGE_TOKEN.

rpm : casse, pas « non verifie »

Ecrit comme tel, et sorti en issue separee (#320) plutot que laisse en ligne de checklist : latest.json ne porte qu'une entree linux-x86_64 construite depuis le .deb, donc une installation rpm recoit des octets deb que Installer::Rpm rejette. C'est un defaut produit, pas un trou de couverture.

Forme

La checklist vit dans docs/qa-update-cycle.md, sur le modele de docs/qa-refonte-seed-categories-ipc.md (bloc Prerequis + cases - [ ]). SKILL.md garde le role de declencheur et pointe dessus — c'est le fichier qu'on lit en faisant une release. Son frontmatter updated: et sa section ## Changelog sont mis a jour selon sa propre convention.

Derniere case : consigner le resultat sur la release Forgejo, et si la checklist n'a pas ete deroulee, l'ecrire avec la raison. Une etape non tracee est indiscernable d'une etape passee.

CI

Aucun workflow ne se declenche sur cette PR : check-rust.yml filtre sur src-tauri/** et .cargo/**, check-frontend.yml ignore docs/** et .claude/**. C'est attendu pour un changement markdown seul — signale ici pour que l'absence de checks ne se lise pas comme un echec.

Pas d'entree CHANGELOG : changement de processus, aucun effet visible pour l'utilisateur.

Resolves #315 L'etape 9 du skill `/release` inspectait `latest.json` et s'arretait la. Ca prouve qu'il est **bien forme**, pas qu'il **installe**. Le reste de la chaine — telechargement TLS, verification de signature, execution de l'installeur, redemarrage — n'est exerce par **aucun** test : `cargo check` et `cargo test` prouvent que ce code compile, rien de plus. Une regression s'y voit chez l'utilisateur, au moment de la mise a jour, et l'auto-update est une fonctionnalite **Base+**. ## Ce n'est pas automatise, et c'est assume Le test demande deux environnements de bureau reels. La valeur ne vient donc pas de l'automatisation mais des **preconditions** : ce sont elles qui separent « derouler le test » de « avoir l'air de le derouler ». Chacune a un mode d'echec ou la case se coche sans que rien n'ait ete verifie. - **Partir de la version precedente.** `check()` compare strictement `release.version > version_courante`. Tester sur la machine qui vient de builder la release affiche « a jour », et la checklist se coche comme « rien a mettre a jour » — le saut silencieux que #315 existe pour eliminer, avec en prime une trace ecrite affirmant qu'elle est passee. - **Une cle Base+ sur chaque machine**, et **supprimer tout `activation.token` venu d'une autre machine**. `useUpdater` appelle `check_entitlement("auto-update")` et bascule en `notEntitled` **avant** d'interroger le serveur ; un token lie a un autre `machine_id` fait retomber l'edition en Gratuite, et le testeur voit une carte anodine plutot qu'un echec. - **Un agent polkit vivant sous Linux**, et noter **quelle invite est reellement apparue** : `install_deb` cascade `pkexec` -> `zenity`/`kdialog` -> `sudo` dans un terminal. Sans agent, l'app **parait figee au lieu d'echouer**, et un chemin de repli passe pour le chemin nominal. ## Deux flux separes, parce qu'ils different vraiment Sous **Windows**, `downloadAndInstall` ne rend jamais la main : le processus fait `exit(0)` et l'installeur NSIS prend le relais. Les etats `readyToInstall` et `installing` **ne s'affichent jamais** — les attendre ferait echouer un test qui a reussi. Sous **Linux**, l'app reste vivante, une invite d'authentification apparait, et l'utilisateur clique le controle de redemarrage. La checklist part du seul point d'entree reel : **Parametres -> Systemes -> « Verifier les mises a jour »**. Il n'y a aucune verification automatique dans l'app, ce bouton et celui de la page d'erreur sont les deux seuls declencheurs. ## Ce que le test ne prouve pas — et ca corrige la premisse de #315 J'avais ecrit dans #315 que le correctif `tar` « ne se manifesterait qu'au moment de la mise a jour ». **C'est faux.** Dans `tauri-plugin-updater`, `tar` n'est atteint que par `install_appimage` et la branche macOS `.app.tar.gz`. Nos bundles ne passent pas par la : le `.deb` fait `pkexec dpkg -i`, le NSIS ecrit le `.exe` dans un temp et le lance. **Tant qu'on ne livre pas d'AppImage, le chemin `tar` est mort** et aucune checklist manuelle ne le couvrira. La doc l'ecrit noir sur blanc. Ce qui est reellement prouve : TLS (`rustls-webpki`), signature minisign, execution de l'installeur, redemarrage. ## Le chemin d'echec n'est pas un rollback Republier le `latest.json` precedent **arrete la propagation**, mais la comparaison stricte de `check()` fait que les utilisateurs deja passes a la version cassee ne se verront **jamais** proposer la precedente : ils sont bloques dessus. Le vrai correctif est une **vN+1**. Presenter le re-`PUT` comme « le rollback » serait faux dans la direction qui compte — quelqu'un le lirait en pleine incident. La doc enonce les trois faits : ce que ca arrete, ce que ca n'arrete pas, et ou est le vrai correctif. Elle note aussi que le corps du `latest.json` precedent est recuperable depuis les assets de la release precedente, sa copie dans le registre ayant ete detruite par le `DELETE` que `release.yml` fait avant chaque envoi, et que l'operation demande le `PACKAGE_TOKEN`. ## rpm : casse, pas « non verifie » Ecrit comme tel, et sorti en issue separee (**#320**) plutot que laisse en ligne de checklist : `latest.json` ne porte qu'une entree `linux-x86_64` construite depuis le `.deb`, donc une installation rpm recoit des octets deb que `Installer::Rpm` rejette. C'est un defaut produit, pas un trou de couverture. ## Forme La checklist vit dans `docs/qa-update-cycle.md`, sur le modele de `docs/qa-refonte-seed-categories-ipc.md` (bloc Prerequis + cases `- [ ]`). `SKILL.md` garde le role de declencheur et pointe dessus — c'est le fichier qu'on lit en faisant une release. Son frontmatter `updated:` et sa section `## Changelog` sont mis a jour selon sa propre convention. Derniere case : consigner le resultat sur la release Forgejo, et si la checklist **n'a pas** ete deroulee, l'ecrire avec la raison. Une etape non tracee est indiscernable d'une etape passee. ## CI **Aucun workflow ne se declenche sur cette PR** : `check-rust.yml` filtre sur `src-tauri/**` et `.cargo/**`, `check-frontend.yml` ignore `docs/**` et `.claude/**`. C'est attendu pour un changement markdown seul — signale ici pour que l'absence de checks ne se lise pas comme un echec. Pas d'entree CHANGELOG : changement de processus, aucun effet visible pour l'utilisateur.
maximus added 1 commit 2026-07-28 01:35:01 +00:00
Step 9 inspected latest.json and stopped there. That proves the file is well
formed, not that it installs: the TLS download, signature verification,
installer execution and relaunch are exercised by no test at all — cargo check
and cargo test only prove that code compiles. A regression there surfaces at
update time, on a user's machine, and automatic updates are a Base+ feature.

Written as a manual checklist rather than automation because it needs two real
desktop environments. The value is in the preconditions, which are what make
the difference between running the test and only appearing to:

- Test from a machine still on the PREVIOUS version. check() compares
  release.version > current strictly, so testing on the machine that just
  built the release shows "up to date" and the checklist gets ticked as
  "nothing to update" — the silent skip it exists to prevent, now with a
  paper trail claiming it passed.
- A Base+ key on each machine, with any activation.token from another machine
  removed. Auto-update is entitlement-gated: useUpdater dispatches NOT_ENTITLED
  before check() ever runs, and a token bound to a different machine_id
  silently resolves the edition back to Free.
- A live polkit agent on Linux, and record which prompt actually appeared —
  install_deb cascades pkexec -> zenity/kdialog -> terminal sudo, so without an
  agent the app appears to hang instead of failing.

The two target flows are written separately because they genuinely differ: on
Windows downloadAndInstall never returns (the process exits and NSIS takes
over, so readyToInstall/installing never render), while on Linux the app stays
alive through a polkit prompt and a restart control.

The doc states what the test does NOT prove: `tar` stays unexercised. Its
vulnerable path is only reached by install_appimage and the macOS .app.tar.gz
branch; our .deb goes through `pkexec dpkg -i` and our NSIS path launches the
.exe. That corrects #315's own premise.

The failure path is documented as an incident playbook rather than a
"rollback", because it is not one. Republishing the previous latest.json stops
propagation, but check()'s strict comparison means users already on the broken
version are never offered the older one — the real fix is a vN+1.

rpm is recorded as known-broken, not unverified, and tracked in #320.

Resolves #315

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

REQUEST_CHANGES

Doc-only PR, donc la revue a porté sur la seule chose qui compte ici : est-ce que chaque affirmation est vraie ? J'ai retracé les 14 claims dans le code. Treize tiennent, souvent au détail près. Une est fausse, et c'est la séquence d'états de la section Linux — la seule cible où ces états sont observables, donc le cœur opérationnel du document.


Bloquant

1. docs/qa-update-cycle.md §2 « Linux (.deb) » — la séquence d'états est inversée

La checklist annonce :

- [ ] Après le téléchargement, l'app reste vivante et passe en `readyToInstall`.
- [ ] Une invite d'authentification apparaît.
- [ ] Authentifier → état `installing`, puis le contrôle de redémarrage apparaît.

Le code fait l'inverse. downloadAndInstall est un seul appel qui télécharge ET installe :

  • node_modules/@tauri-apps/plugin-updater/dist-js/index.js:43-54 → un invoke('plugin:updater|download_and_install').
  • tauri-plugin-updater-2.10.0/src/commands.rs:180-194 — l'événement Finished est émis à la fin du téléchargement, puis download_and_install enchaîne sur l'installation.
  • src/hooks/useUpdater.ts:119-121Finished est un no-op (// handled below), aucun dispatch. L'UI reste donc sur downloading.
  • updater.rs:1048-1141install_debtry_install_with_privilegespkexec : l'invite s'ouvre à l'intérieur du même await.
  • src/hooks/useUpdater.ts:123READY_TO_INSTALL n'est dispatché qu'après que l'installation est terminée.

Séquence réelle :

  1. downloading — barre de progression
  2. téléchargement terminé → l'UI affiche toujours « Téléchargement en cours... »
  3. l'invite d'authentification apparaît, pendant que la carte dit encore « Téléchargement en cours... »
  4. dpkg -i termine → readyToInstall = « Mise à jour prête à installer » + bouton « Installer et redémarrer » ← c'est ça, le contrôle de redémarrage
  5. clic → installing = « Installation en cours... » → relaunch()

Trois conséquences, dans l'ordre de gravité :

  • Le piège que le prérequis polkit existe pour éviter est réintroduit par l'ordre des cases. Sans agent polkit, l'app « paraît figée » — mais elle paraît figée en downloading, pas en readyToInstall. Un testeur qui suit cette checklist cherche un blocage après readyToInstall ; ce qu'il voit, c'est une barre de téléchargement immobile. Il consigne « le téléchargement bloque » au lieu de « pas d'agent polkit » : le mauvais rapport de bug, soit exactement la fausse trace que la page dit combattre.
  • La case 2 se coche à un moment où l'app n'est pas dans l'état annoncé. Le testeur voit une boîte d'authentification par-dessus « Téléchargement en cours... » et aucune ligne de la checklist ne décrit ça.
  • « Authentifier → état installing, puis le contrôle de redémarrage apparaît » inverse cause et effet. installing est dispatché par installAndRestart (useUpdater.ts:129-132) quand l'utilisateur clique le contrôle de redémarrage. Le contrôle apparaît donc d'abord, et installing est ce qui le remplace.

À ajouter au passage, parce que c'est le vrai piège de lecture de cet écran : quand readyToInstall s'affiche, le paquet est déjà installé sur le disque. Le bouton « Installer et redémarrer » ne fait que relaunch(). Le libellé ment sur cette cible ; un testeur qui s'arrête là croit que rien n'a été installé, et celui qui voit la version changer après le clic attribue l'installation au clic.

Séquence corrigée proposée :

- [ ] Même point d'entrée, mêmes états jusqu'à `downloading`.
- [ ] **Pendant que la carte affiche encore « Téléchargement en cours... »**, une invite
      d'authentification apparaît. C'est le moment nominal : `downloadAndInstall` télécharge
      ET installe dans le même appel, et l'événement `Finished` ne change pas d'état.
      **Noter laquelle** : polkit (nominal), zenity/kdialog, ou rien du tout
      (repli `sudo` → l'app reste figée sur « Téléchargement en cours... »).

      Invite observée : `________________`

- [ ] Authentifier → l'app **reste vivante** et passe en `readyToInstall`
      (« Mise à jour prête à installer » + bouton « Installer et redémarrer »).
      À ce stade le `.deb` est **déjà installé** : le bouton ne fait que relancer l'app.
- [ ] Cliquer → état `installing`, l'app redémarre.
- [ ] Vérifier la version, re-vérifier → `upToDate`.

C'est une correction d'un paragraphe. Le reste de la page n'est pas touché.


Suggestions (non bloquantes)

2. §1 Windows — « ce bouton et celui de la page d'erreur sont les deux seuls déclencheurs » : il y en a trois.
checkForUpdate est câblé en UpdateCard.tsx:60 (état idle), :89 (petite icône rafraîchir dans l'état upToDate) et :201 (réessayer, état error). La phrase importante — « il n'y a aucune vérification automatique dans l'app » — est exacte : le seul useEffect (:40-44) charge les notes de version. Il suffit d'écrire trois.

3. SKILL.md:62-65 — la nouvelle entrée de changelog casse l'ordre du fichier.
2026-07-27 est insérée entre 2026-07-01 et 2026-07-13, alors que le fichier était strictement croissant. Faible enjeu (les autres skills ne sont pas cohérents non plus), mais ici c'est une régression locale.

4. Titre de PR. « to step 9 » — le changement ajoute une étape 10.


Vérifié et exact (pour que la correction ne relance pas le travail déjà fait)

J'ai retracé chaque affirmation ; toutes celles-ci tiennent, y compris les numéros de ligne :

  • Comparaison stricte release.version > self.current_versionupdater.rs:532, aucun version_comparator custom côté app. Le prérequis « partir de la version précédente » est fondé.
  • Entitlement avant check()useUpdater.ts:79-86 ; auto-update = Base|Premium (entitlements.rs:22). Mieux que ce que dit la page : même avec auto-update dans les features[] signées, Free est refusé (entitlements.rs:109, fail-closed).
  • activation.token lié au machine_idlicense_commands.rs:210-266. La nuance de la page est exactement juste : token absent = pré-activation tolérée, token d'une autre machine = retour en Gratuite.
  • dev-override absent des builds de release — feature Cargo non-défaut (Cargo.toml:78), et release.yml:50 ne passe aucun --features.
  • Cascade pkexeczenity/kdialogsudoupdater.rs:1101-1141, littéralement dans cet ordre.
  • Windows exit(0)updater.rs:865, donc readyToInstall/installing ne s'affichent effectivement jamais sur cette cible. La section Windows est juste de bout en bout, y compris la remarque sur contentLength (un serveur qui ne le renvoie pas → progressPercent null → barre à 0, visible).
  • tar inatteignable — les deux seuls usages sont install_appimage (updater.rs:1011) et la branche macOS (:1228) ; tauri.conf.json:26 ne cible que nsis, deb, rpm. La correction de la prémisse de #315 est juste, et le chemin est bien mort.
  • rpm cassélatest.json ne porte linux-x86_64 que depuis le .deb (release.yml:104-122), l'installeur est choisi d'après le bundle installé (updater.rs:968), et install_rpm rejette sur les octets magiques (:1058-1063). Les .rpm sont bien publiés quand même (release.yml:50). Sortir ça en #320 plutôt qu'en ligne de checklist est le bon arbitrage.
  • « Si ça casse »DELETE puis PUT sur generic/simpl-resultat/latest avec PACKAGE_TOKEN (release.yml:215-240) ; la copie registre est bien détruite avant chaque envoi ; et latest.json est bien récupérable, la boucle d'upload envoie tout release-assets/* en asset de release. Le point « republier vN-1 n'est pas un rollback » est juste et mérite d'être écrit noir sur blanc.
  • CI — aucun workflow ne se déclenche : check-frontend.yml ignore docs/** et .claude/**, check-rust.yml filtre sur src-tauri/**/.cargo/**. L'absence de checks est attendue, pas un échec.
  • Lien relatif ../../../docs/qa-update-cycle.md depuis .claude/skills/release/ → résout bien à la racine. Modèle docs/qa-refonte-seed-categories-ipc.md existant.
  • Pas d'entrée CHANGELOG : correct, changement de processus sans effet utilisateur.

Le document est bien meilleur que la moyenne d'une checklist QA — les modes d'échec « la case se coche sans que rien ne soit vérifié » sont le bon angle, et l'auto-correction de la prémisse tar de #315 est honnête et vérifiable. C'est précisément parce que sa valeur est sa précision que la séquence Linux doit être juste avant merge.

## REQUEST_CHANGES Doc-only PR, donc la revue a porté sur la seule chose qui compte ici : **est-ce que chaque affirmation est vraie ?** J'ai retracé les 14 claims dans le code. Treize tiennent, souvent au détail près. Une est fausse, et c'est la séquence d'états de la section Linux — la seule cible où ces états sont observables, donc le cœur opérationnel du document. --- ### Bloquant **1. `docs/qa-update-cycle.md` §2 « Linux (.deb) » — la séquence d'états est inversée** La checklist annonce : ``` - [ ] Après le téléchargement, l'app reste vivante et passe en `readyToInstall`. - [ ] Une invite d'authentification apparaît. - [ ] Authentifier → état `installing`, puis le contrôle de redémarrage apparaît. ``` Le code fait l'inverse. `downloadAndInstall` est **un seul appel qui télécharge ET installe** : - `node_modules/@tauri-apps/plugin-updater/dist-js/index.js:43-54` → un `invoke('plugin:updater|download_and_install')`. - `tauri-plugin-updater-2.10.0/src/commands.rs:180-194` — l'événement `Finished` est émis **à la fin du téléchargement**, puis `download_and_install` enchaîne sur l'installation. - `src/hooks/useUpdater.ts:119-121` — `Finished` est un **no-op** (`// handled below`), aucun dispatch. L'UI reste donc sur `downloading`. - `updater.rs:1048-1141` — `install_deb` → `try_install_with_privileges` → `pkexec` : **l'invite s'ouvre à l'intérieur du même `await`**. - `src/hooks/useUpdater.ts:123` — `READY_TO_INSTALL` n'est dispatché qu'**après** que l'installation est terminée. Séquence réelle : 1. `downloading` — barre de progression 2. téléchargement terminé → **l'UI affiche toujours « Téléchargement en cours... »** 3. **l'invite d'authentification apparaît, pendant que la carte dit encore « Téléchargement en cours... »** 4. `dpkg -i` termine → `readyToInstall` = « Mise à jour prête à installer » + bouton « Installer et redémarrer » ← **c'est ça, le contrôle de redémarrage** 5. clic → `installing` = « Installation en cours... » → `relaunch()` Trois conséquences, dans l'ordre de gravité : - **Le piège que le prérequis polkit existe pour éviter est réintroduit par l'ordre des cases.** Sans agent polkit, l'app « paraît figée » — mais elle paraît figée **en `downloading`**, pas en `readyToInstall`. Un testeur qui suit cette checklist cherche un blocage après `readyToInstall` ; ce qu'il voit, c'est une barre de téléchargement immobile. Il consigne « le téléchargement bloque » au lieu de « pas d'agent polkit » : le mauvais rapport de bug, soit exactement la fausse trace que la page dit combattre. - **La case 2 se coche à un moment où l'app n'est pas dans l'état annoncé.** Le testeur voit une boîte d'authentification par-dessus « Téléchargement en cours... » et aucune ligne de la checklist ne décrit ça. - **« Authentifier → état `installing`, puis le contrôle de redémarrage apparaît » inverse cause et effet.** `installing` est dispatché par `installAndRestart` (`useUpdater.ts:129-132`) **quand l'utilisateur clique** le contrôle de redémarrage. Le contrôle apparaît donc d'abord, et `installing` est ce qui le remplace. À ajouter au passage, parce que c'est le vrai piège de lecture de cet écran : **quand `readyToInstall` s'affiche, le paquet est déjà installé sur le disque**. Le bouton « Installer et redémarrer » ne fait que `relaunch()`. Le libellé ment sur cette cible ; un testeur qui s'arrête là croit que rien n'a été installé, et celui qui voit la version changer après le clic attribue l'installation au clic. Séquence corrigée proposée : ``` - [ ] Même point d'entrée, mêmes états jusqu'à `downloading`. - [ ] **Pendant que la carte affiche encore « Téléchargement en cours... »**, une invite d'authentification apparaît. C'est le moment nominal : `downloadAndInstall` télécharge ET installe dans le même appel, et l'événement `Finished` ne change pas d'état. **Noter laquelle** : polkit (nominal), zenity/kdialog, ou rien du tout (repli `sudo` → l'app reste figée sur « Téléchargement en cours... »). Invite observée : `________________` - [ ] Authentifier → l'app **reste vivante** et passe en `readyToInstall` (« Mise à jour prête à installer » + bouton « Installer et redémarrer »). À ce stade le `.deb` est **déjà installé** : le bouton ne fait que relancer l'app. - [ ] Cliquer → état `installing`, l'app redémarre. - [ ] Vérifier la version, re-vérifier → `upToDate`. ``` C'est une correction d'un paragraphe. Le reste de la page n'est pas touché. --- ### Suggestions (non bloquantes) **2. §1 Windows — « ce bouton et celui de la page d'erreur sont les deux seuls déclencheurs » : il y en a trois.** `checkForUpdate` est câblé en `UpdateCard.tsx:60` (état `idle`), `:89` (petite icône rafraîchir dans l'état `upToDate`) et `:201` (réessayer, état `error`). La phrase importante — « il n'y a aucune vérification automatique dans l'app » — est **exacte** : le seul `useEffect` (`:40-44`) charge les notes de version. Il suffit d'écrire trois. **3. `SKILL.md:62-65` — la nouvelle entrée de changelog casse l'ordre du fichier.** `2026-07-27` est insérée entre `2026-07-01` et `2026-07-13`, alors que le fichier était strictement croissant. Faible enjeu (les autres skills ne sont pas cohérents non plus), mais ici c'est une régression locale. **4. Titre de PR.** « to step 9 » — le changement ajoute une **étape 10**. --- ### Vérifié et exact (pour que la correction ne relance pas le travail déjà fait) J'ai retracé chaque affirmation ; toutes celles-ci tiennent, y compris les numéros de ligne : - **Comparaison stricte** `release.version > self.current_version` — `updater.rs:532`, aucun `version_comparator` custom côté app. Le prérequis « partir de la version précédente » est fondé. - **Entitlement avant `check()`** — `useUpdater.ts:79-86` ; `auto-update` = Base|Premium (`entitlements.rs:22`). Mieux que ce que dit la page : même avec `auto-update` dans les `features[]` signées, Free est refusé (`entitlements.rs:109`, fail-closed). - **`activation.token` lié au `machine_id`** — `license_commands.rs:210-266`. La nuance de la page est exactement juste : token absent = pré-activation tolérée, token d'une autre machine = retour en Gratuite. - **`dev-override` absent des builds de release** — feature Cargo non-défaut (`Cargo.toml:78`), et `release.yml:50` ne passe aucun `--features`. - **Cascade `pkexec` → `zenity`/`kdialog` → `sudo`** — `updater.rs:1101-1141`, littéralement dans cet ordre. - **Windows `exit(0)`** — `updater.rs:865`, donc `readyToInstall`/`installing` ne s'affichent effectivement jamais sur cette cible. La section Windows est juste de bout en bout, y compris la remarque sur `contentLength` (un serveur qui ne le renvoie pas → `progressPercent` null → barre à 0, visible). - **`tar` inatteignable** — les deux seuls usages sont `install_appimage` (`updater.rs:1011`) et la branche macOS (`:1228`) ; `tauri.conf.json:26` ne cible que `nsis, deb, rpm`. La correction de la prémisse de #315 est **juste**, et le chemin est bien mort. - **rpm cassé** — `latest.json` ne porte `linux-x86_64` que depuis le `.deb` (`release.yml:104-122`), l'installeur est choisi d'après le bundle **installé** (`updater.rs:968`), et `install_rpm` rejette sur les octets magiques (`:1058-1063`). Les `.rpm` sont bien publiés quand même (`release.yml:50`). Sortir ça en #320 plutôt qu'en ligne de checklist est le bon arbitrage. - **« Si ça casse »** — `DELETE` puis `PUT` sur `generic/simpl-resultat/latest` avec `PACKAGE_TOKEN` (`release.yml:215-240`) ; la copie registre est bien détruite avant chaque envoi ; et `latest.json` est bien récupérable, la boucle d'upload envoie **tout** `release-assets/*` en asset de release. Le point « republier vN-1 n'est pas un rollback » est juste et mérite d'être écrit noir sur blanc. - **CI** — aucun workflow ne se déclenche : `check-frontend.yml` ignore `docs/**` et `.claude/**`, `check-rust.yml` filtre sur `src-tauri/**`/`.cargo/**`. L'absence de checks est attendue, pas un échec. - **Lien relatif** `../../../docs/qa-update-cycle.md` depuis `.claude/skills/release/` → résout bien à la racine. Modèle `docs/qa-refonte-seed-categories-ipc.md` existant. - **Pas d'entrée CHANGELOG** : correct, changement de processus sans effet utilisateur. Le document est bien meilleur que la moyenne d'une checklist QA — les modes d'échec « la case se coche sans que rien ne soit vérifié » sont le bon angle, et l'auto-correction de la prémisse `tar` de #315 est honnête et vérifiable. C'est précisément parce que sa valeur est sa précision que la séquence Linux doit être juste avant merge.
Author
Owner

REQUEST_CHANGES

Passe de re-vérification. Le head n'a pas bougé depuis la revue du 2026-08-14 (10d8a79, commit du 2026-07-27 ; la revue a été postée à 19:57Z et updated_at de la PR s'arrête là). Le blocage n'a donc pas été traité — mais je ne l'ai pas relayé sur parole, je l'ai retracé de zéro depuis les sources. Il est confirmé, et la ligne décisive n'avait pas été citée. Je corrige aussi un point de la revue précédente qui, appliqué tel quel, produirait une correction fausse.


Bloquant — toujours ouvert

1. docs/qa-update-cycle.md §2 « Linux (.deb) » — la séquence d'états ne correspond pas au code

Confirmé, et voici la ligne qui tranche — tauri-plugin-updater-2.10.0/src/updater.rs:723-729 :

pub async fn download_and_install<C: FnMut(usize, Option<u64>), D: FnOnce()>(
    &self, on_chunk: C, on_download_finish: D,
) -> Result<()> {
    let bytes = self.download(on_chunk, on_download_finish).await?;
    self.install(bytes)          // <- même appel, après le Finished
}

on_download_finish() est appelé à updater.rs:710, à la fin du téléchargement ; install(bytes) s'exécute ensuite, dans le même await. La chaîne complète :

  • @tauri-apps/plugin-updater/dist-js/index.jsdownloadAndInstall = un seul invoke('plugin:updater|download_and_install'), jamais install séparément.
  • commands.rs:180-194Finished est émis par la closure on_download_finish, donc avant l'installation.
  • useUpdater.ts:119-121Finished est un no-op (// handled below). L'UI ne change pas d'état.
  • useUpdater.ts:123READY_TO_INSTALL est dispatché après que l'await a résolu, c'est-à-dire après que dpkg -i a terminé.

Séquence réelle sous Linux :

  1. downloading
  2. téléchargement fini → l'UI affiche toujours « Téléchargement en cours... »
  3. l'invite pkexec s'ouvre par-dessus cet écran-là
  4. installation terminée → readyToInstall + bouton « Installer et redémarrer »
  5. clic → installingrelaunch()

La checklist demande de cocher readyToInstall avant l'invite. C'est l'inverse, et les conséquences sont exactement celles que la page dit combattre :

  • Le prérequis polkit est neutralisé par l'ordre des cases. Sans agent, l'app se fige — mais en downloading, pas en readyToInstall. Le testeur qui suit la checklist guette un blocage après readyToInstall et voit une barre de téléchargement immobile : il rapporte « le téléchargement bloque » au lieu de « pas d'agent polkit ». C'est la fausse trace, produite par la page censée l'éliminer.
  • « Authentifier → état installing » inverse cause et effet. installing vient de installAndRestart (useUpdater.ts:129-132), déclenché par le clic sur le contrôle de redémarrage. Le contrôle apparaît d'abord ; installing est ce qui le remplace.
  • À readyToInstall, le .deb est déjà installé sur le disque. installAndRestart ne fait que relaunch() (useUpdater.ts:129-132) — aucune installation. Le libellé du bouton ment sur cette cible : qui s'arrête là croit que rien n'est installé, qui voit la version changer attribue l'installation au clic. À écrire, c'est le vrai piège de lecture de cet écran.

La séquence corrigée proposée dans la revue précédente est juste ; elle reste valable telle quelle. C'est un paragraphe.


Correction de la revue précédente — à lire avant de corriger

2. Le décompte des déclencheurs était faux dans les deux sens. Il y a 4 sites, pas 2 et pas 3.

La revue du 14 disait « il y en a trois » et mappait UpdateCard.tsx:201 sur « la page d'erreur ». C'est inexact : :201 est le retry de l'état error de la carte elle-même, et ErrorPage est un composant distinct avec son propre déclencheur. Le relevé réel :

  • UpdateCard.tsx:60 — bouton « Vérifier les mises à jour » (état idle)
  • UpdateCard.tsx:89 — icône rafraîchir (état upToDate)
  • UpdateCard.tsx:201 — réessayer (état error de la carte)
  • ErrorPage.tsx:82 — bouton de la page d'erreur, via son propre handleCheckUpdate (ErrorPage.tsx:18-38), qui détecte seulement : il affiche la version dispo (:90) et n'offre aucun chemin de téléchargement.

Appliquer « écrire trois » remplacerait donc une imprécision par une autre. Si la phrase doit être corrigée, le fond utile est : quatre déclencheurs manuels, dont celui de la page d'erreur ne fait que détecter — et surtout la partie qui porte réellement, « aucune vérification automatique dans l'app », qui est exacte (le seul useEffect, UpdateCard.tsx:40-44, charge les notes de version quand l'état est déjà available).


Suggestion nouvelle — non bloquante

3. « Si ça casse » : le DELETE et le PUT ne visent pas le même préfixe d'API.

La doc écrit « DELETE puis PUT, avec le PACKAGE_TOKEN ». Dans release.yml:217-219 :

# DELETE uses API v1, PUT uses the package upload API
DELETE_URL="${GITHUB_SERVER_URL}/api/v1/packages/${OWNER}/generic/simpl-resultat/latest"
UPLOAD_URL="${GITHUB_SERVER_URL}/api/packages/${OWNER}/generic/simpl-resultat/latest"

release.yml porte un commentaire explicite là-dessus — donc le piège est connu et déjà tombé une fois. Quelqu'un qui suit la doc en incident et rejoue les deux verbes sur la même URL prend un 404 sur l'un des deux et brûle du temps au pire moment. La page fait l'effort de dire « lire cette section avant, pas pendant » ; le chemin exact des deux appels y a sa place. Le reste de la section est juste et vérifié (la copie registre est bien détruite par le DELETE avant chaque envoi, et le latest.json précédent est bien récupérable en asset de release).

4. Rappels des points mineurs déjà signalés et toujours ouverts : le changelog de SKILL.md insère 2026-07-27 entre 2026-07-01 et 2026-07-13 (le fichier était strictement croissant), et le titre de PR dit « to step 9 » alors que le changement ajoute une étape 10.


Re-vérifié indépendamment — tient

Je n'ai pas repris ces points sur la foi de la revue précédente, je les ai retracés :

  • Comparaison stricteupdater.rs:530-532 : None => release.version > self.current_version, et aucun version_comparator défini côté app (grep vide sur src/ et src-tauri/src/). Le prérequis « partir de la version précédente » et le raisonnement « republier vN-1 n'est pas un rollback » reposent tous deux sur cette ligne, et tiennent.
  • Entitlement avant check()useUpdater.ts:79-86 : check_entitlement("auto-update") puis NOT_ENTITLED et return avant check(). auto-update = Base|Premium (entitlements.rs:22).
  • Cascade pkexeczenity/kdialogsudoupdater.rs:1107 (pkexec), get_password_graphically (zenity puis kdialog), install_with_sudo:1173. Littéralement cet ordre.
  • Windows exit(0)updater.rs:865. readyToInstall/installing ne s'affichent effectivement jamais sur cette cible ; la section Windows est juste de bout en bout. La remarque contentLength l'est aussi : sans lui, progressPercent est null → barre figée à 0 et pas de pourcentage (UpdateCard.tsx:160-166), donc visible à l'œil.
  • tar inatteignable — les deux seuls tar::Archive sont updater.rs:1011 (dans install_appimage, fn 975, bornée par install_deb à 1048) et :1228 (dans #[cfg(target_os = "macos")] impl Update, ouvert à :1204). install_deb fait try_tmp_locations(bytes, "dpkg", "-i"), sans archive. La correction de la prémisse de #315 est juste et c'est la partie la plus utile du document.
  • rpm cassé, pas non vérifiélatest.json ne porte linux-x86_64 que depuis le .deb (release.yml:104-122, plage citée exacte), l'installeur vient du bundle installé (updater.rs:968-970), et install_rpm rejette sur infer::archive::is_rpm (:1058-1063). Sortir ça en #320 (ouverte, type:bug) plutôt qu'en ligne de checklist est le bon arbitrage.
  • CI — aucun workflow déclenché, attendu : check-rust.yml filtre src-tauri/**/.cargo/**, check-frontend.yml ignore docs/** et .claude/**. L'absence de checks n'est pas un échec.
  • Fermeture d'issueResolves #315 est bien dans le message de commit de 10d8a79, pas seulement dans le corps de la PR. L'issue se fermera.
  • Lien relatif ../../../docs/qa-update-cycle.md depuis .claude/skills/release/SKILL.md → résout à la racine du repo. Modèle docs/qa-refonte-seed-categories-ipc.md bien existant, même forme (bloc Prérequis + cases). Frontmatter updated: 2026-07-27 cohérent avec la date du commit. Pas d'entrée CHANGELOG : correct, changement de processus.

Le document vaut mieux que la moyenne des checklists QA — cadrer chaque prérequis par son mode d'échec « la case se coche sans que rien ne soit vérifié » est le bon angle, et l'auto-correction de la prémisse tar de #315 est honnête et vérifiable. C'est précisément parce que sa valeur est sa précision qu'une séquence d'états inversée sur la seule cible où ces états sont observables doit être corrigée avant merge.

## REQUEST_CHANGES Passe de re-vérification. **Le head n'a pas bougé depuis la revue du 2026-08-14** (`10d8a79`, commit du 2026-07-27 ; la revue a été postée à 19:57Z et `updated_at` de la PR s'arrête là). Le blocage n'a donc pas été traité — mais je ne l'ai pas relayé sur parole, je l'ai retracé de zéro depuis les sources. **Il est confirmé, et la ligne décisive n'avait pas été citée.** Je corrige aussi un point de la revue précédente qui, appliqué tel quel, produirait une correction fausse. --- ### Bloquant — toujours ouvert **1. `docs/qa-update-cycle.md` §2 « Linux (.deb) » — la séquence d'états ne correspond pas au code** Confirmé, et voici la ligne qui tranche — `tauri-plugin-updater-2.10.0/src/updater.rs:723-729` : ```rust pub async fn download_and_install<C: FnMut(usize, Option<u64>), D: FnOnce()>( &self, on_chunk: C, on_download_finish: D, ) -> Result<()> { let bytes = self.download(on_chunk, on_download_finish).await?; self.install(bytes) // <- même appel, après le Finished } ``` `on_download_finish()` est appelé à `updater.rs:710`, **à la fin du téléchargement** ; `install(bytes)` s'exécute ensuite, dans le même `await`. La chaîne complète : - `@tauri-apps/plugin-updater/dist-js/index.js` — `downloadAndInstall` = **un seul** `invoke('plugin:updater|download_and_install')`, jamais `install` séparément. - `commands.rs:180-194` — `Finished` est émis par la closure `on_download_finish`, donc avant l'installation. - `useUpdater.ts:119-121` — `Finished` est un **no-op** (`// handled below`). L'UI ne change pas d'état. - `useUpdater.ts:123` — `READY_TO_INSTALL` est dispatché **après** que l'`await` a résolu, c'est-à-dire **après** que `dpkg -i` a terminé. Séquence réelle sous Linux : 1. `downloading` 2. téléchargement fini → **l'UI affiche toujours « Téléchargement en cours... »** 3. **l'invite pkexec s'ouvre par-dessus cet écran-là** 4. installation terminée → `readyToInstall` + bouton « Installer et redémarrer » 5. clic → `installing` → `relaunch()` La checklist demande de cocher `readyToInstall` **avant** l'invite. C'est l'inverse, et les conséquences sont exactement celles que la page dit combattre : - **Le prérequis polkit est neutralisé par l'ordre des cases.** Sans agent, l'app se fige — mais en `downloading`, pas en `readyToInstall`. Le testeur qui suit la checklist guette un blocage après `readyToInstall` et voit une barre de téléchargement immobile : il rapporte « le téléchargement bloque » au lieu de « pas d'agent polkit ». C'est la fausse trace, produite par la page censée l'éliminer. - **« Authentifier → état `installing` » inverse cause et effet.** `installing` vient de `installAndRestart` (`useUpdater.ts:129-132`), déclenché **par le clic** sur le contrôle de redémarrage. Le contrôle apparaît d'abord ; `installing` est ce qui le remplace. - **À `readyToInstall`, le `.deb` est déjà installé sur le disque.** `installAndRestart` ne fait que `relaunch()` (`useUpdater.ts:129-132`) — aucune installation. Le libellé du bouton ment sur cette cible : qui s'arrête là croit que rien n'est installé, qui voit la version changer attribue l'installation au clic. À écrire, c'est le vrai piège de lecture de cet écran. La séquence corrigée proposée dans la revue précédente est juste ; elle reste valable telle quelle. C'est un paragraphe. --- ### Correction de la revue précédente — à lire avant de corriger **2. Le décompte des déclencheurs était faux dans les deux sens. Il y a 4 sites, pas 2 et pas 3.** La revue du 14 disait « il y en a trois » et mappait `UpdateCard.tsx:201` sur « la page d'erreur ». C'est inexact : `:201` est le **retry de l'état `error` de la carte elle-même**, et `ErrorPage` est un composant distinct avec son propre déclencheur. Le relevé réel : - `UpdateCard.tsx:60` — bouton « Vérifier les mises à jour » (état `idle`) - `UpdateCard.tsx:89` — icône rafraîchir (état `upToDate`) - `UpdateCard.tsx:201` — réessayer (état `error` **de la carte**) - `ErrorPage.tsx:82` — bouton de la page d'erreur, via son propre `handleCheckUpdate` (`ErrorPage.tsx:18-38`), qui **détecte seulement** : il affiche la version dispo (`:90`) et n'offre aucun chemin de téléchargement. Appliquer « écrire trois » remplacerait donc une imprécision par une autre. Si la phrase doit être corrigée, le fond utile est : **quatre déclencheurs manuels, dont celui de la page d'erreur ne fait que détecter** — et surtout la partie qui porte réellement, **« aucune vérification automatique dans l'app »**, qui est **exacte** (le seul `useEffect`, `UpdateCard.tsx:40-44`, charge les notes de version quand l'état est déjà `available`). --- ### Suggestion nouvelle — non bloquante **3. « Si ça casse » : le `DELETE` et le `PUT` ne visent pas le même préfixe d'API.** La doc écrit « `DELETE` puis `PUT`, avec le `PACKAGE_TOKEN` ». Dans `release.yml:217-219` : ``` # DELETE uses API v1, PUT uses the package upload API DELETE_URL="${GITHUB_SERVER_URL}/api/v1/packages/${OWNER}/generic/simpl-resultat/latest" UPLOAD_URL="${GITHUB_SERVER_URL}/api/packages/${OWNER}/generic/simpl-resultat/latest" ``` `release.yml` porte un commentaire explicite là-dessus — donc le piège est connu et déjà tombé une fois. Quelqu'un qui suit la doc en incident et rejoue les deux verbes sur la même URL prend un 404 sur l'un des deux et brûle du temps au pire moment. La page fait l'effort de dire « lire cette section **avant**, pas pendant » ; le chemin exact des deux appels y a sa place. Le reste de la section est juste et vérifié (la copie registre est bien détruite par le `DELETE` avant chaque envoi, et le `latest.json` précédent est bien récupérable en asset de release). **4.** Rappels des points mineurs déjà signalés et toujours ouverts : le changelog de `SKILL.md` insère `2026-07-27` entre `2026-07-01` et `2026-07-13` (le fichier était strictement croissant), et le titre de PR dit « to step 9 » alors que le changement ajoute une **étape 10**. --- ### Re-vérifié indépendamment — tient Je n'ai pas repris ces points sur la foi de la revue précédente, je les ai retracés : - **Comparaison stricte** — `updater.rs:530-532` : `None => release.version > self.current_version`, et aucun `version_comparator` défini côté app (grep vide sur `src/` et `src-tauri/src/`). Le prérequis « partir de la version précédente » **et** le raisonnement « republier vN-1 n'est pas un rollback » reposent tous deux sur cette ligne, et tiennent. - **Entitlement avant `check()`** — `useUpdater.ts:79-86` : `check_entitlement("auto-update")` puis `NOT_ENTITLED` et `return` **avant** `check()`. `auto-update` = Base|Premium (`entitlements.rs:22`). - **Cascade `pkexec` → `zenity`/`kdialog` → `sudo`** — `updater.rs:1107` (pkexec), `get_password_graphically` (zenity puis kdialog), `install_with_sudo:1173`. Littéralement cet ordre. - **Windows `exit(0)`** — `updater.rs:865`. `readyToInstall`/`installing` ne s'affichent effectivement jamais sur cette cible ; la section Windows est juste de bout en bout. La remarque `contentLength` l'est aussi : sans lui, `progressPercent` est null → barre figée à 0 et pas de pourcentage (`UpdateCard.tsx:160-166`), donc visible à l'œil. - **`tar` inatteignable** — les deux seuls `tar::Archive` sont `updater.rs:1011` (dans `install_appimage`, fn 975, bornée par `install_deb` à 1048) et `:1228` (dans `#[cfg(target_os = "macos")] impl Update`, ouvert à `:1204`). `install_deb` fait `try_tmp_locations(bytes, "dpkg", "-i")`, sans archive. **La correction de la prémisse de #315 est juste** et c'est la partie la plus utile du document. - **rpm cassé, pas non vérifié** — `latest.json` ne porte `linux-x86_64` que depuis le `.deb` (`release.yml:104-122`, plage citée exacte), l'installeur vient du bundle **installé** (`updater.rs:968-970`), et `install_rpm` rejette sur `infer::archive::is_rpm` (`:1058-1063`). Sortir ça en #320 (ouverte, `type:bug`) plutôt qu'en ligne de checklist est le bon arbitrage. - **CI** — aucun workflow déclenché, attendu : `check-rust.yml` filtre `src-tauri/**`/`.cargo/**`, `check-frontend.yml` ignore `docs/**` et `.claude/**`. L'absence de checks n'est pas un échec. - **Fermeture d'issue** — `Resolves #315` est bien dans le **message de commit** de `10d8a79`, pas seulement dans le corps de la PR. L'issue se fermera. - **Lien relatif** `../../../docs/qa-update-cycle.md` depuis `.claude/skills/release/SKILL.md` → résout à la racine du repo. Modèle `docs/qa-refonte-seed-categories-ipc.md` bien existant, même forme (bloc Prérequis + cases). Frontmatter `updated: 2026-07-27` cohérent avec la date du commit. Pas d'entrée CHANGELOG : correct, changement de processus. Le document vaut mieux que la moyenne des checklists QA — cadrer chaque prérequis par son mode d'échec « la case se coche sans que rien ne soit vérifié » est le bon angle, et l'auto-correction de la prémisse `tar` de #315 est honnête et vérifiable. C'est précisément parce que sa valeur **est** sa précision qu'une séquence d'états inversée sur la seule cible où ces états sont observables doit être corrigée avant merge.
maximus force-pushed issue-315-qa-update-cycle from 10d8a79fd8 to 97d376b83c 2026-08-15 15:52:51 +00:00 Compare
maximus changed title from docs(release): add a real update-cycle QA checklist to step 9 to docs(release): add a real update-cycle QA checklist as step 10 2026-08-15 15:53:50 +00:00
Author
Owner

Blocage corrigé — 97d376b

Les quatre points de la revue sont traités, chacun re-vérifié sur la source avant d'écrire.

Bloquant — séquence d'états Linux. §2 est réécrite dans l'ordre réel : l'invite d'authentification arrive pendant que la carte affiche encore « Téléchargement en cours… », puis readyToInstall, puis le clic qui ne fait que relancer. La case qui demandait de cocher readyToInstall avant l'invite disparaît. Le prérequis polkit du haut de page dit maintenant l'app se fige sans agent (écran de téléchargement, pas readyToInstall) — c'était le maillon qui produisait le mauvais rapport de bug. Ajouté aussi, parce que c'est le vrai piège de lecture de cet écran : à readyToInstall le .deb est déjà sur le disque, installAndRestart ne fait que relaunch().

Vérifié moi-même plutôt que repris sur parole : updater.rs:723-729 (download(...).await? puis install(bytes), même appel), on_download_finish() à :710, useUpdater.ts:119-121 (Finished// handled below, aucun dispatch), :123 (READY_TO_INSTALL après résolution de l'await), :129-132 (INSTALLING puis relaunch(), rien d'autre).

Déclencheurs — quatre, pas deux ni trois. La phrase §1 liste maintenant les quatre sites manuels et précise que celui de la page d'erreur détecte seulement. Confirmé : UpdateCard.tsx:60/89/201 + ErrorPage.tsx:82, dont le handleCheckUpdate (:18-38) s'arrête à setUpdateStatus("available") sans aucun chemin de téléchargement. La partie porteuse — « aucune vérification automatique dans l'app » — était exacte et reste telle quelle.

Préfixes d'API. « Si ça casse » énonce les deux URL en clair, DELETE sur /api/v1/packages/ et PUT sur /api/packages/. Confirmé sur release.yml:217-219, commentaire inclus.

Ordre du changelog SKILL.md. L'entrée 2026-07-27 repasse après 2026-07-13.

Titre de PR corrigé en « as step 10 ».


Branche rebasée sur main (elle avait 15 commits de retard) et empilée sur issue-312-313-drop-quickxml-suppressions pour un merge ff-only de la pile. Tip validé localement : cargo check OK, cargo test 111 passed, 0 failed.

## Blocage corrigé — `97d376b` Les quatre points de la revue sont traités, chacun re-vérifié sur la source avant d'écrire. **Bloquant — séquence d'états Linux.** §2 est réécrite dans l'ordre réel : l'invite d'authentification arrive **pendant** que la carte affiche encore « Téléchargement en cours… », puis `readyToInstall`, puis le clic qui ne fait que relancer. La case qui demandait de cocher `readyToInstall` avant l'invite disparaît. Le prérequis polkit du haut de page dit maintenant **où** l'app se fige sans agent (écran de téléchargement, pas `readyToInstall`) — c'était le maillon qui produisait le mauvais rapport de bug. Ajouté aussi, parce que c'est le vrai piège de lecture de cet écran : à `readyToInstall` le `.deb` est **déjà sur le disque**, `installAndRestart` ne fait que `relaunch()`. Vérifié moi-même plutôt que repris sur parole : `updater.rs:723-729` (`download(...).await?` puis `install(bytes)`, même appel), `on_download_finish()` à `:710`, `useUpdater.ts:119-121` (`Finished` → `// handled below`, aucun dispatch), `:123` (`READY_TO_INSTALL` après résolution de l'`await`), `:129-132` (`INSTALLING` puis `relaunch()`, rien d'autre). **Déclencheurs — quatre, pas deux ni trois.** La phrase §1 liste maintenant les quatre sites manuels et précise que celui de la page d'erreur **détecte seulement**. Confirmé : `UpdateCard.tsx:60/89/201` + `ErrorPage.tsx:82`, dont le `handleCheckUpdate` (`:18-38`) s'arrête à `setUpdateStatus("available")` sans aucun chemin de téléchargement. La partie porteuse — « aucune vérification automatique dans l'app » — était exacte et reste telle quelle. **Préfixes d'API.** « Si ça casse » énonce les deux URL en clair, `DELETE` sur `/api/v1/packages/` et `PUT` sur `/api/packages/`. Confirmé sur `release.yml:217-219`, commentaire inclus. **Ordre du changelog `SKILL.md`.** L'entrée `2026-07-27` repasse après `2026-07-13`. **Titre de PR** corrigé en « as step 10 ». --- Branche rebasée sur `main` (elle avait 15 commits de retard) et empilée sur `issue-312-313-drop-quickxml-suppressions` pour un merge ff-only de la pile. Tip validé localement : `cargo check` OK, `cargo test` **111 passed, 0 failed**.
Author
Owner

Mergée dans main en ff-only : f6418f7 + 97d376b (le correctif de revue), empilée sur #321. Forgejo ne détecte pas un merge local comme merged — d'où cette fermeture manuelle.

Le blocage de la revue est corrigé avant merge : la séquence d'états Linux suit maintenant le code (invite d'authentification pendant « Téléchargement en cours… », puis readyToInstall, puis le clic qui ne fait que relancer), le prérequis polkit dit où l'app se fige, les quatre déclencheurs manuels sont listés avec la page d'erreur marquée détection-seule, les deux préfixes d'API du playbook sont explicités, et le changelog du skill repasse en ordre de date. Détail dans le commentaire précédent.

CI run 371 verte (la branche héritait du commit deps, donc check-rust s'est déclenchée). #315 fermée automatiquement par le Resolves du message de commit.

Mergée dans `main` en **ff-only** : `f6418f7` + `97d376b` (le correctif de revue), empilée sur #321. Forgejo ne détecte pas un merge local comme *merged* — d'où cette fermeture manuelle. Le blocage de la revue est corrigé avant merge : la séquence d'états Linux suit maintenant le code (invite d'authentification **pendant** « Téléchargement en cours… », puis `readyToInstall`, puis le clic qui ne fait que relancer), le prérequis polkit dit où l'app se fige, les quatre déclencheurs manuels sont listés avec la page d'erreur marquée détection-seule, les deux préfixes d'API du playbook sont explicités, et le changelog du skill repasse en ordre de date. Détail dans le commentaire précédent. CI **run 371 verte** (la branche héritait du commit deps, donc `check-rust` s'est déclenchée). #315 fermée automatiquement par le `Resolves` du message de commit.
maximus closed this pull request 2026-08-15 16:13:39 +00:00
All checks were successful
PR Check — Rust / rust (pull_request) Successful in 9m14s

Pull request closed

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#322
No description provided.