Files
tactility/.claude/skills/tactility-firmware-development/SKILL.md
T
2026-09-10 21:37:12 -04:00

3.9 KiB

name, description
name description
tactility-firmware-development 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/<id>, 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/<platform>/<binary>.elf. The old elf/<platform>.elf archive layout produces a loader Not executable error.

  • Manifest v0.2: bin/esp32s3/app.elf
  • Manifest v0.3: bin/esp32s3/<app.0.binary>.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:

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 <device-id>
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:

curl -fsS http://<ip>/api/sysinfo
curl -fsS http://<ip>/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:

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.