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

94 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.