Files
coach-ios/docs/siri-et-widget-watch-runbook-mac.md
Sylvain Bettinelli 0d34908f4f Runbook : la cible watchOS s'appelle CoachWatchWidgetsExtension, pas CoachWatchWidgets
Vérifié dans project.pbxproj avant d'envoyer Sylvain dans Xcode : les quatre
cibles réelles sont App, CoachLiveActivity, CoachWatch et
CoachWatchWidgetsExtension. Le runbook donnait le nom du DOSSIER
(CoachWatchWidgets) pour celui de la cible — il aurait cherché un intitulé
inexistant dans l'inspecteur de Target Membership, à l'étape précisément
décrite comme celle qui décide de tout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-25 07:02:29 +00:00

5.5 KiB

Runbook Mac — Siri + widget Hydratation de la montre

Écrit le 25/09/2026, depuis Linux. Le code Swift est committé ; il reste les étapes Xcode, qui ne peuvent pas se faire d'ici.

⚠️ Nom des cibles, vérifié le 25/09 : la cible watchOS s'appelle CoachWatchWidgetsExtension — le DOSSIER, lui, s'appelle CoachWatchWidgets. Ce runbook disait d'abord le nom du dossier ; corrigé. Les quatre cibles réelles : App, CoachLiveActivity, CoachWatch, CoachWatchWidgetsExtension.

⛔ Rien de ce code n'a été compilé. AppIntents, WidgetKit et SwiftUI sont des frameworks Apple, absents de Swift pour Linux — le CLAUDE.md de ce dépôt le dit. Ce qui a été vérifié à la place, par lecture croisée des sources : que chaque symbole appelé existe (CoachQuickLog.append, todayTotal, pending, CoachWidgetStore.load, nextMidnight, fallbackQuickDrinks, resolvedQuickDrinks, waterMlToday, waterGoalMl, asOf), et qu'aucun symbole n'est déclaré deux fois. Les erreurs de type, de concurrence et d'API n'apparaîtront qu'au build.

Ce que ça apporte

Avant Après
Siri rien — aucun AppShortcutsProvider 5 raccourcis, 16 phrases
Montre complications d'affichage widget Smart Stack qui note un verre
Intents 1, enfermé dans l'extension iPhone 3, partagés entre 3 cibles

Fichiers ajoutés / modifiés

  • ios/App/App/CoachIntents.swift (nouveau) — LogDrinkIntent (déplacé), HydrationStatusIntent, TodaySessionIntent, CoachQuickError.
  • ios/App/App/CoachAppShortcuts.swift (nouveau) — les phrases Siri.
  • ios/App/CoachWatchWidgets/CoachWatchHydration.swift (nouveau) — widget Smart Stack de la montre.
  • ios/App/CoachLiveActivity/CoachQuickWidget.swift — l'intent en a été retiré (il vivait là, invisible des deux autres cibles).
  • ios/App/CoachWatchWidgets/CoachWatchComplications.swift — le widget rejoint le WidgetBundle.

Étapes Xcode

⚠️ Quitter Xcode puis git pull d'abord (règle COWORK : jamais de pull Xcode ouvert).

1. Target Membership — c'est l'étape qui décide de tout

Fichier App CoachLiveActivity CoachWatchWidgetsExtension
CoachIntents.swift ✅ ✅ ✅
CoachAppShortcuts.swift ✅ ❌ ❌
CoachWatchHydration.swift ❌ ❌ ✅
CoachQuickLog.swift ✅ ✅ ✅ (à vérifier)
CoachWidgetSnapshot.swift ✅ ✅ ✅ (déjà le cas)

⚠️ CoachAppShortcuts.swift dans la cible App UNIQUEMENT. Apple attend un seul AppShortcutsProvider par application ; un second dans une extension produirait au mieux un doublon.

⚠️ CoachQuickLog.swift doit être dans CoachWatchWidgetsExtension, sinon le widget de la montre compile mais n'écrit nulle part. Son en-tête le réclamait déjà.

2. Vérifier l'App Group sur la cible Watch

group.ch.hypnotruck.coach sur CoachWatch ET CoachWatchWidgetsExtension. Vérifié depuis Linux le 25/09 : les quatre .entitlements le portent et les CODE_SIGN_ENTITLEMENTS sont câblés. À reconfirmer dans Signing & Capabilities.

3. Build, puis les vérifications qui comptent

  1. Siri — dire « Note un verre d'eau dans Coach ». Attendu : « Noté. X,XX L d'eau aujourd'hui », sans que l'app s'ouvre.
  2. Raccourcis — l'app Raccourcis doit lister les 5 actions sous « Coach ».
  3. Smart Stack — ajouter le widget Hydratation, toucher « +25 cl », vérifier que le total monte et que le badge des saisies en attente s'incrémente.
  4. Synchro — ouvrir l'app iPhone, vérifier que la saisie faite au poignet remonte sur coach.hypnotruck.ch.
  5. Minuit — le total doit repartir de zéro (c'est asOf(_:) qui l'assure, pas le réveil de la timeline : le piège a déjà été payé côté iPhone).

Les trois questions que seul le build tranchera

  1. Une complication de CADRAN accepte-t-elle un bouton d'App Intent, ou est-ce réservé à la Smart Stack ? La doc Apple n'était pas récupérable depuis Linux. Par prudence, .accessoryCircular n'est ici qu'un affichage ; si le cadran accepte l'interactivité, on pourra l'enrichir.
  2. Les phrases Siri passent-elles la validation ? Chaque phrase contient \(.applicationName), comme Apple l'exige, et le nom supposé est « Coach » (CFBundleDisplayName). Si le nom affiché diffère, les phrases ne se déclencheront pas — c'est silencieux.
  3. ProvidesDialog sur watchOS. Les intents rendent some IntentResult & ProvidesDialog pour que Siri réponde à voix haute. À confirmer que la cible watchOS l'accepte sans ajustement.

Ce qui a été volontairement écarté

  • ⛔ Saisie des repas depuis la montre. Pas de caméra, pas de scanner de code-barres, pas de saisie de texte confortable : un bouton « repas » au poignet ne ferait que renvoyer vers l'iPhone. Décidé avec Sylvain le 25/09.
  • ⛔ Un paramètre libre de volume dans les phrases Siri. Un intent paramétré oblige Siri à poser une question — ce qui coûte plus de temps que de sortir le téléphone, et vide le raccourci de son intérêt. Les volumes sont donc fixés (250 ml, 500 ml, café 60 ml).
  • ⛔ Toute borne en bpm dans les réponses de Siri. TodaySession n'en porte pas, et il ne faut pas en ajouter : une fourchette cardiaque annoncée par haut-parleur, hors de la recommandation du jour et de ses réserves, reviendrait à prescrire une intensité à un post-infarctus.