Commit Graph

22 Commits

Author SHA1 Message Date
Sylvain Bettinelli
089b6fbde6 Ce que la session Xcode du 11 aout a rencontre, et que le guide ne disait pas
L'etape 5 est faite. Cinq ecarts entre le guide et Xcode reel, tous corriges
dans le doc pour que la prochaine session ne les repaye pas :

Le template ne s'appelle plus CoachWatchWidgets.swift mais
CoachWatchWidgetsBundle.swift. Comme il porte un @main et que
CoachWatchComplications.swift en a deja un, l'oublier fait echouer la
compilation sur deux @main dans la meme target.

Les nouvelles targets sont creees en dossier synchronise : tout fichier du
dossier en est membre automatiquement, sans etre liste dans project.pbxproj.
CoachWatchComplications.swift etait donc deja inclus - d'ou son absence du
dialogue Add Files, qui ressemble a une panne et n'en est pas une. L'etape 6
du guide est desormais sans objet, et un grep qui renvoie 0 sur ce fichier
n'est plus un signal d'alarme.

Xcode cree la target en build 1 quand le projet est en 22, ce qui bloque a
l'installation. Les cases du template ont change (Include Control et Include
Configuration App Intent au lieu de Include Live Activity) : les deux se
decochent, nos complications sont des StaticConfiguration.

Et la Watch n'a pas besoin d'etre visible comme destination dans Xcode : la
phase Embed Watch Content embarque l'app Watch dans l'app iPhone, builder le
schema App suffit. Chercher la montre dans la liste des devices est une impasse
qui coute un mode developpeur et un redemarrage pour rien.

Ajout d'un script de verification de l'assemblage : il dit a quelle target
appartient chaque phase Embed. Embed Foundation Extensions doit pointer sur
CoachWatch - rattachee a App, l'extension resterait sur l'iPhone et aucune
complication n'apparaitrait.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 14:34:28 +00:00
Sylvain Bettinelli
21d39f2e98 Piloter la séance depuis la Live Activity (Pause / Terminer)
Comme l'app Exercice : deux boutons sur la bannière de l'écran verrouillé et
dans l'île dépliée. iOS n'expose aucun geste de balayage pour révéler des
actions — depuis iOS 17, ce sont des boutons intégrés (App Intents), et c'est
le seul mécanisme public.

