docs(specs): plan phasé — édition & génération d'assets depuis l'Atelier
Repo State / repo-state (push) Failing after 27s
Validate Zacus refactor / validate (push) Successful in 10m55s

Plan de projet (P0–P5) pour éditer/générer écran, audio et fichiers SD/NFS
depuis l'Atelier web, avec ponts firmware et génération assistée
(gateway.ailiance.fr pour le texte). Inclut l'audit du pipeline d'assets
existant, dépendances entre phases, risques, et chemin web/firmware séparés.

NB: la fondation firmware audio (P4 : playback WAV/MP3, montage SD) est
désormais livrée côté ESP32_ZACUS — voir bump submodule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
clement
2026-06-13 16:46:13 +02:00
parent 3e75632486
commit e806fc9634
@@ -0,0 +1,135 @@
# Plan — Édition & génération d'assets depuis l'Atelier (écran, audio, fichiers SD/NFS)
> Statut : **PLAN** (aucun code écrit). Rédigé le 2026-06-13.
> Objectif produit : depuis l'Atelier web, **éditer et générer tous les assets**
> d'un scénario (textes d'écran, audio, images, fichiers data) et les
> **déployer sur le firmware** (LittleFS aujourd'hui, SD/NFS demain), avec
> génération assistée par `gateway.ailiance.fr` (LLM) et les générateurs
> audio/image existants.
## 1. Pourquoi ce document
La demande (« mettre à jour l'atelier pour tout éditer : écran, audio, fichiers
NFS/SD ; montage web ; ponts firmware↔atelier ; génération d'assets via l'atelier
et gateway.ailiance.fr ») couvre **5 chantiers** qui touchent 4 systèmes
(atelier React, gateway FastAPI, firmware ESP-IDF, gateway LLM externe). C'est un
projet **multi-semaines**. Ce plan le décompose en phases livrables, ordonnées par
dépendance et risque, pour exécuter sans tout casser.
## 2. État réel constaté (audit 2026-06-13)
| Domaine | Ce qui existe | Ce qui MANQUE |
|---|---|---|
| **Scénario** | YAML → `compile_runtime3.py` → IR JSON ; hot-load `POST /game/scenario` | — |
| **Écran** | `scene{title,subtitle,symbol,effect}` dans l'IR → `display_ui` (LCD **texte+symbole**) | **Aucune image** : `picture/` existe mais n'est jamais lu par le firmware |
| **Audio** | TTS pool (Piper `:8001`, **F5-TTS** voice-bridge `:8200`), ambiances AudioCraft ; manifests `hotline_tts/manifest.json` | Pas d'éditeur web ; pas de génération à la demande depuis l'atelier |
| **Images** | Printables PNG via OpenAI Images (`tools/printables/`) | Pas embarquées firmware ; pas d'éditeur web |
| **Stockage firmware** | **LittleFS 5 Mo** (partition `storage`), monté `/littlefs` ; `scenario.json` (≤64 Ko), `hotline_tts/`, `music/`, `picture/`, `recorder/` | **Aucun SD ni NFS** — n'existe pas dans le firmware. Plafond 5 Mo strict. Reformaté à chaque flash. |
| **Pont web↔firmware** | gateway `/v1/flash` (hot POST / cold staging / ESP-NOW relay), `/v1/studio`, `/v1/share` (neuf) | Pas de `/v1/assets/*` (génération, staging, sync) |
| **Génération** | Scripts offline Python (TTS, printables, ambiances) | Pas d'orchestration web ; pas de file async (gen > 20 s) |
| **gateway.ailiance.fr** | `ailiance-gateway` : **LLM texte** (chat/completions, embeddings, responses, ~30 modèles). OpenAI-compatible. | Aucune intégration. **Ne fait PAS** d'image ni d'audio. |
### Conséquences cadrantes
- **« Fichiers sur NFS et SD »** et **« images à l'écran »** = **développement firmware** (partitions, montage SD SPI/SDMMC, client NFS, décodage image LovyanGFX). Nécessitent la **carte en main** et des tests hardware. À isoler en fin de parcours.
- **`gateway.ailiance.fr` génère du TEXTE** : dialogues NPC, indices, textes/titres d'écran, descriptions, variations de scénario. Images/audio restent sur les générateurs dédiés (OpenAI Images, F5-TTS, AudioCraft).
- Tout le reste (éditeurs web, génération de texte, wiring des générateurs audio existants, staging LittleFS) se fait **côté web/gateway sans risque firmware**.
## 3. Architecture cible (vue d'ensemble)
```
Atelier (React) ── panneau « Assets »
│ éditer (textes écran, dialogues, indices, refs audio/image)
│ générer (texte → ailiance ; audio → voice-bridge ; image → OpenAI)
Gateway (FastAPI :8400) ── /v1/assets/*
├─ /text/generate → proxy gateway.ailiance.fr (LLM)
├─ /audio/generate → voice-bridge F5 / AudioCraft (ASYNC, file de tâches)
├─ /image/generate → OpenAI Images (ASYNC)
├─ /manifest → CRUD manifest d'assets (versionné)
└─ /stage → préparer le bundle d'assets pour un board
Déploiement
├─ hot : POST /game/scenario (+ assets inline si petits)
├─ cold : staging dans cold_data_dir → flash
├─ SD/NFS: (Phase 4) sync vers /sd ou /nfs du firmware
└─ relay : ESP-NOW vers peers
Firmware (ESP-IDF) ── media_manager + display_ui (+ sd_nfs en Phase 4)
```
## 4. Phases (ordonnées par dépendance et risque)
### Phase 0 — Fondations & contrats *(spec, pas de code applicatif)*
- **Modèle d'asset** unifié : `{id, type(text|audio|image|data), scope(scenario|board|global), source, manifest_ref, version}`.
- **Schéma de manifest versionné** (généralise `hotline_tts/manifest.json`), avec hash de contenu + provenance (générateur, prompt, modèle).
- **Contrat de référence d'asset dans l'IR** : étendre `specs/ZACUS_RUNTIME_3_SPEC.md` (comment un step/scene référence un asset par id, résolu au déploiement).
- **Décision stockage** : budget LittleFS 5 Mo vs SD/NFS — politique « quel asset va où ».
- Livrable : `specs/ZACUS_ASSET_SPEC.md`.
- Dépend de : rien. **Bloque** tout le reste.
### Phase 1 — Génération de TEXTE via ailiance *(web-only, risque nul)*
- Gateway : `POST /v1/assets/text/generate` (proxy `gateway.ailiance.fr/v1/chat/completions`, modèle paramétrable, prompts templatés : réplique NPC, indice progressif, texte d'écran, variation de scénario). Auth ailiance à câbler (clé en settings).
- Atelier : panneau « Générer » — sélection du type, contexte (puzzle/scène courant), aperçu, insertion dans `npc_phrases.yaml` / `hints_adaptive.yaml` / le bloc `scene`.
- Livrable : éditeur+générateur de texte opérationnel sur `zacus.saillant.cc/atelier`.
- Dépend de : Phase 0 (modèle d'asset minimal).
### Phase 2 — Pipeline AUDIO *(web wiring + file async)*
- Gateway : file de tâches async (génération > 20 s) + `POST /v1/assets/audio/generate` (TTS F5 via voice-bridge `:8200` ; ambiances AudioCraft), `GET /v1/assets/audio/{id}/status`, `GET /v1/_staged/{key}` (preview).
- Atelier : panneau Audio — lister (manifest), prévisualiser (lecteur), (re)générer une réplique/ambiance, voir le statut.
- Déploiement : staging dans `hotline_tts/` (LittleFS) via le flux flash existant.
- Dépend de : Phase 0, Phase 1 (UI panneau), file async (commune).
### Phase 3 — Éditeur ÉCRAN *(web maintenant ; image = firmware plus tard)*
- **3a (web)** : éditeur de scène dans l'atelier — `title/subtitle/symbol/effect` avec **aperçu fidèle** du rendu LCD (limites de caractères, symboles, effets). Génération de textes d'écran via ailiance.
- **3b (firmware, hardware)** : support **image** à l'écran — décodage PNG/RGB565 dans `display_ui` (LovyanGFX), lecture depuis LittleFS `picture/`, budget partition. *Nécessite la carte + tests.* À planifier séparément.
- Dépend de : Phase 0 ; 3b dépend de Phase 4 si les images dépassent 5 Mo.
### Phase 4 — Stockage SD / NFS *(firmware lourd, hardware, RISQUE ÉLEVÉ)*
- **Firmware** : montage carte **SD** (SDMMC/SPI) + client **NFS** optionnel au boot ; structure `/sd/zacus/{board_id}/` ; fallback LittleFS ; endpoint `POST /assets/sync` (pull depuis gateway).
- **Partitions** : revoir `partitions.csv` (la SD soulage le plafond 5 Mo).
- **Gateway** : `POST /v1/assets/stage` produit un bundle SD/NFS par board ; sync.
- **Tests** : sur carte réelle uniquement.
- Dépend de : Phase 0 (contrat), accès hardware. **C'est le gros morceau** — à ne lancer qu'avec la carte et du temps de test.
### Phase 5 — Atelier « Assets » unifié + montage web *(intégration)*
- Workspace Assets cohérent (onglets texte/audio/image/data), manifest versionné visible, rollback.
- Flux de déploiement : choisir quels assets vont sur quel board, par quel canal (hot/cold/SD/relay).
- Multi-board : assets board-spécifiques (aujourd'hui un seul `/littlefs/scenario.json` master).
- Dépend de : Phases 14.
## 5. Dépendances (résumé)
```
P0 (contrats) ─┬─> P1 (texte/ailiance) ─┐
├─> P2 (audio) ──────────┼─> P5 (atelier unifié)
├─> P3a (écran web) ─────┤
└─> P4 (SD/NFS firmware) ┴─> P3b (image écran)
```
- **Chemin web sans firmware** : P0 → P1 → P2 → P3a → P5 (livrable, faible risque).
- **Chemin firmware/hardware** : P4 (+P3b) — à mener en parallèle quand la carte est dispo.
## 6. Risques & points durs
1. **Firmware SD/NFS (P4)** : nécessite hardware, tests, possible révision partitions/boot. Risque élevé. Ne pas bloquer le web dessus.
2. **Plafond LittleFS 5 Mo** : tant que P4 n'est pas là, les assets audio/image embarqués sont contraints. Politique de budget à définir en P0.
3. **Génération async** : OpenAI/AudioCraft/F5 peuvent dépasser le timeout gateway (20 s). File de tâches obligatoire dès P2.
4. **`gateway.ailiance.fr`** : LLM texte uniquement ; auth (clé) à câbler ; pas d'images/audio — ne pas surpromettre.
5. **Pas de versioning d'assets** aujourd'hui : à introduire en P0 (manifest + hash) sinon rollback impossible.
6. **Images à l'écran (3b)** : le firmware ne sait pas afficher d'image — c'est un développement, pas un branchement.
## 7. Décisions ouvertes (à trancher avant P1)
- **Où stockent les assets générés ?** Repo `game/`/`audio/`/`assets/` (versionné git) vs store gateway (`share-store`-like) vs les deux ?
- **Clé/accès `gateway.ailiance.fr`** : quelle auth, quel(s) modèle(s) par type de texte ?
- **SD vs NFS** : carte SD locale (simple, robuste terrain) ou NFS (centralisé, besoin réseau fiable) — ou les deux avec fallback ?
- **Périmètre P1** : quels types de texte en priorité (dialogues NPC ? indices ? textes d'écran ?).
## 8. Recommandation de séquencement
1. **P0** (contrat asset + spec) — court, débloque tout.
2. **P1** (texte/ailiance) — première valeur visible, zéro risque firmware.
3. **P2** (audio) puis **P3a** (écran web).
4. **P4/P3b** (SD/NFS + image) — bloc firmware séparé, quand la carte et le temps de test sont là.
5. **P5** (unification) — quand les briques existent.
---
*Réf. : audit pipeline d'assets 2026-06-13 ; `specs/ZACUS_RUNTIME_3_SPEC.md` ;
`tools/zacus-gateway/main.py` ; `ESP32_ZACUS/idf_zacus/{partitions.csv,components/{display_ui,media_manager,game_endpoint}}` ;
`tools/{tts,audio,printables}/`. Voir aussi la barre de menu Atelier (PR #125).*