Applying .badge after .tag on a List(selection:) row wrapped the tagged
label in a view that no longer carried the tag, making the "Alerts &
Notifications" row unselectable on macOS 14. Replaced with an explicit
Label + HStack row showing the active-alert count as a styled capsule —
tag stays on the row, count still renders when alerts are active.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Read-only mounts (DMG images like /Volumes/Ghostty, update snapshots) with
~0% free produced false-positive low-storage alerts. StorageVolumeContext
now carries isReadOnly and totalBytes; the rule skips read-only volumes and
volumes under 1 GB where thresholds are meaningless. Regression tests cover
both exclusions plus the normal trigger path.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Two latent bugs kept all SMC telemetry dead:
- IOServiceMatching("AppleSMCClient") never matched — the kernel service
is AppleSMC, so openWithError always failed and every SMC-gated provider
(thermal, fan, component, power) reported unavailable.
- #pragma pack(1) shrank SMCKeyData_t to 74 bytes; the SMC user client
requires the canonical 80-byte layout and rejected every
IOConnectCallStructMethod with kIOReturnBadArgument. Verified live on
Intel hardware: unpacked calls succeed and return key data.
Also sources the alert engine's batteryLevel from the SMC-independent
batteryHealth path (currentCapacity/maxCapacity), falling back to the
power provider.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Providers emitted identifiers and field keys that decodeSnapshot never
looked up, leaving CPU/kernel/load/disk sections zeroed and memory%,
storage%, network, process RSS, and fan fields decoded as zero.
Store-side decode now reads the emitted schema; providers gain the
previously-missing fields: network isUp (IFF_UP via getifaddrs), process
isStopped/isZombie (pbi_status), fan name (F{i}ID). Memory utilization is
computed as used/total in the decoder. decodeSnapshot is internal for
@testable access; new MMSnapshotContractTests cover the emitted-key
contract with synthetic dictionaries (93 tests total, 0 failures).
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>