docs: cadrage initial Storytime (specs par jalon, roadmap, CLAUDE.md)
Lecteur d'histoires cadenassé pour le coucher (Android/Flutter). - CLAUDE.md : principes craftsmanship/TDD/clean code/clean archi + decisions techniques - ROADMAP.md : suivi haut niveau des 7 jalons, a tenir a jour par etape - docs/specs/ : specs completes decoupees par jalon, etapes en sous-fichiers - .gitignore Flutter (pubspec.lock versionne, projet applicatif) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# 6.1 — Domaine des limites
|
||||
|
||||
## Objectif
|
||||
Modéliser les limites de coucher (minuterie + nombre d'histoires) et la logique
|
||||
qui décide quand avertir et quand arrêter, indépendamment de l'UI.
|
||||
|
||||
## Périmètre & hors-périmètre
|
||||
- Inclus : configuration des limites, compteurs, calcul des seuils d'avertissement et d'arrêt, reset quotidien, persistance des réglages + compteurs.
|
||||
- Exclus : affichage des avertissements (6.2), écran de fin (6.3).
|
||||
|
||||
## Dépendances
|
||||
2.x (événements de lecture : histoire démarrée, position/temps), Jalon 0.
|
||||
|
||||
## Conception
|
||||
- **Domain** (`features/limits/domain/`) :
|
||||
- `LimitSettings` (value object) : `timerEnabled`, `timerDuration?`, `storyCountEnabled`, `maxStories?`.
|
||||
- `SessionCounters` : `elapsed` (Duration), `storiesPlayed` (int), `day` (date du compteur, pour le reset).
|
||||
- `LimitStatus` (résultat de décision) : `ok`, `warnTimeSoon`, `warnLastStory`, `reached`.
|
||||
- `LimitEvaluator` (service de domaine pur) : `LimitStatus evaluate(LimitSettings, SessionCounters)` — applique les seuils (ex. avertissement minuterie à T-5 min ; « dernière histoire » quand `storiesPlayed == maxStories - 1`).
|
||||
- `LimitsRepository` (interface) : `get/saveSettings`, `get/saveCounters`, reset si le jour a changé.
|
||||
- **Application** :
|
||||
- `GetLimitSettingsUseCase`, `SaveLimitSettingsUseCase`.
|
||||
- `RegisterStoryStartedUseCase` (incrémente le compteur + reset si nouveau jour).
|
||||
- `TickElapsedUseCase` / `EvaluateLimitsUseCase` (renvoie `LimitStatus`).
|
||||
- **Data** : `PrefsLimitsRepository` via `shared_preferences` (réglages + compteurs + date du jour). Reset : si la date stockée ≠ aujourd'hui, compteurs remis à zéro à la lecture.
|
||||
|
||||
## Plan TDD
|
||||
1. **Red** : `limit_evaluator_test.dart` — table de cas : minuterie désactivée → toujours `ok` jusqu'au compteur d'histoires ; T-5 min → `warnTimeSoon` ; temps atteint → `reached` ; `storiesPlayed == max-1` → `warnLastStory` ; `== max` → `reached`. Les deux limites combinées : la plus restrictive gagne.
|
||||
2. **Green** : implémenter `LimitEvaluator` (logique pure).
|
||||
3. **Red** : `register_story_started_use_case_test.dart` — incrémente ; si nouveau jour, repart de 0.
|
||||
4. **Green** : implémenter.
|
||||
5. **Red** : `prefs_limits_repository_test.dart` — sauvegarde/relecture des réglages et compteurs ; reset au changement de date (date injectée, pas `DateTime.now()` direct → horloge injectable).
|
||||
6. **Green** : implémenter le repo + horloge injectable.
|
||||
7. **Refactor**.
|
||||
|
||||
## Definition of Done
|
||||
- Tests évaluateur (table de cas) + use cases + repo verts.
|
||||
- Logique de décision sans dépendance Flutter.
|
||||
- `tool/check.sh` passe ; étape 6.1 cochée dans `ROADMAP.md`.
|
||||
|
||||
## Risques / notes
|
||||
- Injecter une `Clock` (interface) pour tester le reset quotidien sans dépendre de l'heure réelle.
|
||||
- Le seuil d'avertissement minuterie (5 min) est une constante nommée, ajustable.
|
||||
@@ -0,0 +1,36 @@
|
||||
# 6.2 — Avertissements doux
|
||||
|
||||
## Objectif
|
||||
Prévenir l'enfant en douceur, **en amont** de l'échéance, sans interrompre l'écoute :
|
||||
« Encore 5 minutes 🌙 », « C'est la dernière histoire ⭐ ».
|
||||
|
||||
## Périmètre & hors-périmètre
|
||||
- Inclus : observation de `LimitStatus`, affichage non bloquant des avertissements, anti-répétition.
|
||||
- Exclus : l'arrêt et l'écran de fin (6.3).
|
||||
|
||||
## Dépendances
|
||||
6.1 (`LimitEvaluator`, `LimitStatus`), 2.x (lecture en cours), 4.x (espace enfant).
|
||||
|
||||
## Conception
|
||||
- **Presentation** (`features/limits/presentation/`) :
|
||||
- `LimitsController` (Riverpod) : combine les compteurs (temps via un tick périodique, histoires via les événements de lecture) et appelle `EvaluateLimitsUseCase` → expose `LimitStatus`.
|
||||
- Sur transition vers `warnTimeSoon` / `warnLastStory` : afficher un overlay/snackbar doux (texte + emoji), **non bloquant**, qui se referme seul. La lecture continue.
|
||||
- **Anti-répétition** : chaque avertissement ne s'affiche qu'une fois par session/seuil (mémoriser le dernier `LimitStatus` notifié).
|
||||
- Ton et style : doux, rassurant, cohérent avec le thème coucher (0.3).
|
||||
- Le tick de temps : un timer léger qui met à jour `elapsed` et réévalue ; s'arrête quand la lecture est en pause.
|
||||
|
||||
## Plan TDD
|
||||
1. **Red** : `limits_controller_test.dart` — séquence d'états simulés : passage à `warnTimeSoon` déclenche **une** notification ; rester en `warnTimeSoon` ne la re-déclenche pas ; `warnLastStory` notifie une fois.
|
||||
2. **Green** : implémenter le contrôleur + anti-répétition.
|
||||
3. **Red** : `warning_overlay_test.dart` (widget) — sur `warnTimeSoon`, le texte « Encore 5 minutes » apparaît puis disparaît ; la lecture n'est pas interrompue (le lecteur reste monté/actif).
|
||||
4. **Green** : implémenter l'overlay.
|
||||
5. **Refactor**.
|
||||
|
||||
## Definition of Done
|
||||
- Tests contrôleur (anti-répétition) + widget verts.
|
||||
- Démo : les avertissements apparaissent au bon moment, une seule fois, sans couper le son.
|
||||
- `tool/check.sh` passe ; étape 6.2 cochée dans `ROADMAP.md`.
|
||||
|
||||
## Risques / notes
|
||||
- Le timer doit se mettre en pause avec la lecture pour ne pas avertir/arrêter à tort pendant une pause.
|
||||
- Textes des messages = constantes nommées (faciles à ajuster / traduire plus tard).
|
||||
@@ -0,0 +1,39 @@
|
||||
# 6.3 — Écran de fin & reprise parent
|
||||
|
||||
## Objectif
|
||||
À l'atteinte d'une limite, arrêter la lecture et afficher un écran apaisant
|
||||
« C'est fini pour ce soir 🌙 », l'app restant épinglée ; seule la saisie du code
|
||||
parental permet de reprendre.
|
||||
|
||||
## Périmètre & hors-périmètre
|
||||
- Inclus : réaction à `LimitStatus.reached` (stop lecture + écran de fin), verrouillage de la reprise derrière le code parental.
|
||||
- Exclus : la logique de décision (6.1) et les avertissements (6.2).
|
||||
|
||||
## Dépendances
|
||||
6.1, 6.2, 2.x (arrêt lecture), 1.x (épinglage maintenu), 5.x (vérification du code).
|
||||
|
||||
## Conception
|
||||
- **Presentation** :
|
||||
- Quand `LimitsController` passe à `reached` : appeler l'arrêt de lecture (`PauseStoryUseCase`/stop) puis afficher `BedtimeOverEndView` (plein écran, doux, étoiles/lune).
|
||||
- L'app **reste épinglée** ; l'écran de fin ne propose aucune sortie système.
|
||||
- **Reprise** : un bouton discret « Parent » → `ParentGateView` (J5). Code correct → réinitialise/lève la limite pour la session (ou ouvre l'espace parent pour ajuster les réglages) ; code incorrect → reste sur l'écran de fin.
|
||||
- Décision à figer : reprendre annule-t-il la limite du soir, ou ré-autorise-t-il une histoire de plus ? → documenter le comportement choisi.
|
||||
- Cohérence avec le reset quotidien (6.1) : le lendemain, compteurs repartis de zéro.
|
||||
|
||||
## Plan TDD
|
||||
1. **Red** : `end_session_flow_test.dart` (contrôleur) — transition vers `reached` → appel d'arrêt de lecture + signal d'affichage de l'écran de fin.
|
||||
2. **Green** : implémenter la réaction.
|
||||
3. **Red** : `bedtime_over_end_view_test.dart` (widget) — l'écran de fin s'affiche ; le bouton « Parent » ouvre la porte ; code correct → reprise selon comportement documenté ; incorrect → reste bloqué.
|
||||
4. **Green** : implémenter l'écran + câblage avec la porte parentale.
|
||||
5. **Validation manuelle** : sur appareil, atteindre une limite (régler un court délai) → lecture stoppée, écran de fin, reprise uniquement par code, app non quittable.
|
||||
6. **Refactor**.
|
||||
|
||||
## Definition of Done
|
||||
- Tests flux de fin + écran + reprise verts.
|
||||
- Démo manuelle complète consignée (limite atteinte → fin → reprise parent).
|
||||
- Comportement de reprise documenté.
|
||||
- `tool/check.sh` passe ; étape 6.3 cochée dans `ROADMAP.md`.
|
||||
|
||||
## Risques / notes
|
||||
- S'assurer que l'écran de fin ne laisse aucune faille de navigation vers le système.
|
||||
- Bien gérer le cas « les deux limites » : la première atteinte déclenche la fin.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Jalon 6 — Limites, avertissements & fin de session
|
||||
|
||||
## Objectif
|
||||
Permettre au parent de fixer des limites de coucher (minuterie **et** nombre
|
||||
d'histoires), prévenir l'enfant en douceur avant l'échéance, puis arrêter la
|
||||
lecture sur un écran apaisant que seul le parent peut lever.
|
||||
|
||||
## Périmètre
|
||||
- Réglages parent : activer/désactiver minuterie (X min) et nombre d'histoires (X), indépendamment.
|
||||
- Compteurs : temps écoulé + histoires jouées, **reset automatique chaque jour**.
|
||||
- Avertissements doux **en amont** : « Encore 5 minutes 🌙 », « C'est la dernière histoire ⭐ ».
|
||||
- À l'atteinte : arrêt de la lecture + écran « C'est fini pour ce soir 🌙 », app toujours épinglée, reprise uniquement par le parent (code).
|
||||
|
||||
## Hors-périmètre
|
||||
- Planning par jour de la semaine, horaires : exclu v1 (limites simples).
|
||||
|
||||
## Étapes
|
||||
1. [6.1 — Domaine des limites](01-domaine-limites.md)
|
||||
2. [6.2 — Avertissements doux](02-avertissements.md)
|
||||
3. [6.3 — Écran de fin & reprise parent](03-fin-session.md)
|
||||
|
||||
## Definition of Done (jalon)
|
||||
- Le parent configure les deux types de limites depuis l'espace parent (J5).
|
||||
- Les avertissements s'affichent en amont, sans interrompre.
|
||||
- À l'échéance, la lecture s'arrête, l'écran de fin s'affiche, et seul le code parental permet de reprendre.
|
||||
- Les compteurs se remettent à zéro chaque jour.
|
||||
- `tool/check.sh` passe ; `ROADMAP.md` 6.1→6.3 cochées.
|
||||
Reference in New Issue
Block a user