Étape 0d.2 : plateau jouable en PWA hors ligne, aide intégrée #13

Merged
pierre merged 8 commits from plateau-ui into main 2026-11-03 00:02:39 +00:00
Owner

Pourquoi

Dernière brique de l'étape 0 (docs/etape-0.md, 0d) : un plateau minimal sur lequel on joue une partie complète contre l'ordinateur, au toucher, sur le Fairphone 4. Le critère de fin de l'étape est « une partie complète jouée sur le Fairphone 4, moins de 2 s par coup de l'IA en niveau standard, tous les tests au vert ». Le domaine existe depuis la MR !11, et le socle est la PWA (ADR 0009) ; il manquait l'interface, l'installation et le hors ligne.

Quoi

  • Plateau jouable (app/src/ui/, TypeScript sans framework) :
    • plateau SVG lisible en portrait (24 points, barre, pions sortis, dés, videau, compte de points) ;
    • saisie au toucher : le pion touché est entouré, et les cases d'arrivée possibles sont en surbrillance. Elles viennent des coups légaux du moteur, via le domaine. On peut annuler ;
    • boutons : lancer les dés, doubler, prendre, passer, nouvelle partie ;
    • le coup de l'ordinateur s'affiche avec son temps de calcul ;
    • la fin de partie donne le gagnant, simple, gammon ou backgammon, et les points ;
    • textes en français dans texts.ts, thème clair et sombre.
  • Assemblage dans app/src/main.ts, seul fichier autorisé à tout importer. Le moteur tourne dans un Web Worker. Les règles dependency-cruiser sont étendues.
  • Reprise automatique de la partie après fermeture de la page : le journal d'événements est sauvegardé dans localStorage, derrière une petite interface de stockage. Le domaine sait reprendre une partie depuis son journal.
  • Aide intégrée (ADR 0008, source unique) : make site copie docs/glossaire/ et docs/scenarios/ dans le site, et la page d'aide (help.ts) les lit à l'exécution. Elle affiche 7 scénarios et 28 termes, sans aucune recopie.
  • PWA : manifeste, icônes provisoires et service worker. Le service worker met en cache les 71 adresses du site, dont les 8,7 Mo du moteur, pour le hors ligne. Sa clé de cache change à chaque version.
  • Site publié : l'application à la racine, les pages de prototype du moteur sous /moteur/. deploy/Caddyfile reçoit une politique de sécurité du contenu (CSP), compatible WebAssembly ('wasm-unsafe-eval') et sans unsafe-inline. tests/test_site.sh vérifie le manifeste, le service worker, l'aide et la CSP.
  • make test-browser, hors de make test car lent. Il joue une partie complète par l'interface dans Chromium et Firefox sans écran, et vérifie :
    • le videau dans les deux sens et la reprise après rechargement ;
    • l'aide et le hors ligne ;
    • zéro violation de la CSP, et le blocage d'un script en ligne ajouté exprès ;
    • l'absence d'erreur dans la page.
  • docs/guide-test-etape-0.md : nouvelle section « Étape 0d : jouer une partie sur le téléphone », pour la vérification finale avec Pierre.

Comment

Travail délégué à un sous-agent selon un plan écrit avant la délégation. Une coupure de quota l'a interrompu ; un agent de reprise l'a terminé dans le même espace de travail. Le plan est supprimé à la clôture et son résultat repris ici.

Deux vrais bugs trouvés et corrigés grâce au test dans les navigateurs, où ils apparaissaient par intermittence :

  1. Débordement de la pile du moteur WebAssembly (ae1ea54). Le callMain d'Emscripten laisse ses arguments sur la pile WebAssembly (64 Ko) sans jamais la vider. Après quelques centaines de commandes, soit en cours de partie, la pile débordait et corrompait la mémoire du moteur : blocage dans Firefox, plantage de l'onglet dans Chromium. Reproduit sous Node (« memory access out of bounds » vers la 460e commande). Chaque commande est maintenant encadrée par stackSave/stackRestore. Le test app/tests/engine-stack.test.ts envoie 3 000 commandes : il échoue sans la correction et passe avec. Ce bug aurait bloqué les parties sur le téléphone, et il touchait aussi les pages /moteur/, corrigées du même coup.
  2. Service worker en échec dans Chromium (9cc0e0c), dans 4 essais sur 5 : il téléchargeait les 8,7 Mo du moteur en même temps que le Worker. Il est maintenant enregistré une fois le moteur chargé, ce qui évite aussi de télécharger ces données deux fois à la première visite.

