Files
Nomarchy/agent/JOURNAL.md
Bernardo Magri 190e13350b
Some checks failed
Check / eval (push) Failing after 2m0s
docs(journal): tray menus verified fixed on the real nm-applet menu
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 08:20:38 +01:00

28 KiB
Raw Blame History

Journal — append-only iteration log

One entry per iteration, newest first. This is the loop's short-term memory: the next session reads the last 35 entries to orient. Keep an entry under ~15 lines; durable lessons go to MEMORY.md, not here. When this file grows past ~25 entries, rotate the tail to JOURNAL-ARCHIVE.md (history, never edited).

Template:

## YYYY-MM-DD — <task title> (<commit sha, or "no commit">)
- **Task:** which BACKLOG item (or QA sweep / bootstrap / escalation)
- **Did:** what changed, in 24 lines
- **Verified:** tier reached (V0/V1/V2) + the actual commands/checks run
- **Pending:** V3 queued? follow-ups filed? anything [stuck]?
- **Next suggestion:** what the following iteration should probably take

2026-07-12 — tray menus truly fixed: counter-rules must live in waybar.css (8eb672b, 72e53e2)

  • Task: Bernardo: icons still missing in the REAL nm-applet menu.
  • Did: e8658fe's gtk.css cure worked in a plain GTK app but not in Waybar: Waybar adds its provider at GTK_STYLE_PROVIDER_PRIORITY_USER too (src/client.cpp) and wins the tie in practice (GTK 3.24) — proven by repro at priority 900 matching the live menu exactly. Only rules in the SAME stylesheet out-specify its *, so every waybar.css now carries a menu block after the reset: arrow 16px, check/radio 14px, separator 1px, menu, menu * font (labels are matched directly by *, inheritance never applies). D-Bus GetLayout first proved nm-applet exports per-network icon-data.
  • Verified: V3 on the real menu — opened nm-applet's tray menu via wlrctl virtual-pointer clicks, grim captures: arrows, checkmarks, separators, Inter labels, Pica's icon, and every network's signal icon in the Available-networks submenu. Bar pills intact. NB: cursor-warp hover does not open GTK submenus (no motion events) — click the item.
  • Pending: nothing for this item.
  • Next suggestion: #89 slice 2 — the override-icon layer.

2026-07-12 — #90 correction: scoping regressed the bar; USER-priority cure (e8658fe)

  • Task: Bernardo reports ac7e6bd broke Boreal's bar + icons still missing.
  • Did: Two lessons. (1) window#waybar * carries id specificity, so the reset started beating the later class rules (pill radius/borders) that plain * correctly lost to — reverted all three stylesheets; arrows restored instead via stylix gtk.css (menu menuitem arrow { min-width/height:16px }) — USER priority (800) outranks waybar's APPLICATION (600) regardless of specificity, same mechanism as the existing check/radio rule. NB comments guard each * block. (2) The "missing icons" were also GTK3's gtk-menu-images default-off: set gtk.gtk3.extraConfig.gtk-menu-images = 1.
  • Verified: V3 — repro (no forced always-show-image): icon, check and arrow all render even with Boreal's reset injected screen-wide; bar screenshot shows pills restored. Flake check green.
  • Pending: Bernardo eyeballs the real nm-applet menu (icons + arrow).
  • Next suggestion: #89 slice 2 — the override-icon layer.

2026-07-12 — #76 closed: hibernate V3 PASSED on TuringMachine (this commit)

  • Task: BACKLOG #76 [human] closure — Bernardo reports the V3 check.
  • Did: Bernardo ran the real power-cycle on the T14s (LUKS + btrfs @swap swapfile): hibernate → power off → single LUKS unlock → session restored, "flawlessly". Deleted #76; HARDWARE-QUEUE resume entry pruned (outcome recorded here + ROADMAP ✓-entry updated); Decisions note marked shipped. The no-swap Hibernate notify check stays open in HARDWARE-QUEUE as the one leftover.
  • Verified: V3 (human, real hardware). Docs-only commit otherwise.
  • Pending: no-swap notify check (needs a swapless session or temporary swapoff -a).
  • Next suggestion: #89 slice 2 — the override-icon layer.

