feat(autotheme): fire at the configured sunrise/sunset, not a 15-min poll
All checks were successful
Check / eval (push) Successful in 4m14s
All checks were successful
Check / eval (push) Successful in 4m14s
The timer's OnCalendar now bakes the configured times (falling back like _hhmm_to_min on a hand-edited state), so the switch lands at the configured minute instead of up to 15 minutes late. The original poll's robustness case is covered without it: Persistent catches transitions missed while powered off, systemd fires elapsed calendar timers on resume, and OnStartupSec settles the theme after login. Baked times mean a time edit must rebuild: the menu's Sunrise/Sunset writes now run `auto --force` when enabled (one rebuild re-bakes the timer and lands on the right theme, same as the enable flow). Day and night slugs stay live reads — but with no poll to catch them up, editing the slot currently on screen applies immediately via a plain `auto`. New eval check `auto-theme-timer` asserts the bake state-bridges-style: configured times reach OnCalendar, garbage falls back to 07:00/20:00, disabled installs no unit. Docs + hardware-queue entry updated to the new semantics. V2: checks.auto-theme (KVM VM, passed) covers the auto engine the timer ticks; checks.auto-theme-timer (eval, passed) covers the unit; OnCalendar strings systemd-analyze-validated; the rebuilt menu script passes bash -n with the new branches in place. V3 pending: live timer firing at the exact configured minute on hardware (existing "Auto-theme pair flip" queue entry, refreshed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
42
flake.nix
42
flake.nix
@@ -342,6 +342,48 @@
|
||||
pkgs.runCommand "nomarchy-state-bridges" { }
|
||||
"touch $out"; # all ${toString (builtins.length cases)} assertions held at eval
|
||||
|
||||
# The baked auto-theme timer (#79 revision): sunrise/sunset land in
|
||||
# the unit's OnCalendar at rebuild, and nothing in a build fails
|
||||
# when that bake goes stale or produces a calendar systemd rejects
|
||||
# — so assert it at eval, state-bridges style.
|
||||
auto-theme-timer =
|
||||
let
|
||||
homeWith = stateFile:
|
||||
(downstream.homeConfigurations.me.extendModules {
|
||||
modules = [{
|
||||
nomarchy.stateFile = nixpkgs.lib.mkForce stateFile;
|
||||
}];
|
||||
}).config;
|
||||
atState = name: at: stateFileOf name { settings.autoTheme = at; };
|
||||
on = homeWith (atState "state-autotheme-on.json" {
|
||||
enable = true; day = "summer-day"; night = "summer-night";
|
||||
sunrise = "06:30"; sunset = "21:45";
|
||||
});
|
||||
garbage = homeWith (atState "state-autotheme-garbage.json" {
|
||||
enable = true; day = "summer-day"; night = "summer-night";
|
||||
sunrise = "sometime"; sunset = "25:99";
|
||||
});
|
||||
off = homeWith absentState; # template carries no autoTheme key
|
||||
cal = c: c.systemd.user.timers.nomarchy-auto-theme.Timer.OnCalendar;
|
||||
cases = [
|
||||
{ n = "configured times are baked into OnCalendar";
|
||||
ok = cal on == [ "*-*-* 06:30:00" "*-*-* 21:45:00" ]; }
|
||||
{ n = "garbage times fall back to 07:00/20:00";
|
||||
ok = cal garbage == [ "*-*-* 07:00:00" "*-*-* 20:00:00" ]; }
|
||||
{ n = "disabled → no timer unit installed";
|
||||
ok = !(off.systemd.user.timers ? nomarchy-auto-theme); }
|
||||
];
|
||||
failed = builtins.filter (c: !c.ok) cases;
|
||||
in
|
||||
if failed != [ ] then
|
||||
throw ''
|
||||
Auto-theme timer bake broken — settings.autoTheme no longer
|
||||
reaches the unit as expected:
|
||||
${nixpkgs.lib.concatMapStringsSep "\n" (c: " ✗ ${c.n}") failed}''
|
||||
else
|
||||
pkgs.runCommand "nomarchy-auto-theme-timer" { }
|
||||
"touch $out"; # all ${toString (builtins.length cases)} assertions held at eval
|
||||
|
||||
# The bridge, end to end on a booted machine: checks.state-bridges
|
||||
# proves the option flips at eval, this proves a state key alone
|
||||
# reaches a RUNNING service. The node sets no
|
||||
|
||||
Reference in New Issue
Block a user