Trois docs demandaient d'ouvrir ios/App/App.xcworkspace. Ce fichier n'existe pas : Capacitor 8 passe par Swift Package Manager (ios/App/CapApp-SPM), il n'y a plus ni Podfile ni workspace CocoaPods. La session s'arretait sur « The file does not exist » des l'ouverture de Xcode. C'est App.xcodeproj qu'il faut ouvrir. Corrige dans SESSION-XCODE.md, widgets-runbook-mac.md et routine-watch-runbook-mac.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6.2 KiB
Runbook Mac — Routine quotidienne sur l'Apple Watch
Écrit côté dev (Linux) le 2026-08-03. Rien n'est compilé. Ce document dit quoi faire sur le Mac pour activer la fonctionnalité, et comment la tester.
Ce que ça fait
La routine anti-douleurs (6 blocs) apparaît sur la montre, cochable au doigt.
Une coche faite sur la Watch remonte à l'iPhone, qui la POSTe au serveur — donc
la page /routine et le widget de la home reflètent immédiatement l'état, et
inversement.
Architecture (à connaître avant de débugger)
page /routine (web) Apple Watch (RoutineView)
│ coche │ coche
▼ ▼
POST /api/routine/check ConnectivityManager.sendRoutine
│ │ sendMessage / transferUserInfo
▼ ▼
data/routine_log.json ◄────────── CoachLiveBridge (délégué WCSession)
▲ POST /api/routine/day │ routeIfNotLiveSample()
│ ▼
└─────────────────────── CoachRoutineBridge (NotificationCenter)
│ notifyListeners
▼
routine.js re-render
Trois décisions structurantes, à ne pas défaire sans raison :
- L'état est serveur, plus en localStorage. La Watch n'a aucun accès au localStorage du WKWebView : il fallait un arbitre commun aux trois surfaces.
- On transmet l'état COMPLET du jour, jamais un delta. Si un message
WatchConnectivity se perd, le suivant recale tout au lieu de laisser les deux
côtés diverger. C'est aussi pour ça que
updateApplicationContextconvient : le système n'en garde que le dernier, ce qui est la sémantique voulue. CoachRoutineBridgen'est PASWCSession.delegate.CoachLiveBridgel'est déjà et le délégué est unique.CoachLiveBridge.routeIfNotLiveSample()aiguille les messagesroutineDoneversNotificationCenter— c'est le seul endroit où j'ai touché au flux live workout (validé E2E sur device le 31/05), et il retournetruesans rien émettre, doncLiveStoren'est pas pollué.
Les blocs eux-mêmes voyagent avec l'état : rien n'est codé en dur côté watchOS. Modifier la routine côté web ne demande donc aucun rebuild.
Étapes Mac
1. Récupérer le code
# Xcode FERMÉ (règle COWORK)
cd ~/coach-ios && git pull
npm install && npx cap sync ios
open ios/App/App.xcodeproj
2. Rien à ajouter dans Xcode
Les trois nouveaux fichiers sont déjà référencés dans project.pbxproj,
dans la bonne target :
| Fichier | Target |
|---|---|
App/CoachRoutineBridge.swift |
App |
CoachWatch/RoutineStore.swift |
CoachWatch |
CoachWatch/RoutineView.swift |
CoachWatch |
Vérification rapide si un doute :
grep -c "RoutineView.swift" ios/App/App.xcodeproj/project.pbxproj # doit valoir 4
(4 = PBXBuildFile + PBXFileReference + children du groupe + Sources phase.)
Backup du pbxproj avant modification : project.pbxproj.bak-routine.
3. Build
Clean Build Folder (Cmd+Shift+K) → Run sur l'iPhone, avec la Watch appairée.
⚠️ CoachAuth.swift doit exister (gitignored) : le plugin s'en sert pour
authentifier son POST vers /api/routine/day. Sans lui, ça ne compile pas.
4. Tester le cycle complet
- Ouvrir l'app iPhone sur
/routine— ça pousse les blocs vers la Watch. - Sur la Watch : app Coach → Routine du jour → la liste des 6 blocs doit apparaître avec la progression.
- Cocher un bloc sur la Watch → retour à l'iPhone, la page
/routinedoit se mettre à jour sans rechargement (eventroutineUpdated). - Cocher un bloc sur l'iPhone → rouvrir la vue Watch, l'état doit suivre.
- Vérifier côté serveur :
ssh ubuntu@83.228.246.229 'cat /home/ubuntu/coach_sportif/data/routine_log.json'
5. Si la Watch affiche « Ouvre l'app Coach sur l'iPhone »
C'est l'état vide normal au premier lancement : la montre n'a pas encore reçu de
blocs. Si ça persiste après avoir ouvert /routine sur l'iPhone :
- console Safari (Développement → iPhone → coach.hypnotruck.ch) :
→
await Capacitor.Plugins.CoachRoutineBridge.getStatus()pairedetwatchAppInstalleddoivent êtretrue. - Xcode console, filtre
subsystem:ch.hypnotruck.coach category:routine. updateApplicationContextéchoue silencieusement si la session n'est pas activée : vérifier queCoachLiveBridge.load()a bien tourné (c'est lui qui active la session).
6. Si une coche Watch ne remonte pas
- Hors de portée de l'iPhone, c'est normal et attendu :
transferUserInfogarantit la livraison différée, la coche partira au prochain rapprochement. La vue affiche un bouton « Renvoyer vers l'iPhone » si l'envoi a échoué net. - Sinon : vérifier le log
POST /api/routine/daycôté Xcode (le plugin logue le code HTTP en cas d'échec — un 401 signifie unCoachAuth.kCoachWebTokenpérimé).
Séance guidée au poignet (2026-08-03)
CoachWatch/RoutineGuidedView.swift — bouton Démarrer sur chaque bloc :
un exercice à la fois, décompte en anneau, passage automatique, haptique à
chaque transition, pause / précédent / suivant.
Chaque exercice écoulé est coché via RoutineStore.toggle, donc renvoyé à
l'iPhone puis au serveur : à la fin, le bloc est déjà à jour sur les trois
surfaces sans un geste de plus.
Le fichier est déjà référencé dans le pbxproj (target CoachWatch), aucun
« Add Files » à faire. Backup : project.pbxproj.bak-guided.
À tester au build : démarrer le bloc 1 sur la montre, laisser tourner deux
exercices, vérifier que la page /routine de l'iPhone se coche toute seule.
Reste à faire (hors périmètre de ce chantier)
- Complication watchOS « Routine » : la target
CoachWatchWidgetsn'existe toujours pas (cf.docs/widgets-runbook-mac.md). - Notification de rappel sur la montre si la routine n'est pas faite à 20 h.