From 4e131370ddab924f977d1bdfaa1df68047de15f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20SAILLANT?= <108685187+electron-rare@users.noreply.github.com> Date: Sun, 1 Mar 2026 13:16:26 +0100 Subject: [PATCH] chore(bundle): canonicalize v3 names and add runtime prepare artifacts --- .../runtime_prepare/DEFAULT.current.json | 1 + .../runtime_prepare/DEFAULT.from_bundle.json | 434 +++++++++++ .../runtime-default-summary.md | 73 ++ .../runtime_prepare/runtime-default.diff | 731 ++++++++++++++++++ .../CODEX_PROMPT.md | 52 ++ .../CONVERSATION_SUMMARY.md | 18 + .../zacus_conversation_bundle_v3/README.md | 32 + .../fsm_mermaid.md | 49 ++ .../scenario_canonical.yaml | 291 +++++++ .../scenario_promptable_template.yaml | 105 +++ .../scenario_runtime.json | 434 +++++++++++ .../zacus_v2.yaml | 172 +++++ 12 files changed, 2392 insertions(+) create mode 100644 artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.current.json create mode 100644 artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.from_bundle.json create mode 100644 artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default-summary.md create mode 100644 artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default.diff create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/CODEX_PROMPT.md create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/CONVERSATION_SUMMARY.md create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/README.md create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/fsm_mermaid.md create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_canonical.yaml create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_promptable_template.yaml create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_runtime.json create mode 100644 scenario-ai-coherence/zacus_conversation_bundle_v3/zacus_v2.yaml diff --git a/artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.current.json b/artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.current.json new file mode 100644 index 0000000..4c28b46 --- /dev/null +++ b/artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.current.json @@ -0,0 +1 @@ +{"app_bindings":[{"app":"AUDIO_PACK","config":null,"id":"APP_AUDIO"},{"app":"SCREEN_SCENE","config":null,"id":"APP_SCREEN"},{"app":"MP3_GATE","config":null,"id":"APP_GATE"},{"app":"WIFI_STACK","config":null,"id":"APP_WIFI"},{"app":"ESPNOW_STACK","config":null,"id":"APP_ESPNOW"},{"app":"QR_UNLOCK_APP","config":null,"id":"APP_QR_UNLOCK"}],"estimated_duration_s":0,"id":"DEFAULT","initial_step":"RTC_ESP_ETAPE1","steps":[{"actions":["ACTION_TRACE_STEP","ACTION_HW_LED_ALERT"],"apps":["APP_AUDIO","APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_U_SON_PROTO","step_id":"SCENE_U_SON_PROTO","transitions":[{"after_ms":0,"event_name":"ANY","event_type":"button","id":"TR_SCENE_U_SON_PROTO_2","priority":120,"target_step_id":"SCENE_LA_DETECTOR","trigger":"on_event"}]},{"actions":["ACTION_TRACE_STEP","ACTION_QUEUE_SONAR"],"apps":["APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_LA_DETECTOR","step_id":"SCENE_LA_DETECTOR","transitions":[{"after_ms":0,"event_name":"BTN_NEXT","event_type":"serial","id":"TR_SCENE_LA_DETECTOR_2","priority":110,"target_step_id":"RTC_ESP_ETAPE1","trigger":"on_event"}]},{"actions":["ACTION_TRACE_STEP","ACTION_HW_LED_ALERT","ACTION_QUEUE_SONAR","ACTION_ESP_NOW_WAITING"],"apps":["APP_AUDIO","APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_WIN_ETAPE","step_id":"RTC_ESP_ETAPE1","transitions":[{"id":"TR_RTC_ESP_ETAPE1_BTN","trigger":"on_event","event_type":"button","event_name":"ANY","target_step_id":"WIN_ETAPE1","after_ms":0,"priority":120}]},{"actions":["ACTION_TRACE_STEP","ACTION_HW_LED_ALERT"],"apps":["APP_AUDIO","APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"PACK_WIN","mp3_gate_open":false,"screen_scene_id":"SCENE_WIN_ETAPE1","step_id":"WIN_ETAPE1","transitions":[{"id":"TR_WIN_ETAPE1_TO_CREDIT","trigger":"on_event","event_type":"timer","event_name":"WIN_ETAPE1_TO_CREDIT","target_step_id":"SCENE_CREDIT","after_ms":60000,"priority":100}]},{"step_id":"SCENE_CREDIT","screen_scene_id":"SCENE_CREDITS","audio_pack_id":"","actions":["ACTION_TRACE_STEP","ACTION_HW_LED_ALERT"],"apps":["APP_AUDIO","APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"mp3_gate_open":false,"transitions":[{"id":"TR_SCENE_CREDIT_BTN","trigger":"on_event","event_type":"button","event_name":"ANY","target_step_id":"STEP_WARNING","after_ms":0,"priority":120}]},{"actions":["ACTION_TRACE_STEP","ACTION_HW_LED_ALERT"],"apps":["APP_AUDIO","APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_WARNING","step_id":"STEP_WARNING","transitions":[{"id":"TR_STEP_WARNING_1","trigger":"on_event","event_type":"audio_done","event_name":"AUDIO_DONE","target_step_id":"STEP_WARNING","after_ms":0,"priority":80}]},{"actions":["ACTION_TRACE_STEP","ACTION_QUEUE_SONAR"],"apps":["APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_LEFOU_DETECTOR","step_id":"SCENE_LEFOU_DETECTOR","transitions":[{"after_ms":0,"event_name":"ETAPE2_DUE","event_type":"timer","id":"TR_SCENE_LEFOU_DETECTOR_1","priority":100,"target_step_id":"STEP_WARNING","trigger":"on_event"},{"after_ms":0,"event_name":"BTN_NEXT","event_type":"serial","id":"TR_SCENE_LEFOU_DETECTOR_2","priority":110,"target_step_id":"RTC_ESP_ETAPE2","trigger":"on_event"},{"after_ms":0,"event_name":"UNLOCK","event_type":"unlock","id":"TR_SCENE_LEFOU_DETECTOR_3","priority":115,"target_step_id":"RTC_ESP_ETAPE2","trigger":"on_event"},{"after_ms":0,"event_name":"FORCE_WIN_ETAPE2","event_type":"serial","id":"TR_SCENE_LEFOU_DETECTOR_5","priority":130,"target_step_id":"RTC_ESP_ETAPE2","trigger":"on_event","debug_only":true}]},{"actions":["ACTION_TRACE_STEP","ACTION_HW_LED_ALERT","ACTION_ESP_NOW_SEND_ETAPE2","ACTION_QUEUE_SONAR"],"apps":["APP_AUDIO","APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"PACK_CONFIRM_WIN_ETAPE2","mp3_gate_open":false,"screen_scene_id":"SCENE_WIN_ETAPE2","step_id":"RTC_ESP_ETAPE2","transitions":[{"after_ms":0,"event_name":"ACK_WIN2","event_type":"espnow","id":"TR_RTC_ESP_ETAPE2_1","priority":130,"target_step_id":"SCENE_QR_DETECTOR","trigger":"on_event"},{"after_ms":0,"event_name":"FORCE_DONE","event_type":"serial","id":"TR_RTC_ESP_ETAPE2_2","priority":120,"target_step_id":"SCENE_QR_DETECTOR","trigger":"on_event","debug_only":true}]},{"actions":["ACTION_TRACE_STEP","ACTION_QR_CODE_SCANNER_START"],"apps":["APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW","APP_QR_UNLOCK"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_QR_DETECTOR","step_id":"SCENE_QR_DETECTOR","transitions":[{"after_ms":0,"event_name":"QR_OK","event_type":"serial","id":"TR_SCENE_QR_DETECTOR_1","priority":140,"target_step_id":"SCENE_FINAL_WIN","trigger":"on_event"},{"after_ms":0,"event_name":"UNLOCK_QR","event_type":"unlock","id":"TR_SCENE_QR_DETECTOR_2","priority":150,"target_step_id":"SCENE_FINAL_WIN","trigger":"on_event"},{"after_ms":0,"event_name":"BTN_NEXT","event_type":"serial","id":"TR_SCENE_QR_DETECTOR_3","priority":110,"target_step_id":"SCENE_FINAL_WIN","trigger":"on_event"},{"after_ms":0,"event_name":"FORCE_WIN_ETAPE2","event_type":"serial","id":"TR_SCENE_QR_DETECTOR_5","priority":130,"target_step_id":"SCENE_FINAL_WIN","trigger":"on_event","debug_only":true}]},{"actions":["ACTION_TRACE_STEP","ACTION_WINNER"],"apps":["APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":false,"screen_scene_id":"SCENE_FINAL_WIN","step_id":"SCENE_FINAL_WIN","transitions":[{"after_ms":0,"event_name":"WIN_DUE","event_type":"timer","id":"TR_SCENE_FINAL_WIN_1","priority":140,"target_step_id":"STEP_MEDIA_MANAGER","trigger":"on_event"},{"after_ms":0,"event_name":"BTN_NEXT","event_type":"serial","id":"TR_SCENE_FINAL_WIN_2","priority":110,"target_step_id":"STEP_MEDIA_MANAGER","trigger":"on_event"},{"after_ms":0,"event_name":"UNLOCK","event_type":"unlock","id":"TR_SCENE_FINAL_WIN_3","priority":120,"target_step_id":"STEP_MEDIA_MANAGER","trigger":"on_event"},{"after_ms":0,"event_name":"FORCE_WIN_ETAPE2","event_type":"serial","id":"TR_SCENE_FINAL_WIN_5","priority":125,"target_step_id":"STEP_MEDIA_MANAGER","trigger":"on_event","debug_only":true}]},{"actions":["ACTION_TRACE_STEP","ACTION_SET_BOOT_MEDIA_MANAGER"],"apps":["APP_SCREEN","APP_GATE","APP_WIFI","APP_ESPNOW"],"audio_pack_id":"","mp3_gate_open":true,"screen_scene_id":"SCENE_MEDIA_MANAGER","step_id":"STEP_MEDIA_MANAGER","transitions":[]}],"version":2,"scenario":"DEFAULT","debug_transition_bypass_enabled":false} \ No newline at end of file diff --git a/artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.from_bundle.json b/artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.from_bundle.json new file mode 100644 index 0000000..14f3c95 --- /dev/null +++ b/artifacts/qa-test/2026-03-01/runtime_prepare/DEFAULT.from_bundle.json @@ -0,0 +1,434 @@ +{ + "scenario": { + "id": "DEFAULT", + "version": 2, + "initial_step": "STEP_U_SON_PROTO", + "app_bindings": [ + "APP_AUDIO", + "APP_SCREEN", + "APP_GATE", + "APP_WIFI", + "APP_ESPNOW", + "APP_SONAR", + "APP_SD", + "APP_CAMERA", + "APP_LED", + "APP_SERIAL", + "APP_TIMER", + "APP_UNLOCK", + "APP_QR", + "APP_INPUT", + "APP_LOG", + "APP_ACTION" + ] + }, + "boot_policy": { + "startup_mode": "story", + "persist_after_validation": true, + "rollback_command_required": true + }, + "qr_rule": { + "enabled": true, + "scene_id": "SCENE_QR_DETECTOR", + "expected_payload": "WIN", + "match_mode": "exact", + "case_insensitive": true, + "success_event": "UNLOCK_QR", + "failure_event": "QR_INVALID", + "timeout_seconds": 30, + "timeout_event": "QR_TIMEOUT" + }, + "media_hub": { + "enabled": true, + "hub_scene_id": "SCENE_MEDIA_MANAGER", + "entries": [ + "SCENE_PHOTO_MANAGER", + "SCENE_MP3_PLAYER", + "SCENE_READY" + ] + }, + "led_policy": { + "strict_rgb": true, + "defaults": { + "ws2812": 1, + "led_auto": 1, + "rgb": "18/45/95" + }, + "scene_overrides": [ + { + "scene_id": "SCENE_LA_DETECTOR", + "rgb": "dynamic_tuner_or_off" + } + ] + }, + "narrative_meta": { + "prototype": "U-SON", + "act_durations_minutes": { + "act_1": 45, + "act_2": 60 + }, + "zone4_piano": { + "code_word": "LEFOU", + "letters_random_order": true, + "anchor": "A on LA 440 Hz" + }, + "qr_location": "Derriere le portrait (Salle des Archives)" + }, + "steps_runtime_order": [ + { + "step_id": "STEP_U_SON_PROTO", + "screen_scene_id": "SCENE_U_SON_PROTO", + "audio_pack_id": "PACK_BOOT_RADIO", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], + "transitions": [ + { + "channel": "audio_done", + "event": "loop", + "target": "STEP_U_SON_PROTO" + }, + { + "channel": "BTN", + "event": "ANY", + "target": "STEP_LA_DETECTOR" + }, + { + "channel": "serial", + "event": "FORCE_ETAPE2", + "target": "STEP_LA_DETECTOR" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "random_one_blink", + "brightness": "random_bright", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_LA_DETECTOR", + "screen_scene_id": "SCENE_LA_DETECTOR", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "timer", + "event": "ETAPE2_DUE", + "target": "STEP_U_SON_PROTO" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_RTC_ESP_ETAPE1" + }, + { + "channel": "unlock", + "event": "UNLOCK", + "target": "STEP_RTC_ESP_ETAPE1" + }, + { + "channel": "action", + "event": "ACTION_FORCE_ETAPE2", + "target": "STEP_RTC_ESP_ETAPE1" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE1", + "target": "STEP_RTC_ESP_ETAPE1" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "dynamic_tuner", + "brightness": "100%", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_RTC_ESP_ETAPE1", + "screen_scene_id": "SCENE_WIN_ETAPE1", + "audio_pack_id": "PACK_CONFIRM_WIN_ETAPE1", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT", + "ACTION_ESP_NOW_SEND_ETAPE1", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "esp_now", + "event": "ACK_WIN1", + "target": "STEP_WIN_ETAPE1" + }, + { + "channel": "serial", + "event": "FORCE_DONE", + "target": "STEP_WIN_ETAPE1" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "off", + "ws2812_3": "off", + "ws2812_4": "on", + "animation": "breathing", + "brightness": "random_bright", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_WIN_ETAPE1", + "screen_scene_id": "SCENE_WIN_ETAPE1", + "audio_pack_id": "PACK_WIN", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], + "transitions": [ + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_WARNING" + }, + { + "channel": "serial", + "event": "FORCE_DONE", + "target": "STEP_WARNING" + }, + { + "channel": "esp_now", + "event": "ACK_WARNING", + "target": "STEP_WARNING" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "off", + "ws2812_3": "off", + "ws2812_4": "on", + "animation": "K2000", + "brightness": "K2000", + "rgb": "red" + } + }, + { + "step_id": "STEP_WARNING", + "screen_scene_id": "SCENE_WARNING", + "audio_pack_id": "PACK_BOOT_RADIO", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], + "transitions": [ + { + "channel": "audio_done", + "event": "loop", + "target": "STEP_WARNING" + }, + { + "channel": "BTN", + "event": "ANY", + "target": "STEP_LEFOU_DETECTOR" + }, + { + "channel": "serial", + "event": "FORCE_ETAPE2", + "target": "STEP_LEFOU_DETECTOR" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "blink_all", + "brightness": "100%", + "rgb": "red" + } + }, + { + "step_id": "STEP_LEFOU_DETECTOR", + "screen_scene_id": "SCENE_LEFOU_DETECTOR", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "timer", + "event": "ETAPE2_DUE", + "target": "STEP_WARNING" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "unlock", + "event": "UNLOCK", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "action", + "event": "ACTION_FORCE_ETAPE2", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE2", + "target": "STEP_RTC_ESP_ETAPE2" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "dynamic_tuner", + "brightness": "100%", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_RTC_ESP_ETAPE2", + "screen_scene_id": "SCENE_WIN_ETAPE2", + "audio_pack_id": "PACK_CONFIRM_WIN_ETAPE2", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT", + "ACTION_ESP_NOW_SEND_ETAPE2", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "esp_now", + "event": "ACK_WIN2", + "target": "STEP_QR_DETECTOR" + }, + { + "channel": "serial", + "event": "FORCE_DONE", + "target": "STEP_QR_DETECTOR" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "off", + "ws2812_3": "off", + "ws2812_4": "on", + "animation": "breathing", + "brightness": "random_bright", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_QR_DETECTOR", + "screen_scene_id": "SCENE_QR_DETECTOR", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_QR_CODE_SCANNER_START", + "ACTION_QR_TIMEOUT_30S" + ], + "transitions": [ + { + "channel": "timer", + "event": "ETAPE2_DUE", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "event", + "event": "QR_TIMEOUT", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_FINAL_WIN" + }, + { + "channel": "unlock", + "event": "UNLOCK_QR", + "target": "STEP_FINAL_WIN" + }, + { + "channel": "action", + "event": "ACTION_FORCE_ETAPE2", + "target": "STEP_FINAL_WIN" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE2", + "target": "STEP_FINAL_WIN" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "bargraph_qr_trigger", + "brightness": "bargraph", + "rgb": "bargraph_red_to_green" + } + }, + { + "step_id": "STEP_FINAL_WIN", + "screen_scene_id": "SCENE_FINAL_WIN", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_WINNER" + ], + "transitions": [ + { + "channel": "timer", + "event": "WIN_DUE", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "unlock", + "event": "UNLOCK", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "action", + "event": "FORCE_WIN_ETAPE2", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE2", + "target": "SCENE_MEDIA_MANAGER" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "blink_all_random", + "brightness": "100%", + "rgb": "random_color" + } + } + ] +} \ No newline at end of file diff --git a/artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default-summary.md b/artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default-summary.md new file mode 100644 index 0000000..5176f57 --- /dev/null +++ b/artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default-summary.md @@ -0,0 +1,73 @@ +# Runtime DEFAULT prepare summary + +## Scope +- Firmware runtime not modified (prepare-only mode). +- Source runtime bundle: `scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_runtime.json`. +- Source firmware current: `hardware/firmware/data/story/scenarios/DEFAULT.json`. + +## High-level delta +- initial_step current: `RTC_ESP_ETAPE1` +- initial_step bundle: `STEP_U_SON_PROTO` +- steps count current: 11 +- steps count bundle: 9 +- app_bindings count current: 6 +- app_bindings count bundle: 16 +- transitions count current: 20 +- transitions count bundle: 34 + +## Step IDs only in current DEFAULT.json +- `RTC_ESP_ETAPE1` +- `RTC_ESP_ETAPE2` +- `SCENE_CREDIT` +- `SCENE_FINAL_WIN` +- `SCENE_LA_DETECTOR` +- `SCENE_LEFOU_DETECTOR` +- `SCENE_QR_DETECTOR` +- `SCENE_U_SON_PROTO` +- `STEP_MEDIA_MANAGER` +- `WIN_ETAPE1` + +## Step IDs only in bundle runtime +- `STEP_FINAL_WIN` +- `STEP_LA_DETECTOR` +- `STEP_LEFOU_DETECTOR` +- `STEP_QR_DETECTOR` +- `STEP_RTC_ESP_ETAPE1` +- `STEP_RTC_ESP_ETAPE2` +- `STEP_U_SON_PROTO` +- `STEP_WIN_ETAPE1` + +## App bindings only in current DEFAULT.json +- `APP_QR_UNLOCK` + +## App bindings only in bundle runtime +- `APP_ACTION` +- `APP_CAMERA` +- `APP_INPUT` +- `APP_LED` +- `APP_LOG` +- `APP_QR` +- `APP_SD` +- `APP_SERIAL` +- `APP_SONAR` +- `APP_TIMER` +- `APP_UNLOCK` + +## Transition event keys only in current DEFAULT.json +- `audio_done:AUDIO_DONE` +- `button:ANY` +- `espnow:ACK_WIN2` +- `serial:QR_OK` +- `timer:WIN_ETAPE1_TO_CREDIT` + +## Transition event keys only in bundle runtime +- `BTN:ANY` +- `action:ACTION_FORCE_ETAPE2` +- `action:FORCE_WIN_ETAPE2` +- `audio_done:loop` +- `esp_now:ACK_WARNING` +- `esp_now:ACK_WIN1` +- `esp_now:ACK_WIN2` +- `event:QR_TIMEOUT` +- `serial:FORCE_ETAPE2` +- `serial:FORCE_WIN_ETAPE1` diff --git a/artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default.diff b/artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default.diff new file mode 100644 index 0000000..5bfbcc0 --- /dev/null +++ b/artifacts/qa-test/2026-03-01/runtime_prepare/runtime-default.diff @@ -0,0 +1,731 @@ +--- DEFAULT.current.json ++++ DEFAULT.from_bundle.json +@@ -1,67 +1,112 @@ + { +- "app_bindings": [ +- { +- "app": "AUDIO_PACK", +- "config": null, +- "id": "APP_AUDIO" ++ "boot_policy": { ++ "persist_after_validation": true, ++ "rollback_command_required": true, ++ "startup_mode": "story" ++ }, ++ "led_policy": { ++ "defaults": { ++ "led_auto": 1, ++ "rgb": "18/45/95", ++ "ws2812": 1 + }, +- { +- "app": "SCREEN_SCENE", +- "config": null, +- "id": "APP_SCREEN" ++ "scene_overrides": [ ++ { ++ "rgb": "dynamic_tuner_or_off", ++ "scene_id": "SCENE_LA_DETECTOR" ++ } ++ ], ++ "strict_rgb": true ++ }, ++ "media_hub": { ++ "enabled": true, ++ "entries": [ ++ "SCENE_PHOTO_MANAGER", ++ "SCENE_MP3_PLAYER", ++ "SCENE_READY" ++ ], ++ "hub_scene_id": "SCENE_MEDIA_MANAGER" ++ }, ++ "narrative_meta": { ++ "act_durations_minutes": { ++ "act_1": 45, ++ "act_2": 60 + }, +- { +- "app": "MP3_GATE", +- "config": null, +- "id": "APP_GATE" +- }, +- { +- "app": "WIFI_STACK", +- "config": null, +- "id": "APP_WIFI" +- }, +- { +- "app": "ESPNOW_STACK", +- "config": null, +- "id": "APP_ESPNOW" +- }, +- { +- "app": "QR_UNLOCK_APP", +- "config": null, +- "id": "APP_QR_UNLOCK" ++ "prototype": "U-SON", ++ "qr_location": "Derriere le portrait (Salle des Archives)", ++ "zone4_piano": { ++ "anchor": "A on LA 440 Hz", ++ "code_word": "LEFOU", ++ "letters_random_order": true + } +- ], +- "debug_transition_bypass_enabled": false, +- "estimated_duration_s": 0, +- "id": "DEFAULT", +- "initial_step": "RTC_ESP_ETAPE1", +- "scenario": "DEFAULT", +- "steps": [ ++ }, ++ "qr_rule": { ++ "case_insensitive": true, ++ "enabled": true, ++ "expected_payload": "WIN", ++ "failure_event": "QR_INVALID", ++ "match_mode": "exact", ++ "scene_id": "SCENE_QR_DETECTOR", ++ "success_event": "UNLOCK_QR", ++ "timeout_event": "QR_TIMEOUT", ++ "timeout_seconds": 30 ++ }, ++ "scenario": { ++ "app_bindings": [ ++ "APP_AUDIO", ++ "APP_SCREEN", ++ "APP_GATE", ++ "APP_WIFI", ++ "APP_ESPNOW", ++ "APP_SONAR", ++ "APP_SD", ++ "APP_CAMERA", ++ "APP_LED", ++ "APP_SERIAL", ++ "APP_TIMER", ++ "APP_UNLOCK", ++ "APP_QR", ++ "APP_INPUT", ++ "APP_LOG", ++ "APP_ACTION" ++ ], ++ "id": "DEFAULT", ++ "initial_step": "STEP_U_SON_PROTO", ++ "version": 2 ++ }, ++ "steps_runtime_order": [ + { + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], +- "apps": [ +- "APP_AUDIO", +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], +- "audio_pack_id": "", +- "mp3_gate_open": false, ++ "audio_pack_id": "PACK_BOOT_RADIO", ++ "led_policy": { ++ "animation": "random_one_blink", ++ "brightness": "random_bright", ++ "rgb": "random_color", ++ "ws2812_1": "on", ++ "ws2812_2": "on", ++ "ws2812_3": "on", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_U_SON_PROTO", +- "step_id": "SCENE_U_SON_PROTO", ++ "step_id": "STEP_U_SON_PROTO", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "ANY", +- "event_type": "button", +- "id": "TR_SCENE_U_SON_PROTO_2", +- "priority": 120, +- "target_step_id": "SCENE_LA_DETECTOR", +- "trigger": "on_event" ++ "channel": "audio_done", ++ "event": "loop", ++ "target": "STEP_U_SON_PROTO" ++ }, ++ { ++ "channel": "BTN", ++ "event": "ANY", ++ "target": "STEP_LA_DETECTOR" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_ETAPE2", ++ "target": "STEP_LA_DETECTOR" + } + ] + }, +@@ -70,25 +115,43 @@ + "ACTION_TRACE_STEP", + "ACTION_QUEUE_SONAR" + ], +- "apps": [ +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], + "audio_pack_id": "", +- "mp3_gate_open": false, ++ "led_policy": { ++ "animation": "dynamic_tuner", ++ "brightness": "100%", ++ "rgb": "random_color", ++ "ws2812_1": "on", ++ "ws2812_2": "on", ++ "ws2812_3": "on", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_LA_DETECTOR", +- "step_id": "SCENE_LA_DETECTOR", ++ "step_id": "STEP_LA_DETECTOR", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "BTN_NEXT", +- "event_type": "serial", +- "id": "TR_SCENE_LA_DETECTOR_2", +- "priority": 110, +- "target_step_id": "RTC_ESP_ETAPE1", +- "trigger": "on_event" ++ "channel": "timer", ++ "event": "ETAPE2_DUE", ++ "target": "STEP_U_SON_PROTO" ++ }, ++ { ++ "channel": "serial", ++ "event": "BTN_NEXT", ++ "target": "STEP_RTC_ESP_ETAPE1" ++ }, ++ { ++ "channel": "unlock", ++ "event": "UNLOCK", ++ "target": "STEP_RTC_ESP_ETAPE1" ++ }, ++ { ++ "channel": "action", ++ "event": "ACTION_FORCE_ETAPE2", ++ "target": "STEP_RTC_ESP_ETAPE1" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_WIN_ETAPE1", ++ "target": "STEP_RTC_ESP_ETAPE1" + } + ] + }, +@@ -96,29 +159,31 @@ + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT", +- "ACTION_QUEUE_SONAR", +- "ACTION_ESP_NOW_WAITING" ++ "ACTION_ESP_NOW_SEND_ETAPE1", ++ "ACTION_QUEUE_SONAR" + ], +- "apps": [ +- "APP_AUDIO", +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], +- "audio_pack_id": "", +- "mp3_gate_open": false, +- "screen_scene_id": "SCENE_WIN_ETAPE", +- "step_id": "RTC_ESP_ETAPE1", ++ "audio_pack_id": "PACK_CONFIRM_WIN_ETAPE1", ++ "led_policy": { ++ "animation": "breathing", ++ "brightness": "random_bright", ++ "rgb": "random_color", ++ "ws2812_1": "on", ++ "ws2812_2": "off", ++ "ws2812_3": "off", ++ "ws2812_4": "on" ++ }, ++ "screen_scene_id": "SCENE_WIN_ETAPE1", ++ "step_id": "STEP_RTC_ESP_ETAPE1", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "ANY", +- "event_type": "button", +- "id": "TR_RTC_ESP_ETAPE1_BTN", +- "priority": 120, +- "target_step_id": "WIN_ETAPE1", +- "trigger": "on_event" ++ "channel": "esp_now", ++ "event": "ACK_WIN1", ++ "target": "STEP_WIN_ETAPE1" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_DONE", ++ "target": "STEP_WIN_ETAPE1" + } + ] + }, +@@ -127,54 +192,33 @@ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], +- "apps": [ +- "APP_AUDIO", +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], + "audio_pack_id": "PACK_WIN", +- "mp3_gate_open": false, ++ "led_policy": { ++ "animation": "K2000", ++ "brightness": "K2000", ++ "rgb": "red", ++ "ws2812_1": "on", ++ "ws2812_2": "off", ++ "ws2812_3": "off", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_WIN_ETAPE1", +- "step_id": "WIN_ETAPE1", ++ "step_id": "STEP_WIN_ETAPE1", + "transitions": [ + { +- "after_ms": 60000, +- "event_name": "WIN_ETAPE1_TO_CREDIT", +- "event_type": "timer", +- "id": "TR_WIN_ETAPE1_TO_CREDIT", +- "priority": 100, +- "target_step_id": "SCENE_CREDIT", +- "trigger": "on_event" +- } +- ] +- }, +- { +- "actions": [ +- "ACTION_TRACE_STEP", +- "ACTION_HW_LED_ALERT" +- ], +- "apps": [ +- "APP_AUDIO", +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], +- "audio_pack_id": "", +- "mp3_gate_open": false, +- "screen_scene_id": "SCENE_CREDITS", +- "step_id": "SCENE_CREDIT", +- "transitions": [ ++ "channel": "serial", ++ "event": "BTN_NEXT", ++ "target": "STEP_WARNING" ++ }, + { +- "after_ms": 0, +- "event_name": "ANY", +- "event_type": "button", +- "id": "TR_SCENE_CREDIT_BTN", +- "priority": 120, +- "target_step_id": "STEP_WARNING", +- "trigger": "on_event" ++ "channel": "serial", ++ "event": "FORCE_DONE", ++ "target": "STEP_WARNING" ++ }, ++ { ++ "channel": "esp_now", ++ "event": "ACK_WARNING", ++ "target": "STEP_WARNING" + } + ] + }, +@@ -183,26 +227,33 @@ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], +- "apps": [ +- "APP_AUDIO", +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], +- "audio_pack_id": "", +- "mp3_gate_open": false, ++ "audio_pack_id": "PACK_BOOT_RADIO", ++ "led_policy": { ++ "animation": "blink_all", ++ "brightness": "100%", ++ "rgb": "red", ++ "ws2812_1": "on", ++ "ws2812_2": "on", ++ "ws2812_3": "on", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_WARNING", + "step_id": "STEP_WARNING", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "AUDIO_DONE", +- "event_type": "audio_done", +- "id": "TR_STEP_WARNING_1", +- "priority": 80, +- "target_step_id": "STEP_WARNING", +- "trigger": "on_event" ++ "channel": "audio_done", ++ "event": "loop", ++ "target": "STEP_WARNING" ++ }, ++ { ++ "channel": "BTN", ++ "event": "ANY", ++ "target": "STEP_LEFOU_DETECTOR" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_ETAPE2", ++ "target": "STEP_LEFOU_DETECTOR" + } + ] + }, +@@ -211,53 +262,43 @@ + "ACTION_TRACE_STEP", + "ACTION_QUEUE_SONAR" + ], +- "apps": [ +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], + "audio_pack_id": "", +- "mp3_gate_open": false, ++ "led_policy": { ++ "animation": "dynamic_tuner", ++ "brightness": "100%", ++ "rgb": "random_color", ++ "ws2812_1": "on", ++ "ws2812_2": "on", ++ "ws2812_3": "on", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_LEFOU_DETECTOR", +- "step_id": "SCENE_LEFOU_DETECTOR", ++ "step_id": "STEP_LEFOU_DETECTOR", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "ETAPE2_DUE", +- "event_type": "timer", +- "id": "TR_SCENE_LEFOU_DETECTOR_1", +- "priority": 100, +- "target_step_id": "STEP_WARNING", +- "trigger": "on_event" ++ "channel": "timer", ++ "event": "ETAPE2_DUE", ++ "target": "STEP_WARNING" + }, + { +- "after_ms": 0, +- "event_name": "BTN_NEXT", +- "event_type": "serial", +- "id": "TR_SCENE_LEFOU_DETECTOR_2", +- "priority": 110, +- "target_step_id": "RTC_ESP_ETAPE2", +- "trigger": "on_event" ++ "channel": "serial", ++ "event": "BTN_NEXT", ++ "target": "STEP_RTC_ESP_ETAPE2" + }, + { +- "after_ms": 0, +- "event_name": "UNLOCK", +- "event_type": "unlock", +- "id": "TR_SCENE_LEFOU_DETECTOR_3", +- "priority": 115, +- "target_step_id": "RTC_ESP_ETAPE2", +- "trigger": "on_event" ++ "channel": "unlock", ++ "event": "UNLOCK", ++ "target": "STEP_RTC_ESP_ETAPE2" + }, + { +- "after_ms": 0, +- "debug_only": true, +- "event_name": "FORCE_WIN_ETAPE2", +- "event_type": "serial", +- "id": "TR_SCENE_LEFOU_DETECTOR_5", +- "priority": 130, +- "target_step_id": "RTC_ESP_ETAPE2", +- "trigger": "on_event" ++ "channel": "action", ++ "event": "ACTION_FORCE_ETAPE2", ++ "target": "STEP_RTC_ESP_ETAPE2" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_WIN_ETAPE2", ++ "target": "STEP_RTC_ESP_ETAPE2" + } + ] + }, +@@ -268,92 +309,79 @@ + "ACTION_ESP_NOW_SEND_ETAPE2", + "ACTION_QUEUE_SONAR" + ], +- "apps": [ +- "APP_AUDIO", +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], + "audio_pack_id": "PACK_CONFIRM_WIN_ETAPE2", +- "mp3_gate_open": false, ++ "led_policy": { ++ "animation": "breathing", ++ "brightness": "random_bright", ++ "rgb": "random_color", ++ "ws2812_1": "on", ++ "ws2812_2": "off", ++ "ws2812_3": "off", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_WIN_ETAPE2", +- "step_id": "RTC_ESP_ETAPE2", ++ "step_id": "STEP_RTC_ESP_ETAPE2", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "ACK_WIN2", +- "event_type": "espnow", +- "id": "TR_RTC_ESP_ETAPE2_1", +- "priority": 130, +- "target_step_id": "SCENE_QR_DETECTOR", +- "trigger": "on_event" ++ "channel": "esp_now", ++ "event": "ACK_WIN2", ++ "target": "STEP_QR_DETECTOR" + }, + { +- "after_ms": 0, +- "debug_only": true, +- "event_name": "FORCE_DONE", +- "event_type": "serial", +- "id": "TR_RTC_ESP_ETAPE2_2", +- "priority": 120, +- "target_step_id": "SCENE_QR_DETECTOR", +- "trigger": "on_event" ++ "channel": "serial", ++ "event": "FORCE_DONE", ++ "target": "STEP_QR_DETECTOR" + } + ] + }, + { + "actions": [ + "ACTION_TRACE_STEP", +- "ACTION_QR_CODE_SCANNER_START" ++ "ACTION_QR_CODE_SCANNER_START", ++ "ACTION_QR_TIMEOUT_30S" + ], +- "apps": [ +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW", +- "APP_QR_UNLOCK" +- ], + "audio_pack_id": "", +- "mp3_gate_open": false, ++ "led_policy": { ++ "animation": "bargraph_qr_trigger", ++ "brightness": "bargraph", ++ "rgb": "bargraph_red_to_green", ++ "ws2812_1": "on", ++ "ws2812_2": "on", ++ "ws2812_3": "on", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_QR_DETECTOR", +- "step_id": "SCENE_QR_DETECTOR", ++ "step_id": "STEP_QR_DETECTOR", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "QR_OK", +- "event_type": "serial", +- "id": "TR_SCENE_QR_DETECTOR_1", +- "priority": 140, +- "target_step_id": "SCENE_FINAL_WIN", +- "trigger": "on_event" ++ "channel": "timer", ++ "event": "ETAPE2_DUE", ++ "target": "STEP_RTC_ESP_ETAPE2" + }, + { +- "after_ms": 0, +- "event_name": "UNLOCK_QR", +- "event_type": "unlock", +- "id": "TR_SCENE_QR_DETECTOR_2", +- "priority": 150, +- "target_step_id": "SCENE_FINAL_WIN", +- "trigger": "on_event" ++ "channel": "event", ++ "event": "QR_TIMEOUT", ++ "target": "STEP_RTC_ESP_ETAPE2" + }, + { +- "after_ms": 0, +- "event_name": "BTN_NEXT", +- "event_type": "serial", +- "id": "TR_SCENE_QR_DETECTOR_3", +- "priority": 110, +- "target_step_id": "SCENE_FINAL_WIN", +- "trigger": "on_event" ++ "channel": "serial", ++ "event": "BTN_NEXT", ++ "target": "STEP_FINAL_WIN" + }, + { +- "after_ms": 0, +- "debug_only": true, +- "event_name": "FORCE_WIN_ETAPE2", +- "event_type": "serial", +- "id": "TR_SCENE_QR_DETECTOR_5", +- "priority": 130, +- "target_step_id": "SCENE_FINAL_WIN", +- "trigger": "on_event" ++ "channel": "unlock", ++ "event": "UNLOCK_QR", ++ "target": "STEP_FINAL_WIN" ++ }, ++ { ++ "channel": "action", ++ "event": "ACTION_FORCE_ETAPE2", ++ "target": "STEP_FINAL_WIN" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_WIN_ETAPE2", ++ "target": "STEP_FINAL_WIN" + } + ] + }, +@@ -362,73 +390,45 @@ + "ACTION_TRACE_STEP", + "ACTION_WINNER" + ], +- "apps": [ +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], + "audio_pack_id": "", +- "mp3_gate_open": false, ++ "led_policy": { ++ "animation": "blink_all_random", ++ "brightness": "100%", ++ "rgb": "random_color", ++ "ws2812_1": "on", ++ "ws2812_2": "on", ++ "ws2812_3": "on", ++ "ws2812_4": "on" ++ }, + "screen_scene_id": "SCENE_FINAL_WIN", +- "step_id": "SCENE_FINAL_WIN", ++ "step_id": "STEP_FINAL_WIN", + "transitions": [ + { +- "after_ms": 0, +- "event_name": "WIN_DUE", +- "event_type": "timer", +- "id": "TR_SCENE_FINAL_WIN_1", +- "priority": 140, +- "target_step_id": "STEP_MEDIA_MANAGER", +- "trigger": "on_event" ++ "channel": "timer", ++ "event": "WIN_DUE", ++ "target": "SCENE_MEDIA_MANAGER" + }, + { +- "after_ms": 0, +- "event_name": "BTN_NEXT", +- "event_type": "serial", +- "id": "TR_SCENE_FINAL_WIN_2", +- "priority": 110, +- "target_step_id": "STEP_MEDIA_MANAGER", +- "trigger": "on_event" ++ "channel": "serial", ++ "event": "BTN_NEXT", ++ "target": "SCENE_MEDIA_MANAGER" + }, + { +- "after_ms": 0, +- "event_name": "UNLOCK", +- "event_type": "unlock", +- "id": "TR_SCENE_FINAL_WIN_3", +- "priority": 120, +- "target_step_id": "STEP_MEDIA_MANAGER", +- "trigger": "on_event" ++ "channel": "unlock", ++ "event": "UNLOCK", ++ "target": "SCENE_MEDIA_MANAGER" + }, + { +- "after_ms": 0, +- "debug_only": true, +- "event_name": "FORCE_WIN_ETAPE2", +- "event_type": "serial", +- "id": "TR_SCENE_FINAL_WIN_5", +- "priority": 125, +- "target_step_id": "STEP_MEDIA_MANAGER", +- "trigger": "on_event" ++ "channel": "action", ++ "event": "FORCE_WIN_ETAPE2", ++ "target": "SCENE_MEDIA_MANAGER" ++ }, ++ { ++ "channel": "serial", ++ "event": "FORCE_WIN_ETAPE2", ++ "target": "SCENE_MEDIA_MANAGER" + } + ] +- }, +- { +- "actions": [ +- "ACTION_TRACE_STEP", +- "ACTION_SET_BOOT_MEDIA_MANAGER" +- ], +- "apps": [ +- "APP_SCREEN", +- "APP_GATE", +- "APP_WIFI", +- "APP_ESPNOW" +- ], +- "audio_pack_id": "", +- "mp3_gate_open": true, +- "screen_scene_id": "SCENE_MEDIA_MANAGER", +- "step_id": "STEP_MEDIA_MANAGER", +- "transitions": [] + } +- ], +- "version": 2 ++ ] + } diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/CODEX_PROMPT.md b/scenario-ai-coherence/zacus_conversation_bundle_v3/CODEX_PROMPT.md new file mode 100644 index 0000000..6c5ec8e --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/CODEX_PROMPT.md @@ -0,0 +1,52 @@ +# Codex Prompt — Zacus Scenario Bundle (Firmware + Narrative) + +You are acting as an embedded firmware engineer working on the Freenove ESP32-S3 Zacus firmware. +Goal: integrate/update the scenario files so the story runtime matches the canonical scenario and remains stable. + +## Bundle contents +- scenario_promptable_template.yaml (human editable input) +- scenario_canonical.yaml (canonical, to be copied into docs/protocols/... target) +- scenario_runtime.json (runtime, to be copied into data/story/scenarios/DEFAULT.json) +- fsm_mermaid.md (visual FSM) +- zacus_v2.yaml (narrative scenario aligned with runtime) + +## Repo targets to update +- docs/protocols/story_specs/scenarios/default_unlock_win_etape2.yaml +- data/story/scenarios/DEFAULT.json + +## Narrative anchors (do not break) +- Prototype: U-SON +- Acte 1: LA 440 Hz (STEP_LA_DETECTOR) +- Acte 2: Zone 4 piano-alphabet → jouer "LEFOU" (letters placed randomly; A on LA 440 Hz) +- QR final: payload "WIN", hidden behind the portrait in the Archives +- After QR success: Media Hub + persistent boot into media_manager (persist_after_validation=true) + +## Required work (must do) +1) Replace/update the target YAML file with `scenario_canonical.yaml`. +2) Replace/update `data/story/scenarios/DEFAULT.json` with `scenario_runtime.json`. +3) Ensure the runtime loader accepts: + - step_id naming convention STEP_* + - transitions encoded as {channel,event,target} + - led_policy as a sibling of transitions (not nested) +4) Ensure QR alignment: + - QR rule scene_id is `SCENE_QR_DETECTOR` + - QR success emits `UNLOCK_QR` and is wired to existing unlock pipeline. +5) Fail-safe: + - `ACTION_QR_TIMEOUT_30S` must fire `QR_TIMEOUT` event after ~30s (or closest existing timer infra). + - Transition `event:QR_TIMEOUT->STEP_RTC_ESP_ETAPE2` must work. + +## Acceptance checks +- No PANIC/ASSERT/ABORT/REBOOT in serial logs. +- Each scene transition produces an ACK ok=1 (or existing equivalent). +- Ownership/locking of camera / mic / amp is consistent: + - SCENE_QR_DETECTOR uses camera + - audio packs do not deadlock mic/amp +- WS2812 behaviour matches per-step led_policy. +- After QR validated once, persist_after_validation=true causes subsequent boots to start in media_manager. + +## Deliverables +- Updated repo files (2 targets) +- Any minimal loader patches required +- Short changelog entry +- Evidence: build log + short serial trace demonstrating path: + STEP_U_SON_PROTO -> ... -> STEP_QR_DETECTOR -> STEP_FINAL_WIN -> SCENE_MEDIA_MANAGER diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/CONVERSATION_SUMMARY.md b/scenario-ai-coherence/zacus_conversation_bundle_v3/CONVERSATION_SUMMARY.md new file mode 100644 index 0000000..1448b26 --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/CONVERSATION_SUMMARY.md @@ -0,0 +1,18 @@ +# Zacus — Conversation Summary (bundle v3) + +This bundle consolidates the key outputs from the conversation: +- Promptable scenario template (user-edited section: prompt_input) +- Canonical scenario YAML (STEP_*/SCENE_* conventions) +- Runtime JSON (DEFAULT.json) +- FSM diagram (Mermaid) +- Codex prompt to update repo targets +- Narrative zacus_v2.yaml aligned with the runtime + real-world gameplay + +Key decisions captured: +- Prototype is U-SON. +- Act 1 (~45 min): LA 440 Hz stabilization (STEP_LA_DETECTOR). +- Act 2 (~60 min): Zone 4 piano-alphabet puzzle → play "LEFOU" (letters randomly placed; A anchored on LA 440 Hz). +- QR final payload is "WIN", hidden behind the portrait in the Archives. +- After QR success: Media Hub + persistent boot into media_manager. + +Generated: 2026-02-25 (Europe/Paris) diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/README.md b/scenario-ai-coherence/zacus_conversation_bundle_v3/README.md new file mode 100644 index 0000000..efd39ee --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/README.md @@ -0,0 +1,32 @@ +# Zacus Conversation Bundle (v3) + +## Purpose +Bundle de travail conversationnel/IA conservé en dehors de la source canon gameplay (`game/scenarios/*.yaml`). + +## Files +- `scenario_promptable_template.yaml`: template éditable (input prompt) +- `scenario_canonical.yaml`: YAML canonique conversation bundle +- `scenario_runtime.json`: JSON runtime dérivé +- `fsm_mermaid.md`: diagramme FSM +- `CODEX_PROMPT.md`: prompt Codex prêt à l'emploi +- `zacus_v2.yaml`: narration MJ alignée bundle +- `CONVERSATION_SUMMARY.md`: synthèse des décisions + +## Validation workflow +1. Installer les dépendances validateurs : + - `bash tools/setup/install_validators.sh` +2. Valider la cohérence interne du bundle : + - `python3 tools/scenario/validate_runtime_bundle.py` +3. Lancer les validateurs projet (non-régression canon/audio/printables en V2) : + - `python3 tools/scenario/validate_scenario.py game/scenarios/zacus_v2.yaml` + - `python3 tools/scenario/export_md.py game/scenarios/zacus_v2.yaml` + - `python3 tools/audio/validate_manifest.py audio/manifests/zacus_v2_audio.yaml` + - `python3 tools/printables/validate_manifest.py printables/manifests/zacus_v2_printables.yaml` + +## Notes +- Ce bundle n'est pas promu automatiquement dans `game/scenarios/*.yaml`. +- Toute promotion doit passer par une revue fonctionnelle dédiée. +## Typical flow +1. Modifier `prompt_input` dans `scenario_promptable_template.yaml`. +2. Revalider la cohérence (`validate_runtime_bundle.py`) puis les validateurs projet V2. +3. Préparer la promotion firmware via un diff `scenario_runtime.json` -> `hardware/firmware/data/story/scenarios/DEFAULT.json` avant toute application. diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/fsm_mermaid.md b/scenario-ai-coherence/zacus_conversation_bundle_v3/fsm_mermaid.md new file mode 100644 index 0000000..8ad5378 --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/fsm_mermaid.md @@ -0,0 +1,49 @@ +# Zacus FSM — Mermaid diagram (runtime DEFAULT) + +```mermaid +stateDiagram-v2 + [*] --> STEP_U_SON_PROTO + + STEP_U_SON_PROTO --> STEP_U_SON_PROTO: audio_done:loop + STEP_U_SON_PROTO --> STEP_LA_DETECTOR: BTN:ANY + STEP_U_SON_PROTO --> STEP_LA_DETECTOR: serial:FORCE_ETAPE2 + + STEP_LA_DETECTOR --> STEP_U_SON_PROTO: timer:ETAPE2_DUE + STEP_LA_DETECTOR --> STEP_RTC_ESP_ETAPE1: serial:BTN_NEXT + STEP_LA_DETECTOR --> STEP_RTC_ESP_ETAPE1: unlock:UNLOCK + STEP_LA_DETECTOR --> STEP_RTC_ESP_ETAPE1: action:ACTION_FORCE_ETAPE2 + STEP_LA_DETECTOR --> STEP_RTC_ESP_ETAPE1: serial:FORCE_WIN_ETAPE1 + + STEP_RTC_ESP_ETAPE1 --> STEP_WIN_ETAPE1: esp_now:ACK_WIN1 + STEP_RTC_ESP_ETAPE1 --> STEP_WIN_ETAPE1: serial:FORCE_DONE + + STEP_WIN_ETAPE1 --> STEP_WARNING: serial:BTN_NEXT + STEP_WIN_ETAPE1 --> STEP_WARNING: serial:FORCE_DONE + STEP_WIN_ETAPE1 --> STEP_WARNING: esp_now:ACK_WARNING + + STEP_WARNING --> STEP_WARNING: audio_done:loop + STEP_WARNING --> STEP_LEFOU_DETECTOR: BTN:ANY + STEP_WARNING --> STEP_LEFOU_DETECTOR: serial:FORCE_ETAPE2 + + STEP_LEFOU_DETECTOR --> STEP_WARNING: timer:ETAPE2_DUE + STEP_LEFOU_DETECTOR --> STEP_RTC_ESP_ETAPE2: serial:BTN_NEXT + STEP_LEFOU_DETECTOR --> STEP_RTC_ESP_ETAPE2: unlock:UNLOCK + STEP_LEFOU_DETECTOR --> STEP_RTC_ESP_ETAPE2: action:ACTION_FORCE_ETAPE2 + STEP_LEFOU_DETECTOR --> STEP_RTC_ESP_ETAPE2: serial:FORCE_WIN_ETAPE2 + + STEP_RTC_ESP_ETAPE2 --> STEP_QR_DETECTOR: esp_now:ACK_WIN2 + STEP_RTC_ESP_ETAPE2 --> STEP_QR_DETECTOR: serial:FORCE_DONE + + STEP_QR_DETECTOR --> STEP_RTC_ESP_ETAPE2: timer:ETAPE2_DUE + STEP_QR_DETECTOR --> STEP_RTC_ESP_ETAPE2: event:QR_TIMEOUT + STEP_QR_DETECTOR --> STEP_FINAL_WIN: serial:BTN_NEXT + STEP_QR_DETECTOR --> STEP_FINAL_WIN: unlock:UNLOCK_QR + STEP_QR_DETECTOR --> STEP_FINAL_WIN: action:ACTION_FORCE_ETAPE2 + STEP_QR_DETECTOR --> STEP_FINAL_WIN: serial:FORCE_WIN_ETAPE2 + + STEP_FINAL_WIN --> SCENE_MEDIA_MANAGER: timer:WIN_DUE + STEP_FINAL_WIN --> SCENE_MEDIA_MANAGER: serial:BTN_NEXT + STEP_FINAL_WIN --> SCENE_MEDIA_MANAGER: unlock:UNLOCK + STEP_FINAL_WIN --> SCENE_MEDIA_MANAGER: action:FORCE_WIN_ETAPE2 + STEP_FINAL_WIN --> SCENE_MEDIA_MANAGER: serial:FORCE_WIN_ETAPE2 +``` diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_canonical.yaml b/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_canonical.yaml new file mode 100644 index 0000000..1608c84 --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_canonical.yaml @@ -0,0 +1,291 @@ +# Zacus Scenario — Canonical YAML (v3) +# Generated: 2026-02-25 +# +# Conventions: +# - step_id = STEP_*, screen_scene_id = SCENE_* +# - led_policy is a sibling of transitions (NOT nested inside) +# - QR rule scene_id aligned to SCENE_QR_DETECTOR +# - Final transitions go to SCENE_MEDIA_MANAGER (hub scene) +# +# Narrative anchors (conversation): +# - Prototype: U-SON +# - Acte 1 (~45min): LA 440 Hz (STEP_LA_DETECTOR) +# - Acte 2 (~60min): Zone 4 piano-alphabet → jouer "LEFOU" (STEP_LEFOU_DETECTOR) +# * Lettres collées en ordre aléatoire sur touches blanches +# * A placé sur la touche correspondant au LA 440 Hz (ancre) +# - QR final: payload "WIN", caché derrière le portrait dans la Salle des Archives + +prompt_input: + meta: + request_name: "DEFAULT_UNLOCK_WIN_ETAPE2" + owner: "clement" + board_target: "freenove_esp32s3" + objective: "U-SON: Acte1 LA440 (~45min) -> Acte2 piano 'LEFOU' (~60min) -> QR WIN -> Media Manager (persistant)" + + boot_policy: + startup_mode: "story" # story | media_manager + persist_after_validation: true + rollback_command_required: true + + qr_rule: + enabled: true + scene_id: "SCENE_QR_DETECTOR" + expected_payload: "WIN" + match_mode: "exact" # exact | prefix | contains + case_insensitive: true + success_event: "UNLOCK_QR" + failure_event: "QR_INVALID" + + media_hub: + enabled: true + hub_scene_id: "SCENE_MEDIA_MANAGER" + entries: + - "SCENE_PHOTO_MANAGER" + - "SCENE_MP3_PLAYER" + - "SCENE_READY" + + led_policy: + strict_rgb: true + defaults: + ws2812: 1 + led_auto: 1 + rgb: "18/45/95" + scene_overrides: + - scene_id: "SCENE_LA_DETECTOR" + rgb: "dynamic_tuner_or_off" + + custom_steps: [] + + serial_test_plan: + - "SC_LOAD DEFAULT" + - "SCENE_GOTO SCENE_U_SON_PROTO" + - "QR_SIM WIN" + - "SC_EVENT UNLOCK_QR" + - "BOOT_MODE_STATUS" + - "RESET" + + acceptance_criteria: + - "Pas de PANIC|ASSERT|ABORT|REBOOT|rst:" + - "Transitions scene avec ACK ... ok=1" + - "Ownership camera/mic/amp coherent" + - "LED WS2812 conformes policy + RGB" + - "Boot mode media_manager persistant apres QR valide" + + notes: + - "Prototype: U-SON." + - "Etape1: LA 440 Hz stable (Acte1 ~45min)." + - "Etape2: piano-alphabet → jouer 'LEFOU' (Acte2 ~60min)." + - "QR WIN: caché derrière le portrait (Salle des Archives)." + - "SCENE_QR_DETECTOR a un timeout (QR_TIMEOUT) pour eviter le blocage." + +scenario: + id: "DEFAULT" + version: 2 + initial_step: "STEP_U_SON_PROTO" + app_bindings: + - "APP_AUDIO" + - "APP_SCREEN" + - "APP_GATE" + - "APP_WIFI" + - "APP_ESPNOW" + - "APP_SONAR" + - "APP_SD" + - "APP_CAMERA" + - "APP_LED" + - "APP_SERIAL" + - "APP_TIMER" + - "APP_UNLOCK" + - "APP_QR" + - "APP_INPUT" + - "APP_LOG" + - "APP_ACTION" + +steps_runtime_order: + + - step_id: "STEP_U_SON_PROTO" + screen_scene_id: "SCENE_U_SON_PROTO" + audio_pack_id: "PACK_BOOT_RADIO" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_HW_LED_ALERT" + transitions: + - "audio_done:loop->STEP_U_SON_PROTO" + - "BTN:ANY->STEP_LA_DETECTOR" + - "serial:FORCE_ETAPE2->STEP_LA_DETECTOR" + led_policy: + ws2812_1: on + ws2812_2: on + ws2812_3: on + ws2812_4: on + animation: "random_one_blink" + brightness: "random_bright" + rgb: "random_color" + + - step_id: "STEP_LA_DETECTOR" + screen_scene_id: "SCENE_LA_DETECTOR" + audio_pack_id: "" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_QUEUE_SONAR" + transitions: + - "timer:ETAPE2_DUE->STEP_U_SON_PROTO" + - "serial:BTN_NEXT->STEP_RTC_ESP_ETAPE1" + - "unlock:UNLOCK->STEP_RTC_ESP_ETAPE1" + - "action:ACTION_FORCE_ETAPE2->STEP_RTC_ESP_ETAPE1" + - "serial:FORCE_WIN_ETAPE1->STEP_RTC_ESP_ETAPE1" + led_policy: + ws2812_1: on + ws2812_2: on + ws2812_3: on + ws2812_4: on + animation: "dynamic_tuner" + brightness: "100%" + rgb: "random_color" + + - step_id: "STEP_RTC_ESP_ETAPE1" + screen_scene_id: "SCENE_WIN_ETAPE1" + audio_pack_id: "PACK_CONFIRM_WIN_ETAPE1" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_HW_LED_ALERT" + - "ACTION_ESP_NOW_SEND_ETAPE1" + - "ACTION_QUEUE_SONAR" + transitions: + - "esp_now:ACK_WIN1->STEP_WIN_ETAPE1" + - "serial:FORCE_DONE->STEP_WIN_ETAPE1" + led_policy: + ws2812_1: on + ws2812_2: off + ws2812_3: off + ws2812_4: on + animation: "breathing" + brightness: "random_bright" + rgb: "random_color" + + - step_id: "STEP_WIN_ETAPE1" + screen_scene_id: "SCENE_WIN_ETAPE1" + audio_pack_id: "PACK_WIN" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_HW_LED_ALERT" + transitions: + - "serial:BTN_NEXT->STEP_WARNING" + - "serial:FORCE_DONE->STEP_WARNING" + - "esp_now:ACK_WARNING->STEP_WARNING" + led_policy: + ws2812_1: on + ws2812_2: off + ws2812_3: off + ws2812_4: on + animation: "K2000" + brightness: "K2000" + rgb: "red" + + - step_id: "STEP_WARNING" + screen_scene_id: "SCENE_WARNING" + audio_pack_id: "PACK_BOOT_RADIO" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_HW_LED_ALERT" + transitions: + - "audio_done:loop->STEP_WARNING" + - "BTN:ANY->STEP_LEFOU_DETECTOR" + - "serial:FORCE_ETAPE2->STEP_LEFOU_DETECTOR" + led_policy: + ws2812_1: on + ws2812_2: on + ws2812_3: on + ws2812_4: on + animation: "blink_all" + brightness: "100%" + rgb: "red" + + - step_id: "STEP_LEFOU_DETECTOR" + screen_scene_id: "SCENE_LEFOU_DETECTOR" + audio_pack_id: "" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_QUEUE_SONAR" + transitions: + - "timer:ETAPE2_DUE->STEP_WARNING" + - "serial:BTN_NEXT->STEP_RTC_ESP_ETAPE2" + - "unlock:UNLOCK->STEP_RTC_ESP_ETAPE2" + - "action:ACTION_FORCE_ETAPE2->STEP_RTC_ESP_ETAPE2" + - "serial:FORCE_WIN_ETAPE2->STEP_RTC_ESP_ETAPE2" + led_policy: + ws2812_1: on + ws2812_2: on + ws2812_3: on + ws2812_4: on + animation: "dynamic_tuner" + brightness: "100%" + rgb: "random_color" + + - step_id: "STEP_RTC_ESP_ETAPE2" + screen_scene_id: "SCENE_WIN_ETAPE2" + audio_pack_id: "PACK_CONFIRM_WIN_ETAPE2" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_HW_LED_ALERT" + - "ACTION_ESP_NOW_SEND_ETAPE2" + - "ACTION_QUEUE_SONAR" + transitions: + - "esp_now:ACK_WIN2->STEP_QR_DETECTOR" + - "serial:FORCE_DONE->STEP_QR_DETECTOR" + led_policy: + ws2812_1: on + ws2812_2: off + ws2812_3: off + ws2812_4: on + animation: "breathing" + brightness: "random_bright" + rgb: "random_color" + + - step_id: "STEP_QR_DETECTOR" + screen_scene_id: "SCENE_QR_DETECTOR" + audio_pack_id: "" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_QR_CODE_SCANNER_START" + - "ACTION_QR_TIMEOUT_30S" + transitions: + - "timer:ETAPE2_DUE->STEP_RTC_ESP_ETAPE2" + - "event:QR_TIMEOUT->STEP_RTC_ESP_ETAPE2" + - "serial:BTN_NEXT->STEP_FINAL_WIN" + - "unlock:UNLOCK_QR->STEP_FINAL_WIN" + - "action:ACTION_FORCE_ETAPE2->STEP_FINAL_WIN" + - "serial:FORCE_WIN_ETAPE2->STEP_FINAL_WIN" + led_policy: + ws2812_1: on + ws2812_2: on + ws2812_3: on + ws2812_4: on + animation: "bargraph_qr_trigger" + brightness: "bargraph" + rgb: "bargraph_red_to_green" + + - step_id: "STEP_FINAL_WIN" + screen_scene_id: "SCENE_FINAL_WIN" + audio_pack_id: "" + actions: + - "ACTION_TRACE_STEP" + - "ACTION_WINNER" + transitions: + - "timer:WIN_DUE->SCENE_MEDIA_MANAGER" + - "serial:BTN_NEXT->SCENE_MEDIA_MANAGER" + - "unlock:UNLOCK->SCENE_MEDIA_MANAGER" + - "action:FORCE_WIN_ETAPE2->SCENE_MEDIA_MANAGER" + - "serial:FORCE_WIN_ETAPE2->SCENE_MEDIA_MANAGER" + led_policy: + ws2812_1: on + ws2812_2: on + ws2812_3: on + ws2812_4: on + animation: "blink_all_random" + brightness: "100%" + rgb: "random_color" + +current_firmware_snapshot: + source_to_update_files: + - "docs/protocols/story_specs/scenarios/default_unlock_win_etape2.yaml" + - "data/story/scenarios/DEFAULT.json" diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_promptable_template.yaml b/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_promptable_template.yaml new file mode 100644 index 0000000..acf7729 --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_promptable_template.yaml @@ -0,0 +1,105 @@ +# Scenario reel - template lisible + promptable. +# +# Comment l'utiliser: +# 1) Edite uniquement la section `prompt_input`. +# 2) Laisse `current_firmware_snapshot` comme reference de l'etat actuel code. +# 3) Envoie ce fichier a Codex: je convertis ensuite vers le YAML canonique + JSON runtime. +# +# NOTE (conversation): +# - Prototype: U-SON +# - Etape 1 (LA_DETECTOR): fréquence audio LA 440 Hz +# - Etape 2 (LEFOU_DETECTOR): puzzle piano-alphabet → jouer "LEFOU" +# * Lettres collées en ordre aléatoire sur les touches blanches +# * A est placé sur la touche correspondant au LA 440 Hz (ancre) +# - QR final: payload "WIN", caché derrière le portrait dans la Salle des Archives + +prompt_input: + meta: + request_name: "A_COMPLETER" + owner: "A_COMPLETER" + board_target: "freenove_esp32s3" + objective: "U-SON: Acte1 LA440 (~45min) -> Acte2 Zone4 piano 'LEFOU' (~60min) -> QR WIN -> Media Manager" + + boot_policy: + startup_mode: "story" # story | media_manager + persist_after_validation: true + rollback_command_required: true + + qr_rule: + enabled: true + scene_id: "SCENE_QR_DETECTOR" + expected_payload: "WIN" + match_mode: "exact" # exact | prefix | contains + case_insensitive: true + success_event: "UNLOCK_QR" + failure_event: "QR_INVALID" + + media_hub: + enabled: true + hub_scene_id: "SCENE_MEDIA_MANAGER" + entries: + - "SCENE_PHOTO_MANAGER" + - "SCENE_MP3_PLAYER" + - "SCENE_READY" + + led_policy: + strict_rgb: true + defaults: + ws2812: 1 + led_auto: 1 + rgb: "18/45/95" + scene_overrides: + - scene_id: "SCENE_LA_DETECTOR" + rgb: "dynamic_tuner_or_off" + + custom_steps: + # Ajoute, retire, ou reordonne des steps ici. + - "A_COMPLETER" + + serial_test_plan: + - "SC_LOAD DEFAULT" + - "SCENE_GOTO" + - "QR_SIM WIN" + - "SC_EVENT UNLOCK_QR" + - "BOOT_MODE_STATUS" + - "RESET" + + acceptance_criteria: + - "Pas de PANIC|ASSERT|ABORT|REBOOT|rst:" + - "Transitions scene avec ACK ... ok=1" + - "Ownership camera/mic/amp coherent" + - "LED WS2812 conformes policy + RGB" + - "Boot mode media_manager persistant apres QR valide" + + notes: + - "Acte 1: LA 440 Hz (stabilité) ~45 minutes." + - "Acte 2: Zone 4 piano-alphabet (LEFOU) + Archives (QR WIN derrière portrait) ~60 minutes." + - "Prototype: U-SON." + - "Ajouter ici les exceptions ou aliases scene." + + scenario: + id: "DEFAULT" + version: 2 + initial_step: "STEP_U_SON_PROTO" + app_bindings: + - "APP_AUDIO" + - "APP_SCREEN" + - "APP_GATE" + - "APP_WIFI" + - "APP_ESPNOW" + - "APP_SONAR" + - "APP_SD" + - "APP_CAMERA" + - "APP_LED" + - "APP_SERIAL" + - "APP_TIMER" + - "APP_UNLOCK" + - "APP_QR" + - "APP_INPUT" + - "APP_LOG" + - "APP_ACTION" + +current_firmware_snapshot: + source_to_update_files: + - "docs/protocols/story_specs/scenarios/default_unlock_win_etape2.yaml" + - "data/story/scenarios/DEFAULT.json" diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_runtime.json b/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_runtime.json new file mode 100644 index 0000000..14f3c95 --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/scenario_runtime.json @@ -0,0 +1,434 @@ +{ + "scenario": { + "id": "DEFAULT", + "version": 2, + "initial_step": "STEP_U_SON_PROTO", + "app_bindings": [ + "APP_AUDIO", + "APP_SCREEN", + "APP_GATE", + "APP_WIFI", + "APP_ESPNOW", + "APP_SONAR", + "APP_SD", + "APP_CAMERA", + "APP_LED", + "APP_SERIAL", + "APP_TIMER", + "APP_UNLOCK", + "APP_QR", + "APP_INPUT", + "APP_LOG", + "APP_ACTION" + ] + }, + "boot_policy": { + "startup_mode": "story", + "persist_after_validation": true, + "rollback_command_required": true + }, + "qr_rule": { + "enabled": true, + "scene_id": "SCENE_QR_DETECTOR", + "expected_payload": "WIN", + "match_mode": "exact", + "case_insensitive": true, + "success_event": "UNLOCK_QR", + "failure_event": "QR_INVALID", + "timeout_seconds": 30, + "timeout_event": "QR_TIMEOUT" + }, + "media_hub": { + "enabled": true, + "hub_scene_id": "SCENE_MEDIA_MANAGER", + "entries": [ + "SCENE_PHOTO_MANAGER", + "SCENE_MP3_PLAYER", + "SCENE_READY" + ] + }, + "led_policy": { + "strict_rgb": true, + "defaults": { + "ws2812": 1, + "led_auto": 1, + "rgb": "18/45/95" + }, + "scene_overrides": [ + { + "scene_id": "SCENE_LA_DETECTOR", + "rgb": "dynamic_tuner_or_off" + } + ] + }, + "narrative_meta": { + "prototype": "U-SON", + "act_durations_minutes": { + "act_1": 45, + "act_2": 60 + }, + "zone4_piano": { + "code_word": "LEFOU", + "letters_random_order": true, + "anchor": "A on LA 440 Hz" + }, + "qr_location": "Derriere le portrait (Salle des Archives)" + }, + "steps_runtime_order": [ + { + "step_id": "STEP_U_SON_PROTO", + "screen_scene_id": "SCENE_U_SON_PROTO", + "audio_pack_id": "PACK_BOOT_RADIO", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], + "transitions": [ + { + "channel": "audio_done", + "event": "loop", + "target": "STEP_U_SON_PROTO" + }, + { + "channel": "BTN", + "event": "ANY", + "target": "STEP_LA_DETECTOR" + }, + { + "channel": "serial", + "event": "FORCE_ETAPE2", + "target": "STEP_LA_DETECTOR" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "random_one_blink", + "brightness": "random_bright", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_LA_DETECTOR", + "screen_scene_id": "SCENE_LA_DETECTOR", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "timer", + "event": "ETAPE2_DUE", + "target": "STEP_U_SON_PROTO" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_RTC_ESP_ETAPE1" + }, + { + "channel": "unlock", + "event": "UNLOCK", + "target": "STEP_RTC_ESP_ETAPE1" + }, + { + "channel": "action", + "event": "ACTION_FORCE_ETAPE2", + "target": "STEP_RTC_ESP_ETAPE1" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE1", + "target": "STEP_RTC_ESP_ETAPE1" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "dynamic_tuner", + "brightness": "100%", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_RTC_ESP_ETAPE1", + "screen_scene_id": "SCENE_WIN_ETAPE1", + "audio_pack_id": "PACK_CONFIRM_WIN_ETAPE1", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT", + "ACTION_ESP_NOW_SEND_ETAPE1", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "esp_now", + "event": "ACK_WIN1", + "target": "STEP_WIN_ETAPE1" + }, + { + "channel": "serial", + "event": "FORCE_DONE", + "target": "STEP_WIN_ETAPE1" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "off", + "ws2812_3": "off", + "ws2812_4": "on", + "animation": "breathing", + "brightness": "random_bright", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_WIN_ETAPE1", + "screen_scene_id": "SCENE_WIN_ETAPE1", + "audio_pack_id": "PACK_WIN", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], + "transitions": [ + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_WARNING" + }, + { + "channel": "serial", + "event": "FORCE_DONE", + "target": "STEP_WARNING" + }, + { + "channel": "esp_now", + "event": "ACK_WARNING", + "target": "STEP_WARNING" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "off", + "ws2812_3": "off", + "ws2812_4": "on", + "animation": "K2000", + "brightness": "K2000", + "rgb": "red" + } + }, + { + "step_id": "STEP_WARNING", + "screen_scene_id": "SCENE_WARNING", + "audio_pack_id": "PACK_BOOT_RADIO", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT" + ], + "transitions": [ + { + "channel": "audio_done", + "event": "loop", + "target": "STEP_WARNING" + }, + { + "channel": "BTN", + "event": "ANY", + "target": "STEP_LEFOU_DETECTOR" + }, + { + "channel": "serial", + "event": "FORCE_ETAPE2", + "target": "STEP_LEFOU_DETECTOR" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "blink_all", + "brightness": "100%", + "rgb": "red" + } + }, + { + "step_id": "STEP_LEFOU_DETECTOR", + "screen_scene_id": "SCENE_LEFOU_DETECTOR", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "timer", + "event": "ETAPE2_DUE", + "target": "STEP_WARNING" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "unlock", + "event": "UNLOCK", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "action", + "event": "ACTION_FORCE_ETAPE2", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE2", + "target": "STEP_RTC_ESP_ETAPE2" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "dynamic_tuner", + "brightness": "100%", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_RTC_ESP_ETAPE2", + "screen_scene_id": "SCENE_WIN_ETAPE2", + "audio_pack_id": "PACK_CONFIRM_WIN_ETAPE2", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_HW_LED_ALERT", + "ACTION_ESP_NOW_SEND_ETAPE2", + "ACTION_QUEUE_SONAR" + ], + "transitions": [ + { + "channel": "esp_now", + "event": "ACK_WIN2", + "target": "STEP_QR_DETECTOR" + }, + { + "channel": "serial", + "event": "FORCE_DONE", + "target": "STEP_QR_DETECTOR" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "off", + "ws2812_3": "off", + "ws2812_4": "on", + "animation": "breathing", + "brightness": "random_bright", + "rgb": "random_color" + } + }, + { + "step_id": "STEP_QR_DETECTOR", + "screen_scene_id": "SCENE_QR_DETECTOR", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_QR_CODE_SCANNER_START", + "ACTION_QR_TIMEOUT_30S" + ], + "transitions": [ + { + "channel": "timer", + "event": "ETAPE2_DUE", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "event", + "event": "QR_TIMEOUT", + "target": "STEP_RTC_ESP_ETAPE2" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "STEP_FINAL_WIN" + }, + { + "channel": "unlock", + "event": "UNLOCK_QR", + "target": "STEP_FINAL_WIN" + }, + { + "channel": "action", + "event": "ACTION_FORCE_ETAPE2", + "target": "STEP_FINAL_WIN" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE2", + "target": "STEP_FINAL_WIN" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "bargraph_qr_trigger", + "brightness": "bargraph", + "rgb": "bargraph_red_to_green" + } + }, + { + "step_id": "STEP_FINAL_WIN", + "screen_scene_id": "SCENE_FINAL_WIN", + "audio_pack_id": "", + "actions": [ + "ACTION_TRACE_STEP", + "ACTION_WINNER" + ], + "transitions": [ + { + "channel": "timer", + "event": "WIN_DUE", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "serial", + "event": "BTN_NEXT", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "unlock", + "event": "UNLOCK", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "action", + "event": "FORCE_WIN_ETAPE2", + "target": "SCENE_MEDIA_MANAGER" + }, + { + "channel": "serial", + "event": "FORCE_WIN_ETAPE2", + "target": "SCENE_MEDIA_MANAGER" + } + ], + "led_policy": { + "ws2812_1": "on", + "ws2812_2": "on", + "ws2812_3": "on", + "ws2812_4": "on", + "animation": "blink_all_random", + "brightness": "100%", + "rgb": "random_color" + } + } + ] +} \ No newline at end of file diff --git a/scenario-ai-coherence/zacus_conversation_bundle_v3/zacus_v2.yaml b/scenario-ai-coherence/zacus_conversation_bundle_v3/zacus_v2.yaml new file mode 100644 index 0000000..066c550 --- /dev/null +++ b/scenario-ai-coherence/zacus_conversation_bundle_v3/zacus_v2.yaml @@ -0,0 +1,172 @@ +id: zacus_v2 +version: 3 +revision: 1 +title: "Le mystère du Professeur Zacus — Version Réelle (U-SON, piano LEFOU, QR WIN)" +theme: "Enquête scientifique + stabilisation audio + épreuve Zone 4 + déverrouillage final" + +players: + min: 6 + max: 14 + +ages: "6–14 ans (9–11 recommandés)" + +duration: + act_1_minutes: 45 + act_2_minutes: 60 + total_minutes: 105 + +firmware: + board_target: freenove_esp32s3 + engine: story_engine_v2 + runtime_scenario_id: "DEFAULT" + + boot_policy: + startup_mode: story + persist_after_validation: true + rollback_command_required: true + after_success_boot: media_manager + + qr_rule: + enabled: true + scene_id: "SCENE_QR_DETECTOR" + expected_payload: "WIN" + match_mode: exact + case_insensitive: true + success_event: "UNLOCK_QR" + failure_event: "QR_INVALID" + timeout_seconds: 30 + timeout_event: "QR_TIMEOUT" + + media_hub: + enabled: true + hub_scene_id: "SCENE_MEDIA_MANAGER" + entries: + - "SCENE_PHOTO_MANAGER" + - "SCENE_MP3_PLAYER" + - "SCENE_READY" + +canon: + prototype: "U-SON" + introduction: > + Le Professeur Zacus a disparu après avoir déclenché une alerte cryptée. + Le prototype U-SON “dérive”: les signaux deviennent instables. + Pour protéger U-SON, l’équipe doit: + (1) stabiliser une référence scientifique (LA 440 Hz), + (2) passer la règle de Zone 4 (installation de l’Électron Fou) via un code piano-alphabet, + (3) récupérer la clé finale (QR “WIN”) cachée aux Archives. + stakes: > + Le vrai test n’est pas la vitesse: c’est la coopération, la précision et le calme. + reveal_finale: > + Zacus réapparaît: c’était un test d’éthique. + U-SON ne doit pas devenir un objet de panique. + L’équipe gagne parce qu’elle a fait juste: stabilité, règle, entraide. + lore_truths: + - "Zone 4 = installation personnelle de l’Électron Fou." + - "Piano-alphabet brouillé: lettres collées en ordre aléatoire sur touches blanches." + - "Ancre: A est placé sur la touche correspondant au LA 440 Hz." + +stations: + - id: STATION_ONDES + act: 1 + name: "Atelier des Ondes" + focus: "Stabiliser LA 440 Hz pour recaler U-SON." + firmware_anchor_step: "STEP_LA_DETECTOR" + + - id: STATION_ZONE4_PIANO + act: 2 + name: "Zone 4 — Studio de Résonance (Piano Alphabet brouillé)" + focus: "Trouver et jouer le code LEFOU (L-E-F-O-U) via lettres sur touches blanches." + firmware_anchor_step: "STEP_LEFOU_DETECTOR" + clue_soft: "En Zone 4, les lettres comptent plus que les notes. A est sur le LA 440." + clue_hard: "Le code est le nom du propriétaire: LEFOU." + + - id: STATION_ARCHIVES_QR + act: 2 + name: "Salle des Archives" + focus: "Trouver et scanner la clé finale." + firmware_anchor_step: "STEP_QR_DETECTOR" + qr_location_real: "Derrière le portrait (cadre) dans la Salle des Archives." + +puzzles: + - id: PUZZLE_LA_440 + act: 1 + type: "audio / stabilisation" + objective: "Produire un LA 440 Hz stable." + firmware_step: "STEP_LA_DETECTOR" + + - id: PUZZLE_PIANO_ALPHABET_5 + act: 2 + type: "piano / code lettres (mapping brouillé)" + objective: "Jouer 5 touches correspondant aux lettres du code." + firmware_step: "STEP_LEFOU_DETECTOR" + mapping_rule_real: > + Les 26 lettres A–Z sont collées sur des touches blanches dans un ordre aléatoire. + Une seule ancre est vraie: A est placé sur le LA 440 Hz. + code_word_5_letters: "LEFOU" + sequence_letters: ["L","E","F","O","U"] + hint_progression: + soft: "A est sur le LA. Cherchez les lettres, pas les notes." + medium: "Le mot est un nom (propriétaire Zone 4)." + hard: "Jouez L-E-F-O-U." + + - id: PUZZLE_QR_WIN + act: 2 + type: "recherche / scan" + objective: "Scanner le QR final WIN." + firmware_step: "STEP_QR_DETECTOR" + qr_payload: "WIN" + location: "Derrière le portrait aux Archives" + +acts: + - act: 1 + title: "Acte 1 — Stabiliser U-SON (LA 440) (≈45 min)" + goal: "Valider Étape 1 via LA 440 Hz." + - act: 2 + title: "Acte 2 — Zone 4 (piano LEFOU) + Archives (QR WIN) (≈60 min)" + goal: "Valider Étape 2, puis scanner QR WIN derrière le portrait." + +audio: + packs: + - pack_id: PACK_BOOT_RADIO + tracks: + - track_id: boot_intro + script_fr: > + Équipe Zacus… ici le Professeur Zacus. + Le prototype U-SON dérive. Les capteurs ne sont plus fiables. + Pour stabiliser U-SON, il vous faut une référence : le LA, quatre-cent-quarante hertz. + Rendez-vous à l’Atelier des Ondes. + Gardez votre calme. + tts_prompt_excerpt: > + Voix adulte calme, rassurante, scientifique. Phrases courtes. + Effets: bip début + souffle léger + bandpass radio. + - track_id: warning_to_zone4 + script_fr: > + Alerte. + Prochaine étape : Zone 4. + Les lettres sont brouillées. + Une seule est sûre : A est sur le LA. + Cinq lettres. Cinq touches. + tts_prompt_excerpt: > + Voix plus urgente mais pas anxiogène. + Effets: bips rapides d’alarme, puis radio léger. + + - pack_id: PACK_CONFIRM_WIN_ETAPE1 + tracks: + - track_id: confirm_win1 + script_fr: > + Signal stabilisé. + Étape un validée. + Liaison confirmée. + + - pack_id: PACK_CONFIRM_WIN_ETAPE2 + tracks: + - track_id: confirm_win2_archives + script_fr: > + Étape deux validée. + Rendez-vous aux Archives. + La clé finale est derrière le portrait. + +qr: + payload: "WIN" + location: "Derrière le portrait dans la Salle des Archives" + lead_in_clue: "Regarde là où Zacus surveille toujours."