Demandé par Sylvain : des widgets, puis « comment lier Siri à mon appli ». Constat avant de commencer : App Intents déclarés : 1 (LogDrinkIntent) AppShortcutsProvider : 0 -> Siri n'avait AUCUNE phrase à écouter Saisie depuis la montre : 0 -> complications d'affichage seulement Et la cause commune : `LogDrinkIntent` vivait dans `CoachQuickWidget.swift`, qui n'appartient qu'à l'extension widget iPhone. Ni l'app (d'où Siri découvre les raccourcis), ni la cible Watch ne pouvaient le voir. Ce qui est ajouté ------------------ - `CoachIntents.swift` — les intents, partagés entre les TROIS cibles. `LogDrinkIntent` y est déplacé (pas dupliqué : deux définitions du même symbole dans une cible qui compile les deux fichiers casseraient le build), plus `HydrationStatusIntent` et `TodaySessionIntent`. - `CoachAppShortcuts.swift` — 5 raccourcis, 16 phrases françaises. Cible App UNIQUEMENT : Apple attend un seul AppShortcutsProvider par application. - `CoachWatchHydration.swift` — widget Smart Stack de la montre : total du jour, jauge, et deux boutons +cl. Le geste se fait au poignet. Choix qui méritent d'être dits ------------------------------- ⛔ Pas de saisie des repas sur la montre. Pas de caméra, pas de scanner, pas de saisie de texte confortable : le bouton ne ferait que renvoyer vers l'iPhone. Tranché avec Sylvain. ⛔ Pas de volume libre dans les phrases Siri. Un intent paramétré oblige Siri à poser une question — plus long que de sortir le téléphone, et le raccourci perd sa raison d'être. Volumes fixés : 250 ml, 500 ml, café 60 ml. ⛔ Aucune borne en bpm dans les réponses vocales. `TodaySession` n'en porte pas (vérifié : sport, title, subtitle, done) 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. Siri annonce QUOI ; l'app dit COMMENT. Deux boutons et pas trois sur la montre : sur 160 pt, un troisième descend les cibles sous le seuil tactile, pour un geste qu'on fait en marchant. ⚠️ RIEN DE CE CODE N'EST COMPILÉ --------------------------------- AppIntents, WidgetKit et SwiftUI sont absents de Swift pour Linux. Ce qui a été vérifié à la place, par lecture croisée des sources : que chaque symbole appelé existe, et qu'aucun n'est déclaré deux fois. Deux erreurs ont d'ailleurs été trouvées ainsi avant commit — `asOf()` ne rend pas un optionnel, et `TodaySession` n'a pas de `durationMin`. Les erreurs de type, de concurrence et d'API n'apparaîtront qu'au build. `docs/siri-et-widget-watch-runbook-mac.md` porte les étapes Xcode, le tableau de Target Membership, les cinq vérifications à faire sur l'appareil, et les trois questions que seul le build tranchera — dont celle-ci : une complication de cadran accepte-t-elle un bouton interactif, ou est-ce réservé à la Smart Stack ? Par prudence, le cadran n'est ici qu'un affichage. 91 tests Swift Linux au vert (non-régression CoachQuickLog / snapshot). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.2 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.
⛔ Rien de ce code n'a été compilé.
AppIntents,WidgetKitetSwiftUIsont 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 leWidgetBundle.
É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
- Siri — dire « Note un verre d'eau dans Coach ». Attendu : « Noté. X,XX L d'eau aujourd'hui », sans que l'app s'ouvre.
- Raccourcis — l'app Raccourcis doit lister les 5 actions sous « Coach ».
- 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.
- Synchro — ouvrir l'app iPhone, vérifier que la saisie faite au poignet
remonte sur
coach.hypnotruck.ch. - 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
- 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,
.accessoryCircularn'est ici qu'un affichage ; si le cadran accepte l'interactivité, on pourra l'enrichir. - 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. ProvidesDialogsur watchOS. Les intents rendentsome IntentResult & ProvidesDialogpour 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.
TodaySessionn'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.