241 lines
12 KiB
Markdown
241 lines
12 KiB
Markdown
# AGENTS.md
|
|
|
|
## Purpose
|
|
|
|
This repository contains firmware and a web application for an ESP32-C6 Mini built with Visual Studio Code and PlatformIO.
|
|
|
|
These instructions are intended for Codex and other coding agents working in this repository. Prefer small, reviewable changes and keep the firmware suitable for a resource-constrained embedded device.
|
|
|
|
## Sources and instruction scope
|
|
|
|
- Treat every file under `sources/` as read-only reference material.
|
|
- Do not edit, rename, move, or delete files under `sources/`.
|
|
- Files under `sources/` may be replaced when the ChatGPT project is synchronized.
|
|
- A more deeply nested `AGENTS.md`, if present, takes precedence for files in its directory tree.
|
|
- Read `MVP.md` before making architectural or gameplay changes.
|
|
- Once present, treat `platformio.ini` as the source of truth for the PlatformIO environments, board identifier, framework, build flags, dependency versions, flash layout, and upload settings.
|
|
- Do not assume that every board sold as “ESP32-C6 Mini” has the same flash size, pinout, LED polarity, or PlatformIO board identifier.
|
|
|
|
## Expected project layout
|
|
|
|
Use the conventional PlatformIO layout unless the existing project deliberately uses another structure:
|
|
|
|
```text
|
|
.
|
|
├── platformio.ini # PlatformIO environments and dependencies
|
|
├── include/ # Public project headers
|
|
├── src/ # Firmware sources and main.cpp
|
|
├── lib/ # Project-specific reusable libraries
|
|
├── data/ # LittleFS web assets
|
|
├── test/ # PlatformIO unit tests
|
|
├── scripts/ # Build and validation helpers
|
|
├── MVP.md # Product and architecture requirements
|
|
└── AGENTS.md # Repository instructions
|
|
```
|
|
|
|
Do not edit generated content under `.pio/`. Do not commit build products, serial logs, local secrets, or editor-specific temporary files.
|
|
|
|
## Working method
|
|
|
|
Before editing:
|
|
|
|
1. Read the relevant requirements and existing implementation.
|
|
2. Inspect `platformio.ini` and use an existing environment instead of inventing one.
|
|
3. Search for repository conventions, existing abstractions, and tests.
|
|
4. Identify whether the change affects firmware, browser assets, the API contract, stored data, or hardware configuration.
|
|
|
|
While editing:
|
|
|
|
- Make the smallest coherent change that satisfies the request.
|
|
- Preserve unrelated user changes and avoid broad formatting rewrites.
|
|
- Keep hardware-specific values in configuration rather than scattering them through the code.
|
|
- Update documentation and tests when behavior or public interfaces change.
|
|
- Do not add a dependency when a small, clear implementation using the existing stack is sufficient.
|
|
- Pin third-party PlatformIO dependencies to known compatible versions in `platformio.ini`.
|
|
- Never patch dependency sources inside `.pio/libdeps`.
|
|
|
|
After editing:
|
|
|
|
1. Run the narrowest relevant tests.
|
|
2. Build every affected PlatformIO environment.
|
|
3. Check compiler output for new warnings, memory pressure, and image-size regressions.
|
|
4. Summarize what changed, what was verified, and anything that still requires physical hardware.
|
|
|
|
## PlatformIO commands
|
|
|
|
Use the repository's actual environment names. List environments or inspect `platformio.ini` before supplying `-e <environment>`.
|
|
|
|
Common non-destructive checks:
|
|
|
|
```sh
|
|
pio run
|
|
pio run -e <environment>
|
|
pio test
|
|
pio test -e <test-environment>
|
|
pio run -t size
|
|
```
|
|
|
|
Use project-provided formatting, linting, or validation scripts when available. Do not invent a formatting command without checking the repository configuration.
|
|
|
|
The following operations affect connected hardware and must only be performed when the user asks for them or clearly authorizes hardware interaction:
|
|
|
|
```sh
|
|
pio run -e <environment> -t upload
|
|
pio run -e <environment> -t uploadfs
|
|
pio device monitor
|
|
pio run -t erase
|
|
```
|
|
|
|
Treat flash erase as destructive. Confirm the target device and environment before uploading or erasing. Never leave a serial monitor running indefinitely.
|
|
|
|
## Firmware design rules
|
|
|
|
### Architecture
|
|
|
|
- Keep domain logic independent from Arduino callbacks and transport code where practical.
|
|
- Separate Wi-Fi, HTTP/WebSocket transport, session handling, persistence, device control, and application logic.
|
|
- Route all state-changing requests through a single validated application layer.
|
|
- Keep the ESP32 authoritative. Browser-side validation improves usability but must not enforce the only copy of a rule.
|
|
- Use explicit state machines for multi-step workflows rather than loosely related Boolean flags.
|
|
- Keep public headers small and avoid unnecessary global state.
|
|
|
|
### Memory and performance
|
|
|
|
- Prefer fixed-size arrays, fixed-width integer types, bounded buffers, and predictable ownership.
|
|
- Avoid unbounded `String` concatenation, repeated heap allocation, large temporary JSON documents, and unnecessary copies.
|
|
- Set explicit limits for sessions, WebSocket clients, request bodies, queue sizes, names, and messages.
|
|
- Parse all external input with bounds checks.
|
|
- Stream or serve files from LittleFS instead of embedding large duplicate assets in RAM.
|
|
- Measure rather than guess when changing task stacks, JSON capacity, filesystem partitions, or connection limits.
|
|
- Check final flash and RAM usage after meaningful changes.
|
|
|
|
### Timing and responsiveness
|
|
|
|
- Avoid long blocking calls and long `delay()` operations.
|
|
- Use `millis()`-based scheduling, timers, queues, or tasks for delayed work.
|
|
- Keep HTTP, WebSocket, timer, and interrupt callbacks short.
|
|
- Never perform filesystem writes, large serialization, or expensive game logic in an interrupt service routine.
|
|
- Ensure the main loop and network stack remain responsive under reconnects and multiple clients.
|
|
- Add timeouts to network and peripheral operations.
|
|
|
|
### Concurrency
|
|
|
|
- Document which task or callback owns mutable state.
|
|
- Protect state shared between callbacks or FreeRTOS tasks with an appropriate mutex, queue, or critical section.
|
|
- Do not hold locks while sending network data or performing slow I/O.
|
|
- Prefer taking a bounded snapshot before serializing state for clients.
|
|
- Make repeated requests idempotent where retries are expected.
|
|
|
|
### C++ conventions
|
|
|
|
- Follow the C++ standard and warning flags configured by the project.
|
|
- Use `enum class`, `constexpr`, `const`, fixed-width integers, and RAII where supported.
|
|
- Prefer clear value types and explicit ownership over raw heap allocation.
|
|
- Check return values from Wi-Fi, filesystem, JSON, and server operations.
|
|
- Avoid macros except for compile-time configuration, platform compatibility, or logging wrappers.
|
|
- Keep functions focused and name units in identifiers when values represent milliseconds, bytes, volts, or similar quantities.
|
|
- Do not enable exceptions or RTTI unless the project already uses and budgets for them.
|
|
|
|
### Logging and errors
|
|
|
|
- Use consistent log levels and concise messages.
|
|
- Never log Wi-Fi passwords, session tokens, private payloads, or other credentials.
|
|
- Avoid high-frequency logs in normal operation.
|
|
- Return stable machine-readable error codes from APIs and separate them from Russian user-facing messages.
|
|
- Fail safely: reject invalid commands without partially modifying application state.
|
|
|
|
## Wi-Fi and configuration
|
|
|
|
- The ESP32-C6 Mini operates as a station on the home Wi-Fi network unless requirements say otherwise.
|
|
- Keep SSIDs, passwords, tokens, certificates, and private endpoints out of tracked source files.
|
|
- Store local secrets in a gitignored file or inject them through build-time configuration.
|
|
- Provide a tracked example file with placeholder values when setup would otherwise be unclear.
|
|
- Never replace real credentials or erase device configuration unless explicitly requested.
|
|
- Reconnect with bounded exponential backoff; do not block the application indefinitely while Wi-Fi is unavailable.
|
|
- The application must handle a changing DHCP address. mDNS may be added as a convenience but must not be the only documented access method unless verified on the target network.
|
|
|
|
## Web server and browser application
|
|
|
|
- Store required HTML, CSS, and JavaScript locally in `data/` so the application does not depend on internet access or a CDN.
|
|
- Prefer framework-free browser code for small interfaces. Justify large client dependencies by a concrete requirement.
|
|
- Keep the HTTP API versionable and document changes to request and response schemas.
|
|
- Validate authentication token, role, current state, game ID, coordinates, lengths, and content type on the server.
|
|
- Generate role-specific responses. Never send hidden or privileged state and rely on CSS or JavaScript to conceal it.
|
|
- Escape user-provided text before rendering it in HTML.
|
|
- Use WebSocket for immediate updates and provide the HTTP polling fallback required by `MVP.md`.
|
|
- Implement reconnect backoff, heartbeat handling, state versioning, and full resynchronization after missed events.
|
|
- Avoid broadcasting one privileged payload to all clients; construct a safe view for each role.
|
|
- Set appropriate cache headers. Do not cache personalized API responses.
|
|
- Compress static assets during the build when supported, but keep the uncompressed sources maintainable.
|
|
- Design touch interactions for phones and tablets. Do not rely on hover or color alone.
|
|
|
|
## Filesystem and persistence
|
|
|
|
- Treat LittleFS layout and the flash partition table as part of the product configuration.
|
|
- Check mount failures and report them clearly; do not silently format a filesystem unless the product explicitly requires that behavior.
|
|
- Use atomic replace patterns for important persisted files where possible.
|
|
- Minimize flash writes and avoid writing frequently changing counters on every event.
|
|
- The MVP keeps active game state and statistics in RAM and resets them after reboot, as specified in `MVP.md`.
|
|
|
|
## Testing expectations
|
|
|
|
### Host or native tests
|
|
|
|
Keep pure application logic buildable without ESP32 hardware where practical. Unit-test at least:
|
|
|
|
- state transitions;
|
|
- bounds and malformed input;
|
|
- game or domain rules;
|
|
- random-generation invariants;
|
|
- serialization and role-specific data filtering;
|
|
- retry and idempotency behavior;
|
|
- bot or automation logic.
|
|
|
|
Use a deterministic random seed in tests and do not use the production seed as an assertion target.
|
|
|
|
### Device tests
|
|
|
|
Features involving Wi-Fi, LittleFS, WebSocket, timing, heap behavior, or peripherals require a final device check. When hardware is available, verify:
|
|
|
|
- cold boot and reconnect behavior;
|
|
- static asset loading from LittleFS;
|
|
- multiple simultaneous clients;
|
|
- WebSocket loss and HTTP fallback;
|
|
- repeated workflows without heap degradation;
|
|
- flash/RAM usage and watchdog stability;
|
|
- operation on the exact ESP32-C6 Mini variant.
|
|
|
|
Do not claim device verification when only a local build or host test was performed.
|
|
|
|
## Security and robustness
|
|
|
|
- Treat every HTTP, WebSocket, serial, and persisted value as untrusted input.
|
|
- Reject oversized, malformed, stale, unauthorized, and out-of-state requests.
|
|
- Use cryptographically strong random session tokens when the platform API provides suitable entropy.
|
|
- Do not put credentials in browser assets, logs, examples, tests, or error responses.
|
|
- Avoid undefined behavior, unchecked indexing, integer overflow, and unsafe string functions.
|
|
- Add rate or queue limits where one client could exhaust device memory or monopolize processing.
|
|
- A home network is not a security boundary. Document any deliberately simplified MVP security assumptions.
|
|
|
|
## Documentation
|
|
|
|
- Keep setup steps reproducible for a new developer using VS Code and PlatformIO.
|
|
- Document the exact board variant, USB/serial behavior, flash size, PlatformIO environment, filesystem upload step, and access URL once known.
|
|
- Update `MVP.md` only when product scope or agreed behavior changes.
|
|
- Update API documentation whenever routes, messages, events, error codes, or authorization rules change.
|
|
- Record hardware-only verification steps rather than implying they were automated.
|
|
|
|
## Definition of done
|
|
|
|
A change is complete when all applicable conditions are met:
|
|
|
|
- The requested behavior is implemented with no unrelated changes.
|
|
- Affected PlatformIO environments build successfully.
|
|
- Relevant automated tests pass.
|
|
- No new compiler warnings or exposed secrets are introduced.
|
|
- Input bounds, failure paths, reconnects, and role permissions are handled.
|
|
- Flash and RAM impact are acceptable for the target ESP32-C6 Mini.
|
|
- Web assets work without an external internet dependency.
|
|
- Documentation and examples reflect the new behavior.
|
|
- Any remaining physical-device checks are explicitly listed in the handoff.
|