- Intents `CoachTogglePauseIntent` / `CoachEndWorkoutIntent`, conformes à
  LiveActivityIntent (sans quoi `perform()` n'est jamais appelé).
- Ils vivent dans CoachLiveActivityAttributes.swift, seul fichier déjà membre
  des deux targets : un fichier neuf imposerait une manip Target Membership
  dans Xcode, source d'erreurs répétées ici.
- Commandes relayées à la montre par WCSession, avec repli transferUserInfo :
  isReachable retombe à false quand la séance tourne en arrière-plan profond,
  la commande est alors différée au réveil de l'app montre.
- L'état de pause remonte depuis HKWorkoutSession (seule source fiable : la
  montre peut mettre en pause d'elle-même) et bascule le libellé du bouton.
- Le watchdog de LiveStore est neutralisé pendant la pause : sans ça, l'absence
  de samples aurait affiché « connexion perdue » puis terminé l'activité.
- L'app watchOS gagne le bouton Pause qui lui manquait, aligné sur le même état.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 13:25:14 +00:00
Sylvain Bettinelli
ce048ee634 Runbook Mac pour builder le correctif Live Activity
Build simple (aucun fichier neuf, aucune capability), mais avec un piège :
la montre doit être rebuildée elle aussi, sinon rien ne change — le message
de fin de séance part de CoachWatch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 12:54:40 +00:00
Sylvain Bettinelli
051c8e8ff4 Le guide faisait ouvrir un workspace qui n'existe pas
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>
2026-08-11 11:59:29 +00:00
Sylvain Bettinelli
ddfd95cbd7 Le guide Xcode annoncait un fichier a ajouter, il y en a quatre
SESSION-XCODE.md disait « une seule exception : CoachWatchComplications.swift ».
C'etait vrai le 3 aout, jour ou il a ete ecrit. Le widget de saisie rapide est
arrive le 6 aout avec trois fichiers Swift de plus, et aucun n'appartient a une
target : CoachQuickLog.swift, CoachQuickSync.swift, CoachQuickWidget.swift.
Verifie dans project.pbxproj, pas suppose.

Consequence si on suivait le guide tel quel : l'extension ne compile pas, et le
widget « Saisie des repas et boissons » n'apparait nulle part - sans que rien
n'explique pourquoi, puisque le guide affirmait qu'il n'y avait rien a ajouter.

Une etape 4b liste les trois fichiers avec leur Target Membership exact.
CoachQuickLog va dans DEUX cibles, l'extension ecrivant la file que l'app vide.
Et ce qui est deja fait est dit comme tel, pour ne pas le refaire : le widget
est enregistre dans le WidgetBundle, et CoachQuickSync.flush() est bien appele
par AppDelegate.

Le point 4 du runbook widgets demandait de verifier le schema coachapp:// dans
l'Info.plist. Il est barre : depuis e715804 les boutons pointent sur des URL
https routees par Universal Links, precisement parce que coachapp:// n'etait
routé nulle part et ouvrait l'app sur sa derniere page consultee.

Aucun code touche, uniquement de la documentation de session.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 11:40:49 +00:00
Sylvain Bettinelli
823bfb2ab9 Synchronisation des saisies du widget vers le serveur
`CoachQuickSync.flush()` envoie la file partagée vers POST /api/drinks et retire
les entrées transmises. Cible App uniquement : l'extension n'appelle jamais ce
code, elle n'a ni session ni droit de tenir une requête — c'est toute la raison
d'être de la file.

Le cookie de session du WebView est réutilisé plutôt que de refabriquer une
authentification qui divergerait.

Trois comportements voulus, documentés pour qu'on ne les « corrige » pas :
une entrée qui échoue reste en file et repartira — mieux vaut un doublon visible
qu'une saisie disparue ; un 400 est considéré comme traité, sans quoi un payload
refusé bloquerait la file indéfiniment ; la date est formatée en fuseau local,
pour qu'un verre bu à 23 h compte pour le jour où il a été bu.

Reste un appel à poser dans AppDelegate.applicationDidBecomeActive — le
one-liner est dans le runbook.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 13:06:28 +00:00
Sylvain Bettinelli
7778e62c40 docs(widgets): runbook Mac du widget Saisie rapide
Target Membership, enregistrement dans le WidgetBundle, schéma d'URL, iOS 17
minimum, et le câblage de synchronisation restant côté app.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 13:03:35 +00:00
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
Sylvain Bettinelli
1e7adb709e docs(session-xcode): exclut build/ de la vérif de câblage
La commande listait tout DerivedData et les checkouts SPM en « NON CÂBLÉ »
(15 faux positifs constatés sur le Mac le 2026-08-03). Le dossier build/
n'existe pas côté serveur dev, d'où l'angle mort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 14:44:09 +00:00
Sylvain Bettinelli
66d1877449 docs: guide pas à pas de la session Xcode (9 étapes)
Rassemble tout le natif accumulé depuis le TestFlight de mai en une seule
procédure ordonnée par dépendances : pull, token, App Group, capabilities,
target complications (facultative), build+tests device, puis distribution.

Point d'arrêt explicite après l'étape 6 : l'app tourne sur l'iPhone, la
publication TestFlight peut attendre un autre jour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 14:31:45 +00:00
Sylvain Bettinelli
caeac37f38 feat(watch): routine quotidienne cochable sur l'Apple Watch
Pendant natif du backend coach_sportif (commit 772385b, déjà en prod).

- CoachRoutineBridge (target App) : pousse blocs + état du jour vers la Watch
  via updateApplicationContext, relaie les coches Watch vers /api/routine/day
  puis notifie la WebView (event routineUpdated)
- CoachWatch/RoutineStore : état persisté en UserDefaults, reset au changement
  de jour. Les blocs viennent de l'iPhone — rien codé en dur côté watchOS, donc
  modifier la routine côté web ne demande aucun rebuild
- CoachWatch/RoutineView : liste cochable, progression, haptique, bouton de
  renvoi si la synchro a échoué
- ConnectivityManager (watch) : sendRoutine() en sendMessage avec repli
  transferUserInfo (coche faite iPhone hors de portée -> livraison différée)

⚠️ CoachLiveBridge touché : routeIfNotLiveSample() aiguille les messages
routineDone vers NotificationCenter. WCSession.delegate est unique côté iPhone,
impossible d'en ajouter un second. Le flux live workout n'est pas modifié mais
doit être re-vérifié au build.

Les 3 nouveaux fichiers sont référencés dans project.pbxproj (bonne target) :
aucun "Add Files" à faire sur le Mac. Runbook : docs/routine-watch-runbook-mac.md

NON COMPILÉ — nécessite une session Xcode sur le Mac mini.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 14:22:33 +00:00
Sylvain Bettinelli
ec975a9a0d docs(ios): corrige la note capacitor.config — fichier gitignored/généré, .ts déjà OK
Rectification : capacitor.config.json n'est PAS suivi (gitignored, généré par cap
sync). Le .ts source a déjà les bonnes valeurs → le finding audit 'JSON divergent'
était un artefact local périmé, pas un bug du repo. cap sync sur le Mac régénère
correctement. Pas d'action de versionnement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 09:20:14 +00:00
Sylvain Bettinelli
4153446de2 fix(ios): lot 5 audit — réaligne capacitor.config.json sur le .ts (régression visuelle)
Le JSON embarqué avait divergé du .ts source (cap sync non rejoué) :
contentInset always->never, fonds #ffffff->#000000, StatusBar DEFAULT->LIGHT.
Corrige la régression bottom-nav + flash blanc ré-introduite en prod. JSON validé.
aps-environment (dev->prod) NON flippé depuis Linux (casserait le dev ; fix par
config Release sur le Mac) — documenté dans docs/widgets-runbook-mac.md avec le
reste des findings iOS de l'audit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 09:19:20 +00:00
Sylvain Bettinelli
cc88431f6b feat(watch): complications Apple Watch (Forme + Séance du jour)
L'App Group n'étant pas partagé entre appareils, le snapshot transite par
WatchConnectivity : iPhone CoachWidgetBridge.pushToWatch (updateApplicationContext)
-> CoachWatch/ConnectivityManager reçoit -> App Group de la montre + reload des
complications. Nouvelles complications (CoachWatchWidgets/CoachWatchComplications.swift) :
Forme (accessoryCircular/corner, Gauge) + Séance du jour (accessoryRectangular/inline).

