These instructions apply to the whole repository.
- Work as an ESP32-S3 firmware and SvelteKit UI agent for MatrixHub.
- Chat with the user in Polish. Keep code, identifiers, comments, logs, commit messages, and commands in English unless the existing file uses Polish.
- Target board/env: Waveshare ESP32-S3 Matrix, PlatformIO env
waveshare_esp32s3_matrix. - The firmware uses the Arduino framework on the pioarduino ESP32 platform, plus ESP-IDF/FreeRTOS APIs where the codebase already uses them.
- The UI is in
interface/and is embedded into firmware throughscripts/build/build_interface.py.
- Do not modify
lib/framework/unless the user explicitly asks for framework changes or the change is unavoidable and explained. - Do not modify
src/wifisensing/csi/vendor/or the prebuilt CSI vendor library unless the user explicitly asks for vendor work. - Do not change firmware logic when the task is about build speed, tooling, documentation, or PlatformIO workflow.
- Respect the existing dirty tree. Do not revert user changes or generated files you did not intentionally touch.
- Keep edits scoped. Prefer existing local patterns over new abstractions.
- For host-only code, use the
nativeenv and keep it undersrc/native/ortest/.src/native/**is intentionally excluded from the ESP32 env.
This repository is hard-bound as:
- repository id:
matrixhub; - repository:
MichalMatu/MatrixHub; - agent binding:
033327ab-700d-43b4-9b3b-caff1acaa2c7; - control branch:
agent-control.
Use this repository's own agent-control branch for tasks and evidence; never route MatrixHub work through another repository's control branch.
If Chat Bridge is active, the wake envelope must identify exactly LA_AGENT=033327ab-700d-43b4-9b3b-caff1acaa2c7, LA_REPO=matrixhub, and LA_REPOSITORY=MichalMatu/MatrixHub. Never infer or switch repositories from conversation history. A different repository requires explicit Bridge Rebind.
- Inspect
.agent/binding.jsonand.agent/status/daemon.jsononagent-controlbefore queueing work when Local Agent compatibility matters. The control binding must match the identity above. - Treat
daemon_version,self_revision,execution_model/execution_variant, current task state, andsupervisor_pidas repository-worker truth. Supervisor-wide fields such asmax_parallel_workersare not guaranteed to be repeated in every repository-worker snapshot; read the shared supervisor status when that field matters. - Queue immutable tasks under
.agent/tasks/<task-id>.json; every executable task must contain exactly"agent_binding": "033327ab-700d-43b4-9b3b-caff1acaa2c7". Follow.agent/runs/<task-id>.jsonand read.agent/results/<task-id>.jsonbefore reporting completion. - Local Agent requires local registry binding ==
.agent/binding.jsonbinding == taskagent_bindingbefore claim/execution. Missing repository binding reportsunbound; a control mismatch reportsbinding_error; missing/wrong task binding is terminally rejected before any task command runs. The serial fallback enforces the same contract. - Set
work_branchexplicitly. Follow MatrixHub Git policy: normal development is ondevelop;mainis the stable release line unless the user explicitly requests another branch. - One MatrixHub task executes at a time, but another registered repository may overlap when resource admission permits it.
- Every task must declare
resourcesexplicitly; missing, malformed, duplicated, oversized, or non-canonical declarations are terminal task-contract errors with no compatibility fallback. - Use
resources: []for repository-local software work, including PlatformIO builds/tests, when no exclusive external device or host-global state is used.memory_limit_mbis an independent RSS watchdog and does not determine resource classification. - Use stable named resources such as
board:matrixhub-s3for USB, serial, upload/flash, monitor, and hardware work so only tasks sharing that concrete resource serialize. - Use
resources: ["machine"]only for genuine whole-host operations such as global Local Agent maintenance or host-global toolchain mutation. Resource contention is a wait state and must continue withNEXT, notSTOP. - Repository workers must not perform supervisor-wide restart/self-update. The production Local Agent runtime lives on
MichalMatu/local-agent/main;agent_multirepo.pyremains the serial fallback. - Binding failures are safety evidence, not routing hints. Do not guess, rotate, or borrow another repository's binding to make a task execute.
- A successful Local Agent result proves local execution/verification, not source publication. Commit/push according to this repository's Git rules as an explicit final gate.
When the Local Agent task/control/resource/status/binding contract changes, update this section together with the canonical MichalMatu/local-agent documentation rather than relying on remembered chat context.
Prefer the helper scripts because they handle the local PlatformIO path and the optimized build settings.
| Area | Command | Notes |
|---|---|---|
| Fast firmware build | ./scripts/build-fast.sh |
Preferred iteration path. Uses waveshare_esp32s3_matrix_dev, skips UI, defaults to -j4. |
| Clean main env | ./scripts/build-clean.sh |
Cleans only waveshare_esp32s3_matrix; the next build should reuse .pio/cache when signatures match. |
| Rebuild diagnosis | ./scripts/build-explain.sh |
Writes build-explain.log using SCons --debug=explain. |
| Native tests | pio test -e native |
Use $HOME/.platformio/penv/bin/pio if pio is not in PATH. |
| Full release build | pio run -e waveshare_esp32s3_matrix |
Builds UI and firmware. Use for final artifacts or UI embed changes. |
| Upload | pio run -e waveshare_esp32s3_matrix -t upload |
Stop any active monitor first. |
| Monitor | pio device monitor |
Use after flashing to inspect runtime logs. |
Build speed facts measured on the Raspberry Pi 5 host:
- A cold full build can take about 15 minutes.
- A normal no-change build is about 38-40 seconds.
- With
.pio/cachewarmed, recreating a clean build directory is about 50 seconds instead of recompiling everything. - Do not run repeated cold clean builds unless the task specifically requires timing cache invalidation or PlatformIO/SCons behavior.
- The main env uses
lib_ldf_mode = chain. Do not switch todeepordeep+before checking missing includes and explicitlib_deps.
Detailed build notes:
BUILD_SPEED_OPTIMIZATION.mddocs/main_docs/BUILD_SPEED_OPTIMIZATION.md
Detailed agent workflows:
docs/agent-workflows/README.mddocs/agent-workflows/build.mddocs/agent-workflows/clean.mddocs/agent-workflows/core_dump.mddocs/agent-workflows/frontend-diagnostics.mddocs/agent-workflows/language_preference.mddocs/agent-workflows/new_module.mddocs/agent-workflows/tests_backend.md
Important entry path:
src/main.cppsrc/system/Application.cppsrc/system/init/core/InitSequence.cppsrc/system/services/ServiceRegistry*.cppsrc/system/init/services/*Initializer.*
Configuration and state:
src/config/System.his the aggregate include for system config.src/config/TaskConfig.howns task stack sizes, priorities, core affinity, timeouts, and task monitoring thresholds.src/config/App.h,src/config/Hardware.h, andsrc/config/Network.hhold app, board, hardware, and network constants.- Runtime JSON config serialization lives in
src/config/json/. - RTC-backed persistent structs live in
src/system/rtc/types/. - Increment
RTC::kSchemaVersioninsrc/system/rtc/RtcConfig.hwhen changing RTC struct layout.
Core module directories:
src/api/: HTTP and WebSocket API controllers.src/system/: boot, lifecycle, service registry, logging, memory, power, watchdog, health, RTC, and shutdown.src/notifications/telegram/: Telegram client, commands, queue, polling, and worker runtime.src/udp/: UDP pusher and settings.src/wifisensing/: RSSI and CSI sensing.src/ble/: BLE facade, scanning, parsing, and BLE settings.src/alarms/,src/shelly/,src/sensors/,src/matrix/,src/keyboard/,src/macros/,src/airmouse/,src/usb_terminal/, andsrc/compensation/: domain services and settings.interface/src/: SvelteKit UI routes, services, stores, components, types, and tests.
- Services are owned by
ServiceRegistryand wired during boot through the initializer classes undersrc/system/init/services/. - Keep API classes in
src/api/*transport-focused: parse requests, call services, and serialize responses. Put business logic in the domain service. - Prefer explicit dependency injection through
begin()or constructors. Avoid adding new globalexterndependencies. - Register new long-lived services in
ServiceRegistryand document ownership or shutdown implications when they matter. - Keep task stack sizes, priorities, and core choices in
CONFIG::TASKS; do not hardcodexTaskCreate*parameters inline. - Use
/rest/...for framework/system-style endpoints and/api/...for domain endpoints, matching existing routing.
- Default to PSRAM for large non-DMA, non-ISR buffers. As a rule of thumb, temporary user-space buffers over 512 bytes should use PSRAM.
- Use internal DRAM for DMA buffers, ISR-accessed data, and latency-critical small structures.
- Use
SYSTEM::SpiRamJsonDocumentfor large JSON documents and stream large API responses in chunks instead of building hugeStringobjects. - Use
heap_caps_free()for memory allocated withheap_caps_malloc(). - Avoid long-lived Arduino
Stringobjects in services, large buffers, and persistent data. Prefer fixedchar[],std::stringwith project allocators, or existing PSRAM helpers. - ISR callbacks must not allocate, block, log heavily, or take mutexes. Use fixed-size data and FreeRTOS ISR-safe queue calls.
- For CSI, keep the callback path minimal and pass
CsiPacketdata to worker tasks through the existing queue path insrc/wifisensing/csi/data/.
scripts/build/build_interface.pyalready avoids rewritinglib/framework/core/WWWData.hwhen content is unchanged. Preserve that behavior.- If adding a generator, write generated files only when bytes actually differ. Avoid timestamp-only headers that invalidate half the firmware.
- Use
custom_skip_ui = yesorSKIP_UI=1only for developer firmware iteration. Full release builds must embed the UI.
- For firmware logic that can run on host, add or update
pio test -e nativecoverage. - For ESP32-only behavior, keep tests focused and explain what was verified by build, logs, or static inspection.
- USB Terminal
target_port: "auto"has been verified end-to-end on Linux/Raspberry Pi. When working on macOS, re-test the auto port detection on real hardware. Windows and Android are not covered by the current POSIX shell auto-detection path and need separate host-mode verification or implementation. - For UI changes, follow the existing
interface/test/build workflow. Do not rebuild the UI during firmware-only work unless the UI embed is part of the task.
- Never create additional branches unless the user explicitly asks for a new branch. Commit directly on the current branch when the user asks for a commit.
- Keep
mainas the stable release line only. Do normal development ondevelop, then release by merging the completed work tomain, bumping the version, running a full release build, taggingvX.Y.Z, and pushing both the branch and tag. - Keep commits focused and do not include unrelated user changes.
- This repo may be ahead of
origin/mainif GitHub HTTPS authentication is not configured. Ifgit pushfails with a username/auth error, report it instead of rewriting remotes or history.