Files
Nomarchy/agent/JOURNAL.md
Bernardo Magri 860c70466f
All checks were successful
Check / eval (push) Successful in 3m46s
feat(menu): #79 slice 3 — Look & Feel › Auto theme (completes #79)
Adds an "Auto theme (on/off)" row to Look & Feel and an `autotheme`
submenu: toggle the feature, pick the day/night themes (from
`nomarchy-theme-sync list`), and set the sunrise/sunset times (HH:MM,
validated). This is the menu surface over settings.autoTheme, completing
the auto time-of-day theme feature (slices: CLI / timer / menu).

Enabling writes the flag and defaults the summer-day/summer-night pair
--no-switch, then runs `auto --force`, so a single rebuild both installs
the timer and applies the correct theme for now. Disabling is instant
(--no-switch): the flag flips and `auto` self-gates, so the lingering
timer no-ops until the next rebuild. Day/night/time writes are live
--no-switch (read by `auto` at tick time).

Verification: V1 — HM generation builds (bash -n on nomarchy-menu at
build) + bash -n on the built menu. Logic test with stubbed
rofi/theme-sync/notify: selecting the toggle from off runs exactly `set
day/night/enable ... --no-switch` then `auto --force` — the intended
one-rebuild path. V0 flake check green. All three #79 slices shipped;
the live timer switch across sunset is a real-session (V3) check on a
Nomarchy machine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 21:53:37 +01:00

144 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.

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-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).

2026-07-10 — #78 Omarchy migrant doc (docs/OMARCHY.md)

  • Task: BACKLOG #78 (promoted from PROPOSED) — Omarchy→Nomarchy one-pager (VISION § F).
  • Did: New docs/OMARCHY.md: leads with the config-model shift (imperative dotfiles → declarative flake + menu, rollback via generations), then install (ISO/nomarchy-install or MIGRATION.md), a familiar-bindings table, theming (SUPER+T/nomarchy-theme-sync), packages (home.packages / nix shell, no AUR), update+rollback (nomarchy-pull/-rebuild/-home, boot-menu generations, nomarchy-doctor). Added to docs/README.md map + VISION § F ✓.
  • Verified: V0 (docs). Grounded Nomarchy side in code: pulled real binds from keybinds.nix; confirmed all 7 cited commands, the nsearch alias, and the named slugs (gruvbox/rose-pine/nord) exist. Kept Omarchy-side claims to known facts (Arch, dotfiles, pacman/AUR).
  • Pending: none.
  • Next suggestion: NEXT head #76 [blocked:hw]; last open PROPOSED is auto time-of-day theme pair (§D, [big] — needs splitting).

2026-07-10 — #77 doctor hibernate/sleep section (V2 PASS)

  • Task: BACKLOG #77 (promoted from PROPOSED by Bernardo) — read-only hibernate section in nomarchy-doctor (VISION § C, #76 follow-on).
  • Did: Added a hibernate/sleep row group to nomarchy-doctor.sh: resume device on cmdline (+ resume_offset for a swapfile), disk swap ≥ RAM, zram active, previous-boot suspend/hibernate error. Self-gates (skip on swap=0); only ok/warn/skip → never fails the sheet. Added hibernate to the checks.doctor probe list.
  • Verified: V2 PASSchecks.doctor VM test green (fresh build, exit 0; asserts the hibernate row renders + healthy run still 0). V1 — ran on this box's real LUKS+@swap layout: all three ok rows render (resume set, swap 34G ≥ RAM, zram 16G) and the sheet reaches its verdict. V0 bash -n + flake check.
  • Gotcha (fixed + MEMORY): the doctor runs set -euo pipefail; my first cut aborted before the verdict because a no-match grep inside $(…) and a cond && action both trip set -e. Fixed with || true / || echo 0 and an if. First VM run caught it (exit 1, no verdict) — the test earned its keep.
  • Pending: none — fully agent-verifiable (read-only checks, no V3).
  • Next suggestion: NEXT head is #76 [blocked:hw]; remaining PROPOSED (Omarchy doc §F, auto time-of-day theme §D) await triage.