2026-07-12 — #90 tray submenu arrows: root cause was waybar CSS (this commit)

  • Task: BACKLOG #90 [stuck] (interactive, Bernardo driving on T14s).
  • Did: Diagnosis was wrong — Papirus-Dark resolves pan-end-symbolic fine via its breeze-dark inheritance (breeze ships inside the nixpkgs papirus output). Real cause: Waybar's stylesheet applies process-wide, and the * { min-height: 0; } block collapsed the arrow node in the SNI tray menus Waybar hosts. Scoped the * block to window#waybar in boreal + executive-slate waybar.css and waybar.nix generatedStyle (tooltip rules restate the font — tooltips are separate toplevels); removed the go-next-symbolic remap workaround from stylix.nix.
  • Verified: V3 — live GTK3 repro app popping a dbusmenu-shaped menu, screenshotted via grim: arrow vanishes with old CSS injected screen-wide, renders with fixed CSS; property bisect pinned min-height: 0 as the sole culprit. V1 flake check green.
  • Pending: post-switch check that the real nm-applet menu shows the arrow (needs a human click on the tray icon).
  • Next suggestion: #89 slice 2 — the override-icon layer.

2026-07-11 — interactive T14s session: migration follow-ups (50a5586…6967d89)

  • Task: Escalation — Bernardo driving, live on the migrated T14s (first full session on real Nomarchy hardware; 7 commits).
  • Did: autologin restored (migration missed the LUKS-machine line — fixed downstream + MIGRATION.md example); SUPER+0 → workspace 10; VPN tooltip names active VPNs (stuck-shield confusion was Tailscale); battery "Not charging" hold-band tooltip (+ 4 whole-swap themes); GTK submenu arrows (bundled SVG — Papirus lacks pan-end-symbolic and inherits uninstalled breeze); xdg.userDirs.setSessionVariables pinned (HM 26.05 flip); easyeffects gated on a live tray host (After= waybar.service was inert — waybar is supervisor-run, not a unit); #89 slice-1 SNI inventory recorded; #76 unblocked → [human].
  • Verified: V3 throughout — live binds via hyprctl binds, GTK menu screenshot (arrow + check render), SNI watcher registration, deployed configs inspected; V1 flake check green on every commit.
  • Pending: Bernardo: nomarchy-rebuild (autologin + new services), then the #76 hibernate power-cycle. #89 targets narrowed to EasyEffects (slice 2) + Signal (slice 3).
  • Next suggestion: #89 slice 2 — the override-icon layer.

2026-07-11 — hotfix: Left=Back bound over rofi default → every menu dead

  • Task: Escalation — V3 on the migrated T14s: all nomarchy-menu entry points (main, battery, power-profile, VPN) showed rofi's "Binding 'Left' is already bound" error dialog instead of a menu.
  • Did: rofi.nix — release kb-move-char-back to Control+b before binding -kb-custom-1 Left, in both rofi_menu copies (menu + vpn). rofi hard-fails on duplicate bindings, and reports it in a GUI dialog, not stderr — stub tests and bash -n can never catch this class. Filed PROPOSED: EasyEffects 8 blue tray icon; parallel finger/password.
  • Verified: V3 — real rofi on the T14s: old flags reproduce the error dialog (screenshot), fixed flags render the menu; after HM switch, nomarchy-menu renders end-to-end. V0 flake check green.
  • Pending: flatpak apps missing from drun = stale session env (relogin), not a code bug. EasyEffects icon + pam items in PROPOSED.
  • Next suggestion: V3 sweep of the remaining 05bab55 session items.

2026-07-11 — post-migration fix batch (05bab55; entry backfilled)

  • Task: Escalation — first real-hardware migration (TuringMachine → Nomarchy) surfaced a batch of annoyances; session crashed before journaling, entry written by the follow-up session.
  • Did: Force fprintAuth off unless fingerprint.pam; first-boot toast waits for swaync + retries; night-light handles masked units; VPN menu rofi_menu no-op fixed; ← = Back in list menus; GTK menu contrast; mic-mute LED udev rule + sync; EasyEffects after tray; MIGRATION.md notes.
  • Verified: V0 flake check; checks.first-boot; checks.hardware-toggles.
  • Pending: V3 on the migrated machine. Follow-up found the downstream ~/.nomarchy lock still pinned the previous commit — the user's rebuild excluded this batch (mic LED "regression" was just that). Also: HM programs.chromium.extensions from the old config wasn't carried over, so Chromium externally-uninstalled all extensions and their data (wallets included); recovered from the pre-nomarchy-home btrfs snapshot. MIGRATION.md browser note rewritten with the real mechanism.
  • Next suggestion: V3 sweep of the 05bab55 items after a locked rebuild.

