align AI instructions with upstream
some updates coming from ongoing work
This commit is contained in:
13
.github/agent-build.instructions.md
vendored
13
.github/agent-build.instructions.md
vendored
@@ -11,7 +11,7 @@ Use these timeout values when running builds:
|
|||||||
|
|
||||||
| Command | Typical Time | Minimum Timeout | Notes |
|
| Command | Typical Time | Minimum Timeout | Notes |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `npm run build` | ~3 s | 30 s | Web UI → `wled00/html_*.h` headers |
|
| `npm run build` | ~3 s | 30 s | Web UI → `wled00/html_*.h` `wled00/js_*.h` headers |
|
||||||
| `npm test` | ~40 s | 2 min | Validates build system |
|
| `npm test` | ~40 s | 2 min | Validates build system |
|
||||||
| `npm run dev` | continuous | — | Watch mode, auto-rebuilds on changes |
|
| `npm run dev` | continuous | — | Watch mode, auto-rebuilds on changes |
|
||||||
| `pio run -e <env>` | 15–20 min | 30 min | First build downloads toolchains; subsequent builds are faster |
|
| `pio run -e <env>` | 15–20 min | 30 min | First build downloads toolchains; subsequent builds are faster |
|
||||||
@@ -23,13 +23,13 @@ Use these timeout values when running builds:
|
|||||||
### Web UI Changes
|
### Web UI Changes
|
||||||
|
|
||||||
1. Edit files in `wled00/data/`
|
1. Edit files in `wled00/data/`
|
||||||
2. Run `npm run build` to regenerate `wled00/html_*.h` headers
|
2. Run `npm run build` to regenerate `wled00/html_*.h` `wled00/js_*.h` headers
|
||||||
3. Test with local HTTP server (see Manual Testing below)
|
3. Test with local HTTP server (see Manual Testing below)
|
||||||
4. Run `npm test` to validate
|
4. Run `npm test` to validate
|
||||||
|
|
||||||
### Firmware Changes
|
### Firmware Changes
|
||||||
|
|
||||||
1. Edit files in `wled00/` (but **never** `html_*.h` files)
|
1. Edit files in `wled00/` (but **never** `html_*.h` and `js_*.h` files)
|
||||||
2. Ensure web UI is built first: `npm run build`
|
2. Ensure web UI is built first: `npm run build`
|
||||||
3. Build firmware: `pio run -e esp32_4MB_V4_M` (set timeout ≥ 30 min)
|
3. Build firmware: `pio run -e esp32_4MB_V4_M` (set timeout ≥ 30 min)
|
||||||
4. Flash to device: `pio run -e [target] --target upload`
|
4. Flash to device: `pio run -e [target] --target upload`
|
||||||
@@ -85,8 +85,8 @@ Test these scenarios after every web UI change:
|
|||||||
### Recovery Steps
|
### Recovery Steps
|
||||||
|
|
||||||
- **Force web UI rebuild**: `npm run build -- -f`
|
- **Force web UI rebuild**: `npm run build -- -f`
|
||||||
- **Clear generated files**: `rm -f wled00/html_*.h` then `npm run build`
|
- **Clear generated files**: `rm -f wled00/html_*.h wled00/js_*.h` then `npm run build`
|
||||||
- **Clean PlatformIO cache**: `pio run --target clean`
|
- **Clean PlatformIO build artifacts**: `pio run --target clean`
|
||||||
- **Reinstall Node deps**: `rm -rf node_modules && npm ci`
|
- **Reinstall Node deps**: `rm -rf node_modules && npm ci`
|
||||||
|
|
||||||
## CI/CD Validation
|
## CI/CD Validation
|
||||||
@@ -106,7 +106,8 @@ Match this workflow in local development to catch failures before pushing.
|
|||||||
|
|
||||||
## Important Reminders
|
## Important Reminders
|
||||||
|
|
||||||
- **Never edit or commit** `wled00/html_*.h` — auto-generated from `wled00/data/`
|
- Always **commit source code**
|
||||||
|
- **Never edit or commit** `wled00/html_*.h` and `wled00/js_*.h` — auto-generated from `wled00/data/`
|
||||||
- Web UI rebuild is part of the PlatformIO firmware compilation pipeline
|
- Web UI rebuild is part of the PlatformIO firmware compilation pipeline
|
||||||
- Common firmware environments: `esp32_4MB_V4_M`, `esp32_16MB_V4_S_HUB75`, `esp32S3_8MB_PSRAM_M_qspi`, `esp32_16MB_V4_M_eth`, `esp8266_4MB_S` (deprecated), `esp32dev_compat`
|
- Common firmware environments: `esp32_4MB_V4_M`, `esp32_16MB_V4_S_HUB75`, `esp32S3_8MB_PSRAM_M_qspi`, `esp32_16MB_V4_M_eth`, `esp8266_4MB_S` (deprecated), `esp32dev_compat`
|
||||||
- List all PlatformIO targets: `pio run --list-targets`
|
- List all PlatformIO targets: `pio run --list-targets`
|
||||||
|
|||||||
2
.github/cicd.instructions.md
vendored
2
.github/cicd.instructions.md
vendored
@@ -71,6 +71,8 @@ schedule:
|
|||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
|
Important: Several current workflows still violate parts of the baseline below - migration is in progress.
|
||||||
|
|
||||||
### Permissions — Least Privilege
|
### Permissions — Least Privilege
|
||||||
|
|
||||||
Declare explicit `permissions:` blocks. The default token permissions are broad; scope them to the minimum required:
|
Declare explicit `permissions:` blocks. The default token permissions are broad; scope them to the minimum required:
|
||||||
|
|||||||
28
.github/copilot-instructions.md
vendored
28
.github/copilot-instructions.md
vendored
@@ -40,22 +40,19 @@ Always reference these instructions first and fallback to search or bash command
|
|||||||
|
|
||||||
<!-- HUMAN_ONLY_END -->
|
<!-- HUMAN_ONLY_END -->
|
||||||
|
|
||||||
**Always run `npm ci; npm run build` before `pio run`.** The web UI build generates `wled00/html_*.h` header files required by firmware compilation.
|
- **Always run `npm ci; npm run build` before `pio run`.** The web UI build generates `wled00/html_*.h` header files required by firmware compilation.
|
||||||
**Build firmware to validate code changes**: `pio run -e esp32_4MB_V4_M` — must succeed, never skip this step.
|
- **Build firmware to validate code changes**: `pio run -e esp32_4MB_V4_M` — must succeed, never skip this step.
|
||||||
Common firmware environments: `esp32_4MB_V4_M`, `esp32_16MB_V4_S_HUB75`, `esp32S3_8MB_PSRAM_M_qspi`, `esp32_16MB_V4_M_eth`, `esp32dev_compat`, `esp8266_4MB_S` (deprecated)
|
- Common firmware environments: `esp32_4MB_V4_M`, `esp32_16MB_V4_S_HUB75`, `esp32S3_8MB_PSRAM_M_qspi`, `esp32_16MB_V4_M_eth`, `esp32dev_compat`, `esp8266_4MB_S` (deprecated)
|
||||||
|
|
||||||
For detailed build timeouts, development workflows, troubleshooting, and validation steps, see [agent-build.instructions.md](agent-build.instructions.md).
|
For detailed build timeouts, development workflows, troubleshooting, and validation steps, see [agent-build.instructions.md](agent-build.instructions.md).
|
||||||
|
|
||||||
## Repository Structure
|
## Repository Structure
|
||||||
|
|
||||||
tl;dr:
|
tl;dr:
|
||||||
* Firmware source: `wled00/` (C++).
|
* Firmware source: `wled00/` (C++). Web UI source: `wled00/data/`. Build targets: `platformio.ini`.
|
||||||
* Build targets: `platformio.ini`.
|
* Auto-generated headers: `wled00/html_*.h` and `wled00/js_*.h` — **never edit or commit**.
|
||||||
* Web UI source: `wled00/data/`.
|
* ArduinoJSON + AsyncJSON: `wled00/src/dependencies/json`. CI/CD: `.github/workflows/`.
|
||||||
* Auto-generated headers: `wled00/html_*.h` — **never edit or commit**.
|
|
||||||
* ArduinoJSON + AsyncJSON: `wled00/src/dependencies/json`
|
|
||||||
* Usermods: `usermods/` (`.h` files, included via `usermods_list.cpp`).
|
* Usermods: `usermods/` (`.h` files, included via `usermods_list.cpp`).
|
||||||
* CI/CD: `.github/workflows/`.
|
|
||||||
|
|
||||||
Main development trunk: `mdev` branch. Make PRs against this branch.
|
Main development trunk: `mdev` branch. Make PRs against this branch.
|
||||||
|
|
||||||
@@ -81,27 +78,30 @@ tools/cdata-test.js # Test suite
|
|||||||
package.json # Node.js scripts and release ID
|
package.json # Node.js scripts and release ID
|
||||||
.github/workflows/ # CI/CD pipelines
|
.github/workflows/ # CI/CD pipelines
|
||||||
```
|
```
|
||||||
<!-- HUMAN_ONLY_END -->
|
|
||||||
|
|
||||||
|
<!-- HUMAN_ONLY_END -->
|
||||||
## General Guidelines
|
## General Guidelines
|
||||||
|
|
||||||
- **Never edit or commit** `wled00/html_*.h` — auto-generated from `wled00/data/`.
|
|
||||||
- **Repository language is English.** Suggest translations for non-English content.
|
- **Repository language is English.** Suggest translations for non-English content.
|
||||||
- **Use VS Code with PlatformIO extension** for best development experience.
|
- **Use VS Code with PlatformIO extension** for best development experience.
|
||||||
|
- **Never edit or commit** `wled00/html_*.h` and `wled00/js_*.h` — auto-generated from `wled00/data/`.
|
||||||
|
- If updating Web UI files in `wled00/data/`, **make use of common functions in `wled00/data/common.js` whenever possible**.
|
||||||
- **When unsure, say so.** Gather more information rather than guessing.
|
- **When unsure, say so.** Gather more information rather than guessing.
|
||||||
- **Acknowledge good patterns** when you see them. Summarize good practices as part of your review - positive feedback always helps.
|
- **Acknowledge good patterns** when you see them. Summarize good practices as part of your review - positive feedback always helps.
|
||||||
- **Provide references** when making analyses or recommendations. Base them on the correct branch or PR.
|
- **Provide references** when making analyses or recommendations. Base them on the correct branch or PR.
|
||||||
- **Look for user-visible breaking changes and ripple effects**. Ask for confirmation that these were introduced intentionally.
|
- **Highlight user-visible breaking changes and ripple effects**. Ask for confirmation that these were introduced intentionally.
|
||||||
- **Unused / dead code must be justified or removed**. This helps to keep the codebase clean, maintainable and readable.
|
- **Unused / dead code must be justified or removed**. This helps to keep the codebase clean, maintainable and readable.
|
||||||
- **C++ formatting available**: `clang-format` is installed but not in CI
|
- **C++ formatting available**: `clang-format` is installed but not in CI
|
||||||
- No automated linting is configured — match existing code style in files you edit. See `cpp.instructions.md` and `web.instructions.md` for language-specific conventions, and `cicd.instructions.md` for GitHub Actions workflows.
|
- No automated linting is configured — match existing code style in files you edit.
|
||||||
|
|
||||||
|
See `cpp.instructions.md`, `esp-idf.instructions.md` and `web.instructions.md` for language-specific conventions, and `cicd.instructions.md` for GitHub Actions workflows.
|
||||||
|
|
||||||
### Attribution for AI-generated code
|
### Attribution for AI-generated code
|
||||||
Using AI-generated code can hide the source of the inspiration / knowledge / sources it used.
|
Using AI-generated code can hide the source of the inspiration / knowledge / sources it used.
|
||||||
- Document attribution of inspiration / knowledge / sources used in the code, e.g. link to GitHub repositories or other websites describing the principles / algorithms used.
|
- Document attribution of inspiration / knowledge / sources used in the code, e.g. link to GitHub repositories or other websites describing the principles / algorithms used.
|
||||||
- When a larger block of code is generated by an AI tool, mark it with an `// AI: below section was generated by an AI` comment (see C++ guidelines).
|
- When a larger block of code is generated by an AI tool, mark it with an `// AI: below section was generated by an AI` comment (see C++ guidelines).
|
||||||
- Every non-trivial AI-generated function should have a brief comment describing what it does. Explain parameters when their names alone are not self-explanatory.
|
- Every non-trivial AI-generated function should have a brief comment describing what it does. Explain parameters when their names alone are not self-explanatory.
|
||||||
- AI-generated code must be well documented; comment-to-code ratio > 15% is expected. Do not rephrase source code, but explain the concepts/logic behind the code.
|
- AI-generated code must be well documented with meaningful comments that explain intent, assumptions, and non-obvious logic. Do not rephrase source code; explain concepts and reasoning.
|
||||||
|
|
||||||
### Pull Request Expectations
|
### Pull Request Expectations
|
||||||
|
|
||||||
|
|||||||
40
.github/cpp.instructions.md
vendored
40
.github/cpp.instructions.md
vendored
@@ -18,13 +18,13 @@ See also: [CONTRIBUTING.md](../CONTRIBUTING.md) for general style guidelines tha
|
|||||||
- Space between keyword and parenthesis: `if (...)`, `for (...)`. No space between function name and parenthesis: `doStuff(a)`
|
- Space between keyword and parenthesis: `if (...)`, `for (...)`. No space between function name and parenthesis: `doStuff(a)`
|
||||||
- No enforced line-length limit; wrap when a line exceeds your editor width
|
- No enforced line-length limit; wrap when a line exceeds your editor width
|
||||||
|
|
||||||
<!-- HUMAN_ONLY_START -->
|
|
||||||
## Naming
|
## Naming
|
||||||
|
|
||||||
- **camelCase** for functions and variables: `setValuesFromMainSeg()`, `effectCurrent`
|
- **camelCase** for functions and variables: `setValuesFromMainSeg()`, `effectCurrent`
|
||||||
- **PascalCase** for classes and structs: `PinManagerClass`, `BusConfig`
|
- **PascalCase** for classes and structs: `PinManagerClass`, `BusConfig`
|
||||||
- **UPPER_CASE** for macros and constants: `WLED_MAX_USERMODS`, `DEFAULT_CLIENT_SSID`
|
- **UPPER_CASE** for macros and constants: `WLED_MAX_USERMODS`, `DEFAULT_CLIENT_SSID`
|
||||||
|
|
||||||
|
<!-- HUMAN_ONLY_START -->
|
||||||
## Header Guards
|
## Header Guards
|
||||||
|
|
||||||
Most headers use `#ifndef` / `#define` guards. Some newer headers add `#pragma once` before the guard:
|
Most headers use `#ifndef` / `#define` guards. Some newer headers add `#pragma once` before the guard:
|
||||||
@@ -64,6 +64,7 @@ void calculateCRC(const uint8_t* data, size_t len) {
|
|||||||
Single-line AI-assisted edits do not need the marker — use it when the AI produced a contiguous block that a human did not write line-by-line.
|
Single-line AI-assisted edits do not need the marker — use it when the AI produced a contiguous block that a human did not write line-by-line.
|
||||||
|
|
||||||
<!-- HUMAN_ONLY_START -->
|
<!-- HUMAN_ONLY_START -->
|
||||||
|
<!-- hidden from AI for now, as it created too many "please add a description" review findings in my first tests -->
|
||||||
- **Function & feature comments:** Every non-trivial function should have a brief comment above it describing what it does. Include a note about each parameter when the names alone are not self-explanatory:
|
- **Function & feature comments:** Every non-trivial function should have a brief comment above it describing what it does. Include a note about each parameter when the names alone are not self-explanatory:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@@ -77,7 +78,6 @@ uint8_t gammaCorrect(uint8_t value, float gamma);
|
|||||||
```
|
```
|
||||||
<!-- HUMAN_ONLY_END -->
|
<!-- HUMAN_ONLY_END -->
|
||||||
|
|
||||||
|
|
||||||
Short accessor-style functions (getters/setters, one-liners) may skip this if their purpose is obvious from the name.
|
Short accessor-style functions (getters/setters, one-liners) may skip this if their purpose is obvious from the name.
|
||||||
|
|
||||||
## Preprocessor & Feature Flags
|
## Preprocessor & Feature Flags
|
||||||
@@ -106,12 +106,38 @@ uint8_t gammaCorrect(uint8_t value, float gamma);
|
|||||||
- **PSRAM-aware allocation**: use `d_malloc()` (prefer DRAM), `p_malloc()` (prefer PSRAM) from `util.h`
|
- **PSRAM-aware allocation**: use `d_malloc()` (prefer DRAM), `p_malloc()` (prefer PSRAM) from `util.h`
|
||||||
- **Avoid Variable Length Arrays (VLAs)**: FreeRTOS task stacks are typically 2–8 KB. A runtime-sized VLA can silently exhaust the stack. Use fixed-size arrays or heap allocation (`d_malloc` / `p_malloc`). Any VLA must be explicitly justified in source or PR.
|
- **Avoid Variable Length Arrays (VLAs)**: FreeRTOS task stacks are typically 2–8 KB. A runtime-sized VLA can silently exhaust the stack. Use fixed-size arrays or heap allocation (`d_malloc` / `p_malloc`). Any VLA must be explicitly justified in source or PR.
|
||||||
<!-- HUMAN_ONLY_START -->
|
<!-- HUMAN_ONLY_START -->
|
||||||
GCC/Clang support VLAs as an extension (they are not part of the C++ standard), so they look like a legitimate feature — but they are allocated on the stack at runtime. On ESP32/ESP8266, a VLA whose size depends on a runtime parameter (segment dimensions, pixel counts, etc.) can silently exhaust the stack and cause the program to behave in unexpected ways or crash.
|
GCC/Clang support VLAs as an extension (they are not part of the C++ standard), so they look like a legitimate feature — but they are allocated on the stack at runtime. On ESP32/ESP8266, a VLA whose size depends on a runtime parameter (segment dimensions, pixel counts, etc.) can silently exhaust the stack and cause the program to behave in unexpected ways or crash.
|
||||||
<!-- HUMAN_ONLY_END -->
|
<!-- HUMAN_ONLY_END -->
|
||||||
- **Larger buffers** (LED data, JSON documents) should use PSRAM when available and technically feasible
|
- **Larger buffers** (LED data, JSON documents) should use PSRAM when available and technically feasible
|
||||||
- **Hot-path**: some data should stay in DRAM or IRAM for performance reasons
|
- **Hot-path**: some data should stay in DRAM or IRAM for performance reasons
|
||||||
- Memory efficiency matters, but is less critical on boards with PSRAM
|
- Memory efficiency matters, but is less critical on boards with PSRAM
|
||||||
|
|
||||||
|
Heap fragmentation is a concern:
|
||||||
|
<!-- HUMAN_ONLY_START -->
|
||||||
|
- Fragmentation can lead to crashes, even when the overall amount of available heap is still good. The C++ runtime doesn't do any "garbage collection".
|
||||||
|
<!-- HUMAN_ONLY_END -->
|
||||||
|
- Avoid frequent `d_malloc` and `d_free` inside a function, especially for small sizes.
|
||||||
|
- Avoid frequent creation / destruction of objects.
|
||||||
|
- Allocate buffers early, and try to re-use them.
|
||||||
|
- Instead of incrementally appending to a `String`, reserve the expected max buffer upfront by using the `reserve()` method.
|
||||||
|
<!-- HUMAN_ONLY_START -->
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
String result;
|
||||||
|
result.reserve(65); // pre-allocate to avoid realloc fragmentation
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// prefer DRAM; falls back gracefully and enforces MIN_HEAP_SIZE guard
|
||||||
|
_ledsDirty = (byte*) d_malloc(getBitArrayBytes(_len));
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
_mode.reserve(_modeCount); // allocate memory to prevent initial fragmentation - does not increase size()
|
||||||
|
_modeData.reserve(_modeCount); // allocate memory to prevent initial fragmentation - does not increase size()
|
||||||
|
```
|
||||||
|
<!-- HUMAN_ONLY_END -->
|
||||||
|
|
||||||
## `const` and `constexpr`
|
## `const` and `constexpr`
|
||||||
Add `const` to cached locals in hot-path code (helps the compiler keep values in registers). Pass and store objects by `const&` to avoid copies in loops.
|
Add `const` to cached locals in hot-path code (helps the compiler keep values in registers). Pass and store objects by `const&` to avoid copies in loops.
|
||||||
|
|
||||||
@@ -175,6 +201,12 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit");
|
|||||||
#error "WLED_MAX_BUSSES exceeds hard limit"
|
#error "WLED_MAX_BUSSES exceeds hard limit"
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// using static_assert() to validate enumerated types (zero cost at runtime)
|
||||||
|
static_assert(0u == static_cast<uint8_t>(PinOwner::None),
|
||||||
|
"PinOwner::None must be zero, so default array initialization works as expected");
|
||||||
|
```
|
||||||
<!-- HUMAN_ONLY_END -->
|
<!-- HUMAN_ONLY_END -->
|
||||||
|
|
||||||
Prefer `constexpr` over `#define` for typed constants (scope-safe, debuggable). Use `static_assert` instead of `#if … #error` for compile-time validation.
|
Prefer `constexpr` over `#define` for typed constants (scope-safe, debuggable). Use `static_assert` instead of `#if … #error` for compile-time validation.
|
||||||
@@ -530,7 +562,7 @@ Prefer blocking FreeRTOS primitives (`xQueueReceive`, `ulTaskNotifyTake`, `vTask
|
|||||||
- If possible, use `static` for local (C-style) variables and functions (keeps the global namespace clean)
|
- If possible, use `static` for local (C-style) variables and functions (keeps the global namespace clean)
|
||||||
- Avoid unexplained "magic numbers". Prefer named constants (`constexpr`) or C-style `#define` constants for repeated numbers that have the same meaning
|
- Avoid unexplained "magic numbers". Prefer named constants (`constexpr`) or C-style `#define` constants for repeated numbers that have the same meaning
|
||||||
- Include `"wled.h"` as the primary project header where needed
|
- Include `"wled.h"` as the primary project header where needed
|
||||||
- **Float-to-unsigned conversion is undefined behavior when the value is out of range.** Converting a negative `float` directly to an unsigned integer type (`uint8_t`, `uint16_t`, …) is UB per the C++ standard — the Xtensa (ESP32) toolchain may silently wrap, but RISC-V (ESP32-C3/C6) can produce different results due to clamping. Cast through a signed integer first:
|
- **Float-to-unsigned conversion is undefined behavior when the value is out of range.** Converting a negative `float` directly to an unsigned integer type (`uint8_t`, `uint16_t`, …) is UB per the C++ standard — the Xtensa (ESP32) toolchain may silently wrap, but RISC-V (ESP32-C3/C5/C6/P4) can produce different results due to clamping. Cast through a signed integer first:
|
||||||
```cpp
|
```cpp
|
||||||
// Undefined behavior — avoid:
|
// Undefined behavior — avoid:
|
||||||
uint8_t angle = 40.74f * atan2f(dy, dx); // negative float → uint8_t is UB
|
uint8_t angle = 40.74f * atan2f(dy, dx); // negative float → uint8_t is UB
|
||||||
|
|||||||
5
.github/web.instructions.md
vendored
5
.github/web.instructions.md
vendored
@@ -24,5 +24,6 @@ applyTo: "wled00/data/**"
|
|||||||
|
|
||||||
## Build Integration
|
## Build Integration
|
||||||
|
|
||||||
Files in this directory are processed by `tools/cdata.js` into `wled00/html_*.h` headers.
|
Files in this directory are processed by `tools/cdata.js` into generated headers
|
||||||
Run `npm run build` after any change. **Never edit the generated `html_*.h` files directly.**
|
(`wled00/html_*.h`, `wled00/js_*.h`).
|
||||||
|
Run `npm run build` after any change. **Never edit generated headers directly.**
|
||||||
|
|||||||
Reference in New Issue
Block a user