Files
AutoFilm-ESP32/AGENTS.md
gronod 2458a61625 Add model-executable refactor megaplan and session phases
Lock P00–P08 with in/out scope, frozen APIs, verify commands, and
one-phase-per-session protocol for the IDF modular UI work.
2026-09-16 11:12:29 +00:00

5.4 KiB
Raw Permalink Blame History

Agent conventions — AutoFilm-ESP32

Instructions for humans and coding agents working in this repository.

Product constraints

  • Default temperatures, step times, and CW/CCW rotation counts for C41, E6, ECN-2, B&W, Custom, and B&WREV do not change unless a commit message explicitly says so and the recipe table in docs/CURRENT_STATE.md is updated in the same change.
  • The machine must always be stoppable while a step is running: keypad Esc ('X', 4 across / 4 down) and, on the S3 panel, a STOP control. Stop drops motor enable immediately, then offers Resume or return to step select.
  • UI must not block on motor motion, OneWire conversion, or melody playback.

Branch and docs

  • Integration branch is develop. Feature and refactor work is done on a branch cut from develop, then opened as a PR into develop.
  • Do not PR this work into main. main is not the day-to-day integration line.
  • Active work branch for this refactor: refactor/esp-idf-modular-ui (rebase onto develop if the branch still points at main).
  • Architecture intent: docs/CURRENT_STATE.md, docs/TARGET_ARCHITECTURE.md, docs/CICD.md.
  • Implementation sessions: docs/megaplans/REFACTOR-MEGAPLAN.md then exactly one docs/megaplans/refactor/Pxx-*.md. Do not start the next phase in the same session.
  • Do not commit secrets (Git tokens, Wi-Fi passwords, sdkconfig with provisioned keys).

Layout

Path Role
src/, include/ Legacy Arduino sources; shrink, do not grow, except bugfixes needed for the port
main/ IDF entry
components/app_* Application: process table, machine, UI
components/ui_cmd Command/event types only
components/hal_* Hardware adapters
components/board_* Pin maps and board bring-up
docs/ Design notes
.gitea/workflows/ Gitea Actions (tests + firmware builds)

New behaviour goes into components/, not into larger menu.cpp files.

Framework policy

  • Build system is ESP-IDF. PlatformIO + Arduino remains only until the IDF skeleton compiles both boards.
  • Arduino-as-component is allowed as a bridge for AccelStepper, Keypad, LiquidCrystal_I2C, OneWire, DallasTemperature.
  • Treat Arduino as debt:
    • No Arduino types (String, Keypad, AccelStepper, LiquidCrystal_I2C) in headers of app_machine, app_process, or ui_cmd.
    • Do not add new Arduino library dependencies.
    • Prefer IDF drivers (GPIO, RMT, I2C, LEDC, esp_timer, esp_lcd) for new work.
  • Two firmware flavours: board_wroom and board_jc4827w543. Gate pins and peripherals with board CMake, not #ifdef sprinkled through the state machine.

Concurrency

  • One responsibility per task: input, UI, machine, motor, temperature, audio.
  • Cross-task data: FreeRTOS queues, task notifications, atomics. No unsynchronised use of lcd / stepper / sensors.
  • ISR / stop path: set a flag, disable motor EN, xQueueSendFromISR / xTaskNotifyFromISR. No heap, no delay, no LCD from ISR.
  • Do not vTaskDelete worker tasks after startup. Do not disable the task watchdog to “make it work”.
  • vTaskDelay / esp_timer instead of busy-wait millis() loops.

UI / machine split

  • UI emits commands; machine emits events. See docs/TARGET_ARCHITECTURE.md.
  • Touch and keypad are input adapters. They produce the same commands.
  • Display adapters render events. Machine code must compile with no display driver linked (except in tests that stub HAL).

Code style

  • C11 for new IDF components; C++17 only where an existing Arduino library forces it, isolated in hal_*.
  • snake_case for new functions and files; existing camelCase stays until that file is rewritten.
  • 4-space indent to match the current tree.
  • No raw new / malloc for per-frame strings. No String concatenation on the control path.
  • Log with ESP_LOGx tags (machine, motor, ui, temp, input), not Serial.print.
  • Errors are esp_err_t across HAL boundaries.

Recipes

  • Recipe tables live in app_process (or today’s devSequence.cpp until moved).
  • Session time nudges (±5 s) are RAM overlays, not edits of the const defaults.
  • Persistent custom profiles are out of scope until designed; do not half-add NVS.

Hardware notes

  • WROOM pins are defined in the legacy config headers; do not silently reuse them on the S3 panel.
  • JC4827W543C: NV3041A 480×272 QSPI, GT911 on I²C, limited free IO. Confirm any new GPIO against the board pin table before assigning STEP/DIR/EN/1-Wire.
  • Motor enable is active LOW on the current WROOM wiring. Safe state is disabled.

Commits and review

  • Cut work from develop. Open PRs against develop.
  • Imperative commit subjects (Add machine stop notify, not Added).
  • One concern per commit when practical (HAL wrap ≠ UI rewrite ≠ recipe move).
  • Do not reformat whole legacy files in the same commit as a behaviour change.
  • If defaults would change, fail the change unless the user explicitly asked.

Tests

  • Prefer host-side tests for app_process lookup and the machine state machine with a stub motor (tests/host, CMake + CTest).
  • On-target smoke: select process, start a short Custom step, Esc mid-step, confirm EN high and Resume works.
  • CI is Gitea Actions: host tests must pass before either firmware image is built. See docs/CICD.md.
  • After tests/host exists, run it before push. After the IDF skeleton exists, a local idf.py build for the board you touched is expected.