Changelog
What changed, by version.
Written from the real git history and the build logs in iterations/ — nothing here is backfilled from memory. Format follows Keep a Changelog.
Unreleased — Week 1 roadmap
Open as PR #68, not yet merged to master. Built as four parallel phases (one subagent each, in isolated git worktrees, hub-verified, then hand-merged), tracked in issues #64–#67 and mapping back to the 14 Week 1 section issues #1–#14. The backend test suite grew from 76 to 353 tests, all passing.
Because all four phases modified the same core classes, integration was done as real 3-way git merges with every conflict hand-resolved to combine both sides' intent — roughly 40 conflict blocks — rather than by applying patches. The merge itself surfaced 5 real regressions, listed under Fixed.
Added — audio modes & musical intelligence Phase A
- Six new color-mapping modes, bringing the total to 20:
energy_contour,bass_only_pulse,mirror_mode,random_walk_hue,silence_flash_recover,crescendo_ramp. TempoTracker— BPM estimation by autocorrelation over an onset-strength signal, tap-tempo, beat-confidence scoring, an adaptive beat threshold, and three sensitivity presets. Tempo state is surfaced in the session status payload.- All eight genre preset bundles plus custom preset save/apply — each bundle sets mode, sensitivity, hue, band count, dwell and beat-sensitivity together.
Added — signal quality & test tooling Phase B
SignalConditioner— automatic gain control with configurable attack/release, a noise gate, clip/overload detection, DC-offset removal, independent per-band gain, and a calibrate-from-silence flow with persisted per-device calibration.- Full N-band spectrum exposure in the session status payload, a rolling latency window on
BulbSender, and beat-flash / BPM data hooks — the data layer a live visualizer needs. - A reusable synthetic-audio test harness, golden-value regression tests locking every mode's exact hue/brightness output against a fixed multi-tone input, fuzz tests, and a latency-measurement harness.
Added — orchestration, per-bulb config & zones Phase C
- Two new group role modes —
waveandmirror— alongside the existing unison / phase-offset / band-split. - Per-bulb hue-offset, brightness-scale and band-assignment overrides within a group session.
- Failover handling for unreachable bulbs, so one dead bulb no longer degrades the whole group. Orchestration presets (full CRUD) let a multi-bulb arrangement be saved and reapplied.
- A Zone data model sitting above groups, resolving direct device membership and group membership into one deduped list.
- Per-bulb hue-calibration, max-brightness cap and audio-reactive-eligibility enforced down at the device layer rather than advisory in the API — a capped bulb stays capped regardless of which route drives it.
- Per-device-index audio-input sensitivity calibration, an audio-input health-check endpoint, and index validation so a bad device index fails with a clear 400 instead of deep inside the capture thread.
Added — sessions, reliability, safety & accessibility Phase D
- Session-conflict detection — a solo and a group session competing for the same bulb is now caught, with a
forceoverride, instead of two senders fighting over one device. - Session lifecycle controls: max-duration auto-stop, a warm-up ramp, auto-pause on a manual command with auto-resume after a grace period, one-click resume-last-session, and named session presets.
- Schedule-engine support for scheduled audio sessions.
- Reliability hardening: an explicit socket timeout on audio sends, a watchdog thread that restarts a stalled sender, device fallback when the configured audio input disappears, graceful restart on stream errors, config validation, and sliding-window rate limiting on start/stop.
- Photosensitive-epilepsy safety — a hard flash-rate cap citing WCAG 2.3.1 “Three Flashes or Below Threshold” and ITU-R BT.1702, enforced in the send path rather than left to the caller; per-mode flash-heavy metadata; a one-click disable-flash-heavy toggle; a reduced-motion profile; and a configurable max-brightness-swing.
- Lightshow capture / export / replay — records every action a sender actually sends, exports it as JSON, and replays it later with no live audio. Plus applause/cheer detection and silence-triggered auto-off.
Fixed
- A mode-validation check on the solo audio-reactive start route was silently dropped while hand-merging — the group route kept its check, the solo route didn't. Restored.
- The new rate limiter's state is module-level and leaked across tests in the same run, so unrelated tests started failing with 429s. Now reset by an autouse fixture.
- Three test mocks returned a bare
object()from a mockedstart_session, which broke once the merged route began calling.confirmation()on the returned session. - A genuine naming collision — Phase A's
audio_presets()route handler shadowed theaudio_presetsmodule Phase D's routes import. Renamed the handler. - Four subagent worktree directories were accidentally committed as embedded git repositories by the merge's
git add -A. Untracked, and that path is now gitignored.
Fixed — found by live testing, not by the suite
The backend suite mocks the Tuya device layer, so none of these were reachable by it. All three surfaced from testing against a real physical bulb that had gone unreachable on the LAN:
- An unreachable device hung any
/statuscall for minutes. Timed directly against the real device: 3m26s before tinytuya gave up, because nothing bounded its connection timeout (default 5s) or retry limit (default 5 — and each retry cost noticeably more than the timeout in practice, so it isn't a cleantimeout × retriesbound). Capped at 2s / 1 retry; the same real device now fails in ~2s. - The status badge got stuck reading “connecting…” forever. Its render function returned early whenever no poll had ever succeeded, and that condition was only cleared by a successful poll — so if a device never came back, the placeholder never updated no matter how many times it polled. Fixed with an explicit “have we polled at least once” flag.
- The badge and the Control panel showed contradictory labels — “LIVE DATA · OFF” versus “OFFLINE” for the same device — once the fix above let an offline status object populate the cache, at which point the badge read the power field off it instead of checking whether the device was online at all.
Known gaps in this round (deliberately not claimed as done)
- No frontend visualizer. Phase B shipped the spectrum/beat/latency data, but nothing renders it yet.
- Genre presets are reasoned, not tuned by ear. The bulb has been offline for every build session so far, so nobody has actually heard “jazz” vs “metal” on real hardware.
- Two unreconciled preset systems ship together — genre bundles and session-config snapshots — overlapping in name only. Likewise two unreconciled calibration systems (per-device-key signal conditioning vs. per-device-index sensitivity).
- Most of the music-player-adjacent section is not built — scope was deliberately cut to just lightshow capture/replay rather than taking on media-player integration.
- An offline device still takes ~9–13s for the page to fully settle, since the badge and the panel each make their own independent (now ~2s-bounded) call. A shared in-flight cache would fix it; not built.
v0.3.0 — 2026-07-29
Four phases built in parallel (isolated subagent worktrees, hub-verified and merged), plus a QoL round and a mobile-fix PR. Feature count: 137 → 159.
Added
- Two new audio modes —
harmonic_pairsandkick_snare_split. - Remote-access hardening — session listing/revocation, an audit log, per-IP login rate limiting.
bulbctl— a stdlib-only CLI wrapping the full REST API, with shell completions.GET /api/analytics/usage— real per-device on-time from logged history.- A real backend pytest suite (previously none existed).
- Live-ticking sleep/wake timer countdowns and status badge — no more refresh-to-see.
- Remembers last device/panel, keyboard shortcuts, copy-to-clipboard, and Undo on cancelled timers.
- Rounder/softer visual pass, and a real mobile-friendliness fix (sidebar was squeezing to ~16px on phones).
- Tailscale Serve documented and exercised as the recommended off-LAN access path.
- New Active Roadmap / Roadmap Archive / Network Graph pages on this site, replacing the old single roadmap page.
Fixed
- A real flicker bug in
harmonic_pairs— 180°-apart hue anchors cancelling to (0,0) at a 50/50 energy split. - The mobile sidebar-squeeze bug (an unreset grid-column span at ≤800px).
- A real test-isolation gap — most of the pytest suite didn't isolate PIN-gate state, so enabling it for real broke 16 tests with 401s.
v0.2.0 — 2026-07-28
Two build rounds shipped together: audio-reactive lighting (and its v2 rework) and secure remote access. Feature count: 97 → 137.
Added
- Audio-reactive lighting: 12 modes, capturing from VoiceMeeter/virtual-cable sources or real microphones.
- Multi-bulb audio orchestration — unison, phase-offset, and band-split roles.
- Sub-15ms internal decision latency, decoupled from a configurable per-bulb dwell time.
- Network auto-discovery — weekly background scanning plus on-demand scan.
- PIN-gated remote access — PBKDF2-hashed PIN, signed sessions, brute-force lockout.
AGENTS.md, a ~1,000-item phased roadmap, three new project skills, this documentation site.
Fixed
- An IP-change log entry reported the wrong “old IP” (mutated the value before reading it).
- The audio brightness floor never actually reached its floor during silence.
- Bulb network calls inside the audio callback froze the entire analysis pipeline when the bulb was slow/offline — moved to a dedicated sender thread.
- Hue smoothing used a linear blend that breaks at the 0°/360° wrap boundary.
- The PIN gate blocked the root page itself once enabled — a real lock-yourself-out bug.
v0.1.1 — 2026-07-27
Added
- Polyform Noncommercial License 1.0.0; GitHub mirror links in
README.md.
Fixed
- Scrubbed a briefly-leaked device ID and LAN IP before the GitHub mirror went public.
v0.1.0 — 2026-07-27
Initial prototype. 97 working features, built after reverse-engineering local control of a Bytech A19 Wi-Fi RGB+CCT bulb. See Build History for how the local credentials were obtained.
**Smart Bulb Dashboard — v0.1.0** (2026-07-27) Initial prototype. 97 working features, built after reverse-engineering local control of a Bytech A19 Wi-Fi RGB+CCT bulb (Tuya protocol v3.5). Full changelog: https://therocksss.github.io/smart-bulb-dashboard/changelog.htmlFull file with the release-automation process note: the complete CHANGELOG.md.