Vérification par la session principale :

  • make setup && make build && make lint && make test : 10/10. Les 7 scénarios Cucumber passent, et le domaine, l'interface, le moteur et l'assemblage sont sans violation d'architecture (30 modules) ;
  • make test-browser, relancé ici :
Chromium Firefox
Partie complète, backgammon, 33 coups de chaque côté complète, backgammon, 36 et 37 coups
Videau le joueur double, l'ordinateur prend doublé dans les deux sens
Reprise, aide, CSP, erreurs OK, OK, aucune violation, aucune erreur OK, OK, aucune violation, aucune erreur
Hors ligne page rechargée sans réseau depuis le cache cache rempli ; hors ligne non simulable sous Playwright
Tour de l'ordinateur le plus long (PC) 0,4 s 5,1 s

Choix et compromis

  • SVG et DOM, sans framework ni animation : un prototype jouable, pas le plateau soigné de l'étape 1. La palette est provisoire (bois, ivoire, un accent) ; l'identité définitive vient du travail en cours sur le brief créatif.
  • localStorage pour la reprise : suffisant pour une partie en cours. Le stockage des parties (IndexedDB, plusieurs parties, branches) viendra à l'étape 1, derrière la même interface.
  • Service worker enregistré après le chargement du moteur : un peu plus tard qu'au tout début, mais fiable.
  • make test-browser hors de make test : plusieurs minutes et une image de 3 Go. Il est à lancer avant chaque publication importante.
  • Le videau centré affiche 64, comme dans gnubg. C'est habituel pour un joueur, mais peut surprendre un débutant : à revoir avec le design.

Risques et déploiement

  • Nouvelle dépendance de test à valider par Pierre : Playwright 1.48.2 (Apache-2.0), image mcr.microsoft.com/playwright:v1.48.2-noble, utilisée uniquement par make test-browser. Rien n'est embarqué.
  • Firefox : sur ce PC, un tour de l'ordinateur atteint 5,1 s, contre 0,4 s sous Chromium. Sur le Fairphone, Chrome tient largement les 2 s (mesures de l'ADR 0009) ; Firefox sur le téléphone reste à mesurer.
  • Publication : après fusion, make deploy-prod remplace la page de test par l'application à la racine. Les pages de test restent sous /moteur/.
  • Thème sombre : les pions foncés sur les cases foncées restent lisibles grâce à leur contour, mais c'est le point faible de la palette provisoire.

Retour arrière : redéployer l'image précédente dans CapRover (onglet Deployment), ou annuler le commit de fusion.

Comment vérifier

git switch main && git pull
make setup && make build
make lint && make test
make test-browser      # quelques minutes

Puis, sur le téléphone, après publication : https://ustagammon.sans.pub, en suivant la section « Étape 0d » de docs/guide-test-etape-0.md.

Hors périmètre

  • La vérification finale sur le Fairphone avec Pierre, qui clôt l'étape 0.
  • Le design soigné, les animations, l'analyse de partie et les niveaux : étape 1.

Generated with Claude Code https://claude.com/claude-code