2026-07-11 — #88 neon-glass polish / finish

  • Task: NEXT #88 — finish neon-glass (VISION § D), not quarantine.
  • Did: Rewrote themes/neon-glass/rofi.rasi (was invalid var() CSS; now Boreal-style glass with @colors, cyan edge, soft selection). btop accent titles/selection; JSON ui rounding 14 + slight glass opacity; preview.png from theme-shot desktop. No waybar.css.
  • Verified: V2 — contrast 24×7 pass; theme-wholeswap green; theme-shot neon-glass desktop+menu viewed (cyan bar + glass menu); boreal theme-shot regression green (menu/bar intact).
  • Pending:
  • Next suggestion: post-install hardware hints PROPOSED, or human HARDWARE-QUEUE.

2026-07-11 — Promote neon-glass → NEXT #88 (Bernardo)

  • Task: human triage: promote neon-glass PROPOSED.
  • Did: NEXT #88 neon-glass polish/finish (VISION § D); path = finish (not quarantine). Notes: no broken waybar.css reintro without wholeswap parity; V2 theme-shot required. PROPOSED pitch removed; VISION pointers updated. No implementation this commit.
  • Verified: V0 (backlog/docs only).
  • Pending:
  • Next suggestion: implement #88 (theme-shot V2).

2026-07-11 — VISION hygiene + PROPOSED (queue empty)

  • Task: QA/docs loop — NEXT still only #76 [blocked:hw]; no product item to implement without inventing work.
  • Did: Marked Theme A/B/C shipped rows in docs/VISION.md (Firmware #43, Fingerprint #55, doctor stack, rebuild errors #56, Boreal default, hibernate confidence #77). Rewrote “Suggested agent slices” to open work only. PROPOSED: post-install hardware hints; neon-glass finish/quarantine [human].
  • Verified: V0 — docs/backlog only (no module change). Prior iterations V2 suite still stands; no regression claimed here.
  • Pending: human triage of PROPOSED; HARDWARE-QUEUE V3.
  • Next suggestion: promote post-install hints → NEXT, or human HARDWARE-QUEUE / neon-glass call.

2026-07-11 — QA sweep (queue empty but #76)

  • Task: QA sweep — NEXT only has #76 [blocked:hw]; no other actionable items.
  • Did: option-docs (88 opts) + template-sot green; HM generation has What changed? / doctor float / first-boot unit; rotated JOURNAL.md 41→18 entries (tail → JOURNAL-ARCHIVE). No product code change.
  • Verified: V2nix flake check --no-build; rebuilt green: doctor, first-boot, what-changed, clamshell-logind, dock-audio, windowrule-syntax, battery-notify, zram-swap, nightlight-geo.
  • Pending: #76 V3 hibernate on Nomarchy hardware; #86/#87 V3 dock QA.
  • Next suggestion: HARDWARE-QUEUE pass by human, or promote LATER wallpapers split / triage PROPOSED.

2026-07-11 — #87 dock audio sink priority

  • Task: NEXT #87 — default audio follows dock plug/unplug.
  • Did: WirePlumber 90-nomarchy-dock-audio (HDMI/DP session prio 1100, USB 1050) via modules/nixos/dock-audio-rules.nix + default.nix pipewire. checks.dock-audio pure rule asserts + conf-file VM. V3 hotplug steps in HARDWARE-QUEUE. Closed #87.
  • Verified: V2nix flake check --no-build; checks.dock-audio green (pure rule asserts + conf installed under wireplumber.conf.d).
  • Pending: V3 real HDMI/USB-dock hotplug (HARDWARE-QUEUE).
  • Next suggestion: QA sweep or LATER wallpapers split if promoted.

2026-07-11 — #86 clamshell HandleLidSwitchDocked

  • Task: NEXT #86 — lid closed + external monitor must not suspend.
  • Did: Explicit HandleLidSwitchDocked=ignore in modules/nixos/power.nix (logind settings.Login). Undocked lid behaviour unchanged. idle.nix comment corrected. checks.clamshell-logind asserts conf + active logind. V3 steps in HARDWARE-QUEUE. Closed #86.
  • Verified: V2nix flake check --no-build; checks.clamshell-logind green (HandleLidSwitchDocked=ignore + logind active).
  • Pending: V3 real lid+external on laptop (HARDWARE-QUEUE).
  • Next suggestion: #87 dock audio sink follow.

2026-07-11 — #85 hardware hall of fame + split #84

  • Task: NEXT #85 docs hall of fame; #84 was [big] → split.
  • Did: HARDWARE.md §9 install-tested table (T14s Gen 4 AMD, Latitude 5410/5310) + DMI PR invite; renumbered following sections. #84 → #86 clamshell + #87 dock audio. VISION/ROADMAP; closed #85.
  • Verified: V0 (docs only).
  • Pending:
  • Next suggestion: #86 clamshell or #87 dock audio (both product).

2026-07-11 — #83 doctor first-boot pre-activate flag

  • Task: NEXT #83 — doctor points at failed installer HM pre-activate.
  • Did: doctor row: if /var/log/nomarchy-hm-preactivate.log is present and no Home Manager generation exists → ✖ + home-manager switch --flake ~/.nomarchy -b bak. Skip/ok otherwise. Extended checks.doctor (fail arm + recovered gen). Closed #83.
  • Verified: V2 — checks.doctor green (fail arm + recovered gen); local smoke with NOMARCHY_HM_PREACTIVATE_LOG / empty HOME.
  • Pending:
  • Next suggestion: #85 docs hall of fame (cheap) or split #84 dock.

2026-07-11 — #82 generation readability

  • Task: NEXT #82 — plain-language “what changed last rebuild”.
  • Did: pkgs/nomarchy-what-changed (nvd → “N added, M removed, K updated”); wired into lifecycle post-nomarchy-rebuild / nomarchy-home (full nvd + notify toast); System What changed? (toast + floating full report). checks.what-changed with NOMARCHY_NVD fixture. Closed #82.
  • Verified: V2 — checks.what-changed green; local smoke on real HM gens (“Desktop: 1 added, 1 removed”) + fixture counts.
  • Pending:
  • Next suggestion: #83 doctor pre-activate fail flag or #85 docs.

2026-07-11 — #81 first-boot welcome toast

  • Task: NEXT #81 — dismissible “you're set” card (VISION § B).
  • Did: pkgs/nomarchy-first-boot + user oneshot (modules/home/first-boot.nix): notify once with SUPER+M/T/? + Network
    • Doctor pointers; marker settings.firstBootShown via theme-sync --no-switch (in-checkout state). Skip live hostname. Option nomarchy.firstBootWelcome.enable (default on). checks.first-boot. ROADMAP/VISION/README; closed #81.
  • Verified: V2nix flake check --no-build; checks.first-boot green (toast + marker + silent re-run + live skip); local shim smoke; downstream-template-home carries the user unit.
  • Pending: V3 — real swaync rendering on first installed login (toast body is pure text; not queued unless it misbehaves).
  • Next suggestion: #82 generation readability or #85 docs hall of fame.

2026-07-11 — #80 doctor battery health readout

  • Task: NEXT #80 — battery health in nomarchy-doctor (VISION § C).
  • Did: Doctor row: cycle_count + retained capacity (charge_full/design or energy_*) as % of design; system batteries only; soft warn <70% design; skip when attrs absent. NOMARCHY_POWER_SUPPLY_ROOT for the VM fixture. Extended checks.doctor (fake BAT0 + Device-scope MOUSE0 ignore). HARDWARE §10, ROADMAP ✓, VISION ✓; closed #80.
  • Verified: V2nix flake check --no-build; checks.doctor green; local smoke on real BAT0 (342 cycles, 81% via energy_*) + fixture.
  • Pending: Power-menu surface left optional/out of scope (doctor is the product surface for report-only health).
  • Next suggestion: #81 first-boot welcome card (highest product ROI) or #85 docs-only hall of fame.

2026-07-11 — Triage: VISION-gap PROPOSED → NEXT #80#85 (Bernardo)

  • Task: Bernardo promoted five of the six fresh VISION-gap pitches (all but the wallpapers split, which stays LATER).
  • Did: NEXT gains #80 battery health readout, #81 first-boot welcome card, #82 generation readability, #83 doctor pre-activate fail flag, #84 dock life polish [big], #85 hardware hall of fame. PROPOSED placeholder left. No implementation started (explicit instruction).
  • Verified: V0 (backlog only).
  • Pending:
  • Next suggestion: #80 (smallest) or #81 (highest product ROI); #84 must be split first.

2026-07-11 — Quick wins: exit-node locations + geo tooltip

  • Task: BACKLOG LATER "VPN exit-node richer display" + a geo-mode tooltip nit from the previous iteration (human asked for quick wins).
  • Did: Tailscale Exit node picker rows now "hostname — Country City", sliced by the header's fixed-width column offsets (COUNTRY/CITY are multi-word; never field-split), locationless nodes stay bare, pick strips back to hostname at the first space. Nightlight Waybar tooltip says "follows your location" in geo mode. Queue's VPN entry updated.
  • Verified: V1 — awk proven against a fabricated 3-case fixture (Mullvad 1-word + multi-word city + bare node); flake check exit 0; downstream-template-home builds (writeShellScriptBin syntax-gates both scripts). Real tailscale output is V3 (existing VPN queue entry).
  • Pending: V3 VPN menu live paths (extended, not new).
  • Next suggestion: wallpapers artifact split (LATER, decided).

2026-07-11 — Night-light geo mode (lat/long → wlsunset)

  • Task: BACKLOG LATER "Night-light geo mode" (human-picked).
  • Did: nomarchy.nightlight.latitude/.longitude (both set = geo mode): services.wlsunset (location-computed sunrise/sunset, .temperature → night temp) replaces hyprsunset; the toggle script's unit= and the live-state ExecCondition follow via one unit let-binding. Template example lines, README row, ROADMAP ✓. New checks.nightlight-geo: pure-eval asserts on the rendered units (coords + temp in ExecStart, ExecCondition present, hyprsunset off). Declarative-only (no menu writer — coords are machine config like keyboard layout).
  • Verified: V1 — nix flake check --no-build exit 0 (evals the new asserts + option-docs); built downstream-template-home (default hyprsunset path unregressed) + the check drv. Caught en route: HM renders ExecStart as a list (toString needed in eval asserts).
  • Pending: V3 queued (HARDWARE-QUEUE § Any machine): visible warm shift at location night + toggle/persistence on the swapped unit.
  • Next suggestion: wallpapers artifact split (LATER, decided).

2026-07-11 — Sync-sweep rule + grooming + zram user docs (human-requested)

  • Task: Bernardo: groom stale items and codify the check so they don't recur; close the zram user-doc gap.
  • Did: LOOP.md §5 gains step 4 Sync sweep (grep item/feature across agent/+docs/ on ship; prune recorded [x] queue entries) + an AGENTS.md rule line. Applied it: BACKLOG PROPOSED pruned (auto-theme pitch was stale — shipped as #79; shipped/promoted placeholders removed; v1.0 pointer rewritten; FUTURE promoted-stub dropped). HARDWARE-QUEUE pruned 29 checked [x] entries (363→~250 lines), dangling refs reworded, prune rule in header. README §3 now documents the zram default + hibernation out-of-the-box + MIGRATION pointer.
  • Verified: V0 (docs/meta only) — grep sweep for dangling refs clean.
  • Pending: night-light geo mode next (same session).
  • Next suggestion: wallpapers artifact split (LATER, decided).

2026-07-11 — Vendor-neutral agent docs restructure (human-requested)

  • Task: Bernardo: de-vendor the agent instructions (multi-model repo), clean stale files, better docs/agent/.claude structure.
  • Did: New root AGENTS.md entry (CLAUDE.md → symlink). Skill bodies moved to agent/: VERIFICATION.md (enforcement, ex-nomarchy skill), DELEGATION.md (tiers light/standard/frontier + scout/runner contracts + fan-out; consolidates CLAUDE.md table + LOOP §economy + skill §6.5), THEME-DESIGN.md (ex-theme skill, now with frontmatterd shim). .claude/ is a thin adapter (shims route into agent/). Maps updated (agent/, docs/, README tree). Stale: .gitignore old_distro entry dropped; local result*/pycache removed. JOURNAL rotated (29 kept, 120 → JOURNAL-ARCHIVE.md).
  • Verified: V0 — nix flake check --no-build exit 0 with the symlink tracked; vendor-name grep clean outside DELEGATION's mapping table.
  • Pending: nothing; other harnesses add their own adapter row when used.
  • Next suggestion: #76/#79 remain [blocked:hw]; otherwise groom PROPOSED.

2026-07-11 — #76 checks.hibernate-swapfile (VM-verify the swapfile+offset)

  • Task: Bernardo — push #76's swapfile-resume residual into a VM (like the auto-theme sunset trick).
  • Did: Tried a full runtime-swapfile hibernate→resume test; it hit a bounded, definitive CanHibernate=no — systemd won't hibernate to a swap that isn't declared in the boot config, and a runtime-computed resume_offset can't reach the boot cmdline (the genuine chicken-and-egg). First cut also had an unbounded wait_for_shutdown that hung → killed it, bounded the wait in a thread (180s) + a CanHibernate pre-check, which is what surfaced the clean verdict. Pivoted checks.hibernate-swapfile to what a VM can prove deterministically and the partition test can't: the installer swapfile build + offset — NOCOW mkswapfile, file-type swapon, valid map-swapfile -r offset accepted by /sys/power/resume_offset, zram above it. (Device fix: /dev/vdb once useNixStoreImage was dropped.)
  • Verified: V2 PASS (fresh build, exit 0). BACKLOG/ROADMAP updated; #76 residual narrowed to the literal encrypted power-cycle (dev box runs it).
  • Lesson: the sunset-trick spirit applies but not always the full cycle — when systemd/kernel gates the behaviour (CanHibernate), verify the construction deterministically and leave only the physical cycle to HW. Always bound wait_for_shutdown (no timeout param → thread + join).
  • Next suggestion: #76/#79 both [blocked:hw]; QA / PROPOSED otherwise.

2026-07-11 — Code-review fixes (parallel review of the session batch)

  • Task: Bernardo asked for parallel work; spawned a fresh-eyes opus review of 2055842..HEAD (static). It found the batch sound — 2 real LOW edge bugs, 1 false positive, 1 cosmetic.
  • Did: (1) cmd_auto — inverted sunrise/sunset (sunrise > sunset) went perpetually day; replaced the not between shortcut with a real wrap-around mins >= sunrise or mins < sunset, so a cross-midnight day window switches both ways. (2) rofi.nix autotheme HH:MM guard tightened [0-2][0-9][01][0-9]|2[0-3] so 2429 are rejected. Dismissed the breeze finding (papirus DOES ship breeze/breeze-dark — verified) and the cosmetic doctor-RAM one.
  • Verified: py_compile; boundary truth-table (normal + wrap-around); HH:MM case table (23:00/19:59/20:00 accept, 24/25/30:00 reject); auto --which normal-case unchanged; menu bash -n; flake check green. Normal case unchanged so checks.auto-theme still holds.
  • Pending: hibernate-swapfile VM test still running (uncommitted flake.nix).
  • Next suggestion: land hibernate-swapfile once its VM test returns.

2026-07-10 — #79 V2: checks.auto-theme (simulated sunset) — was mis-framed V3

  • Task: Bernardo challenged the "V3 real-session" framing — a simulated sunset IS VM-testable. He's right; I'd conflated "needs a real desktop" with "needs the generic home-manager switch."
  • Did: Added checks.auto-theme runNixOSTest: installs nomarchy-theme-sync, points NOMARCHY_DEFAULT_THEMES at presets, stubs the switch via NOMARCHY_REBUILD (a marker), configures the pair+schedule, then walks the VM clock 19:55→20:05→20:06→next-day 07:30 asserting slug goes summer-day → night (1 rebuild) → night (idempotent, still 1) → day (2). The self-gating I relied on: presets via env, wallpaper/notify no-op headless, run_switch honors NOMARCHY_REBUILD + waybar nudge is check=False.
  • Verified: V2 PASSnix build .#checks…auto-theme fresh, exit 0. Dropped #79's [blocked:hw]; it's done (V2). Updated ROADMAP.
  • Lesson: don't default "timer/session feature" to V3 — stub only the generic step (the real HM switch, covered elsewhere) and simulate the rest (clock) headlessly. Only the literal timer-fires-on-OnCalendar is on-HW, and its schedule is systemd-analyze-validated.
  • Next suggestion: NEXT head #76 [blocked:hw]; else QA / PROPOSED.

2026-07-10 — #79 slice 3: Look & Feel Auto theme menu (#79 complete)

  • Task: BACKLOG #79 slice 3 — the menu; completes the feature.
  • Did: rofi.nix — "Auto theme (on/off)" row in Look & Feel + an autotheme) submenu: toggle, pick day/night (from nomarchy-theme-sync list), set sunrise/sunset (HH:MM input, validated). Enable writes the flag + defaults the summer pair --no-switch, then exec auto --force — one rebuild installs the timer AND applies the right theme. Disable is instant --no-switch (auto self-gates; the lingering timer no-ops). Day/night/times are live --no-switch.
  • Verified: V1 — HM generation builds (writeShellScriptBin bash -n on nomarchy-menu passes) + bash -n on the built menu. Logic test (stubbed rofi/theme-sync/notify): selecting "Auto theme (off)" runs exactly set day summer-day, set night summer-night, set enable true (all --no-switch), then auto --force — the intended one-rebuild path. Disable path is static-clear (set false --no-switch, no auto); a stateful-stub dynamic test would loop (stub doesn't reflect the flip). V0 flake check green. #79 collapsed to [blocked:hw] (all 3 slices done; only live-session switch remains, needs a Nomarchy machine).
  • Pending: V3 real-session (timer switches day↔night across sunset).
  • Next suggestion: NEXT head #76/#79 both [blocked:hw]; QA/PROPOSED.

2026-07-10 — #79 slice 2: auto-theme systemd timer

  • Task: BACKLOG #79 slice 2 — the timer/hook.
  • Did: modules/home/autotheme.nix (imported in home default.nix): systemd.user.{service,timer}.nomarchy-auto-theme, install gated on config.nomarchy.settings.autoTheme.enable or false (state-driven, like updates.nix gates on its enable). Service runs nomarchy-theme-sync auto with a PATH for home-manager; timer OnStartupSec=1min + OnCalendar=*:0/15 + Persistent. Chose periodic over exact sunrise/sunset timers — robust to suspend/DST, and auto is idempotent so ticks are cheap (rebuild only at the transition).
  • Verified: V1 — real-config eval (state temp-enabled, restored): settings.autoTheme.enable→true, timer OnCalendar=*:0/15, service ExecStart=… nomarchy-theme-sync auto; disabled→no units (isolation eval condition=false). systemd-analyze calendar '*:0/15' valid. V0 flake check green. (Gotcha: a new .nix file is invisible to the flake until git add — flake eval only sees tracked files.)
  • Pending: live timer→home-manager switch on a real Nomarchy session (needs a Nomarchy machine, like #76). Slice 3 (menu) next.
  • Next suggestion: #79 slice 3 — Look & Feel Auto theme menu.

2026-07-10 — #79 slice 1: auto time-of-day theme CLI primitive

  • Task: Split BACKLOG #79 (VISION § D, [big]) into 3 slices (CLI / timer / menu); took slice 1.
  • Did: nomarchy-theme-sync auto — reads settings.autoTheme.{enable,day,night,sunrise,sunset}, computes day/night by the local clock, and applies the matching preset only if different (idempotent → the slice-2 timer won't rebuild needlessly). --which prints the decision without switching; --force/--no-switch too. Factored cmd_apply's core into apply_named so auto reuses the exact same one engine (GOALS: no second pipeline).
  • Verified: V1 package builds; functional tests on the built bin against scratch state: wide-day→day slug, 00:0000:01 window→night, disabled→no-op, missing day/night→die, auto --no-switch writes state, re-run→"already on" no-op, plain apply still writes (refactor intact). V0 py_compile + flake check + checks.theme-sync-validate green.
  • Pending: slices 2 (systemd sunrise/sunset timers + login apply, V2) and 3 (Look & Feel menu) remain under #79.
  • Next suggestion: #79 slice 2 — the timer/hook (V2 runNixOSTest).