All checks were successful
Check / eval (push) Successful in 3m4s
Swap the vim-style SUPER+H/J/K/L focus binds for SUPER+arrow keys (movefocus l/r/u/d). SUPER+arrows were unbound and there are no vim move-window binds, so no collision. prettyKeys renders the arrow keysyms as glyphs so the SUPER+? cheatsheet shows "SUPER + <-" not "SUPER + left". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
69 KiB
69 KiB
Journal — append-only iteration log
One entry per iteration, newest first. This is the loop's short-term memory: the next session reads the last 3–5 entries to orient. Keep an entry under ~15 lines; durable lessons go to MEMORY.md, not here.
Template:
## YYYY-MM-DD — <task title> (<commit sha, or "no commit">)
- **Task:** which BACKLOG item (or QA sweep / bootstrap / escalation)
- **Did:** what changed, in 2–4 lines
- **Verified:** tier reached (V0/V1/V2) + the actual commands/checks run
- **Pending:** V3 queued? follow-ups filed? anything [stuck]?
- **Next suggestion:** what the following iteration should probably take
2026-07-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.nixfocus binds now useleft/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 taughtprettyKeys(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 evalconfirms 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 toio.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— addedSHIFT+Print(region→file) andCTRL+Print(screen→file) alongside the existing barePrint(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 evalof 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 normaland-matching normalboth fixed "steam"→Steam;-no-sortdid 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", keepingmatching="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' coloredbattery-profile-{performance,balanced,powersave}family (the-symbolicvariants are #444 grey → invisible on dark themes; verified the colored ones carry real fills). Returned row text stays the bare profile name, sopowerprofilesctl setis unaffected; added-show-icons. - Verified: V0
nix flake check --no-buildgreen 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-runningdisplaydrops straight back into the same mode picker — an apparent no-op. (Multi-monitor works:displayre-shows the chooser, a genuine previous level.) - Fix:
modules/home/rofi.nixdisplay handler now tracksmodeBack—displaywhen the chooser was shown, elsesystem. Mode-picker Back doesexec "$0" "$modeBack", so single-monitor Back leaves Display for System. - Verified: V0
nix flake check --no-buildgreen. 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
↩ Backrow drew two arrows: the↩glyph in the label AND a themedgo-previousicon. - Fix:
back()inmodules/home/rofi.nixwasrow "$BACK" go-previous(label + icon). Changed toprintf '%s\n' "$BACK"— now identical to what the plain pick-lists already append, so every Back row shows a single↩glyph. KeptBACK="↩ 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-buildgreen (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 (rofinomarchy-menuis 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→bottomin the generatedwaybar.nixand 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.activationPackagebuilds; the built.config/waybar/configshows"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). Wiredmodules/home/options.nixandmodules/nixos/options.nixto useconfig.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-glasspreset 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-slatepreset 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
cpuandmemoryfrommodules-rightand the CSS styling blocks inmodules/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.shand packaged it inpkgs/nomarchy-control-center. Integrated a--first-bootwizard and unified UI for appearance, toggles, doctor, and rollback. Added the package toflake.nixandmodules/nixos/default.nix. Added "Control Center" to the System menu inrofi.nix. - Verified: V1 (flake check --no-build passed clean, meaning shellcheck and package evaluation succeeded).
- Pending: V2/V3 to visually verify the
gumUI 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-buildpassed 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 Hyprlandworkspacerules and apply instantly on profile switch (hyprctl keyword workspace+dispatch moveworkspacetomonitor). monitor-rules.nix gained pureworkspaceRule; 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
-symbolicicon 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
f211ef0rewrite 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
~/.nomarchyruntime 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 wallpaperpaints naturally; dropped the testScript seed+manual-repaint (too late for exec-once; manual runs also lack WAYLAND_DISPLAY, which awww's client needs to find its socket). - Verified: V2 — summer-night capture shows wallpaper + cream inverted bar + menu + placeholder dim, all coherent. V1 flake check green.
- Pending: identity-theme vibe capture (lumon/retro-82); the
[human]icon-weight call; HARDWARE-QUEUE eyeballs. - Next suggestion: item 28c identity capture, or park 28 for Bernardo's taste calls.
2026-07-05 — clock zone tooltip (iteration #43, LATER item)
- Task: LATER › auto-timezone Waybar tooltip. Bullet deleted.
- Did: the clock tooltip's first line is now the zone —
{:%Z (UTC%z)}above the calendar — in the generated bar AND both summer whole-swaps (parity). Under auto-timezone the existing tz-watch SIGUSR2 reload keeps it current, so it shows the detected zone live. (%Z abbreviation, not the IANA name — strftime has no code for that; good enough for an "(optional)" nicety.) - Verified: V0; V1 — rendered generated config carries the new tooltip-format; both summer jsonc parse (jq) with %Z present. Hover render → V3 queued.
- Pending: V3. LATER now holds only deferred/big/hw/human items.
- Next suggestion: a QA sweep, or stop-and-wait — the queue is effectively drained for unattended work; meaty LATER items (wallpapers split is deferred by decision, installer round 2 [big]) deserve Bernardo's go-ahead or a fresh session.
2026-07-05 — doctor bar tripwire (iteration #42, LATER item)
- Task: LATER › doctor Waybar warning. Bullet deleted.
- Did: nomarchy-doctor-status (named bin, PATH): silent exit 0 while the doctor is healthy or absent (self-gate), else JSON with the first ✖ lines jq-escaped into the tooltip, in @bad; click = nomarchy-menu doctor (the sheet). custom/doctor added to the generated bar (after battery, interval 300 — the check is real work, this is a tripwire not a monitor) + CSS, AND both summer whole-swaps (module list, jsonc block, CSS membership + @red rule) per the parity rule.
- Verified: V0; V1 — template-home builds, status bash -n, config
- CSS each carry the module, both summer jsonc still parse (jq) with the block; FUNCTIONAL — self-gate silent, and a shimmed failing doctor produces valid JSON (jq-verified: class bad, ✖ lines in tooltip). Live render → V3 queued.
- Pending: V3. LATER remaining: wallpapers-artifact split (deferred by decision), installer round 2 [big], boot-from- snapshot, night-light geo, icon overrides, MIPI camera [hw], auto-timezone tooltip, VPN richer display, release bump [human].
- Next suggestion: auto-timezone Waybar tooltip (small) — or a QA sweep; the meatier LATER items deserve a fresh session.
2026-07-05 — OCR screenshot-to-text (iteration #41, LATER item)
- Task: LATER › OCR (NEXT is fully human/event-gated, so LATER is in play per LOOP.md). Bullet deleted.
- Did: Capture › "OCR region → clipboard" (self-gated on tesseract): slurp (Esc = silent cancel, the recording pattern) → grim → tesseract stdin/stdout → wl-copy, whitespace-only results toast instead of clobbering the clipboard; success toasts the word count. tesseract ships eng-only via rofi.nix home.packages (override documented — unscoped it drags every language's traineddata, real cost on a compile-from-source distro).
- Verified: V0; V1 — template-home builds, menu bash -n, gated row + case present; FUNCTIONAL — the profile's own tesseract read a rendered test image back verbatim ("Nomarchy OCR smoke test 42"), so the OCR half of the pipe is proven; grim/slurp half needs a session → V3 queued.
- Pending: V3.
- Next suggestion: LATER: doctor Waybar warning (self-gating bar indicator fed by nomarchy-doctor) or auto-timezone tooltip; both small.
2026-07-05 — Look & Feel menu category (iteration #40, item 19)
- Task: BACKLOG NEXT#19 — its ≥3-entries gate is met (Theme, Next wallpaper, Night light). Item deleted.
- Did: root's Theme row → "Look & Feel" (pango-escaped — -markup-rows menus treat & as an entity; matched on Look); new lookfeel mode: Theme (SUPER+T hint), Next wallpaper (SUPER+SHIFT+T hint via the new generalized hintForAction), Night light row moved from System (System thins by one). Root stays six. menuHint is now sugar over hintForAction.
- Verified: V0; V1 — menu bash -n, lookfeel mode + escaped label
- night light relocated (4 occurrences, all in lookfeel/nightlight paths); VISUAL — tokyo-night capture: root renders "Look & Feel" correctly with six rows and intact hints. Submenu flow → V3 queued.
- Pending: V3. NEXT now: 28 (Bernardo-gated) · 14 (Monday watch) · 18 [big, Decision-gated] · 20 [human] — the LATER tier or QA sweeps are next for the loop.
- Next suggestion: LATER's OCR screenshot-to-text (two-row Capture addition, self-contained) — or a QA sweep.
2026-07-05 — launch-or-focus binds (iteration #39, item 17)
- Task: BACKLOG NEXT#17 (the UI review is Bernardo-gated; back to the queue head). Item deleted.
- Did: nomarchy.launchOrFocus (listOf submodule: key/mods/class/ command/desc; opt-in, template example) → hyprland.nix generates binds through a shared nomarchy-focus-or-launch script (jq case-insensitive class match → focuswindow "(?i)" regex, else launch; uninstalled command → toast, so binds survive suite edits); rofi.nix renders the same entries into the SUPER+? cheatsheet via prettyKeys (single source). README row.
- Verified: V0; V1 — scratch downstream with 2 entries: both binds rendered (default command = lowercased class; custom mods/command/desc honored), tool bash -n + usage exit 64, cheatsheet rows present. Focus behaviour needs a session → V3 queued.
- Pending: V3. Queue after this: #18 control center [big, needs the form-factor Decision], #19 Look&Feel menu (gated on ≥3 entries), #20 [human], LATER tier.
- Next suggestion: a QA sweep (#18/#19/#20 are blocked-ish) — or item 19's precondition check (does Look & Feel earn 3 entries yet?).
2026-07-05 — placeholder dim + latte review + backdrop probe (iteration #38, item 28c)
- Task: item 28 slice (c) — the summer-rasi quickie + the light- theme capture.
- Did: both summer rasi: placeholder-color @bg0 → bg0 at 60% alpha (#…99), so prompt and placeholder no longer read as one phrase. Captured catppuccin-latte at 1080p: the generated menu is COHERENT on light themes (zebra rows on the 28b-retuned surface, hints dimmed) — closes the audit's "dark terminal on latte" concern as a stale preview. Backdrop suspicion probed with a dedicated VM (hyprctl getoption): misc:background_color IS set (0xFFEFF1F5) — awww's empty-state layer occludes it in the wallpaper-less VM; on hardware the fix covers the startup gap as intended.
- Verified: rasi edits grep-verified (rasi parses at rofi runtime; visual rides the next summer capture / V3); latte menu capture reviewed; probe output above.
- Pending: item 28 remaining: icon-weight
[human], hardware eyeballs (queued), identity-theme capture (optional), slice (d) needs nothing (parity verified). - Next suggestion: item 28 is now Bernardo-gated (taste calls + V3); the loop should return to the general BACKLOG head (item 14 watch / item 17 launch-or-focus).
2026-07-05 — rofi keybind hints (iteration #37, item 28c)
- Task: item 28 slice (c) — the hint column, the audit's biggest remaining UX item.
- Did: rofi.nix: menuHint builds a dimmed pango span (size small, alpha 55%) from keybinds.nix via the cheatsheet's prettyKeys — single source, hints can't drift from the live binds; applied to root (Apps/Theme/Power/Keybindings; Apps special-cased, it's rofi drun not a menu module), Tools (all eight leaves), System (Network/Bluetooth/DND); those three menus now pass -markup-rows. Contains-glob matching and the exact "↩ Back" match are unaffected (labels keep their prefix; Back stays markup-free).
- Verified: V0; V1 rendered menu bash -n + hint spans present + 3× -markup-rows; VISUAL — tokyo-night capture: hints render dimmed and subordinate on normal AND selected (accent) rows; Tools/System rows correctly bare.
- Pending: slice-c remainder: summer-rasi placeholder dim,
latte/identity captures, icon-weight
[human]. - Next suggestion: the placeholder-dim quickie + a latte capture in one tick; then item 28 pauses for Bernardo's icon-weight call and the hardware eyeballs.
2026-07-05 — bar group rhythm + @muted adoption (iteration #36, item 28c)
- Task: item 28 slice (c) — the two queued bar polish items.
- Did: waybar.nix generated CSS: margin-left 14px on the three right-cluster group heads (pulseaudio/powerprofile/battery — media · toggles · status; hidden heads degrade to uniform spacing); workspaces buttons, dnd bell, and muted volume moved from alpha(@text,.5) tints to the semantic @muted role — safe since 28b floor-gates muted/base ≥ 2.0 (the old comment warning against @muted documented the pre-28b world; rewritten to state the new invariant). Whole-swap bars untouched (authored identity).
- Verified: V0; V1 rendered CSS has 4 @muted uses + the margin rule; VISUAL — tokyo-night re-capture: themed backdrop confirmed (navy base, not black), group gap visible before the volume group, workspace pill legible. Cross-theme minima are guaranteed by the gated checker rather than per-theme eyeballs.
- Pending: slice-c remainder: rofi hint column, summer-rasi
placeholder dim, icon-weight
[human], latte/identity captures. - Next suggestion: rofi keybind-hint column (the biggest remaining UX win), or the two-line placeholder nit as a quickie.
2026-07-05 — summer-day capture review + themed backdrop (iteration #35, item 28c)
- Task: item 28 slice (c) — whole-swap capture review + the first cheap polish fix.
- Did: captured summer-day at 1080p (harness, VM): the authored
slate menu + island-pill bar hold up with the 28b retunes —
initially misread as polarity soup, but the rasi whole-swap
deliberately mirrors the bar's slate strip: identity, keep (nit
filed: undimmed entry placeholder). The surviving cross-theme fix:
Hyprland
misc:background_color= theme base (was compositor black — a glitch-looking flash behind missing/slow wallpaper, glaring on light themes). Punch list updated. - Verified: V0; V1 — template-home rebuilt, rendered hyprland.conf
carries
background_color=rgb(1a1b26)(theme base). Backdrop visible confirmation rides the next capture run / V3. - Pending: captures for latte + one identity theme; polish items
queued: bar group margins, @muted adoption, rofi hint column, icon
weight
[human]. - Next suggestion: bar polish slice (group margins + @muted) — code-level, verifiable by build + re-capture.
2026-07-05 — 1080p capture harness + first slice-c review (iteration #34, item 28c)
- Task: item 28 slice (c) prep — full-res captures for the per-surface polish pass.
- Did: tools/theme-shot.nix (maintainer tool, THEME env-driven):
full themed desktop headless at 1920x1080 via the memory recipe +
two fixes over the spike — home-manager.useGlobalPkgs (HM submodule
otherwise misses the overlay → 'nomarchy-theme-sync missing') and a
menu.png shot (hyprctl dispatch exec nomarchy-menu). Proven on
tokyo-night; both shots read. Findings → item 28 punch list: rofi
root width vs empty space (→ keybind-hint column idea), icon-weight
mix (color Papirus vs mono bar)
[human], bar group margins confirmed, alpha-tint dim vs @muted role. Whole-swap module parity verified textually (no drift; cpu/memory omission is identity). - Verified: harness runs end-to-end (exit 0, screenshots read); eval from tools/ with relative flake path OK. Wallpaper still doesn't paint (theme-sync needs ~/.nomarchy in the guest — fix noted in the header for the next run).
- Pending: capture summer-day/night (whole-swaps) + latte; then the polish slices; icon-weight call is Bernardo's.
- Next suggestion: run the retuned-theme captures + start the cheap polish items (group margins, @muted adoption).
2026-07-05 — P2 floors retuned + gated (iteration #33, item 28b done)
- Task: item 28 slice (b) remainder — the P2 contrast floors.
- Did: 18 hex retunes across 9 themes: muted raised on lumon/ white/retro-82/everforest (OKLCH hue-preserving minimal solve to ≥2.05) + gruvbox→bg4 #7c6f64, nord→#616e88 (community standard), latte→overlay1 #8c8fa1; text-on-surface via surface nudges (ristretto darker, latte lighter); accentAlt darkened (latte, summer-day); warn darkened on the light themes (latte, summer-day, rose-pine-dawn) and flexoki-light's four statuses moved to the canonical 600 series. check-theme-contrast.py gates all four adopted floors (muted ≥2, text/surface ≥4.5, accentAlt ≥3, warn ≥2.5 — warn is the battery tint); good/bad stay audit-only (identity), so no exemption mechanism was needed. Slice (b) done.
- Verified: V0 + checks.theme-contrast GREEN (21×7); re-audit: contrast findings 20→1 (miasma bad = identity); flake check green. Rendering is V3 → queued (P2 eyeball entry).
- Pending: slices (c) per-surface polish (needs 1080p captures) and (d) whole-swap bar parity; ansi[] conventions decision still open (audit notes).
- Next suggestion: slice (c) prep — 1080p captures via the VM recipe, or hardware captures if Bernardo prefers eyeballing first.
2026-07-05 — P1 palette retunes + gated subtext floor (iteration #32, item 28b)
- Task: item 28 slice (b), P1s from the #31 audit.
- Did: summer-day: surface #5c6a72(=text!)→#efe7d0 raised cream,
subtext #fdf6e3(=base!)→#6e828a slate; flexoki-light to canonical
Flexoki tones: surface #E6E4D9(ui), overlay #B7B5AC, subtext
#6F6E69(tx-2), muted #878580(base-500); miasma surface #000→#2e2e2e;
kanagawa surface #090618→#2a2a37 (upstream sumiInk4 — old value was
sumiInk0, darker than bg). check-theme-contrast.py gains the adopted
subtext/base ≥ 3pairing (the item-25/27 trap, now impossible). Model note recorded:overlayis 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 pollshyprctl monitors allevery 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.displayProfilestate 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
colorpickermode (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-recordstart/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),
validatesubcommand, 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 onparsed(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 atvalidate. - 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
setrefused 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
rollbackcase in nomarchy-menu (System submenu row): lists the last 10home-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
generationsoutput (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},|| trueso 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 -tbut 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.gapsOutCLI key, awww(-daemon) naming, 21 presets, tokyo-night's 4 wallpapers, summer-night's light @fg bar, live,highresmkForce, .gitea/workflows/check.yml, QEMU gl flags, template.#me+ ~/.nomarchy/NOMARCHY_PATH. All accurate. Fixed the two real gaps: OVERRIDES §2 predatednomarchy.monitors(now routes there + quick-ref row); TESTING §1 lacked the shell-syntax check §1b claims CI runs (addedbash -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 -dmenucall 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 tocompact = 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 rendersSUPER + ?. 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 waybarrespawns 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 (1b0eeeaCONFIRMED). - PASS (late confirm): auto-timezone —
timedatectlshows Europe/London. - Bug: SUPER+? never fires —
$mod, questionmisses 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-waybarsupervisor (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 cleanpkill -x waybarwhen 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, nonix flake update; README §3/§5 + motd. - Verified: V0; V1 (HM renders
exec-once=nomarchy-waybar, supervisor bash -n;sys-rebuildin systemPackages). V2: headless software-GL desktop VM (recipe from memory — gotchas hit: node needs the overlay, users.users., useGlobalPkgs) — SIGKILL→new pid, clean kill→respawn, SIGUSR2→alive. Result recorded below once green. - Pending: V3 on the Latitude: theme switch survives / bar returns.
- Next suggestion: item 22 (network menu rows) or 24 (Back audit).
2026-07-04 — Keyboard cycle bind + parity (iteration #6) + Latitude triage
- Task: BACKLOG NOW#5; mid-iteration Bernardo delivered Latitude 5410 hardware-QA findings (the machine got a real session!).
- Did:
multiLayoutBindsin 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#languageCSS 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, #23sys-rebuild(no-update rebuild), #24 Back-everywhere audit.
- Verified: V0 (JSON + flake check) + V1 both directions
(single-layout build: no bind;
us,devia 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.packagesgains 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
886571653post-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-guicanary (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--avoidlist, 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-protectionrunNixOSTest, 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 commentedvm-checksjob 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.autoCommitlive-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;bgexcluded. Menu: System › Auto-commit (instant, self-gated on.git). Rider:getprints booleans as JSONtrue/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-buildrun 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).