feat: enforce schedule rules in the background via DeviceActivity windows
Schedule (time-window) rules had no background enforcement: RuleScheduler.sync() skipped them, so their shields were applied only by RuleEnforcer.refresh() — the launch + 30s foreground loop. A window that began while the app was closed didn't engage until the user reopened the app, which is why scheduled blocks could land late or unevenly. RuleScheduler now registers a repeating DeviceActivitySchedule per enabled schedule rule's window (sched-<uuid>, plus sched2-<uuid> for windows that cross midnight, since DeviceActivity can't express an interval whose end precedes its start). The monitor extension routes these to a new ScheduleEnforcement.reconcile(), which recomputes the rule's live schedule state from its snapshot (RuleSchedule.isActive, honouring days, pause and the midnight-crossing rule) and applies or clears the shield to match — the same logic RuleEnforcer.refresh runs in the foreground, kept as the reconciliation safety net because interval callbacks are known to fire late or not at all. - RuleSnapshot gains startMinutes/endMinutes, with a tolerant decoder so snapshots written before these fields still load instead of failing the whole batch and blinding the extensions until the app reopens. - Window activities are fingerprinted on their interval alone, so changing days, mode or apps no longer needlessly restarts monitoring. On-device verification of the background transition is still pending (the simulator does not deliver DeviceActivity callbacks); covered by new unit tests across the scheduler, the snapshot codec and the new enforcement reactions. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
11
AGENTS.md
11
AGENTS.md
@@ -140,9 +140,14 @@ Gotchas learned the hard way:
|
||||
limits accrue in the Usage section and block at the budget; open-limit
|
||||
apps shield immediately with an "Open (N left)" button; an open lasts
|
||||
~15 minutes (DeviceActivity's minimum interval) before re-shielding.
|
||||
- **Schedule-rule background transitions** still rely on the app running
|
||||
(launch / foreground 30s loop); schedule rules have no DeviceActivity
|
||||
monitoring yet — only limit rules do.
|
||||
- **Schedule-rule background transitions** are now backed by DeviceActivity:
|
||||
`RuleScheduler` registers a repeating window activity per schedule rule
|
||||
(`sched-<uuid>`, plus `sched2-<uuid>` for midnight-crossing windows) and the
|
||||
monitor extension recomputes + applies/clears the shield on interval
|
||||
start/end. The foreground 30s loop remains as the reconciliation safety net
|
||||
because interval callbacks are unreliable. On-device verification of the
|
||||
background transition is still pending (the simulator does not deliver
|
||||
DeviceActivity callbacks).
|
||||
- `FamilyActivityPicker` shows few apps on the simulator; fine on device.
|
||||
- `FamilyActivityPicker` **silently ignores selections** (binding never
|
||||
updates, rows still show checkmarks) unless real FamilyControls
|
||||
|
||||
Reference in New Issue
Block a user