## [0.55.0] - 2026-09-09

### Added
- **io:** add procedural WS2812B effects for rules
- **rules:** add stateful A/B toggle node
- **io:** add per-pixel WS2812B control for rules
- **io:** add PSRAM-backed WS2812B control for rules
- **web:** reorganize player and management navigation
- **rules:** add bounded execution history in PSRAM
- **rules:** add continuous-condition mode to Check nodes
- **diag:** report the DMA-capable half of internal RAM
- **network-music:** play through the service so the queue, length and position exist
- **network-music:** make it a first-class media source for transport and hotspots
- **network-music:** lay the playlist out from the shared browser section
- **network-music:** report track position and length for the progress bar
- **network-music:** add HTTP MP3 playback with dedicated screen and server playlist
- **rules:** show a rule's id beside its name, on the canvas and in the table
- **rules:** let import update a rule that is already on the device
- **rules:** let import update a rule that is already on the device
- **scripts:** add a web-only flash scope to build-flash.py
- **rules:** export one rule, and let import add instead of replacing
- **rules:** offer a dimmable output's level next to its on / off
- **io:** make the PWM frequency a device-wide setting
- **rules:** let a check wait for its condition before giving up
- **rules:** let a check inside a sequence stop the branch when it fails
- **rules:** set a PWM level from the action list, not by typing the command
- **rules:** name each group of controls on the shelf
- **rules:** add blocks from the block they follow, and flag a condition the trigger already decides
- **rules:** give a rule an else branch, and add the ≥ and ≤ operators
- **rules:** trigger on an I/O slot crossing a value
- **web:** show the live pin map on the I/O page
- **io:** measure analog inputs on the ADC1 slots

### Changed
- **ui:** time label scrolling in ms so a slower speed actually applies
- **lwip:** halve the TCP receive window, pinned whole by a fast server
- **network-music:** close the old pipeline before building the next one
- **audio:** let the MP3 duration parser work from a buffer, not just a file
- **network-music:** poll a revision counter instead of the 25 KB snapshot fix(network-music): keep the NVS commit off the state mutex fix(network-music): confine the directory proxy to the saved server
- **rules:** send IR learning to the Remotes tab instead of doing it twice
- **rules:** list the switch slots under the buttons, IR last

### Fixed
- **rules:** light the block the device actually ran on else branches
- **rules:** restore condition insertion and drop the redundant check record
- **rules:** add hold timeout, optimize history, and harden testing and diagnostics
- **rules:** report queue rejection and improve rule testing
- **audio:** tear the pipeline down when the retry budget runs out
- **network-music:** read the length past a big ID3 tag instead of giving up
- **ui:** rebuild the network-music screen when internet assets land
- **network-music:** put the worker stack back to 8192, the settings write needs it
- **network-music:** read the track length before playback, not against it
- **network-music:** move the worker stack into task_stacks.h and trim it to measurement
- **audio:** tear the pipeline down when a finite stream ends, not just flag it
- **web:** name the layout sections and the hotspot action that SD shares with Network Music
- **ui:** show the VU on Network Music and name the layouts it shares with SD
- **network-music:** restore the queued track after a fetch, not a radio station
- **web:** move the Network Music server to the Network tab and style its save button
- **web:** restyle the Network Music page to the shared header and theme
- **audio:** handle HTTP EOF and mark playback finished after audio drains
- **web:** show the PWM frequency range and clamp the field to it
- **rules:** move Export and Import up beside Save rules
- **web:** drop the English humidity word from the weather readout
- **rules:** stop render() unselecting a control the moment it is clicked
- **io:** the pull-up label said GND, which is where the switch goes, not the pull
- **io:** tell the card a pin is pending instead of calling it unassigned
- **rules:** repair the table view and give it every edit the canvas has
- **rules:** stop the table view throwing on any rule with a condition
- **rules:** hang the otherwise tab on the condition it forks at
- **rules:** say what unit an I/O value is compared in
