From 8f3b1b39e74b050d6d0b1e31683ea3708e54586e Mon Sep 17 00:00:00 2001 From: Samuel Bouchet Date: Thu, 16 Apr 2026 22:37:20 +0200 Subject: [PATCH] Document automation harness usage in CLAUDE.md --- CLAUDE.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 5eccbb3..be847be 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,3 +30,74 @@ Tout `Control` (ColorRect, Label…) a `MouseFilter = Stop` par defaut. Quand un ### Plans Les fichiers de plan doivent etre rediges a la racine du workspace (ex: `/workspace/PLAN_juice.md`), **pas** dans `.claude/plans/` car ce dossier a une taille limitee. + +## Harnais d'automatisation (Claude peut jouer tout seul) + +Le jeu peut etre pilote de maniere autonome via le flag `--automation=`. Un +`AutomationHarness` (`Scripts/Automation/`) s'active alors comme noeud au root de la +scene, lit des commandes JSON dans `/inbox/`, ecrit les resultats dans +`/outbox/`, et place les captures d'ecran dans `/screens/`. Sans le flag, +comportement normal — overhead zero. + +Cote agent, un wrapper Python stdlib (`tools/automation/harness.py`) expose une API +simple. Godot attendu a `C:\Apps\godot\Godot_v4.6.2-stable_mono_win64_console.exe`. + +### Build + utilisation + +```bash +dotnet build Chessistics.csproj # compiler avant tout lancement +python tools/automation/smoke.py # smoke test end-to-end +python tools/automation/run_game.py # REPL interactif +``` + +### API Python + +```python +from tools.automation.harness import Harness + +with Harness.launch() as h: + h.load_mission("campaign_01", 0) # charge la campagne + mission 0 + state = h.state() # snapshot complet (dict) + h.screenshot("before") # -> .automation_runs//screens/before.png + h.place("Pawn", (0, 0), (0, 1)) # pose une piece + h.step() # un tour (auto-wait animation) + h.screenshot("after") + h.set_speed(0.1); h.play() # auto-play rapide +``` + +Methodes : `screenshot`, `state`, `select`, `place`, `click_cell`, `key`, `play`, +`pause`, `step`, `wait_idle`, `set_speed`, `load_mission`, `back_to_menu`, `quit`. + +Toutes les commandes non-query attendent `EventAnimator.IsAnimating == false` avant +de retourner -> appels en serie toujours vus par le prochain `state()`. + +### Validation visuelle par Claude + +Les PNG 1280x720 ecrites dans `.automation_runs//screens/` peuvent etre lues +directement par l'outil `Read` de Claude. Workflow type pour valider l'UI : + +1. `h.load_mission("campaign_01", N)` + `h.screenshot("mission_N_start")` +2. Lire le PNG -> verifier titre, flavor banner, board, panneau objectifs, stock +3. Placer des pieces via `h.place(...)` et re-screenshot +4. `h.step()` en boucle + screenshot a chaque etape +5. Attendre `phase == "MissionComplete"` dans le snapshot + +Cette boucle permet de valider que : +- Les demandes affichent les bons compteurs +- Les pieces bougent comme prevu +- Le stock se met a jour +- L'ecran `MissionComplete` apparait quand attendu + +### Details importants + +- `Place` passe par le signal `PlacementRequested` (meme chemin qu'un vrai clic) -- + ne pas appeler `GameSim.ProcessCommand(PlacePieceCommand)` directement dans le + dispatcher, ca mute deux fois. +- Les captures d'ecran sont prises apres `RenderingServer.frame_post_draw` -> le + frame reflete l'etat final, animations incluses. +- La facade (`AutomationFacade`) est la **seule** surface exposee au dispatcher. + Elle ne touche que des methodes/signals publics de `GameSim`, `InputMapper`, + `EventAnimator`, `ControlBar`, `PieceStockPanel`. La separation black-box tient. +- Les fichiers IPC sont ecrits `.tmp` puis renommes (atomique sur Windows). +- La campagne se charge via `load_mission("campaign_01", 0)`. Passer a une mission + > 0 n'est pas supporte directement (il faut passer par `MissionComplete` reel).