# Offline Command Word Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Make the board keep AFE offline wake word recognition while also enabling the offline command word `切换模式` in non-power-off states. **Architecture:** Keep `AfeWakeWord` as the primary ESP32-S3 wake-word implementation whenever a WakeNet model exists. Attach MultiNet command detection inside `AfeWakeWord`, and enable a Chinese MultiNet model in configuration so the command recognizer can initialize. The board command callback remains log-only per user confirmation. **Tech Stack:** ESP-IDF, ESP-SR WakeNet/MultiNet, C++ audio service, C board support code, Python static validation. ## Global Constraints - Do not change the offline command behavior beyond log-only callback. - Preserve existing AFE wake-word behavior. - User will perform final firmware compilation. - Avoid broad refactors. --- ### Task 1: Static Validation for Offline Command Wiring **Files:** - Create: `tools/validate_offline_command_wiring.py` **Interfaces:** - Consumes: `main/audio/audio_service.cc`, `sdkconfig`, `sdkconfig.defaults.esp32s3` - Produces: a command-line validator that exits non-zero if AFE wake word is not preferred or Chinese MultiNet is not enabled. - [ ] **Step 1: Write the failing validation script** ```python from pathlib import Path ROOT = Path(__file__).resolve().parents[1] def read_text(path: str) -> str: return (ROOT / path).read_text(encoding="utf-8") def require(condition: bool, message: str) -> None: if not condition: raise SystemExit(message) def main() -> None: audio_service = read_text("main/audio/audio_service.cc") afe_pos = audio_service.find("wake_word_ = std::make_unique();") custom_pos = audio_service.find("wake_word_ = std::make_unique();") require(afe_pos != -1, "AfeWakeWord selection is missing") require(custom_pos != -1, "CustomWakeWord fallback is missing") require(afe_pos < custom_pos, "AfeWakeWord must be preferred before CustomWakeWord when WakeNet exists") sdkconfig = read_text("sdkconfig") defaults = read_text("sdkconfig.defaults.esp32s3") multinet_enabled = "CONFIG_SR_MN_CN_MULTINET" in sdkconfig and "CONFIG_SR_MN_CN_NONE=y" not in sdkconfig defaults_enabled = "CONFIG_SR_MN_CN_MULTINET" in defaults require(multinet_enabled, "sdkconfig must enable a Chinese MultiNet model") require(defaults_enabled, "sdkconfig.defaults.esp32s3 must enable a Chinese MultiNet model") if __name__ == "__main__": main() ``` - [ ] **Step 2: Run validation to verify it fails** Run: `python tools/validate_offline_command_wiring.py` Expected: FAIL with either `AfeWakeWord must be preferred...` or `sdkconfig must enable...`. - [ ] **Step 3: Implement minimal wiring/config changes** Modify `main/audio/audio_service.cc` so `SetModelsList()` chooses `AfeWakeWord` first when WakeNet exists, then falls back to `CustomWakeWord` when only MultiNet exists. Modify `sdkconfig` and `sdkconfig.defaults.esp32s3` to enable a Chinese MultiNet model: ```text CONFIG_SR_MN_CN_MULTINET7_QUANT=y # CONFIG_SR_MN_CN_NONE is not set ``` - [ ] **Step 4: Run validation to verify it passes** Run: `python tools/validate_offline_command_wiring.py` Expected: no output and exit code 0. - [ ] **Step 5: Optional compile check** User will run ESP-IDF build locally and report any errors.