diff --git a/docs/feuille-de-route.md b/docs/feuille-de-route.md index 12f4f08..c63633b 100644 --- a/docs/feuille-de-route.md +++ b/docs/feuille-de-route.md @@ -10,11 +10,12 @@ Légende : 🔄 en cours · ⏳ à venir · ⏸ conditionnel ## Étape 0 — Prototype technique Acquis : socle du dépôt, organisation (ADR 0001, 0003, 0006), source du moteur -(ADR 0005 : gnubg officiel, commit 14b6798). +(ADR 0005 : gnubg officiel, commit 14b6798), gnubg de référence et 32 positions +de référence (0a.2), moteur embarqué et `engine-cli` (0a.3), comparaison +automatique aux références, tolérance 0,002 (0a.4). | Sous-étape | Contenu | État | Plan | | --- | --- | --- | --- | -| 0a.4 | `make test` compare `engine-cli` aux références | 🔄 | `plans/2026-11-02-comparaison-references.md` | | 0b | Moteur en WebAssembly, page de test dans un Web Worker, `make deploy-web`, `make bench` | ⏳ | | | Mesures | Pierre relève les mesures sur le Fairphone 4 | ⏳ | | | Décision | Socle PWA ou Android natif, consigné dans un ADR — validation de Pierre | ⏳ | | diff --git a/docs/plans/2026-11-02-comparaison-references.md b/docs/plans/2026-11-02-comparaison-references.md deleted file mode 100644 index 4dc2aec..0000000 --- a/docs/plans/2026-11-02-comparaison-references.md +++ /dev/null @@ -1,120 +0,0 @@ -# Comparer le moteur embarqué aux références de gnubg de bureau - -- **Date** : 2026-11-02 -- **Étape** : 0a.4 -- **Statut** : terminé -- **Exécutant** : sous-agent general-purpose, dans un worktree isolé - -## Objectif - -`make test` vérifie automatiquement que le moteur embarqué (`build/engine-cli`) -retrouve les résultats de gnubg de bureau sur les 32 positions de -`tests/reference/`, aux niveaux 0 et 2 plis, avec une tolérance mesurée et -justifiée. - -## Consignes - -1. **Sortie d'`engine-cli` alignée sur le contrat** de - `tests/reference/README.md` : une sous-commande (par exemple - `engine-cli reference [dés]`, ou une option) produit, - pour une position et un niveau, un objet de même structure que la partie - `plies[""]` d'un fichier de résultat (`evaluation`, `moves` ou `cube`). - Le classement des coups suit exactement la méthode de la commande `hint` de - gnubg (documentée dans le README du format) : nombre de coups, notation, - pli réel de chaque coup. Garder `engine-cli` simple : réutiliser les - fonctions d'`engine.h`, compléter `engine.h` si nécessaire. -2. **Comparateur** : un script lisible (Python 3 ou shell avec `jq`) qui, pour - chaque position et chaque niveau, appelle `engine-cli`, compare au résultat - de référence et affiche un rapport clair (position, niveau, champ, valeur - attendue, valeur obtenue, écart). Il tourne **dans Docker** (ajouter ce qu'il - faut à `docker/build-c/Dockerfile` et changer l'étiquette de l'image dans le - `Makefile`), jamais avec les outils du PC (ADR 0004). -3. **Critères de concordance** : - - même nombre de coups légaux ; - - même meilleur coup, sauf si gnubg lui-même sépare les deux premiers coups - de moins que la tolérance (cas d'égalité : le dire dans le rapport) ; - - même pli réel du meilleur coup ; - - équités et probabilités à la tolérance près, pour les coups communs ; - - même décision de videau, et équités du videau à la tolérance près. -4. **Tolérance mesurée, pas devinée** : mesurer l'écart maximal observé sur - les 32 positions, l'expliquer (gnubg de bureau en SSE2 avec `-ffast-math`, - moteur embarqué en C générique), et mesurer aussi l'écart d'un build du - moteur sans `-ffast-math`. Fixer la tolérance avec une marge raisonnable et - la justifier dans `tests/reference/README.md`. -5. **`tests/test_engine_reference.sh`**, lancé par `make test` : lance - `make engine` si nécessaire puis le comparateur ; échoue avec le rapport si - un critère n'est pas tenu. -6. **`tests/test_reference.sh`** n'utilise plus `jq` sur le PC : passer par - l'image Docker de la chaîne C (ADR 0004), et mettre `CREDITS.md` à jour. - -Contraintes : -- respecter `CLAUDE.md` et les ADR 0004, 0005 et 0007 : simplicité, identifiants - en anglais, commentaires en français, aucune installation hors Docker, - `-j2` ; -- ne pas modifier les références (`tests/reference/results/`) ni les fichiers - de `engine/gnubg/` ; si une divergence vient d'un vrai défaut du moteur - embarqué, corriger dans `engine/compat/` ou `engine/src`, et le dire ; -- ne rien masquer : si une position ne concorde pas, le rapport doit le - montrer, avec la cause trouvée ou les hypothèses ; -- `make lint` et `make test` doivent passer ; commits petits, en français, avec - la ligne `Co-Authored-By: Claude Opus 5.5 ` ; -- ne pas pousser ni créer de merge request. - -Rapport attendu : ce qui a été fait, la tolérance retenue et sa justification -(écarts mesurés avec et sans `-ffast-math`), les éventuelles divergences et -leur cause, les commandes de vérification. - -## Critères de réussite - -- `make test` compare les 32 positions aux deux niveaux et passe. -- La tolérance est documentée et justifiée par des mesures. -- Une divergence volontairement introduite (par exemple une référence - modifiée dans une copie) fait échouer le test avec un rapport lisible. - -## Résultat - -Terminé le 2026-11-02, branche `comparaison-travail`. `make lint` et -`make test` passent (7/7) ; les 32 positions concordent aux deux niveaux -avec la tolérance retenue, sans aucune égalité de meilleur coup à signaler. - -**Fait.** - -- `engine-cli --ply N reference POSITION_ID MATCH_ID [DÉS]` produit un niveau - au format de `tests/reference/` (`evaluation`, puis `moves` ou `cube`). - Nombres écrits avec 9 chiffres significatifs (float32 exact). -- `tests/reference/compare.py` (Python 3) et `tests/test_engine_reference.sh` - (lancé par `make test`) : comparaison dans l'image `ustagammon/build-c:2`, - qui reçoit Python 3 et jq. `tests/test_reference.sh` se relance dans cette - image : plus de jq sur le PC. `CREDITS.md` à jour. -- Critères, tolérance et mesures documentés dans `tests/reference/README.md`. - -**Défauts du moteur embarqué trouvés et corrigés** (`engine/engine.c`) : - -- en match, l'équité des coups classés était convertie deux fois par - `mwc2eq` (`ScoreMove` la convertit déjà) ; -- `engine_best_moves` n'appliquait pas tout `hint` : `fAnalyse` était faux - et `RefreshMoveList` absent (classement par niveau d'évaluation, puis - départage des égalités). - -Changements d'interface : `engine_cube` gagne `optimal` et `decision_text` ; -`decision` prend le nom de l'énumération de gnubg (`DOUBLE_TAKE`…), comme -les références (`tests/test_engine.sh` adapté). - -**Tolérance : 0,002**, sur probabilités et équités. Mesures sur 2 598 -nombres : écart maximal 9,5e-4 et 99 % des écarts sous 1,6e-4, que le moteur -soit compilé avec ou sans `-ffast-math` (les deux builds diffèrent entre eux -de 1,1e-6 au plus). La cause est la sigmoïde de gnubg de bureau en SSE2 avec -`-ffast-math`, qui calcule `1/x` par `_mm_rcp_ps` (environ 12 bits) ; preuve : -le moteur compilé en SSE2 pour l'essai redonne les références au bit près. -L'écart maximal vient d'un seul coup (`opening-64-match`, 2 plis, `8/2 6/2`), -où l'écart de 1e-4 fait basculer un choix discret de la recherche. - -**Critère de divergence vérifié** : sur une copie de `results/` avec une -équité décalée de 0,01, un nombre de coups légaux, une décision de videau et -un meilleur coup modifiés, `compare.py --results ` échoue avec un -tableau de 10 écarts lisibles. - -**Suites possibles** : mesurer de même sur téléphone (NEON, autre -approximation de la division) ; envisager un build SSE2 d'`engine-cli` sur PC -si l'on veut une concordance au bit près (non retenu : le moteur de -l'application tournera en C générique ou en NEON).