# Journal archive — rotated iteration log

Older entries rotated out of [JOURNAL.md](JOURNAL.md) (same format,
newest first). Append-only history; do not edit. Rotation: when
JOURNAL.md grows past ~25 entries, move the tail here.

---

## 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 PASS** — `checks.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 PASS** — `nix 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:** **V1** — `nix 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:** **V0** — `nix 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:** **V2** — `nix 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 V2** — `checks.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 A–C; 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 installer’s 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:** **V2** — `THEME=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-notify’s 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:** **V1** — `checks.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 can’t regress. Closed #61.
- **Verified:** **V0** — `python3 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) — 55–63 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:** **V2** — `THEME=<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:** **V2** — `nix 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 12–23
  `@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±1`→`r±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 #51–54 (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) — 51–54 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-gens` → `mktemp` + 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 #47–50 (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 #47–50 present, no
  leftover promoted-pitch text.
- **Pending:** none. #47–50 are now actionable and agent-friendly (all no-VM).
- **Next suggestion:** spawn worktree agents on #47–50 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 refresh` → `get-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-click` → `powermgmt` 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
  `question` → `slash` (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 `modeBack` —
  `display` 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: top` → `bottom` 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 (2–14 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 &amp; 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 P1–P3 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 (a–d) 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.<u>, 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).