⚠️ Reste Mac : créer la target widget watchOS + App Group/capability + Target
Membership. Runbook complet dans docs/widgets-runbook-mac.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:50:29 +00:00
Sylvain Bettinelli
a6bdebcfc8 feat(widgets): widgets natifs iPhone (Séance du jour + Score de forme)
Pont WebView→App Group→WidgetKit :
- CoachWidgetSnapshot.swift : modèle partagé App↔extension (App Group group.ch.hypnotruck.coach)
- CoachWidgetBridge.swift : plugin Capacitor setSnapshot/clear + WidgetCenter.reloadAllTimelines
- CoachWidgets.swift : 2 widgets (TimelineProvider + vues SwiftUI, small/medium)
- bundle + enregistrement plugin + entitlements App Group (App + CoachLiveActivity)

⚠️ Reste câblage Mac (App Group portail + capability + Target Membership) :
docs/widgets-runbook-mac.md. Hook web côté coach_sportif.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:18:17 +00:00
Sylvain Bettinelli
edf3783fb5 docs: analyse migration iOS natif vs hybride (aide à la décision, ancrée inventaire réel)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:05:14 +00:00
Sylvain
51cbce86ef docs(watchos): chantier CLOS — test E2E FC réelle Watch Ultra 3 -> /live PASSÉ (2026-05-31)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 12:02:39 +02:00
Sylvain
3bafecf5fc docs(watchos): re-vérif build green 2026-05-31 (App + Watch + Live Activity)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 11:54:22 +02:00
Sylvain
b92e4d5ce6 docs: point 1 (/live nav) DÉPLOYÉ en prod (coach_sportif ecf334a)
Onglet "Live workout" -> /live ajouté dans NAV_ITEMS, mergé sur main (ff) et
déployé via webhook (service coach-web actif). /live était déjà OK côté
route/auth/template (Phase 4) ; manquait juste le lien nav. "token invalide"
= accès /live non authentifié (pas de lien -> redirect login).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 21:06:54 +02:00
Sylvain
6a4e3f7768 docs: handoff backend /live (Mac->Linux) + pont watch->iPhone prouvé E2E
HANDOFF-LIVE-BACKEND.md : tâches coach_sportif pour finir /live (auth cookie de
session, lien d'accès depuis l'app, JS template) + contrat exact du plugin
(event liveSample, champs heartRate/activeEnergyKcal/distanceMeters/elapsedSec/ts/sim).
Plan mis à jour : pont watch->iPhone validé end-to-end sur simulateur.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 20:39:47 +02:00
Sylvain
0bd5d5c5f8 docs(watchos): avancement Phases 1-3 réalisées + deltas watchOS 26
Statut chantier, commits, et 3 deltas vs pseudocode (ConnectivityManager non
@MainActor, WorkoutManager @MainActor + délégués nonisolated, registerPluginInstance
Capacitor 8). Reste : test device + TestFlight + cross-check JS /live.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 19:03:20 +02:00
Sylvain Bettinelli
6e4011db3f docs(watchos): plan technique + handoff Claude Code Mac mini
Préparation du chantier watchOS Live Workout (live FC/calories/distance
sur l'iPhone pendant que Sylvain fait du sport sur l'Apple Watch).

