feat(alerts): Threshold Alert Engine, Notification Center & Release Packaging (M5 / Issue #24) #26

Merged
gronod merged 2 commits from feat/24-threshold-alerts into milestone/m5-alerts-hardening 2026-09-08 14:04:19 +01:00
Owner

Summary

Implements Issue #24 (Threshold Alerts & macOS Notification Center Integration) plus the M5 release-packaging step from BUILD-PLAN.md.

Alert Engine (Sources/Intelligence/)

  • AlertEngine (@Observable, @MainActor) evaluates five configurable rules after every telemetry decode pass via a Sendable AlertEvaluationContext:
    • High CPU temperature (> 95°C, peak core/package)
    • Cooling fan stall (0 RPM while CPU ≥ 75°C)
    • Low free memory (< 500 MB) / Critical kernel memory pressure
    • Low storage per volume (< 10 GB or < 10% free)
    • Low battery (< 10% while discharging)
  • Edge-triggered breach → resolve lifecycle with per-alert cooldown (default 15 min, configurable), so persistent conditions re-fire at most once per window and cleared conditions can alert again immediately.
  • Capped in-memory alert history log (200 events: triggered/resolved).
  • AlertConfiguration persisted as JSON in UserDefaults.

Notification Delivery

  • AlertNotificationDispatching protocol (mockable, per AGENTS.md synthetic-testing rules) backed by UNUserNotificationCenter.
  • Authorization requested at launch via NSApplicationDelegateAdaptor; MM_ALERT category with Open MacMonitor and View Processes actions routed through AppNavigationBus (activates window, selects Processes tab).
  • Foreground banners enabled via willPresent[.banner, .sound, .list].

UI

  • New macOS Settings scene (AlertsSettingsView): master toggle, permission status, test notification, cooldown picker, per-rule thresholds.
  • New Alerts & Notifications sidebar tab (AlertsView): active-alert cards + history log.
  • Warning badge in the dashboard header and an ⚠ indicator in the menu bar label while alerts are active.

Bug fix

  • Memory pressureLevel now decodes memoryPressureStatus (previously always fell back to "Normal").

Release Packaging (M5 item 2)

  • New release-package job in .gitea/workflows/build.yml on v* tags: Release x86_64 build → ad-hoc codesign (required for notifications in distributed builds) → ditto zip → workflow artifact + Gitea release asset MacMonitor-intel-x86_64.zip.

Verification

  • xcodebuild build test -scheme MacMonitor -destination 'platform=macOS,arch=x86_64' CODE_SIGNING_ALLOWED=NO87 tests, 0 failures (25 new MMAlertsTests).
  • swiftlint lint0 violations.
  • xcodegen generate regenerated project.pbxproj.

Closes #24 once merged through milestone/m5-alerts-hardeningdevelop.

## Summary Implements **Issue #24** (Threshold Alerts & macOS Notification Center Integration) plus the M5 release-packaging step from BUILD-PLAN.md. ### Alert Engine (`Sources/Intelligence/`) - `AlertEngine` (@Observable, @MainActor) evaluates five configurable rules after every telemetry decode pass via a Sendable `AlertEvaluationContext`: - High CPU temperature (> 95°C, peak core/package) - Cooling fan stall (0 RPM while CPU ≥ 75°C) - Low free memory (< 500 MB) / Critical kernel memory pressure - Low storage per volume (< 10 GB or < 10% free) - Low battery (< 10% while discharging) - Edge-triggered breach → resolve lifecycle with per-alert cooldown (default 15 min, configurable), so persistent conditions re-fire at most once per window and cleared conditions can alert again immediately. - Capped in-memory alert history log (200 events: triggered/resolved). - `AlertConfiguration` persisted as JSON in `UserDefaults`. ### Notification Delivery - `AlertNotificationDispatching` protocol (mockable, per AGENTS.md synthetic-testing rules) backed by `UNUserNotificationCenter`. - Authorization requested at launch via `NSApplicationDelegateAdaptor`; `MM_ALERT` category with **Open MacMonitor** and **View Processes** actions routed through `AppNavigationBus` (activates window, selects Processes tab). - Foreground banners enabled via `willPresent` → `[.banner, .sound, .list]`. ### UI - New macOS **Settings** scene (`AlertsSettingsView`): master toggle, permission status, test notification, cooldown picker, per-rule thresholds. - New **Alerts & Notifications** sidebar tab (`AlertsView`): active-alert cards + history log. - Warning badge in the dashboard header and an ⚠ indicator in the menu bar label while alerts are active. ### Bug fix - Memory `pressureLevel` now decodes `memoryPressureStatus` (previously always fell back to "Normal"). ### Release Packaging (M5 item 2) - New `release-package` job in `.gitea/workflows/build.yml` on `v*` tags: Release x86_64 build → ad-hoc `codesign` (required for notifications in distributed builds) → `ditto` zip → workflow artifact + Gitea release asset `MacMonitor-intel-x86_64.zip`. ## Verification - `xcodebuild build test -scheme MacMonitor -destination 'platform=macOS,arch=x86_64' CODE_SIGNING_ALLOWED=NO` — **87 tests, 0 failures** (25 new `MMAlertsTests`). - `swiftlint lint` — **0 violations**. - `xcodegen generate` regenerated `project.pbxproj`. Closes #24 once merged through `milestone/m5-alerts-hardening` → `develop`.
gronod added 2 commits 2026-09-08 13:59:55 +01:00
Introduce Sources/Intelligence with an @Observable AlertEngine that evaluates
five configurable rules (CPU temperature, fan stall, low memory, low storage,
low battery) against a Sendable AlertEvaluationContext built after each
telemetry decode pass. Breached conditions dispatch through a mockable
AlertNotificationDispatching protocol to UNUserNotificationCenter with
per-alert cooldowns, edge-triggered resolve detection, and a capped
in-memory history log.

Add a macOS Settings scene (AlertsSettingsView) for thresholds, cooldown,
permission status, and test notifications; a new Alerts and Notifications
sidebar tab with active-alert cards and the history log; header and menu bar
warning indicators; and an AppNavigationBus so notification actions
(Open MacMonitor, View Processes) steer the main window.

Also fix the memory snapshot decode to read memoryPressureStatus so
pressureLevel is populated correctly.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add a release-package job (gated on v* tags, after build-and-test) that
builds the Release configuration for x86_64, ad-hoc signs the app bundle so
UNUserNotificationCenter works in the distributed build, archives
MacMonitor.app via ditto, uploads it as a workflow artifact, and creates a
Gitea release with the zip attached via the API token.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
gronod merged commit 431b2376c3 into milestone/m5-alerts-hardening 2026-09-08 14:04:19 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gronod/MacMonitor#26