## Pourquoi Dernière brique de l'étape 0 (`docs/etape-0.md`, 0d) : un plateau minimal sur lequel on joue une partie complète contre l'ordinateur, au toucher, sur le Fairphone 4. Le critère de fin de l'étape est « une partie complète jouée sur le Fairphone 4, moins de 2 s par coup de l'IA en niveau standard, tous les tests au vert ». Le domaine existe depuis la MR !11, et le socle est la PWA (ADR 0009) ; il manquait l'interface, l'installation et le hors ligne. ## Quoi - **Plateau jouable** (`app/src/ui/`, TypeScript sans framework) : - plateau SVG lisible en portrait (24 points, barre, pions sortis, dés, videau, compte de points) ; - saisie au toucher : le pion touché est entouré, et les cases d'arrivée possibles sont en surbrillance. Elles viennent des coups légaux du moteur, via le domaine. On peut annuler ; - boutons : lancer les dés, doubler, prendre, passer, nouvelle partie ; - le coup de l'ordinateur s'affiche avec son temps de calcul ; - la fin de partie donne le gagnant, simple, gammon ou backgammon, et les points ; - textes en français dans `texts.ts`, thème clair et sombre. - **Assemblage dans `app/src/main.ts`**, seul fichier autorisé à tout importer. Le moteur tourne dans un Web Worker. Les règles dependency-cruiser sont étendues. - **Reprise automatique** de la partie après fermeture de la page : le journal d'événements est sauvegardé dans `localStorage`, derrière une petite interface de stockage. Le domaine sait reprendre une partie depuis son journal. - **Aide intégrée** (ADR 0008, source unique) : `make site` copie `docs/glossaire/` et `docs/scenarios/` dans le site, et la page d'aide (`help.ts`) les lit à l'exécution. Elle affiche 7 scénarios et 28 termes, sans aucune recopie. - **PWA** : manifeste, icônes provisoires et service worker. Le service worker met en cache les 71 adresses du site, dont les 8,7 Mo du moteur, pour le hors ligne. Sa clé de cache change à chaque version. - **Site publié** : l'application à la racine, les pages de prototype du moteur sous `/moteur/`. `deploy/Caddyfile` reçoit une politique de sécurité du contenu (CSP), compatible WebAssembly (`'wasm-unsafe-eval'`) et sans `unsafe-inline`. `tests/test_site.sh` vérifie le manifeste, le service worker, l'aide et la CSP. - **`make test-browser`**, hors de `make test` car lent. Il joue une partie complète par l'interface dans Chromium et Firefox sans écran, et vérifie : - le videau dans les deux sens et la reprise après rechargement ; - l'aide et le hors ligne ; - zéro violation de la CSP, et le blocage d'un script en ligne ajouté exprès ; - l'absence d'erreur dans la page. - **`docs/guide-test-etape-0.md`** : nouvelle section « Étape 0d : jouer une partie sur le téléphone », pour la vérification finale avec Pierre. ## Comment Travail délégué à un sous-agent selon un plan écrit avant la délégation. Une coupure de quota l'a interrompu ; un agent de reprise l'a terminé dans le même espace de travail. Le plan est supprimé à la clôture et son résultat repris ici. **Deux vrais bugs trouvés et corrigés** grâce au test dans les navigateurs, où ils apparaissaient par intermittence : 1. **Débordement de la pile du moteur WebAssembly** (ae1ea54). Le `callMain` d'Emscripten laisse ses arguments sur la pile WebAssembly (64 Ko) sans jamais la vider. Après quelques centaines de commandes, soit en cours de partie, la pile débordait et corrompait la mémoire du moteur : blocage dans Firefox, plantage de l'onglet dans Chromium. Reproduit sous Node (« memory access out of bounds » vers la 460e commande). Chaque commande est maintenant encadrée par `stackSave`/`stackRestore`. Le test `app/tests/engine-stack.test.ts` envoie 3 000 commandes : il échoue sans la correction et passe avec. Ce bug aurait bloqué les parties sur le téléphone, et il touchait aussi les pages `/moteur/`, corrigées du même coup. 2. **Service worker en échec dans Chromium** (9cc0e0c), dans 4 essais sur 5 : il téléchargeait les 8,7 Mo du moteur en même temps que le Worker. Il est maintenant enregistré une fois le moteur chargé, ce qui évite aussi de télécharger ces données deux fois à la première visite. Vérification par la session principale : - `make setup && make build && make lint && make test` : 10/10. Les 7 scénarios Cucumber passent, et le domaine, l'interface, le moteur et l'assemblage sont sans violation d'architecture (30 modules) ; - `make test-browser`, relancé ici : | | Chromium | Firefox | | --- | --- | --- | | Partie | complète, backgammon, 33 coups de chaque côté | complète, backgammon, 36 et 37 coups | | Videau | le joueur double, l'ordinateur prend | doublé dans les deux sens | | Reprise, aide, CSP, erreurs | OK, OK, aucune violation, aucune erreur | OK, OK, aucune violation, aucune erreur | | Hors ligne | page rechargée sans réseau depuis le cache | cache rempli ; hors ligne non simulable sous Playwright | | Tour de l'ordinateur le plus long (PC) | 0,4 s | 5,1 s | ## Choix et compromis - **SVG et DOM, sans framework ni animation** : un prototype jouable, pas le plateau soigné de l'étape 1. La palette est provisoire (bois, ivoire, un accent) ; l'identité définitive vient du travail en cours sur le brief créatif. - **`localStorage` pour la reprise** : suffisant pour une partie en cours. Le stockage des parties (IndexedDB, plusieurs parties, branches) viendra à l'étape 1, derrière la même interface. - **Service worker enregistré après le chargement du moteur** : un peu plus tard qu'au tout début, mais fiable. - **`make test-browser` hors de `make test`** : plusieurs minutes et une image de 3 Go. Il est à lancer avant chaque publication importante. - **Le videau centré affiche 64**, comme dans gnubg. C'est habituel pour un joueur, mais peut surprendre un débutant : à revoir avec le design. ## Risques et déploiement - **Nouvelle dépendance de test à valider par Pierre** : Playwright 1.48.2 (Apache-2.0), image `mcr.microsoft.com/playwright:v1.48.2-noble`, utilisée uniquement par `make test-browser`. Rien n'est embarqué. - **Firefox** : sur ce PC, un tour de l'ordinateur atteint 5,1 s, contre 0,4 s sous Chromium. Sur le Fairphone, Chrome tient largement les 2 s (mesures de l'ADR 0009) ; Firefox sur le téléphone reste à mesurer. - **Publication** : après fusion, `make deploy-prod` remplace la page de test par l'application à la racine. Les pages de test restent sous `/moteur/`. - **Thème sombre** : les pions foncés sur les cases foncées restent lisibles grâce à leur contour, mais c'est le point faible de la palette provisoire. Retour arrière : redéployer l'image précédente dans CapRover (onglet *Deployment*), ou annuler le commit de fusion. ## Comment vérifier ``` git switch main && git pull make setup && make build make lint && make test make test-browser # quelques minutes ``` Puis, sur le téléphone, après publication : https://ustagammon.sans.pub, en suivant la section « Étape 0d » de `docs/guide-test-etape-0.md`. ## Hors périmètre - La vérification finale sur le Fairphone avec Pierre, qui clôt l'étape 0. - Le design soigné, les animations, l'analyse de partie et les niveaux : étape 1. Generated with Claude Code https://claude.com/claude-code
pierre added 8 commits 2026-11-03 00:02:37 +00:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ce dont l'interface a besoin, sans règle réimplémentée : le plateau vu de
chaque camp, les demi-coups que le moteur accepte à la suite de ceux déjà
saisis, le droit de doubler selon le moteur, et la reprise d'une partie
depuis son journal enregistré. Les types du navigateur sont ajoutés à
l'application ; le domaine reste vérifié sans eux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L'application est à la racine du site : plateau en SVG, saisie au toucher
(pion puis case d'arrivée, proposées à partir du moteur), boutons du jet,
du videau et de nouvelle partie, coup de l'ordinateur affiché avec son
temps, fin de partie, reprise depuis localStorage, aide lue dans les
copies de docs/. Le moteur tourne dans le Web Worker existant ; main.ts
est le seul assembleur (nouvelles règles dependency-cruiser). Le service
worker met tout le site en cache, avec une empreinte du contenu comme
version. Les pages de test du moteur passent sous /moteur/. Politique de
sécurité du contenu dans le Caddyfile ; make test-browser joue une partie
dans Chromium et Firefox sans écran (Playwright, hors de make test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
callMain (Emscripten) copie les arguments sur la pile du WebAssembly
(64 Ko) sans les retirer. Pendant une partie dans le navigateur, le même
moteur reçoit des centaines de commandes : vers la 540e, la pile débordait
et corrompait la mémoire du moteur (moteur muet dans Firefox, onglet planté
dans Chromium, « memory access out of bounds » sous Node). Repéré par
make test-browser. stackSave et stackRestore sont exportés et encadrent
chaque commande ; un test en envoie 3000 à la suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dans Chromium, l'installation du service worker échouait (« Cache.add()
encountered a network error » sur wasm/engine.data) quand le Worker du
moteur téléchargeait les mêmes 8,7 Mo au même moment : l'application
n'était alors pas disponible hors ligne. Repéré par make test-browser,
reproduit dans quatre essais sur cinq sans ce changement, jamais avec. Évite aussi
de télécharger deux fois ces données à la première visite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
make test-browser vérifie maintenant la politique de sécurité dans
Chromium et Firefox : aucune violation pendant toute la partie, et un
script en ligne ajouté exprès est bloqué. Un blocage est diagnostiqué
(étape, capture, dernière commande du moteur, journal de la partie) au
lieu d'attendre sans fin. Firefox sous Playwright refuse toute navigation
hors ligne : on y vérifie le cache et le contrôle par le service worker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pierre merged commit f8b89a8c44 into main 2026-11-03 00:02:39 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: pierre/Ustagammon#13