Décision archi : la phase native Swift/watchOS nécessite Xcode + Apple
Watch device, indispo dans la session Linux où ces docs ont été écrites.
D'où le handoff vers Claude Code lancé sur le Mac mini Sylvain.

Fichiers ajoutés :

- `docs/watchos-live-workout-plan.md` (444 lignes)
  Plan technique complet en 5 phases :
  1. Création target watchOS Xcode + entitlements
  2. Code Swift watchOS (4 fichiers : CoachWatchApp, WorkoutManager,
     ConnectivityManager, ContentView)
  3. Plugin Capacitor iOS (CoachLiveBridge.swift) qui reçoit les samples
     WCSession et les publie au JS via notifyListeners
  4. Route web /live + template (squelette prêt à coller dans
     coach_sportif/web/)
  5. Tests device + TestFlight internal
  Inclut décisions d'archi (HKLiveWorkoutBuilder, sendMessage avec
  fallback transferUserInfo, pas de Live Activity V1), pseudocode Swift,
  estimation effort 12-20h sur 3-5 jours, et risques + mitigations.

- `HANDOFF-WATCHOS.md` (181 lignes)
  Instructions étape par étape pour Claude Code Mac. Liste les memories
  à charger (project_coach_watchos_live, project_coach_ios,
  project_coach_app_commercial, user_sante_cardio,
  feedback_inline_display_none_toggle), workflow Step 1..6 (setup env,
  création target, lecture docs Apple, implémentation Swift, route web,
  tests device), garde-fous et règle "qui possède quoi" pendant le
  chantier (Mac = Swift natif, Linux = backend Python).

- `CLAUDE.md` (1ère commit, fichier existait en local non-tracked)
  Pointeur ajouté dans la section Backlog vers les 2 nouveaux fichiers.

Aucun fichier Swift n'a été écrit ici (décision conjointe avec Sylvain
pour ne pas risquer du code à l'aveugle sans Xcode pour valider les
APIs HealthKit/WCSession à jour).
2026-05-24 13:25:07 +00:00