# 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. > ⛔ **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 | CoachWatchWidgets | |---|:--:|:--:|:--:| | `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 `CoachWatchWidgets`**, 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 **CoachWatchWidgets**. 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.