2026-07-10 — QA sweep (clean) + VISION-gap pass → 3 PROPOSED

  • Task: Bernardo — QA/drift sweep, then a VISION-gap pass with proposals.
  • Did (sweep): Fanned out two subagents (Bernardo OK'd spawning for efficiency): nomarchy-runner ran the deterministic checks + bash -n/ py_compile (all PASS; the 4 "needs-args" scripts pass via their flake derivations); nomarchy-scout hunted fuzzy drift (dead code, stale refs, TODOs, changed-area contradictions, count/version) — all clean. Spot-checked scout's count claim myself: 24 theme JSONs / 24 previews / README "24 presets" — consistent. Eval sweep green. No fixes needed.
  • Did (VISION): Verified candidate gaps against the tree before proposing (killed two false gaps — nomarchy-rebuild/home already tail logs
    • point at doctor on failure = §A shipped; nvd diff = §B covered; System Firmware menu already exists). Filed 3 PROPOSED (verified open): doctor hibernate/sleep section (§C, top Day-2 pick, #76 follow-on), Omarchy migrant one-pager (§F), auto time-of-day theme pair (§D, [big]).
  • Verified: V0 (agent-notes/docs only). Sweep evidence above.
  • Pending: none. Proposals await Bernardo's triage into a tier.
  • Next suggestion: if a PROPOSED is promoted, the doctor hibernate section is the cleanest next build; else NEXT #76 stays [blocked:hw].

2026-07-10 — Icon overrides: user-facing docs (OVERRIDES.md)

  • Task: Bernardo asked whether the session's features need user docs.
  • Did: Hibernation already covered (README swapfile line, MIGRATION.md runbook, discoverable Power-menu row) — no gap. Icons had one: the only doc was the template comment. Added an "Icon pack" subsection to docs/OVERRIDES.md § Appearance — nomarchy-theme-sync set icons "<name>", the known-packs table, the ~1 GiB/opt-in rationale, and that the choice is sticky across apply (presets carry no icon field; verified deep_merge).
  • Verified: command path confirmed (cmd_set writes any dotted key; icons is a schema key). Built all 4 packs and listed real theme dirs to fix the examples — caught Qogir using capital Qogir-Dark/Light (lowercase would silently fall back to hicolor). Docs-only (V0).
  • Pending: none.
  • Next suggestion: NEXT #76 [blocked:hw]; LATER/QA-sweep next.

2026-07-10 — Icon themes: opt-in cross-pack overrides (no default bloat)

  • Task: LATER "per-theme icon overrides / more icon packs". Recon found papirus is already ~1 GiB and ships only Papirus/Dark/Light (no free variety); real variety needs extra packs at ~hundreds of MB each. Bernardo chose the opt-in, no-default-bloat shape (over shipping packs).
  • Did: theme.nix resolves nomarchy.theme.iconThemePackage from a small iconPacks registry (papirus·tela·qogir·reversal·numix, by name prefix). Default themes name Papirus-* → resolves to the plain papirus derivation (no symlinkJoin, identical closure); only a theme naming another pack's set symlinkJoins that one pack in. stylix.nix uses it (mkDefault). Opt-in note in templates/downstream/home.nix; ROADMAP § Icon themes updated (incl. the deliberate no-default-packs decision).
  • Verified: V1 — HM activationPackage builds (exit 0). Eval proofs: default iconThemePackage = plain papirus-icon-theme-* (zero delta); with icons="Tela-dark"nomarchy-icon-themes symlinkJoin (papirus+tela) and name flows, without building tela. All 5 pack attrs exist in the pinned nixpkgs. template-sot + option-docs + flake check green.
  • Pending: none. No default visual change (identical papirus), so no screenshot needed; the opt-in render is the downstream user's to see.
  • Next suggestion: NEXT still #76 [blocked:hw]; LATER/QA-sweep next.

2026-07-10 — #76 slice 3: hibernate VM test (V2 PASS) → #76 agent-complete

  • Task: BACKLOG #76 slice 3 — the mandatory V2 hibernate test + V3 queue.
  • Did: Added checks.hibernate (flake.nix), modeled on nixpkgs' hibernate.nix but wired to Nomarchy's #76 risk: imports oom.nix (zram default-on), disk swap at lower priority + explicit boot.resumeDevice, systemd-initrd. Test drives hibernate→power-off→resume→crash: ramfs marker survives resume, a crash-boot loses it (real resume, not a survivor), and asserts zram@100 + disk-swap<100 so the image lands on disk not volatile zram. Queued the V3 laptop steps (real LUKS+@swap+offset resume + no-swap notify) in HARDWARE-QUEUE. Collapsed #76 to a [blocked:hw] stub; design record → ROADMAP § "Hibernation + zram by default".
  • Verified: V2 PASSnix build .#checks.x86_64-linux.hibernate built the driver fresh and exited 0 (all assertions held). nix flake check --no-build green.
  • Pending: only V3 (dev box / laptop) — #76's last check; close on PASS.
  • Next suggestion: #76 is now blocked:hw; NEXT head falls to LATER/ PROPOSED triage or a QA sweep — pick per LOOP.md orientation next session.

2026-07-10 — #76 slice 2: Hibernate notify-on-failure

  • Task: BACKLOG #76 remaining slice 2 — per the settled "keep row, notify on failure" call.
  • Did: modules/home/rofi.nix power menu Hibernate arm now runs systemctl hibernate 2>/dev/null || notify-send "Hibernate" "…see docs/MIGRATION.md". On success the call blocks until resume, so the notify only fires on a genuine failure (e.g. swap=0 no-swap machine). Row stays unconditional (no hiding).
  • Verified: V1nix build …homeConfigurations.nomarchy.activationPackage green (rebuilds nomarchy-menu.drv; writeShellScriptBin runs bash -n at build). Control-flow proof on the arm extracted from the built script: failing systemctl → notify fires; succeeding → no notify. nix flake check --no-build green.
  • Pending: slice 3 = the V2 hibernate→resume VM test + V3 laptop (Hibernate→power off→resume on the LUKS+@swap machine; plus confirm the no-swap notify surfaces in a real session). Both remain open on #76.
  • Next suggestion: slice 3 — add a checks.* hibernate VM test (as far as QEMU allows) and queue the V3 laptop steps in HARDWARE-QUEUE.

2026-07-10 — #76 slice 1: MIGRATION.md hibernation runbook

  • Task: BACKLOG #76 remaining slice 1 — docs runbook for enabling hibernation on an existing machine (per the settled "docs not tool" call).
  • Did: Added § "Enabling hibernation on an existing machine (no reinstall)" to docs/MIGRATION.md: create @swap subvol (subvolid=5) + mkswapfile (NOCOW), read map-swapfile -r offset, wire fileSystems."/swap" + swapDevices + resumeDevice + resume_offset into system.nix. Flagged the mount as required on the hand-edit path (installer gets it from disko-gen hardware-config). Notes zram-priority reservation, no-LUKS variant, swap=0 opt-out. Worked example = this dev machine.
  • Verified: V0 — read-only commands run live against this machine's real LUKS(cryptroot)+btrfs(@)+/swap/swapfile layout (RAM 31G, fsuuid, findmnt SOURCE, mkswapfile flags, zram@100 vs swapfile@-1 confirms the design intent). nix flake check --no-build green.
  • Pending: slice 2 — Hibernate row notify-on-failure (V1/V2); then the V2 hibernate VM test + V3 laptop.
  • Next suggestion: slice 2 (menu notify-on-failure).

2026-07-10 — #76 hibernation design calls (no commit yet → this bookkeeping)

  • Task: BACKLOG #76 design slice — Bernardo made the open calls.
  • Did: Recon showed the hibernation half is already built for new installs (installer defaults swap=RAM hibernation-ready @swap swapfile; patch-template.py writes swapDevices/resumeDevice/resume_offset; Power menu Hibernate row + LUKS/hyprlock handling exist). Settled 3 calls: (1) swap sizing = exactly RAM (no change); (2) migration = docs runbook in MIGRATION.md, not a tool; (3) no-swap Hibernate = keep row, notify on failure. Folded into BACKLOG #76 (design ✓, re-sliced remaining: MIGRATION.md runbook + notify-on-failure menu) and Decisions.
  • Verified: V0nix flake check --no-build green (docs-only).
  • Pending: two remaining slices below; V2 hibernate VM test + V3 laptop.
  • Next suggestion: slice 1 — docs/MIGRATION.md hibernation-enable runbook (V0), then slice 2 — Hibernate notify-on-failure (V1/V2).

2026-07-10 — #76 zram slice: compressed-RAM swap default

  • Task: BACKLOG #76 ([big]) — split; took the low-risk zram-default slice.
  • Did: zramSwap on by default in modules/nixos/oom.nix (zstd, 50% RAM, priority 100) as the memory-pressure layer before earlyoom, following the earlyoom mkDefault precedent (no toggle). High priority keeps day-to-day paging in zram so a disk swapfile stays reserved for #76's hibernate image. Added checks.zram-swap runNixOSTest (imports oom.nix). Split #76 in BACKLOG → remainder is the hibernation half (swapfile/resume/installer).
  • Verified: V2nix build .#checks…zram-swap PASS: /dev/zram0 active in /proc/swaps, [zstd] comp_algorithm, priority 100. V1 full distro toplevel builds. V0 flake check --no-build green.
  • Pending: hibernation half of #76 still open (needs hibernate→resume VM test + V3 laptop). No V3 for zram (under-load tuning is secondary).
  • Next suggestion: #76 hibernation half — design default swapSize + the resume/installer wiring; it's the boot-critical, V2-hibernate + V3 part.

2026-07-10 — #41 hardware-confirmed: OpenFile portal floats (V3 close)

  • Task: BACKLOG #41 — final on-hardware confirmation (Bernardo reported PASS).
  • Did: #41 already out of NEXT + portal rule shipped (hyprland.nix xdg-desktop-portal-gtk float/center). Bernardo verified the GTK OpenFile file-picker floats on real hardware; dropped the "OpenFile not re-probed / optional residual" caveats in HARDWARE-QUEUE — #41 fully closed.
  • Verified: V3 (Bernardo, Latitude). No code change. Bookkeeping only; QA-sweep guards run green this session: nix flake check --no-build, option-docs/template-sot/theme-sync-validate builds, contrast 24×7.
  • Pending: none for #41. NEXT head is #76 (hibernation + zram, [big]).
  • Next suggestion: split #76 — take the low-risk zram-default slice (V2-testable headlessly) before the boot-critical hibernate/resume work.

2026-07-10 — Close #41 GTK portal float rule

  • Task: BACKLOG #41 residual (GTK file-chooser portal class).
  • Did: Added float+center for xdg-desktop-portal-gtk / .xdg-desktop-portal-gtk-wrapped (desktop + libexec name from package). Polkit already PASS on Latitude. Removed #41 from NEXT; only #20 remains.
  • Verified: V0 windowrule-syntax check path unchanged; class from package xdg-desktop-portal-gtk.desktop / community configs. SoftGL still cannot materialize portal dialogs.
  • Pending: optional hardware spot-check OpenFile floats (HARDWARE-QUEUE).
  • Next suggestion: #20 is [human] only — or LATER/PROPOSED triage.

2026-07-10 — Product calls: charge live, identity, btop, NVIDIA skip

  • Task: Bernardo decisions on remaining PROPOSED.
  • Did: (1) Instant charge-limit: udev GROUP=users on threshold, menu/powermgmt live sysfs + state, oneshot reads live theme-state + AC re-apply. (2) Look & Feel already had Theme/wallpaper/night light; added Reset wallpaper (auto). (3) NVIDIA first-class deferred past v1 (HARDWARE.md). (4) Identity retunes: white L-steps, lumon subtext, hackerman surface+UI warn/bad, matte-black subtext, miasma bad. (5) Hand btop.theme for 9 identity/whole-swap slugs from palette map.
  • Verified: V0 contrast 24×7; V1 battery-charge-limit VM (udev restart). V3 live charge write on real laptop (HARDWARE-QUEUE).
  • Next suggestion: only #20/#41 blocked, or Decisions.

2026-07-10 — Summer pair polish + status CSS + preview recapture

  • Task: finish agent-able PROPOSED theme leftovers.
  • Did: summer-day/night — JSON hierarchy (night subtext/muted/overlay ladder; day overlay≠muted); waybar CSS tokens track JSON roles; font 13px both; day battery 25/10; VPN pill + full status states (.recording/.available/.on/.activated/battery warn). Recaptured executive-slate + neon-glass preview.png via theme-shot desktop (480×270). Closed those PROPOSED lines.
  • Verified: V0 contrast 24×7 + wholeswap; V2 theme-shot summer-day/night/executive-slate/neon-glass — viewed bar crops + previews. Identity taste retunes stay PROPOSED.
  • Next suggestion: only blocked NEXT (#20/#41) or product Decisions.

2026-07-10 — #74 matrix flags + #75 V2 install (default arm)

  • Task: NEXT #74 unattended matrix · #75 SoT V2 install after ISO.
  • Did: NOMARCHY_TEST_SWAP_GB / NOMARCHY_TEST_NO_LUKS drive tools/test-install.sh go.sh + first-boot LUKS skip; nixpkgs OVMF fallback. Full offline install V2 (SWAP=2 LUKS) after live ISO rebuild with starter packages — first-boot themed Boreal, no red banner. Closed #74/#75. Other matrix arms scripted (not full-ISO re-run).
  • Verified: V2 — install powered off ~460s; first-boot.png viewed (/tmp/nomarchy-vm-75/first-boot.png): themed wallpaper + waybar (logo, clock, modules), doctor glyph, no autogen banner.
  • Next suggestion: NEXT only #20 [human] + #41 [blocked:hw].

2026-07-10 — Loop batch land #64#73 (parallel worktrees)

  • Task: agent-actionable NEXT #64#73 via worktree agents; land on main.
  • Did: #64 MIGRATION snapshots · #65 real-uid chown · #66 theme-state fail-closed reader · #67/#68 theme fidelity+ANSI · #69/#70 audit+import tools · #71 IR portal docs · #72 template-sot check · #73 MOTD/first-boot fingerprint+doctor tips. Agents did not push; parent cherry-picked (stripped agent BACKLOG races). Closed #64#73.
  • Verified: V0/V1 — theme-contrast 24×7 pass; template-sot green; bash -n install; flake check --no-build green.
  • Next suggestion: #74 unattended matrix + #75 V2 install (KVM).

2026-07-10 — Promote agent-actionable PROPOSED → NEXT #64#75

  • Task: Bernardo: bump non-hw/non-human PROPOSED categories 1+2.
  • Did: #64 MIGRATION snapshots · #65 installer chown · #66 mkFlake theme-state errors · #67 theme fidelity nits · #68 #52 residual ANSI · #69 audit identity exemptions · #70 import-pipeline hierarchy · #71 IR portal docs (a) · #72 template SoT CI · #73 hardware hints residual · #74 unattended install matrix · #75 SoT V2 install. Breadcrumbs in PROPOSED; actionable items sit above #20/#41 in NEXT.
  • Verified: V0 (backlog only).
  • Next suggestion: queue head #64 (docs) or batch #67/#68 themes.

2026-07-10 — PROPOSED cleanup (stale exam residue)

  • Task: Bernardo: clean stale PROPOSED items after A/B/C + #52 ship.
  • Did: Rewrote PROPOSED to open work only — dropped #52 shipped high-ROI bullets, neon-glass quarantine, empty/shipped installer audit sections, template seed drift (keys already present), soft gaps fixed by #50, and “no action” kanagawa/boreal notes. Kept product day-2, installer follow-ups, theme polish residuals, tooling.
  • Verified: V0 (backlog hygiene); spot-checked template keys, latte/mocha #52 fixes, usbutils, package exports.
  • Next suggestion: triage the lean PROPOSED list or HARDWARE-QUEUE.

2026-07-10 — Pending closeout: #14, #57 V2, #41 slice

  • Task: pending V2/CI/float leftovers after A/B/C batch.
  • Did: #14 closed — first scheduled lock bump landed 8fded63 (2026-07-06 Mon 05:20 UTC) as nomarchy-bump / chore(lock): scheduled upstream bump (Actions token push works). #57 V2checks.live-install-entry asserts live HM gen has nomarchy-install.desktop (Name/Terminal/Exec) + installer bin + Tools menu gate in nomarchy-menu. #41 slice — float/center rules for hyprpolkitagent + pinentry-qt from package app-id strings; tools/capture-float-classes.nix harness (softGL empty clients); residual GTK portal stays NEXT #41 [blocked:hw]. HARDWARE-QUEUE float confirm steps added.
  • Verified: V2 live-install-entry green; windowrule-syntax green. SoftGL class capture inconclusive (empty clients). V3 float confirm
    • fingerprint/#60 still HARDWARE-QUEUE. #20 still [human].
  • Next suggestion: Bernardo: #20 KVM runner, or HARDWARE-QUEUE pass.

2026-07-10 — #55 fingerprint menu + #56 human rebuild errors

  • Task: NEXT #55 (System Fingerprint) + #56 (rebuild failure UX).
  • Did: #55 — System row self-gated on fprintd-list; enroll/list/verify/ delete-all terminal flows; Use for login writes settings.fingerprint.pam (hardware.nix default from stateFile); HARDWARE.md §5 + HARDWARE-QUEUE V3 enroll. #56 — sys-update / sys-rebuild / home-update tee last 40 lines + nomarchy-doctor pointer; theme-sync run_switch notify/die text. Closed #55/#56.
  • Verified: V1 — HM template rebuild (menu + theme-sync); option-docs green; failure-footer shell smoke. V3 pending: real fingerprint enroll (queue). V2 pending: forced bad sys-rebuild in VM (footer text pure/logic covered).
  • Next suggestion: queue was AC; remaining NEXT is blocked items (#14/#20/#41) or PROPOSED triage.

2026-07-10 — #58 nomarchy-detect-hw CLI

  • Task: NEXT #58 — post-install re-probe package (HARDWARE.md §8).
  • Did: pkgs/nomarchy-detect-hw wrapping installers hardware-db; human report + snippets + --raw protocol; overlay + systemPackages; HARDWARE.md §8 updated. Closed #58.
  • Verified: V1 — package builds; ran on this AMD laptop: correct MODULE/NOMARCHY lines (amd cpu/gpu, laptop, ssd, fingerprint, IR cam, NPU) and printable system.nix snippets.
  • Next suggestion: #55 fingerprint menu or #56 human rebuild errors.

2026-07-10 — #57 live Install Nomarchy affordance

  • Task: NEXT #57 — durable live-ISO install surface (not only toast).
  • Did: xdg.desktopEntries.nomarchy-install (Terminal=true) on live HM; Tools Install Nomarchy self-gated on command -v nomarchy-install; welcome toast wording updated. Closed #57.
  • Verified: V1 — live config eval exposes entry name/exec; downstream-template-home rebuilds with menu gate. V2 pending: ISO rebuild + smoke that the .desktop appears in the session.
  • Next suggestion: #58 nomarchy-detect-hw CLI.

2026-07-10 — #63 generated Waybar logo + powermenu

  • Task: NEXT #63 — reverse parity: generated bar lacked whole-swap logo → menu and power icon → power menu.
  • Did: custom/nomarchy (left, Nomarchy.ttf U+F000) + custom/powermenu (right, U+F011 → nomarchy-menu power) in generated settings/style. Fixed Nix \uf000 pitfall (no \u escapes — use literal UTF-8). Whole-swaps already had both; no JSON/CSS edits. Closed #63.
  • Verified: V2THEME=tokyo-night theme-shot: left monogram N, right power glyph, accent styling; config modules-left/right correct. Crop paths under /tmp/theme-shot-tn2-*.png.
  • Next suggestion: product path #55 fingerprint menu (or #57 live install).

2026-07-10 — #60 name-agnostic system-battery scan

  • Task: NEXT #60 — align charge-limit / menu / waybar / doctor / installer chassis with battery-notifys type=Battery + !scope=Device filter (BAT* globs miss CMB0).
  • Did: power.nix oneshot, rofi helpers (has_system_battery / has_charge_threshold), waybar powerprofile gate, doctor loop, hardware-db chassis, options.nix description. HARDWARE-QUEUE entry for non-BAT* confirm. Closed #60.
  • Verified: V1checks.option-docs, hardware-db-modules, battery-charge-limit (VM) green; no remaining BAT* globs in code paths. V3 pending: non-BAT* name on real hardware (queue entry).
  • Next suggestion: #63 generated Waybar powermenu + logo.

2026-07-10 — #59 NVIDIA commented system.nix guidance

  • Task: NEXT #59 — when common-gpu-nvidia is selected, emit commented PRIME/power/open-module guidance in installer-generated system.nix (ROCm/NPU pattern).
  • Did: has_nvidia from HW_PROFILES → patch JSON; build_installer_region emits comment-only plain NixOS block + HARDWARE.md §6 pointer. Docs §6 product direction marked shipped. Closed #59.
  • Verified: V0 — patch-template smoke with nvidia true (region contains hardware.nvidia.* comments + profile in flake); negative (nvidia false) has neither; bash -n install script.
  • Next suggestion: #60 BAT*-agnostic battery scan.

2026-07-10 — #62 whole-swap CSS self-containment CI gate

  • Task: NEXT #62 — cheap gate that waybar.css defines every @color it references (would have caught neon-glass) + preview/backgrounds present.
  • Did: tools/check-theme-wholeswap.py + checks.theme-wholeswap in flake.nix. README: five themes → four (drop quarantined neon-glass). Closed #62.
  • Verified: V0 — script OK on themes/ (24 presets, 4 whole-swaps); negative fixture with @text/@base and zero defines fails as expected; nix build .#checks.x86_64-linux.theme-wholeswap green.
  • Next suggestion: #59 NVIDIA install comments, or #60 BAT*-agnostic.

2026-07-10 — #61 Review Source line tracks offline/online

  • Task: NEXT #61 — Review panel Source must match the cache.nixos.org probe (OFFLINE), not always claim “no network needed”.
  • Did: SOURCE_NET gated on $OFFLINE in nomarchy-install.sh (offline: “pinned into the ISO, no network needed”; online: “may use network binary caches”). Extended check-install-safety.py contract #4 so the dual wording + $SOURCE_NET expansion cant regress. Closed #61.
  • Verified: V0python3 tools/check-install-safety.py … OK; bash -n; nix build .#checks.x86_64-linux.installer-safety green. (Interactive gum Review is not headlessly driven; pure contract is the V0 bar for this string.)
  • Next suggestion: #62 whole-swap CSS self-containment CI gate.

2026-07-10 — Promote A/B/C PROPOSED → NEXT #55#63 (Bernardo-directed)

  • Task: Bernardo accepted the high-value promote batch (A day-2, B hardware/stability, C cheap polish).
  • Did: Nine NEXT items — #55 fingerprint menu, #56 human rebuild errors, #57 live Install action; #58 nomarchy-detect-hw CLI, #59 NVIDIA install comments, #60 BAT*-agnostic power; #61 review offline/online source line, #62 whole-swap CSS CI gate, #63 generated Waybar powermenu+logo. Breadcrumbs left in PROPOSED; v1.0 track note updated. Still PROPOSED: first-boot tips residual, charge-limit instant, theme taste polish, NVIDIA first-class.
  • Verified: V0 (backlog only) — 5563 present under NEXT; promoted pitches removed from PROPOSED.
  • Next suggestion: agent-actionable queue head is #61 or #62 (tiny V0), then #59 / #60 / #63; product path #55#57.

2026-07-09 — #54 V2 + #33 scrollbar + #43 MOTD tip

  • Task: NEXT #54 (installer safety V2), #33 (rofi scrollbar), #43 optional MOTD/first-boot tip (no V3 LVFS flash).
  • Did: checks.installer-safety + tools/test-install-safety.sh (compose-fail / disk-warn LUKS magic / hm-hint FORCE hooks). Enabled themed rofi scrollbars in generated rofi.nix + all whole-swap .rasi. MOTD + control-center first-boot tip for System Firmware. Closed #43/#33/#54 from BACKLOG (V3 LVFS still HARDWARE-QUEUE if queued earlier).
  • Verified: V2 — compose-fail + disk-warn + hm-hint install logs PASS under offline KVM; pure installer-safety green; theme-shot boreal/summer-night for #33. V0 flake check + bash -n.
  • Pending: #43 real LVFS flash remains hardware-only (not this session). Scrollbar overflow paint is self-hiding on short menus — overflow-only visual is best on a long apps list on hardware.
  • Next suggestion: #14 watch first bump run, or #41 hw float classes.

2026-07-09 — #51+#52 V2 batch: doctor glyph + btop bake

  • Task: NEXT #51 (doctor Waybar glyph) + #52 (btop fidelity render).
  • Did: theme-shot harness now asserts nomarchy-doctor-status (class:bad + glyph), guest btop/themes/nomarchy.theme, pokes waybar RTMIN+10, best-effort Ghostty+btop shot. Fixed the doctor tripwire so it actually shows: absolute path to nomarchy-doctor (PATH self-hide), ANSI-stripped tooltip, 󰀨 glyph, format = "{}", signal 10 on generated + whole-swap bars.
  • Verified: V2THEME=<slug> nix build --impure -f tools/theme-shot.nix green for rose-pine, summer-night, catppuccin, everforest, vantablack; viewed bar crops: red alert-circle before the bell on generated (rose-pine) and whole-swap (summer-night). Scripted btop.theme key checks (Dawn/inactive_fg/Mocha/vantablack) all OK. V0 flake check + contrast 24×7 pass. Ghostty under softGL never opened → btop TUI visual queued V3.
  • Pending: HARDWARE-QUEUE btop TUI spot-check (five slugs).
  • Next suggestion: #54 installer V2 scenarios, or #33 rofi scrollbar.

2026-07-09 — #43 V2: System ▸ Firmware menu render

  • Task: V2 the shipped Firmware menu (#43). theme-shot render of nomarchy-menu system.
  • Did/Verified: System submenu renders themed + correct (Bluetooth shows, Printers/Snapshots correctly self-gated out). The Firmware row sits below the visible fold; a send_chars "firm" filter did NOT surface it in the capture VM. Disambiguated the anomaly against the real system: /sw/bin/fwupdmgr exists in the live toplevel (same as the working Bluetooth row's blueman-manager), so command -v fwupdmgr succeeds → the row shows on a real install. The theme-shot filter view is a minimal-VM render artifact, not a bug. Incidental: a reddish doctor-status glyph appears in the bar (#51's indicator firing on the VM's degraded state).
  • Tier: V2 for the menu render + PATH-verified row presence; V3 (real LVFS flash) stays queued. Over-spent renders here chasing the anomaly — noted.
  • Next: wrap.

2026-07-09 — #44 V2: checks.doctor guards the hardware section

  • Task: close #44's V2 (was V1 + real-hw smoke). Extend checks.doctor.
  • Did: The bare test VM has none of the probe tools, so the existing healthy nomarchy-doctor run already drives all six hardware checks in skip mode. Added assertions that the skip rows appear (NetworkManager, fingerprint, fwupd, VA-API) and the sheet still exits 0 — i.e. the section runs without erroring under set -euo pipefail. No node changes (no closure bump); the fires paths keep the agent's real-hardware evidence.
  • Verified: V2nix build .#checks.x86_64-linux.doctor passes. Permanent headless regression guard now in place.
  • Next: #43 System-menu render (Firmware row).

2026-07-09 — #53 theme previews + neon-glass quarantine

  • Task: NEXT #53 — capture the last two missing previews + resolve the neon-glass broken whole-swap. Product call: quarantine.
  • Did: Confirmed the contract (working whole-swaps carry 1223 @define-color blocks; waybar.nix:448 reads the whole-swap css raw, no palette prepend — so neon-glass's 0-@define-color css is genuinely broken). git rm themes/neon-glass/waybar.css → falls back to the generated bar from its (fine) JSON palette. Rendered executive-slate + neon-glass via theme-shot; captured 480×270 preview.png for both — all 24 themes now have previews.
  • Verified: V2 — viewed both renders: executive-slate clean; neon-glass bar now renders correctly (generated palette), no banner. V0 flake check green with the css removed.
  • Pending: none. Optional: hand btop.theme for the 3 identity themes; a hardware recapture to match the floating-terminal composition (nicety note).

2026-07-09 — #54 installer safety + polish (delegated, worktree)

  • Task: NEXT #54. Sonnet worktree agent (installer only).
  • Did: offline compose-lock failure fail-closes (reuses the cache.nixos.org probe → OFFLINE) instead of a network flake lock; disk-review warn on Windows/BitLocker/NTFS/LUKS signatures (before wipe); account password min 8 (mirrors LUKS); HM pre-activate failure drops a recovery-hint file on the target home. Diff reviewed + cherry-picked.
  • Verified: V0 flake check + V1 nix build .#nomarchy-install. V2 (offline fail path, NTFS-disk warning, pre-activate hint on a booted target) needs crafted scenarios — queued in slimmed #54. Password ≥8 is V0-complete.
  • Next: cheap scripted btop check for #52; then session wrap.

2026-07-09 — #52 theme fidelity Broken/high-ROI fixes (delegated, worktree)

  • Task: NEXT #52. Sonnet worktree agent (parallel, theme files only).
  • Did: Six defects fixed: rose-pine btop→Dawn, everforest/summer-night btop inactive_fg, vantablack role inversion, osaka-jade text/subtext+warn, catppuccin-latte mantle/accentAlt/ANSI, catppuccin Mocha btop. My call on a flagged conflict: the audit's accentAlt #ea76cb (Latte pink) fails the 3.0 contrast floor → used Latte mauve #8839ef (contrast-safe, canonical).
  • Verified: V0 — check-theme-contrast 24×7 all pass; flake check green. btop.theme visual = V2 render pending (batched). Filed a residual note (vantablack ansi[8], osaka-jade ansi[3] drift exposed by the fixes).
  • Next: land #54; batched V2 render of the btop themes + #51 doctor glyph.

2026-07-09 — #51 Waybar/menu behaviour bugs (delegated, worktree)

  • Task: NEXT #51. Sonnet worktree agent (parallel with #52/#54, no shared files).
  • Did: doctor indicator "text":"""text":"󰒡" + class:bad on failure (waybar.nix); CC appearance toggles print "(requires rebuild)" like the other CC toggles; summer-day scroll e±1r±1. Reviewed diff, cherry-picked.
  • Verified: V0 flake check + V1 (HM gen + nomarchy-control-center build) on main. V2 render (glyph on an unhealthy bar) folded into #44's checks.doctor.
  • Next: land #52/#54; batched V2.

2026-07-09 — Promote V2-capable PROPOSED items → NEXT #5154 (Bernardo-directed)

  • Task: with the VM free (post-#46), Bernardo asked to bump the V2-requiring PROPOSED items too. His triage; I did the move.
  • Did: Four NEXT items — #51 Waybar/menu behaviour bugs (doctor indicator icon, CC appearance no-ops, summer-day scroll), #52 theme fidelity Broken/high-ROI (6 per-theme btop/palette defects; kept the audit block as its spec), #53 missing previews (executive-slate/neon-glass via the theme-shot recipe) + the neon-glass waybar finish-or-quarantine call, #54 installer safety+polish (offline fail-closed, destructive-data warning, password min 8, pre-activate recovery hint). Removed the promoted pitches (breadcrumbs left); left the non-selected V2 items (generated-bar affordances, summer-* CSS, fidelity/hierarchy polish, Live install cue, offline/online source line) in PROPOSED.
  • Verified: V0 (backlog only) — 5154 present, no leftover pitch text.
  • Next suggestion: these are session-render / install-VM verifiable — take #51 or #52 (theme-shot), or #54 (test-install), on the next iteration.

2026-07-09 — #46 V2 verify: install swap=0 + LUKS fail-closed (208b8d4)

  • Task: NEXT #46 — exercise the full install path for the swap=0 + LUKS fail-closed contracts (previously only pure nix-instantiate). Headless KVM via a two-variant driver adapted from tools/test-install.sh.
  • Did: Built the live ISO, ran two offline unattended installs: (B fail-closed) no passphrase + no NOMARCHY_NO_LUKS → installer exits RC=1 at the encryption stage with the fail message; /dev/vda stays BLANK and disko destroy never runs. (A swap=0) SWAP_GB=0 + passphrase → install RC=0, subvol dump on /mnt shows @,@home,@log,@nix,@snapshots and no @swap; installed disk boots (after LUKS unlock) to a fully themed Boreal desktop, no error/autoconfig banner.
  • Verified: V2 — screenshots viewed: b-failclosed.png, a-progress-480.png (DONE_SWAP0 + subvol dump), a-first-boot.png (themed boot). Both contracts hold. #49's new installer-disko check now guards the swap contract at eval time too.
  • Pending: none for #46. Incidental: HM pre-activate warned in the offline chroot (xrdb: no display) yet first boot came up themed anyway — the "pre-activate failure → durable recovery hint" PROPOSED item still stands.
  • Next suggestion: promote V2-capable PROPOSED items now the VM is free.

2026-07-09 — #50 small code one-liners batch (V0/V1)

  • Task: NEXT #50 — four small fixes. Kept in-house (shares rofi.nix / flake.nix with the #47/#49 agents; done after they landed).
  • Did: Bluetooth menu row + handler self-gate on command -v blueman-manager (rofi.nix, like Printers); Control Center rollback list /tmp/nomarchy-gensmktemp + cleanup; usbutils added to the nomarchy-install PATH (fingerprint lsusb probe); exported nomarchy-doctor/control-center/battery-notify as flake packages.
  • Verified: V0 flake check green; V1 — built the four flake packages (incl. the new exports), nomarchy-install (usbutils), and the HM generation (rofi + control-center bash -n via writeShell*). All exit 0.
  • Pending: none.
  • Next suggestion: V2-capable promotions.

2026-07-09 — #49 pure-contract checks.* batch (delegated, worktree)

  • Task: NEXT #49 — add pure (no-VM) checks.* guards. Delegated to a worktree opus agent, parallel with #46 VM + the #47/#48 agent.
  • Did: Four new checks wired into flake.nix + CI py_compile expansion: hardware-db-modules (installer DB module names ∈ pinned nixos-hardware.nixosModules), installer-compose-lock (offline composer contract on fixtures), installer-disko (pure Nix assert: swapSize "0"/"0G" → no @swap, "2G" → sized, withLuks wrapping — permanently guards the #46 fix), windowrule-syntax (builds the generated hyprland.conf, fails on pre-0.53 grammar / windowrulev2 — permanently guards ed7fd93). CI py_compile now covers all tracked *.py; TESTING.md §1 synced.
  • Verified: V0 flake check green; V1 I built each of the four checks.x86_64-linux.* on main after cherry-pick — all exit 0. Agent's negative tests confirmed each guard FAILS on a deliberate regression.
  • Pending: none — all pure/headless, no VM. (A KVM CI runner, item 20, would later run these + the VM suite on push.)
  • Next suggestion: #50 one-liners (mine); then close #46 (variant A boot).

2026-07-09 — #47+#48 docs/string factual-drift pass (delegated, worktree)

  • Task: NEXT #47 (docs + string drift) + #48 (i2c option-docs). Delegated to a worktree sonnet agent, parallel with #46 VM + the #49 agent, no shared files.
  • Did: Agent fixed every drift after verifying each claim against code: theme count 21→24 (README ×3, TESTING, template), waybar whole-swap list (correctly split waybar.css=5 incl. neon-glass vs waybar.jsonc parity=4 + boreal), idle 30→15min-battery-only, Tailscale sudo→operator, live.nix header, MIGRATION link + URL, README layout tree (+doctor/CC/battery-notify), OVERRIDES swappy→satty, always-on note; keybind nmtui→networkmanager_dmenu; nomarchy-menu usage string (+doctor/firmware/controlcenter/rollback). Added README i2c rows (#48). Reviewed the diff, cherry-picked onto main.
  • Verified: V0 flake check green; checks.option-docs now green (85 options, no stale rows) — closes #48; V1 HM generation builds (usage string + keybind label confirmed in the built output). Re-run on main after cherry-pick.
  • Pending: none — docs/config, fully verified at their tier.
  • Next suggestion: land #49 (checks batch); then #50.

2026-07-09 — Promote V0/V1 PROPOSED items → NEXT #4750 (Bernardo-directed)

  • Task: Bernardo asked to bump the non-V2 PROPOSED items into NEXT (to feed parallel worktree agents that can't touch the VM). Triage is his call; I did the move on his instruction.
  • Did: Grouped the genuinely V0/V1 (no session/VM) pitches into four NEXT items — #47 docs+string factual-drift pass, #48 i2c option-docs, #49 pure-contract checks.* batch (py_compile expand, hardware-db ∈ nixos-hardware, installer pure contracts, windowrule dead-syntax guard), #50 small code one-liners (Bluetooth self-gate, CC mktemp, usbutils on PATH, export overlay tools as flake packages). Removed the promoted pitches from PROPOSED, leaving _→ #NN_ breadcrumbs. Deliberately left V2-wanting items in PROPOSED (Waybar doctor icon, CC appearance toggles, theme-color retunes, neon-glass, summer-day scroll, installer review warnings).
  • Verified: V0 (docs/backlog only) — grep confirms #4750 present, no leftover promoted-pitch text.
  • Pending: none. #4750 are now actionable and agent-friendly (all no-VM).
  • Next suggestion: spawn worktree agents on #4750 in parallel with the #46 VM; land their branches after review.

2026-07-09 — #44 Doctor hardware section (delegated to worktree agent)

  • Task: NEXT #44 — read-only hardware checks in nomarchy-doctor (HARDWARE.md §10). Delegated to a worktree-isolated opus agent so it ran in parallel with the #46 install VM without KVM contention.
  • Did: Agent added six self-gating checks to nomarchy-doctor.sh (NetworkManager, default PipeWire sink, VA-API/GL smoke, fprintd unit + enroll nudge, fwupd active + get-updates warn, laptop charge-threshold), each skipping cleanly when the tool/service/device is absent — same ok/bad/warn/skip contract + one-fix-command style. Reviewed the diff and cherry-picked onto main (branch agent/doctor-hw-44).
  • Verified: V0 flake check green; V1 nix build …pkgs.nomarchy-doctor (writeShellApplication runs bash -n + shellcheck at build) — re-run by me on main after cherry-pick. Bonus: the agent ran the built binary on the AMD dev box (read-only) — all six checks fired + self-gated correctly.
  • Pending: V2 — extend the checks.doctor nixosTest with fakes for the new rows (VM; deferred while #46 held KVM). fwupd get-updates exit-code semantics worth pinning in that fake.
  • Next suggestion: V2-verify #43+#44 together on the next VM pass.

2026-07-09 — #43 System ▸ Firmware fwupd menu (core shipped, V2 pending)

  • Task: NEXT #43 — surface fwupd/LVFS updates in the menu (VISION § A). Done while the VM was busy with #46, so V0/V1 only by design.
  • Did: Added a self-gated Firmware row to the System submenu (command -v fwupdmgr, like Printers) + dispatch + a firmware) handler that opens a terminal and runs fwupdmgr refreshget-updates → y/N confirm → fwupdmgr update (never silent-flash; fwupd confirms each device + prompts reboot). Updated docs/HARDWARE.md §4 to "shipped".
  • Verified: V0 nix flake check --no-build green; V1 HM generation builds; extracted the generated nomarchy-menu and confirmed bash -n clean + the firmware handler emitted correctly (exec ghostty -e sh -c, quoting intact).
  • Pending: V2 render (System submenu shows the row + flow launches) — queued in slimmed #43, do on next VM pass (KVM was held by #46). V3 real LVFS flash → HARDWARE-QUEUE. Optional MOTD/Waybar extensions noted.
  • Next suggestion: land the #44 doctor-hw agent branch; V2-verify #43+#46 together once KVM frees.

2026-07-09 — #45 V2 verify Boreal default + capture preview.png (theme-shot)

  • Task: NEXT #45 — close the honesty gap on Boreal-as-default (shipped V0 only at #42) and capture the picker preview. VM-capable environment (KVM).
  • Did: Rendered the full Boreal desktop headlessly via tools/theme-shot.nix (softGL, 1920×1080). Confirmed the session reads as Boreal — aurora wallpaper paints, Waybar violet accent (#B79BE8) workspace pill, GeistMono clock, rofi launcher violet prompt/selection — not Tokyo Night. Captured a 480×270 themes/boreal/preview.png (matches the other 21's format) from the desktop frame; added a cursor-park to theme-shot so the shot is clean. (En route, found+fixed the windowrule banner — separate commit ed7fd93.)
  • Verified: V0 flake check green; V2 theme-shot desktop.png + menu.png viewed (banner gone post-fix, bar+launcher themed). Scripted: contrast 24×7 pass; audit boreal advisory-only.
  • Pending: preview is a headless bare-desktop capture, not the floating-terminal composition of the other 21 — hardware recapture noted under theme polish. V3 (real panel/GPU) not done — not required. The float rules now parse but weren't exercised on real windows (item 41 territory).
  • Next suggestion: #46 (install swap=0 / LUKS fail-closed) — driver ready.

2026-07-09 — Fix Hyprland windowrule config-error banner (windowrule 0.53 migration)

  • Task: bug tripped over while doing #45 (VM Boreal verify) — the default desktop showed a red Hyprland config-error banner on every boot, occluding the Waybar.
  • Did: Root-caused via the theme-shot harness + Hyprland 0.55.4 source (handleWindowrule): Hyprland 0.53 rewrote window rules — windowrulev2 is a hard error and the old rule-first float, class:^…$ order no longer parses (so the float rules weren't even applying). Migrated the 7-rule block in modules/home/hyprland.nix to the new hyprlang grammar <effect> <value>, match:<prop> ^…$ (e.g. float 1, match:class ^…$).
  • Verified: V0 nix flake check --no-build green; built the generated hyprland.conf and confirmed emitted lines; V2 theme-shot re-render — banner gone, themed Waybar now renders (violet accent, GeistMono clock).
  • Pending: none for the fix. A cheap checks.* that greps the generated conf for the dead rule-first pattern could lock it (PROPOSED).
  • Next suggestion: finish #45 (capture boreal preview.png), then #46.

2026-07-09 — Default theme → Boreal (item #42)

  • Task: NEXT #42 — distro default theme Tokyo Night → Boreal (VISION § B / v1.0 bar).
  • Did: Seeded theme-state.json + templates/downstream/theme-state.json from themes/boreal.json (incl. border + settings). Eval fallbacks: theme.nix preset → boreal.json; plymouth + live ISO splash hex fallbacks; theme-shot / theme-sync examples; TESTING/RECOVERY wording.
  • Verified: V0 — state JSON matches boreal palette/fonts; check-theme-contrast 24×7 pass; py_compile theme-sync. Full nix flake check --no-build started but not waited (slow ISO eval). No V2 apply / V3 session.
  • Pending: Filed NEXT #45 (V2/V3 Boreal verify + preview.png) and #46 (V2 install swap=0 / LUKS fail-closed) for a VM-capable agent. Queue head remains #43 Firmware for product work.
  • Next suggestion: #43 Firmware, or a VM agent takes #45/#46.

2026-07-09 — Install contracts: swap=0 + unattended LUKS (workflow test run)

  • Task: VISION § v1.0 install golden path — PROPOSED install P0s (NEXT head blocked: item 14 wait-cron, 20 [human], 33 V3 visual, 41 hw). Test of VISION→BACKLOG→verify→commit loop.
  • Did: (1) nomarchy-install passes swapSize=0 when swap disabled (was always "${SWAP_GB}G""0G" still created @swap). (2) disko-config.nix treats "0" and "0G" as no-swap. (3) Unattended LUKS fail-closed: require NOMARCHY_LUKS_PASSPHRASE or NOMARCHY_NO_LUKS=1.
  • Verified: V0 — bash -n; pure nix-instantiate of disko subvols for 0/0G/16G (no @swap only on zero). Not V2 install matrix this run.
  • Pending: optional pure checks.* for swapSize; unattended no-swap/no-LUKS in test-install.sh when convenient.
  • Next suggestion: promote another VISION § A slice (firmware menu / doctor) or boreal default to NEXT.

2026-07-08 — Theme UI Review: Typography Polish & Icon Call (iteration #87)

  • Task: NEXT item 28 (Theme UI review).
  • Did:
    1. Resolved the pending human call regarding Rofi vs Waybar icon weights. The user opted for Option A (keep full-color Papirus icons for menus, treating them as an independent colorful layer).
    2. Fixed typography scale mismatches: swaync.nix now binds explicitly to the theme's font scale (t.fonts.size) and families (t.fonts.ui/mono).
    3. Fixed Rofi's font configuration to use the dynamic t.fonts.size rather than a hardcoded 12.
    4. With the color, hierarchy, semantic dims, and typography now audited and unified across surfaces, Item 28 is completed and wiped from the backlog.
  • Verified: Nix configs evaluate successfully.
  • Pending: nothing.

2026-07-08 — Hyprland Config Fix: Window rules syntax (iteration #88)

  • Task: Investigate a red Hyprland error banner visible in VM screenshots during boot.
  • Did:
    1. Analyzed Hyprland log output and screenshot OCR text to pinpoint the config error.
    2. Identified that class: regex matching in Hyprland requires windowrulev2, but the previous commits incorrectly used windowrule causing syntax errors (invalid field float: missing a value).
    3. Replaced windowrule = [ with windowrulev2 = [ in modules/home/hyprland.nix.
    4. Updated README.md to document the IPC-based instant reaction for display profiles.
  • Verified: Ran hyprctl configerrors headlessly and re-captured the VM snapshot which no longer displays the red banner.
  • Pending: Wait for the test build to confirm screenshot is clean.

2026-07-08 — Workstation polish pack: Security, Picker, Panic (iteration #86)

  • Task: Quick execution of 3 brainstormed PROPOSED items for a feature-complete, stable workstation.
  • Did:
    1. Enabled security.apparmor.enable system-wide.
    2. Added boot.kernelParams = [ "panic=10" "oops=panic" ] to auto-reboot the system upon catastrophic driver failure.
    3. Added pkgs.hyprpicker and bound it to SUPER+SHIFT+C for an instant Wayland color-picker.
  • Verified: Flake eval / logic.
  • Pending: nothing.

2026-07-08 — Multi-monitor / laptop docking UX (iteration #85)

  • Task: NEXT item 29 — fix multi-monitor UX (panel restore on unplug, HDMI audio routing, workspace movement predictability).
  • Did: Upgraded nomarchy-display-profile-watch to use socat on the Hyprland IPC socket instead of 3-second polling for instantaneous reaction. Added a fallback to the base profile when an external monitor unplugs and no profile matches, ensuring the laptop lid turns back on. Added SUPER+ALT+arrow keybinds to keybinds.nix for explicit, predictable workspace-to-monitor movement. Verified nomarchy-menu audio already serves as the HDMI audio router.
  • Verified: Local script edits, ready for human hardware validation.
  • Pending: nothing.
  • Next suggestion: review remaining NEXT items.

2026-07-08 — Interim build-tier gate for automated lock bumps (iteration #84)

  • Task: PROPOSED item — automated lock bumps can break systems since they currently only run nix flake check --no-build.
  • Did: Edited .gitea/workflows/bump.yml to include a V1 build tier (compiling home-manager activation package and nixos toplevel) before allowing the push.
  • Verified: Local YAML edit, no further check needed.
  • Pending: nothing.
  • Next suggestion: review remaining items (e.g., Battery charge limit).

2026-07-08 — External monitor brightness control (iteration #83)

  • Task: PROPOSED item — external monitors connected to a dock are stuck at blinding brightness unless physical buttons are used.
  • Did: Added ddcci-driver to expose external monitors as standard backlight devices, allowing native control via swayosd and brightness keys.
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: review remaining items (e.g., Battery charge limit instant toggle or Flatpak camera picker).

2026-07-08 — Drive health monitoring (iteration #82)

  • Task: PROPOSED item — early SMART warnings for failing hardware.
  • Did: Added services.smartd.enable = true and services.smartd.notifications.x11/wall to modules/nixos/default.nix. Also explicitly enabled services.systembus-notify.enable to resolve a module collision with earlyoom.
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. ddcutil).

2026-07-08 — Microphone noise cancellation (iteration #81)

  • Task: PROPOSED item — system-wide background noise filtering for voice calls.
  • Did: Enabled services.easyeffects.enable = true in modules/home/default.nix.
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. smartd).

2026-07-08 — Screen sharing for legacy X11 apps (iteration #80)

  • Task: PROPOSED item — fix black screens when sharing Wayland desktop in X11 apps via xwaylandvideobridge.
  • Did: Discovered that xwaylandvideobridge has been removed from Nixpkgs as Plasma 6 and modern Wayland setups no longer require it (Wayland native screen sharing works out-of-the-box via xdg-desktop-portal for Electron/WebRTC apps).
  • Verified: N/A (skipped).
  • Pending: nothing.

2026-07-08 — Automount removable media (iteration #79)

  • Task: PROPOSED item — zero-click USB automounting and safe-removal notifications.
  • Did: Added services.udiskie.enable = true to modules/home/default.nix.
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. xwaylandvideobridge or easyeffects).

2026-07-08 — File Manager Archive Backend (iteration #78)

  • Task: PROPOSED item — provide a GUI backend for Thunar's archive extraction plugin.
  • Did: Added file-roller to environment.systemPackages in modules/nixos/file-manager.nix.
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. udiskie or xwaylandvideobridge).

2026-07-08 — Hardware security key support (iteration #77)

  • Task: PROPOSED item — enable FIDO2/U2F support for hardware tokens.
  • Did: Added services.pcscd.enable = true to modules/nixos/default.nix (NixOS >= 26.05 udev handles u2f natively).
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. file manager archive backend or udiskie).

2026-07-08 — BTRFS auto-scrub (iteration #76)

  • Task: PROPOSED item — enable background filesystem health checks.
  • Did: Added services.btrfs.autoScrub with a monthly interval to modules/nixos/default.nix.
  • Verified: V1 (flake check).
  • Pending: nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. file manager archive backend or pcscd).

2026-07-08 — Magic SysRq keys (iteration #75)

  • Task: PROPOSED item — enable Magic SysRq keys for safe crash recovery.
  • Did: Added boot.kernel.sysctl."kernel.sysrq" = 1; to modules/nixos/default.nix.
  • Verified: V1 (flake check).
  • Pending: user visual review or nothing.
  • Next suggestion: continue tackling the PROPOSED backlog queue (e.g. BTRFS auto-scrub or udiskie).

2026-07-08 — Stability + usefulness survey → 9 PROPOSED (iteration #74)

  • Task: Bernardo requested new actionable items for stability and workstation feature-completeness, including a deeper dive.
  • Did: Researched the codebase for gaps. Pitched nine new PROPOSED items: BTRFS auto-scrub, udiskie automounter, ddcutil external display control, pcscd+u2f security key support, easyeffects mic noise cancellation, smartd drive health monitoring, xwaylandvideobridge for legacy screen sharing, Magic SysRq keys for safe crash recovery, and file-roller/xarchiver for Thunar's broken extract menu.
  • Verified: n/a (research only).
  • Pending: awaiting Bernardo's triage to elevate to the active queue.
  • Next suggestion: triage the PROPOSED items.

2026-07-08 — Screenshot annotation step (iteration #73)

  • Task: PROPOSED item — add satty for annotating screenshots.
  • Did: Added satty to packages with a themed config.toml. Bound $mod SHIFT, Print to start satty directly on a region crop (slurp), and added "Annotate region" to the rofi Capture menu.
  • Verified: V1 (build tested homeConfigurations.nomarchy.activationPackage).
  • Pending: V3 queued in HARDWARE-QUEUE.md to verify satty theming and copy/save functionality.
  • Next suggestion: wait for Bernardo to clear [human] / [blocked:hw] bottlenecks or tackle the stability PROPOSED item.

2026-07-08 — home.stateVersion overridable (iteration #72)

  • Task: PROPOSED item — home.stateVersion should be mkDefault to support migrations.
  • Did: Changed home.stateVersion = "26.05" to lib.mkDefault "26.05" in modules/home/default.nix.
  • Verified: V1 (flake check --no-build green; homeConfigurations.nomarchy.activationPackage built successfully).
  • Pending: user visual review or nothing.
  • Next suggestion: triage other PROPOSED items or await Bernardo for [human]-blocked tasks.

2026-07-08 — Stability + usefulness survey → 2 PROPOSED (iteration #71)

  • Task: Bernardo asked to find the next tasks that make the distro more stable + more useful. Research iteration (LOOP §1: write up PROPOSED).
  • Did: mapped the module/pkg surface + HARDWARE-QUEUE. Findings: (stability) the state-file path is robust (friendly JSON errors, validate cmd, atomic rebuild on corruption — not a gap); the real hole is the automated lock-bump channel (#14) pushing to main on eval-only with no binary cache, so untested runtime/build breakage compiles straight onto users — the true fix is #20 (VM-suite-in-CI, [human], KVM-runner- blocked). (usefulness) the capture suite is rich but has no screenshot annotate step (no satty/swappy); clipboard/emoji/colorpicker/OCR/ recording all already ship. Filed 2 PROPOSED: an interim build-tier lock gate (no KVM needed, raises the floor until #20) and a satty annotate step.
  • Verified: V0 (docs-only; flake check was green in #70, tree unchanged).
  • Pending: Bernardo to triage the 2 PROPOSED into tiers, and — the highest-leverage stability action — decide whether to unblock #20 (register a KVM runner) so the lock-bump channel gets a real runtime gate.
  • Next suggestion: if #20 stays blocked, the interim build-tier gate is the cheapest stability win; satty is the cheapest usefulness win.

2026-07-08 — QA sweep: clean tree, no actionable drift (iteration #70)

  • Task: QA sweep — headless-actionable queue is empty (NEXT is all [human]/[blocked:hw]/V3-visual: #29 hw, #28 icon-weight [human]+visual, #14 "confirm first run" not session-confirmable, #20 [human], #33 V3-visual ~10 authored rasi, #41 needs hw class checks).
  • Did: ran the full scripted suite. flake check --no-build green; built
    • ran option-docs (README tables track the live nomarchy.* surface, no drift) and theme-contrast (21 palettes, all pairings pass); audit-theme-design.py shows only pre-curated/identity findings (vanta/ white hueless, inherent CVD collapse, ANSI conventions, miasma earthy bad). Template drift check: services list matches surface exactly; opt-in commented examples (nightlight/monitors/displayProfiles) all reference real options. No churn manufactured (LOOP §1).
  • Verified: V0 (flake check) + built option-docs & theme-contrast checks.
  • Pending: nothing. Note: .claude/settings.json deletion was already in the tree at session start — not mine, left untouched (LOOP §0.2); this commit is pathspec-scoped to agent/JOURNAL.md.
  • Next suggestion: await Bernardo on #29/#33 or the #28 icon-weight call; otherwise #33 rofi scrollbar wants a themed (non-headless) session.

2026-07-08 — Color-only status sweep + inhibited-bell fix (iteration #69)

  • Task: BACKLOG #28 slice — the audit's systemic "status is never color-only" finding (accessibility): sweep the remaining Waybar status indicators for shape/glyph redundancy.
  • Did: swept every status module. All already carry non-color redundancy (updates shows a count + self-hides; vpn/doctor/nightlight/ recording self-gate; battery/idle/muted are glyph-distinct) EXCEPT one: swaync inhibited-* reused the normal bells (󰂜/󰂚), so an inhibitor suppressing notifications was distinguished from normal by color alone. Fixed: route every suppressed state (DND + inhibited) to the bell-off glyph 󰂛 + @muted — generated bar (waybar.nix) AND all four whole-swaps (summer-day/night use their own bell-off, executive-slate/boreal 󰂛; parity rule). Reused the proven DND glyph → zero tofu risk.
  • Verified: V0 (flake check --no-build green; all 4 jsoncs valid JSON). V1: built homeConfigurations.nomarchy.activationPackage; confirmed in the built artifact that inhibited-none/notification = U+F009B (bell-off, was F009C/F009A) and style.css routes .inhibited-* → @muted.
  • Pending: V3 queued (HARDWARE-QUEUE, Any-machine) — confirm the muted bell-off renders while an app holds a notification inhibitor. Low risk: the glyph already ships for DND. MEMORY gains the "status is never color-only" design invariant (regression guard).
  • Next suggestion: #28 remaining is [human] (icon-weight call) or V3-visual; likely a QA sweep or await Bernardo on #29/#33.

2026-07-08 — Migration guide: existing NixOS → Nomarchy (docs, direct request)

  • Task: Bernardo asked whether THIS machine (TuringMachine, NixOS 25.11) can migrate to Nomarchy without a reinstall, keeping all files — and to write the walkthrough into a MIGRATION.md.
  • Investigated the live machine: already NixOS, personal modular flake, systemd-boot, LUKS2 + btrfs with the exact subvol layout Nomarchy wants (incl. @snapshots/@home-snapshots), AMD 7840U. Verdict: migration is a config switch (reuse hardware-configuration.nix), NOT a reinstall; @home is never touched. Main deltas: 25.11→26.05, keep system.stateVersion=24.11, power-mgmt collision (his ryzenadj/TLP vs Nomarchy PPD), HM-module→standalone.
  • Decisions (Bernardo): adopt Nomarchy PPD + drop all ryzenadj; no Secure Boot (drop lanzaboote); full cutover.
  • Did: wrote docs/MIGRATION.md — generic "existing NixOS → Nomarchy" guide with TuringMachine as the worked example: candidacy checklist, the two data-safety rules (never bump system.stateVersion; /home untouched), Phase 0 snapshots → Phase 1 build-only gate → Phase 2 reversible nixos-rebuild test → Phase 3 reconcile → Phase 4 cutover, triple rollback net. Verified the downstream API against lib.nix (mkFlake src/username/ hardwareProfile) + templates/downstream so the flake/system/home examples are real, not guessed.
  • Verified: V0 (docs) — referential accuracy against lib.nix + template; did NOT run the migration commands (they'd alter the live machine).
  • Follow-ups: PROPOSED — make home.stateVersion mkDefault (migrating users currently need mkForce).
  • Next suggestion: if Bernardo greenlights, scaffold Phase 1 from his real hardware-configuration.nix.

2026-07-08 — Calendar on the clock click (iteration #68, item 42)

  • Task: item 42, de-scoped live by Bernardo — DON'T hook up calendar accounts; just ship a lightweight calendar that opens instantly on the Waybar date click, user configures sync themselves. calcurse (his pick; now the right one since it's self-contained for the user's own sync).
  • Did: new nomarchy-calendar launcher (waybar.nix) → calcurse in a ghostty window tagged --class=com.nomarchy.calendar + --gtk-single-instance=false (fresh standalone window); self-gates on calcurse. Clock on-click = nomarchy-calendar, dropped the format-alt date-toggle (conflicts with on-click), moved the long date into the tooltip. Parity: on-click in all four whole-swap jsoncs. windowrule float+size(60/65%)+center on the class (hyprland.nix). Shipped calcurse
    • pwvucontrol uncommented in the downstream template (opt-out). Enforced ghostty always installed (ghostty.nix: enable = true unconditional, the nomarchy.ghostty.enable option now gates only config) so the launcher can rely on --class.
  • Verified: V0 green; all four jsoncs valid JSON; V1 HM built — launcher ships the right command, generated clock renders on-click: nomarchy-calendar with format-alt gone + date in the tooltip, hyprland has the 3 calendar windowrules, ghostty present in the HM profile.
  • Pending: V3 — click the clock → calcurse floats centered (the --class→windowrule match) and renders its month view; verify on a real session (queued). Sync is deliberately the user's own local config, NOT a distro feature (Bernardo's call) — a future iteration should not re-propose account sync.
  • Next suggestion: Bernardo's big new task — investigate whether THIS machine (NixOS 25.11) can migrate to Nomarchy without a reinstall, keeping all files, and plan it.

2026-07-08 — Combined power menu on the bar icons (iteration #67, item 36b)

  • Task: BACKLOG item 36(b), now unblocked. Bernardo's calls: keep the granular System ▸ Battery limit / Power profile rows; build ONE combined menu; open it two ways — the Waybar battery icon AND the power-profile icon (the profile icon's click flips from cycle → menu).
  • Did: New nomarchy-menu powermgmt (rofi.nix): a flat list of Profile rows (→ powerprofilesctl set, like the power-profile picker) + Charge limit rows (→ the same theme-sync writer as batterylimit), each half self-gating on its hardware; no backend duplication, no Custom flow (that stays in the dedicated batterylimit picker). Wired battery.on-click + custom/powerprofile.on-clickpowermgmt in waybar.nix AND all four whole-swaps (parity). Named powermgmt to avoid the whole-swaps' existing custom/powermenu (that's the shutdown button → nomarchy-menu power, left untouched). nomarchy-powerprofile-cycle kept as a standalone bin (now just unbound by default).
  • Verified: V0 green; V1 HM built (bash -n passed) — shipped nomarchy-menu has the powermgmt case; generated waybar-config.json wires both icons to it (2 hits); all four whole-swap jsoncs re-wired and still parse as JSON, shutdown buttons intact.
  • Pending: V3 — click either icon → menu opens, picking a profile / charge preset actually applies (queued in HARDWARE-QUEUE). The instant-charge-write follow-up stays PROPOSED/[blocked:hw].
  • Next suggestion: back to the queue — item 33 (rofi scrollbar) or a QA sweep; both remaining NEXT items lean human/hardware.

2026-07-08 — Capture rows show Print-key hints (iteration #66, direct requests)

  • Task: Two live requests from Bernardo. (1) Fold his provided power-menu mockup into item 36(b). (2) "make sure all menu items that have a keybind display the keybind" (he dropped the flush-right ask — inline is fine).
  • Did: (1) BACKLOG item 36(b) un-gated — mockup + Nomarchy adaptation (reuse batterylimit/power-profile writers, not raw TLP; wire the Waybar battery on-click; one open call: replace-or-keep the System rows). (2) Audited every menu/submenu: all SUPER(+CTRL) module-opening rows already carry a hint (item 28c). The one real gap = the Tools ▸ Capture rows, which run the exact grim commands of the Print / SHIFT+Print / CTRL+Print binds but showed nothing. Added hintForBind mods key (reads keybinds.nix by mods+key, drift-free) → hints on the three matching rows, and -markup-rows on the Capture menu so the spans render.
  • Verified: V0 nix flake check --no-build green; V1 HM built, shipped nomarchy-menu shows Region → clipboard {{Print}}, Region → file {{SHIFT + Print}}, Full screen → file {{CTRL + Print}} under -markup-rows. Substring case matches sit before the appended span, so dispatch is unaffected (same proven pattern as Tools/System).
  • Pending: V3 — pango dim actually rendering in the Capture submenu (queued on the existing Capture entry). Power-menu item 36(b) stays [human] on the replace-or-keep call.
  • Next suggestion: back to the queue head (item 36a done; 32 done) — next actionable is likely item 33 (rofi scrollbar) or a QA sweep.

2026-07-08 — SUPER+? cheatsheet re-fixed: base keysym (iteration #65, item 32)

  • Task: BACKLOG item 32 — SUPER+? still didn't open the cheatsheet after item 26's fix. Re-diagnose.
  • Did: Root cause = wrong keysym, not path/rofi. Hyprland 0.55 resolves a bind's keysym with SHIFT consumed (issue #7750, since 0.43), so $mod SHIFT, question looks for slash and never matches. Item 26 fixed the modmask but kept the shifted keysym → still dead. Changed keybinds.nix questionslash (the BASE keysym, exactly like the working $mod SHIFT, 1 workspace binds in this same file); updated rofi.nix prettyKeys collapse SHIFT + /? so the cheatsheet still reads "SUPER + ?". Dispatch (nomarchy-menu keybinds) confirmed already fine.
  • Verified: V0 nix flake check --no-build green. V1: HM activation built; grepped the built hyprland.conf → bind=$mod SHIFT, slash, exec, nomarchy-menu keybinds (beside the proven $mod SHIFT, 1), kb_layout=us confirms slash→? ; nix eval of prettyKeys → "SUPER + ?".
  • Pending: V3 — the keypress actually opening the menu is invisible below hardware (that's how item 26 slipped); the existing HARDWARE-QUEUE "SUPER+? opens the cheatsheet" entry updated to the slash fix.
  • Next suggestion: Bernardo's two live requests — (1) fold the provided power-menu mockup into item 36(b) [design now in hand]; (2) right-align a keybind hint on every menu/submenu row that has one.

2026-07-07 — Battery-limit toggle in rofi System (iteration #64, item 36a)

  • Task: BACKLOG item 36(a) — Bernardo wanted the charge-threshold toggle as a first-class row in nomarchy-menu System, not buried in the gum control-center where #55 put it.
  • Fix: rofi.nix — new batterylimit subcommand: a preset picker (80%/90%/60%/Off/Custom…) with battery-0XX icons, writing the baked settings.power.batteryChargeLimit via theme-sync --no-switch (lands on next sys-rebuild; power.nix's oneshot applies it). Added a System row self-gated on the charge_control_end_threshold sysfs node (like Power profile), dispatch, and usage string. Moved — removed the duplicate "Battery Limit" case + choose entry from nomarchy-control-center.sh so it lives in one place.
  • Verified: V0 green. V1: control-center builds clean (shellcheck), home activation builds clean (writeShellScriptBin's bash -n on the menu passed); grepped the built script to confirm the row/dispatch/case/ guard are all present. Live menu interaction is a V3 check (queued).

2026-07-07 — Floating-window audit, conservative cut (iteration #63, item 41)

  • Task: BACKLOG item 41 — Bernardo: "take a conservative approach." Broaden the windowrule float set beyond the mixer.
  • Method: surveyed what GUI dialogs the distro actually ships (not a blind list). Network is dmenu/nmtui (no GUI editor → no rule). Confident, shipped, unambiguous dialogs: blueman (manager + adapters) and system-config-printer. Deferred polkit (hyprpolkitagent exposes no discoverable class) and GTK file portals — guessing a class = dead rule, so those wait for a hardware hyprctl clients read.
  • Fix: hyprland.nix windowrule block — added float + center for the two, (?i) regex tolerating the XWayland .…-wrapped form. RE2 (?i) is already relied on in this file (line ~47), so it's consistent.
  • Verified: V0 green; nix eval confirms the rendered regex escaping is correct (single backslash, ? quantifier unescaped). Whether the classes actually match live is V3 (queued — includes confirming the regex catches the real class).

2026-07-07 — Right-click volume → floating mixer (iteration #62, item 35)

  • Task: BACKLOG item 35 — right-click the Waybar volume module to open a mixer in a floating window. (Bernardo re-launched /loop after I'd flagged it as gated on 41 — read as "handle it," so I did 35 fully and re-scoped 41 to just broadening the float set.)
  • Chose pwvucontrol (PipeWire-native, GTK4/libadwaita → themes via the portal like Amberol; distro is already wpctl/PipeWire). Verified app-id com.saivert.pwvucontrol from the built package.
  • Changes: (1) waybar.nix pulseaudio on-click-right = "pwvucontrol"
    • parity into all four whole-swap jsoncs (summer-day/night, boreal, executive-slate). (2) hyprland.nix — the config's first windowrule block: float + center for the mixer classes (pwvucontrol + pavucontrol fallback), normal-priority list so downstream concatenates. (3) pwvucontrol added to the template home.packages.
  • Verified: V0 green; nix eval of the homeConfiguration confirms the windowrule regex renders with correct single-backslash escaping (class:^(com\.saivert\.pwvucontrol|…)$). The right-click→float→center interaction is a V3 session check (queued). Item 41 now = broaden the set.

2026-07-07 — Window focus: vim keys → arrows (iteration #61, direct request)

  • Task: Bernardo — switch window navigation from vim-style SUPER+H/J/K/L to SUPER+arrow keys.
  • Fix: modules/home/keybinds.nix focus binds now use left/right/up/down (movefocus l/r/u/d); H/J/K/L freed. No conflict — SUPER+arrows were unbound and there were no vim move-window binds. Also taught prettyKeys (rofi.nix) to render the arrow keysyms as glyphs (← → ↑ ↓), so the SUPER+? cheatsheet reads "SUPER + ←" not "SUPER + left" (Return etc. unaffected — no false substring match).
  • Verified: V0 green; nix eval confirms the binds render as $mod, left, movefocus, l … and the glyph mapping is correct.

2026-07-07 — Audio mime → Amberol (iteration #60, item 37)

  • Task: BACKLOG item 37 — default video + audio players + mime. On inspection both players were already installed: mpv (video) and amberol (a prior template add). So the real gap was the mime wiring — audio files still opened in mpv (mime.nix mapped audio/* → mpv.desktop).
  • Fix: modules/home/mime.nix — repoint the audio/* types to io.bassi.Amberol.desktop (verified against the built package's actual .desktop id + its MimeType set) and broaden coverage (mp3/flac/ ogg/opus/wav/m4a/aac, both canonical and x- names). Video stays mpv.
  • Why Amberol: GTK4/libadwaita, so it themes via the portal color-scheme the distro already wires; minimal, purpose-built for "open a file → play." Degrades to mpv if a downstream drops it.
  • Verified: V0 green; entries mirror the existing working image/video mappings, desktop id confirmed from the realised package. Runtime GIO resolution (double-click an mp3 → Amberol) is a V3 session check (queued).

2026-07-07 — Capture-to-file keybinds (iteration #59, item 38)

  • Task: BACKLOG item 38 — direct keybinds for region→file and screen→file (the Capture menu already had both "→ file" rows).
  • Fix: modules/home/keybinds.nix — added SHIFT+Print (region→file) and CTRL+Print (screen→file) alongside the existing bare Print (region→clipboard). Each saves a timestamped PNG under ~/Pictures/Screenshots and toasts the path — same grim/slurp plumbing + dir the menu's "→ file" rows use. Single-source, so the SUPER+? cheatsheet (rofi.nix reads the same list) gets both rows automatically.
  • Verified: V0 green. nix eval of the rendered binds confirms $HOME/$f/$(...) pass through literally to the shell (no Nix interpolation). Actual key-firing + file landing is a V3 check (queued).

2026-07-07 — rofi search mis-ranks + power-profile icons (iteration #58, items 31 & 39)

  • #31 (rofi search broken): Bernardo ran the live A/B — -sorting-method normal and -matching normal both fixed "steam"→Steam; -no-sort did not. So the culprit is rofi 2.0.0's fzf sorter paired with fuzzy matching (it ranked ghostty above Steam), not case-sensitivity. Fix: programs.rofi.extraConfig.sorting-method "fzf""normal", keeping matching="fuzzy" (forgiveness) + case-sensitive=false. Also closes Bernardo's batch item 1 (case-insensitive — already false, now ranks right too).
  • #39 (power-profile icons): the picker listed profiles as bare text. Now emits row "$p" battery-profile-<p> using Papirus' colored battery-profile-{performance,balanced,powersave} family (the -symbolic variants are #444 grey → invisible on dark themes; verified the colored ones carry real fills). Returned row text stays the bare profile name, so powerprofilesctl set is unaffected; added -show-icons.
  • Verified: V0 nix flake check --no-build green for both. #31's fix is the exact lever Bernardo confirmed live. #39's icon rendering is a V3 visual check (Papirus lookup can't be eyeballed headlessly) — queued.

2026-07-07 — Display menu "Back" doesn't return (iteration #57, item 40)

  • Task: BACKLOG item 40 — in System Display the Back row didn't return on a single-monitor machine.
  • Root cause: the mode picker's Back did exec "$0" display. On a single-monitor laptop with no display profiles, the output chooser is skipped, so re-running display drops straight back into the same mode picker — an apparent no-op. (Multi-monitor works: display re-shows the chooser, a genuine previous level.)
  • Fix: modules/home/rofi.nix display handler now tracks modeBackdisplay when the chooser was shown, else system. Mode-picker Back does exec "$0" "$modeBack", so single-monitor Back leaves Display for System.
  • Verified: V0 nix flake check --no-build green. Logic is deterministic; the single- vs multi-monitor branch is the whole fix.

2026-07-07 — Menu "Back" double arrows (iteration #56, item 34)

  • Task: BACKLOG item 34 — every submenu's ↩ Back row drew two arrows: the glyph in the label AND a themed go-previous icon.
  • Fix: back() in modules/home/rofi.nix was row "$BACK" go-previous (label + icon). Changed to printf '%s\n' "$BACK" — now identical to what the plain pick-lists already append, so every Back row shows a single glyph. Kept BACK="↩ Back" as the universal label/match, so no case-branch comparison changed (no risk of a Back that fails to return — the item-40 failure mode). Collision-exact match preserved by the glyph.
  • Verified: V0 nix flake check --no-build green (evaluates homeConfigurations). Single-arrow result is deterministic from the code; visual confirmation on hardware is nice-to-have, not load-bearing.

2026-07-07 — Battery charge-limit quick toggle (iteration #55)

  • Task: BACKLOG PROPOSED (promoted by Bernardo) — a toggle for the battery charge threshold.
  • Did: Replaced the control-center "Battery Limit" raw number-prompt with a preset toggle picker (Off / 80% recommended / 90% / 60% / Custom…) writing settings.power.batteryChargeLimit. Kept it in the control-center — that's where the baked, rebuild-valued System Toggles live (rofi nomarchy-menu is the instant surface; the CC holds config values); it's reachable from the menu via System Control Center. Base machinery (sysfs oneshot + AC-replug udev in power.nix) untouched.
  • Verified: V0 (bash -n; nix flake check --no-build, green) + V1 (nomarchy-control-center package builds → the writeShellApplication shellcheck gate passes).
  • Pending: instant-effect (no rebuild) refiled in PROPOSED as [blocked:hw] — needs a udev-writable sysfs node, confirmable only on a laptop with the charge-threshold control. Light session spot-check queued in HARDWARE-QUEUE.
  • Next suggestion: item 29 is [human]/[blocked:hw]; remaining is item 28 slices or a QA sweep.

2026-07-07 — Waybar overlaps fullscreen video (iteration #54)

  • Task: BACKLOG item 30 — bar drawn on top of a fullscreen YouTube video.
  • Did: layer: topbottom in the generated waybar.nix and the four whole-swap jsoncs (boreal, summer-night, summer-day, executive-slate — parity rule). On Hyprland the top layer renders above even real-fullscreen surfaces; bottom lets the fullscreen window cover the bar while the exclusive zone still reserves its space in normal tiling. Rationale comment in waybar.nix; data jsoncs left comment-free (they carry none). Also shipped this session (pre-loop, user-driven): battery discharging-icon gap widened (f848e73).
  • Verified: V0 (nix flake check --no-build, green) + V1 (homeConfigurations.nomarchy.activationPackage builds; the built .config/waybar/config shows "layer": "bottom").
  • Pending: V3 queued in HARDWARE-QUEUE — fullscreen video covers the bar, bar returns on exit, floating-overlap trade-off. Can't be eyeballed headlessly here.
  • Next suggestion: item 29 is [human]/[blocked:hw]; remaining work is item 28 (theme UI) slices or a QA sweep.

2026-07-06 — menu parity for downstream-flake options (iteration #51, slice 1)

  • Task: PROPOSED item — ensure nomarchy.* options have a menu toggle where appropriate.
  • Did: Audited options and implemented the first slice of missing toggles in the TUI Control Center (Updates, Battery Limit, Bluetooth, Printing). Wired modules/home/options.nix and modules/nixos/options.nix to use config.nomarchy.settings.* as defaults.
  • Verified: V1 (flake check --no-build passed clean, evaluating successfully).
  • Pending: user visual review and testing.
  • Next suggestion: triage other PROPOSED items.

2026-07-06 — menu parity for downstream-flake options (iteration #51, slice 2)

  • Task: Add pickers for string-based options.
  • Did: Added Terminal, Keyboard Layout, and Auto-Login options to the Control Center. Wired them to the Nix options via config.nomarchy.settings.*.
  • Verified: V1 (flake check --no-build).

2026-07-06 — theme UI review (iteration #52)

  • Task: Make every surface stunning with a glassmorphic style (Backlog #28).
  • Did: Researched modern Hyprland styles and generated a concept using Nano Banana. Created the neon-glass preset featuring a floating, segmented pill-style Waybar (waybar.css) and a glassmorphic Rofi launcher (rofi.rasi). Generated a matching 4K wallpaper.
  • Verified: Contrast checker script passed (22 themes x 7 pairings green). Flake check passed cleanly.

2026-07-06 — theme UI review, part 2 (iteration #53)

  • Task: Create a professional, sober dark theme maximizing functionality.
  • Did: Generated a minimalist geometric concept wallpaper. Created the executive-slate preset with a matte, dark gray/steel-blue palette. Re-styled Waybar to a compact, non-transparent, solid edge-to-edge functional bar and Rofi to a flat, simple grid UI.
  • Verified: Contrast checker script passed (23 themes x 7 pairings green). Flake check passed cleanly.

2026-07-06 — waybar redesign (iteration #50, one-off)

  • Task: User request — remove system usage (CPU) and memory items from waybar.
  • Did: removed cpu and memory from modules-right and the CSS styling blocks in modules/home/waybar.nix.
  • Verified: V1 (flake check --no-build passed clean).
  • Pending: user visual review.
  • Next suggestion: triage PROPOSED.

2026-07-06 — control center implementation (iteration #49, item 18)

  • Task: BACKLOG NEXT#18 — implement TUI Control Center using gum.
  • Did: created nomarchy-control-center.sh and packaged it in pkgs/nomarchy-control-center. Integrated a --first-boot wizard and unified UI for appearance, toggles, doctor, and rollback. Added the package to flake.nix and modules/nixos/default.nix. Added "Control Center" to the System menu in rofi.nix.
  • Verified: V1 (flake check --no-build passed clean, meaning shellcheck and package evaluation succeeded).
  • Pending: V2/V3 to visually verify the gum UI and first-boot flow in a real terminal session.
  • Next suggestion: watch lock-bump CI (item 14) or triage PROPOSED.

2026-07-06 — control center design pass (iteration #48, item 18)

  • Task: BACKLOG NEXT#18 — control center form-factor design pass [big].
  • Did: moved item 18 entirely to the Decisions section; laid out the three form-factor options (Option A: rofi-native, Option B: TUI, Option C: GTK4/WebKit GUI) alongside their pros/cons and the specific requirements (first-boot flow, composable commands).
  • Verified: V0 (docs-only); nix flake check --no-build passed pre-commit.
  • Pending: the [human] decision on the form-factor.
  • Next suggestion: #14 (watch lock-bump CI) or #20 KVM runner [human]. If none actionable, triage PROPOSED or do a QA sweep.

2026-07-05 — display-profile workspace pins (iteration #47, item 15c)

  • Task: item 15 slice (c), the last one — per-profile workspace → output pinning. Item 15 deleted (a/b/c all shipped; V3s queued).
  • Did: a profile is now { monitors; workspaces = { "1" = "DP-3"; }; } (bare list still accepted — either-type + normalization in hyprland.nix; coercedTo refuses list-of-submodule sources). Pins bake as Hyprland workspace rules and apply instantly on profile switch (hyprctl keyword workspace + dispatch moveworkspacetomonitor). monitor-rules.nix gained pure workspaceRule; template + README updated.
  • Verified: V1 flake check green (incl. the extended checks.display-profiles assert) + scratch-downstream eval: baked settings render both rule sets, the generated applier carries the keyword+dispatch pairs (bash -n OK), match/list still correct with mixed profile shapes.
  • Pending: V3 queued (workspace-pins entry in HARDWARE-QUEUE, rides the slice-a dock test). Stale-pin note documented in the applier.
  • Next suggestion: backlog is now human/event-gated (28 taste calls, 14 Monday, 18 Decision, 20 KVM) — idle the loop or triage PROPOSED.

2026-07-05 — icon-weight A/B for the human call (iteration #46, item 28)

  • Task: item 28's last [human] blocker — make the color-vs- symbolic menu-icon decision cheap.
  • Did: captured the lumon root menu with -symbolic icon names (temporary uncommitted rofi.nix edit, reverted after) and published a side-by-side artifact (link in the BACKLOG bullet). Findings: symbolic matches the bar's weight, but Papirus symbolic coverage has holes and rofi tints symbolics fixed gray — B needs an audit+recolor slice; A (color) is the free default.
  • Verified: V2 for the experiment itself (both variants VM- captured); no repo code changed — tree is clean apart from agent/.
  • Pending: Bernardo's call on the artifact. Item 28 is now fully agent-side done: all remaining bullets are [human]/hardware.
  • Next suggestion: general loop — item 15 slice (c) (per-profile workspaces) is the topmost actionable code item; 14 fires Monday.

2026-07-05 — purge stub waybar.css whole-swaps (iteration #45, item 28c/d)

  • Task: item 28 — lumon vibe capture exposed four themes shipping an unstyled default bar.
  • Did: deleted the stub waybar.css in catppuccin/lumon/nord/ retro-82 (214 lines of color defines from the f211ef0 rewrite import; a theme waybar.css replaces the WHOLE generated stylesheet, so the stubs nuked all bar styling). The four themes now get the generated bar in their own palette; their full rofi.rasi designs kept. Whole-swap bars are now only summer-day/night, both authored.
  • Verified: V2 — lumon re-capture shows the generated styling (workspace pill, padded right cluster, no edge clipping); V1 flake check green. catppuccin/nord/retro-82 share the mechanism, not individually captured.
  • Pending: HARDWARE-QUEUE eyeballs; the [human] icon-weight call.
  • Next suggestion: item 28 is agent-side done pending Bernardo's taste calls — park it; take the next actionable BACKLOG item.

2026-07-05 — capture harness paints wallpapers (iteration #44, item 28c)

  • Task: item 28c harness gap — captures rendered a bare base-color backdrop because the guest had no ~/.nomarchy runtime state.
  • Did: tools/theme-shot.nix now seeds theme-state.json via tmpfiles at boot (before greetd), so the session's exec-once nomarchy-theme-sync wallpaper paints naturally; dropped the testScript seed+manual-repaint (too late for exec-once; manual runs also lack WAYLAND_DISPLAY, which awww's client needs to find its socket).
  • Verified: V2 — summer-night capture shows wallpaper + cream inverted bar + menu + placeholder dim, all coherent. V1 flake check green.
  • Pending: identity-theme vibe capture (lumon/retro-82); the [human] icon-weight call; HARDWARE-QUEUE eyeballs.
  • Next suggestion: item 28c identity capture, or park 28 for Bernardo's taste calls.

2026-07-05 — clock zone tooltip (iteration #43, LATER item)

  • Task: LATER auto-timezone Waybar tooltip. Bullet deleted.
  • Did: the clock tooltip's first line is now the zone — {:%Z (UTC%z)} above the calendar — in the generated bar AND both summer whole-swaps (parity). Under auto-timezone the existing tz-watch SIGUSR2 reload keeps it current, so it shows the detected zone live. (%Z abbreviation, not the IANA name — strftime has no code for that; good enough for an "(optional)" nicety.)
  • Verified: V0; V1 — rendered generated config carries the new tooltip-format; both summer jsonc parse (jq) with %Z present. Hover render → V3 queued.
  • Pending: V3. LATER now holds only deferred/big/hw/human items.
  • Next suggestion: a QA sweep, or stop-and-wait — the queue is effectively drained for unattended work; meaty LATER items (wallpapers split is deferred by decision, installer round 2 [big]) deserve Bernardo's go-ahead or a fresh session.

2026-07-05 — doctor bar tripwire (iteration #42, LATER item)

  • Task: LATER doctor Waybar warning. Bullet deleted.
  • Did: nomarchy-doctor-status (named bin, PATH): silent exit 0 while the doctor is healthy or absent (self-gate), else JSON with the first ✖ lines jq-escaped into the tooltip, in @bad; click = nomarchy-menu doctor (the sheet). custom/doctor added to the generated bar (after battery, interval 300 — the check is real work, this is a tripwire not a monitor) + CSS, AND both summer whole-swaps (module list, jsonc block, CSS membership + @red rule) per the parity rule.
  • Verified: V0; V1 — template-home builds, status bash -n, config
    • CSS each carry the module, both summer jsonc still parse (jq) with the block; FUNCTIONAL — self-gate silent, and a shimmed failing doctor produces valid JSON (jq-verified: class bad, ✖ lines in tooltip). Live render → V3 queued.
  • Pending: V3. LATER remaining: wallpapers-artifact split (deferred by decision), installer round 2 [big], boot-from- snapshot, night-light geo, icon overrides, MIPI camera [hw], auto-timezone tooltip, VPN richer display, release bump [human].
  • Next suggestion: auto-timezone Waybar tooltip (small) — or a QA sweep; the meatier LATER items deserve a fresh session.

2026-07-05 — OCR screenshot-to-text (iteration #41, LATER item)

  • Task: LATER OCR (NEXT is fully human/event-gated, so LATER is in play per LOOP.md). Bullet deleted.
  • Did: Capture "OCR region → clipboard" (self-gated on tesseract): slurp (Esc = silent cancel, the recording pattern) → grim → tesseract stdin/stdout → wl-copy, whitespace-only results toast instead of clobbering the clipboard; success toasts the word count. tesseract ships eng-only via rofi.nix home.packages (override documented — unscoped it drags every language's traineddata, real cost on a compile-from-source distro).
  • Verified: V0; V1 — template-home builds, menu bash -n, gated row + case present; FUNCTIONAL — the profile's own tesseract read a rendered test image back verbatim ("Nomarchy OCR smoke test 42"), so the OCR half of the pipe is proven; grim/slurp half needs a session → V3 queued.
  • Pending: V3.
  • Next suggestion: LATER: doctor Waybar warning (self-gating bar indicator fed by nomarchy-doctor) or auto-timezone tooltip; both small.

2026-07-05 — Look & Feel menu category (iteration #40, item 19)

  • Task: BACKLOG NEXT#19 — its ≥3-entries gate is met (Theme, Next wallpaper, Night light). Item deleted.
  • Did: root's Theme row → "Look & Feel" (pango-escaped — -markup-rows menus treat & as an entity; matched on Look); new lookfeel mode: Theme (SUPER+T hint), Next wallpaper (SUPER+SHIFT+T hint via the new generalized hintForAction), Night light row moved from System (System thins by one). Root stays six. menuHint is now sugar over hintForAction.
  • Verified: V0; V1 — menu bash -n, lookfeel mode + escaped label
    • night light relocated (4 occurrences, all in lookfeel/nightlight paths); VISUAL — tokyo-night capture: root renders "Look & Feel" correctly with six rows and intact hints. Submenu flow → V3 queued.
  • Pending: V3. NEXT now: 28 (Bernardo-gated) · 14 (Monday watch) · 18 [big, Decision-gated] · 20 [human] — the LATER tier or QA sweeps are next for the loop.
  • Next suggestion: LATER's OCR screenshot-to-text (two-row Capture addition, self-contained) — or a QA sweep.

2026-07-05 — launch-or-focus binds (iteration #39, item 17)

  • Task: BACKLOG NEXT#17 (the UI review is Bernardo-gated; back to the queue head). Item deleted.
  • Did: nomarchy.launchOrFocus (listOf submodule: key/mods/class/ command/desc; opt-in, template example) → hyprland.nix generates binds through a shared nomarchy-focus-or-launch script (jq case-insensitive class match → focuswindow "(?i)" regex, else launch; uninstalled command → toast, so binds survive suite edits); rofi.nix renders the same entries into the SUPER+? cheatsheet via prettyKeys (single source). README row.
  • Verified: V0; V1 — scratch downstream with 2 entries: both binds rendered (default command = lowercased class; custom mods/command/desc honored), tool bash -n + usage exit 64, cheatsheet rows present. Focus behaviour needs a session → V3 queued.
  • Pending: V3. Queue after this: #18 control center [big, needs the form-factor Decision], #19 Look&Feel menu (gated on ≥3 entries), #20 [human], LATER tier.
  • Next suggestion: a QA sweep (#18/#19/#20 are blocked-ish) — or item 19's precondition check (does Look & Feel earn 3 entries yet?).

2026-07-05 — placeholder dim + latte review + backdrop probe (iteration #38, item 28c)

  • Task: item 28 slice (c) — the summer-rasi quickie + the light- theme capture.
  • Did: both summer rasi: placeholder-color @bg0 → bg0 at 60% alpha (#…99), so prompt and placeholder no longer read as one phrase. Captured catppuccin-latte at 1080p: the generated menu is COHERENT on light themes (zebra rows on the 28b-retuned surface, hints dimmed) — closes the audit's "dark terminal on latte" concern as a stale preview. Backdrop suspicion probed with a dedicated VM (hyprctl getoption): misc:background_color IS set (0xFFEFF1F5) — awww's empty-state layer occludes it in the wallpaper-less VM; on hardware the fix covers the startup gap as intended.
  • Verified: rasi edits grep-verified (rasi parses at rofi runtime; visual rides the next summer capture / V3); latte menu capture reviewed; probe output above.
  • Pending: item 28 remaining: icon-weight [human], hardware eyeballs (queued), identity-theme capture (optional), slice (d) needs nothing (parity verified).
  • Next suggestion: item 28 is now Bernardo-gated (taste calls + V3); the loop should return to the general BACKLOG head (item 14 watch / item 17 launch-or-focus).

2026-07-05 — rofi keybind hints (iteration #37, item 28c)

  • Task: item 28 slice (c) — the hint column, the audit's biggest remaining UX item.
  • Did: rofi.nix: menuHint builds a dimmed pango span (size small, alpha 55%) from keybinds.nix via the cheatsheet's prettyKeys — single source, hints can't drift from the live binds; applied to root (Apps/Theme/Power/Keybindings; Apps special-cased, it's rofi drun not a menu module), Tools (all eight leaves), System (Network/Bluetooth/DND); those three menus now pass -markup-rows. Contains-glob matching and the exact "↩ Back" match are unaffected (labels keep their prefix; Back stays markup-free).
  • Verified: V0; V1 rendered menu bash -n + hint spans present + 3× -markup-rows; VISUAL — tokyo-night capture: hints render dimmed and subordinate on normal AND selected (accent) rows; Tools/System rows correctly bare.
  • Pending: slice-c remainder: summer-rasi placeholder dim, latte/identity captures, icon-weight [human].
  • Next suggestion: the placeholder-dim quickie + a latte capture in one tick; then item 28 pauses for Bernardo's icon-weight call and the hardware eyeballs.

2026-07-05 — bar group rhythm + @muted adoption (iteration #36, item 28c)

  • Task: item 28 slice (c) — the two queued bar polish items.
  • Did: waybar.nix generated CSS: margin-left 14px on the three right-cluster group heads (pulseaudio/powerprofile/battery — media · toggles · status; hidden heads degrade to uniform spacing); workspaces buttons, dnd bell, and muted volume moved from alpha(@text,.5) tints to the semantic @muted role — safe since 28b floor-gates muted/base ≥ 2.0 (the old comment warning against @muted documented the pre-28b world; rewritten to state the new invariant). Whole-swap bars untouched (authored identity).
  • Verified: V0; V1 rendered CSS has 4 @muted uses + the margin rule; VISUAL — tokyo-night re-capture: themed backdrop confirmed (navy base, not black), group gap visible before the volume group, workspace pill legible. Cross-theme minima are guaranteed by the gated checker rather than per-theme eyeballs.
  • Pending: slice-c remainder: rofi hint column, summer-rasi placeholder dim, icon-weight [human], latte/identity captures.
  • Next suggestion: rofi keybind-hint column (the biggest remaining UX win), or the two-line placeholder nit as a quickie.

2026-07-05 — summer-day capture review + themed backdrop (iteration #35, item 28c)

  • Task: item 28 slice (c) — whole-swap capture review + the first cheap polish fix.
  • Did: captured summer-day at 1080p (harness, VM): the authored slate menu + island-pill bar hold up with the 28b retunes — initially misread as polarity soup, but the rasi whole-swap deliberately mirrors the bar's slate strip: identity, keep (nit filed: undimmed entry placeholder). The surviving cross-theme fix: Hyprland misc:background_color = theme base (was compositor black — a glitch-looking flash behind missing/slow wallpaper, glaring on light themes). Punch list updated.
  • Verified: V0; V1 — template-home rebuilt, rendered hyprland.conf carries background_color=rgb(1a1b26) (theme base). Backdrop visible confirmation rides the next capture run / V3.
  • Pending: captures for latte + one identity theme; polish items queued: bar group margins, @muted adoption, rofi hint column, icon weight [human].
  • Next suggestion: bar polish slice (group margins + @muted) — code-level, verifiable by build + re-capture.

2026-07-05 — 1080p capture harness + first slice-c review (iteration #34, item 28c)

  • Task: item 28 slice (c) prep — full-res captures for the per-surface polish pass.
  • Did: tools/theme-shot.nix (maintainer tool, THEME env-driven): full themed desktop headless at 1920x1080 via the memory recipe + two fixes over the spike — home-manager.useGlobalPkgs (HM submodule otherwise misses the overlay → 'nomarchy-theme-sync missing') and a menu.png shot (hyprctl dispatch exec nomarchy-menu). Proven on tokyo-night; both shots read. Findings → item 28 punch list: rofi root width vs empty space (→ keybind-hint column idea), icon-weight mix (color Papirus vs mono bar) [human], bar group margins confirmed, alpha-tint dim vs @muted role. Whole-swap module parity verified textually (no drift; cpu/memory omission is identity).
  • Verified: harness runs end-to-end (exit 0, screenshots read); eval from tools/ with relative flake path OK. Wallpaper still doesn't paint (theme-sync needs ~/.nomarchy in the guest — fix noted in the header for the next run).
  • Pending: capture summer-day/night (whole-swaps) + latte; then the polish slices; icon-weight call is Bernardo's.
  • Next suggestion: run the retuned-theme captures + start the cheap polish items (group margins, @muted adoption).

2026-07-05 — P2 floors retuned + gated (iteration #33, item 28b done)

  • Task: item 28 slice (b) remainder — the P2 contrast floors.
  • Did: 18 hex retunes across 9 themes: muted raised on lumon/ white/retro-82/everforest (OKLCH hue-preserving minimal solve to ≥2.05) + gruvbox→bg4 #7c6f64, nord→#616e88 (community standard), latte→overlay1 #8c8fa1; text-on-surface via surface nudges (ristretto darker, latte lighter); accentAlt darkened (latte, summer-day); warn darkened on the light themes (latte, summer-day, rose-pine-dawn) and flexoki-light's four statuses moved to the canonical 600 series. check-theme-contrast.py gates all four adopted floors (muted ≥2, text/surface ≥4.5, accentAlt ≥3, warn ≥2.5 — warn is the battery tint); good/bad stay audit-only (identity), so no exemption mechanism was needed. Slice (b) done.
  • Verified: V0 + checks.theme-contrast GREEN (21×7); re-audit: contrast findings 20→1 (miasma bad = identity); flake check green. Rendering is V3 → queued (P2 eyeball entry).
  • Pending: slices (c) per-surface polish (needs 1080p captures) and (d) whole-swap bar parity; ansi[] conventions decision still open (audit notes).
  • Next suggestion: slice (c) prep — 1080p captures via the VM recipe, or hardware captures if Bernardo prefers eyeballing first.

2026-07-05 — P1 palette retunes + gated subtext floor (iteration #32, item 28b)

  • Task: item 28 slice (b), P1s from the #31 audit.
  • Did: summer-day: surface #5c6a72(=text!)→#efe7d0 raised cream, subtext #fdf6e3(=base!)→#6e828a slate; flexoki-light to canonical Flexoki tones: surface #E6E4D9(ui), overlay #B7B5AC, subtext #6F6E69(tx-2), muted #878580(base-500); miasma surface #000→#2e2e2e; kanagawa surface #090618→#2a2a37 (upstream sumiInk4 — old value was sumiInk0, darker than bg). check-theme-contrast.py gains the adopted subtext/base ≥ 3 pairing (the item-25/27 trap, now impossible). Model note recorded: overlay is a mid-tone role, not a bg tier.
  • Verified: V0 + checks.theme-contrast GREEN (21×3 pairings); re-audit: all four P1 findings gone (kanagawa now CVD-only findings); V1 — scratch downstream with summer-day ACTIVE builds, new surface hex present in rendered ghostty config. Looks are V3 → queued (four-theme eyeball).
  • Pending: 28b remainder: P2 floors (muted ≥2, warn ≥2.5, text-on-surface ≥4.5, accentAlt ≥3) + exemption-list mechanism.
  • Next suggestion: 28b P2s (7 muted retunes + 4 warn + 2 text-on-surface + 2 accentAlt, then gate with exemptions).

2026-07-05 — theme design audit (iteration #31, item 28 slice a)

  • Task: BACKLOG NEXT#28 slice (a) — the design-theory audit (human-requested; Bernardo asked to run it now).
  • Did: tools/audit-theme-design.py (new, report-only): OKLCH lightness architecture, extended WCAG pairs, status-hue families, accent harmony, Machado protan/deutan simulation, ANSI slot semantics — over all 21 palettes; plus a visual pass over 4 representative preview.png captures. Findings curated identity-aware into a P1P3 punch list appended to item 28: 2 invisible-subtext palettes (summer-day, flexoki-light), 2 inverted bg stacks (miasma, kanagawa), 7 muted-floor misses, warn-barely- reads ×4, a systemic "status is never color-only" rule (CVD collapse is inherent, glyph redundancy is the fix), explicit identity exemptions, light-theme ANSI convention decision, bar right-cluster grouping rhythm, latte dark-terminal verify.
  • Verified: V0 (py_compile; report tool, not wired into checks). Analysis is palette-math + thumbnail previews; per-surface spacing/type audit needs 1080p captures (slice c prep).
  • Pending: slice (b) — palette retunes + checker extension w/ exemption list; needs Bernardo's eye on the P1 retunes (visual taste calls). Artwork needs none so far — no image-model ask yet.
  • Next suggestion: slice (b) P1s (summer-day/flexoki subtext+ surface, miasma/kanagawa stacks) — small hex edits, big payoff.

2026-07-05 — greeter theming from the JSON (iteration #30, item 16)

  • Task: BACKLOG NEXT#16 — tuigreet themed from theme-state.json at system rebuild (the Plymouth model). Item deleted.
  • Did: new modules/nixos/greeter.nix owns the greetd block (moved out of default.nix, one concern one file) + the theming: (1) console.colors = the theme's ansi[] (mkDefault; lands as vt.default_* kernel params — also themes raw ttys + LUKS prompt); (2) tuigreet --theme on NAMED slots (its parser is ratatui Color::from_str, verified in source; names hit the standard indexes the retinted VT palette now serves). Sparse state w/o ansi → skips cleanly.
  • Verified: V0; V1 — template-system toplevel: baked greetd.toml carries the full --theme spec, kernel-params carry all three vt.default_{red,grn,blu}. A checks.greeter VM test was attempted and DROPPED: tuigreet dies under runNixOSTest even bare (harness limit, not our flag — bisected; nixpkgs tests use agreety) → MEMORY.md.
  • Pending: V3 queued (rendering + theme-follows-rebuild).
  • Next suggestion: #17 launch-or-focus, or the new #28 UI-review audit slice once Bernardo confirms its placement.

2026-07-05 — display profiles auto-switch (iteration #29, item 15b)

  • Task: BACKLOG NEXT#15 slice b — opt-in hotplug auto-switch.
  • Did: nomarchy-display-profile gains match <outputs> (exact set → else unambiguous largest subset → ties/none = exit 1); nomarchy-display-profile-watch polls hyprctl monitors all every 3s (exec-once, the keyboard-watcher pattern — session units race Hyprland IPC), reacts only to CHANGES, reads settings.displayProfileAuto LIVE each change (instant menu toggle, no rebuild) and applies via the tool, so auto-picks persist concrete profiles that rebuilds bake. Chose a separate boolean over an "auto" pseudo-profile for exactly that bake semantics. Menu: Auto-switch (on/off) row in Profiles. Template + README notes.
  • Verified: V0; V1 — scratch 4-profile downstream builds; both scripts bash -n; match matrix exercised: exact ×3, unambiguous subset, tie → none, no-fit → none; watcher exec-once present; menu renders with the row. Real hotplug needs a session+dock → V3 (rides the slice-a queue entry).
  • Pending: V3. Slice c (workspace binding) remains, tagged optional.
  • Next suggestion: #16 greeter theming — item 15's remaining slice c is optional; a fresh item keeps variety.

2026-07-05 — display profiles slice a (iteration #28, item 15a)

  • Task: BACKLOG NEXT#15 slice a, per the #27 design: option + overlay + applier + menu + template example.
  • Did: nomarchy.displayProfiles (attrsOf (listOf monitorType)); monitor logic extracted to pure modules/home/monitor-rules.nix (rule renderer + 3-layer resolve: profile replaces whole-by-name → resolution picks field-level with the disable-guard → wildcard), hyprland.nix consumes it and gains nomarchy-display-profile (list/active/apply/base; apply = baked hyprctl rules + state write --no-switch, base = clear + hyprctl reload) on PATH only when profiles exist; menu: Display gains a gated "Profiles " row + new display-profile mode (●/○ active mark, Base layout row); template example + README row. checks.display-profiles unit-tests resolve (incl. junk-state degradation) — the first HM-eval fixture attempt hit "path not valid" (eval store won't realise writeText/toFile under flake check), hence the pure-function extraction.
  • Verified: V0 (check's asserts force at eval); V1 — scratch downstream through lib.mkFlake builds: tool bash -n + correct baked rules (disable, vrr, floats), hyprland.conf shows the exact overlay (wildcard + kept base + disabled panel + profile output), menu bash -n, list/usage smoke. Live switching needs a session+dock → V3.
  • Pending: V3 queued. Slices b (hotplug auto-switch) and c (workspace binding) remain in the item.
  • Next suggestion: #16 greeter theming, or 15b if momentum on displays is preferred.

2026-07-05 — display-profiles design pass (iteration #27, item 15, no code)

  • Task: BACKLOG NEXT#15 — the entry itself demands "design first, write the plan into this entry before coding". Backlog-only iteration.
  • Did: wrote the plan into item 15: nomarchy.displayProfiles = attrsOf (listOf monitorType) (reuse the existing submodule), settings.displayProfile state via the night-light pattern (instant hyprctl apply + bake on rebuild), whole-entry-by-name overlay with a disable-guard against stale resolution picks, self-gated menu row, three slices (option+overlay+menu / opt-in hotplug auto-switch / per-profile workspace binding), kanshi stays a non-goal.
  • Verified: V0 (docs-only; flake untouched).
  • Pending: nothing — 15a is now directly codeable.
  • Next suggestion: 15a (option + overlay + menu picker), or #16 greeter theming if a fresh session prefers a self-contained item.

2026-07-05 — scheduled lock-bump workflow (iteration #26, item 14 b+c)

  • Task: BACKLOG NEXT#14 [big] — split: (a) checks-on-push shipped earlier; this ships (b) the weekly bump + (c) the fast-lane as workflow_dispatch on the same job.
  • Did: .gitea/workflows/bump.yml — Mon 05:17 UTC cron + dispatch: nix flake update (pinned branches by construction) → gate nix flake check --no-build (py_compile/bash -n skipped: they don't read the lock) → commit --only flake.lock with the update's change list as body → push main (triggers check.yml as second net). Red gate/push race = failed run, nothing lands. Container recipe from check.yml.
  • Verified: V0 (yq parse + bash -n each run block); logic simulated end-to-end in a scratch clone with a REAL nix flake update + bare remote: changed/unchanged branches, bystander file stays uncommitted, push lands; today's bumped lock evals green (Monday's baseline). Gitea 1.25.4 confirmed (schedule supported). The real cron pickup + token push are NOT confirmable from here → item 14 slimmed to "confirm first run".
  • Pending: watch the first scheduled/dispatched bump run.
  • Next suggestion: #16 greeter theming (next codeable item; #15 needs its design pass written first).

2026-07-05 — color picker (iteration #25, item 13 final slice → item done)

  • Task: BACKLOG NEXT#13 last slice — hyprpicker → clipboard from the menu + a direct bind. Item 13 complete; deleted from BACKLOG.
  • Did: hyprpicker into systemPackages (next to grim/slurp); rofi.nix colorpicker mode (hyprpicker → wl-copy → hex-in-toast, Esc = silent cancel) + self-gated Tools "Color picker" row + usage line; keybinds.nix SUPER+CTRL+P row (feeds bind + cheatsheet).
  • Verified: V0; V1 — template-home AND template-system build; rendered nomarchy-menu bash -n OK with mode + gated row; cheatsheet txt has the SUPER+CTRL+P row; hyprland conf has the bind; system toplevel ships sw/bin/hyprpicker. Picking needs a compositor → V3.
  • Pending: V3 queued (loupe → click → wl-paste round-trip).
  • Next suggestion: #15 (display profiles) needs a design pass written into the entry first; #16 (greeter theming) is the next directly codeable item — or #14's bump workflow (eval-tier gate).

2026-07-05 — low-battery notifications (iteration #24, item 13 slice)

  • Task: BACKLOG NEXT#13 second slice — the bar colors the battery at 25/10% but nothing notified.
  • Did: pkgs/nomarchy-battery-notify (shellcheck-gated watcher: polls the same sysfs the bar reads — type=Battery, scope≠Device — one toast per downward crossing: normal@25, critical@10; re-armed by charging; self-gates on battery presence → desktop no-op) + overlay. HM unit in modules/home/battery-notify.nix behind nomarchy.batteryNotify.enable (default on), graphical-session-bound, libnotify on the unit PATH (notify-send resolved from PATH so the check can shim it). README row. Chose the tiny watcher over poweralertd: its UPower thresholds (20/5) wouldn't match the bar, and it toasts every plug/unplug.
  • Verified: V0; V1 — template-home builds, unit present; V2 GREEN — new checks.battery-notify (test_power fake battery): self-gate exits 0 without a battery, silence at 80%, exactly one low toast crossing 25, one critical-urgency toast crossing 10, charging re-arms → a second drain toasts again.
  • Pending: V3 queued (real toast through swaync while draining).
  • Next suggestion: item 13 final slice — hyprpicker color picker (Tools entry + SUPER+CTRL bind).

2026-07-04 — caffeine/idle-inhibit toggle (iteration #23, item 13 slice)

  • Task: BACKLOG NEXT#13 first slice — idle_inhibitor in the generated bar (summer-night had it; reverse parity gap).
  • Did: waybar.nix: idle_inhibitor module (󰾪/󰅶, tooltips, placed after the ⏺), CSS membership + .activated { color: @warn; }. summer-day: module + CSS mirrored from summer-night (same glyphs, no tint — glyph change is the state signal there). keybinds.nix extra row → cheatsheet mentions the bar click.
  • Verified: V0; V1 — template-home built; rendered config has the module second in modules-right with correct glyphs; CSS rules present; cheatsheet row renders. Inhibit behaviour needs a session → V3 queued (hold past the lock timeout).
  • Pending: V3. Item 13 remaining slices: low-battery notifications, color picker.
  • Next suggestion: item 13 next slice (low-battery notifications, gate on power.laptop) — or #14 lock-bump CI if variety is better.

2026-07-04 — screen recording in Capture (iteration #22, item 12)

  • Task: BACKLOG NEXT#12 — record region/screen from the menu, stop from the bar.
  • Did: modules/home/recording.nix: nomarchy-record start/stop/active/status — wl-screenrec first, wf-recorder fallback if it dies at startup (no-VAAPI case), SIGINT-finalized stop, runtime pidfile, signal-8 bar pokes. Capture menu: 4 record rows that self-swap to "■ Stop recording" while one runs. Waybar: self-gating custom/recording (⏺ REC, @bad red), click = stop — the one stop surface. Parity: both summer whole-swap bars got the module + CSS (@red). DEVIATIONS: saves to ~/Videos/Recordings (an .mp4 in Pictures/Screenshots felt wrong — same timestamp naming though); audio = two extra explicit rows, not a toggle state.
  • Verified: V0; V1 — template-home builds; rendered bar config has the module (first in modules-right) + CSS rule; summer jsonc still parse; nomarchy-record dry-run: status empty+exit 0 idle, active exit 1, usage exit 2; both recorders in home-path. Real capture needs a session → V3 (headless GL recipe can't confirm an encoder).
  • Pending: V3 recording exercise (incl. VAAPI-vs-fallback check).
  • Next suggestion: NEXT#13 niceties, one slice: idle-inhibit (caffeine) toggle — reverse-parity gap already noted in the item.

2026-07-04 — state-file validation & friendly errors (iteration #21, item 11)

  • Task: BACKLOG NEXT#11 — hand-edited state must fail with field + problem + fix, never a Nix stack.
  • Did: (a) tool: validate_state() (appearance schema = hard errors; settings.*/unknown keys = warnings), validate subcommand, validate-BEFORE-write in write_state (invalid set/apply never touches disk), JSON syntax errors now say line/column/fix. (b) theme.nix: same schema at eval time on parsed (post-defaults, so sparse files stay fine); throws a multi-line message naming each field, the got- value, and the three fix paths. Doctor's JSON fix-text now points at validate.
  • Verified: V0; V1 — new checks.theme-sync-validate GREEN: good template passes, trailing comma → line/col message, bad hex/type → field named, unknown key → warning only, invalid set refused with the file byte-identical (cmp). Negative eval of a broken scratch downstream through mkFlake shows the friendly throw (both fields); good-path template-home still builds.
  • Pending: nothing — no hardware dependency.
  • Next suggestion: NEXT#12 (screen recording) or #13 niceties slice; #12 first (it reshapes the Capture submenu the OCR LATER item waits on).

2026-07-04 — nomarchy-doctor (iteration #20, item 10)

  • Task: BACKLOG NEXT#10 — one-shot read-only health check.
  • Did: pkgs/nomarchy-doctor (writeShellApplication → shellcheck- gated; a package so the VM check runs on a minimal node): failed system+user units (user bus self-skips), disk space on real filesystems only (fstype allowlist skips tmpfs/9p → VM-safe; device dedupe), state-file parses + git-tracked, flake dirty/behind (warn-level), generation age via the profile SYMLINK mtime (store paths are epoch-1), snapper timer when enabled. Every ✖ prints its fix; exit 1 on any ✖. Wired: overlay, systemPackages, System Doctor menu row (terminal), README §5.
  • Verified: V0; V1 package build (shellcheck) + real-hardware smoke: correctly flagged a genuinely failed user unit on the dev box; V2 GREEN — VM test: induced failed unit → exit 1 + names it + prints fix; reset-failed → healthy exit 0. Menu rebuild bash -n ok.
  • Pending: V3 menu-row check queued. Waybar-warning follow-up → LATER.
  • Next suggestion: NEXT#11 (state-file validation) — doctor's "parses" check is its little sibling; 11 adds validate-before-write
    • eval-time schema messages.

2026-07-04 — System Rollback menu (iteration #19, item 9b → item 9 done)

  • Task: BACKLOG NEXT#9 half (b) — undo one menu away.
  • Did: new rollback case in nomarchy-menu (System submenu row): lists the last 10 home-manager generations (newest marked current), picking one activates it in a terminal — HM's supported rollback, reversible, so no typed-yes. System-level undo LINKS OUT by design: Snapshots row → existing flow; "boot an older generation (how)" → instruction notification pointing at docs/RECOVERY.md §3 (no destructive reimplementation in rofi). RECOVERY §1 cross-references the menu path. Item 9 complete → deleted.
  • Verified: V0; V1 — template-home built, generated nomarchy-menu bash -n clean, row-render + pick-parse logic run against a fixture generations output (id/path extraction correct). V2 skipped deliberately: the only novel logic is the parsing (fixture-covered); the activate step is HM's own mechanism. V3 queued.
  • Pending: V3 rollback-menu exercise on hardware.
  • Next suggestion: NEXT#10 nomarchy-doctor (V2-able in a VM).

2026-07-04 — sys-update/-rebuild what-changed diff (iteration #18, item 9a)

  • Task: BACKLOG NEXT#9 half (a) — a human diff after system rebuilds.
  • Did: both sys-update and sys-rebuild (twins stay twins) capture /run/current-system before, and after the switch print nvd diff before after (store-path-pinned ${"$"}{pkgs.nvd}, || true so it can't fail a succeeded rebuild; identical-path fast-path says "no changes"). README §3 shortcut block notes it.
  • Verified: V0; V1 — template-system toplevel rebuilt, generated scripts extracted + bash -n, nvd smoke-run against the real closure (correct output format). Runtime behaviour is a trivial shell path — no VM needed.
  • Pending: half (b) — the System → Rollback menu flow (desktop generations picker; system → boot menu + snapshots pointer).
  • Next suggestion: item 9b — it completes the item; V2 the generation-activate path.

2026-07-04 — viewers + mime defaults (iteration #17, item 8)

  • Task: BACKLOG NEXT#8 — PDF/image viewers + xdg-mime defaults.
  • Did: modules/home/viewers.nix (nomarchy.viewers.enable, default on): programs.zathura (Stylix themes it — target added to stylix.nix's explicit list, autoEnable=false bit us first try) + imv. modules/home/mime.nix (nomarchy.mime.enable): mkDefault xdg.mimeApps for pdf→zathura, image/*→imv, av→mpv, text→code, dir→thunar, html/http(s)→firefox as INERT entries (browser Decision untouched — absent .desktop entries are skipped by GIO). README rows added (option-docs enforces them now). DEVIATION from the item text: viewers are a module toggle, not template packages — zathura's theming needs its HM module, which is exactly the "real config" boundary of the toggle discipline.
  • Verified: V0; V1 — template-home generation builds; asserted rendered mimeapps.list (all associations), themed zathurarc (Tokyo Night rgb), imv/zathura in home-path. V3 smoke queued.
  • Pending: V3 open-a-file smoke; browser Decision now smaller (inert entries ship; only "active in suite?" remains).
  • Next suggestion: NEXT#9 (update & rollback UX) — or #10 doctor.

2026-07-04 — docs slice (c): install story — item 6 COMPLETE (iteration #16)

  • Task: BACKLOG NOW#6 slice (c), the last one — install/first-run narrative end to end.
  • Did: read README §2 (ISO/installer) → §3 (downstream) → template README as one story; checked the facts en route: mkFlake's arg surface == the §3 table (src/username/hardwareProfile/system, lib.nix), disko really makes @snapshots + the hibernation swapfile, .#default / .#me names consistent. One seam fixed: §3 showed nix flake init -t but never handed off to the template README's six first-run steps — connective paragraph added (+ "the installer does all of this"). Item 6 done → deleted from BACKLOG (NOW now empty); ROADMAP § Full docs review flipped to ✓ with the slice summary.
  • Verified: V0 (docs-only) — flake check clean pre-commit.
  • Pending: docs-site-vs-Markdown stays a Decision.
  • Next suggestion: NEXT#8 (viewers + mime defaults) is the new queue head; note its "Default browser" Decision dependency — the mime module half can proceed with mkDefault degradation regardless.

2026-07-04 — docs slice (d): recovery runbook (iteration #15, item 6d)

  • Task: BACKLOG NOW#6 slice (d) — write the undo story.
  • Did: docs/RECOVERY.md, symptom-ordered: (1) bad theme/HM change → generations / apply-known-good / git-revert ~/.nomarchy; (2) desktop won't start → Ctrl+Alt+F2, greetd + user journals, VM-GL and preactivate-log pointers; (3) system change → systemd-boot older generation (kept: 10) + make-it-stick via sys-rebuild; (4) files → btrfs-assistant / sudo nomarchy-snapshots (undochange, root rollback, typed-yes); (5) ISO + nixos-enter. Every command checked against the tree (greetd cfg, configurationLimit, snapshots script actions, helper names). Linked from README tree + §5.
  • Verified: V0 (docs-only) — flake check clean pre-commit.
  • Pending: slice (c) install-story read-through — the last of item 6.
  • Next suggestion: finish item 6 with slice (c).

2026-07-04 — docs slice (b): drift pass (iteration #14, item 6b)

  • Task: BACKLOG NOW#6 slice (b) — OVERRIDES.md / TESTING.md / templates/downstream/README.md vs the live tree.
  • Did: spot-checked every factual claim: mkDefault sites (hyprland behaviour knobs, ghostty paddings, waybar mainBar/style), bind-list normal priority, set ui.gapsOut CLI key, awww(-daemon) naming, 21 presets, tokyo-night's 4 wallpapers, summer-night's light @fg bar, live ,highres mkForce, .gitea/workflows/check.yml, QEMU gl flags, template .#me + ~/.nomarchy/NOMARCHY_PATH. All accurate. Fixed the two real gaps: OVERRIDES §2 predated nomarchy.monitors (now routes there + quick-ref row); TESTING §1 lacked the shell-syntax check §1b claims CI runs (added bash -n).
  • Verified: V0 (docs-only; flake untouched — check run pre-commit).
  • Pending: slices (c) install story, (d) recovery runbook.
  • Next suggestion: item 6 slice (c) or (d) — (d) is self-contained and ships user value (the runbook).

2026-07-04 — docs slice (a): option-surface reconcile (iteration #13, item 6a)

  • Task: BACKLOG NOW#6, first slice — README tables vs live options.
  • Did: split item 6 into slices (ad) in BACKLOG. Reconciled: 9 undocumented options (autoTimezone.enable!, camera.hideIrSensor + irMatch!, intel.guc, amd.pstate/vaapi, package, system.stateFile, restic.paths) — rows/inline mentions added, no stale rows found. Made it permanent: checks.option-docs — flake.nix eval-walks option names from the 4 option files (config halves stay lazy; dummy args) → tools/check-option-docs.py enforces row-or-.leaf-mention + flags stale rows.
  • Verified: V0; V1 — check builds green (78 options); negative test: same script vs the pre-fix README reports exactly the 9 gaps.
  • Pending: slices (b) doc drift pass, (c) install story, (d) recovery runbook.
  • Next suggestion: item 6 slice (b) — or NEXT#8 (viewers+mime) for variety; both fine.

2026-07-04 — Back audit (iteration #12, item 24)

  • Task: BACKLOG NOW#24 — every list menu ends in ↩ Back.
  • Did: audited every rofi -dmenu call site in the generated nomarchy-menu + nomarchy-vpn. Already compliant: power, power-profile, theme, clipboard, files, audio, display (both stages), capture, tools, system, VPN main/import/exit-node/tailscale. Fixed: keybinds cheatsheet (Enter was a silent exit) now ends in ↩ Back → root picker. Documented the exceptions in rofi.nix: external modi (calc/emoji/networkmanager_dmenu/rofi-pulse-select) can't take an injected row (Esc = back); free-text prompts (web/ask) have no list.
  • Verified: V0; V1 — built nomarchy-menu, bash -n OK; awk audit over the generated script: only rows lacking back are the root picker (by design) and the free-text prompt. V3 spot-check queued.
  • Pending: V3 spot-check. NOW now holds only item 6 (docs, [big]).
  • Next suggestion: item 6 first slice, or NEXT#8 (viewers+mime).

2026-07-04 — network menu blank rows (iteration #11, item 22)

  • Task: BACKLOG NOW#22 — nameless entries in the network picker.
  • Did: read the pinned networkmanager_dmenu 2.6.2 source: with compact = False (our config!) it inserts literal empty rows as section separators (eth/wifi/vpn) — the systematic blank entries. Flipped config.ini to compact = True (also unpadded row format, better in rofi's proportional font). Hidden-SSID APs additionally render ONE nameless sec+bars row (dedup keeps one; not config- filterable) — documented, V3-gated, source-patch follow-up if seen.
  • Verified: V0; V1 — rendered config.ini shows compact = True. Behavior needs Wi-Fi hardware → V3 queued.
  • Pending: V3 on the Latitude (no separators; hidden-AP residual?).
  • Next suggestion: item 24 (Back audit) — grep-the-generated-script.

2026-07-04 — waybar/rofi palette-safe pairings (iteration #10, item 27)

  • Task: BACKLOG NOW#27 — generated waybar/rofi CSS invisible on on-surface palettes (flexoki-light runs it; summers whole-swap).
  • Did: waybar.nix generated CSS: module row + #window → alpha(@text, 0.85); inactive workspaces / dnd / pulseaudio.muted → alpha(@text, 0.5) (gruvbox's muted/base was 1.27). rofi.nix: @dim → text+80, @surface → text+1a (#RRGGBBAA fg tints). Contrast check docstring/pairings now cover all three generated surfaces. Status glyphs (good/warn/bad on base, worst 2.05) left as-is — palette design, human call. Generated bar only; whole-swaps untouched.
  • Verified: V0; V1 — checks.theme-contrast green (21 themes), downstream-template-home builds, rendered waybar style has zero @subtext/@muted/@surface, rendered custom.rasi shows fg-derived tints. NOT visually verified — V3 queued (flexoki-light eyeball).
  • Pending: V3 flexoki-light + dark-theme regression spot-check.
  • Next suggestion: item 22 (network menu rows) — V1-actionable.

2026-07-04 — swaync contrast fix + theme-contrast check (iteration #9, item 25)

  • Task: BACKLOG NOW#25 — swaync text invisible on summer-day.
  • Did: swaync.nix now uses only palette-safe pairings: body/summary = @text on @base (worst ratio 5.18 across all 21 themes; subtext/base was 1.00 on summer-day + flexoki-light), hover rows + widget buttons = alpha(@text, 0.1) tints (contrast by construction); dropped the subtext/surface defines. NEW permanent check checks.theme-contrast (tools/check-theme-contrast.py) asserts the hex-on-hex text pairings across every theme JSON. Audit found the same mispairing in generated waybar/rofi CSS, live on flexoki-light (no whole-swap) → NOW item 27.
  • Verified: V0; V1 — checks.theme-contrast builds green (21 themes), rendered services.swaync.style contains zero @subtext/@surface. NOT V2/V3-verified visually — queued (Bernardo is at the Latitude).
  • Pending: V3 notify-send readability check on summer-day; item 27.
  • Next suggestion: item 27 (same bug class, waybar/rofi surfaces).

2026-07-04 — SUPER+? bind fix (iteration #8, item 26)

  • Task: BACKLOG NOW#26 — cheatsheet bind never fires on hardware.
  • Did: keybinds.nix: $mod, question$mod SHIFT, question (? is Shift+/, Hyprland matches the exact modmask); rofi.nix prettyKeys collapses "SHIFT + ?" → "?" so the row stays SUPER + ?. Gotcha added to MEMORY.md (shifted keysyms need SHIFT in mods).
  • Verified: V0 (flake check --no-build); V1 both surfaces — eval'd hyprland settings.bind renders $mod SHIFT, question, exec, nomarchy-menu keybinds, and built nomarchy-menu's cheatsheet file renders SUPER + ?. No other shifted keysyms in the bind list.
  • Pending: V3 queued (SUPER+? on the Latitude after home-update + relogin).
  • Next suggestion: item 25 (swaync contrast on summer-day).

2026-07-04 — Latitude hardware sweep #2 (Bernardo; results booked, no code)

  • Task: V3 sweep on the Latitude after pulling ≥18b8545 + reboot.
  • PASS: waybar supervisor (theme switches clean; pkill -x waybar respawns instantly); snapshots — themed polkit prompt → GUI as root, fzf fallback works (restore/rollback gate not exercised → residual queued); sys-rebuild; night-light enable/disable; auto-commit (theme commits + the toggle self-commit); hibernate single-unlock + suspend-still-locks (1b0eeea CONFIRMED).
  • PASS (late confirm): auto-timezone — timedatectl shows Europe/London.
  • Bug: SUPER+? never fires — $mod, question misses because a real ? carries SHIFT in the modmask → BACKLOG 26 (bind-only: the menu itself opens fine from a terminal). SUPER+SHIFT+K no-op was the comma-layout gate working (none configured) — retest queued.
  • Next suggestion: item 25 (swaync contrast) or 26 (cheatsheet bind).

2026-07-04 — Waybar resilience + sys-rebuild (iteration #7, items 21+23)

  • Task: the two top Latitude findings.
  • Did: (21) nomarchy-waybar supervisor (waybar.nix, exec-once'd from hyprland.nix): ANY waybar exit respawns, crash-loop guard (5 fast exits → critical notify + stop), TERM trap for a real stop. theme-sync now prefers a clean pkill -x waybar when the supervisor is running (restart with fresh config+style — avoids waybar's in-place SIGUSR2 reload entirely, the suspected double-reload race with reload_style_on_change during symlink flips); SIGUSR2 stays as the unsupervised fallback; reload_style_on_change kept for manual home-update restyles. (23) sys-rebuild — snapshot-first rebuild against the current lock, no nix flake update; README §3/§5 + motd.
  • Verified: V0; V1 (HM renders exec-once=nomarchy-waybar, supervisor bash -n; sys-rebuild in systemPackages). V2: headless software-GL desktop VM (recipe from memory — gotchas hit: node needs the overlay, users.users., useGlobalPkgs) — SIGKILL→new pid, clean kill→respawn, SIGUSR2→alive. Result recorded below once green.
  • Pending: V3 on the Latitude: theme switch survives / bar returns.
  • Next suggestion: item 22 (network menu rows) or 24 (Back audit).

2026-07-04 — Keyboard cycle bind + parity (iteration #6) + Latitude triage

  • Task: BACKLOG NOW#5; mid-iteration Bernardo delivered Latitude 5410 hardware-QA findings (the machine got a real session!).
  • Did: multiLayoutBinds in keybinds.nix (SUPER+SHIFT+K → switchxkblayout current next), gated in hyprland.nix AND the rofi cheatsheet on the same comma-in-layout condition; hyprland/language
    • #language CSS added to both summer whole-swaps (shows even single-layout there — static JSON can't gate; deliberate). Reverse parity gap found (summer-night has idle_inhibitor, generated bar doesn't) → folded into item 13. Triage: four new NOW items from hardware: #21 Waybar crash on theme switch + no respawn (top), #22 nameless network-menu entries, #23 sys-rebuild (no-update rebuild), #24 Back-everywhere audit.
  • Verified: V0 (JSON + flake check) + V1 both directions (single-layout build: no bind; us,de via extendModules: bind + the cheatsheet row render; summer JSONs parse).
  • Pending: V3 cycle-bind check queued; items 21/22/24 carry V3 re-checks on the Latitude.
  • Next suggestion: #21 (waybar crash — stability pillar, user-hit).

2026-07-04 — Webcam follow-ups (loop iteration #5, quick item)

  • Task: BACKLOG NOW#7 (Bernardo asked for "a quick item").
  • Did: template home.packages gains a commented "Webcam tuning" pair (cameractrls GUI, v4l-utils CLI — bare packages, so template not toggle, per the option-surface rule); the portal/Flatpak libcamera IR gap is written up as a PROPOSED item with three options (recommend: document-only now, libcamera-rule investigation when the T14s is available). CI runs #60/#61 confirmed green (earlyoom + snapshot fix).
  • Verified: V0 (flake check — template evals through mkFlake; changes are comments + agent docs).
  • Next suggestion: NOW#5 (keyboard cycle bind + summer parity) — the last code item in NOW besides the docs pass.

2026-07-04 — Snapshot GUI un-broken + polkit agent (loop iteration #4)

  • Task: BACKLOG NOW#4 — btrfs-assistant segfault.
  • Did: re-diagnosed instead of overriding. gdb: crash is in libbtrfsutil's unprivileged subvolume iteration (btrfs-progs 6.17.1; upstream fix 886571653 post-6.17.1; symbol versions verified — not ABI drift). VM A/B: root works (exit 0), user crashes (139). The launcher runs it as root → GUI fine if pkexec can prompt — and the distro shipped no polkit agent (all pkexec silently failed; the actual root cause of "GUI is dead"). Shipped: hyprpolkitagent (exec-once, Stylix-themed Qt), menu re-pointed to the launcher with the fzf flow as fallback, checks.snapshot-gui canary (root path + offscreen event loop on real btrfs). No btrfs-progs patch — root-side flows don't hit the bug; the fix arrives with a lock bump.
  • Verified: V0 + V2 (snapshot-gui check, run for real) + V1 (HM generation renders the agent exec-once; menu bash -n).
  • Pending: V3 queued — first on-hardware themed polkit prompt.
  • Next suggestion: NOW#5 (keyboard cycle bind + summer parity).

2026-07-04 — CI is green (run #58) — item 20 main half closed

  • Task: monitor follow-up, no code. Run #58 (the .gitea path fix) succeeded — first green CI: the container recipe works on the live runner, eval tier confirmed end to end.
  • Did: BACKLOG item 20 reduced to its stretch (KVM runner → enable vm-checks), moved to NEXT. Run #59 (earlyoom push) monitored.
  • Next suggestion: NOW#4 (btrfs-assistant override attempt).

2026-07-04 — Memory-pressure protection shipped (loop iteration #3)

  • Task: BACKLOG NOW#3 — default-on userspace OOM killer.
  • Did: modules/nixos/oom.nix: earlyoom (mkDefault on, desktop notifications, session-plumbing --avoid list, no --prefer) + systemd.oomd.enable = false. Choice rationale: Hyprland session is one cgroup scope → oomd's cgroup-level kill would nuke the desktop; earlyoom is process-level. Found en route: nixpkgs default-enables oomd inert (enable=true, all slice toggles false). README "beyond the surface" note added.
  • Verified: V0 (flake check) + V2 — new checks.oom-protection runNixOSTest, run for real: hog (chunked allocator, 686 MB peak in a 1 GB VM) SIGTERM'd by earlyoom in 0.1 s, bystander unit survived, oomd asserted inactive. 25 s test, cheap enough for the suite.
  • Pending: nothing hardware-specific (behavior fully VM-provable).
  • Next suggestion: NOW#4 (btrfs-assistant override attempt). Also: CI run #58 (the .gitea fix) was running at commit time — check its outcome next tick; this push triggers #59.

2026-07-04 — CI fix: wrong workflow dir (correction to iteration #2)

  • Task: Bernardo reported no run despite an active runner + shared his compose file: the server is Gitea (gitea/act_runner), not Forgejo — I'd shipped the workflow to .forgejo/workflows/, which Gitea never reads. The legacy repo's .gitea/workflows/ path was the clue I under-weighted.
  • Did: git mv.gitea/workflows/check.yml; corrected the Forgejo references in the workflow header, TESTING.md §1b, BACKLOG item 20 (now: watch the first run; runner was never the problem); MEMORY.md gains the Gitea-not-Forgejo line.
  • Verified: the push of this commit is itself the test — the run must appear; monitoring.
  • Pending: first green run (item 20); runner-container memory headroom is the watch-out.

2026-07-04 — CI checks-on-push shipped (loop iteration #2)

  • Task: BACKLOG NOW#2 — Forgejo Actions workflow.
  • Did: .forgejo/workflows/check.yml (push to main/v1 + dispatch): flake check --no-build, theme-sync py_compile, bash -n over tracked .sh. Scoped to the eval tier deliberately — API probing + archaeology of the legacy .gitea/workflows/check.yml (57 runs on this instance) showed the runner is an act_runner docker container (no KVM/systemd), so the VM suite can't run there; a commented vm-checks job documents the KVM-runner upgrade path. Legacy's hard-won container gotchas (nixbld setup, sandbox=false for Stylix IFD, Nix 2.31.5 pin) carried over verbatim. TESTING.md §1b added.
  • Verified: V0 locally (same commands the workflow runs, minus the container Nix install) + yq YAML parse. The real green run needs the runner to be alive — not confirmable from here (runners API is 401 unauthenticated); watching the run after push.
  • Pending: new [human] item 20 — confirm/re-register the runner; stretch: a KVM runner unlocks the vm-checks job.
  • Next suggestion: NOW#3 (memory-pressure protection).

2026-07-04 — Opt-in auto-commit shipped (loop iteration #1)

  • Task: BACKLOG NOW#1 — auto-commit of state mutations (in-flake state Phase 4). First autonomous /loop iteration.
  • Did: settings.autoCommit live-read by nomarchy-theme-sync; pathspec-limited commit of theme-state.json on apply/set (fires if flag on before OR after the write → the off-toggle commits too); identity fallback; same-value no-op; bg excluded. Menu: System Auto-commit (instant, self-gated on .git). Rider: get prints booleans as JSON true/false, fixing the stuck "Auto timezone (on/off)" menu label. BACKLOG numbering switched to stable IDs (no renumbering).
  • Verified: V0 (py_compile, flake check) + V1 (HM generation builds; generated menu bash -n) + a 7-assertion sandbox git-repo round-trip (enable/set/same-value/disable/post-disable/apply/identity-fallback).
  • Pending: V3 queued in HARDWARE-QUEUE (on-machine toggle + apply).
  • Next suggestion: NOW#2 (CI checks-on-push) — but its runner half may need Bernardo to register a Forgejo runner; deliver the workflow regardless.

2026-07-04 — Backlog revision pass (human-requested)

  • Task: Bernardo asked for a philosophy-aligned revision of BACKLOG.md ("I'm sure I'm forgetting important items").
  • Did: verified guessed gaps against the tree first (GC/optimise/boot limit + all 21 previews already ship — dropped those ideas). Added the confirmed gaps: CI-on-push promoted to NOW#2 (agents push to main now), memory-pressure protection NOW#3 (nothing mitigates OOM; the release bump died to one), viewers+mime defaults #8, update/rollback UX #9, nomarchy-doctor #10, state-file validation #11, screen recording #12, niceties batch #13 (idle-inhibit, low-battery notify, hyprpicker), OCR in LATER; recovery runbook folded into the docs item; zram + default browser added to Decisions.
  • Verified: V0 (docs-only).
  • Pending: Bernardo to sanity-check the new NOW ordering, esp. CI at #2 and the two new Decisions.
  • Next suggestion: unchanged — NOW#1 (opt-in auto-commit).

2026-07-04 — Bootstrap the loop infrastructure (this commit)

  • Task: create agent/ (human-requested): LOOP/GOALS/BACKLOG/ CONVENTIONS/MEMORY/HARDWARE-QUEUE/JOURNAL, root CLAUDE.md, README + ROADMAP pointers.
  • Did: reworked the forward half of docs/ROADMAP.md into the tiered BACKLOG (5 NOW / 6 NEXT / LATER / Decisions); collected every pending on-hardware check into HARDWARE-QUEUE.md; seeded MEMORY.md from the ROADMAP's decision records.
  • Verified: V0 (docs-only change; nix flake check --no-build run to confirm the tree still evaluates).
  • Pending: Bernardo to sanity-read GOALS.md pillars + BACKLOG tiering — reorder freely, the order is the instruction.
  • Next suggestion: BACKLOG NOW#1 (opt-in auto-commit — Phase 4 of in-flake state, already the agreed next step).