Ajoute 10 blocs pour rendre les conditions composables (avant: chaînes
opaques tapées à la main) :
- Reporters: opCompare, opBool, opNot, opArith, valVar, valScore,
valNumber, valText → sérialisés vers la grammaire d'expression existante
(ex: "score > 5", "(pct >= 60) and (lives > 0)")
- Contrôle: loopRepeat, loopWhile (nouveau kind IR "loop")
- logicIf/sceneBranch acceptent un reporter branché OU le champ texte
(rétrocompat totale)
Catalogue 41→51 blocs, catégories Opérateurs + Contrôle. Compilateur
gateway (_reporter_to_expr) miroir du serializeReporter() TS. Hub
Blockly régénéré.
Validé: build atelier OK, 18 tests scenario-engine, round-trip
bloc→IR (reporters + loops + rétrocompat).
NB: le kind IR "loop" exige un support firmware runtime3 (à ajouter
dans une passe firmware) ; les conditions sont déjà évaluées par le
firmware existant.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Catégorie « Énigmes » dans le catalogue Blockly canonique :
zacus_scene (écran maître title/subtitle/symbol/effect),
zacus_puzzleQR et zacus_puzzleSound. L'export blocks_to_runtime3
les attache au step courant comme objets IR scene/puzzle (pas des
actions), avec clamping/troncature vers les limites strictes du
gateway pour que l'IR émis valide toujours. Copie hub régénérée
via sync_blockly_catalog.sh. 14 tests d'export ajoutés (60 verts).
The Atelier exposed a legacy 12-block gameplay-config language whose
export the gateway could not compile (no blocks_studio_version) — and
no start/end blocks. It now speaks the same language as the zacus-hub
native Studio: the 38-block scene catalog (sceneStart/sceneEnd, npcSay
voice lines, HW/ESP-NOW/M5/PLIP, logic) lives once in
@zacus/shared/blockly; the hub copy is GENERATED via
tools/dev/sync_blockly_catalog.sh.
- Export/import rewritten to blocks_studio_version: 2 (flat nodes,
next pointers, logicIf slots) via shared blocks-doc.ts — what
POST /v1/flash compiles to Runtime 3 IR, and what the hub Studio
reads/writes (full interop).
- « Zacus dit » gains voice (voice-bridge voice_ref), emotion and rate
fields; the compiler forwards them as optional tts_say fields
(omitted at defaults, backward compatible).
- Editor validation now mirrors compiler rules: missing sceneStart,
duplicate scene ids, unknown goto targets, empty voice lines.
Verified: tsc clean, vite build green, v2->IR round-trip OK
(entry STEP_intro, tts_say{voice_ref,emotion,rate}).
New multiplatform SwiftUI app under apps/zacus-hub/ generated via
XcodeGen (project.yml). Three modes share a HubSession actor that
talks to tools/zacus-gateway over Tailscale-only HTTP/WS.
Game-master: live state stream (WebSocket /v1/state/ws), backend
health badges, hint trigger, journal.
Companion: push-to-talk via AVAudioRecorder (M4A AAC 16 kHz),
fallback file picker, hint request, transcript via voice-bridge
proxy.
Studio: YAML editor with validate/save (existing /v1/studio
routes), plus a Scratch tab hosting a Blockly + zelos-renderer
workspace in WKWebView. 38 custom Zacus block types across 10
categories (Scènes, NPC, Audio, LCD, Hardware ESP32, ESP-NOW,
BOX-3, M5, PLIP, Logique), .sb3 export/import via JSZip (procedure
calls + embedded YAML for lossless round-trip), Flasher sheet that
calls /v1/flash/{board} with auto/hot/cold strategies and shows
per-board step results including the cold-flash idf.py command.
ATS exception domains cover the Tailscale CGNAT range plus the
electron-server / studio / macm1 hostnames so the WebView and
URLSession can hit plain HTTP on the tailnet without TLS.
Token stays in the Keychain (cc.saillant.zacus.hub) — never
committed to source.