Repository navigation
Conversation
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Max errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|---|
| ✅ ACTION | actionlint | 8 | 0 | 0 | 0.56s | ||
| ✅ BASH | bash-exec | 2 | 0 | 0 | 0.42s | ||
| ✅ BASH | shellcheck | 2 | 0 | 0 | 0.47s | ||
| ✅ BASH | shfmt | 2 | 0 | 0 | 0.01s | ||
| ✅ C | clang-format | 1 | 0 | 0 | 0.04s | ||
| ✅ C | cppcheck | 1 | 0 | 0 | 0.02s | ||
| ✅ C | cpplint | 1 | 0 | 0 | 0.25s | ||
| ✅ CPP | clang-format | 100 | 0 | 0 | 0.6s | ||
| ✅ CPP | cppcheck | 100 | 0 | 0 | 4.58s | ||
| ✅ CPP | cpplint | 100 | 0 | 0 | 5.59s | ||
| ✅ EDITORCONFIG | editorconfig-checker | 284 | 0 | 0 | 0.48s | ||
| ✅ JSON | jsonlint | 6 | 0 | 0 | 0.09s | ||
| ✅ JSON | v8r | 6 | 0 | 0 | 3.32s | ||
| markdownlint | 107 | 3 | 0 | 2.98s | |||
| ✅ YAML | yamllint | 25 | 0 | 0 | 0.69s |
Detailed Issues
⚠️ MARKDOWN / markdownlint - 3 errors
.opencode/skills/web-ui/SKILL.md:34 error MD028/no-blanks-blockquote Blank line inside blockquote
docs/superpowers/plans/2026-08-10-olimex-c6-local-ui-implementation.md:106:401 error MD013/line-length Line length [Expected: 400; Actual: 452]
docs/superpowers/plans/2026-08-16-norvi-button-calibration.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 412]
Notices
MAKEFILE, MAKEFILE_CHECKMAKE, MARKDOWN_MARKDOWN_LINK_CHECK. See Removed linters to find their replacements.
See detailed reports in MegaLinter artifacts
Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)
- Documentation: Custom Flavors
- Command:
npx mega-linter-runner@10.1.0 --custom-flavor-setup --custom-flavor-linters ACTION_ACTIONLINT,BASH_EXEC,BASH_SHELLCHECK,BASH_SHFMT,C_CPPCHECK,C_CPPLINT,C_CLANG_FORMAT,CPP_CPPCHECK,CPP_CPPLINT,CPP_CLANG_FORMAT,EDITORCONFIG_EDITORCONFIG_CHECKER,JSON_JSONLINT,JSON_V8R,MARKDOWN_MARKDOWNLINT,YAML_YAMLLINT

