diff --git a/.claude/rules/CLAUDE.md b/.claude/rules/CLAUDE.md index daced9bd..241dc736 100644 --- a/.claude/rules/CLAUDE.md +++ b/.claude/rules/CLAUDE.md @@ -63,3 +63,7 @@ Strong success criteria let you loop independently. Weak criteria ("make it work --- **These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes. + +For current-firmware merges, board customization retention, ESP-IDF build/flash, +and external-app compatibility verification, also follow +`.claude/skills/tactility-firmware-development/SKILL.md`. diff --git a/.claude/skills/tactility-firmware-development/SKILL.md b/.claude/skills/tactility-firmware-development/SKILL.md new file mode 100644 index 00000000..64318b4c --- /dev/null +++ b/.claude/skills/tactility-firmware-development/SKILL.md @@ -0,0 +1,97 @@ +--- +name: tactility-firmware-development +description: Use when merging current Tactility firmware, preserving local ES3C28P/ES3C35P customizations, building/flashing ESP32 firmware, or validating external apps against it. +--- + +# Tactility firmware development + +## Scope and success criteria + +Use this skill for firmware upgrades, especially when upstream changes the app +loader, dashboard API, SDK export, or device model. Before editing, record the +active branch, `git status --short`, selected `Devices/`, serial port, and +the expected device identity. Preserve user work and local board +customizations; do not reset or overwrite a dirty tree. + +Success is not merely a successful flash: the board must boot, mount storage, +return `/api/sysinfo`, expose required internal apps, and accept an external +app rebuilt against this exact firmware. + +## Upgrade and customization audit + +1. Fetch and compare the intended upstream branch before merging. Treat + `upstream/main` as distinct from experimental release/IDF branches unless + the task explicitly asks for one of those branches. +2. Merge without discarding local work (for example, `git merge --autostash + upstream/main` after inspecting status). Resolve conflicts by preserving + required ES3C28P and ES3C35P device definitions, partition selection, + display/font customizations, and product features. +3. Compare the pre-upgrade customization commit against the resulting worktree. + Check new app registrations, CMake/source inclusion, settings pages, + web-server endpoints, and board-specific `sdkconfig` entries—not just files + that happen to conflict. +4. Commit the resulting firmware customization as a focused, reviewable + commit after `git diff --check`. + +## Multi-binary external-app compatibility + +Upstream app packaging changed to `bin//.elf`. The old +`elf/.elf` archive layout produces a loader `Not executable` error. + +- Manifest v0.2: `bin/esp32s3/app.elf` +- Manifest v0.3: `bin/esp32s3/.elf` + +When this change arrives, update the companion app tool and rebuild every app +from a fresh SDK exported from this firmware. Do not attempt to repair a +packaged ELF on the SD card: its layout and ABI must both be regenerated. + +## Build and flash + +Use the installed IDF 5.5 environment; host virtual environments can corrupt +both Python dependencies and IDF tooling: + +```zsh +unset VIRTUAL_ENV PYTHONPATH PYTHONHOME +export IDF_PYTHON_ENV_PATH=/Users/adolforeyna/.espressif/python_env/idf5.5_py3.9_env +source /Users/adolforeyna/esp/esp-idf/export.sh + +# Select/check the intended board before this step. +python device.py +idf.py build +idf.py -p /dev/cu.usbmodemXXXX flash +``` + +`Tactility/CMakeLists.txt` uses a non-configure-dependent source glob. After +adding a new `.c`/`.cpp` file, run `idf.py reconfigure build`; otherwise a +linker error for a newly referenced symbol may only mean CMake has not +discovered the source file yet. + +## Boot and feature acceptance + +Capture serial at 115200 after flash or reset. Confirm the board name, SD-card +mount, HTTP-server start, Wi-Fi address, and any feature-specific startup logs. +Then query the resolved device: + +```zsh +curl -fsS http:///api/sysinfo +curl -fsS http:///api/apps +``` + +For MCP settings, verify the `McpSettings` internal app appears in `/api/apps`. +When enabled, verify MCP stream startup logs. For a feature restored from an +older customization, validate its registration path and persisted settings, +not only its source files. + +## External-app acceptance gate + +Use the companion app skill's exact-firmware wrapper: + +```zsh +cd /path/to/tactility_apps +scripts/build_current_firmware_app.sh Apps/MyApp --firmware /path/to/tactility +``` + +Inspect the resulting tar member path, install through port-80 dashboard API, +launch it, and read serial. Required evidence is the loader's `Loading +.../bin/...`, an ELF entry address, `Task started`, and app-specific startup +logs. HTTP 200 or a package simply appearing in `/api/apps` is insufficient.