fix(desktop): l'app démarre après une mise à jour, et parle quand elle ne peut pas

Installer une nouvelle version remplace les fichiers sur disque mais ne touche
pas le process en cours : l'ancienne instance gardait le port 7317, la version
fraîchement installée mourait sur EADDRINUSE avant son handshake, et le shell se
contentait d'un console.error suivi d'un app.quit(). Depuis le lanceur, cliquer
l'icône ne produisait donc rien du tout.

- Tout échec de démarrage ouvre un dialogue Retry / Show log / Quit
  (start-failure.ts, texte pur et testé) et la sortie du daemon est conservée
  dans <userData>/logs/daemon.log. Une mort du daemon APRÈS le handshake propose
  de le relancer, au lieu de laisser une fenêtre morte à l'écran.
- Le port est diagnostiqué avant le spawn (port-guard.ts, empreinte
  {pid, ownerPid, port}) : un daemon orphelin, dont l'Electron est mort, est
  repris (SIGTERM puis SIGKILL, en attendant un bind réellement possible) ;
  une instance vivante ou un tiers (service, npx) est annoncé avec l'action qui
  débloque, et jamais tué. La reprise exige deux preuves, l'empreinte orpheline
  ET l'identité du process (ps -ww), car un pidfile périmé peut désigner un pid
  recyclé entre-temps par un programme quelconque.
- Une mise à jour installée à chaud est signalée avec « Restart now »
  (upgrade-watch.ts), qui arrête le daemon avant app.relaunch() ; sans quoi le
  lock d'instance unique renvoyait silencieusement sur la fenêtre de l'ancienne
  version, et on croyait avoir migré.
- ARBORETUM_DESKTOP_PORT pour cohabiter avec un Arboretum qui occupe 7317 en
  permanence (service installé, ou daemon lancé en terminal).

24 tests dans packages/desktop/test, et quatre scénarios rejoués en dev sous
xvfb-run avec profil isolé : port tenu par un tiers, orphelin repris puis SPA
servie, instance vivante laissée intacte, pid recyclé épargné.
This commit is contained in:
2026-08-05 09:10:43 +02:00
parent c6deded0c6
commit 9390b62249
12 changed files with 882 additions and 33 deletions
+1
View File
@@ -333,6 +333,7 @@ Environment variables:
| `ARBORETUM_EMIT_TOKEN_FD` | daemon | Write the access token to this file descriptor at start-up. Used by the desktop app to sign itself in; not meant for manual use. |
| `XDG_DATA_HOME` | daemon | Root of the data directory (see above). |
| `ARBORETUM_SHELL` | daemon (Windows) | Shell used to run project commands. Default `powershell.exe`. |
| `ARBORETUM_DESKTOP_PORT` | desktop app | Port the desktop app starts its own daemon on. Default `7317`. Set it when another Arboretum permanently holds that port (a service installed with `arboretum install`, or one you run in a terminal). |
Settings beyond CLI flags (the directories Arboretum scans for repos and how often, the `claude` binary path and home, and the session retention / purge windows) live in **Settings** in the UI. They are broadcast over the WebSocket, so every connected browser reflects a change in real time, no reload needed.