v0.7.2 β the monitor you can trust
Sprout 0.7.2 is the release where the logger became unkillable and the plants got a real registry.
The headline promise, kept: just be a damn logger and never stop. The collection worker now supervises itself, restarts on any death, refuses loudly instead of silently, and every failure it can still hit writes itself into a log in plain words. The dashboard's one button never lies about recording state.
The other half: Plants & Sensors β your real fleet in a tab. Add plants and sensors, map any sensor to any plant with a plant-first picker (no channel soup), pause what's resting, and permanently delete what's gone β with a receipt showing exactly what left the disk. Classic review-then-save; nothing changes until you say so.
Also aboard: per-channel calibration tiers live on the wire and honest on every chip (a fully-calibrated channel wears no badge at all), an opt-in environment overlay (context, not cause), era-aware provenance that never cries VIOLATION at your own history, a web flasher that offers only what's bench-proven, ed25519 release signing (this release is its first live fire), and the dashboard's old 15-second slowness diagnosed down to ~3.
Grown on a kitchen windowsill. Raw counts + band are the truth. tend well. π±
What's Changed
β¨ Features
- feat(analytics): cross-board comparability guard (honesty-guard slice, #832) by @OrangePeachPink in #943
- feat(dashboard): three-tier cal honesty β the C5 stops wearing "provisional" (#951) by @OrangePeachPink in #957
- feat(firmware): wifi==serial config-command parity β /cmd endpoint (#826) by @OrangePeachPink in #954
- feat(firmware/build): board-aware factory_bin + verified-marker (#271) by @OrangePeachPink in #956
- feat(firmware/cal): per-board-type calibration resolution chain (#952) by @OrangePeachPink in #964
- feat(dashboard): surface config_id on Diagnostics β closes the last ADR-0030 gap (#831) by @OrangePeachPink in #984
- feat(serve): verify-then-assert auto-start collection at launch β the honest promise of Monitor (#872) by @OrangePeachPink in #991
- feat(registry): temporal registry model β #921 slice 1 (Data foundation) by @OrangePeachPink in #996
- feat(cal): parse the cal_tier wire token β #951 tier chip true on the live WiFi fleet (#952/#957) by @OrangePeachPink in #997
- feat(registry): /registry GET seam for the Plants & Sensors tab + board taxonomy (#921 slice 2) by @OrangePeachPink in #1000
- feat(dashboard): Plants & Sensors tab β read-only registry + first-run landing (#921 slice 2) by @OrangePeachPink in #1003
- feat(telemetry): cal_tier/cal_src on the WiFi soil rows β the live tier chip (#4) by @OrangePeachPink in #1002
- feat(pages): Actions-deployed Pages β web-flasher bins + design library (#271) by @OrangePeachPink in #1006
- ci(release): ed25519 firmware signing + key-ceremony run-sheet (#302, PR-in-waiting) by @OrangePeachPink in #989
- feat(registry): POST /registry/apply β classic-save the mapping batch (#921 slice 3) by @OrangePeachPink in #1021
- feat(registry): device purge β the delete backend (#921 slice 4, small β v0.7.2) by @OrangePeachPink in #1022
- feat(dashboard): Plants & Sensors editing β add + classic save (#921 slice 3a) by @OrangePeachPink in #1023
- feat(registry): per-channel view on /registry β cal tier/provenance + free-port occupancy (#921 slice 5) by @OrangePeachPink in #1025
- feat(dashboard): opt-in environmental overlay on the plant trajectory + the value-verdict (#922) by @OrangePeachPink in #1030
- feat(dashboard): the mapping picker β plant-first, no dropdown soup (#921 slice 3b) by @OrangePeachPink in #1033
- feat(dashboard): Plants & Sensors lifecycle β Pause/Resume + loud Delete (#921 slice 3c) by @OrangePeachPink in #1024
π Bug fixes
- fix(docs): pin Design Library contributor links to /blob/main; absolute PRD link by @OrangePeachPink in #914
- fix(design): commit Trust-Your-Sensor board photos (EXIF-stripped) + link the page (#912) by @OrangePeachPink in #937
- refactor(ui): plantLabel() everywhere + identity-leak tripwire β #803-805 class extinct (#925) by @OrangePeachPink in #939
- perf(serve): phase-timing decomposition for slow dashboard builds (#953) by @OrangePeachPink in #959
- fix(docs): repoint retired-BACKLOG ref + site-absolute the served /docs links (#911) by @OrangePeachPink in #960
- fix(ux): control-surface collapse β one collection action, serial baseline β Diagnostics (#923) by @OrangePeachPink in #955
- perf(fleet): parallelize served-device fetches β the ~14s was timeouts, not re-parse (#953 slice 2) by @OrangePeachPink in #967
- fix(dashboard): fleet-poll sources get their own labeled line, not file cosplay (#965) by @OrangePeachPink in #970
- fix(serve): client abort mid-response no longer cascades into a double traceback (#969) by @OrangePeachPink in #992
- fix(launcher): say when self-update is skipped + print the running sha by @OrangePeachPink in #982
- fix(serve): Stop preempts the request pile β reject-new + grace + hard-exit (#972) by @OrangePeachPink in #987
- fix(ux): served status line speaks honest sensor counts, not transport-split (#974) by @OrangePeachPink in #986
- feat(dashboard): dual-state logging button + am-I-recording banner (#980 + #979) by @OrangePeachPink in #999
- fix(dx): identifier-guard catches denylisted hostnames via committed SHA-256 hashes by @OrangePeachPink in #961
- fix(fleet): supervise the logger β restart on crash, loud give-up, idempotent start (#1004 Β· #968 Β· #1007) by @OrangePeachPink in #1010
- fix: close the P0 release gate β one-button start guards + mDNS IP-persist (#1004, #953) by @OrangePeachPink in #1014
- fix(dashboard): request-generation guard β a stale /data.json response can't paint (#976) by @OrangePeachPink in #1016
- fix(launcher): stub/body split so self-update can't overwrite the running script by @OrangePeachPink in #1015
- fix(ux): era-aware provenance contract β no red VIOLATION at legacy dirt data (#977) by @OrangePeachPink in #1017
- fix(logger): archival failures surface loudly, never silently swallowed (#900, slice) by @OrangePeachPink in #1019
- fix(pages): pull esp32c5 from the web flasher β EWT 10.0.0 can't flash it (#271) by @OrangePeachPink in #1028
- fix(registry): _REPO off-by-one β read/write the real config, not tools/config/ (#1029) by @OrangePeachPink in #1031
π Documentation
- docs(audit): ADR-0030 display-contract conformance β config_id is the one gap (#831) by @OrangePeachPink in #945
- docs(onboarding): Windows USB-serial driver prep + first-run pio penv retry by @OrangePeachPink in #948
- docs(adr): ADR-0026 body β Phase-0 acknowledgment + maker-first scaling by @OrangePeachPink in #944
- fix(docs): release-notes template points Discussions at its absolute URL (#911 finding 4) by @OrangePeachPink in #958
- docs(voice): welcome AI-assisted contributions, without gatekeeping (#920 slice 1) by @OrangePeachPink in #962
- docs(ux): sweep the settled collection vocabulary to the remaining surfaces (#873) by @OrangePeachPink in #971
- docs(on-ramp): reference cal_class_defaults.h as the real-anchor source (#550) by @OrangePeachPink in #983
- docs(voice): plain-language the contributor path β de-jargonize merge + review (#920 slice 2) by @OrangePeachPink in #988
- docs(doctrine): codify the honesty-law pair β wear only the caveats you've earned (#977) by @OrangePeachPink in #990
- docs(experiments): 2026-07-11 watering dose-response β first per-pot-cal fleet run (v0.7.2) by @OrangePeachPink in #1037
π§ Other changes
- fix(firmware): bump PLANTS_FW_VERSION 0.7.0 β 0.7.1 + OTA fleet (ADR-0030 symptom-1 relabel) by @OrangePeachPink in #902
- chore(release): sync the product version line to 0.7.1 (pyproject + lock) by @OrangePeachPink in #903
- ci(public): restore full per-PR CI β revert the #740 slim posture (free public minutes) by @OrangePeachPink in #906
- docs(adr): ratification batch β 0026 Β· 0029 Β· 0030 Β· 0031 Proposed β Accepted (maintainer rulings, 2026-07-10) by @OrangePeachPink in #915
- docs(process): velocity modes V1/V2 β the v0.7.2 accelerated pilot + its fence by @OrangePeachPink in #916
- perf(dashboard): window the read path to the range β root opens fast (#918) by @OrangePeachPink in #932
- fix(analytics): trend + forecast fits exclude fault/sub-rail/OOB rows (#919) by @OrangePeachPink in #935
- chore(analytics): dedupe the capture-parse β watering_arc reuses watering_events (#909) by @OrangePeachPink in #938
- fix(logger): surface the monitor give-up reason to the operator (#813 loud-give-up) by @OrangePeachPink in #941
- fix(firmware): board-aware cal-selection seam β C5 uses its own cal, not the classic table (#899) by @OrangePeachPink in #933
- feat(dashboard): render live WiFi RSSI per device β real dBm + labeled band (#814) by @OrangePeachPink in #973
- perf(fleet): last-good-IP-first candidate order β kill the flat 4.7s mDNS fetch tax (#953 slice 3) by @OrangePeachPink in #981
Full Changelog: v0.7.1...v0.7.2