From c4b17f52bdf296c825f98d2fd8c580a901b61ab3 Mon Sep 17 00:00:00 2001 From: ewowi Date: Tue, 6 Oct 2026 21:28:59 +0200 Subject: [PATCH 1/4] Keep core free of light headers and MoonBase on the app's address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The core no longer includes anything from the light domain: the WLED shim, MQTT and MoonStats read the light output through an interface the light domain implements. MoonBase, the recovery image, now answers on the app's static address over Ethernet and WiFi, so a device without DHCP stays reachable during an update. The code report gains rules for large stack frames, buffers allocated by hand in light, module types named in the UI and name spread, and docgen counts appendix sections nothing links to. KPI: 256lights | Desktop:2142KB | tick:1/5/7/2/7/7/267/7/7/11us(FPS:1000000/200000/142857/500000/142857/142857/3745/142857/142857/90909) | src:299(75751) | test:227(50921) | functions-over:333 Commit: src +696/-456 lines | test +296/-34 lines | code findings 1497 -> 1659 (complex function -1, large file -1, large stack frame +60, light include in core -10, long function -1, module type in the UI +69, name spread +22, raw allocation in light +24) | duplicated lines 3791 -> 3791 (+0) The code findings and docgen warnings rise only by the new rules (large stack frame, raw allocation in light, module type in the UI, name spread; appendix sections nothing refers to, 432): each is a rule whose own count starts here. Flash against the last commit: classic +2 KB, S3 +1 KB, P4 +4 KB, S31 +4 KB, mostly the null checks a noexcept operator new adds and the onListChanged vtable slot. Core - `core/util/LightOutput.h` (renamed from LightSummary.h): the device shape and the palettes as colors, implemented by Drivers and read through an ActiveInstance seat; `rgbToHueSat` moves to `color.h`, and three Palettes helpers go. - `onListChanged` hook and `Scheduler::notifyListChanged` replace the cast to Drivers after a list edit; a driver re-resolves its correction only when the fixture-profile list changed. - `core/util/ThreadSlot.h`: the per-thread slot claim, shared by the MoonLive sinks; `addControl`, its sink and `runDefineControls` move to the neutral builtins and register once for both tables. - `MoonLiveScript`, `MoonLiveScriptFile`, the script catalog and its generator, and `WLEDAudioSyncPacket` move into core; each role's new-script template lives with its binding; `Dim` sits beside `ModuleRole`. - `core/util/Ipv4.h`: the dotted-quad parser and the static-address rule, returning a fault code, shared with MoonBase; IpSettings maps it to the card's sentence. - `ModuleFactory::registerType` builds its probe on the heap, removing 32 frames over 512 bytes (5.9 KB for AudioService); `MoonModule::operator new` is noexcept, so a failed allocation returns nullptr instead of running a constructor on null. - MoonBase reads and pins the app's Ethernet and per-network WiFi static addresses on link-up, through `ConfigScrape.h`'s `SavedIp` readers. Light domain - Drivers implements `LightOutput`; the flow builtins share one `advectTrail` body. Scripts/MoonDeck - check_code: rules for large stack frames (from `-Wframe-larger-than=512` in the desktop build, read from saved findings at no extra cost), buffers allocated by hand in `src/light`, module types named in `src/ui` and name spread. - check_docgen: appendix sections no `@xref` or link reaches, as a ratcheted warning; report headings say ERRORS and WARNINGS. Tests - LightOutput seat lifecycle, WLED palette by index and color through a fake output, the list-changed hook, ThreadSlot, the heap probe, the MoonBase IP contract and scraper, and the new code and docgen rules. - The ControlModule test fixture releases its tree, so a leaked Drivers no longer holds the light-output seat for later tests. Docs/CI - Architecture: the domain boundary stands at zero through LightOutput; every light buffer is a ScratchBuffer member. - Coding standards, MoonDeck and the supporting pages describe the new rules and headers; OPEN-WORK.md goes, the plans carry their own โœ… and ๐Ÿšง. - Bench on the Olimex: no-PSRAM memory, static IP on Ethernet and WiFi, MoonBase over Ethernet and WiFi on the app's address, and a cable plugged in while on WiFi. Reviews - ๐Ÿ‘พ onListChanged costs a vtable slot per module type (~0.6 KB) โ†’ accepted: the standard per-event hook, as onFileChanged. - ๐Ÿ‘พ noexcept operator new adds a null check per new (~1.5 KB) โ†’ accepted: it is the fix for construction on null; named above as the flash delta's reason. - ๐Ÿ‘พ MoonBase carried seven sentences it never prints โ†’ done: the shared rule returns a fault code, the text stays in the app (MoonBase โˆ’656 B). - ๐Ÿ‘พ readIp compiled twice in MoonBase โ†’ done: one body through a function pointer. - ๐Ÿ‘พ The heap probe โ†’ accepted: transient, freed before the next registration. Co-Authored-By: Claude Opus 5.5 --- CMakeLists.txt | 7 +- docs/contributing/coding-standards.md | 3 + docs/contributing/documentation-standards.md | 4 +- docs/explanation/architecture/mooncore.md | 2 +- docs/explanation/architecture/moonlight.md | 1 + docs/moonmodules/core/services.md | 2 +- docs/moonmodules/core/supporting.md | 4 +- docs/moonmodules/light/supporting.md | 4 +- docs/reference/metrics/code.md | 139 ++++++----- docs/reference/metrics/docgen.md | 219 ++++++++++++++++-- docs/reference/metrics/prose.md | 8 +- docs/reference/metrics/repo-health.json | 46 ++-- docs/reference/metrics/repo-health.md | 76 +++--- docs/work/present/OPEN-WORK.md | 38 --- ... mapping and scripted sensors (partial).md | 5 +- ...ts, one report for simplicity (partial).md | 14 +- ...k submodules (shipped, partly verified).md | 8 +- ...onfiguration (in PR 129, M3 unverified).md | 16 +- esp32/main/CMakeLists.txt | 2 +- moonbase/main/CMakeLists.txt | 4 +- moonbase/main/moonbase_main.cpp | 50 +++- moondeck/MoonDeck.md | 4 + moondeck/check/check_code.py | 137 ++++++++++- moondeck/check/check_docgen.py | 63 ++++- moondeck/docs/screenshot_modules.py | 2 +- src/core/module/Control.h | 19 +- src/core/module/MoonModule.h | 13 +- src/core/module/Scheduler.cpp | 15 +- src/core/module/Scheduler.h | 3 + src/core/moonlive/MoonLiveBuiltins_common.h | 81 +++++++ src/core/moonlive/MoonLiveBuiltins_service.h | 6 +- src/{light => core}/moonlive/MoonLiveScript.h | 22 +- .../moonlive/MoonLiveScriptFile.h | 88 +------ .../moonlive/catalog_scripts.cmake | 0 .../moonlive/catalog_scripts.py | 0 src/{light => core}/moonlive/script_catalog.h | 0 src/core/services/AudioService.h | 4 +- src/core/services/MoonLiveService.h | 30 ++- src/core/system/HttpServerModule.cpp | 54 +++-- src/core/system/HttpServerModule.h | 7 +- src/core/system/IpSettings.h | 64 ++--- src/core/system/MoonStatsModule.h | 8 +- src/core/system/MqttModule.cpp | 25 +- src/core/util/ConfigScrape.h | 68 +++++- src/core/util/Ipv4.h | 95 ++++++++ src/core/util/LightOutput.h | 85 +++++++ src/core/util/LightSummary.h | 29 --- src/core/util/ModuleFactory.h | 18 +- src/core/util/ThreadSlot.h | 43 ++++ .../util/WLEDAudioSyncPacket.h | 0 src/core/util/color.h | 15 ++ src/light/drivers/DriverBase.h | 7 + src/light/drivers/Drivers.h | 29 ++- src/light/drivers/Hub75Slots.h | 3 +- src/light/moonlive/MoonLiveBuiltins_light.h | 149 +++--------- src/light/moonlive/MoonLiveEffect.h | 50 +++- src/light/moonlive/MoonLiveLayout.h | 31 ++- src/light/moonlive/MoonLiveModifier.h | 19 +- src/light/moonlive/MoonLivePalette.h | 25 +- src/light/util/Palette.h | 40 +--- src/light/util/light_types.h | 7 - test/CMakeLists.txt | 3 +- test/python/test_check_code.py | 56 ++++- test/python/test_check_docgen.py | 19 ++ test/python/test_moonlive_catalog_scripts.py | 2 +- test/unit/core/fake_light_output.h | 34 +++ test/unit/core/moonlive_device_codegen.inc | 2 +- test/unit/core/unit_AudioService_sync.cpp | 2 +- test/unit/core/unit_ControlModule.cpp | 4 +- .../unit/core/unit_HttpServerModule_apply.cpp | 33 ++- test/unit/core/unit_ModuleFactory.cpp | 17 ++ test/unit/core/unit_MoonBaseContract.cpp | 39 ++++ test/unit/core/unit_MoonStatsReport.cpp | 1 + test/unit/core/unit_MqttModule.cpp | 11 +- test/unit/core/unit_ThreadSlot.cpp | 48 ++++ .../unit_WledAudioSyncPacket.cpp | 10 +- test/unit/light/MoonLiveScriptFixture.h | 2 +- test/unit/light/unit_Drivers_container.cpp | 36 ++- test/unit/light/unit_Drivers_livePalettes.cpp | 2 +- .../unit/light/unit_MoonLiveScriptResolve.cpp | 2 +- test/unit/light/unit_MoonLiveScripts.cpp | 7 +- 81 files changed, 1614 insertions(+), 726 deletions(-) delete mode 100644 docs/work/present/OPEN-WORK.md rename src/{light => core}/moonlive/MoonLiveScript.h (92%) rename src/{light => core}/moonlive/MoonLiveScriptFile.h (79%) rename src/{light => core}/moonlive/catalog_scripts.cmake (100%) rename src/{light => core}/moonlive/catalog_scripts.py (100%) rename src/{light => core}/moonlive/script_catalog.h (100%) create mode 100644 src/core/util/Ipv4.h create mode 100644 src/core/util/LightOutput.h delete mode 100644 src/core/util/LightSummary.h create mode 100644 src/core/util/ThreadSlot.h rename src/{light => core}/util/WLEDAudioSyncPacket.h (100%) create mode 100644 test/unit/core/fake_light_output.h create mode 100644 test/unit/core/unit_ThreadSlot.cpp rename test/unit/{light => core}/unit_WledAudioSyncPacket.cpp (85%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90ca6433a..0f9f8d98d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,9 @@ else() # and that count may only fall, while each site stays a judgment (a driver may have to wait # on hardware), so failing the build on them would block every other gate. add_compile_options(-Wfunction-effects -Wno-error=function-effects) + # A stack frame over 512 bytes, counted the same way: a task's stack is sized for its deepest call, so one large frame costs every task that reaches it. + # Here rather than for every compiler: the code report reads this build's saved findings, and the frame a Release build lays out is the one a task pays for. + add_compile_options(-Wframe-larger-than=512 -Wno-error=frame-larger-than) # Each file's findings are kept beside its object, so the code report reads the whole tree after an incremental build instead of a clean one. find_package(Python3 COMPONENTS Interpreter QUIET) if(Python3_Interpreter_FOUND AND NOT CMAKE_CXX_COMPILER_LAUNCHER) @@ -278,9 +281,9 @@ file(CONFIGURE OUTPUT ${MOONLIVE_STAMP} CONTENT "${MOONLIVE_SCRIPT_LIST}\n") set(MOONLIVE_CATALOG_STAMP ${CMAKE_BINARY_DIR}/moonlive_catalog.stamp) add_custom_command( OUTPUT ${MOONLIVE_CATALOG_STAMP} - COMMAND ${CMAKE_COMMAND} -DSCRIPT_DIR=${CMAKE_SOURCE_DIR}/moonlive -DOUT=${CMAKE_SOURCE_DIR}/src/light/moonlive/script_catalog.h -DUV_EXECUTABLE=${UV_EXECUTABLE} -P ${CMAKE_SOURCE_DIR}/src/light/moonlive/catalog_scripts.cmake + COMMAND ${CMAKE_COMMAND} -DSCRIPT_DIR=${CMAKE_SOURCE_DIR}/moonlive -DOUT=${CMAKE_SOURCE_DIR}/src/core/moonlive/script_catalog.h -DUV_EXECUTABLE=${UV_EXECUTABLE} -P ${CMAKE_SOURCE_DIR}/src/core/moonlive/catalog_scripts.cmake COMMAND ${CMAKE_COMMAND} -E touch ${MOONLIVE_CATALOG_STAMP} - DEPENDS ${MOONLIVE_SCRIPTS} ${MOONLIVE_STAMP} ${CMAKE_SOURCE_DIR}/src/light/moonlive/catalog_scripts.cmake ${CMAKE_SOURCE_DIR}/src/light/moonlive/catalog_scripts.py + DEPENDS ${MOONLIVE_SCRIPTS} ${MOONLIVE_STAMP} ${CMAKE_SOURCE_DIR}/src/core/moonlive/catalog_scripts.cmake ${CMAKE_SOURCE_DIR}/src/core/moonlive/catalog_scripts.py COMMENT "Generating MoonLive script catalog" ) add_custom_target(moonlive_catalog DEPENDS ${MOONLIVE_CATALOG_STAMP}) diff --git a/docs/contributing/coding-standards.md b/docs/contributing/coding-standards.md index 677011088..6ba1ef97b 100644 --- a/docs/contributing/coding-standards.md +++ b/docs/contributing/coding-standards.md @@ -181,6 +181,9 @@ A finding is a named code smell. Every smell has a named, behavior-preserving mo | Platform code outside `src/platform` | Move Function into the platform layer; `if constexpr` on `platform_config.h` | a target's facts in one layer | | A blocking call on the render path | Move the work off the render thread: a worker, a cached value, a deferred apply | the tick only computes | | A name spread across files | Move Function, self-registration | a concept in one place | +| A module type named in the UI | Replace Conditional with Polymorphism: the module declares a control, a role or a flag | the UI knows no module | +| A stack frame over 512 bytes | Move the large local into a member or a `ScratchBuffer`, sized once | no task's stack pays for it | +| A buffer taken by hand in the light domain | Replace it with a `ScratchBuffer` member | owned, sized, reported and freed in one place | Cut first: a branch that chooses between equals is data, a guard is an early return, and nesting is what a reader trips on, more than branch count. The theory behind the moves is Ousterhout's: complexity is dependencies and obscurity, so a deep module with a small interface absorbs it and its callers stay simple. A function may stay over a limit when splitting it would hide a sequence that belongs together. It says so in one line, and its count stays rather than being forced. diff --git a/docs/contributing/documentation-standards.md b/docs/contributing/documentation-standards.md index e9e1e136c..c95cbc182 100644 --- a/docs/contributing/documentation-standards.md +++ b/docs/contributing/documentation-standards.md @@ -287,9 +287,9 @@ These are traps, not style: each one silently loses content from the generated p /// ## Terminology ``` - A renamed heading leaves the anchor pointing at nothing, and the generator drops the dead link rather than failing. So `check_docgen` verifies that every `@xref` names a heading in the same file. The reverse is not a rule: a `@moreinfo` section is an appendix a reader scrolls to, and most are reached that way rather than through a link. + A renamed heading leaves the anchor pointing at nothing, and the generator drops the dead link rather than failing. So `check_docgen` verifies that every `@xref` names a heading in the same file. The reverse is counted. A `@moreinfo` section that no `@xref` in its file and no link from a page or another source reaches is a section nothing refers to. It is a warning whose count only falls, since a section no reader is sent to is the first to cut. - **A section written to hold a comment's depth carries an `@xref` back from that comment.** Moving the reasoning out is what keeps the code readable; the anchor is what keeps it findable. The reader at the line that raises the question gets a link to the answer. Where no single line owns the section, the appendix stands alone and the reverse rule above applies. + **A section written to hold a comment's depth carries an `@xref` back from that comment.** Moving the reasoning out is what keeps the code readable; the anchor is what keeps it findable. The reader at the line that raises the question gets a link to the answer. Where no single line owns the section, a page that sends readers there links it as `moxygen/.md#`, or the section is a candidate to cut. - **Wrap any `` in backticks**, or it renders as a live element and swallows the page. - **Write "such as", not "e.g."** The brief ends at the first period. - **A weasel that CONTRASTS is information.** "bytes actually allocated" against requested, "the factor actually in use" against configured: the word carries the distinction the comment exists to draw. Vale flags the word rather than the use, which is why its Weasel rule is a suggestion. diff --git a/docs/explanation/architecture/mooncore.md b/docs/explanation/architecture/mooncore.md index bf17789e8..704c0a35e 100644 --- a/docs/explanation/architecture/mooncore.md +++ b/docs/explanation/architecture/mooncore.md @@ -111,7 +111,7 @@ Abstractions are added when a concrete implementation needs them, not pre-design **Platform boundary (hard rule).** All `#ifdef`, `#if defined`, platform-specific `#include`s, and hardware API calls live exclusively in `src/platform/`. Everything outside `src/platform/` compiles on every target without modification. Compile-time platform branching uses `if constexpr` on `platform_config.h` flags, never a preprocessor `#ifdef`. **Domain boundary.** A file in `src/core` includes nothing from `src/light`: core declares an interface, and the light domain implements and registers it. -Both boundaries are rules in [the code report](../../reference/metrics/code.md), whose counts may only fall: the platform one at zero, the domain one at the crossings that remain. +Both boundaries are rules in [the code report](../../reference/metrics/code.md), each at zero, and a crossing raises the count the ratchet refuses. `LightOutput` is the domain boundary's shape: the light domain's `Drivers` implements it, and the WLED shim, MQTT and MoonStats read the device shape and the palettes through it. **The desktop build runs everything (hard rule).** Every module, effect and driver in the repo links and runs on the host, the platform layer has no silicon behind the call. Where a peripheral is absent the host *emulates* it rather than declaring itself incapable: the parallel WS2812 buses are backed by heap buffers, `lcdLanes` / `parlioLanes` / `rmtTxChannels` report a real chip's counts, and `hasLcdCam` is true. Code excluded from the host binary is code that cannot be unit-tested and cannot be seen by any AST-based check. It only ever runs where it is hardest to debug, which is what the LED drivers were until they were linked here. diff --git a/docs/explanation/architecture/moonlight.md b/docs/explanation/architecture/moonlight.md index f585e6c66..09cf6e42f 100644 --- a/docs/explanation/architecture/moonlight.md +++ b/docs/explanation/architecture/moonlight.md @@ -324,6 +324,7 @@ Non-negotiable: - Effects always write to their layer's logical buffer. Never to output, never to physical coordinates. - Drivers always own the output path (blending, mapping, brightness correction, channel reordering). - Layer buffer is mandatory: if it doesn't fit, reduce dimensions until it does ("at least see something"). +- A light module's buffer is a `ScratchBuffer` member, which sizes it, reports it in `dynamicBytes()` and frees it in `release()`, so no allocation is held unreported or leaked. The [code report](../../reference/metrics/code.md) counts each buffer still taken by hand, and that count only falls. ### Per-module reporting diff --git a/docs/moonmodules/core/services.md b/docs/moonmodules/core/services.md index 69f010c7f..c308e398a 100644 --- a/docs/moonmodules/core/services.md +++ b/docs/moonmodules/core/services.md @@ -38,7 +38,7 @@ A user-added Service: the audio source the audio-reactive effects consume. `mode - `syncPort`: (network build) the UDP port, 11988 by default; `sync status` reports the state. - read-only: `level` (RMS), `peakHz` (the audio driving effects, from any source). -Detail: [technical](moxygen/AudioService.md) ยท [the sync packet](../light/moxygen/WLEDAudioSyncPacket.md) ยท [the lock-free ring](moxygen/SpscRing.md) +Detail: [technical](moxygen/AudioService.md) ยท [the sync packet](moxygen/WLEDAudioSyncPacket.md) ยท [the lock-free ring](moxygen/SpscRing.md) [Tests](../../reference/tests/unit-tests.md#audioservice) diff --git a/docs/moonmodules/core/supporting.md b/docs/moonmodules/core/supporting.md index 35925f245..e4f3c2ae4 100644 --- a/docs/moonmodules/core/supporting.md +++ b/docs/moonmodules/core/supporting.md @@ -31,6 +31,7 @@ A flat parser returns zero for a missing key, which is indistinguishable from a | [`ScratchBuffer`](moxygen/ScratchBuffer.md) | One owned allocation with a typed view, so a module sizes its working memory once rather than per frame. The heavy body compiles once rather than per element type. | | [`SpscRing`](moxygen/SpscRing.md) | The textbook Lamport queue: one thread pushes, one pops, and each index is written by exactly one side. The release and acquire pair is what publishes the element data. | | [`TryLock`](moxygen/TryLock.md) | A non-blocking latch for a resource two threads reach. It never waits, so the render core is never held by a slower caller. | +| [`ThreadSlot`](moxygen/ThreadSlot.md) | A small table of slots a thread claims by its id, standing in for `thread_local` where an ESP32 task has no TLS. The script builtins reach their sinks through it. | | `Sort.h` | In-place insertion sort over a fixed array, for the small bounded collections the system holds. Every module sorts the same way and supplies only its comparator. | ## Wire formats and parsing @@ -42,6 +43,7 @@ A flat parser returns zero for a missing key, which is indistinguishable from a | [`FirmwareImage`](moxygen/FirmwareImage.md) | Reads an image's header without the vendor framework. The layout is a fixed on-disk format, so the same bytes parse on a device and in a test. | | [`PinList`](moxygen/util_PinList.md) ยท [`HostList`](moxygen/HostList.md) | The two list parsers a board configuration needs: a pin list and a host list of addresses and names, both typed by a human into one text control. | | [`Addressing`](moxygen/Addressing.md) ยท [`HostResolver`](moxygen/HostResolver.md) | One rule for sending to many receivers, unicast, multicast or broadcast, and the cache that turns a host name into an address off the render thread. | +| [`ConfigScrape`](moxygen/ConfigScrape.md) ยท [`Ipv4`](moxygen/Ipv4.md) | The keys MoonBase reads out of the app's saved config without a parser, and the IPv4 parse and static-address rule both images check by. | | [`sha256`](moxygen/sha256.md) ยท [`crc`](moxygen/crc.md) | A cryptographic digest for update verification and identity, and a cheap checksum used as a fingerprint of a block of state. | | [`Sha1`](moxygen/Sha1.md) ยท [`Base64`](moxygen/Base64.md) | The two codecs the WebSocket handshake needs, the digest that standard mandates and the encoding that carries it. | @@ -49,7 +51,7 @@ A flat parser returns zero for a missing key, which is indistinguishable from a | Header | What it is | |---|---| -| [`LightSummary`](moxygen/LightSummary.md) | A plain-data summary of the light pipeline's output, so the network shims report the real device shape without including anything from the light domain. | +| [`LightOutput`](moxygen/LightOutput.md) | The light pipeline as core reads it: the device's shape and its palettes as colors. The light domain implements it, so the network shims and MoonStats include nothing from the light domain. | | [`AudioFrame`](moxygen/AudioFrame.md) | One snapshot of analysed audio, produced once per render tick and consumed by audio-reactive effects. | | [`BinaryBroadcaster`](moxygen/BinaryBroadcaster.md) | The sink a producer holds instead of the concrete server, so a driver sends to every client without depending on the web server. | | `build_info.h` | The version and build identity, generated from the project manifest rather than edited by hand. | diff --git a/docs/moonmodules/light/supporting.md b/docs/moonmodules/light/supporting.md index 1a9bff2b3..5611c63c2 100644 --- a/docs/moonmodules/light/supporting.md +++ b/docs/moonmodules/light/supporting.md @@ -111,9 +111,9 @@ Detail: [technical](moxygen/MoonLiveParticles.md) ### Script file -One scripted module's script: the file it names, the compiled program, and the content hash that decides when to recompile. Shared by every scripted binding, effect, layout, modifier and palette alike. +One scripted module's script: the file it names, the compiled program, and the content hash that decides when to recompile. Shared by every scripted binding, effect, layout, modifier, palette and service alike, so it lives in core. -Detail: [technical](moxygen/MoonLiveScript.md) +Detail: [technical](../core/moxygen/MoonLiveScript.md) ### Effect base diff --git a/docs/reference/metrics/code.md b/docs/reference/metrics/code.md index ef1fb0109..036d83fef 100644 --- a/docs/reference/metrics/code.md +++ b/docs/reference/metrics/code.md @@ -4,20 +4,23 @@ Generated by [`moondeck/check/check_code.py`](../../../moondeck/check/check_code Every function, block and file over a limit the [coding standards](../../contributing/coding-standards.md#static-checks) set. Current state only: the trend is this file's git history. The list only shrinks, per rule and in total, and a touched file clears its own rows. -**1497 finding(s)** across 310 file(s). 3.04% of all lines are duplicated, 3791 lines. +**1659 finding(s)** across 320 file(s). 3.01% of all lines are duplicated, 3791 lines. ## By rule | Rule | Findings | |---|---:| | duplicated block | 786 | -| complex function | 286 | +| complex function | 285 | | blocking call on the render path | 191 | | deeply nested | 114 | -| long function | 50 | +| module type in the UI | 69 | +| large stack frame | 60 | +| long function | 49 | | long parameter list | 34 | -| large file | 26 | -| light include in core | 10 | +| large file | 25 | +| raw allocation in light | 24 | +| name spread | 22 | ## How a finding is solved @@ -32,18 +35,22 @@ Each rule is a code smell with a named move from the refactoring catalog, the ta - **blocking call on the render path** (a call from tick, tick20ms or tick1s that can block or allocate): Move the work off the render thread (a worker, a cached value, a deferred apply), or annotate a callee that cannot block. - **platform code outside src/platform** (a vendor header or a platform #ifdef outside src/platform): Move it behind a function in src/platform, and branch on platform_config.h with if constexpr. - **light include in core** (a src/core file including a light/ header): Dependency Inversion: core declares the interface, and the light domain implements and registers it. +- **module type in the UI** (a registered type's name as a string literal in src/ui): Replace Conditional with Polymorphism: the module declares what the UI needs (a control, a role, a flag) and the UI reads it. +- **name spread** (a type named in more than 10 files beyond its own): Move Function, self-registration: a concept in one place, which callers reach through its role or an interface. +- **large stack frame** (a function whose stack frame is over 512 bytes): Move the large local into a member or a ScratchBuffer, sized once, so no task's stack pays for it. +- **raw allocation in light** (an array new, malloc or platform::alloc in src/light outside ScratchBuffer): Replace the allocation with a ScratchBuffer member, which owns, sizes and frees it. ## By area | Area | Findings | |---|---:| | `test` | 584 | -| `light` | 387 | -| `core` | 324 | -| `platform` | 169 | +| `light` | 418 | +| `core` | 381 | +| `platform` | 173 | +| `ui` | 72 | | `moondeck` | 24 | -| `src` | 4 | -| `ui` | 3 | +| `src` | 5 | | `mooninstaller` | 2 | ## By file @@ -52,51 +59,56 @@ The next function worth simplifying is at the top of each file's list. | File | Findings | Worst | |---|---:|---| -| `src/core/system/HttpServerModule.cpp` | 40 | `HttpServerModule::handleConnection`, complex function 119 | -| `src/platform/desktop/platform_desktop.cpp` | 37 | `platform::spawnEncoderProcess`, complex function 58 | +| `src/core/system/HttpServerModule.cpp` | 60 | `HttpServerModule::handleConnection`, complex function 119 | +| `src/platform/desktop/platform_desktop.cpp` | 41 | `platform::spawnEncoderProcess`, complex function 58 | +| `src/ui/migrate.js` | 41 | `line 29: 'I2cBusModule'`, module type in the UI 1 | | `test/unit/core/unit_FilesystemModule_persistence.cpp` | 34 | `lines 158-170, also in test/unit/core/unit_FilesystemModule_persistence.cpp:124`, duplicated block 13 | -| `src/core/moonlive/MoonLiveCompiler.cpp` | 26 | `moonlive::Parser::parseCall`, complex function 59 | -| `src/core/system/MqttModule.cpp` | 26 | `MqttModule::routePublish`, complex function 28 | -| `src/light/drivers/ParallelLedDriver.h` | 23 | `ParallelLedDriver::reinit`, complex function 36 | +| `src/core/system/MqttModule.cpp` | 31 | `MqttModule::routePublish`, complex function 29 | +| `src/ui/app.js` | 29 | `app.js`, large file 8976 | +| `src/core/moonlive/MoonLiveCompiler.cpp` | 27 | `moonlive::Parser::parseCall`, complex function 59 | +| `src/light/drivers/ParallelLedDriver.h` | 27 | `ParallelLedDriver::reinit`, complex function 36 | +| `src/light/drivers/PreviewDriver.h` | 27 | `PreviewDriver::buildCoordTable`, complex function 37 | +| `src/light/drivers/RtspDriver.h` | 23 | `RtspDriver::serveControl, line 185`, large stack frame 1680 | | `test/unit/light/unit_I80Peripheral.cpp` | 23 | `lines 151-170, also in test/unit/light/unit_ParlioPeripheral.cpp:214`, duplicated block 20 | -| `src/light/drivers/RtspDriver.h` | 22 | `lines 92-104, also in src/light/drivers/HlsDriver.h:105`, duplicated block 13 | | `test/unit/light/unit_PanelCardDriver.cpp` | 22 | `lines 22-39, also in test/unit/light/unit_NdiDriver.cpp:29`, duplicated block 18 | | `test/unit/light/unit_RainbowEffect.cpp` | 22 | `lines 69-85, also in test/unit/light/unit_ParticlesEffect.cpp:32`, duplicated block 17 | -| `src/light/drivers/PreviewDriver.h` | 21 | `PreviewDriver::buildCoordTable`, complex function 37 | | `src/light/powerfunctions/draw.h` | 21 | `draw::scroll`, complex function 28 | -| `test/unit/core/unit_HttpServerModule_apply.cpp` | 21 | `lines 481-492, also in test/unit/core/unit_HttpServerModule_apply.cpp:113`, duplicated block 12 | +| `test/unit/core/unit_HttpServerModule_apply.cpp` | 21 | `lines 510-521, also in test/unit/core/unit_HttpServerModule_apply.cpp:116`, duplicated block 12 | +| `src/core/system/NetworkModule.h` | 20 | `NetworkModule in 27 files`, name spread 27 | | `test/unit/light/unit_ParallelLedDriver_ring.cpp` | 20 | `lines 486-503, also in test/unit/light/unit_ParallelLedDriver_ring.cpp:432`, duplicated block 18 | -| `src/core/system/NetworkModule.h` | 19 | `NetworkModule::syncAccessPoint`, complex function 18 | +| `src/light/drivers/HueDriver.h` | 19 | `HueDriver::pollPairing, line 297`, large stack frame 1184 | | `src/platform/esp32/platform_esp32.cpp` | 19 | `platform::httpRequest`, complex function 30 | | `src/platform/esp32/platform_esp32_moon_i80.cpp` | 18 | `platform::createRingState`, complex function 32 | | `test/unit/core/unit_PinsModule.cpp` | 18 | `lines 46-57, also in test/unit/light/unit_Hub75Driver_pins.cpp:66`, duplicated block 12 | -| `src/core/services/AudioService.h` | 17 | `AudioService::syncEnsureSocket`, complex function 17 | +| `src/core/services/AudioService.h` | 17 | `AudioService in 50 files`, name spread 50 | | `src/light/effects/PacmanEffect.h` | 16 | `lines 243-257, also in src/light/effects/FishTankEffect.h:244`, duplicated block 15 | -| `src/light/moonlive/MoonLiveBuiltins_light.h` | 15 | `moonlive::mm_light_escape`, complex function 13 | | `src/platform/esp32/platform_esp32_ota.cpp` | 15 | `platform::otaWriteMoonBase`, complex function 33 | | `test/unit/light/unit_PaintBrushEffect.cpp` | 15 | `lines 44-61, also in test/unit/light/unit_GEQ3DEffect.cpp:58`, duplicated block 18 | | `test/unit/light/unit_SolidEffect.cpp` | 15 | `lines 9-22, also in test/unit/light/unit_FixedRectangleEffect.cpp:90`, duplicated block 14 | +| `src/core/module/Control.cpp` | 14 | `applyControlValue`, complex function 74 | | `test/unit/light/unit_ParlioPeripheral.cpp` | 14 | `lines 214-233, also in test/unit/light/unit_I80Peripheral.cpp:151`, duplicated block 20 | -| `src/light/drivers/HueDriver.h` | 13 | `HueDriver::parseLights`, complex function 15 | +| `src/light/layers/Layer.h` | 13 | `Layer in 133 files`, name spread 133 | | `test/unit/light/unit_HlsDriver.cpp` | 13 | `lines 30-47, also in test/unit/light/unit_PanelCardDriver.cpp:22`, duplicated block 18 | | `test/unit/light/unit_RandomMapModifier.cpp` | 13 | `lines 116-132, also in test/unit/light/unit_BlurzEffect.cpp:49`, duplicated block 17 | -| `src/core/module/Control.cpp` | 12 | `applyControlValue`, complex function 74 | +| `src/core/system/DevicesModule.h` | 12 | `lines 73-80, also in src/core/system/DevicesModule.h:59`, duplicated block 8 | +| `src/light/drivers/HlsDriver.h` | 12 | `lines 105-117, also in src/light/drivers/RtspDriver.h:92`, duplicated block 13 | | `test/unit/light/unit_RubiksCubeEffect.cpp` | 12 | `lines 60-78, also in test/unit/light/unit_RubiksCubeEffect.cpp:28`, duplicated block 19 | | `src/core/services/OscModule.h` | 11 | `OscModule::sendValue`, complex function 18 | -| `src/core/system/DevicesModule.h` | 11 | `lines 73-80, also in src/core/system/DevicesModule.h:59`, duplicated block 8 | +| `src/core/system/ControlModule.h` | 11 | `ControlModule::storePreset, line 907`, large stack frame 1296 | +| `src/light/moonlive/MoonLiveBuiltins_light.h` | 11 | `moonlive::mm_light_escape`, complex function 13 | | `src/platform/esp32/platform_esp32_i80.cpp` | 11 | `platform::createState`, complex function 27 | | `test/unit/light/unit_StarFieldEffect.cpp` | 11 | `lines 88-103, also in test/unit/light/unit_StarFieldEffect.cpp:13`, duplicated block 16 | -| `src/light/drivers/HlsDriver.h` | 10 | `lines 105-117, also in src/light/drivers/RtspDriver.h:92`, duplicated block 13 | +| `src/light/drivers/Drivers.h` | 10 | `Drivers in 63 files`, name spread 63 | | `src/light/effects/GEQ3DEffect.h` | 10 | `lines 140-150, also in src/light/effects/GEQ3DEffect.h:113`, duplicated block 11 | | `src/light/effects/GameOfLifeEffect.h` | 10 | `GameOfLifeEffect::evolveAutomaton`, complex function 67 | | `test/unit/light/unit_BlendMap.cpp` | 10 | `lines 283-289, also in test/unit/light/unit_BlendMap.cpp:212`, duplicated block 7 | | `test/unit/light/unit_Effects_container.cpp` | 10 | `lines 188-199, also in test/unit/light/unit_Effects_container.cpp:139`, duplicated block 12 | | `src/core/services/InfraredService.h` | 9 | `lines 113-135, also in src/core/services/GamepadService.h:108`, duplicated block 23 | -| `src/core/system/MoonStatsModule.h` | 9 | `buildMoonStatsReport`, long parameter list 11 | -| `src/light/drivers/Drivers.h` | 9 | `Drivers::prepare`, complex function 26 | +| `src/core/system/FilesystemModule.cpp` | 9 | `FilesystemModule::reapplyNode, line 177`, large stack frame 2368 | | `src/light/drivers/PanelCardDriver.h` | 9 | `lines 187-195, also in src/light/drivers/NetworkSendDriver.h:212`, duplicated block 9 | -| `src/light/layers/Layer.h` | 9 | `Layer::buildFoldedLUT`, complex function 25 | | `test/unit/light/unit_ParallelLedDriver_swap.cpp` | 9 | `lines 176-184, also in test/unit/light/unit_ParallelLedDriver_swap.cpp:112`, duplicated block 9 | +| `src/core/system/MoonStatsModule.h` | 8 | `MoonStatsModule::sendReport, line 330`, large stack frame 1712 | +| `src/core/system/WiFiModule.h` | 8 | `lines 352-359, also in src/light/drivers/FixtureProfilesModule.h:245`, duplicated block 8 | | `src/light/effects/FixedPointEffect.h` | 8 | `FixedPointEffect::drawBoids`, complex function 19 | | `src/light/effects/FlyingToastersEffect.h` | 8 | `lines 60-69, also in src/light/effects/FlyingToastersEffect.h:40`, duplicated block 10 | | `src/light/effects/SpaceInvadersEffect.h` | 8 | `lines 436-444, also in src/light/effects/SpriteCast.h:59`, duplicated block 9 | @@ -106,9 +118,8 @@ The next function worth simplifying is at the top of each file's list. | `test/unit/light/unit_MovingHeadEffect.cpp` | 8 | `lines 107-118, also in test/unit/light/unit_MovingHeadEffect.cpp:45`, duplicated block 12 | | `test/unit/light/unit_NoiseMeterEffect.cpp` | 8 | `lines 100-120, also in test/unit/light/unit_NoiseMeterEffect.cpp:49`, duplicated block 21 | | `test/unit/light/unit_draw.cpp` | 8 | `lines 352-358, also in test/unit/light/unit_draw.cpp:334`, duplicated block 7 | -| `src/core/system/ControlModule.h` | 7 | `ControlModule::driveSurface`, complex function 15 | -| `src/core/system/FilesystemModule.cpp` | 7 | `FilesystemModule::applyNode`, complex function 15 | -| `src/core/system/WiFiModule.h` | 7 | `lines 352-359, also in src/light/drivers/FixtureProfilesModule.h:245`, duplicated block 8 | +| `src/core/moonlive/MoonLiveSpill.cpp` | 7 | `moonlive::spillToBudget`, complex function 128 | +| `src/core/system/SystemModule.h` | 7 | `SystemModule in 31 files`, name spread 31 | | `src/core/util/JsonUtil.h` | 7 | `json::parseString`, complex function 34 | | `src/light/effects/FishTankEffect.h` | 7 | `lines 244-258, also in src/light/effects/PacmanEffect.h:243`, duplicated block 15 | | `src/platform/esp32/platform_esp32_hub75.cpp` | 7 | `platform::hub75Init`, complex function 32 | @@ -117,8 +128,10 @@ The next function worth simplifying is at the top of each file's list. | `test/unit/core/unit_NetworkModule.cpp` | 7 | `lines 556-564, also in test/unit/core/unit_NetworkModule.cpp:190`, duplicated block 9 | | `test/unit/light/unit_NdiDriver.cpp` | 7 | `lines 29-46, also in test/unit/light/unit_PanelCardDriver.cpp:22`, duplicated block 18 | | `test/unit/light/unit_PlasmaEffect.cpp` | 7 | `lines 24-39, also in test/unit/light/unit_MetaballsEffect.cpp:22`, duplicated block 16 | -| `src/core/moonlive/MoonLiveSpill.cpp` | 6 | `moonlive::spillToBudget`, complex function 128 | -| `src/core/system/SystemModule.h` | 6 | `platform::getMacAddress in tick1s`, blocking call on the render path 1 | +| `src/core/moonlive/moonlive_lower.h` | 6 | `moonlive::lowerWith`, complex function 82 | +| `src/core/system/FirmwareUpdateModule.h` | 6 | `FirmwareUpdateModule in 13 files`, name spread 13 | +| `src/core/util/InputMapping.h` | 6 | `firePadRow, line 151`, large stack frame 1504 | +| `src/light/drivers/NetworkSendDriver.h` | 6 | `NetworkSendDriver::tick, line 192`, large stack frame 1760 | | `src/light/layers/BlendMap.h` | 6 | `blendMap`, complex function 35 | | `src/platform/esp32/platform_esp32_fs.cpp` | 6 | `lines 198-207, also in src/platform/esp32/platform_esp32_fs.cpp:149`, duplicated block 10 | | `src/platform/esp32/platform_esp32_improv.cpp` | 6 | `platform::improvTask`, complex function 22 | @@ -134,8 +147,6 @@ The next function worth simplifying is at the top of each file's list. | `src/core/module/Scheduler.cpp` | 5 | `Scheduler::getControlWide`, complex function 18 | | `src/core/services/AnalogService.h` | 5 | `lines 105-123, also in src/core/services/InfraredService.h:117`, duplicated block 19 | | `src/core/services/AudioBands.h` | 5 | `magnitudesToBands`, complex function 19 | -| `src/core/system/FirmwareUpdateModule.h` | 5 | `FirmwareUpdateModule::readMoonBaseVersion in tick1s`, blocking call on the render path 1 | -| `src/core/util/InputMapping.h` | 5 | `setInputActionField`, complex function 22 | | `src/core/util/JsonSink.h` | 5 | `JsonSink::writeJsonString`, deeply nested 8 | | `src/core/util/noise.h` | 5 | `lines 304-310, also in src/core/util/noise.h:288`, duplicated block 7 | | `src/light/drivers/PinList.h` | 5 | `assignCounts`, complex function 30 | @@ -145,7 +156,6 @@ The next function worth simplifying is at the top of each file's list. | `src/light/layouts/CarLightsLayout.h` | 5 | `lines 49-65, also in src/light/layouts/TorontoBarGourdsLayout.h:50`, duplicated block 17 | | `src/light/layouts/RingLayout.h` | 5 | `lines 85-100, also in src/light/layouts/CarLightsLayout.h:95`, duplicated block 16 | | `src/light/layouts/TorontoBarGourdsLayout.h` | 5 | `lines 50-66, also in src/light/layouts/CarLightsLayout.h:49`, duplicated block 17 | -| `src/light/util/Palette.h` | 5 | `Palettes::rgbToHueSat`, complex function 12 | | `src/platform/desktop/moonlive_asm_x86_64.cpp` | 5 | `lines 570-577, also in src/platform/desktop/moonlive_asm_x86_64.cpp:528`, duplicated block 8 | | `src/platform/esp32/moonlive_asm_riscv.cpp` | 5 | `lines 40-47, also in src/platform/desktop/moonlive_asm_arm64.cpp:34`, duplicated block 8 | | `src/platform/esp32/platform_esp32_h264.cpp` | 5 | `platform::hlsSegment`, complex function 26 | @@ -153,21 +163,26 @@ The next function worth simplifying is at the top of each file's list. | `test/unit/light/unit_FireEffect.cpp` | 5 | `lines 29-42, also in test/unit/light/unit_RainbowEffect.cpp:69`, duplicated block 14 | | `test/unit/light/unit_FreqSawsEffect.cpp` | 5 | `lines 19-29, also in test/unit/light/unit_RainbowEffect.cpp:69`, duplicated block 11 | | `test/unit/light/unit_GEQ3DEffect.cpp` | 5 | `lines 58-75, also in test/unit/light/unit_PaintBrushEffect.cpp:44`, duplicated block 18 | -| `test/unit/light/unit_MoonLiveScripts.cpp` | 5 | `lines 286-294, also in test/unit/light/unit_MoonLiveScripts.cpp:258`, duplicated block 9 | +| `test/unit/light/unit_MoonLiveScripts.cpp` | 5 | `lines 287-295, also in test/unit/light/unit_MoonLiveScripts.cpp:259`, duplicated block 9 | | `test/unit/light/unit_RandomEffect.cpp` | 5 | `lines 10-22, also in test/unit/light/unit_RandomMapModifier.cpp:115`, duplicated block 13 | +| `src/core/moonlive/MoonLive.cpp` | 4 | `moonlive::MoonLive::ensureArena`, complex function 21 | +| `src/core/moonlive/MoonLiveScriptFile.h` | 4 | `moonlive::compileScriptFile`, complex function 19 | | `src/core/services/ButtonService.h` | 4 | `lines 96-118, also in src/core/services/InfraredService.h:113`, duplicated block 23 | +| `src/core/system/EthernetModule.h` | 4 | `EthernetModule::defineControls`, complex function 24 | | `src/core/system/ImprovProvisioningModule.h` | 4 | `NetworkModule::setTxPowerSetting in tick1s`, blocking call on the render path 1 | | `src/core/system/TasksModule.h` | 4 | `TasksModule::TaskListSource::writeListRowDetail`, complex function 11 | -| `src/light/drivers/NetworkSendDriver.h` | 4 | `lines 212-220, also in src/light/drivers/PanelCardDriver.h:187`, duplicated block 9 | | `src/light/drivers/ParallelSlots.h` | 4 | `encodeWs2812ShiftData`, complex function 19 | +| `src/light/drivers/RmtLedDriver.h` | 4 | `line 377: if (!frame_) frame_ = static_cast(platform::alloc(`, raw allocation in light 1 | | `src/light/effects/NebulaEffect.h` | 4 | `NebulaEffect::data`, complex function 27 | | `src/light/effects/NetworkReceiveEffect.h` | 4 | `platform::UdpSocket::recvFrom in tick`, blocking call on the render path 1 | | `src/light/effects/PolarNoiseEffect.h` | 4 | `lines 100-110, also in src/light/effects/TunnelEffect.h:96`, duplicated block 11 | | `src/light/effects/SpriteCast.h` | 4 | `lines 59-67, also in src/light/effects/SpaceInvadersEffect.h:436`, duplicated block 9 | | `src/light/effects/TrailsEffect.h` | 4 | `TrailsEffect::writeWide`, deeply nested 4 | -| `src/light/moonlive/MoonLiveScriptFile.h` | 4 | `moonlive::compileScriptFile`, complex function 19 | +| `src/light/layers/MappingLUT.h` | 4 | `MappingLUT::allocateDestinations`, complex function 12 | | `src/light/powerfunctions/particles.h` | 4 | `particles::Pool::collide`, complex function 16 | +| `src/light/util/Palette.h` | 4 | `lines 360-365, also in src/light/util/Palette.h:349`, duplicated block 6 | | `src/light/util/RtspSession.h` | 4 | `rtsp::parseTransport`, complex function 28 | +| `src/main.cpp` | 4 | `mm_main`, long function 179 | | `src/platform/desktop/main_desktop.cpp` | 4 | `main`, deeply nested 5 | | `test/js/ui-mooncloud.test.mjs` | 4 | `lines 6-17, also in test/js/installer-s31-webflash.test.mjs:11`, duplicated block 12 | | `test/unit/light/unit_BlurzEffect.cpp` | 4 | `lines 137-155, also in test/unit/light/unit_GEQEffect.cpp:156`, duplicated block 19 | @@ -181,21 +196,18 @@ The next function worth simplifying is at the top of each file's list. | `test/unit/light/unit_PraxisEffect.cpp` | 4 | `lines 9-21, also in test/unit/light/unit_RandomMapModifier.cpp:115`, duplicated block 13 | | `test/unit/light/unit_RmtLedDriver_lifecycle.cpp` | 4 | `lines 19-30, also in test/unit/light/unit_RmtLedDriver_pins.cpp:17`, duplicated block 12 | | `test/unit/light/unit_fluid.cpp` | 4 | `lines 160-169, also in test/unit/light/unit_TrailsEffect.cpp:54`, duplicated block 10 | -| `src/core/moonlive/MoonLive.cpp` | 3 | `moonlive::MoonLive::ensureArena`, complex function 21 | -| `src/core/moonlive/moonlive_lower.h` | 3 | `moonlive::lowerWith`, complex function 82 | +| `src/core/moonlive/MoonLiveBuiltins_common.h` | 3 | `moonlive::mm_ml_addControl`, complex function 12 | | `src/core/services/GamepadService.h` | 3 | `lines 108-130, also in src/core/services/InfraredService.h:113`, duplicated block 23 | | `src/core/system/AccessPointModule.h` | 3 | `platform::UdpSocket::recvFrom in tick20ms`, blocking call on the render path 1 | -| `src/core/system/EthernetModule.h` | 3 | `EthernetModule::defineControls`, complex function 24 | | `src/core/system/PinsModule.h` | 3 | `PinsModule::PinListSource::collect`, deeply nested 5 | | `src/core/util/HostList.h` | 3 | `parseHostList`, complex function 27 | | `src/core/util/HostResolver.h` | 3 | `HostResolver::pass`, deeply nested 4 | | `src/core/util/math16.h` | 3 | `lines 373-378, also in src/core/util/math8.h:94`, duplicated block 6 | | `src/light/drivers/Hub75Driver.h` | 3 | `Hub75Driver::prepare`, complex function 11 | -| `src/light/drivers/RmtLedDriver.h` | 3 | `platform::rmtWs2812Transmit in tick`, blocking call on the render path 1 | | `src/light/effects/AuroraEffect.h` | 3 | `lines 132-140, also in src/light/effects/TunnelEffect.h:92`, duplicated block 9 | | `src/light/effects/PongEffect.h` | 3 | `PongEffect::render`, complex function 15 | | `src/light/effects/SolidEffect.h` | 3 | `SolidEffect::static_cast`, complex function 36 | -| `src/main.cpp` | 3 | `mm_main`, long function 179 | +| `src/light/layouts/GridLayout.h` | 3 | `GridLayout in 85 files`, name spread 85 | | `src/platform/desktop/moonlive_asm_arm64.cpp` | 3 | `lines 34-41, also in src/platform/esp32/moonlive_asm_riscv.cpp:40`, duplicated block 8 | | `test/unit/core/unit_NetworkModule_ethernet.cpp` | 3 | `lines 276-285, also in test/unit/core/unit_NetworkModule_ethernet.cpp:193`, duplicated block 10 | | `test/unit/light/unit_AuroraEffect.cpp` | 3 | `lines 40-48, also in test/unit/light/unit_PolarLut_equivalence.cpp:40`, duplicated block 9 | @@ -214,13 +226,16 @@ The next function worth simplifying is at the top of each file's list. | `moondeck/moontube/reset_device.py` | 2 | `lines 241-246, also in moondeck/moontube/reset_device.py:219`, duplicated block 6 | | `moondeck/scenario/run_scenario.py` | 2 | `lines 33-39, also in moondeck/docs/build_docs.py:43`, duplicated block 7 | | `src/core/moonlive/MoonLiveBuiltins.h` | 2 | `lines 208-219, also in src/core/moonlive/MoonLiveBuiltins.h:111`, duplicated block 12 | -| `src/core/moonlive/MoonLiveBuiltins_common.h` | 2 | `lines 77-82, also in src/core/moonlive/MoonLiveBuiltins_common.h:65`, duplicated block 6 | | `src/core/services/MidiService.h` | 2 | `MidiService::decode`, complex function 18 | -| `src/core/services/MoonLiveService.h` | 2 | `line 6: #include "light/moonlive/MoonLiveScript.h"`, light include in core 1 | | `src/core/system/DevicePlugin.h` | 2 | `lines 94-100, also in src/core/system/DevicePlugin.h:75`, duplicated block 7 | +| `src/core/system/HttpServerModule.h` | 2 | `HttpServerModule in 21 files`, name spread 21 | +| `src/core/system/I2cBusModule.h` | 2 | `I2cBusModule::scan`, complex function 18 | | `src/core/system/MqttPacket.h` | 2 | `buildMqttConnect`, complex function 31 | +| `src/core/system/Sha1.h` | 2 | `sha1, line 21`, large stack frame 944 | | `src/core/util/ModuleFactory.h` | 2 | `ModuleFactory::create`, deeply nested 4 | | `src/core/util/PinList.h` | 2 | `parsePinList`, complex function 15 | +| `src/light/drivers/DriverBase.h` | 2 | `line 164: if (!wire_) wire_ = static_cast(platform::alloc(by`, raw allocation in light 1 | +| `src/light/drivers/FixtureProfilesModule.h` | 2 | `lines 245-252, also in src/core/system/WiFiModule.h:352`, duplicated block 8 | | `src/light/drivers/Hub75Slots.h` | 2 | `hub75Encode`, complex function 20 | | `src/light/drivers/MoonI80Peripheral.h` | 2 | `MoonI80Peripheral::busInitRing`, complex function 12 | | `src/light/effects/BeatRipplesEffect.h` | 2 | `BeatRipplesEffect::renderSurface`, complex function 12 | @@ -228,13 +243,15 @@ The next function worth simplifying is at the top of each file's list. | `src/light/effects/FreqSawsEffect.h` | 2 | `FreqSawsEffect::for`, deeply nested 5 | | `src/light/effects/LinesEffect.h` | 2 | `LinesEffect::if`, deeply nested 5 | | `src/light/effects/MetaballsEffect.h` | 2 | `lines 73-84, also in src/light/effects/SpiralEffect.h:79`, duplicated block 12 | +| `src/light/effects/NoiseEffect.h` | 2 | `NoiseEffect in 25 files`, name spread 25 | | `src/light/effects/PlasmaEffect.h` | 2 | `lines 82-92, also in src/light/effects/SpiralEffect.h:78`, duplicated block 11 | | `src/light/effects/PulseEffect.h` | 2 | `PulseEffect::for`, deeply nested 5 | +| `src/light/effects/RainbowEffect.h` | 2 | `RainbowEffect in 18 files`, name spread 18 | | `src/light/effects/RubiksCubeEffect.h` | 2 | `RubiksCubeEffect::init in tick`, blocking call on the render path 1 | | `src/light/effects/StarFieldEffect.h` | 2 | `StarFieldEffect::for`, deeply nested 4 | | `src/light/effects/TetrixEffect.h` | 2 | `TetrixEffect::static_cast`, complex function 28 | | `src/light/layouts/GridBlacksLayout.h` | 2 | `GridBlacksLayout::placeLights`, deeply nested 4 | -| `src/light/layouts/GridLayout.h` | 2 | `lines 43-53, also in src/light/layouts/TubesLayout.h:45`, duplicated block 11 | +| `src/light/moonlive/MoonLiveEffect.h` | 2 | `MoonLiveEffect in 15 files`, name spread 15 | | `src/light/powerfunctions/polar.h` | 2 | `PolarLut::prepare`, complex function 41 | | `src/light/powerfunctions/shader.h` | 2 | `shader::cosPalette`, long parameter list 13 | | `src/light/util/MpegTs.h` | 2 | `ts::Writer::writeAccessUnit`, complex function 23 | @@ -265,7 +282,7 @@ The next function worth simplifying is at the top of each file's list. | `test/unit/light/unit_SineEffect.cpp` | 2 | `lines 22-30, also in test/unit/light/unit_DistortionWavesEffect.cpp:26`, duplicated block 9 | | `test/unit/light/unit_SingleColumnLayout.cpp` | 2 | `lines 12-25, also in test/unit/light/unit_GridLayout.cpp:8`, duplicated block 14 | | `moondeck/check/check_clang_query.py` | 1 | `check_clang_query.py`, large file 1057 | -| `moondeck/check/check_docgen.py` | 1 | `check_docgen.py`, large file 1798 | +| `moondeck/check/check_docgen.py` | 1 | `check_docgen.py`, large file 1849 | | `moondeck/check/check_footprint.py` | 1 | `lines 31-41, also in moondeck/check/check_nonblocking.py:30`, duplicated block 11 | | `moondeck/check/check_nonblocking.py` | 1 | `lines 30-40, also in moondeck/check/check_footprint.py:31`, duplicated block 11 | | `moondeck/ci/verify_version.py` | 1 | `lines 39-45, also in moondeck/scenario/run_scenario.py:33`, duplicated block 7 | @@ -279,21 +296,23 @@ The next function worth simplifying is at the top of each file's list. | `mooninstaller/install-orchestrator.js` | 1 | `install-orchestrator.js`, large file 1284 | | `mooninstaller/install.js` | 1 | `install.js`, large file 1449 | | `src/core/module/Control.h` | 1 | `sanitizeHostname`, complex function 16 | +| `src/core/module/StateDocument.cpp` | 1 | `, line 371`, large stack frame 1264 | | `src/core/moonlive/MoonLive.h` | 1 | `moonlive::MoonLive::addDeclaredControl`, complex function 14 | -| `src/core/moonlive/MoonLiveBuiltins_service.h` | 1 | `line 8: #include "light/moonlive/MoonLiveBuiltins_light.h"`, light include in core 1 | | `src/core/moonlive/MoonLiveIr.h` | 1 | `moonlive::IrProgram::push`, complex function 11 | +| `src/core/moonlive/MoonLiveScript.h` | 1 | `moonlive::MoonLiveScript::sync`, complex function 18 | | `src/core/services/AudioLevel.h` | 1 | `computeLevel`, complex function 14 | +| `src/core/services/MoonLiveService.h` | 1 | `moonlive::MoonLive::runValue in tick20ms`, blocking call on the render path 1 | | `src/core/services/OscPacket.h` | 1 | `osc::parse`, complex function 32 | +| `src/core/services/Services.h` | 1 | `Services in 11 files`, name spread 11 | | `src/core/system/FileManagerModule.cpp` | 1 | `platform::filesystemUsed in tick1s`, blocking call on the render path 1 | -| `src/core/system/HttpServerModule.h` | 1 | `HttpServerModule::cancelBufferedSend`, deeply nested 4 | -| `src/core/system/I2cBusModule.h` | 1 | `I2cBusModule::scan`, complex function 18 | -| `src/core/system/Sha1.h` | 1 | `sha1`, deeply nested 5 | +| `src/core/system/FilesystemModule.h` | 1 | `FilesystemModule in 25 files`, name spread 25 | +| `src/core/system/MoonTalkModule.h` | 1 | `MoonTalkModule::send, line 103`, large stack frame 1440 | | `src/core/util/Addressing.h` | 1 | `sendAddressed`, complex function 11 | | `src/core/util/CaptivePortal.h` | 1 | `captive::dnsReply`, complex function 21 | | `src/core/util/ImprovFrame.h` | 1 | `ImprovFrameParser::feed`, complex function 22 | +| `src/core/util/color.h` | 1 | `rgbToHueSat`, complex function 12 | | `src/core/util/math8.h` | 1 | `lines 94-99, also in src/core/util/math16.h:373`, duplicated block 6 | | `src/light/drivers/Correction.h` | 1 | `Correction::apply`, complex function 30 | -| `src/light/drivers/FixtureProfilesModule.h` | 1 | `lines 245-252, also in src/core/system/WiFiModule.h:352`, duplicated block 8 | | `src/light/drivers/I80Peripheral.h` | 1 | `I80Peripheral::validateBusFatal`, complex function 14 | | `src/light/drivers/NdiDriver.h` | 1 | `platform::ndiSendFrame in tick`, blocking call on the render path 1 | | `src/light/effects/BallpitEffect.h` | 1 | `lines 80-85, also in src/light/effects/FireworksEffect.h:83`, duplicated block 6 | @@ -304,23 +323,22 @@ The next function worth simplifying is at the top of each file's list. | `src/light/effects/GEQEffect.h` | 1 | `GEQEffect::for`, complex function 19 | | `src/light/effects/LavaLampEffect.h` | 1 | `lines 68-78, also in src/light/effects/SpiralEffect.h:79`, duplicated block 11 | | `src/light/effects/MovingHeadEffect.h` | 1 | `MovingHeadEffect::shape`, complex function 11 | -| `src/light/effects/NoiseEffect.h` | 1 | `lines 83-90, also in src/light/effects/RainbowEffect.h:47`, duplicated block 8 | | `src/light/effects/RadialSpectrumEffect.h` | 1 | `RadialSpectrumEffect::for`, deeply nested 4 | -| `src/light/effects/RainbowEffect.h` | 1 | `lines 47-54, also in src/light/effects/NoiseEffect.h:83`, duplicated block 8 | | `src/light/effects/SineEffect.h` | 1 | `SineEffect::for`, deeply nested 4 | | `src/light/effects/SphereMoveEffect.h` | 1 | `SphereMoveEffect::for`, deeply nested 4 | | `src/light/effects/WaterRippleEffect.h` | 1 | `WaterRippleEffect::if`, deeply nested 4 | -| `src/light/layers/MappingLUT.h` | 1 | `MappingLUT::allocateDestinations`, complex function 12 | +| `src/light/layers/Buffer.h` | 1 | `line 65: data_ = static_cast(platform::alloc(totalBytes));`, raw allocation in light 1 | +| `src/light/layers/Effects.h` | 1 | `Effects in 81 files`, name spread 81 | | `src/light/layouts/CubeLayout.h` | 1 | `lines 81-88, also in src/light/layouts/GridLayout.h:43`, duplicated block 8 | | `src/light/layouts/HumanSizedCubeLayout.h` | 1 | `HumanSizedCubeLayout::placeLights`, complex function 21 | +| `src/light/layouts/Layouts.h` | 1 | `Layouts in 110 files`, name spread 110 | | `src/light/layouts/PanelLayout.h` | 1 | `lines 54-69, also in src/light/layouts/PanelsLayout.h:64`, duplicated block 16 | | `src/light/layouts/PanelsLayout.h` | 1 | `lines 64-79, also in src/light/layouts/PanelLayout.h:54`, duplicated block 16 | | `src/light/layouts/SphereLayout.h` | 1 | `SphereLayout::forEachShellPoint`, deeply nested 4 | | `src/light/layouts/TubesLayout.h` | 1 | `lines 45-55, also in src/light/layouts/GridLayout.h:43`, duplicated block 11 | -| `src/light/moonlive/MoonLiveEffect.h` | 1 | `moonlive::MoonLive::run in tick`, blocking call on the render path 1 | +| `src/light/modifiers/RandomMapModifier.h` | 1 | `line 112: platform::alloc(static_cast(boxCount) * sizeof(nrOfL`, raw allocation in light 1 | | `src/light/moonlive/MoonLiveModifier.h` | 1 | `MoonLiveModifier::modifyLogical`, complex function 12 | | `src/light/moonlive/MoonLivePalette.h` | 1 | `moonlive::MoonLive::runValue in tick`, blocking call on the render path 1 | -| `src/light/moonlive/MoonLiveScript.h` | 1 | `moonlive::MoonLiveScript::sync`, complex function 18 | | `src/light/powerfunctions/fluid.h` | 1 | `Fluid::resize`, complex function 14 | | `src/light/util/E131Packet.h` | 1 | `parseE131Packet`, complex function 17 | | `src/module_types.cpp` | 1 | `registerModuleTypes`, long function 148 | @@ -331,7 +349,6 @@ The next function worth simplifying is at the top of each file's list. | `src/platform/esp32/platform_esp32_i2s.cpp` | 1 | `platform::audioMicInit`, complex function 11 | | `src/platform/esp32/platform_esp32_tasks.cpp` | 1 | `platform::taskSnapshot`, complex function 12 | | `src/platform/platform.h` | 1 | `platform.h`, large file 1192 | -| `src/ui/app.js` | 1 | `app.js`, large file 8976 | | `src/ui/install-picker.js` | 1 | `install-picker.js`, large file 1048 | | `src/ui/preview3d.js` | 1 | `preview3d.js`, large file 1431 | | `test/js/installer-eth-only.test.mjs` | 1 | `lines 13-23, also in test/js/ui-mooncloud.test.mjs:6`, duplicated block 11 | @@ -343,10 +360,10 @@ The next function worth simplifying is at the top of each file's list. | `test/js/ui-render-guard.test.mjs` | 1 | `lines 13-25, also in test/js/ui-ws-scheme.test.mjs:10`, duplicated block 13 | | `test/js/ui-script-picker-download.test.mjs` | 1 | `lines 12-22, also in test/js/ui-ws-scheme.test.mjs:10`, duplicated block 11 | | `test/js/ui-visibility.test.mjs` | 1 | `lines 7-16, also in test/js/ui-ws-scheme.test.mjs:13`, duplicated block 10 | -| `test/python/test_check_docgen.py` | 1 | `test_check_docgen.py`, large file 1551 | +| `test/python/test_check_docgen.py` | 1 | `test_check_docgen.py`, large file 1570 | | `test/scenario_runner.cpp` | 1 | `scenario_runner.cpp`, large file 1266 | | `test/unit/core/unit_ControlModule.cpp` | 1 | `unit_ControlModule.cpp`, large file 1574 | -| `test/unit/core/unit_Control_apply_absent_key.cpp` | 1 | `lines 92-103, also in test/unit/core/unit_HttpServerModule_apply.cpp:38`, duplicated block 12 | +| `test/unit/core/unit_Control_apply_absent_key.cpp` | 1 | `lines 92-103, also in test/unit/core/unit_HttpServerModule_apply.cpp:39`, duplicated block 12 | | `test/unit/core/unit_moonlive_compiler.cpp` | 1 | `unit_moonlive_compiler.cpp`, large file 1865 | | `test/unit/core/unit_moonlive_fill.cpp` | 1 | `unit_moonlive_fill.cpp`, large file 1348 | | `test/unit/light/unit_BreakoutEffect.cpp` | 1 | `lines 18-27, also in test/unit/light/unit_TetrixEffect.cpp:20`, duplicated block 10 | diff --git a/docs/reference/metrics/docgen.md b/docs/reference/metrics/docgen.md index 96f43e408..0d662671c 100644 --- a/docs/reference/metrics/docgen.md +++ b/docs/reference/metrics/docgen.md @@ -4,9 +4,9 @@ Generated by [`moondeck/check/check_docgen.py`](../../../moondeck/check/check_do Every place the generated documentation breaks the shape [the standards](../../contributing/documentation-standards.md#the-card) define. Current state only: the trend is this file's git history. The list only shrinks. -**0 error(s)** and **2453 warning(s)** across 176 page(s). +**0 error(s)** and **2877 warning(s)** across 359 page(s). -**5633 appendix line(s)** after `@moreinfo`. This only falls as well: a cleanup cuts first, and moves only what neither the code, the test name nor the spec says. +**5632 appendix line(s)** after `@moreinfo`. This only falls as well: a cleanup cuts first, and moves only what neither the code, the test name nor the spec says. An error is in a file that generates a documentation page, a header or a catalog page, so the finding is a defect in what gets published and it fails the gate. A warning is in an implementation file, which publishes nothing: its comments are a note to the next reader, worth fixing without being worth stopping a commit for. Both are counted here, because a warning nobody sees is a warning nobody fixes. @@ -16,10 +16,11 @@ The split is temporary. It stages the sweep rather than ranking the two kinds of | Rule | Errors | Warnings | |---|---:|---:| -| over-wide comment lines | 0 | 1756 | +| over-wide comment lines | 0 | 1750 | | multi-line comment blocks | 0 | 447 | -| over-long sentences | 0 | 90 | -| over-wide doc lines | 0 | 85 | +| appendix sections nothing refers to | 0 | 432 | +| over-long sentences | 0 | 89 | +| over-wide doc lines | 0 | 84 | | member deep dives | 0 | 75 | ## By documentation area @@ -28,9 +29,18 @@ The unit a sweep runs in: one summary page and the headers it owns, as the [hier | Summary page | Errors | Warnings | |---|---:|---:| -| `(tests, no card)` | 0 | 1868 | -| `platform/index.md` | 0 | 332 | -| `core/system.md` | 0 | 253 | +| `(tests, no card)` | 0 | 1871 | +| `platform/index.md` | 0 | 349 | +| `core/system.md` | 0 | 324 | +| `light/effects.md` | 0 | 81 | +| `light/drivers.md` | 0 | 56 | +| `core/supporting.md` | 0 | 50 | +| `light/power-functions.md` | 0 | 44 | +| `light/supporting.md` | 0 | 31 | +| `core/services.md` | 0 | 29 | +| `light/moonlive.md` | 0 | 22 | +| `light/modifiers.md` | 0 | 11 | +| `light/layouts.md` | 0 | 9 | ## Where the work is @@ -38,7 +48,7 @@ Per area, since that is the unit a sweep runs in: the files ranked, then the rul ### (tests, no card) -**0 error(s)** and **1868 warning(s)** across 154 file(s). +**0 error(s)** and **1871 warning(s)** across 156 file(s). | Findings | File | | |---:|---|---| @@ -52,13 +62,13 @@ Per area, since that is the unit a sweep runs in: the files ranked, then the rul | 44 | `test/unit/core/unit_moonlive_codegen_xtensa.cpp` | warning | | 42 | `test/unit/light/unit_ParallelSlots.cpp` | warning | | 38 | `test/unit/light/unit_Drivers_rendersplit.cpp` | warning | -| 1-36 each | *144 more warning files, 1205 findings* | | +| 1-36 each | *146 more warning files, 1208 findings* | | -By rule, warnings: 1418 over-wide comment lines, 205 multi-line comment blocks, 89 over-long sentences, 84 over-wide doc lines, 72 member deep dives. +By rule, warnings: 1414 over-wide comment lines, 205 multi-line comment blocks, 88 over-long sentences, 83 over-wide doc lines, 72 member deep dives, 9 appendix sections nothing refers to. ### platform/index.md -**0 error(s)** and **332 warning(s)** across 18 file(s). +**0 error(s)** and **349 warning(s)** across 24 file(s). | Findings | File | | |---:|---|---| @@ -72,20 +82,195 @@ By rule, warnings: 1418 over-wide comment lines, 205 multi-line comment blocks, | 19 | `src/platform/esp32/platform_esp32_parlio.cpp` | warning | | 10 | `src/platform/esp32/platform_esp32_i2s.cpp` | warning | | 10 | `src/platform/esp32/platform_esp32_improv.cpp` | warning | -| 1-9 each | *8 more warning files, 30 findings* | | +| 1-9 each | *14 more warning files, 47 findings* | | -By rule, warnings: 218 over-wide comment lines, 114 multi-line comment blocks. +By rule, warnings: 218 over-wide comment lines, 114 multi-line comment blocks, 17 appendix sections nothing refers to. ### core/system.md -**0 error(s)** and **253 warning(s)** across 4 file(s). +**0 error(s)** and **324 warning(s)** across 23 file(s). | Findings | File | | |---:|---|---| -| 188 | `src/core/system/HttpServerModule.cpp` | warning | +| 186 | `src/core/system/HttpServerModule.cpp` | warning | | 37 | `src/core/system/FilesystemModule.cpp` | warning | +| 26 | `src/core/system/HttpServerModule.h` | warning | | 19 | `src/core/module/Scheduler.cpp` | warning | | 9 | `src/core/system/FileManagerModule.cpp` | warning | +| 4 | `src/core/system/MqttPacket.h` | warning | +| 4 | `src/core/system/WledPacket.h` | warning | +| 3 | `src/core/module/MoonModule.h` | warning | +| 3 | `src/core/module/Scheduler.h` | warning | +| 3 | `src/core/system/DevicePlugin.h` | warning | +| 1-3 each | *13 more warning files, 30 findings* | | -By rule, warnings: 128 multi-line comment blocks, 120 over-wide comment lines, 3 member deep dives, 1 over-long sentences, 1 over-wide doc lines. +By rule, warnings: 128 multi-line comment blocks, 118 over-wide comment lines, 73 appendix sections nothing refers to, 3 member deep dives, 1 over-long sentences, 1 over-wide doc lines. + +### light/effects.md + +**0 error(s)** and **81 warning(s)** across 56 file(s). + +| Findings | File | | +|---:|---|---| +| 4 | `src/light/effects/EffectBase.h` | warning | +| 3 | `src/light/effects/ColorTrailsEffect.h` | warning | +| 3 | `src/light/effects/PulseEffect.h` | warning | +| 2 | `src/light/effects/AuroraEffect.h` | warning | +| 2 | `src/light/effects/BallpitEffect.h` | warning | +| 2 | `src/light/effects/DemoReelEffect.h` | warning | +| 2 | `src/light/effects/FireworksEffect.h` | warning | +| 2 | `src/light/effects/FluidEffect.h` | warning | +| 2 | `src/light/effects/FreqMatrixEffect.h` | warning | +| 2 | `src/light/effects/FreqSawsEffect.h` | warning | +| 1-2 each | *46 more warning files, 57 findings* | | + +By rule, warnings: 81 appendix sections nothing refers to. + +### light/drivers.md + +**0 error(s)** and **56 warning(s)** across 19 file(s). + +| Findings | File | | +|---:|---|---| +| 9 | `src/light/drivers/ColorLight5A75Packet.h` | warning | +| 8 | `src/light/drivers/ParallelSlots.h` | warning | +| 5 | `src/light/drivers/Hub75Slots.h` | warning | +| 3 | `src/light/drivers/Drivers.h` | warning | +| 3 | `src/light/drivers/FixtureProfilesModule.h` | warning | +| 3 | `src/light/drivers/HlsDriver.h` | warning | +| 3 | `src/light/drivers/PinList.h` | warning | +| 3 | `src/light/drivers/RtspDriver.h` | warning | +| 2 | `src/light/drivers/HueDriver.h` | warning | +| 2 | `src/light/drivers/MoonI80Peripheral.h` | warning | +| 1-2 each | *9 more warning files, 15 findings* | | + +By rule, warnings: 56 appendix sections nothing refers to. + +### core/supporting.md + +**0 error(s)** and **50 warning(s)** across 23 file(s). + +| Findings | File | | +|---:|---|---| +| 6 | `src/core/util/BinaryBroadcaster.h` | warning | +| 4 | `src/core/util/AudioFrame.h` | warning | +| 4 | `src/core/util/ControlSurface.h` | warning | +| 3 | `src/core/util/LightOutput.h` | warning | +| 3 | `src/core/util/PinList.h` | warning | +| 3 | `src/core/util/build_info.h` | warning | +| 3 | `src/core/util/sha256.h` | warning | +| 2 | `src/core/util/FirmwareImage.h` | warning | +| 2 | `src/core/util/HostList.h` | warning | +| 2 | `src/core/util/ImprovFrame.h` | warning | +| 1-2 each | *13 more warning files, 18 findings* | | + +By rule, warnings: 50 appendix sections nothing refers to. + +### light/power-functions.md + +**0 error(s)** and **44 warning(s)** across 10 file(s). + +| Findings | File | | +|---:|---|---| +| 11 | `src/core/util/math16.h` | warning | +| 11 | `src/core/util/noise.h` | warning | +| 4 | `src/core/util/oscillators.h` | warning | +| 4 | `src/light/powerfunctions/draw.h` | warning | +| 4 | `src/light/powerfunctions/polar.h` | warning | +| 3 | `src/light/powerfunctions/raymarch.h` | warning | +| 3 | `src/light/powerfunctions/shader.h` | warning | +| 2 | `src/light/powerfunctions/fonts.h` | warning | +| 1 | `src/core/util/math8.h` | warning | +| 1 | `src/light/powerfunctions/particles.h` | warning | + +By rule, warnings: 44 appendix sections nothing refers to. + +### light/supporting.md + +**0 error(s)** and **31 warning(s)** across 13 file(s). + +| Findings | File | | +|---:|---|---| +| 4 | `src/light/layers/BlendMap.h` | warning | +| 4 | `src/light/layers/Layer.h` | warning | +| 3 | `src/light/layers/MappingLUT.h` | warning | +| 3 | `src/light/util/DdpPacket.h` | warning | +| 3 | `src/light/util/FixtureChannels.h` | warning | +| 2 | `src/light/layers/Buffer.h` | warning | +| 2 | `src/light/layers/Effects.h` | warning | +| 2 | `src/light/util/ArtNetPacket.h` | warning | +| 2 | `src/light/util/Palette.h` | warning | +| 2 | `src/light/util/RtpH264.h` | warning | +| 1-2 each | *3 more warning files, 4 findings* | | + +By rule, warnings: 31 appendix sections nothing refers to. + +### core/services.md + +**0 error(s)** and **29 warning(s)** across 9 file(s). + +| Findings | File | | +|---:|---|---| +| 8 | `src/core/services/AudioBands.h` | warning | +| 5 | `src/core/services/AudioLevel.h` | warning | +| 3 | `src/core/services/AnalogService.h` | warning | +| 3 | `src/core/services/ButtonService.h` | warning | +| 3 | `src/core/services/OscPacket.h` | warning | +| 2 | `src/core/services/InfraredService.h` | warning | +| 2 | `src/core/services/MoonLiveService.h` | warning | +| 2 | `src/core/services/OscModule.h` | warning | +| 1 | `src/core/services/AudioService.h` | warning | + +By rule, warnings: 29 appendix sections nothing refers to. + +### light/moonlive.md + +**0 error(s)** and **22 warning(s)** across 13 file(s). + +| Findings | File | | +|---:|---|---| +| 3 | `src/core/moonlive/moonlive_lower.h` | warning | +| 3 | `src/light/moonlive/MoonLiveLayout.h` | warning | +| 3 | `src/light/moonlive/MoonLivePalette.h` | warning | +| 2 | `src/core/moonlive/MoonLiveBuiltins_common.h` | warning | +| 2 | `src/core/moonlive/MoonLiveIr.h` | warning | +| 2 | `src/core/moonlive/MoonLiveScript.h` | warning | +| 1 | `src/core/moonlive/MoonLiveBuiltins.h` | warning | +| 1 | `src/core/moonlive/MoonLiveBuiltins_service.h` | warning | +| 1 | `src/core/moonlive/MoonLiveScriptFile.h` | warning | +| 1 | `src/core/moonlive/MoonLiveSpill.h` | warning | +| 1 each | *3 more warning files, 3 findings* | | + +By rule, warnings: 22 appendix sections nothing refers to. + +### light/modifiers.md + +**0 error(s)** and **11 warning(s)** across 6 file(s). + +| Findings | File | | +|---:|---|---| +| 4 | `src/light/modifiers/ModifierBase.h` | warning | +| 2 | `src/light/modifiers/RegionModifier.h` | warning | +| 2 | `src/light/modifiers/RotateModifier.h` | warning | +| 1 | `src/light/modifiers/MirrorModifier.h` | warning | +| 1 | `src/light/modifiers/PinwheelModifier.h` | warning | +| 1 | `src/light/modifiers/RandomMapModifier.h` | warning | + +By rule, warnings: 11 appendix sections nothing refers to. + +### light/layouts.md + +**0 error(s)** and **9 warning(s)** across 7 file(s). + +| Findings | File | | +|---:|---|---| +| 3 | `src/light/layouts/Layouts.h` | warning | +| 1 | `src/light/layouts/CarLightsLayout.h` | warning | +| 1 | `src/light/layouts/CubeLayout.h` | warning | +| 1 | `src/light/layouts/PanelLayout.h` | warning | +| 1 | `src/light/layouts/PanelsLayout.h` | warning | +| 1 | `src/light/layouts/Rings241Layout.h` | warning | +| 1 | `src/light/layouts/TorontoBarGourdsLayout.h` | warning | + +By rule, warnings: 9 appendix sections nothing refers to. diff --git a/docs/reference/metrics/prose.md b/docs/reference/metrics/prose.md index b8c01c9a6..bc627d6eb 100644 --- a/docs/reference/metrics/prose.md +++ b/docs/reference/metrics/prose.md @@ -9,13 +9,13 @@ This number is the debt behind that gate, and it RATCHETS: a rise fails the chec docgen.md does. A comment is prose wherever it lives, so a `//` in the web interface and a `#` in a script are counted beside a `///` in a header. -**3185 finding(s)** across 377 file(s). +**3186 finding(s)** across 377 file(s). | rule | findings | |---|---| -| `MoonLight.EmDash` | 1636 | +| `MoonLight.EmDash` | 1634 | | `MoonLight.Weasel` | 738 | -| `MoonLight.SentenceLength` | 474 | +| `MoonLight.SentenceLength` | 477 | | `MoonLight.Temporal` | 248 | | `MoonLight.Spelling` | 43 | | `MoonLight.SelfReference` | 33 | @@ -25,7 +25,7 @@ docgen.md does. A comment is prose wherever it lives, so a `//` in the web inter | file | findings | |---|---| -| `moondeck/MoonDeck.md` | 256 | +| `moondeck/MoonDeck.md` | 259 | | `moondeck/moondeck.py` | 169 | | `docs/how-to/home-automation.md` | 117 | | `mooninstaller/install-orchestrator.js` | 96 | diff --git a/docs/reference/metrics/repo-health.json b/docs/reference/metrics/repo-health.json index 874cfcfb4..57e8481ea 100644 --- a/docs/reference/metrics/repo-health.json +++ b/docs/reference/metrics/repo-health.json @@ -1,12 +1,12 @@ { - "commit": "35a2f0fb", + "commit": "c9b39d4f", "flash": { - "esp32s3-n16r8": 2243984, - "esp32": 2192048, - "esp32p4rev1-eth": 2173984, + "esp32s3-n16r8": 2245328, + "esp32": 2194592, + "esp32p4rev1-eth": 2177776, "esp32p4rev1-eth-wifi": 2358896, "esp32s3-n8r8": 2087168, - "esp32s31": 2545392, + "esp32s31": 2549760, "esp32-16mb": 2060368, "esp32-eth": 1681040, "esp32-wrover": 1843760, @@ -14,7 +14,7 @@ "esp32p4rev3-eth": 2073888, "esp32s3-zero": 2024192, "esp32-pico": 2107168, - "desktop-macos": 2151832, + "desktop-macos": 2193880, "desktop-windows": 1925120 }, "measured": { @@ -679,21 +679,21 @@ } }, "loc": { - "core": 25734, - "light": 31845, + "core": 27054, + "light": 30739, "platform": 17198, "ui": 12227, - "test": 62726, - "moondeck": 30424 + "test": 62987, + "moondeck": 30588 }, "comments": { "core": { - "lines": 6191, - "ratio": 0.266 + "lines": 6484, + "ratio": 0.265 }, "light": { - "lines": 7649, - "ratio": 0.269 + "lines": 7410, + "ratio": 0.271 }, "platform": { "lines": 3613, @@ -704,29 +704,29 @@ "ratio": 0.3 }, "test": { - "lines": 6923, + "lines": 6944, "ratio": 0.128 }, "moondeck": { - "lines": 4959, - "ratio": 0.186 + "lines": 4966, + "ratio": 0.185 } }, "tests": { - "cases": 2319, + "cases": 2325, "scenarios": 30 }, "docs": { - "md_files": 142, - "md_lines": 30366, - "plans_files": 42, + "md_files": 141, + "md_lines": 30561, + "plans_files": 41, "backlog_lines": 3247, "lessons_lines": 532, "claude_md_lines": 283 }, "complexity": { - "functions": 4143, - "over_threshold": 335, + "functions": 4158, + "over_threshold": 333, "worst_ccn": 128 } } diff --git a/docs/reference/metrics/repo-health.md b/docs/reference/metrics/repo-health.md index 1c149ebac..f80226511 100644 --- a/docs/reference/metrics/repo-health.md +++ b/docs/reference/metrics/repo-health.md @@ -1,6 +1,6 @@ # Repo health -Measured at `35a2f0fb`. Generated by [`moondeck/check/repo_health.py`](../../../moondeck/check/repo_health.py) on every KPI-gate run. **Do not edit by hand.** +Measured at `c9b39d4f`. Generated by [`moondeck/check/repo_health.py`](../../../moondeck/check/repo_health.py) on every KPI-gate run. **Do not edit by hand.** Current state only; the trend is this file's git history (`git log -p docs/reference/metrics/repo-health.md`). Nothing here fails a build: the numbers make growth visible, the judgment stays human. @@ -8,20 +8,20 @@ Current state only; the trend is this file's git history (`git log -p docs/refer | Metric | v6.0.0 | Now | Change | |---|---:|---:|---:| -| flash desktop-macos | 1,963 KB | 2,101 KB | +138.4 KB (+7.0%) | -| flash esp32 | 2,061 KB | 2,141 KB | +79.5 KB (+3.9%) | -| flash esp32p4rev1-eth | 2,022 KB | 2,123 KB | +101.3 KB (+5.0%) | -| flash esp32s3-n16r8 | 2,111 KB | 2,191 KB | +79.9 KB (+3.8%) | -| flash esp32s31 | 2,395 KB | 2,486 KB | +90.3 KB (+3.8%) | +| flash desktop-macos | 1,963 KB | 2,142 KB | +179.4 KB (+9.1%) | +| flash esp32 | 2,061 KB | 2,143 KB | +82.0 KB (+4.0%) | +| flash esp32p4rev1-eth | 2,022 KB | 2,127 KB | +105.0 KB (+5.2%) | +| flash esp32s3-n16r8 | 2,111 KB | 2,193 KB | +81.2 KB (+3.8%) | +| flash esp32s31 | 2,395 KB | 2,490 KB | +94.6 KB (+3.9%) | | tick Effects_pipeline_builds_and_renders (desktop-macos) | 7 ยตs | 6 ยตs | -1 (-14.3%) | | tick Layouts_resize_reallocates_live (desktop-macos) | 12 ยตs | 10 ยตs | -2 (-16.7%) | -| lines core | 22,299 | 25,734 | +3,435 (+15.4%) | -| lines light | 31,054 | 31,845 | +791 (+2.5%) | +| lines core | 22,299 | 27,054 | +4,755 (+21.3%) | +| lines light | 31,054 | 30,739 | -315 (-1.0%) | | lines platform | 16,798 | 17,198 | +400 (+2.4%) | | lines ui | 11,394 | 12,227 | +833 (+7.3%) | -| lines test | 57,759 | 62,726 | +4,967 (+8.6%) | -| lines moondeck | 29,325 | 30,424 | +1,099 (+3.7%) | -| unit tests | 2,120 | 2,319 | +199 (+9.4%) | +| lines test | 57,759 | 62,987 | +5,228 (+9.1%) | +| lines moondeck | 29,325 | 30,588 | +1,263 (+4.3%) | +| unit tests | 2,120 | 2,325 | +205 (+9.7%) | | scenarios | 21 | 30 | +9 (+42.9%) | Against the release `v6.0.0`, the fixed point a user compares with; the tables below compare against the last commit. A firmware not rebuilt since `v6.0.0` is left out, and a measure the release did not record yet, such as the code report, joins from the next one. @@ -30,20 +30,20 @@ Against the release `v6.0.0`, the fixed point a user compares with; the tables b | Target | Flash | Capacity | Used | Built | |---|---:|---:|---:|:--:| -| desktop-macos | 2,101 KB (โˆ’16 KB) โœ“ | - | - | yes | +| desktop-macos | 2,142 KB (+41 KB) โš  | - | - | yes | | desktop-windows | 1,880 KB | - | - | carried 6d | -| esp32 | 2,141 KB (+208 B) โš  | 2,496 KB | 86% | yes | +| esp32 | 2,143 KB (+2 KB) โš  | 2,496 KB | 86% | yes | | esp32-16mb | 2,012 KB | 4,096 KB | 49% | **STALE 27d** | | esp32-eth | 1,642 KB | 2,496 KB | 66% | **STALE 25d** | | esp32-pico | 2,058 KB | 3,072 KB | 67% | **STALE 27d** | | esp32-wrover | 1,801 KB | 2,496 KB | 72% | carried (age?) | -| esp32p4rev1-eth | 2,123 KB (+640 B) โš  | 4,096 KB | 52% | yes | +| esp32p4rev1-eth | 2,127 KB (+4 KB) โš  | 4,096 KB | 52% | yes | | esp32p4rev1-eth-wifi | 2,304 KB | 4,096 KB | 56% | carried 6d | | esp32p4rev3-eth | 2,025 KB | 4,096 KB | 49% | **STALE 7d** | -| esp32s3-n16r8 | 2,191 KB (+416 B) โš  | 4,096 KB | 54% | yes | +| esp32s3-n16r8 | 2,193 KB (+1 KB) โš  | 4,096 KB | 54% | yes | | esp32s3-n8r8 | 2,038 KB | 3,072 KB | 66% | **STALE 28d** | | esp32s3-zero | 1,977 KB | 2,496 KB | 79% | **STALE 28d** | -| esp32s31 | 2,486 KB (+512 B) โš  | 4,096 KB | 61% | yes | +| esp32s31 | 2,490 KB (+4 KB) โš  | 4,096 KB | 61% | yes | | qemu | 1,351 KB | - | - | carried (age?) | `Built: yes` was measured this run. `carried (age?)` was not rebuilt either and predates this record, so its age is unknown: it dates itself on the next build. `carried Nd` was NOT rebuilt and its number is N days old, so an absent delta says nothing about the change. **STALE** marks a carry older than 7 days: the number has gone unchecked long enough that growth will surface later as one jump, blamed on whichever commit happens to rebuild that target. `Used` is against the app slot in the firmware's own partition table. @@ -52,17 +52,17 @@ Against the release `v6.0.0`, the fixed point a user compares with; the tables b | Target | Net | New | Removed | Grown | Shrunk | Other | Since | |---|---:|---:|---:|---:|---:|---:|---| -| esp32 | +0.2 KB | +0.0 KB | +0.0 KB | +0.3 KB | -0.1 KB | -0.0 KB | `35a2f0fb` | -| esp32p4rev1-eth | +0.6 KB | +0.0 KB | +0.0 KB | +0.9 KB | -0.4 KB | +0.0 KB | `35a2f0fb` | -| esp32s3-n16r8 | +0.4 KB | +0.0 KB | +0.0 KB | +0.5 KB | -0.1 KB | +0.0 KB | `35a2f0fb` | -| esp32s31 | +0.5 KB | +0.0 KB | +0.0 KB | +0.5 KB | -0.1 KB | +0.0 KB | `35a2f0fb` | +| esp32 | +2.5 KB | +43.4 KB | -25.3 KB | +5.1 KB | -9.2 KB | -11.5 KB | `c9b39d4f` | +| esp32p4rev1-eth | +3.7 KB | +51.1 KB | -31.1 KB | +7.9 KB | -9.8 KB | -14.3 KB | `c9b39d4f` | +| esp32s3-n16r8 | +1.3 KB | +43.9 KB | -25.8 KB | +5.6 KB | -10.8 KB | -11.6 KB | `c9b39d4f` | +| esp32s31 | +4.3 KB | +54.2 KB | -30.4 KB | +7.8 KB | -11.3 KB | -16.0 KB | `c9b39d4f` | Largest moves: -- **esp32**: `mm::ui::appJs` +137 B, `mm::HttpServerModule::streamFsFile(mm::platform::TcpConnecti` +65 B, `mm::HttpServerModule::handleListPatchRow(mm::platform::TcpCo` -45 B, `_ZN2mm13ModuleFactory12registerTypeINS_13NetworkModuleEEEbPK` -38 B, `mm::DriverBase::rebuildCorrection(unsigned char)` +32 B -- **esp32p4rev1-eth**: `mm::DriverBase::rebuildCorrection(unsigned char)` -348 B, `mm::TetrixEffect::tick()` +144 B, `mm::ui::appJs` +137 B, `mm::Hub75Driver::tick()` +106 B, `bool mm::ModuleFactory::registerType(c` +100 B -- **esp32s3-n16r8**: `mm::TetrixEffect::tick()` +144 B, `mm::ui::appJs` +137 B, `_ZN2mm13ModuleFactory12registerTypeINS_16RubiksCubeEffectEEE` -108 B, `mm::Hub75Driver::tick()` +96 B, `mm::HttpServerModule::handleListPatchRow(mm::platform::TcpCo` +45 B -- **esp32s31**: `mm::ui::appJs` +137 B, `mm::Hub75Driver::tick()` +106 B, `mm::platform::hub75Init(mm::platform::Hub75Handle&, mm::plat` +84 B, `mm::registerModuleTypes()` -68 B, `mm::RubiksCubeEffect::init(mm::draw::Canvas const&, short, s` +62 B +- **esp32**: `void mm::draw::advect16