diff --git a/AGENTS.md b/AGENTS.md
index cdbba5b..c8f37ad 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,142 +1,272 @@
-# TabataGo — iOS Tabata Workout App
+# TabataGo — Référence canonique pour agents IA
-> Tabata interval training app for iOS + watchOS with HealthKit integration.
+> **Une seule source de vérité.** Ce document décrit le projet *réel*. Si un autre
+> fichier (CLAUDE.md, schema.sql) contredit, ce document gagne.
-## Agent Context
+---
-This project is part of the **Millian Team** — an AI agent engineering team.
-When working here, agents should load the relevant skill:
-- `senior-ios` — SwiftUI, Xcode, iOS/watchOS development
-- `senior-backend` — Supabase backend
-- `senior-devops` — Deploy infrastructure
-- `po-pm` — Product vision, specs, validation
+## 0. ⚠️ Fichiers obsolètes — NE PAS LIRE
-## Tech Stack
+| Fichier | Statut | Pourquoi |
+|---------|--------|----------|
+| `CLAUDE.md` (racine) | ❌ OBSOLÈTE | Décrit **TabataFit**, un concept Expo/React Native abandonné |
+| `supabase/schema.sql` | ❌ OBSOLÈTE | Header littéral "TabataFit" — décrit l'ancien schéma |
+| `supabase/seed.sql`, `supabase/setup-admin.sql` | ⚠️ Vérifier | Peuvent être périmés ; préférer `supabase/migrations/` |
+| `AGENTS.md` (ancien, racine) | 🔄 Remplacé par celui-ci | Mentionne PostHog 3.x comme actif (faux, voir §3) |
-| Layer | Tech |
-|-------|------|
-| App | SwiftUI, iOS 26.0+ |
-| Watch | SwiftUI, watchOS 11.0+ |
-| Widget | WidgetKit, Live Activities |
-| Language | Swift 6.0 (strict concurrency) |
-| Architecture | MVVM, @Observable, AppState central |
-| Backend | Supabase (PostgreSQL, Auth, Storage) |
-| Subscriptions | RevenueCat 5.x |
-| Analytics | PostHog 3.x |
-| Health | HealthKit (heart rate, calories, workouts) |
-| Music | Apple Music integration + YouTube worker |
-| Build | XcodeGen (project.yml → .xcodeproj) |
-| Package Manager | Swift Package Manager |
+**Source de vérité du schéma : `supabase/migrations/001` → `006`.** Jamais `schema.sql`.
-## Project Structure
+---
+
+## 1. Identité produit
+
+| | |
+|---|---|
+| **Nom** | TabataGo |
+| **Bundle** | `fr.millianlmx.tabatago` |
+| **Team** | `2MJF39L8VY` |
+| **But** | App d'entraînement Tabata (intervalles 20s travail / 10s repos) sur iOS + watchOS, avec programmes par zone corporelle, HealthKit, musique, et abonnements RevenueCat |
+| **Version** | 1.0 (build 2) — non publiée App Store |
+| **Propriétaire** | Millian LMX (CEO) |
+| **Gitea** | `https://gitea.1000co.fr/millianlmx/tabatago` |
+
+---
+
+## 2. Stack technique
+
+| Couche | Réalité vérifiée |
+|--------|------------------|
+| Langage | **Swift 6.0**, concurrence stricte (`SWIFT_STRICT_CONCURRENCY: complete`) |
+| UI | **SwiftUI** uniquement |
+| iOS | **26.0+** |
+| watchOS | **11.0+** |
+| Build | **XcodeGen** — `project.yml` est la source, `.xcodeproj` est généré |
+| SPM | **Supabase** `2.5.0+`, **RevenueCat** `5.0.0+` |
+| ❌ NON installé | **PostHog** — absent de `project.yml` packages. Voir §3. |
+| Architecture | **MVVM + `@Observable`**, `AppState.shared` central |
+| Backend | **Supabase** (PostgreSQL, Auth, Storage, Edge Functions Deno) |
+| Local cache | **SwiftData** (`TabataGoSchema.container`) |
+| Santé | **HealthKit** (fréquence cardiaque, calories, workouts) |
+| CI/CD | **Gitea Actions** sur runner macOS auto-hébergé (label `macos`) |
+
+---
+
+## 3. Architecture iOS
+
+### Cibles (`tabatago-swift/project.yml`)
+
+| Cible | Type | Plateforme | Bundle ID |
+|-------|------|------------|-----------|
+| `TabataGo` | application | iOS 26.0 | `fr.millianlmx.tabatago` |
+| `TabataGoWatch` | application | watchOS 11.0 | `fr.millianlmx.tabatago.watchkitapp` |
+| `TabataGoWatchWidget` | app-extension | watchOS 11.0 | `fr.millianlmx.tabatago.watchkitapp.widget` |
+| `TabataGoTests` | bundle.unit-test | iOS | `.tests` |
+| `TabataGoUITests` | bundle.ui-testing | iOS | `.uitests` |
+
+**Dépendances d'intégration** : `TabataGo` embed `TabataGoWatch` qui embed `TabataGoWatchWidget`.
+Fichier partagé entre iOS et watch : `TabataGo/Services/WatchConnectivityTypes.swift` (compilé dans les deux targets via `group: TabataGoWatch/Services`).
+
+### Bootstrap & data flow
```
-tabatago/
-├── tabatago-swift/ # Main Xcode project
-│ ├── project.yml # XcodeGen spec
-│ ├── Config/
-│ │ ├── Secrets.xcconfig # API keys (not committed)
-│ │ └── Secrets.xcconfig.example
-│ ├── TabataGo/ # iOS App
-│ │ ├── App/ # App entry, state, root view
-│ │ │ ├── TabataGoApp.swift
-│ │ │ ├── RootView.swift
-│ │ │ └── AppState.swift
-│ │ ├── Views/
-│ │ │ ├── Tabs/ # MainTabView, Home, Activity, Programs, Profile
-│ │ │ ├── Player/ # Workout player (PlayerView, NowPlaying)
-│ │ │ ├── Programs/ # ProgramDetail, BodyZone
-│ │ │ ├── Onboarding/ # Onboarding flow
-│ │ │ ├── Paywall/ # RevenueCat paywall
-│ │ │ ├── Complete/ # Workout completion screen
-│ │ │ ├── Settings/ # Settings, policies
-│ │ │ └── Components/ # Shared UI components
-│ │ ├── ViewModels/ # HomeVM, HealthVM, PlayerVM, PurchaseVM, MusicVM
-│ │ ├── Models/ # WorkoutProgram, WorkoutSession, UserProfile, etc.
-│ │ ├── Services/ # Supabase, HealthKit, Music, Audio, Purchase, Analytics
-│ │ ├── Theme/ # App theme
-│ │ ├── Utilities/ # Strings, Environment
-│ │ └── Resources/ # Assets, Localizable, entitlements
-│ ├── TabataGoWatch/ # watchOS App
-│ │ ├── Views/ # WatchRoot, WatchIdle, WatchActivity, WatchPlayer
-│ │ ├── Services/ # WatchConnectivity, WatchPlayerEngine
-│ │ ├── Complications/ # Watch face complications
-│ │ └── Resources/
-│ ├── TabataGoWidget/ # iOS Widget + Live Activities
-│ ├── TabataGoTests/ # Unit tests
-│ └── TabataGoUITests/ # UI tests
-├── supabase/ # Supabase config
-│ ├── schema.sql
-│ ├── seed.sql
-│ ├── setup-admin.sql
-│ └── migrations/ # SQL migrations (001-006)
-└── youtube-worker/ # Node.js worker for YouTube music
- ├── server.js
- ├── package.json
- └── Dockerfile
+TabataGoApp (@main)
+ └─ RootView()
+ ├─ .environment(AppState.shared) // @Observable singleton
+ ├─ .modelContainer(TabataGoSchema.container) // SwiftData
+ └─ .task { await AppState.shared.bootstrap() }
```
-## Dependencies (SPM)
+`AppState.bootstrap()` (MainActor, idempotent, skip en preview) :
+1. `PurchaseService.shared.initialize()` (RevenueCat)
+2. `AnalyticsService.shared.initialize()` — ⚠️ **no-op par défaut** car PostHog n'est pas dans SPM : tout est gardé par `#if canImport(PostHog)` qui est toujours faux. La taxonomie d'events existe mais n'émet rien tant que la dépendance n'est pas ajoutée.
-- **Supabase** 2.5+ — Backend SDK (Auth, Database, Storage)
-- **RevenueCat** 5.0+ — In-app purchases
-- **PostHog** 3.0+ — Analytics
+### Navigation (PAS de NavigationStack)
-## Features
+`MainTabView` = **`TabView` + `Tab(value:)`** (Liquid Glass, iOS 26), 4 onglets dans cet ordre exact du code :
-- Tabata/interval workout player with configurable timers
-- Pre-built workout programs by body zone
-- HealthKit integration (heart rate, calories, workout saving)
-- Apple Watch companion with real-time metrics
-- Live Activities + Dynamic Island
-- Music integration (Apple Music + YouTube)
-- RevenueCat subscriptions
-- Onboarding flow
-- Activity tracking & workout history
+```
+home → programs → activity → profile
+```
-## Commands
+Modals full-screen via `.sheet`/`fullScreenCover` au-dessus :
+`PlayerView`, `CompletionView`, `PaywallView`, `OnboardingView`.
+
+### Services (`TabataGo/Services/`)
+
+| Service | Rôle |
+|---------|------|
+| `SupabaseService` | Client Supabase (Auth, DB, Storage) |
+| `HealthKitService` | Lecture/écriture HealthKit |
+| `PurchaseService` | RevenueCat IAP, état d'abonnement |
+| `MusicService` | Apple Music + intégration piste YouTube |
+| `AudioService` | Playback audio (coachs sonores, alerts) |
+| `AnalyticsService` | **Stub PostHog** (voir ci-dessus) |
+| `PhoneConnectivityManager` | Côté iOS — WatchConnectivity (échange avec la montre) |
+| `WatchConnectivityTypes` | Protocoles/messages partagés iOS↔Watch (compilé dans les 2 targets) |
+
+> Le miroir côté watch est `TabataGoWatch/Services/WatchConnectivityManager.swift` (cible watchOS, pas iOS).
+
+### ViewModels (`@Observable`)
+
+`HomeViewModel`, `HealthViewModel`, `PlayerViewModel`, `PurchaseViewModel`, `MusicPlayerViewModel`.
+
+### Models (`TabataGo/Models/`)
+
+`WorkoutProgram`, `WorkoutSession`, `UserProfile`, `HealthSnapshot`, `MusicTrack`, `WorkoutActivityAttributes`, `MusicActivityAttributes` (Live Activities), `TabataGoSchema` (SwiftData), `PreviewData`/`MockPrograms` (previews).
+
+### Watch (`TabataGoWatch/`)
+
+`TabataGoWatchApp` → `WatchRootView` → états `WatchIdleView` / `WatchActivityView` / `WatchPlayerView`.
+Moteur : `WatchPlayerEngine`. Connectivité : `WatchConnectivityManager` (coté watch).
+Complications : `TabataGoComplication`.
+
+---
+
+## 4. Base de données
+
+### Supabase — source = `supabase/migrations/` (001→006)
+
+| # | Fichier | Contenu |
+|---|---------|---------|
+| 001 | `001_initial_schema.sql` | `trainers`, `workouts`, `collections`, `achievements`, `admin_users` |
+| 002 | `002_download_jobs.sql` | `download_jobs`, `download_items` (jobs d'import playlist YouTube) |
+| 003 | `003_music_genre.sql` | `music_genre` |
+| 004 | `004_download_items_public_read.sql` | RLS : lecture publique de `download_items` |
+| 005 | `005_workout_programs.sql` | **DROP** `programs`/`program_workouts` → **CREATE** `workout_programs` (body_zone enum `upper-body`/`lower-body`/`full-body` + level `Beginner`/`Intermediate`/`Advanced`) et `program_tabatas` (3 tabatas/program, 2 exercices chacun, 8 rounds × 20s/10s) + RLS public read + admin all |
+| 006 | `006_seed_workout_programs.sql` | **18 programmes seedés** (12 free : 4 par zone en 2B+1I+1A ; 6 premium) + **54 tabatas** (18×3), UUIDs stables |
+
+**Tables actives post-migration** : `trainers`, `workouts`, `collections`, `achievements`, `admin_users`, `download_jobs`, `download_items`, `music_genre`, `workout_programs`, `program_tabatas`.
+
+**Tables supprimées (ne pas recréer)** : `programs`, `program_workouts` (DROP en 005).
+
+**RLS** : lecture publique sur `workout_programs`/`program_tabatas`/`download_items` ; écriture restreinte aux `admin_users` (`EXISTS (SELECT 1 FROM admin_users WHERE id = auth.uid())`).
+
+### SwiftData — cache local
+
+`TabataGoSchema.container` (et `.previewContainer` pour les `#Preview`). Persistance offline des sessions/programmes côté app. Ne pas confondre avec Supabase.
+
+---
+
+## 5. CI/CD
+
+### Workflow : `.gitea/workflows/pr-iphone-deploy.yml`
+
+**Trigger** : PR ouverte/synchronize/reopened sur `main`.
+**Runner** : label `macos` (auto-hébergé).
+**Déroulé** :
+
+1. **Checkout** (shallow, branche head) via `PR_API_TOKEN`.
+2. **Setup PATH** : `echo "/opt/homebrew/bin" >> $GITHUB_PATH` — requis car Rosetta ne le voit pas.
+3. **Clean ciblé** :
+ - Supprime build artifacts, `TabataGo.xcodeproj`, `Package.resolved`, DerivedData, ModuleCache.
+ - **GARDE le cache SPM** (`../build/spm-cache`) — RevenueCat ≈ 1.1 GiB, re-cloner = 5+ min et échecs aléatoires du sandbox.
+4. **Install tools** : `brew install xcodegen node ios-deploy`.
+5. **xcodegen generate** → `xcodebuild -resolvePackageDependencies` → **build** (`-scheme TabataGo`, Debug, auto-provisioning, team `2MJF39L8VY`).
+6. **Deploy iPhone** UDID `00008120-000925CE3672201E` : `devicectl` WiFi d'abord, fallback `ios-deploy` USB.
+7. **Post comment** "Prêt à tester" sur la PR.
+8. **Job `wait-approval`** : poll (30s, max 240 = 2h) les commentaires de la PR. `LGTM` → auto-merge. `KO` → blocage. Timeout → fail.
+
+### Secrets
+
+| Secret | Usage |
+|--------|-------|
+| `PR_API_TOKEN` | Checkout + API Gitea (comment, merge). **JAMAIS `GITEA_TOKEN`/`GITHUB_TOKEN`** |
+| `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `REVENUECAT_API_KEY`, `POSTHOG_API_KEY` | Injectés via `Config/Secrets.xcconfig` → Info.plist |
+
+### ⚠️ Pitfalls CI
+
+- `/opt/homebrew/bin` **hors PATH par défaut** sous Rosetta → toujours l'ajouter.
+- **xcodegen 2.45.4 ne génère pas de schemes auto** → scheme `TabataGo` défini explicitement dans `project.yml` (ne pas le supprimer).
+- **Ne jamais `rm -rf` le cache SPM** dans le CI (c'est l'inverse des build artifacts).
+- `SWIFT_ENABLE_EXPLICIT_MODULES=NO` au build — requis sinon segfault linker sur `.pcm` stale.
+- `-skipPackagePluginValidation -allowProvisioningUpdates`.
+
+---
+
+## 6. Sous-projets
+
+### `admin-web/` — Dashboard admin
+
+Next.js 15 App Router, shadcn/ui. Gestion workouts / trainers / collections / programs.
+Auth Supabase → table `admin_users`. Stack : TypeScript, `middleware.ts`, tests Playwright (`e2e/`) + Vitest.
+
+### `youtube-worker/` — Worker YouTube
+
+Node.js (`server.js`, `package.json`, `Dockerfile`). Télécharge l'audio de playlists YouTube → **Supabase Storage**. Piloté par les Edge Functions ci-dessous.
+
+### `supabase/functions/` — Edge Functions (Deno)
+
+| Function | Rôle |
+|----------|------|
+| `youtube-playlist/` | Crée un `download_job`, liste les vidéos |
+| `youtube-process/` | Orchestre le téléchargement (via youtube-worker) |
+| `youtube-status/` | Statut d'un job |
+| `youtube-classify/` | Classification genre musical |
+| `main/` | Auth JWT (helper `jose`) |
+| `_shared/` | `auth.ts`, `cors.ts`, `supabase-client.ts`, `youtube-client.ts` |
+
+> Le pipeline musical complet : Edge Functions orchestrent → `youtube-worker` (Node.js) télécharge via **yt-dlp** + **Innertube** → audio dans Supabase Storage (`workout-audio` bucket) → classification automatique par **Gemini** (`gemini-3.1-flash-lite-preview`) → métadonnées dans `download_jobs`/`download_items` → genre dans `music_genre`.
+
+---
+
+## 7. Règles d'or pour les agents
+
+1. **Source de vérité = `project.yml` + `supabase/migrations/`.** Tout le reste est dérivé ou obsolète.
+2. **SwiftUI only.** Pas d'UIKit sauf nécessité absolue démontrée.
+3. **`@Observable`** (macro Observation), **jamais `@ObservableObject`/`@Published`**.
+4. **Concurrency stricte.** `async/await` partout, `@MainActor` sur l'UI, pas de completion handlers.
+5. **Pas de force-unwrap.** `guard let`/`if let`, jamais `!`.
+6. **Navigation = TabView + sheet/fullScreenCover.** **Pas de `NavigationStack`.**
+7. **Tout en français** côté user-facing (`Localizable.xcstrings` / `L10n`). Codes/types restent en anglais.
+8. **XcodeGen.** Éditer `project.yml`, pas `.xcodeproj`. Régénérer avec `xcodegen generate`.
+9. **Secrets.** Jamais committer `Config/Secrets.xcconfig`. Template = `.example`.
+10. **Lazy d'abord.** Avant d'ajouter une dépendance : stdlib Apple, puis ce qui existe déjà dans le repo, puis SPM déjà installé. PostHog n'est pas installé — ne pas l'ajouter sans justification.
+
+---
+
+## 8. Anti-patterns / pièges documentés
+
+| ❌ Ne pas faire | ✅ Faire |
+|-----------------|---------|
+| Lire `CLAUDE.md` ou `schema.sql` pour le schéma | Lire `supabase/migrations/001→006` |
+| Importer PostHog comme si c'était actif | Savoir que `AnalyticsService` est un **no-op** (PostHog pas en SPM) |
+| Utiliser `NavigationStack` | `TabView` + modals |
+| `@ObservableObject` / `@Published` | `@Observable` |
+| Force-unwrap `!` | `guard let` |
+| Strings UI en anglais | Françaises dans `L10n`/`Localizable.xcstrings` |
+| `rm -rf` le cache SPM en CI | Garder `build/spm-cache` |
+| Utiliser `GITEA_TOKEN` en CI | `PR_API_TOKEN` uniquement |
+| Supprimer le scheme explicite dans `project.yml` | xcodegen 2.45.4 n'en crée pas |
+| Compter sur `admin-web/` pour la app iOS | Dashboard admin séparé, communique via Supabase uniquement |
+| Recréer `programs`/`program_workouts` | Remplacés par `workout_programs`/`program_tabatas` (migration 005) |
+
+---
+
+## 9. Contexte projet & skills
+
+- **Repo Gitea** : `https://gitea.1000co.fr/millianlmx/tabatago` (branche intégration : `main`).
+- **Équipe** : "Millian Team" — équipe d'agents IA. Skills à loader selon la tâche :
+ - `senior-ios` — SwiftUI, Xcode, iOS/watchOS
+ - `senior-backend` — Supabase, SQL, Edge Functions
+ - `senior-devops` — CI/CD Gitea Actions, deploy
+ - `po-pm` — vision produit, specs, validation
+- **Team skill TabataGo** : documente les anti-patterns ci-dessus ; aligne tous les agents sur les mêmes conventions.
+- **Hermes profile actif** : `default`. Les skills vivent dans le profile sous `skills/`.
+- **Docs utiles** : `docs/ci-cd-setup.md`, `docs/app-store-submission.md`, `docs/maestro-e2e-testing-strategy.md`, `docs/ui-feature-brief.md`.
+- **Scripts** : `scripts/ci-status.py`, `scripts/deploy-functions.sh`.
+
+### Commandes usuelles
```bash
-# From tabatago-swift/
-xcodegen generate # Generate .xcodeproj
-open TabataGo.xcodeproj # Open in Xcode
+# Générer le projet Xcode
+cd tabatago-swift && xcodegen generate
-# In Xcode
-Cmd+R → Run on simulator
-Cmd+U → Run tests
+# Ouvrir
+open tabatago-swift/TabataGo.xcodeproj
+
+# Déployer les Edge Functions
+bash scripts/deploy-functions.sh
+
+# Statut CI
+python3 scripts/ci-status.py
```
-
-## Configuration
-
-- `Config/Secrets.xcconfig` contains API keys (not committed)
-- Template: `Config/Secrets.xcconfig.example`
-- Env vars: `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `REVENUECAT_API_KEY`, `POSTHOG_API_KEY`
-
-## Current State
-
-- **Version**: 1.0 (build 2) — not yet released
-- **State**: App functional, needs finishing work
-- **Platforms**: iOS 26.0+, watchOS 11.0+
-- **Requires**: macOS with Xcode 26+ to build
-
-## Supabase Schema
-
-Tables: `profiles`, `workout_sessions`, `workout_programs`, `download_jobs`, `music_genre`, etc.
-See `supabase/schema.sql` and `supabase/migrations/` for full schema.
-
-## Team Rules
-
-1. **Swift Concurrency** — async/await everywhere, no completion handlers
-2. **@Observable** — not @ObservableObject
-3. **No force unwrap** — `guard let` always, never `!`
-4. **SwiftUI only** — no UIKit unless unavoidable
-5. **XcodeGen** — project.yml is source of truth, not .xcodeproj
-6. **Secrets** — never commit Secrets.xcconfig
-7. **French** — all user-facing strings in French (Localizable.xcstrings)
-
-## Project Context
-
-- **User**: Millian LMX (CEO)
-- **Gitea**: https://gitea.1000co.fr/millianlmx/tabatago
-- **Supabase**: Managed instance (URL in secrets)
-- **App Store**: Not yet published
diff --git a/AGENTS.md.old b/AGENTS.md.old
new file mode 100644
index 0000000..cdbba5b
--- /dev/null
+++ b/AGENTS.md.old
@@ -0,0 +1,142 @@
+# TabataGo — iOS Tabata Workout App
+
+> Tabata interval training app for iOS + watchOS with HealthKit integration.
+
+## Agent Context
+
+This project is part of the **Millian Team** — an AI agent engineering team.
+When working here, agents should load the relevant skill:
+- `senior-ios` — SwiftUI, Xcode, iOS/watchOS development
+- `senior-backend` — Supabase backend
+- `senior-devops` — Deploy infrastructure
+- `po-pm` — Product vision, specs, validation
+
+## Tech Stack
+
+| Layer | Tech |
+|-------|------|
+| App | SwiftUI, iOS 26.0+ |
+| Watch | SwiftUI, watchOS 11.0+ |
+| Widget | WidgetKit, Live Activities |
+| Language | Swift 6.0 (strict concurrency) |
+| Architecture | MVVM, @Observable, AppState central |
+| Backend | Supabase (PostgreSQL, Auth, Storage) |
+| Subscriptions | RevenueCat 5.x |
+| Analytics | PostHog 3.x |
+| Health | HealthKit (heart rate, calories, workouts) |
+| Music | Apple Music integration + YouTube worker |
+| Build | XcodeGen (project.yml → .xcodeproj) |
+| Package Manager | Swift Package Manager |
+
+## Project Structure
+
+```
+tabatago/
+├── tabatago-swift/ # Main Xcode project
+│ ├── project.yml # XcodeGen spec
+│ ├── Config/
+│ │ ├── Secrets.xcconfig # API keys (not committed)
+│ │ └── Secrets.xcconfig.example
+│ ├── TabataGo/ # iOS App
+│ │ ├── App/ # App entry, state, root view
+│ │ │ ├── TabataGoApp.swift
+│ │ │ ├── RootView.swift
+│ │ │ └── AppState.swift
+│ │ ├── Views/
+│ │ │ ├── Tabs/ # MainTabView, Home, Activity, Programs, Profile
+│ │ │ ├── Player/ # Workout player (PlayerView, NowPlaying)
+│ │ │ ├── Programs/ # ProgramDetail, BodyZone
+│ │ │ ├── Onboarding/ # Onboarding flow
+│ │ │ ├── Paywall/ # RevenueCat paywall
+│ │ │ ├── Complete/ # Workout completion screen
+│ │ │ ├── Settings/ # Settings, policies
+│ │ │ └── Components/ # Shared UI components
+│ │ ├── ViewModels/ # HomeVM, HealthVM, PlayerVM, PurchaseVM, MusicVM
+│ │ ├── Models/ # WorkoutProgram, WorkoutSession, UserProfile, etc.
+│ │ ├── Services/ # Supabase, HealthKit, Music, Audio, Purchase, Analytics
+│ │ ├── Theme/ # App theme
+│ │ ├── Utilities/ # Strings, Environment
+│ │ └── Resources/ # Assets, Localizable, entitlements
+│ ├── TabataGoWatch/ # watchOS App
+│ │ ├── Views/ # WatchRoot, WatchIdle, WatchActivity, WatchPlayer
+│ │ ├── Services/ # WatchConnectivity, WatchPlayerEngine
+│ │ ├── Complications/ # Watch face complications
+│ │ └── Resources/
+│ ├── TabataGoWidget/ # iOS Widget + Live Activities
+│ ├── TabataGoTests/ # Unit tests
+│ └── TabataGoUITests/ # UI tests
+├── supabase/ # Supabase config
+│ ├── schema.sql
+│ ├── seed.sql
+│ ├── setup-admin.sql
+│ └── migrations/ # SQL migrations (001-006)
+└── youtube-worker/ # Node.js worker for YouTube music
+ ├── server.js
+ ├── package.json
+ └── Dockerfile
+```
+
+## Dependencies (SPM)
+
+- **Supabase** 2.5+ — Backend SDK (Auth, Database, Storage)
+- **RevenueCat** 5.0+ — In-app purchases
+- **PostHog** 3.0+ — Analytics
+
+## Features
+
+- Tabata/interval workout player with configurable timers
+- Pre-built workout programs by body zone
+- HealthKit integration (heart rate, calories, workout saving)
+- Apple Watch companion with real-time metrics
+- Live Activities + Dynamic Island
+- Music integration (Apple Music + YouTube)
+- RevenueCat subscriptions
+- Onboarding flow
+- Activity tracking & workout history
+
+## Commands
+
+```bash
+# From tabatago-swift/
+xcodegen generate # Generate .xcodeproj
+open TabataGo.xcodeproj # Open in Xcode
+
+# In Xcode
+Cmd+R → Run on simulator
+Cmd+U → Run tests
+```
+
+## Configuration
+
+- `Config/Secrets.xcconfig` contains API keys (not committed)
+- Template: `Config/Secrets.xcconfig.example`
+- Env vars: `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `REVENUECAT_API_KEY`, `POSTHOG_API_KEY`
+
+## Current State
+
+- **Version**: 1.0 (build 2) — not yet released
+- **State**: App functional, needs finishing work
+- **Platforms**: iOS 26.0+, watchOS 11.0+
+- **Requires**: macOS with Xcode 26+ to build
+
+## Supabase Schema
+
+Tables: `profiles`, `workout_sessions`, `workout_programs`, `download_jobs`, `music_genre`, etc.
+See `supabase/schema.sql` and `supabase/migrations/` for full schema.
+
+## Team Rules
+
+1. **Swift Concurrency** — async/await everywhere, no completion handlers
+2. **@Observable** — not @ObservableObject
+3. **No force unwrap** — `guard let` always, never `!`
+4. **SwiftUI only** — no UIKit unless unavoidable
+5. **XcodeGen** — project.yml is source of truth, not .xcodeproj
+6. **Secrets** — never commit Secrets.xcconfig
+7. **French** — all user-facing strings in French (Localizable.xcstrings)
+
+## Project Context
+
+- **User**: Millian LMX (CEO)
+- **Gitea**: https://gitea.1000co.fr/millianlmx/tabatago
+- **Supabase**: Managed instance (URL in secrets)
+- **App Store**: Not yet published
diff --git a/CLAUDE.md b/CLAUDE.md.obsolete
similarity index 100%
rename from CLAUDE.md
rename to CLAUDE.md.obsolete
diff --git a/admin-web/AUTH_SETUP.md b/admin-web/AUTH_SETUP.md
deleted file mode 100644
index 1e763f9..0000000
--- a/admin-web/AUTH_SETUP.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Authentication Setup Guide
-
-## Overview
-This guide sets up full server-side authentication for the TabataFit Admin panel.
-
-## Prerequisites
-- Supabase project running (local or hosted)
-- Admin-web Next.js app running
-- Database schema already applied
-
-## Step 1: Configure Supabase Dashboard
-
-1. Go to your Supabase Dashboard → Authentication → Providers
-2. **Enable Email Provider**
-3. **Disable "Confirm email"** (for easier testing, re-enable for production)
-4. Go to Authentication → URL Configuration
-5. Set **Site URL**: `http://localhost:3000` (or your production URL)
-6. Add **Redirect URLs**: `http://localhost:3000/**`
-
-## Step 2: Create Admin User
-
-### Option A: Via Supabase Dashboard (Easiest)
-1. Go to Supabase Dashboard → Authentication → Users
-2. Click "Add user" or "Invite user"
-3. Enter email: `admin@tabatafit.com`
-4. Set password: Your chosen password
-5. Click "Create user"
-6. Copy the user's UUID (click on the user to see details)
-
-### Option B: Via Login Page
-1. Go to `http://localhost:3000/login`
-2. Click "Sign up" (if available) or use dashboard method above
-
-## Step 3: Add User to Admin Table
-
-**Important**: After creating the user, you MUST add them to the admin_users table.
-
-Run this SQL in Supabase SQL Editor:
-
-```sql
--- Replace with your actual email or UUID
-INSERT INTO public.admin_users (id, email, role)
-SELECT id, email, 'admin'
-FROM auth.users
-WHERE email = 'admin@tabatafit.com'
-ON CONFLICT (id) DO NOTHING;
-```
-
-Or if you have the UUID:
-```sql
-INSERT INTO public.admin_users (id, email, role)
-VALUES ('paste-uuid-here', 'admin@tabatafit.com', 'admin');
-```
-
-## Step 4: Verify Setup
-
-Run this to confirm:
-```sql
-SELECT au.id, au.email, au.role, u.email as auth_email
-FROM public.admin_users au
-JOIN auth.users u ON au.id = u.id;
-```
-
-You should see your admin user listed.
-
-## Step 5: Login
-
-1. Go to `http://localhost:3000/login`
-2. Enter email: `admin@tabatafit.com`
-3. Enter password: (the one you set)
-4. You should be redirected to the dashboard
-
-## Troubleshooting
-
-### "Not authorized as admin" error
-- User exists in auth.users but not in admin_users table
-- Run Step 3 SQL to add them
-
-### "Failed to fetch" errors
-- Check that EXPO_PUBLIC_SUPABASE_URL is set in .env.local
-- For admin-web, also add NEXT_PUBLIC_SUPABASE_URL with same value
-
-### Still can't create workouts
-- Verify you're logged in (check browser cookies)
-- Check that admin_users table has your user
-- Check RLS policies are applied correctly
-
-## Default Credentials (Example)
-
-**Email**: `admin@tabatafit.com`
-**Password**: (You choose during setup)
-
-**Note**: Change this to a secure password in production!
-
-## Security Notes
-
-1. **Production**: Enable email confirmations
-2. **Production**: Use strong passwords
-3. **Production**: Enable 2FA if available
-4. **Production**: Restrict CORS origins in Supabase
-5. **Production**: Use environment-specific admin credentials
\ No newline at end of file
diff --git a/admin-web/TEST_IMPLEMENTATION.md b/admin-web/TEST_IMPLEMENTATION.md
deleted file mode 100644
index 05eed31..0000000
--- a/admin-web/TEST_IMPLEMENTATION.md
+++ /dev/null
@@ -1,218 +0,0 @@
-# TabataFit Admin Dashboard - Test Implementation Summary
-
-## ✅ Completed Implementation
-
-### 1. Unit Tests
-
-#### UI Components (100% Coverage)
-- **button.test.tsx** ✓ (already existed)
-- **select.test.tsx** ✓ (already existed)
-- **switch.test.tsx** ✓ (already existed)
-- **dialog.test.tsx** ✓ **NEW** - 8 test cases
- - Dialog rendering
- - Open/close behavior
- - Click outside to close
- - Escape key handling
- - Footer rendering
- - Custom styling
- - Accessibility features
-
-#### Custom Components
-- **exercise-list.test.tsx** ✓ (already existed)
-- **media-upload.test.tsx** ✓ (42 tests, 90%+ coverage)
-- **tag-input.test.tsx** ✓ (already existed)
-- **sidebar.test.tsx** ✓ **NEW** - 11 test cases
- - Logo and navigation rendering
- - Active state highlighting
- - Navigation links
- - Logout functionality
- - Error handling
- - Icon rendering
- - Styling verification
-
-### 2. Integration Tests
-
-#### Page Tests
-- **login/page.test.tsx** ✓ **NEW** - 11 test cases
- - Form rendering
- - Input validation
- - Successful login
- - Invalid credentials
- - Non-admin user handling
- - Loading states
- - Network error handling
-
-- **page.test.tsx** (Dashboard) ✓ **NEW** - 12 test cases
- - Header rendering
- - Stats cards display
- - Loading states
- - Quick actions section
- - Getting started section
- - Route links
- - Error handling
- - Icon verification
- - Color classes
-
-### 3. E2E Tests
-
-#### Playwright Configuration ✓ **NEW**
-- Installed @playwright/test
-- Configured for Chromium and Firefox
-- Automatic dev server startup
-- Screenshot on failure
-- HTML reporting
-
-#### E2E Test Suite
-- **e2e/auth.spec.ts** ✓ **NEW**
- - Login form display
- - Validation errors
- - Route protection
- - Navigation between pages
-
-### 4. Test Scripts Added
-
-```json
-{
- "test:e2e": "playwright test",
- "test:e2e:ui": "playwright test --ui",
- "test:e2e:headed": "playwright test --headed",
- "test:all": "npm run test && npm run test:e2e"
-}
-```
-
-## 📊 Current Test Coverage
-
-| Metric | Before | After | Target |
-|--------|--------|-------|--------|
-| Lines | 88% | ~92% | 95% |
-| Functions | 92% | ~94% | 95% |
-| Branches | 78% | ~82% | 85% |
-| Statements | 85% | ~90% | 90% |
-
-## 🧪 Test Files Created
-
-### New Test Files (7 files)
-1. `components/ui/dialog.test.tsx`
-2. `components/sidebar.test.tsx`
-3. `app/login/page.test.tsx`
-4. `app/page.test.tsx`
-5. `e2e/auth.spec.ts`
-6. `playwright.config.ts`
-
-### Modified Files
-- `package.json` - Added E2E test scripts
-
-## 🎯 Test Categories
-
-### Unit Tests
-- ✅ Component rendering
-- ✅ User interactions (clicks, input)
-- ✅ State changes
-- ✅ Props validation
-- ✅ Styling verification
-- ✅ Accessibility checks
-
-### Integration Tests
-- ✅ Page routing
-- ✅ Data fetching
-- ✅ Form submissions
-- ✅ Error handling
-- ✅ Loading states
-
-### E2E Tests
-- ✅ Authentication flows
-- ✅ Navigation
-- ✅ Route protection
-- ✅ Cross-browser testing
-
-## 🚀 How to Run Tests
-
-### Unit Tests
-```bash
-# Run all unit tests
-npm run test
-
-# Run with coverage
-npm run test:coverage
-
-# Watch mode
-npm run test:watch
-```
-
-### E2E Tests
-```bash
-# Run E2E tests
-npm run test:e2e
-
-# Run with UI
-npm run test:e2e:ui
-
-# Run in headed mode (see browser)
-npm run test:e2e:headed
-```
-
-### All Tests
-```bash
-# Run both unit and E2E tests
-npm run test:all
-```
-
-## 📋 Remaining Work (Optional)
-
-### High Priority
-- [ ] workouts/page.test.tsx - Full CRUD tests
-- [ ] trainers/page.test.tsx - Delete dialog tests
-- [ ] workout-form.tsx coverage improvement (currently 71%)
-
-### Medium Priority
-- [ ] collections/page.test.tsx
-- [ ] media/page.test.tsx
-- [ ] Additional E2E tests for CRUD operations
-
-### Low Priority
-- [ ] Visual regression tests with Storybook
-- [ ] Performance benchmarks
-- [ ] Accessibility audit with axe
-
-## 🎉 Achievements
-
-✅ **All Critical Paths Tested**
-- Authentication flow
-- Dashboard stats
-- Navigation
-- Sidebar functionality
-- UI component library
-
-✅ **Test Infrastructure Complete**
-- Vitest configured
-- Playwright configured
-- Mock utilities ready
-- CI/CD scripts prepared
-
-✅ **Coverage Improved**
-- Added 42+ new test cases
-- Improved dialog component to 100%
-- Added sidebar component tests
-- Added page integration tests
-
-## 🔧 Testing Best Practices Implemented
-
-1. **Mock External Dependencies** - Supabase, Next.js router
-2. **Test User Interactions** - Clicking, typing, navigation
-3. **Verify Error States** - Network errors, auth failures
-4. **Check Accessibility** - Roles, labels, ARIA attributes
-5. **Test Responsive Behavior** - Different viewports (E2E)
-6. **Isolate Tests** - Clean mocks between tests
-
-## 📚 Documentation
-
-- Each test file is self-documenting
-- Descriptive test names explain the behavior
-- Comments for complex mock setups
-- Type safety with TypeScript
-
----
-
-**Status**: ✅ **Phase 1 Complete** - Core testing infrastructure implemented
-
-**Next Steps**: Run `npm run test:all` to execute full test suite!
\ No newline at end of file
diff --git a/docs/maestro-e2e-testing-strategy.md b/docs/maestro-e2e-testing-strategy.md
deleted file mode 100644
index f54cb9e..0000000
--- a/docs/maestro-e2e-testing-strategy.md
+++ /dev/null
@@ -1,643 +0,0 @@
-# Maestro E2E Testing Strategy for TabataFit
-
-## Executive Summary
-
-**Maestro** is a mobile UI testing framework that uses YAML-based test flows. It's ideal for TabataFit because:
-- ✅ Declarative YAML syntax (no code required)
-- ✅ Built-in support for React Native
-- ✅ Handles animations and async operations gracefully
-- ✅ Excellent for regression testing critical user flows
-- ✅ Can run on physical devices and simulators
-
----
-
-## Prerequisites
-
-Before implementing these tests, ensure the following features are complete:
-
-### Required Features (Implement First)
-- [ ] Onboarding flow (5 screens + paywall)
-- [ ] Workout player with timer controls
-- [ ] Browse/Workouts tab with workout cards
-- [ ] Category filtering (Full Body, Core, Cardio, etc.)
-- [ ] Collections feature
-- [ ] Trainer profiles
-- [ ] Subscription/paywall integration
-- [ ] Workout completion screen
-- [ ] Profile/settings screen
-
-### Nice to Have (Can Add Later)
-- [ ] Activity history tracking
-- [ ] Offline mode support
-- [ ] Deep linking
-- [ ] Push notifications
-
----
-
-## Priority Test Flows
-
-### **P0 - Critical Flows (Must Test Every Release)**
-1. **Onboarding → First Workout**
-2. **Browse → Select Workout → Play → Complete**
-3. **Subscription Purchase Flow**
-4. **Background/Foreground During Workout**
-
-### **P1 - High Priority**
-5. **Category Filtering**
-6. **Collection Navigation**
-7. **Trainer Workout Discovery**
-8. **Profile Settings & Data Persistence**
-
-### **P2 - Medium Priority**
-9. **Activity History Tracking**
-10. **Offline Mode Behavior**
-11. **Deep Linking**
-12. **Push Notifications**
-
----
-
-## Test Suite Structure
-
-```
-.maestro/
-├── config.yaml # Global test configuration
-├── flows/
-│ ├── critical/ # P0 flows - Run on every PR
-│ │ ├── onboarding.yaml
-│ │ ├── workoutComplete.yaml
-│ │ └── subscription.yaml
-│ ├── core/ # P1 flows - Run before release
-│ │ ├── browseAndPlay.yaml
-│ │ ├── categoryFilter.yaml
-│ │ ├── collections.yaml
-│ │ └── trainers.yaml
-│ └── regression/ # P2 flows - Run nightly
-│ ├── activityHistory.yaml
-│ ├── offlineMode.yaml
-│ └── settings.yaml
-├── helpers/
-│ ├── common.yaml # Shared test steps
-│ ├── assertions.yaml # Custom assertions
-│ └── mock-data.yaml # Test data
-└── environments/
- ├── staging.yaml
- └── production.yaml
-```
-
----
-
-## Installation & Setup
-
-### 1. Install Maestro CLI
-
-```bash
-# macOS/Linux
-curl -Ls "https://get.maestro.mobile.dev" | bash
-
-# Verify installation
-maestro --version
-```
-
-### 2. Setup Test Directory Structure
-
-```bash
-mkdir -p .maestro/flows/{critical,core,regression}
-mkdir -p .maestro/helpers
-mkdir -p .maestro/environments
-```
-
-### 3. Maestro Configuration (`config.yaml`)
-
-```yaml
-# .maestro/config.yaml
-appId: com.tabatafit.app
-name: TabataFit E2E Tests
-
-# Timeouts
-timeout: 30000 # 30 seconds default
-retries: 2
-
-# Environment variables
-env:
- TEST_USER_NAME: "Test User"
- TEST_USER_EMAIL: "test@example.com"
-
-# Include flows
-include:
- - flows/critical/*.yaml
- - flows/core/*.yaml
-
-# Exclude on CI
-exclude:
- - flows/regression/offlineMode.yaml # Requires airplane mode
-```
-
----
-
-## P0 Critical Test Flows
-
-### Test 1: Complete Onboarding Flow
-
-**File:** `.maestro/flows/critical/onboarding.yaml`
-
-```yaml
-appId: com.tabatafit.app
-name: Complete Onboarding & First Workout
-
-onFlowStart:
- - clearState
-
-steps:
- # Splash/Loading
- - waitForAnimationToEnd:
- timeout: 5000
-
- # Screen 1: Problem - "Not Enough Time"
- - assertVisible: "Not enough time"
- - tapOn: "Continue"
-
- # Screen 2: Empathy
- - assertVisible: "We get it"
- - tapOn: "Continue"
-
- # Screen 3: Solution
- - assertVisible: "4-minute workouts"
- - tapOn: "Continue"
-
- # Screen 4: Wow Moment
- - assertVisible: "Transform your body"
- - tapOn: "Get Started"
-
- # Screen 5: Personalization
- - tapOn: "Name input"
- - inputText: "Test User"
- - tapOn: "Beginner"
- - tapOn: "Lose Weight"
- - tapOn: "3 times per week"
- - tapOn: "Start My Journey"
-
- # Screen 6: Paywall (or skip in test env)
- - runScript: |
- if (maestro.env.SKIP_PAYWALL === 'true') {
- maestro.tapOn('Maybe Later');
- }
-
- # Should land on Home
- - assertVisible: "Good morning|Good afternoon|Good evening"
- - assertVisible: "Test User"
-
-onFlowComplete:
- - takeScreenshot: "onboarding-complete"
-```
-
-### Test 2: Browse, Select, and Complete Workout
-
-**File:** `.maestro/flows/critical/workoutComplete.yaml`
-
-```yaml
-appId: com.tabatafit.app
-name: Browse, Play & Complete Workout
-
-steps:
- # Navigate to Workouts tab
- - tapOn: "Workouts"
- - waitForAnimationToEnd
-
- # Wait for data to load
- - assertVisible: "All|Full Body|Core|Upper Body"
-
- # Select first workout
- - tapOn:
- id: "workout-card-0"
- optional: false
-
- # Workout Detail Screen
- - assertVisible: "Start Workout"
- - tapOn: "Start Workout"
-
- # Player Screen
- - waitForAnimationToEnd:
- timeout: 3000
-
- # Verify timer is running
- - assertVisible: "Get Ready|WORK|REST"
-
- # Fast-forward through workout (simulation)
- - repeat:
- times: 3
- commands:
- - waitForAnimationToEnd:
- timeout: 5000
- - assertVisible: "WORK|REST"
-
- # Complete workout
- - tapOn:
- id: "done-button"
- optional: true
-
- # Complete Screen
- - assertVisible: "Workout Complete|Great Job"
- - assertVisible: "Calories"
- - assertVisible: "Duration"
-
- # Return to home
- - tapOn: "Done|Continue"
- - assertVisible: "Home|Workouts"
-
-onFlowComplete:
- - takeScreenshot: "workout-completed"
-```
-
-### Test 3: Subscription Purchase Flow
-
-**File:** `.maestro/flows/critical/subscription.yaml`
-
-```yaml
-appId: com.tabatafit.app
-name: Subscription Purchase Flow
-
-steps:
- # Trigger paywall (via profile or workout limit)
- - tapOn: "Profile"
- - tapOn: "Upgrade to Premium"
-
- # Paywall Screen
- - assertVisible: "Unlock Everything|Premium"
- - assertVisible: "yearly|monthly"
-
- # Select plan
- - tapOn:
- id: "yearly-plan"
-
- # Verify Apple Pay/Google Pay sheet appears
- - assertVisible: "Subscribe|Confirm"
-
- # Note: Actual purchase is mocked in test env
- - runScript: |
- if (maestro.env.USE_MOCK_PURCHASE === 'true') {
- maestro.tapOn('Mock Purchase Success');
- }
-
- # Verify premium activated
- - assertVisible: "Premium Active|You're all set"
-
-tags:
- - purchase
- - revenue-critical
-```
-
----
-
-## P1 Core Test Flows
-
-### Test 4: Category Filtering
-
-**File:** `.maestro/flows/core/categoryFilter.yaml`
-
-```yaml
-appId: com.tabatafit.app
-name: Category Filtering
-
-steps:
- - tapOn: "Workouts"
- - waitForAnimationToEnd
-
- # Test each category
- - tapOn: "Full Body"
- - assertVisible: "Full Body"
-
- - tapOn: "Core"
- - assertVisible: "Core"
-
- - tapOn: "Cardio"
- - assertVisible: "Cardio"
-
- - tapOn: "All"
- - assertVisible: "All Workouts"
-
- # Verify filter changes content
- - runScript: |
- const before = maestro.getElementText('workout-count');
- maestro.tapOn('Core');
- const after = maestro.getElementText('workout-count');
- assert(before !== after, 'Filter should change workout count');
-```
-
-### Test 5: Collection Navigation
-
-**File:** `.maestro/flows/core/collections.yaml`
-
-```yaml
-appId: com.tabatafit.app
-name: Collection Navigation
-
-steps:
- - tapOn: "Browse"
- - waitForAnimationToEnd
-
- # Scroll to collections
- - swipe:
- direction: UP
- duration: 1000
-
- # Tap first collection
- - tapOn:
- id: "collection-card-0"
-
- # Collection Detail Screen
- - assertVisible: "Collection"
- - assertVisible: "workouts"
-
- # Start collection workout
- - tapOn: "Start"
- - assertVisible: "Player|Timer"
-
-onFlowComplete:
- - takeScreenshot: "collection-navigation"
-```
-
-### Test 6: Trainer Discovery
-
-**File:** `.maestro/flows/core/trainers.yaml`
-
-```yaml
-appId: com.tabatafit.app
-name: Trainer Discovery
-
-steps:
- - tapOn: "Browse"
-
- # Navigate to trainers section
- - swipe:
- direction: UP
-
- # Select trainer
- - tapOn:
- id: "trainer-card-0"
-
- # Verify trainer profile
- - assertVisible: "workouts"
-
- # Select trainer's workout
- - tapOn:
- id: "workout-card-0"
-
- # Should show workout detail
- - assertVisible: "Start Workout"
-```
-
----
-
-## Reusable Test Helpers
-
-### Common Actions (`helpers/common.yaml`)
-
-```yaml
-# .maestro/helpers/common.yaml
-appId: com.tabatafit.app
-
-# Launch app fresh
-- launchApp:
- clearState: true
-
-# Wait for data loading
-- waitForDataLoad:
- commands:
- - waitForAnimationToEnd:
- timeout: 3000
- - assertVisible: ".*" # Any content loaded
-
-# Handle permission dialogs
-- handlePermissions:
- commands:
- - tapOn:
- text: "Allow"
- optional: true
- - tapOn:
- text: "OK"
- optional: true
-
-# Navigate to tab
-- navigateToTab:
- params:
- tabName: ${tab}
- commands:
- - tapOn: ${tab}
-
-# Start workout from detail
-- startWorkout:
- commands:
- - tapOn: "Start Workout"
- - waitForAnimationToEnd:
- timeout: 5000
- - assertVisible: "Get Ready|WORK"
-```
-
----
-
-## Running Tests
-
-### Local Development
-
-```bash
-# Install Maestro
-curl -Ls "https://get.maestro.mobile.dev" | bash
-
-# Run single test
-maestro test .maestro/flows/critical/onboarding.yaml
-
-# Run all critical tests
-maestro test .maestro/flows/critical/
-
-# Run with specific environment
-maestro test --env SKIP_PAYWALL=true .maestro/flows/
-
-# Record video of test
-maestro record .maestro/flows/critical/workoutComplete.yaml
-
-# Run with tags
-maestro test --include-tags=critical .maestro/flows/
-```
-
-### CI/CD Integration (GitHub Actions)
-
-```yaml
-# .github/workflows/maestro.yml
-name: Maestro E2E Tests
-
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
-
-jobs:
- e2e-tests:
- runs-on: macos-latest
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Setup Node
- uses: actions/setup-node@v3
-
- - name: Install Maestro
- run: curl -Ls "https://get.maestro.mobile.dev" | bash
-
- - name: Start iOS Simulator
- run: |
- xcrun simctl boot "iPhone 15"
- sleep 10
-
- - name: Install App
- run: |
- npm install
- npx expo prebuild
- npx pod install
- npx react-native run-ios --simulator="iPhone 15"
-
- - name: Run Critical Tests
- run: |
- export MAESTRO_DRIVER_STARTUP_TIMEOUT=120000
- maestro test .maestro/flows/critical/
-
- - name: Upload Test Results
- if: always()
- uses: actions/upload-artifact@v3
- with:
- name: maestro-results
- path: |
- ~/.maestro/tests/
- *.png
-```
-
----
-
-## Test Coverage Matrix
-
-| Feature | Test File | Priority | Frequency | Status |
-|---------|-----------|----------|-----------|--------|
-| Onboarding | `onboarding.yaml` | P0 | Every PR | ⏳ Pending |
-| Workout Play | `workoutComplete.yaml` | P0 | Every PR | ⏳ Pending |
-| Purchase | `subscription.yaml` | P0 | Every PR | ⏳ Pending |
-| Category Filter | `categoryFilter.yaml` | P1 | Pre-release | ⏳ Pending |
-| Collections | `collections.yaml` | P1 | Pre-release | ⏳ Pending |
-| Trainers | `trainers.yaml` | P1 | Pre-release | ⏳ Pending |
-| Activity | `activityHistory.yaml` | P2 | Nightly | ⏳ Pending |
-| Offline | `offlineMode.yaml` | P2 | Weekly | ⏳ Pending |
-
----
-
-## React Native Prerequisites
-
-Before running tests, add `testID` props to components for reliable selectors:
-
-```tsx
-// WorkoutCard.tsx
-
- {/* ... */}
-
-
-// WorkoutPlayer.tsx
-
-
-// Paywall.tsx
-
- {/* ... */}
-
-```
-
-### Required testIDs Checklist
-
-- [ ] `workout-card-{index}` - Workout list items
-- [ ] `collection-card-{index}` - Collection items
-- [ ] `trainer-card-{index}` - Trainer items
-- [ ] `done-button` - Complete workout button
-- [ ] `yearly-plan` / `monthly-plan` - Subscription plans
-- [ ] `start-workout-button` - Start workout CTA
-- [ ] `category-{name}` - Category filter buttons
-- [ ] `tab-{name}` - Bottom navigation tabs
-
----
-
-## Environment Variables
-
-Create `.env.maestro` file:
-
-```bash
-# Test Configuration
-SKIP_PAYWALL=true
-USE_MOCK_PURCHASE=true
-TEST_USER_NAME=Test User
-TEST_USER_EMAIL=test@example.com
-
-# API Configuration (if needed)
-API_BASE_URL=https://api-staging.tabatafit.com
-```
-
----
-
-## Troubleshooting
-
-### Common Issues
-
-1. **Tests fail on first run**
- - Clear app state: `maestro test --clear-state`
- - Increase timeout in config.yaml
-
-2. **Element not found**
- - Verify testID is set correctly
- - Add wait times before assertions
- - Check for animations completing
-
-3. **Purchase tests fail**
- - Ensure `USE_MOCK_PURCHASE=true` in test env
- - Use sandbox/test products
-
-4. **Slow tests**
- - Use `waitForAnimationToEnd` with shorter timeouts
- - Disable animations in test builds
-
-### Debug Commands
-
-```bash
-# Interactive mode
-maestro studio
-
-# View hierarchy
-maestro hierarchy
-
-# Record test execution
-maestro record
-
-# Verbose logging
-maestro test --verbose
-```
-
----
-
-## Next Steps (After Features Are Complete)
-
-1. ✅ Create `.maestro/` directory structure
-2. ✅ Write `config.yaml`
-3. ✅ Implement P0 critical test flows
-4. ✅ Add testIDs to React Native components
-5. ✅ Run tests locally
-6. ✅ Setup CI/CD pipeline
-7. ⏳ Implement P1 core test flows
-8. ⏳ Add visual regression tests
-9. ⏳ Setup nightly regression suite
-
----
-
-## Resources
-
-- [Maestro Documentation](https://maestro.mobile.dev/)
-- [Maestro YAML Reference](https://maestro.mobile.dev/api-reference/commands)
-- [React Native Testing with Maestro](https://maestro.mobile.dev/platform-support/react-native)
-- [Maestro Best Practices](https://maestro.mobile.dev/advanced/best-practices)
-
----
-
-**Created:** March 17, 2026
-**Status:** Implementation Pending (Waiting for feature completion)
diff --git a/docs/ui-feature-brief.md b/docs/ui-feature-brief.md
deleted file mode 100644
index c04e174..0000000
--- a/docs/ui-feature-brief.md
+++ /dev/null
@@ -1,486 +0,0 @@
-# TabataFit — UI Feature Brief
-
-> Generated for Google Stitch design handoff.
-> Covers all end-user screens, interactions, states, and navigation flows.
-
----
-
-## App Overview
-
-**TabataFit** is a mobile fitness app ("Apple Fitness+ for Tabata") built with React Native / Expo. It delivers guided Tabata HIIT workouts with video, voice coaching, music, and Apple Watch heart-rate sync.
-
-### Design System
-
-| Token | Value | Usage |
-|-------|-------|-------|
-| Background | `#000000` | Pure black base |
-| Surface | `#1C1C1E` | Cards, sheets |
-| Brand | `#FF6B35` | Flame orange — primary accent |
-| Rest | `#5AC8FA` | Ice blue — rest phases |
-| Success | `#30D158` | Energy green — completion |
-| Prep phase | `#FF9500` | Orange-yellow |
-| Work phase | `#FF6B35` | Flame orange |
-| Rest phase | `#5AC8FA` | Ice blue |
-| Complete phase | `#30D158` | Green |
-
-- Supports **dark and light mode**
-- Multi-language (i18n)
-- Haptic feedback throughout
-
----
-
-## Navigation Structure
-
-```
-Root Stack
-├── Onboarding (6-step flow)
-├── (tabs)
-│ ├── Home — index
-│ ├── Explore — browse workouts
-│ ├── Activity — stats & history
-│ └── Profile — settings & account
-├── workout/[id] — Workout detail (push)
-├── program/[id] — Program detail (push)
-├── collection/[id] — Collection detail (push)
-├── player/[id] — Workout player (push, full-screen)
-├── complete/[id] — Post-workout celebration (push)
-├── paywall — Premium upsell (modal)
-├── explore-filters — Filter sheet (form sheet modal)
-└── privacy — Privacy policy (push)
-```
-
-**Tab bar**: 4 tabs — Home, Explore, Activity, Profile. SF Symbol icons. Badge support.
-
----
-
-## 1. Onboarding Flow
-
-A 6-screen linear funnel shown on first launch. Progress dots at top. Skip available on some steps.
-
-### 1.1 Problem Screen
-- **Purpose**: Motivational hook about time constraints
-- **Elements**: Headline text, subtitle, illustration
-- **CTA**: Continue
-
-### 1.2 Empathy Screen
-- **Purpose**: User selects fitness barriers to build rapport
-- **Elements**: Grid of 4 selectable cards — "No time", "Low motivation", "No knowledge", "No gym"
-- **Interaction**: Tap to select, max 2 selections, visual highlight on selected
-- **CTA**: Continue (enabled after 1+ selection)
-
-### 1.3 Solution Screen
-- **Purpose**: Show Tabata's effectiveness
-- **Elements**: Animated comparison bar chart (Tabata vs traditional cardio calorie burn)
-- **CTA**: Continue
-
-### 1.4 Wow Screen
-- **Purpose**: Reveal key app features
-- **Elements**: 4 feature cards with staggered entrance animations — Timer, Exercises, Voice Coaching, Progress Tracking
-- **CTA**: Continue
-
-### 1.5 Personalization Screen
-- **Purpose**: Collect user preferences to personalize experience
-- **Inputs**:
- - Name (text input)
- - Fitness level: Beginner / Intermediate / Advanced (single select chips)
- - Goal: Weight Loss / Cardio / Strength / Wellness (single select chips)
- - Weekly frequency: 2x / 3x / 5x per week (single select chips)
-- **CTA**: Continue (enabled when all fields filled)
-
-### 1.6 Paywall Screen (Onboarding variant)
-- **Purpose**: Premium conversion at end of onboarding
-- **Elements**: Premium features list, yearly/monthly plan toggle with real prices from RevenueCat
-- **CTAs**: Subscribe, Restore Purchases, Skip (close button)
-- **States**: Loading prices, purchase in progress, error
-
----
-
-## 2. Home Tab
-
-Personalized dashboard and primary entry point.
-
-### Elements
-- **Greeting header**: Time-based ("Good morning/afternoon/evening") + user's name + animated mascot
-- **Streak badge**: Current streak count with flame icon
-- **Quick stats row**: 3 stat pills — Current streak, This week (workouts), Total minutes
-- **Assessment card**: Feature-flagged (currently OFF) — fitness assessment prompt
-- **Program cards**: 3 horizontal cards (Upper Body, Lower Body, Full Body)
- - Each shows: icon, title, progress bar (% complete), status badge (Not Started / In Progress / Completed)
- - CTA per card: Start / Continue / Restart (depends on state)
-- **Switch program button**: Opens program selection
-
-### Navigation
-- Tap program card → `program/[id]`
-- Tap "Start" on program → `player/[id]` (first workout)
-- Tap "Continue" → `player/[id]` (next incomplete workout)
-
-### States
-- **New user**: 0 stats, no streak, programs at 0%
-- **Returning user**: Populated stats, active streak, program progress
-
----
-
-## 3. Explore Tab
-
-Browse, search, and filter the full workout catalog.
-
-### Elements
-- **Search bar**: Search by workout title, trainer name, exercise name, category. Real-time filtering.
-- **Featured collection**: Hero card at top with image, title, workout count. Tap → `collection/[id]`
-- **Trainer avatars**: Horizontal scroll of circular trainer photos. Tap to filter workouts by trainer.
-- **Collections carousel**: Horizontal scroll of collection cards. Tap → `collection/[id]`
-- **Recommended For You**: Horizontal workout card list, personalized based on workout history
-- **Featured workouts**: Grid of highlighted workouts
-- **All Workouts section**:
- - Category filter pills: All, Full Body, Upper Body, Lower Body, Core, Cardio
- - Filter button → opens `explore-filters` sheet
- - Active filter indicator + clear filters button
- - 2-column workout card grid
-
-### Workout Card
-- Thumbnail image
-- Duration badge overlay
-- Title, trainer name, level indicator
-- Lock icon if premium-only and user is free tier
-
-### Navigation
-- Tap workout card → `workout/[id]`
-- Tap collection → `collection/[id]`
-- Tap trainer avatar → filters workout list by that trainer
-- Tap filter button → `explore-filters` (form sheet modal)
-
-### States
-- **Loading**: Skeleton placeholders for cards
-- **Error**: Error message with Retry button
-- **Empty search**: "No workouts found" message
-- **Filtered**: Active filter chips shown, clear all button
-
----
-
-## 4. Activity Tab
-
-Workout history, statistics, and achievements.
-
-### Elements
-- **Streak banner**: Current streak + longest streak (flame icons)
-- **Stats grid** (2x2): Each stat in a card with circular progress ring
- - Total workouts (ring fills toward goal)
- - Total minutes
- - Total calories
- - Best streak
-- **Weekly bar chart**: Sun–Sat, each bar filled if a workout was completed that day, current day highlighted
-- **Recent workouts list**: Last 5 workouts
- - Each row: workout title, relative time ("2h ago"), duration, calories
- - Tap → `workout/[id]`
-- **Achievements grid**: 4 achievement badges displayed
- - Types: workouts milestone, streak milestone, minutes milestone, calories milestone
- - States: locked (greyed out) / unlocked (colored with checkmark)
-
-### States
-- **Empty**: No workouts yet — motivational message + "Start Your First Workout" CTA → `explore`
-- **Populated**: All sections visible with data
-
----
-
-## 5. Profile Tab
-
-User settings, account management, and app info.
-
-### Elements
-- **User header**: Avatar circle with initial, display name, plan label ("Free" or "TabataFit+")
-- **Stats row**: 3 inline stats — workouts count, streak, calories
-- **Upgrade CTA** (free users only): Gradient button → `paywall`
-
-#### Workout Settings Section
-- Haptic feedback toggle
-- Sound effects toggle
-- Voice coaching toggle
-
-#### Notifications Section
-- Daily reminders toggle
-- Reminder time display (when enabled)
-
-#### Personalization Section (premium only)
-- Sync status indicator
-
-#### About Section
-- Version number
-- Rate App → opens App Store rating prompt
-- Contact Us → opens email compose
-- FAQ → opens external web link
-- Privacy Policy → `privacy` screen
-
-#### Account Section (premium only)
-- Restore Purchases → triggers RevenueCat restore
-
-#### Danger Zone
-- Sign Out button
-- Data deletion: triggers confirmation modal
-
-### Data Deletion Modal
-- Warning text explaining data loss
-- Cancel / Delete buttons
-- Delete is destructive (red)
-
----
-
-## 6. Workout Detail Screen
-
-Pre-workout information screen. Reached by tapping any workout card.
-
-**Route**: `workout/[id]`
-
-### Elements
-- **Header**: Thumbnail or video preview, back button, heart/save button (toggle)
-- **Title**: Workout name
-- **Trainer**: Trainer name (colored text)
-- **Metadata row**: Duration (minutes), Calories estimate, Level badge (Beginner/Intermediate/Advanced)
-- **Equipment list**: Icons + labels for required equipment (or "No equipment")
-- **Timing card**: Prep time, Work time, Rest time, Rounds — displayed in a structured card
-- **Exercise list**: Ordered list of exercises with individual durations
-- **Repeat rounds indicator**: Shows if rounds repeat the exercise sequence
-- **Music vibe label**: Genre/mood of the workout soundtrack
-
-### CTAs
-- **Start Workout** → `player/[id]` (if unlocked or user is premium)
-- **Unlock with TabataFit+** → `paywall` (if locked and user is free tier)
-
-### Header Actions
-- **Back**: Navigate back
-- **Save/Unsave**: Heart icon toggle — saves workout to favorites
-
-### States
-- **Loading**: Skeleton layout
-- **Unlocked**: Full detail visible, "Start Workout" CTA
-- **Locked**: Full detail visible but "Unlock with TabataFit+" CTA replaces start button
-
----
-
-## 7. Program Detail Screen
-
-Multi-week training program overview with per-week workout breakdown.
-
-**Route**: `program/[id]`
-
-### Elements
-- **Header**: Program icon, title, subtitle (e.g., "4 weeks · 12 workouts")
-- **Description**: Program summary text
-- **Stats card**: 3 stats — Weeks, Workouts, Total Minutes
-- **Tags**: Equipment required (e.g., Dumbbells, Mat) + Equipment optional + Focus areas (e.g., Arms, Core)
-- **Progress bar** (if started): Percentage complete with label
-- **Training plan**: Expandable week sections
- - Each week shows its workouts in order
- - Workout rows show: title, duration, completion checkmark (if done)
- - Current week has a "Current" badge
- - Future weeks may show lock icons (progressive unlock)
-
-### CTAs
-- **Start Program** (not started) → `player/[id]` (first workout)
-- **Continue Training** (in progress) → `player/[id]` (next incomplete workout)
-- **Restart** (completed) → resets progress, starts from week 1
-
-### States
-- **Not Started**: 0% progress, all weeks shown, "Start Program" CTA
-- **In Progress**: Progress bar filled, completed workouts checked, "Continue Training" CTA
-- **Completed**: 100% progress, all checked, "Restart" CTA
-
----
-
-## 8. Collection Detail Screen
-
-A curated group of workouts.
-
-**Route**: `collection/[id]`
-
-### Elements
-- **Header**: Collection title, description, workout count
-- **Workout list**: Vertical list of workout cards in the collection
- - Each card: thumbnail, title, trainer, duration, level
- - Lock icon for premium-gated workouts
-
-### Navigation
-- Tap workout → `workout/[id]`
-- Back button → previous screen
-
----
-
-## 9. Player Screen
-
-Full-screen workout execution with timer, video, audio, and Watch sync.
-
-**Route**: `player/[id]`
-
-### Layout
-- **Full-screen dark mode** — no tab bar, no status bar chrome
-- **Background**: Workout video (HLS streaming) or gradient fallback
-- **Phase-colored tint**: Background overlay changes color per phase (prep=orange, work=flame, rest=blue, complete=green)
-
-### Timer Section
-- **Timer ring**: Large circular progress indicator, fills as phase progresses
-- **Phase label**: PREP / WORK / REST / COMPLETE (color-coded)
-- **Countdown**: Large MM:SS timer (uses tabular-nums for alignment)
-- **Round indicator**: "Round 3 of 8" text
-
-### Exercise Info
-- **Current exercise name**: Large text
-- **Next exercise preview**: Smaller text ("Up next: Burpees")
-- **Coach encouragement**: Motivational text overlays (e.g., "Keep going!", "Almost there!")
-
-### Controls
-- **Start**: Begins the workout (shown before first start)
-- **Pause / Resume**: Toggle button during workout
-- **Stop**: Ends workout early (confirmation prompt)
-- **Skip**: Skip to next phase
-
-### Stats Overlay
-- **Calories**: Running calorie count
-- **Heart rate**: BPM from Apple Watch (if connected)
-- **Rounds**: Current / total
-
-### Burn Bar
-- Horizontal bar comparing user's current calorie burn vs. average for this workout
-- Updates in real-time
-
-### Now Playing Pill
-- Shows current music track name
-- Skip track button
-
-### Audio & Haptics
-- **Sound effects**: Phase start chime, 3-2-1 countdown beeps, workout complete fanfare
-- **Haptic feedback**: Phase transitions, countdown ticks, button presses
-- **Voice coaching**: Audio cues for exercises and encouragement
-- **Screen stays awake** (useKeepAwake)
-
-### Apple Watch Integration
-- Sends: workout state (phase, timer, exercise)
-- Receives: play/pause, skip, stop commands, heart rate data
-
-### Completion State
-- Timer ring shows 100%
-- Phase label: COMPLETE
-- Summary: Rounds completed, calories burned, total minutes
-- **Done** CTA → `complete/[id]`
-
-### States
-- **Ready**: Before starting — shows workout info, Start CTA
-- **Active**: Timer running, video playing, stats updating
-- **Paused**: Timer frozen, controls show Resume
-- **Complete**: Summary shown, Done CTA
-
----
-
-## 10. Workout Complete Screen
-
-Post-workout celebration and next steps.
-
-**Route**: `complete/[id]`
-
-### Elements
-- **Celebration animation**: Concentric emoji rings spinning (fire, muscle, lightning emojis)
-- **Stats grid**: 3 stats — Calories, Minutes, 100% completion
-- **Burn bar result**: Percentile comparison ("You burned more than 73% of users")
-- **Streak display**: Current streak count + subtitle ("Keep it going!")
-- **Share button**: Opens native share sheet with workout summary
-- **Recommended next workouts**: 3 horizontal workout cards
- - Tap → `workout/[id]`
-- **Back to Home** CTA → navigates to Home tab
-
-### Sync Consent Modal
-- Appears after first workout for premium users
-- Prompts to enable cross-device data sync
-- Accept / Decline buttons
-
----
-
-## 11. Paywall Screen
-
-Premium subscription purchase flow.
-
-**Route**: `paywall` (presented as modal)
-
-### Elements
-- **Header**: "TabataFit+" branding
-- **Features grid**: 6 premium feature cards with icons
- - Music during workouts
- - Unlimited workouts
- - Detailed stats
- - Calorie tracking
- - Smart reminders
- - No ads
-- **Plan selection**: Two radio-style options
- - Yearly: Price/year + "Save 50%" badge (highlighted as best value)
- - Monthly: Price/month
- - Prices fetched live from RevenueCat
-- **Subscribe CTA**: Gradient button, shows selected plan price
-- **Restore purchases**: Text link below CTA
-- **Terms**: Privacy policy + terms of service links
-- **Close button**: X in top corner to dismiss
-
-### States
-- **Loading**: Skeleton while fetching prices from RevenueCat
-- **Ready**: Plans displayed with real prices
-- **Purchasing**: Loading spinner on CTA, inputs disabled
-- **Error**: Error message with retry
-- **Success**: Dismisses modal, unlocks premium features
-
----
-
-## 12. Explore Filters Sheet
-
-Filter modal for the Explore tab workout grid.
-
-**Route**: `explore-filters` (form sheet modal with grabber)
-
-### Elements
-- **Level filter chips**: All / Beginner / Intermediate / Advanced (single select)
-- **Equipment filter chips**: All / None / Dumbbells / Band / Mat (dynamic from data, single select)
-- **Apply**: Dismiss sheet, filters persist in shared store
-- **Clear**: Reset all filters to "All"
-
----
-
-## 13. Privacy Policy Screen
-
-Static content screen.
-
-**Route**: `privacy`
-
-### Elements
-- Privacy policy text content
-- Back navigation
-
----
-
-## Cross-Cutting Features
-
-### Premium Gating
-- Free users see all workouts but some are locked (lock icon overlay)
-- Tapping a locked workout's "Start" CTA redirects to `paywall`
-- Premium users have full access to all workouts, stats sync, and personalization
-
-### Internationalization (i18n)
-- All user-facing strings are translated via i18n system
-- Multi-language support throughout
-
-### Haptic Feedback
-- Configurable via Profile settings toggle
-- Triggered on: button presses, phase changes, countdown ticks, achievements
-
-### Analytics (PostHog)
-- Events tracked across all screens: screen views, button taps, workout starts/completions, purchases, onboarding steps
-
-### Dark / Light Mode
-- Full theme support — colors adapt to system appearance
-- Player screen is always dark mode regardless of system setting
-
-### Loading & Error States
-- Skeleton placeholders during data fetches
-- Error states with descriptive message + Retry button
-- Empty states with motivational messaging + CTAs
-
-### Animations
-- Onboarding: staggered card reveals, animated charts
-- Home: mascot animation
-- Player: timer ring fill, phase color transitions
-- Complete: spinning emoji celebration rings
-- Navigation: standard iOS push/pop + modal presentations
diff --git a/supabase/schema.sql b/supabase/schema.sql
index 312c915..551a784 100644
--- a/supabase/schema.sql
+++ b/supabase/schema.sql
@@ -1,3 +1,6 @@
+-- ⚠️ OBSOLÈTE — Ce fichier décrit l'ancien concept "TabataFit" (abandonné).
+-- Le schéma actif est dans supabase/migrations/001 → 006.
+-- Voir AGENTS.md pour la référence canonique.
-- ============================================================
-- TabataFit Supabase Schema
-- ============================================================
diff --git a/supabase/seed.sql b/supabase/seed.sql
index 4ff2a21..acb39c3 100644
--- a/supabase/seed.sql
+++ b/supabase/seed.sql
@@ -1,3 +1,5 @@
+-- ⚠️ OBSOLÈTE — Ce fichier date du concept "TabataFit" (abandonné).
+-- Le vrai seed est dans supabase/migrations/006_seed_workout_programs.sql.
-- ============================================================
-- TabataFit Seed Data
-- ============================================================
diff --git a/supabase/setup-admin.sql b/supabase/setup-admin.sql
index 3d0211c..a9aaf42 100644
--- a/supabase/setup-admin.sql
+++ b/supabase/setup-admin.sql
@@ -1,3 +1,5 @@
+-- ⚠️ PARTIELLEMENT OBSOLÈTE — Référence TabataFit.
+-- La fonction is_admin() reste valide pour admin_users.
-- ============================================================
-- Setup: Initial Admin User and Authentication
-- ============================================================