Show us your support by starring ⭐ the repository
- TelemetryQueue: fixed-capacity single-producer/single-consumer ring buffer for cross-core publish requests (control loop -> PublishTask) - SensorSlots: lock-free temperature slots (SensorTask -> readers), volatile word-sized fields are atomic on ESP32 - Native tests for both, wired into test/native build (84 suites green)
Native Test Coverage
Report from native unit tests (ASan + gcov). |
stritti
left a comment
There was a problem hiding this comment.
Reviewed the current head b6894da against the ESP32 reliability, concurrency, and Clean-Code rules. The multicore direction is good, but I see several merge blockers in the current implementation:
-
TelemetryQueue has an out-of-bounds ring-buffer bug.
items_is declared asitems_[CAPACITY]withCAPACITY == 8, but head/tail advance moduloCAPACITY + 1. Index 8 is therefore reachable anditems_[8]can be read/written after wrap-around. This is real memory corruption. Please either allocateCAPACITY + 1storage or implement the full/empty scheme with indices constrained to[0, CAPACITY-1]. Add a wrap-around regression test (fill -> dequeue -> enqueue -> drain) because the current tests do not exercise this path. -
The dedicated-bus
esp32devpath does not start the pool sensor conversion.SensorTaskonly callssolarTemperatureNode.beginMeasurement(), waits, and then callsfinishMeasurement()on both nodes. That works for the shared NORVI bus, but onesp32devsolar and pool use separateDallasTemperatureinstances, so the pool bus needs its ownbeginMeasurement()before the wait/read phase. Please model shared-bus and dedicated-bus scheduling explicitly and test both hardware topologies. -
volatileis being used as cross-core synchronization.SensorSlots,DegradationManager, and display flags rely on word-sizedvolatilereads/writes.volatiledoes not provide C++ inter-task/inter-core synchronization or ordering.SensorSlotsalso publishesvalueandfoundindependently, so readers can observe a mixed snapshot. Please usestd::atomicwhere a single value is sufficient, or a proper snapshot/sequence-counter/FreeRTOS synchronization mechanism for related fields. -
PublishTask introduces concurrent access to MQTT/application state.
PublishTaskcallsMqttPublisher::publishDiscovery()/publishStates()on Core 0, while MQTT command callbacks can still executehandleMqttMessage()and callpublishStates()/ mutateOperationModeNode,ConfigManager, etc. This breaks the intended single-writer architecture. The later command-queue approach from #209 should be incorporated conceptually so both inbound commands and outbound publishing have explicit task ownership. -
Task creation failures are ignored. All
xTaskCreatePinnedToCore()return values should be checked. If SensorTask fails to start after sensor handling has been removed from the control loop, the controller silently runs without fresh sensor data. A critical task startup failure needs a defined safe failure path and should be testable. -
The PR is significantly behind current
main. Its base SHA is still1870c3ewhilemainhas moved substantially, including MQTT, OTA, sensor-recovery and reliability changes. I would rebase/update this architecture onto currentmainbefore doing deeper integration work; otherwise several fixes in newer PRs will conflict with assumptions made here.
The architectural goal itself is worth keeping: moving sensor conversion and OLED I/O off the safety-critical control loop is a good fit for ESP32. I would not merge this implementation until the memory-safety and cross-core ownership issues above are resolved.
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
1 similar comment
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Head and tail advance modulo CAPACITY + 1 (one free slot tells full from empty), but the storage only had CAPACITY slots, so index 8 was written and read after wrap-around. Size the storage CAPACITY + 1 and add a fill/dequeue/enqueue/drain wrap-around test (ASan flags the old code). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SkKZgzzbP5Tq235ytaiKfi
SensorTask only called beginMeasurement() on the solar node. On the shared NORVI bus that starts the conversion for both sensors, but on esp32dev each sensor has its own bus, so the pool sensor was read without a conversion. runDallasMeasurementCycle() now begins both measurements before the single wait; tests cover both topologies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SkKZgzzbP5Tq235ytaiKfi
…zation SensorSlots copies value and found flag together under a portMUX critical section (std::mutex natively) and offers snapshot(), so readers never see a mixed pair; the OLED uses snapshots. Sensor status flags in DegradationManager and the display redraw/render flags are std::atomic, and render() resets the redraw flag with exchange() so a request cannot be lost. Adds a concurrent writer/reader test for SensorSlots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SkKZgzzbP5Tq235ytaiKfi
Task start functions return whether xTaskCreatePinnedToCore() succeeded. decideTaskStartupAction() (TaskStartupPolicy.hpp, tested) defines the failure path: a missing SensorTask or PublishTask restarts the controller, a persistent failure ends in boot-loop safe mode; a missing DisplayTask is logged and the controller continues without OLED. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SkKZgzzbP5Tq235ytaiKfi
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SkKZgzzbP5Tq235ytaiKfi
|
Status of the review points (commits
Generated by Claude Code |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
stritti
left a comment
There was a problem hiding this comment.
Die Architektur geht in die richtige Richtung, ist auf dem aktuellen Head aber noch nicht merge-reif. Die neuen Core-0-Tasks greifen weiterhin auf mutable Core-1-Zustände und auf den Dallas/OneWire-Bus ohne vollständige Ownership-Grenze zu. Zusätzlich ist der DS18B20-Zyklus nicht tatsächlich asynchron und die bisherige 5-s-Recovery-Kadenz geht verloren.
Blockierend:
- PublishTask/DisplayTask lesen mutable Loop-Singletons cross-core ohne Snapshot/Lock.
- DallasTemperature/OneWire wird nach der Auslagerung weiterhin von Core 1 über Web/MQTT angesprochen.
Weitere funktionale Regressionen:
3. DallasTemperature 4.0.6 wartet standardmäßig bereits in requestTemperatures(); die zusätzliche 800-ms-Wartephase verdoppelt die Blockierzeit des SensorTasks.
4. Bei fehlendem Sensor wird nicht mehr mit RECOVERY_INTERVAL=5 s gemessen, sondern mit loopInterval, standardmäßig 10 s.
Die CI ist grün, kann diese Hardware-/Concurrency-Probleme aber nicht abdecken. Die im PR beschriebenen On-Device-Prüfungen sind außerdem noch offen.
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
1 similar comment
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Architekturhinweise und Follow-up-PlanDer aktuelle Head von #170 setzt die entscheidende Multicore-Grenze inzwischen richtig: OneWire/Dallas gehört nach dem Start exklusiv dem Scope von #170#170 soll nur die sichere Multicore-Basis liefern und nicht gleichzeitig den gesamten Controller architektonisch umbauen. Vor dem Merge sollten deshalb nur noch Inkonsistenzen innerhalb dieses Scopes bereinigt werden:
Architekturregeln für die Folgearbeiten
Geplante Folge-PRs
Wichtig für die Reihenfolge: Datei-/Verzeichnisverschiebungen erst nach der Entkopplung. Der reine Layer-Ordnerumbau ohne vorherige Dependency-Grenzen bringt wenig und erschwert die Reviews. Damit bleibt #170 klein genug, um die Concurrency-Änderung separat zu verifizieren, während die strukturelle Entkopplung in eigenständigen PRs reviewbar bleibt. |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
Angelegte Architektur-PRs und ReihenfolgeDie Architekturarbeit ist jetzt in eigenständige, reviewbare Schritte zerlegt:
Empfohlene Merge-Reihenfolge
#215/#216/#217 sind nach #214 weitgehend unabhängig und können parallel reviewed werden. #219 und #220 sind ebenfalls fachlich getrennt, sollten aber vor #221 abgeschlossen sein. Die Draft-PRs #218-#221 enthalten absichtlich zunächst OpenSpec/Design/Tasks. Damit sind Scope, Invarianten und Hardware-/Safety-Verifikation festgelegt, bevor Produktivcode in große Refactorings gezogen wird. |
Native Test Coverage
Report from native unit tests (ASan + gcov). |
|
Review-Nacharbeit zum aktuellen Architekturhinweis ist auf Head
Verifikation für
Die weitergehenden Architekturvorschläge aus dem Review (Command Dispatcher / Runtime Snapshot / MQTT-Presentation-Split etc.) behandle ich als separate Follow-up-PRs und nicht als Scope-Erweiterung von #170. |
Architektur-Follow-up aktualisiertDie Nacharbeit aus der CI-/Review-Prüfung ist umgesetzt:
Aktualisierte Reihenfolge
#213 entfällt aus der Merge-Reihenfolge, weil seine Änderungen bereits Bestandteil von #170 sind. |
Final architecture
This PR isolates only blocking sensor acquisition on ESP32 Core 0. Mutable application state remains single-writer on the Arduino control-loop task on Core 1.
Core 0
SensorTaskowns DS18B20 / OneWire access and the internal ESP32 temperature acquisition.SensorSlots.SensorTaskis registered with the task watchdog.Core 1
MqttCommandQueue; command processing andMqttPublisherserialization run on Core 1.TelemetryQueuedefers publish requests, but is drained directly byPoolController::loop()on Core 1.DisplayCoordinatoron Core 1.The earlier three-worker design (
SensorTask+PublishTask+DisplayTask) was deliberately narrowed during concurrency review. ObsoletePublishTask,DisplayTaskandTaskStartupPolicyartifacts have been removed.CoreSchedulernow owns onlySensorTasklifecycle and stack-watermark logging.Reliability fixes included
TelemetryQueuewrap-around storage.setWaitForConversion(false).volatilepairs.Verification
CI is expected to cover:
esp32dev,norvi_ae01_r,olimex_esp32_c6_evbManual verification (on-device)
The following checks intentionally remain open until verified on real hardware: