8.7 KiB
Focus pendant le staging et catalogue installé — 27 octobre 2026
Incident réel conservé
Après installation vérifiée de l’extension Firefox signée 1.1.2, l’admission a
retrouvé l’identité exacte de la fenêtre Firefox enregistrée. Sept fenêtres
attendues étaient présentes. L’unique essai réel autorisé a ensuite échoué avec
RECOVERY_FOCUS_MISMATCH, transaction 475fac98b5234db0bddaded9cfe4198f.
Deux déplacements avaient été exécutés, aucune ancre créée et aucun slot reconstruit. Au déplacement de ChatGPT 16, le moteur attendait le conteneur interne 32 ; Sway a focalisé le terminal 58. Le journal conserve cette divergence.
Les deux clients déplacés par cet essai, Kitty 37 et ChatGPT 16, ont été ramenés
séparément au workspace 1 après vérification de leurs identités et de leurs
origines. Le stage est vide. Cette remise en place n’est ni une restauration
réussie du checkpoint ni un rollback structurel complet. Le journal reste
required et son reçu RECOVERY_REQUIRED.
Le checkpoint de 08:33:18 est inchangé :
9a36bb310f48d989a8763092ae220a974a00786da6fba2c86dc25e7cfed1cd89.
Il décrit ChatGPT et deux Kitty sur 1, Firefox sur 2, WhatsApp sur 9, LiMusic
sur 10 et un troisième Kitty dans le scratchpad caché.
Cause vérifiée sur SwayFX réel
Les listes de focus du JSON IPC donnent l’ordre des enfants directs. La recherche interne de focus inactif examine une pile globale de descendants de toute profondeur. Cette information globale ne peut pas toujours être reconstruite depuis le seul arbre public.
Deux historiques synthétiques, exécutés avec le binaire installé SwayFX 0.6, ont produit exactement le même arbre public, listes de focus comprises. Le déplacement de la même feuille focalisée a néanmoins choisi un conteneur interne dans un historique et une feuille dans l’autre. Le focus sur un conteneur interne est donc légitime ; le remplacer systématiquement par une feuille casserait l’autre cas.
Cette preuve établit le défaut de prédiction de cette transition. Elle ne prétend pas reconstituer l’historique caché précis du bureau réel.
Sources locales vérifiées au tag 0.6 :
sway/ipc-json.c, sway/input/seat.c, sway/commands/move.c et
sway/tree/workspace.c, dans
/home/fy59/Documents/Development/swayfx-mosaic.
Correction
Le moteur déplace d’abord les feuilles hors du sous-arbre focalisé, puis celles de ce sous-arbre, en conservant l’ordre relatif de chaque groupe. Si la branche focalisée doit disparaître, toutes les feuilles de son workspace source doivent pouvoir être stagées. Un client étranger ou un scratchpad montré qui resterait en place entraîne un refus préalable.
Cette admission s’applique aussi aux workspaces sources absents du checkpoint.
Elle passe avant tout journal transactionnel et est répétée après Guard. Le
contrôle du lot déjà admis garde la priorité : une nouvelle fenêtre apparue
après capture reste APPLICATION_MEMBERSHIP_CHANGED.
Le nouveau refus RESTORE_FOCUS_STAGING_UNPROVEN est différé uniquement en
phase 0. Après ouverture de la transaction, il reste une erreur transactionnelle.
L’interface fournit une explication et un nouvel essai manuel. Aucun retry
automatique ni déplacement forcé du focus n’a été ajouté.
Le prédicteur et tous les contrôles stricts de recovery.py restent inchangés.
Les focus sur workspace, client étranger ou conteneur interne conservant un
descendant sont préservés.
Catalogue des applications
Le catalogue découvre maintenant les lanceurs installés avec GIO. L’inventaire de cette machine contient 103 entrées, dont 95 cataloguées : 6 politiques explicites et 89 entrées découvertes. Les métadonnées NoDisplay et OnlyShowIn ne sont pas assimilées à une absence d’application.
La nouvelle stratégie V2 ouvre au plus une instance absente, puis attend toutes les fenêtres enregistrées avant le moindre déplacement. Elle ne promet pas de rouvrir les documents ni les commandes d’un terminal. Les identités ambiguës restent refusées. Firefox conserve son provider exact.
Voir session-v2-installed-app-catalog-v1.md pour la politique complète,
les huit exclusions motivées et les limites de l’inventaire.
Validation
- Suite Python intégrée finale : 150 tests réussis en 16,473 s.
- 10 nouveaux tests de staging, 16 de catalogue et 3 pour Proton Pass.
- Aucun résultat attendu des tests existants n’a été assoupli. Le contrôle intégré a permis de corriger deux régressions : racine synthétique sans ID et priorité du refus d’un changement de lot après capture.
- Ancien moteur sur la reproduction imbriquée : échec attendu après deux
déplacements, avec
RECOVERY_FOCUS_MISMATCH. - Nouveau moteur sur la même reproduction : succès, quatre slots et quatre swaps vérifiés, arbre/focus conformes, journal complete, aucune ancre ni fenêtre restant au stage, client étranger conservé.
- Variante avec focus initial interne : succès.
- Source avec client étranger restant : refus avant toute commande et sans journal/tentative.
- Cas existants preserve-empty-workspace et preserve-foreign : succès.
- Injection focus-helper-late : le refus strict après swaps reste présent.
- Deux historiques avec arbre IPC identique : focus natifs distincts démontrés.
Ces essais utilisent des sockets Sway privés et des clients synthétiques. Ils ne constituent pas la validation d’une nouvelle restauration du bureau réel.
Reprise préparée avant autorisation
Les preuves privées se trouvent dans :
/home/fy59/.local/state/labfy-sway/session-v2-diagnostics/20261027-102041-signed112-restore.
La dernière observation contient cinq survivants : LiMusic 7, ChatGPT 16, Kitty 37, Proton Pass 46 et WhatsApp 62. Firefox 50 et Kitty 58/60 sont observés absents ; leur fermeture n’est attribuée à aucune action particulière.
Le plan nominatif retirement-current-plan.md concerne uniquement la
transaction ci-dessus. Il propose d’archiver les trois fichiers actifs exacts,
avec copies persistantes et contrôles d’identités, de session, d’inactivité et
d’empreintes. Le reçu distinct doit porter retired-after-manual-return,
jamais une réussite automatique fictive.
Le helper est en dry-run par défaut. Sa fixture privée vérifie les renommages
et leur retour en cas d’échec ; son dry-run réel a réussi sans modifier les
fichiers protégés. Le retrait réel et un nouvel essai exigent l’autorisation
distincte prévue par session-v2-focus-recovery-fix-v1.md.
Une future restauration devra retrouver la fenêtre Firefox avec son UUID enregistré, préparer les fenêtres manquantes, puis prouver les postconditions. Ne pas remplacer le checkpoint par la disposition partielle actuelle.
Validation réelle après autorisation — 12:10:59
L’utilisateur a autorisé le retrait nominatif de la tentative échouée et un
unique nouvel essai. Le helper a archivé les trois fichiers exacts sous
/run/user/1000/labfy-sway/retired-475fac98b5234db0bddaded9cfe4198f, en conservant
leurs copies persistantes et le statut distinct retired-after-manual-return.
Les deux terminaux manquants ont été ouverts. Le lancement normal de Firefox a réouvert sa dernière fenêtre fermée, dont les métadonnées portaient l’UUID attendu ; le provider a confirmé cette même identité sur le conteneur 79. Aucune modification d’UUID ni réécriture de la session Firefox n’a été effectuée.
L’unique nouvel essai a réussi, transaction
335bf44840674810b4761ade767f31db : 7/7 slots, 6/6 ancres créées, échangées et
nettoyées, helpers suspendus/repris 1/1, arbre et focus vérifiés, recovery
complete sans issue. Un contrôle indépendant après l’essai a confirmé :
- workspace 1 : ChatGPT à gauche, deux Kitty empilés à droite ;
- workspace 2 : Firefox, avec l’identité exacte attendue ;
- workspace 9 : WhatsApp ; workspace 10 : LiMusic ;
- troisième Kitty caché, géométrie conforme au checkpoint ;
- Proton Pass étranger inchangé ; aucun stage ni aucune ancre restante.
Une capture réelle supplémentaire a réussi avec huit fenêtres et six
applications, dont Proton Pass. Elle est conservée uniquement dans le dossier
de diagnostic et n’a pas remplacé le checkpoint automatique d’origine.
L’acquittement restored a été enregistré après ces preuves ; startup-status
indique aucun essai en cours, différé ou interrompu.
Preuves privées :
/home/fy59/.local/state/labfy-sway/session-v2-diagnostics/20261027-120604-focus-catalog-restore.
Le checkpoint d’origine conserve son SHA-256 9a36bb310f48d989a8763092ae220a974a00786da6fba2c86dc25e7cfed1cd89.
Cette validation porte sur une restauration réelle dans la session active ;
aucune nouvelle déconnexion/reconnexion n’a été déclenchée pour ce contrôle.