Jusqu'ici, l'application ne gardait qu'une partie : son journal d'événements, sous une seule clé localStorage. Commencer une nouvelle partie effaçait l'ancienne, et les branches créées par « Rejouer d'ici » n'étaient visibles nulle part.
L'étape 1 a besoin de bien plus :
l'historique des parties, pour le bilan, l'analyse et la progression (1e, 1h) ;
la reprise d'une partie précise, pour le « Reprendre l'ancienne » de la révision UX ;
un moyen d'analyser ses parties dans GNU Backgammon de bureau.
Le plan docs/plans/2026-11-03-parties-enregistrees.md (sous-étape 1b) fixait ces objectifs. Il est supprimé dans cette MR.
Quoi
Toutes les parties restent sur l'appareil, finies ou en cours, chacune avec toutes ses branches.
Au démarrage, la partie en cours est reprise.
Une ligne « Mes parties » dans le menu en feuille donne la liste des parties. On peut :
reprendre une partie, ou l'une de ses branches, sans rechargement ;
l'exporter en SGF ;
la supprimer, en deux touchers et sans boîte du navigateur.
L'export SGF contient toutes les branches, en variantes, avec la branche courante en premier.
« Reprendre l'ancienne » relit maintenant l'ancienne partie dans le stockage et supprime la nouvelle, restée vide.
La partie enregistrée par les versions précédentes est migrée sans intervention.
Sans IndexedDB, l'app se replie sur localStorage, puis sur la mémoire.
Comment
Le travail a été délégué à un sous-agent, en deux temps : d'abord le stockage et le domaine, puis le branchement sur la révision UX une fois celle-ci fusionnée.
Stockage : l'interface GameLibrary (list, load, save, remove, current, setCurrent) s'appuie sur deux stockages :
IndexedDB, utilisé directement : base « ustagammon » version 1, avec trois magasins (games, journals, settings). Le résumé et le journal d'une partie sont écrits dans la même transaction ;
localStorage en repli.
Les opérations s'exécutent dans l'ordre des appels. GameSession tient la partie affichée et sait reprendre l'ancienne. Le stockage s'ouvre pendant le chargement du moteur : le plateau s'affiche toujours avant le moteur.
Domaine : branches(journal) lit les feuilles de l'arbre d'événements, déjà en place. summarizeGame résume une partie. exportSgf écrit le SGF avec les conventions de sgf.c de gnubg. Le moteur ne sert qu'à décoder une position de départ particulière.
Vérification de l'export : 6 parties jouées sur le vrai moteur, soit 9 fichiers SGF, sont relues par le gnubg de bureau de référence (Docker). Après chaque coup, la position de gnubg doit égaler celle du journal. Un coup altéré ou une position altérée font bien échouer la vérification.
Interface : games-view.ts n'appelle ni le stockage ni le moteur ; dependency-cruiser le vérifie.
ADR 0007 amendé : le schéma IndexedDB et les clés localStorage deviennent des formats durables, comme le journal. Toute modification passe par une migration testée.
Vérification par la session principale, après fusion de main :
make lint : aucun problème ;
make test : 10/10, dont 20 scénarios Gherkin et la relecture des SGF par gnubg.
L'agent a lancé make test-browser sur son dernier code, avant la fusion de main, qui n'apportait que de la documentation. Il passe dans Chromium et Firefox :
« nouvelle partie puis Reprendre l'ancienne : journal identique » ;
« mes parties : 3 parties listées, SGF exporté, première partie reprise sans rechargement » ;
aucune boîte native, aucune erreur.
Choix et compromis
Pas de bibliothèque IndexedDB (idb, Dexie), donc aucune nouvelle dépendance. En contrepartie, le stockage IndexedDB n'est testé que dans un vrai navigateur ; la logique commune est testée sous Node.
Branche courante en premier dans le SGF : gnubg 1.08 ne lit que la première variante (« FIXME restore other variations » dans sgf.c). Les autres branches sont dans le fichier, mais gnubg les ignore.
Sauvegardes non attendues : fermer la page dans les millisecondes qui suivent une action peut perdre cette action.
Pas de score de match avant 1c ; le résultat de la partie en tient lieu.
Identifiants : date plus hasard. crypto.randomUUID n'existe pas en http, que sert make deploy.
Risques et déploiement
Migration à sens unique : l'ancienne clé localStorage est effacée une fois la partie importée. Si l'on revient à la version précédente, elle commence une partie neuve ; les parties restent dans IndexedDB.
Changement de schéma : modifier le schéma demandera une montée de version avec migration (ADR 0007 amendé).
Configuration : aucune configuration serveur.
Retour arrière : annuler la fusion.
Comment vérifier
make lint && make test # relecture des SGF par gnubg dans tests/test_web.sh
make test-browser # ligne « mes parties : ... »
ls build/sgf-samples/
Sur le téléphone :
Jouer quelques coups.
Ouvrir Menu, puis « Nouvelle partie ».
Ouvrir Menu, puis « Mes parties » : les deux parties y sont.
Reprendre la première, puis exporter un SGF.
Ouvrir le SGF dans GNU Backgammon de bureau : load game fichier.sgf.
Hors périmètre
L'adresse #/parties (0e.4).
L'écran d'analyse et « Rejouer d'ici » depuis l'analyse (1e).
## Pourquoi
Jusqu'ici, l'application ne gardait qu'une partie : son journal d'événements, sous une seule clé `localStorage`. Commencer une nouvelle partie effaçait l'ancienne, et les branches créées par « Rejouer d'ici » n'étaient visibles nulle part.
L'étape 1 a besoin de bien plus :
- l'historique des parties, pour le bilan, l'analyse et la progression (1e, 1h) ;
- la reprise d'une partie précise, pour le « Reprendre l'ancienne » de la révision UX ;
- un moyen d'analyser ses parties dans GNU Backgammon de bureau.
Le plan `docs/plans/2026-11-03-parties-enregistrees.md` (sous-étape 1b) fixait ces objectifs. Il est supprimé dans cette MR.
## Quoi
- **Toutes les parties restent sur l'appareil**, finies ou en cours, chacune avec toutes ses branches.
- **Au démarrage, la partie en cours est reprise.**
- **Une ligne « Mes parties » dans le menu en feuille** donne la liste des parties. On peut :
- reprendre une partie, ou l'une de ses branches, sans rechargement ;
- l'exporter en SGF ;
- la supprimer, en deux touchers et sans boîte du navigateur.
- **L'export SGF contient toutes les branches**, en variantes, avec la branche courante en premier.
- **« Reprendre l'ancienne »** relit maintenant l'ancienne partie dans le stockage et supprime la nouvelle, restée vide.
- **La partie enregistrée par les versions précédentes est migrée** sans intervention.
- **Sans IndexedDB**, l'app se replie sur `localStorage`, puis sur la mémoire.
## Comment
Le travail a été délégué à un sous-agent, en deux temps : d'abord le stockage et le domaine, puis le branchement sur la révision UX une fois celle-ci fusionnée.
- **Stockage** : l'interface `GameLibrary` (list, load, save, remove, current, setCurrent) s'appuie sur deux stockages :
- IndexedDB, utilisé directement : base « ustagammon » version 1, avec trois magasins (`games`, `journals`, `settings`). Le résumé et le journal d'une partie sont écrits dans la même transaction ;
- `localStorage` en repli.
Les opérations s'exécutent dans l'ordre des appels. `GameSession` tient la partie affichée et sait reprendre l'ancienne. Le stockage s'ouvre pendant le chargement du moteur : le plateau s'affiche toujours avant le moteur.
- **Domaine** : `branches(journal)` lit les feuilles de l'arbre d'événements, déjà en place. `summarizeGame` résume une partie. `exportSgf` écrit le SGF avec les conventions de `sgf.c` de gnubg. Le moteur ne sert qu'à décoder une position de départ particulière.
- **Vérification de l'export** : 6 parties jouées sur le vrai moteur, soit 9 fichiers SGF, sont relues par le gnubg de bureau de référence (Docker). Après chaque coup, la position de gnubg doit égaler celle du journal. Un coup altéré ou une position altérée font bien échouer la vérification.
- **Interface** : `games-view.ts` n'appelle ni le stockage ni le moteur ; dependency-cruiser le vérifie.
- **ADR 0007 amendé** : le schéma IndexedDB et les clés `localStorage` deviennent des formats durables, comme le journal. Toute modification passe par une migration testée.
Vérification par la session principale, après fusion de `main` :
- `make lint` : aucun problème ;
- `make test` : 10/10, dont 20 scénarios Gherkin et la relecture des SGF par gnubg.
L'agent a lancé `make test-browser` sur son dernier code, avant la fusion de `main`, qui n'apportait que de la documentation. Il passe dans Chromium et Firefox :
- « nouvelle partie puis Reprendre l'ancienne : journal identique » ;
- « mes parties : 3 parties listées, SGF exporté, première partie reprise sans rechargement » ;
- aucune boîte native, aucune erreur.
## Choix et compromis
- **Pas de bibliothèque IndexedDB** (idb, Dexie), donc aucune nouvelle dépendance. En contrepartie, le stockage IndexedDB n'est testé que dans un vrai navigateur ; la logique commune est testée sous Node.
- **Branche courante en premier dans le SGF** : gnubg 1.08 ne lit que la première variante (« FIXME restore other variations » dans sgf.c). Les autres branches sont dans le fichier, mais gnubg les ignore.
- **Sauvegardes non attendues** : fermer la page dans les millisecondes qui suivent une action peut perdre cette action.
- **Pas de score de match** avant 1c ; le résultat de la partie en tient lieu.
- **Identifiants** : date plus hasard. `crypto.randomUUID` n'existe pas en http, que sert `make deploy`.
## Risques et déploiement
- **Migration à sens unique** : l'ancienne clé `localStorage` est effacée une fois la partie importée. Si l'on revient à la version précédente, elle commence une partie neuve ; les parties restent dans IndexedDB.
- **Changement de schéma** : modifier le schéma demandera une montée de version avec migration (ADR 0007 amendé).
- **Configuration** : aucune configuration serveur.
- **Retour arrière** : annuler la fusion.
## Comment vérifier
```
make lint && make test # relecture des SGF par gnubg dans tests/test_web.sh
make test-browser # ligne « mes parties : ... »
ls build/sgf-samples/
```
Sur le téléphone :
1. Jouer quelques coups.
2. Ouvrir Menu, puis « Nouvelle partie ».
3. Ouvrir Menu, puis « Mes parties » : les deux parties y sont.
4. Reprendre la première, puis exporter un SGF.
5. Ouvrir le SGF dans GNU Backgammon de bureau : `load game fichier.sgf`.
## Hors périmètre
- L'adresse `#/parties` (0e.4).
- L'écran d'analyse et « Rejouer d'ici » depuis l'analyse (1e).
- Le score de match (1c).
- L'historique de progression (1h).
- L'import de SGF.
Generated with Claude Code https://claude.com/claude-code
« Reprendre l'ancienne » relit l'ancienne partie dans le stockage par son
identifiant et supprime la nouvelle (GameSession).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Pourquoi
Jusqu'ici, l'application ne gardait qu'une partie : son journal d'événements, sous une seule clé
localStorage. Commencer une nouvelle partie effaçait l'ancienne, et les branches créées par « Rejouer d'ici » n'étaient visibles nulle part.L'étape 1 a besoin de bien plus :
Le plan
docs/plans/2026-11-03-parties-enregistrees.md(sous-étape 1b) fixait ces objectifs. Il est supprimé dans cette MR.Quoi
localStorage, puis sur la mémoire.Comment
Le travail a été délégué à un sous-agent, en deux temps : d'abord le stockage et le domaine, puis le branchement sur la révision UX une fois celle-ci fusionnée.
Stockage : l'interface
GameLibrary(list, load, save, remove, current, setCurrent) s'appuie sur deux stockages :games,journals,settings). Le résumé et le journal d'une partie sont écrits dans la même transaction ;localStorageen repli.Les opérations s'exécutent dans l'ordre des appels.
GameSessiontient la partie affichée et sait reprendre l'ancienne. Le stockage s'ouvre pendant le chargement du moteur : le plateau s'affiche toujours avant le moteur.Domaine :
branches(journal)lit les feuilles de l'arbre d'événements, déjà en place.summarizeGamerésume une partie.exportSgfécrit le SGF avec les conventions desgf.cde gnubg. Le moteur ne sert qu'à décoder une position de départ particulière.Vérification de l'export : 6 parties jouées sur le vrai moteur, soit 9 fichiers SGF, sont relues par le gnubg de bureau de référence (Docker). Après chaque coup, la position de gnubg doit égaler celle du journal. Un coup altéré ou une position altérée font bien échouer la vérification.
Interface :
games-view.tsn'appelle ni le stockage ni le moteur ; dependency-cruiser le vérifie.ADR 0007 amendé : le schéma IndexedDB et les clés
localStoragedeviennent des formats durables, comme le journal. Toute modification passe par une migration testée.Vérification par la session principale, après fusion de
main:make lint: aucun problème ;make test: 10/10, dont 20 scénarios Gherkin et la relecture des SGF par gnubg.L'agent a lancé
make test-browsersur son dernier code, avant la fusion demain, qui n'apportait que de la documentation. Il passe dans Chromium et Firefox :Choix et compromis
crypto.randomUUIDn'existe pas en http, que sertmake deploy.Risques et déploiement
localStorageest effacée une fois la partie importée. Si l'on revient à la version précédente, elle commence une partie neuve ; les parties restent dans IndexedDB.Comment vérifier
Sur le téléphone :
load game fichier.sgf.Hors périmètre
#/parties(0e.4).Generated with Claude Code https://claude.com/claude-code