diff --git a/Makefile b/Makefile
index 3883141..b4cd0cc 100644
--- a/Makefile
+++ b/Makefile
@@ -107,8 +107,6 @@ lint: ## Vérifie le style et les erreurs courantes
deploy: site ## Sert l'application sur le réseau local (Ctrl+C pour arrêter)
@ip="$$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{ for (i = 1; i < NF; i++) if ($$i == "src") print $$(i + 1) }')"; \
echo "Application : http://$${ip:-ADRESSE-DU-PC}:$(WEB_PORT)/"; \
- echo "Test du moteur : http://$${ip:-ADRESSE-DU-PC}:$(WEB_PORT)/moteur/"; \
- echo "Page de mesure : http://$${ip:-ADRESSE-DU-PC}:$(WEB_PORT)/moteur/bench.html"; \
echo "À ouvrir depuis le téléphone, sur le même Wi-Fi. Ctrl+C pour arrêter."
@docker run --rm --init -p $(WEB_PORT):8080 -v "$(CURDIR)/$(BUILD_DIR)/site:/site:ro" \
$(BUILD_C_IMAGE) python3 -m http.server 8080 --directory /site
@@ -123,7 +121,7 @@ SITE_ICONS := icone.svg icone-192.png icone-512.png icone-maskable-192.png icone
# Le site tel qu'il sera publié, reconstruit entièrement à chaque appel :
# - web/ à la racine : la page de l'application, son style, sa police, le
-# manifeste, le Web Worker du moteur, et les pages de test sous moteur/ ;
+# manifeste et le Web Worker du moteur ;
# - sous icons/, le logo et les icônes de la charte, copiés depuis
# docs/identite/logo/ (une seule source, ADR 0010) ;
# - l'application compilée (build/web/src/) sous app/ ;
diff --git a/docs/adr/0009-socle-pwa-typescript.md b/docs/adr/0009-socle-pwa-typescript.md
index c9cbed2..72bdfb4 100644
--- a/docs/adr/0009-socle-pwa-typescript.md
+++ b/docs/adr/0009-socle-pwa-typescript.md
@@ -68,3 +68,24 @@ vérification des dépendances.
standard ») est tenu même au niveau fort (2 plis) : c'est le niveau standard
de l'ordinateur à l'étape 0d.
- Firefox sur le téléphone reste à vérifier, sans bloquer.
+
+## Amendements
+
+### 2026-11-03 — Pages de test du moteur retirées du site
+
+Décidé par Pierre après son premier test sur le téléphone : « supprimer la
+partie test du moteur totalement ».
+
+- Les pages de test et de mesure de l'étape 0b (`web/moteur/` : `index.html`,
+ `bench.html` et leurs scripts) sont supprimées. Le site publié n'a plus rien
+ sous `/moteur/`, ni dans le cache du service worker ; `make deploy`
+ n'annonce plus que l'application, et l'aide ne renvoie plus vers le test du
+ moteur.
+- Les mesures du Fairphone 4 ci-dessus, faites avec `bench.html`, restent la
+ référence. Pour les refaire, la mesure se lance sous Node sur le PC
+ (`make bench`) : son code partagé est déplacé de `web/moteur/benchmark.mjs`
+ vers `engine-wasm/benchmark.mjs`. Une mesure sur le téléphone demanderait de
+ remettre une page de mesure, à décider le moment venu.
+- Le moteur reste vérifié par la suite de contrat sur WebAssembly
+ (`make test`) et, dans l'application, par la partie jouée dans un navigateur
+ (`make test-browser`).
diff --git a/docs/deploiement.md b/docs/deploiement.md
index ea30cc3..13b27b2 100644
--- a/docs/deploiement.md
+++ b/docs/deploiement.md
@@ -2,8 +2,8 @@
Ustagammon est un site statique (PWA, ADR 0009) : des fichiers HTML,
JavaScript, le moteur en WebAssembly et ses données. L'application est à la
-racine ; les pages de test du moteur de l'étape 0b restent publiées sous
-`/moteur/` (test du moteur) et `/moteur/bench.html` (mesure). Il est publié sur
+racine ; les pages de test du moteur de l'étape 0b ont été retirées (ADR
+0009, amendement du 2026-11-03). Il est publié sur
CapRover, machine `sans-pub` (https://captain.cloud.sans.pub), app
`ustagammon`, sur https://ustagammon.sans.pub.
@@ -112,8 +112,7 @@ ssh sans.pub 'sudo docker service ps srv-captain--ustagammon --format "{{.Image}
```
Puis ouvrir le site sur le téléphone : le plateau s'affiche et une consigne
-remplace « Chargement du moteur… ». La page de test du moteur
-(https://ustagammon.sans.pub/moteur/) doit afficher « Moteur prêt ».
+remplace « Chargement du moteur… ».
## Retour arrière
diff --git a/engine-wasm/bench.mjs b/engine-wasm/bench.mjs
index f45b59c..a414894 100644
--- a/engine-wasm/bench.mjs
+++ b/engine-wasm/bench.mjs
@@ -1,4 +1,4 @@
-// bench.mjs -- la mesure de la page bench.html, sous Node, sur le PC
+// bench.mjs -- mesure du moteur WebAssembly sous Node, sur le PC
// (`make bench`). Premier ordre de grandeur seulement : le chiffre qui compte
// est celui du téléphone.
//
@@ -10,7 +10,7 @@ import os from "node:os";
import { fileURLToPath } from "node:url";
import { gzipSync } from "node:zlib";
import createEngineModule from "../build/wasm/engine.mjs";
-import { DOWNLOADED_FILES, formatReport, measureTimes } from "../web/moteur/benchmark.mjs";
+import { DOWNLOADED_FILES, formatReport, measureTimes } from "./benchmark.mjs";
import { commands, loadEngine } from "../web/engine-wasm.mjs";
const root = new URL("../", import.meta.url);
diff --git a/web/moteur/benchmark.mjs b/engine-wasm/benchmark.mjs
similarity index 91%
rename from web/moteur/benchmark.mjs
rename to engine-wasm/benchmark.mjs
index b9c3348..213e877 100644
--- a/web/moteur/benchmark.mjs
+++ b/engine-wasm/benchmark.mjs
@@ -1,5 +1,7 @@
-// benchmark.mjs -- mesure du moteur WebAssembly, partagée par la page de
-// mesure (bench.html, dans le navigateur) et `make bench` (sous Node).
+// benchmark.mjs -- mesure du moteur WebAssembly sous Node, pour `make bench`
+// (engine-wasm/bench.mjs). Elle servait aussi à la page de mesure du site,
+// retirée avec les pages de test du moteur (ADR 0009, amendement du
+// 2026-11-03).
//
// Copyright (C) 2026 les auteurs d'Ustagammon.
// Licence : GPLv3 ou ultérieure (voir LICENSE).
@@ -20,13 +22,12 @@ export const TIME_THRESHOLDS = [
// Taille totale à télécharger, compressée : moins de 40 Mo.
export const DOWNLOAD_LIMIT_BYTES = 40e6;
-// Fichiers téléchargés pour faire tourner le moteur dans la page de test,
-// chemins relatifs à la racine du site (web/ ; wasm/ est build/wasm/).
+// Fichiers téléchargés pour faire tourner le moteur dans l'application
+// (hors code de l'application elle-même, quelques dizaines de Ko), chemins
+// relatifs à la racine du site (web/ ; wasm/ est build/wasm/).
export const DOWNLOADED_FILES = [
- "moteur/index.html",
- "moteur/style.css",
- "moteur/page.mjs",
- "moteur/engine-client.mjs",
+ "index.html",
+ "app.css",
"engine-worker.mjs",
"engine-wasm.mjs",
"wasm/engine.mjs",
diff --git a/tests/test_site.sh b/tests/test_site.sh
index ff3b846..774c058 100755
--- a/tests/test_site.sh
+++ b/tests/test_site.sh
@@ -1,8 +1,9 @@
#!/usr/bin/env bash
# Vérifie l'image de production (deploy/) avec le site assemblé (make package) :
# construit l'image en local, la lance, et contrôle ce que reçoit un
-# navigateur (application, pages de test du moteur, aide, manifeste, service
-# worker, types MIME, compression, politique de sécurité, version).
+# navigateur (application, aide, manifeste, service worker, types MIME,
+# compression, politique de sécurité, version), et l'absence des anciennes
+# pages de test du moteur.
set -euo pipefail
cd "$(dirname "$0")/.."
@@ -71,10 +72,12 @@ check "wasm/engine.mjs" "text/javascript"
check "wasm/engine.wasm" "application/wasm"
check "wasm/engine.data" "application/octet-stream"
check "version.json" "application/json"
-# Pages de test du moteur (étape 0b).
-check "moteur/" "text/html"
-check "moteur/bench.html" "text/html"
-check "moteur/engine-client.mjs" "text/javascript"
+# Les pages de test du moteur (étape 0b) sont retirées (ADR 0009,
+# amendement du 2026-11-03) : plus rien sous /moteur/.
+[ ! -e build/site/moteur ] || report "build/site/moteur/ existe encore"
+for gone in moteur/ moteur/bench.html; do
+ curl -s -o /dev/null -w "%{http_code}" "$base/$gone" | grep -qx 404 || report "/$gone : 404 attendu"
+done
# Aide : copies du glossaire et des scénarios (ADR 0008).
check "docs/scenarios/jouer-une-partie.feature" "text/plain"
check "docs/glossaire/README.md" "text/markdown"
@@ -94,15 +97,16 @@ done < <(grep -o '"src": "[^"]*"' <<<"$manifest" | sed 's/"src": "\(.*\)"/\1/')
# Le service worker met en cache chaque fichier du site, avec une version.
sw="$(curl -s "$base/sw.js")"
grep -qE '^const VERSION = "[0-9a-f]{16}";' <<<"$sw" || report "sw.js : version absente"
-for file in ./ index.html app/main.js wasm/engine.data wasm/engine.wasm moteur/ \
+for file in ./ index.html app/main.js wasm/engine.data wasm/engine.wasm \
docs/glossaire/videau.md version.json fonts/AlegreyaSans-Bold.woff2 icons/favicon.svg; do
grep -qF " \"$file\"," <<<"$sw" || report "sw.js : $file absent de la liste à mettre en cache"
done
listed="$(grep -c '^ "' <<<"$sw")"
present="$(find build/site -type f ! -name sw.js | wc -l)"
-# Chaque fichier, plus « ./ » et « moteur/ » pour les deux index.html.
-[ "$listed" -eq "$((present + 2))" ] \
- || report "sw.js liste $listed adresses pour $present fichiers (plus 2 dossiers)"
+# Chaque fichier, plus « ./ » pour index.html.
+[ "$listed" -eq "$((present + 1))" ] \
+ || report "sw.js liste $listed adresses pour $present fichiers (plus « ./ »)"
+grep -q '"moteur/' <<<"$sw" && report "sw.js met encore en cache des pages de test du moteur"
grep -o '^ "[^"]*"' <<<"$sw" | tr -d ' "' | while read -r file; do
curl -sf -o /dev/null "$base/$file" || echo "sw.js : $file introuvable sur le site"
done | grep . && report "sw.js liste des fichiers introuvables"
diff --git a/web/moteur/bench-page.mjs b/web/moteur/bench-page.mjs
deleted file mode 100644
index f6a47c1..0000000
--- a/web/moteur/bench-page.mjs
+++ /dev/null
@@ -1,98 +0,0 @@
-// bench-page.mjs -- page de mesure (bench.html) : chronomètre le moteur
-// dans un Web Worker et produit le rapport à copier.
-//
-// Copyright (C) 2026 les auteurs d'Ustagammon.
-// Licence : GPLv3 ou ultérieure (voir LICENSE).
-
-import { DOWNLOADED_FILES, DOWNLOAD_LIMIT_BYTES, formatReport, measureTimes, summarize }
- from "./benchmark.mjs";
-import { startEngine } from "./engine-client.mjs";
-
-const $ = (id) => document.getElementById(id);
-
-// Taille d'un fichier du site, brute et compressée gzip (comme le ferait un
-// serveur qui compresse ses réponses).
-// name est relatif à la racine du site, un dossier au-dessus de cette page.
-async function fileSize(name) {
- const blob = await (await fetch("../" + name, { cache: "no-store" })).blob();
- const gzipped = blob.stream().pipeThrough(new CompressionStream("gzip"));
- const gzipBytes = (await new Response(gzipped).arrayBuffer()).byteLength;
- return { name, bytes: blob.size, gzipBytes };
-}
-
-function addRow(cells) {
- const row = $("table").insertRow();
- for (const text of cells) {
- row.insertCell().textContent = text;
- }
-}
-
-async function measure() {
- $("start").disabled = true;
- $("results").hidden = true;
- $("table").replaceChildren();
-
- $("status").textContent = "Chargement du moteur…";
- const start = performance.now();
- const engine = startEngine();
- await engine.ready;
- const loadMs = performance.now() - start;
-
- const { positions } = await (await fetch("../wasm/positions.json")).json();
- let memoryBytes = 0;
- const times = await measureTimes({
- bestMove: (...args) => engine.bestMove(...args).then(keepMemory),
- cubeDecision: (...args) => engine.cubeDecision(...args).then(keepMemory),
- }, positions, (done, total) => {
- $("status").textContent = "Calcul " + done + " sur " + total + "…";
- });
- function keepMemory(answer) {
- memoryBytes = answer.memoryBytes;
- return answer;
- }
-
- $("status").textContent = "Mesure de la taille à télécharger…";
- const files = await Promise.all(DOWNLOADED_FILES.map(fileSize));
-
- for (const s of summarize(times)) {
- addRow([s.label, Math.round(s.medianMs) + " ms", Math.round(s.maxMs) + " ms",
- s.limitMs + " ms", s.ok ? "OK" : "dépassé"]);
- }
- const gzipTotal = files.reduce((sum, f) => sum + f.gzipBytes, 0);
- addRow(["Taille compressée", "", (gzipTotal / 1e6).toFixed(1).replace(".", ",") + " Mo",
- DOWNLOAD_LIMIT_BYTES / 1e6 + " Mo", gzipTotal < DOWNLOAD_LIMIT_BYTES ? "OK" : "dépassé"]);
-
- $("report").value = formatReport({
- environment: navigator.userAgent, files, loadMs, memoryBytes, times,
- });
- $("results").hidden = false;
- $("status").textContent = "Mesure terminée.";
-}
-
-// Copie dans le presse-papiers. L'API moderne n'existe que sur les pages
-// sécurisées (https ou localhost) : sur le réseau local en http, on
-// sélectionne le texte et on utilise l'ancienne commande de copie.
-async function copyReport() {
- try {
- if (navigator.clipboard) {
- await navigator.clipboard.writeText($("report").value);
- } else {
- $("report").select();
- if (!document.execCommand("copy")) {
- throw new Error();
- }
- }
- $("copy-status").textContent = "Rapport copié : collez-le dans la conversation.";
- } catch {
- $("report").select();
- $("copy-status").textContent = "Copie impossible : le texte est sélectionné, "
- + "copiez-le à la main (appui long, puis Copier).";
- }
-}
-
-$("start").onclick = () => measure().catch((error) => {
- $("status").textContent = "La mesure a échoué : " + error.message;
- $("status").classList.add("error");
- $("start").disabled = false;
-});
-$("copy").onclick = copyReport;
diff --git a/web/moteur/bench.html b/web/moteur/bench.html
deleted file mode 100644
index ca4d92a..0000000
--- a/web/moteur/bench.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-Ustagammon : mesure du moteur
-
-
-
-
-
-
Mesure du moteur
-
Cette page chronomètre le moteur sur les positions de référence : meilleur coup
- aux niveaux rapide et fort, décision de videau au niveau fort. Elle mesure aussi
- la taille à télécharger et la mémoire utilisée. Comptez une à quelques minutes ;
- gardez l'écran allumé et la page au premier plan.