Files
coach-ios/docs/routine-watch-runbook-mac.md
Sylvain Bettinelli f032ee2126 feat(watch): séance guidée au poignet
Pendant natif du lecteur web. Bouton Démarrer par bloc : un exercice à la fois,
décompte en anneau, passage auto, haptique à chaque transition, pause et
navigation. Pendant une routine au sol, la montre est bien plus pratique que
d'aller chercher le téléphone — c'est tout l'intérêt de la version watchOS.

Chaque exercice écoulé est coché via RoutineStore.toggle, donc renvoyé à
l'iPhone puis au serveur : à la fin le bloc est à jour sur les trois surfaces.

La durée par exercice est désormais transmise dans le snapshot (duration_sec,
optionnel pour rester compatible avec les snapshots déjà persistés) : la vue
guidée utilise la vraie durée au lieu de répartir celle du bloc.

RoutineGuidedView.swift est déjà référencé dans le pbxproj (target CoachWatch),
aucun Add Files à faire. Backup : project.pbxproj.bak-guided

NON COMPILÉ — à inclure au prochain build Xcode.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:32:29 +00:00

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 :

  1. 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.
  2. 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 updateApplicationContext convient : le système n'en garde que le dernier, ce qui est la sémantique voulue.
  3. CoachRoutineBridge n'est PAS WCSession.delegate. CoachLiveBridge l'est déjà et le délégué est unique. CoachLiveBridge.routeIfNotLiveSample() aiguille les messages routineDone vers NotificationCenter — c'est le seul endroit où j'ai touché au flux live workout (validé E2E sur device le 31/05), et il retourne true sans rien émettre, donc LiveStore n'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.xcworkspace

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

  1. Ouvrir l'app iPhone sur /routine — ça pousse les blocs vers la Watch.
  2. Sur la Watch : app Coach → Routine du jour → la liste des 6 blocs doit apparaître avec la progression.
  3. Cocher un bloc sur la Watch → retour à l'iPhone, la page /routine doit se mettre à jour sans rechargement (event routineUpdated).
  4. Cocher un bloc sur l'iPhone → rouvrir la vue Watch, l'état doit suivre.
  5. 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()
    
    paired et watchAppInstalled doivent être true.
  • Xcode console, filtre subsystem:ch.hypnotruck.coach category:routine.
  • updateApplicationContext échoue silencieusement si la session n'est pas activée : vérifier que CoachLiveBridge.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 : transferUserInfo garantit 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/day côté Xcode (le plugin logue le code HTTP en cas d'échec — un 401 signifie un CoachAuth.kCoachWebToken pé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 CoachWatchWidgets n'existe toujours pas (cf. docs/widgets-runbook-mac.md).
  • Notification de rappel sur la montre si la routine n'est pas faite à 20 h.