Some checks failed
Check / eval (push) Has been cancelled
Airplane: runtime Wi-Fi+Bluetooth kill-switch with prior-state restore, System menu + SUPER+CTRL+R, Waybar plane glyph (self-hides, whole-swap parity). Fastfetch: chafa sextants at 24×12 (was block 20×10) for a finer monogram; V2 kitty screenshots under boreal and summer-night.
88 KiB
88 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. When this file grows past ~25 entries, rotate the tail to JOURNAL-ARCHIVE.md (history, never edited).
Template:
## YYYY-MM-DD — <task title> (<commit sha, or "no commit">)
- **Task:** which BACKLOG item (or QA sweep / bootstrap / escalation)
- **Did:** what changed, in 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-15 — #104 airplane mode + #122 fastfetch sextant logo
- Task: NEXT #104 (Airplane) + #122 (crisper fastfetch logo).
- Did: (104)
nomarchy-airplaneruntime Wi-Fi+BT kill-switch with prior restore; System menu row; SUPER+CTRL+R; Waybarcustom/airplane(signal 11, self-hides); whole-swap jsonc/css parity. (122) chafasextant24×12, rsvg 360px. - Verified: V1 airplane state machine (on/off/status empty when off);
bash -n; keybinds-cheatsheet; menu-back; flake check --no-build; HM gen.
V2 fastfetch: real kitty screenshots
/tmp/nomarchy-v2-122/{boreal-sextant,summer-kitty,boreal-block}.png— sextant clearly finer than block; no tofu; accents track. - Pending: V3 airplane on a machine with live radios (HARDWARE-QUEUE).
- Next suggestion: #111 Recovery menu, or #98 with screenshot.
2026-07-15 — #107 state.json + nomarchy-state-sync
- Task: BACKLOG #107 — rename misnamed system state file and CLI.
- Did:
theme-state.json→state.json(template, root, docs, modules); package/CLInomarchy-theme-sync→nomarchy-state-syncwith symlink alias;modules/state-read.nix; mkFlake/doctor/lifecycle read legacy name; writes always land onstate.jsonand remove the old file. - Verified: py_compile; legacy-file unit migrate (write removes theme-state.json); V0 flake check pending in same push.
- Pending: drop
nomarchy-theme-syncalias after release notes. - Next suggestion: #104 airplane, or #98 with a screenshot.
2026-07-15 — Close #94 installed chromium + kill Hyprland update-news
- Task: Residual #94 (chromium on installed path) + first-boot polish seen while probing.
- Did: Re-booted leftover offline install disk (
target.img). Probe: Chromium 150 on PATH, https/html →chromium-browser.desktop, Chromium window opens (about:blank+ keyring prompt). Closed #94. Addedecosystem.no_update_news+no_donation_nag(every first boot showed “Hyprland updated to 0.55.x!”). - Verified: V2 install re-boot screenshots
/tmp/nomarchy-v2-94/; V0nix flake check --no-build; HM gen conf contains ecosystem keys. - Pending: V3 optional on Acer (hardware already had no browser on live before #103; installed path is the one that mattered).
- Next suggestion: #107 state.json rename, or #98 if screenshot lands.
2026-07-15 — File #127 docked idle blackout (no code)
- Task: Bernardo: docked laptop idle → black screens; external KB/mouse no wake; unplug external did not restore panel; Caps Lock still worked. Explains the "session crash" (seat brick, not agent-only).
- Did: NOW #127 + HARDWARE-QUEUE capture steps. Code read: AC idle path is lock+DPMS not suspend; dock mode disables eDP; both wake and undock recovery failed on the incident.
- Verified: V0 (docs/agent only).
- Pending: hardware journal capture on next repro; then fix.
- Next suggestion: continue fix batches, or dig into #127 if Bernardo can leave SSH open for a controlled repro.
2026-07-15 — V2 verification of fix batches (doctor-float + test-install)
- Task: V2-test shipped items that admit VM harnesses (#95 doctor, #123 bake, #112/#124/#125 install path).
- Did / Verified:
- V2 doctor-float (boreal):
nix build --impure -f tools/doctor-float.nixPASS. Classcom.nomarchy.doctor, floating, centered; clienttitle=kitty. Screenshots:/tmp/nomarchy-v2-doctor/{desktop-before,doctor-float}.png. SoftGL window body is blank (known softGL terminal paint); float/class contract holds. - V2 test-install.sh (offline LUKS+swap): machine-checkable PASS
(~28 min). Artifacts
/tmp/nomarchy-v2-batch/:- ISO:
result/iso/nomarchy-live-….iso(#125) first-boot.png: themed Boreal desktop + Waybar, no red autogenerated banner, no login prompt → HM pre-activate (#123) succeeded (visual)- install completed poweroff; LUKS boot + passphrase works
- ISO:
- Disk filter fixture: fd0/loop excluded, vda/sda kept (#112 logic)
- V2 doctor-float (boreal):
- Pending: V3 on Acer/XPS; mount installed disk for log/flake-url strings needs root (skipped). Doctor softGL paint is not a product fail.
- Next suggestion: continue backlog or hardware V3.
2026-07-15 — #108 keybinds cheatsheet groups + completeness check
- Task: BACKLOG #108 — group SUPER+? as Window/Workspace/Menu/Media; automated completeness.
- Did: every bind/extra in keybinds.nix gets
group; cheatsheet renders section headers;checks.keybinds-cheatsheetasserts groups + every desc present (proved via assert). - Verified: V0 flake check; cheatsheet file shows ── Window ── etc.
- Pending: V3 eyeball SUPER+? on a real session (optional).
- Next suggestion: #94 residual or #107 state.json rename.
2026-07-15 — Fix batch #112 disk picker, #106 menu Back, #113 offline theme
- Task: Second fix-only batch from NEXT/NOW residuals.
- Did: (112)
list_installable_disksexcludes fd/loop/sr/zram/tiny (<8 GiB), sorts largest-first; installer-safety markers. (106)tools/check-menu-back.py+checks.menu-back(proved to fail when Back stripped). (113) offline theme contract: TESTING item 6 scoped to default/ current theme;run_switchprints clear offline-oriented message on network/build failures. - Verified: V0 flake check; installer-safety; menu-back prove-fail; py_compile theme-sync.
- Pending: V2 unattended install with OVMF fd0 present (optional).
- Next suggestion: #108 keybinds audit, or #94 test-install chromium.
2026-07-15 — Fix batch #123–#126 (install bake, flake ref, ISO name, display)
- Task: Fix-only NOW batch: #123 dconf pre-activate, #124 main flake seed, #125 ISO filename, #126 display mode list.
- Did: (123) pre-activate creates
/run/user/$UID+ prefersdbus-run-session -- activate. (124) seed?ref=main; patch-template rewritesinputs.nomarchy.urlfrom NOMARCHY_FLAKE_URL (was unused); template default main. (125)image.baseName→ nomarchy-live-….iso. (126) sort modes by pixel area; toast shows hyprctl size; TESTING QEMU note. - Verified: V0 flake check; installer-safety;
image.baseNameevalnomarchy-live-…; patch-template flakeUrl rewrite; mode sort unit fixture. - Pending: V3 reinstall on Acer/XPS (#123/#124); optional full
test-install.shV2 when time allows. - Next suggestion: #112 disk-picker fd0, or V2 test-install for #123.
2026-07-15 — File #125 ISO name + #126 display resolution invert (no code)
- Task: Bernardo: (1) installer ISO still named nixos; (2) live VM Display picker — higher modes made the screen look lower-res.
- Did: NOW #125 — artifact is
nixos-live-….isobecauseimage.baseNameis still the nixpkgs default; volumeID already NOMARCHY_LIVE. #126 — rofi display mode list/apply path; separate sort bug vs QEMU scaling before coding. - Verified: V0 (docs/agent only); confirmed
result/iso/nixos-live-…isoon tree. - Pending: implement when picked.
- Next suggestion: still #123 (HM pre-activate), or #125 if a one-liner.
2026-07-15 — #95 complete: Kitty is the only terminal (this commit)
- Task: Bernardo: make kitty default and only option — drop dual-terminal complexity (Ghostty failed on Acer OpenGL 4.2; fallback was more code).
- Did: Removed
ghostty.nixandnomarchy.ghostty.enable. Kitty always installed + themed; defaultnomarchy.terminal = "kitty". Doctor, calendar, what-changed →kitty --class=com.nomarchy.*. Dropped install-time GL probe + mesa-demos. Updated README/REQUIREMENTS/OVERRIDES/TESTING/tools. - Verified: V0 flake check; downstream-template-home builds with kitty, no ghostty; installer-safety green.
- Pending: V3 Acer SUPER+Return + doctor float (HARDWARE-QUEUE).
- Next suggestion: #123 (HM pre-activate dconf).
2026-07-15 — #95: themed Kitty when OpenGL < 4.3 (superseded above)
- Task: Bernardo: when GL < 4.3 automatically add kitty — and theme it.
- Did:
modules/home/kitty.nixthemes Kitty from theme-state (same palette/font/opacity as Ghostty); enables whennomarchy.terminalis kitty ornomarchy.kitty.enable. Installer runsglxinfo(mesa-demos on PATH) and, if OpenGL < 4.3, writessettings.terminal = "kitty"(+terminalReason) into theme-state. Docs/REQUIREMENTS + README rows. - Verified: V0 flake check; HM gen with
settings.terminal=kittybuilds — kitty.conf has Boreal colors,TERMINAL=kitty, Hyprland$terminal=kitty; default template HM has ghostty and no kitty package. - Pending: V3 Acer install; doctor/calendar still hardcode ghostty.
- Next suggestion: #123 (HM pre-activate dconf) — still highest install pain.
2026-07-15 — docs/REQUIREMENTS.md (OpenGL floor + disk planning)
- Task: Bernardo: why Acer lacks OpenGL 4.3; start documenting minimum system requirements including storage (Nix store + snapshots).
- Did: Answer is hardware generation (HD 4000 / Ivy Bridge tops at GL
4.2; Ghostty needs 4.3). New
docs/REQUIREMENTS.md— UEFI/x86_64, GPU table, RAM, disk floors (40/64/128 GiB) + swap≈RAM, why store+snapper grow; linked from README, docs map, HARDWARE.md; #95 notes the generation ceiling. - Verified: V0 (docs only).
- Pending: #95 still needs a runtime fallback; tighten disk numbers when
a fresh install is
df-measured end-to-end. - Next suggestion: #123 (installer bake).
2026-07-15 — File install findings from Acer + XPS photos (no code)
- Task: Bernardo: real installs on Acer Aspire M5-481T + Dell XPS 9350; photos of the install end screens and post-boot sessions. Figure out issues and queue them — do not implement in this iteration.
- Did: Read the six photos. Three distinct root causes (not one vague
"home didn't build"):
- #123 — HM pre-activate dies on both machines at dconf
(
/run/user/1001/dconf: Permission denied) → partial first boot (weird GTK + missing nm-applet are symptoms, not separate bugs). - #124 — seeded flake hardcodes
?ref=v1while installer writes main-eranomarchy.hardware.*; v1 lags (~hundreds of commits) →nomarchy.hardware does not existon Acer rebuild/pull. - #95 — Ghostty Acer-only (XPS is fine). Two photos = two
attempts on the Aspire: pre-HM explicit
OpenGLOutdated, post-HM quiet exit afterGDK_DISABLE(same machine; kitty used as the working shell). Primary blocker is GL ≥ 4.3. HARDWARE-QUEUE V3 rows. Photos stay local (not committed).
- #123 — HM pre-activate dies on both machines at dconf
(
- Verified: V0 (docs/agent only).
- Pending: implement #123 first; then #124; #95 independent (Acer GL).
- Next suggestion: #123 (installer bake) — highest blast radius.
2026-07-15 — #95 timeline: both Ghostty fails are Acer, pre/post HM
- Task: Bernardo corrected the Ghostty story again.
- Did: XPS works. Both fail photos are Aspire M5-481T: (1) before home
properly built → OpenGL 4.2/
OpenGLOutdated; (2) after home built → silent exit afterGDK_DISABLE=gles-api,vulkan. Kitty was the manual working terminal used to run those experiments. #95 + HARDWARE-QUEUE rewritten; not two machines. - Verified: V0 (docs only).
- Pending: —
- Next suggestion: still #123.
2026-07-15 — #119: mime defaults must name a present .desktop (this commit)
- Task: BACKLOG #119 —
text/plainnamed vscode, which the live ISO never ships (same GIO-skip trap as #94, one key over). - Did:
text/plainis now an ordered fallbackcode.desktop→org.gnome.TextEditor.desktop(HM tries the next when the preferred is missing). Live profile gainsmpvtoo — video mime defaults had the same hole and the package is free via the template pin. Extendedchecks.live-baseline-appsso every[Default Applications]key has at least one listed.desktopon live (HM path + system path for thunar) and on the default template install. - Verified: V2 — check green; mimeapps.list renders
text/plain=code.desktop;org.gnome.TextEditor.desktop; proved to fail whentext/plainis a vscode-only singleton. V0 flake check green. - Pending: V3 launch of a
.txton the Acer is covered by the existing #103 HARDWARE-QUEUE entry (now expects Text Editor for text files). Opting out of both vscode and Text Editor still leaves no handler — that is the delete-the-line convention, not a silent live-ISO bug. - Next suggestion: #95 (Ghostty does not open) or #94 residual (test-install chromium launch).
2026-07-14 — #118: smartd self-gates; the doctor was right all along (this commit)
- Task: BACKLOG #118 — Bernardo's live ISO showed a red Waybar health icon reporting smartd.
- Did: smartd's DEVICESCAN finds nothing where no drive answers SMART and
exits 17, so systemd marks it failed, the doctor honestly reports a
failed unit, and Waybar paints
@bad. Everything downstream was correct — smartd was the bug, not the doctor. Added anExecConditionrunningsmartctl --scan(empty exactly when smartd would find nothing), so the unit goes inactive rather than failed. NOTSuccessExitStatus = 17, which would also swallow exit 17 on a machine that has drives — the reason the daemon exists. - Scope was never live-only: smartd mkDefaults true everywhere and QEMU virtio has no SMART, so every VM install has been booting to a health warning, and every V2 run had been showing it as noise.
- Verified: V2 —
checks.smartd-gateboots the real distro module (not a restatement of it;nixpkgs.configneededmkForceto yield to the test's pkgs) and asserts both halves, since they pull opposite ways: a gate that never skips leaves the red icon, one that always skips silently kills drive-health monitoring — the failure nobody notices until a disk dies quietly. No-SMART node →ActiveState=inactive, not failed, absent fromsystemctl --failed(what the doctor actually reads); and the gate's logic driven against a scan that finds a device → exit 0, because QEMU cannot answer SMART honestly and pretending otherwise would test nothing. Proved to fail by unwiring the condition. flake check + doctor + hardware-toggles- live-baseline-apps + option-docs + state-bridges green.
- Pending: V3 — that smartd still RUNS on real drives (dev box, real NVMe). Queued with an explicit fail-condition: if it skips there, revert the gate rather than tune it.
- Next suggestion: #119 (
text/plainnames vscode — the last of #94's bug class), or #95 (Ghostty does not open) at the top of NOW.
2026-07-14 — #121 reverted: the fix worked, the gain didn't survive measuring (this commit)
- Task: Bernardo's call on #121 (shipped
0b464af, reverted here): "Let's leave it honestly. Sounds too much work for a negligible gain." - Did: removed the chromium overlay +
checks.chromium-single-closure; template HM closure back to 9.38 GiB and the duplicate unwrapped chromium is back, deliberately.overlays.defaultcarries a comment saying so, and the ROADMAP entry is now a ✗ decided-against record holding the measurement, the working approach, and the commit to recover it from. - Why this was right: the fix worked, but it substitutes into a
buildCommandnixpkgs owns — coupling us to wrapper internals with a silent no-op failure mode, which is why it needed a permanent check too. That standing cost buys ~195 MiB of download and ~19 MiB of disk. Boring beats clever at that exchange rate (CONVENTIONS). - The lesson that outlives it, and the real product of the last two items:
closure size is not disk size and is not image size — measure the
artifact. Removing a 687 MiB path moved the ISO by 8 KiB, because
mksquashfs dedupes duplicate files and
auto-optimise-storehardlinks them (the two paths share inodes —stat-verified;ducounts 639 MiB for the pair vs ~620 for one). Only the wire can't dedupe. This is stamped on #120, whose entire size table is closure arithmetic — without it, "drop the pin, save 4 GiB" would have evaporated at the squashfs exactly like this did. - Verified: V0 flake check green; revert confirmed by closure (the plain chromium is back, 9.38 GiB) rather than by reading the diff.
- Next suggestion: #118 (smartd self-gate).
2026-07-14 — #121: one chromium, not two — 687 MiB off every install (superseded by the revert above)
- Task: BACKLOG #121, found by measuring #103's ISO delta. Nothing was failing — that is the point; a duplicate browser breaks no build.
- Did: nixpkgs' chromium wrapper with
enableWideVine = true(what the template ships, for DRM) runs the-wvcopy but linksshare/*from the plain unwrapped build. A symlink is a store reference, so a second 687 MiB chromium rode along for a directory of.desktopfiles nothing executes — on every installed machine, not just the ISO.overlays.defaultnow moves the symlink source to the copy we already run; the template needs no change (lib.nix, the repo pkgs, and nixosModules all apply the overlay). - The check that decided the approach: whether the
-wvcopy itself references the plain build. It iscp -aof it, so it plausibly would — and if it did, no wrapper change could drop the duplicate and the whole item was dead. Verified self-contained first, then fixed. Also verified, not assumed:.override { enableWideVine = true; }composes with the overlay'soverrideAttrs(order usually matters — here it survives), so the template's existing line picks the fix up untouched. - Verified: V2 — only
-wv+ the tiny sandbox remain in the template closure. Equivalence proved, not hoped: the wrapper still execs the-wvbuild, WidevineCdm present there,share/{applications,icons,man}match stock with the.desktopbyte-identical. Newchecks.chromium-single-closureasserts the invariant (exactly one full unwrapped chromium — plain or-wv, never both), proved to fail by neutering the overlay's regex: reports "found 2", names both, and warns off the tempting "fix" of dropping enableWideVine (which silently kills DRM). - I overstated this, and measuring the artifact corrected it. I claimed
−687 MiB "on every install". True savings, all measured:
nominal closure −687 MiB (9.38→8.71 GiB), ISO −8 KiB of 8.078 GiB,
installed disk ~−19 MiB, cache-install download −195 MiB. Two
dedupes that closure arithmetic cannot see: mksquashfs detects duplicate
files (the
-wvcopy iscp -aof the plain build, so the ISO stored the blocks once), and auto-optimise-store hardlinks identical files — the two paths share inodes (verified bystat;ducounts 639 MiB for the pair vs ~620 for one). Only the wire can't dedupe: 195 MiB compressed NAR. - The rule this establishes: closure size is not disk size and is not image size. Measure the artifact. Directly relevant to #120, whose whole size table is closure arithmetic — noted there.
- So the fix is a download win (which is what #120's netinstall wants) and ~nothing for today's offline ISO. Whether that is worth coupling an overlay to nixpkgs' wrapper internals is Bernardo's call — raised, not assumed; it is guarded and no-ops if upstream moves. Worth an upstream patch regardless (the wrapper should take its desktop entry from the variant it wraps).
- Pending: nothing hardware-blocked. #120's size table updated (desktop is 13.34 GiB post-#121, not 14.01) and carries the closure-vs-artifact caveat.
- Next suggestion: #118 (smartd self-gate) — Bernardo's stated order.
2026-07-14 — #103: the live ISO gets a desktop, for +41 MiB (this commit)
- Task: BACKLOG #103 — Bernardo, live ISO 2026-07-14: still no browser, no office. "That makes a live iso useful."
- Did: the live HM user in
flake.nixnow names its own set — chromium, libreoffice-fresh, gnome-text-editor, amberol, snapshot. Firefox dropped (Bernardo's call): chromium owns the HTTP mime default and ships in the installed template, and it was the one item that would cost a real closure. - The finding that inverted the trade: I asked Bernardo to choose on a
~+2 GB premise. Wrong premise —
system.extraDependenciesalready pins the template's HM closure into the ISO for offline installs, so chromium/ libreoffice/amberol were already in the image's store, just absent from the live user's profile. Verified, not assumed: the live and template chromium resolve to the same store path, so reusing the template's exactchromium.override { enableWideVine = true; }costs zero — a plainchromiumwould have been a second 2.5 GiB closure. Only text-editor and snapshot are new: 9 paths, 133 MiB uncompressed (99 MiB is gst-plugins-rs). His Firefox call still held for the right reason — it was genuinely unpinned. - Verified: V2 — measured ISO delta (the item's pass condition), both
built from the same tree: 8.038 → 8.078 GiB = +41.2 MiB (+0.50%).
New
checks.live-baseline-appsasserts each app is on PATH and has a .desktop the launcher can see (a bin without one is invisible), that HTTPS resolves to a chromium entry that is actually present (#94's trap), and that Firefox has not crept back. Proved to fail: dropping snapshot makes it name the missing entry. flake check + live-install-entry + option-docs + template-sot green. - Pending: V3 — that the apps launch needs hardware (HARDWARE-QUEUE,
Acer M5-481T: from the launcher only, no terminal). New #119:
text/plainnames vscode, which the live ISO never ships — #94's bug one mime key over, and now the last of its kind. - Where the 8 GiB actually goes (Bernardo asked how Debian fits one in 4 GB;
I first blamed the offline-install pin and that was wrong — measured, the
pin is 4.02 of 18.03 GiB uncompressed, ~22%). The live desktop itself is
14.01 GiB: libreoffice 1457 MiB, initrd 1369, linux-firmware 770, mesa,
fonts, two chromiums (see #121). Debian fits ~4 GB by installing by copying
the live filesystem (no second closure) and by sharing one library version
archive-wide, where Nix pins exact deps per package. Compression is not the
gap — we already use
zstd -19(2.23:1). Bernardo's call: keep the offline ISO as is, add a netinstall variant → #120 (NEXT). Filed #121: the Widevine chromium wrapper drags a second 687 MiB unwrapped chromium in for itsshare/applicationsalone — pre-existing, on every installed machine. - Next suggestion: #118 (smartd self-gate) — Bernardo's stated order.
2026-07-14 — triage: #117 is not work, it's an input to #110 (this commit)
- Task: Bernardo's call on #117 (filed by the previous entry, which suggested it as the next item — it is not; that suggestion is stale).
- Did: Control Center is being retired (#110, NEXT,
[big]), so fixing its toggles builds on a condemned surface. #117 stays filed as a record feeding #110's migration matrix, marked not-standalone. Gave #110 the facts #116 turned up: its Bluetooth/Printing rows write state keys that only became live ina9f3a64, so those two toggles never worked for anyone — meaning there is no behavior to preserve, but the keys and their bridges are real now and must not be dropped with the rows, or a machine whose state saysbluetooth.enable = falsesilently flips back on at the next rebuild.checks.state-bridgeswill fail loudly if that happens. - Verified: V0 —
nix flake check --no-build. Backlog/journal only. - Next suggestion: #110 (the retirement itself, needs splitting first) or
#115 suspend-then-hibernate — both
[human]-gated on a design question.
2026-07-14 — #116: the state bridges that never were (a9f3a64)
- Task: BACKLOG #116 — NixOS options defaulting from
config.nomarchy.settings, an attribute that exists only on the HM side. - Did:
nomarchy.settingsis declared in exactly ONE place (modules/home/options.nix:412), soor <fallback>had been swallowing a missing-attribute error on the NixOS side forever. Options now declare a static default and the implementing module reads the state viastate-read.nix+lib.mkIf (state != null) (lib.mkDefault state)— done forbluetooth.enable(default.nix) andservices.printing.enable(services.nix).batteryChargeLimit's read is simply deleted: power.nix's oneshot reads the key withjqat runtime, which is why that menu worked. greeter.nix moved off a rawfromJSONonto the fail-closed reader. - The finding that mattered: the item said "three options … benign today"
and both halves were wrong. There were four (it grepped
options.nix, notmodules/nixos/— the same mistake in miniature as the bug it filed), and two were live user-facing bugs: Control Center's Bluetooth and Printing toggles wrote state nothing read and printed "requires rebuild", so they reported success and did nothing, for as long as they had existed. - Verified: V2. Before/after eval on the same flipped state proves
the bug was real: BEFORE
hardware.bluetooth.enable=true+printing=false(toggle inert); AFTER both flip, and a hand-set value still outranks the state. Permanent guards, since nothing in a build fails when a bridge dies:checks.state-bridges(11 eval assertions — absent key → default, state → config, hand-set → wins) andchecks.printing-from-state, a runNixOSTest whose node's ONLY input is the state file and which waits for a runningcups.service(+ avahi). The guard was proved to fail: re-breaking the bluetooth bridge made it throw, naming both broken assertions — a check that cannot fail is worse than none (625b7e3's lesson, applied). V0 flake check; option-docs, template-sot, downstream-template-{system,home}, installer-safety, hardware-toggles, battery-charge-limit all green. - Pending: no V3 — the mechanism is fully proved headlessly. New #117 (PROPOSED): the control-center toggles still leave the rebuild to the user, unlike every menu toggle since; a user can't tell "needs a rebuild" from "broken again", which is the symptom #116 just removed.
- Next suggestion: #117 (needs Bernardo's call: rebuild per-toggle vs one
apply-at-exit), or #115 suspend-then-hibernate — also
[human]-gated, and its state read now has a worked shape to copy.
The five entries below were reconstructed from the commits on 2026-07-14 after a session crash — the work was committed and pushed, and each commit did its own sync sweep (BACKLOG #115/#116, HARDWARE-QUEUE, docs); only the journal was missing. Written from the commit messages, not from memory.
2026-07-14 — one fingerprint switch, an auto-login toggle, the state bridge (eb38008)
- Task: Bernardo, post-reboot: "Use for login" was the wrong question — whether the finger works is one decision, and whether login prompts at all is a different one that was never in the menu.
- Did: System › Fingerprint is now a single on/off switch (enroll/list/
verify/delete demoted to plumbing behind it) writing the one
settings.fingerprint.pamkey;idle.nixdefaultsidle.fingerprintfrom that same key, so lock screen and login/sudo move together. New System › Auto-login (nomarchy-autologin), installer-seeded ON for LUKS machines. Making both state-owned surfaced two real bugs:greeter.autoLogindefaulted fromconfig.nomarchy.settings…, an attribute that exists ONLY on the HM side, andor nullswallowed it — the state path never worked on any machine ever built; andstate-sync getprinted Python'sNonefor a JSON null, so anycase … null)would miss. - Verified: V1 — flake check, installer-safety, option-docs pass.
Proved by eval/build: a state carrying autoLogin yields greetd
initial_session, template state yields none, a hand-set null beats the state;fingerprint.pam=truealone renders hyprlock's auth block; both tools bash -n clean and land in systemPackages; the get round trip printsnull. - Pending: V3 — HARDWARE-QUEUE "fingerprint + auto-login toggles on
hardware" (T14s, after unpinning the two system.nix lines). Filed #116
(two more NixOS options read the same phantom bridge — a grep for
config.nomarchy.settingsundermodules/nixos/should return nothing when done) and #115 (suspend-then-hibernate,[human]on delay/AC policy). - Next suggestion: #116 — the worked example is in the tree and the two remaining reads are known.
2026-07-14 — a real lock bind, and a lock screen that speaks in sentences (9792976)
- Task: two nits from the post-reboot hardware pass.
- Did: Super+Escape never locked anything — there was no lock bind at all,
only the power menu's Lock row and the idle timeout. Lock now lives at
Super+Ctrl+L (bare Super+L collides with common app binds), dispatching
loginctl lock-session— the power menu's path, so hypridle'slock_cmdstays the single place deciding what a lock looks like. The prompt's clipped fragments are sentences now, placeholder sentence-cased to match. - Verified: V1 — flake check; the built home generation carries the
bind, the new ready/present messages (built with
idle.fingerprintforced on, since the in-repo config leaves it off), and a cheatsheet row the generator produced on its own from the shared list. - Pending: V3 — the reader itself only exists on hardware.
- Next suggestion: the fingerprint/auto-login menu surface (became
eb38008).
2026-07-14 — put the fingerprint hint where it can be seen (fbbeac6)
- Task:
e2de906fixed the invisible reader and left an invisible message — Bernardo: "unlock worked, but still no message", same symptom as before the fix, completely different cause. - Did: the lock screen is deliberately clock-only — the input field fades
out while empty (hyprlock's
fade_on_emptydefault), so$FPRINTPROMPTin its placeholder rendered faithfully into a widget nobody sees until they had already given up on the finger and started typing. Moved to a label; the placeholder goes back to its exact previous string, so the non-fingerprint path is unchanged. - The lesson: I assumed the field was visible and reasoned from there. It
has never been visible — "it has always been like this" is what cracked it.
Both candidate surfaces (label vs
fade_on_empty=false) were tested on hardware rather than picked; Bernardo chose the label, which keeps the clock-only look instead of making opting into fingerprint mean permanently gaining a widget the design never had. - Verified: V2 — flake check; checks.theme-contrast + option-docs pass
(
subtext-on-baseis held to a 3.0 floor on all 21 themes by the guard that exists because two themes once shipped subtext == base — the same bug as this commit, one layer down). V3 — Bernardo confirms the line reads. - Next suggestion: the lock bind + prompt copy nits (became
9792976).
2026-07-14 — unlock by fingerprint; hyprlock never used the PAM flag (e2de906)
- Task: Bernardo tested the lock screen with
fingerprint.pamon — sudo took a finger, hyprlock did nothing. - Did: the PAM stack was never the problem (grosshack sits in
/etc/pam.d/hyprlockat order 11400 exactly like sudo's) — hyprlock just never asks it: its PAM conversation runs only on submit, so a module wanting to prompt while polling the reader never gets a turn. It has its own fprintd-over-D-Bus backend behindauth:fingerprint:enabled, which nothing in the distro ever set. Newnomarchy.idle.fingerprint(default false), mirroringhardware.fingerprint.pamthe waykeyboard.layoutmirrors the xkb option — hyprlock is configured in standalone HM, which has noosConfig. Opt-in, because with no reader hyprlock advertises a scan that cannot happen. - Verified: V2 — flake check; checks.option-docs passes (failed first with "undocumented option", the check doing its job).
- Pending: V3 — Bernardo applies and confirms both factors work.
- Next suggestion: confirm the prompt actually renders (it did not —
fbbeac6).
2026-07-14 — parallel fingerprint: 3 of 4 counts confirmed, 1 removed as a trap (625b7e3)
- Task: HARDWARE-QUEUE "parallel fingerprint-or-password on the real
reader" (Bernardo, AMD dev box, gen 422,
fingerprint.pam = true). - Did: confirmed on the real reader: one prompt, typed password works,
sensor works, wrong-finger ×3 falls back to password. The fourth count —
"password keeps working with fprintd stopped" — is removed rather than
checked off: fprintd is D-Bus activated, so
systemctl stopdoes not keep it down. Bernardo ran it and the fingerprint still worked, which is exactly the evidence the daemon came back and the dead-reader path was never exercised. A check that passes whether or not the property holds is worse than no check. The property needs no hardware anyway: password isauth sufficientat 11700, independent of the fprintd rule at 11400 — visible by eval, asserted by checks.hardware-toggles in a reader-less VM. - Verified: V3 (hardware, Bernardo) for the three counts; docs-only commit.
- Pending: still open on that item — hyprlock, the greeter (needs the
reboot), and
fingerprint.parallel = falserestoring sequential behavior. - Next suggestion: the hyprlock half (became
e2de906).
2026-07-14 — docking round 7 FAILED; the keyword was inert, not raced (this commit)
- Task: HARDWARE-QUEUE docking round 7 result (Bernardo, AMD dev box) — 5–6 consecutive unplugs, the panel never came back. Round 6's fix did nothing because round 6's diagnosis was wrong.
- Did: Probed it live instead of re-reading the journal. With ZERO enabled
outputs,
hyprctl keyword monitor eDP-1,preferred,auto,1is inert — accepted,ok, exit 0, and never flushed until a DRM event arrives. Not a race: inert across 4s and 5s in two runs.dispatch forcerendererreloadis inert too; onlyhyprctl reloadescapes (99ms / 289ms, cable out). So the transition issues the keyword, and escalates toreloadonly whenmonitorsproves it inert — then re-asserts the rule and callsnomarchy-keyboard-layout restoreper device, since a reload drops runtimedevice[…]:kb_layoutkeywords. Also made the menu'senableprove itself. - The lesson, worth more than the fix: round 6 built its race theory on
enable-timeout×2 +result=ok×1, and I extended it with a "phantom re-add" theory from theadded= DP-2lines. Both were the same artifact: everyresult=okwas Bernardo replugging the cable because the screen was black — his hotplug flushed the queued rule and the next poll claimed the win. A watcher whose success is indistinguishable from the user working around it will keep confirming whatever story you bring. The probe cost 10 minutes and killed two rounds of theory. - Verified: V3 (partial) — the fixed
nomarchy-display-transition undock eDP-1driven through two real unplugs on the dev box: panel on, workspaces 1–3 home, 1.8s,keyword=inert escalate=reload→enable=via-reload→result=ok. Keyboard-restore proven too, on a K400 whose receiver is in the laptop (so it survives the cable): kept its rememberedus, while a control barehyprctl reloaddropped it to the sessiongb— the clobber was an inference until measured, and it makesrestore_keyboardsload-bearing. Plus V2:nix flake check --no-buildall pass;checks.docking-ux+checks.dock-audio+monitor-fallback.nixpass; shellcheck clean on display-transition (profile-watch's lone SC2125 is pre-existing). - Pending: HARDWARE-QUEUE round 8 — the watcher-driven path needs a relogin (exec-once, baked store path) and repetition (5+ unplugs, one with the lid shut). New BACKLOG #114 (PROPOSED): tuigreet ignores per-device layouts.
- Next suggestion: #114, or the dock direction's unverified panel-off (it disables the panel trusting hyprctl's exit code — same class, latent).
2026-07-14 — docking round 6: undock left the laptop panel black (superseded by round 7 above)
- Task: HARDWARE-QUEUE docking round 6 result (Bernardo, AMD dev box). Plug side all passed (auto-dock, audio to the monitor, wallpaper on the external); unplugging left the panel black until re-docked.
- Did: Bernardo's journal was decisive — 3 undocks, 2×
result=enable-timeout+ 1×result=ok, so an intermittent race. Two fixes in modules/home/hyprland.nix: (1) the undockhyprctl keyword monitor eDP-1,preferred,auto,1exits 0 but is dropped when it lands mid-teardown of the departing external — now re-issued every poll for 5s, withmonitorslisting the panel as the only proof; (2) the watcher marked the departure handled via"$TRANSITION" undock … || true+awaiting_lid_open=1andknown_outputshad already moved, so nothing ever retried — one lost keyword = a dark panel. The undock is now a queued invariant driven on the 1s tick (6 attempts, thenresult=gave-up). - Verified: V2 —
nix flake check --no-buildall checks passed;nix build --impure -f tools/monitor-fallback.nixexit 0 in 57s (reaches the finallid-open transitioncheckpoint); shellcheck clean on both generated scripts (the lone SC2125 is pre-existing + intentional). Honest limit: the harness CANNOT reach this race — QEMU's headless backend aborts Hyprland if the last active output is deleted while the DRM output is disabled, so it must undock before removing DP-1 and never collides the two. The fix itself is V3 pending; comment added at tools/monitor-fallback.nix so a reader doesn't mistake a pass for coverage. - Pending: V3 → HARDWARE-QUEUE round 7 (unplug ≥5×; old failure was only ~2 in 3). Rounds 4–6 opened 5 counts: 4 are now confirmed fixed on hardware (wallpaper, auto-dock, monitor audio, keyboard prompting once — Bernardo), the undock is this commit, and headphone jack-follow is still untested — now its own entry, to fold into the round 7 session.
- Next suggestion: wait on round 7 before touching the dock path again.
2026-07-13 — #99 live-seed git-init; theme-switch failure filed as #113 (this commit)
- Task: BACKLOG #99 — false "state.json NOT git-tracked" doctor/ Waybar warning in the live session; resolve the held question from Fable.
- Did: hosts/live.nix
nomarchy-seed-flakenowgit init+add+commits the seeded~/.nomarchy(like nomarchy-install.sh:654), so the live checkout is a committed repo. Also committed #94's live-posture comment in flake.nix (separate commit). - Verified: V2 — focused serial-log VM run (
/tmp/nomarchy-v2-theme-99/): doctor prints✔ state.json is git-tracked+✔ flake checkout is clean,GIT_REPO_OK/TRACKED_OKmarkers. Held question RESOLVED: the same run's offline gruvbox switch failed with a 1176-drv source rebuild, but a local drv-equivalence test proved the failingbvl30ggn…home-manager-generation.drvis BYTE-IDENTICAL path-seeded vs git-seeded → the git-seed is exonerated; the failure is a pre-existing ISO-pinning gap (unpinned non-default-theme generation), now filed as #113. - Pending: #113 (offline theme-switch contract); #94 launch check; #97 V2 click; #96 V3 + #101 round 2 (HARDWARE-QUEUE).
- Next suggestion: #113 — decide pin-all-themes vs scope the offline promise.
2026-07-13 — #96+#97 menu gates explain instead of vanish/raw-fail (this commit)
- Task: BACKLOG #96 (battery-limit row silently absent on threshold-less firmware) and #97 (raw "Connection to BlueZ failed").
- Did: rofi.nix — Battery limit row now gates on
has_system_battery(like Power profile); the leaf explains a missingcharge_control_end_thresholdas a firmware capability. Bluetooth leaf checksbluetooth.servicebefore exec'ing blueman and explains the service-down vs no-adapter (/sys/class/bluetoothempty) cases with rfkill/firmware hints. - Verified: V1 — built nomarchy-menu, bash -n green, both new paths present in the generated script; V0 flake check green. VM can't fake a threshold-less battery or a BT adapter, so the behavioral checks are queued: #96 → HARDWARE-QUEUE (Acer + T14s row check); #97 → the no-adapter message is exercisable in the next QEMU run (planned with #94's test-install pass; VMs have no BT adapter).
- Pending: #97 V2 click-check in the next VM run; #96 V3 on the Acer.
- Next suggestion: #94 test-install run (chromium launch + BT click).
2026-07-13 — #107 direct System/Tools menu keybinds (this commit)
- Task: BACKLOG #107 — conflict-free direct bindings via keybinds.nix.
- Did:
SUPER+CTRL+I→nomarchy-menu system(Super+I settings muscle memory),SUPER+CTRL+T→nomarchy-menu toolsin keybinds.nix (single source: Hyprland + cheatsheet); root-menu Tools/System rows now carrymenuHintshortcut hints. - Verified: V2 — eval: 41 binds, zero duplicate mods+key; both binds in
the generated Hyprland config; built nomarchy-menu bash -n green with
cheatsheet rows + hints rendered. In-session on the live ISO: VIEWED
/tmp/nomarchy-v2-swap-93/40-system-menu.png+41-tools-menu.png— both submenus open directly from the binds. V0 flake check green. - Pending: nothing.
- Next suggestion: #99 pending the focused doctor/theme-switch VM run.
2026-07-13 — #93 installer swap prompt labeled + explained (this commit)
- Task: BACKLOG #93 — the swap field was a bare prefilled gum input (no visible section, label, or unit; the placeholder never shows once a value is prefilled).
- Did:
nomarchy-install.sh: visible "Swap & hibernation" section, two info lines (default = RAM ⇒ hibernation-ready; 0 = no swap), a labeled--headeron the input, and unambiguous info + Review lines ("N GiB swapfile (enables hibernation)" / "none (hibernation disabled)"). - Verified: V2 — full interactive KVM UI drive on the built ISO; VIEWED
/tmp/nomarchy-v2-swap-93/10-swap-prompt.png(section, both info lines, labeled prefilled input) and…/30-doctor.png(Review box: "Swap: 6 GiB swapfile (enables hibernation)"); wipe confirm aborted by mismatch, nothing touched. bash -n + V0 flake check green. - Pending: side-finding: QEMU exposed
/dev/fd0as the FIRST picker row — recorded as live repro evidence on #112. - Next suggestion: #99/#107 commits from the same evidence run.
2026-07-13 — charge-limit start-limit-hit on spaced AC storms (this commit)
- Task: Live V3 failure of #101 (TuringMachine doctor badge, 18:16): a
spaced dock/AC event storm → 5 successful starts in 10s →
start-limit-hit, unit marked failed though every run succeeded. - Did:
unitConfig.StartLimitIntervalSec = 0onnomarchy-battery-charge-limit(idempotent sub-second write — rate limiting only manufactures false failures); extendedchecks.battery-charge-limitwith the exemption assert + an 8× sequential start loop and a clean-state check. - Verified: V2 — the check passes under KVM (exit 0: exemption asserted, 8 spaced starts, not failed, no start-limit-hit; original coalescing phase still green). V0 flake check green.
- Pending: V3 round 2 re-queued in HARDWARE-QUEUE (#101 entry updated).
- Next suggestion: land the in-flight #93/#99/#107 evidence run.
2026-07-13 — #102 Nextcloud Desktop opt-in in the template (this commit)
- Task: BACKLOG #102 — document upstream HM
services.nextcloud-clientas a downstream-template opt-in; no Nomarchy wrapper. - Did: Commented
services.nextcloud-clientblock intemplates/downstream/home.nix(enable + startInBackground), and pointed the bare# nextcloud-clientpackage line at it (service = app + session lifecycle; re-comment removes both). - Verified: V1 — pinned HM 26.05 module confirmed
(enable/package/startInBackground); eval test on an uncommented template
copy via
lib.mkFlake: unit ExecStartnextcloud --background, WantedBy/PartOfgraphical-session.target.nix flake check --no-buildgreen (includes template-sot + downstream-template-home). - Pending: nothing — runtime lifecycle is the upstream module's contract.
- Next suggestion: #93/#99/#107 land next (shared live-VM evidence run).
2026-07-13 — User-promoted NEXT queue curation (#102–#112; this commit)
- Task: Audit Bernardo's live-ISO, application, menu, and device follow-ups against shipped behavior and curate the executable queue.
- Did: Promoted scoped work as NEXT #102–#112, with
[big]split gates for System-menu IA and Control Center retirement. Reused NOW #96 for the Acer threshold finding; #106/#108 start from shipped navigation/bind coverage. - Verified: V0 — read-only source/option/menu audit and
git diff --check. - Pending: #105 and #110 must be split before implementation; no runtime behavior changed.
- Next suggestion: #93 remains the NOW head; #102 is the first NEXT item.
2026-07-13 — #92 catalog-only installer keyboard selection (this commit)
- Task: Make installer layout/variant choices understandable without allowing arbitrary XKB values to break generated Nix.
- Did: Added a pinned human-readable XKB catalog, a one-step US/default path, strict searchable layout/variant pickers, shared exact validation for interactive and unattended input, and a resolved review summary.
- Verified: V2 — full flake eval; installer safety/keyboard/package builds; shell/Python/diff checks; real validator accepts valid layout-specific rows and rejects fabricated/prefix/wrong-layout values before installer setup. Exact-current-ISO KVM UI review captured catalog, variant, and review screens; strict unmatched input was rejected and the blank disk remained untouched.
- Pending: V3 real-hardware install remains; V2 artifacts are under
/tmp/nomarchy-v2-keyboard-92-current/. - Next suggestion: #93 swap-size prompt and explanation.
2026-07-13 — #91 installer no-variant normalization (this commit)
- Task: Stop the keyboard picker's display-only
(none)value from breaking generatedxkb-console-keymap.drvand the whole installation. - Did: Normalize at the shared input boundary and defensively in the real
template patcher. Added a
us+ sentinel fixture, actual console-keymap build, and made the offline installer VM carry the literal sentinel. - Verified: V2 — full flake eval; focused installer-keyboard/safety/
template builds; shell/Python/Nix syntax and diff checks; KVM
tools/test-install.shinstalled offline with LUKS + swap, powered off after ~400s, unlocked, and booted the themed desktop. Inspected install progress, LUKS, and first-boot captures under/tmp/nomarchy-vm/. - Pending: #92 now explicitly forbids free-form XKB values. Expanded the existing per-device keyboard hardware check for the connected-at-login menu.
- Next suggestion: #92 installer keyboard selection clarity/safety.
2026-07-13 — #101 charge-limit AC-event burst recovery (this commit)
- Task: Fix
nomarchy-battery-charge-limit.servicefailing when USB-C dock power events arrive while its settling write is still active. - Did: The oneshot now returns inactive after success; immediate and
delayed udev paths use coalescing
startjobs instead of interruptingrestartjobs. Strengthened the focused VM with a 12-event Mains burst during an extended active run and explicit failed/start-limit assertions. - Verified: V0
nix flake check --no-build, module parse, andgit diff --check; V2nix build .#checks.x86_64-linux.battery-charge-limit --no-link -Lunder KVM — the 12-event active-run burst finished inactive/success, changed InvocationID, and produced no failed/start-limit journal result. - Pending: V3 post-rebuild dock-power burst check in HARDWARE-QUEUE.
- Next suggestion: run V3 #101 alongside docking round 4, then #91.
2026-07-13 — #100 dock transition recovery (this commit)
- Task: Fix the real T14s dangling workspace, closed-lid cable-removal
suspend/apparent crash, and BenQ audio miss after
7ebfab4. - Did: Added one atomic dock/internal-first undock helper; the IPC watcher
owns a verified low-level lid inhibitor through physical lid-open, with
validated stale-process cleanup.
monitoraddednow debounces a settled PipeWire/WirePlumber reprobe then picks an available dock sink; generic audio events never override a manual choice. Named clamshell profiles share the safe transition. Replaced the fallback VM tool with a bounded hotplug workspace/output/inhibitor test and strengthened generated-artifact guards. - Verified: V2 —
nix flake check --no-build; targeted docking-UX, option-docs, and template-SoT builds; andnix build --impure -f tools/monitor-fallback.nix --no-link -Lall green. The KVM guest proved atomic workspace handoff, internal-first restoration, inhibitor retention with the simulated lid closed, and release on lid-open. The harness restores the DRM output before deleting QEMU's last synthetic headless output because that backend-specific zero-output state aborts Hyprland before a usable removal lifecycle is delivered. - Pending: V3 exact closed-lid BenQ round 4 in HARDWARE-QUEUE. No real-hardware or real monitor-audio claim.
- Next suggestion: run V3 round 4, then take installer #91.
2026-07-13 — Live ISO hardware findings queued (#91–#99)
- Task: Transcribe Bernardo's Acer Aspire M5-481T install/session notes and installer failure photo into the executable queue.
- Did: Added nine separate NOW items: literal
(none)XKB install failure, keyboard/swap installer clarity, missing browser, Ghostty launch, charge-threshold discoverability, BlueZ failure, Boreal button contrast, and the false-looking untracked-theme warning. - Verified: V0 — exact backlog IDs/content reviewed; Nix failure's first
causal error preserved separately from cascading dependency failures;
git diff --checkgreen. - Pending: implementation and item-specific V1–V3 verification.
- Next suggestion: #91 — fix the installation-blocking keyboard variant.
2026-07-13 — Docking hardware-QA corrections (interactive feedback)
- Task: Bernardo's real clamshell QA: menu on hidden eDP, no keyboard layout route, audio stayed on speakers, laptop-off lost apps, abrupt undock never restored eDP.
- Did: Rofi → focused output; replaced eDP disable with safe Dock mode
(move workspaces/focus, keep fallback); display watcher now unconditional,
reconnecting and race-tolerant. Keyboard watcher runs by default with all
XKB layouts + System › Keyboard. Audio also reacts to card/port changes;
monitor-added re-applies the current awww wallpaper to the new output.
Corrected the fallback harness assumption; added
checks.docking-uxand synced README/template/ROADMAP/hardware queue. - Verified: V1 —
nix flake check --no-build;checks.docking-uxbuilt the real HM generation and passed syntax/invariant/layout-catalog assertions; option docs 90/90, template SoT 4/4; Nix parse + Python compile + diff check. V2 unavailable (no readable KVM). - Pending: hardware retest in HARDWARE-QUEUE (docking correction round 3).
- Next suggestion: hardware retest this exact dock sequence.
2026-07-12 — #89 slice 3: Documented Signal tray icon limitation (no commit)
- Task: BACKLOG #89 slice 3 — Signal's tray icon is full-colour blue and doesn't match the monochrome bar.
- Did: Researched Signal's Linux tray icon behavior. Found it is a hardcoded, dynamically generated pixmap (
Signal_status_icon_1) driven by its Electron wrapper with no built-in toggle for a monochrome icon. Added an entry todocs/ROADMAP.md's known issues noting that certain Electron apps cannot be natively themed. Closed out #89 from the backlog without introducing brittleapp.asarrepacking hacks. - Verified: N/A (Documentation only).
- Pending: #89 is fully closed.
- Next suggestion: Pick the next item from the BACKLOG.
2026-07-12 — CI OOM: memory-bounded eval for check.yml/bump.yml
- Task: Bernardo: check.yml always red since he capped the runner container at 2 GB (uncapped it OOM'd the whole 4 GB VPS); bump.yml status unknown.
- Did: Measured (GNU time, eval-cache off): one-process
nix flake check --no-buildpeaks 6.0 GB RSS — that's the whole story. Newtools/ci-eval.sh: same coverage, ONE output per nix process (heap freed between outputs); both workflows now call it. bump.yml also got max-jobs=1/cores=2. Facts: bump.yml WORKS — landed8fded63on 2026-07-06, on schedule; ROADMAP's "no CI today" was stale → fixed. - Verified: V1+ — ci-eval.sh ran green locally end-to-end (3:22); per-output cold peaks measured: worst check 0.99 GB (hardware-toggles), nomarchy toplevel 0.78 GB, HM 0.60 GB, except nomarchy-live 2.69 GB (live ISO eval) — fits only with the container's swap allowance (docker default --memory-swap = 2×memory); if Bernardo set swap off, that one output still OOMs → server-side one-liner (--memory=2g --memory-swap=6g) or a skip-hatch decision.
- Pending: real proof is the next push's Actions run on the VPS — watch nomarchy-live's step; can't be verified from this machine.
- Next suggestion: confirm green run on the remote, then hardware V3 batch.
2026-07-12 — parallel fingerprint-or-password (interactive, promoted)
- Task: Bernardo promoted the PROPOSED "fingerprint or password in parallel" item live; wants it default-on for fingerprint-PAM users.
- Did: Packaged pam-fprint-grosshack v0.3.0 (pkgs/, source-reviewed
first: all failure paths → PAM_AUTHINFO_UNAVAIL, typed password only
ferried via AUTHTOK to pam_unix try_first_pass — can't lock out
password login). New
nomarchy.hardware.fingerprint.parallel(default true; false = stock sequential). Wiring swaps stock fprintd's rule modulePath (mkForce) so ordering is inherited. README/template rows; BACKLOG PROPOSED entry closed into ROADMAP ✓. - Verified: V2 — checks.hardware-toggles extended to three nodes and
green: parallel node asserts grosshack line before pam_unix in
/etc/pam.d/sudo AND
sudo -Swith the right password succeeds / wrong password fails with NO reader present (the lockout invariant); seqpam node = stock pam_fprintd, no grosshack; nopam = neither. Package builds (meson needed libpam-wrapper + python3). flake check green. - Pending: V3 on the AMD dev box (HARDWARE-QUEUE): the actual type-or-touch race, fprintd-stopped fallback, hyprlock/greeter behavior after a fingerprint win (pthread_cancel'd prompt quirk).
- Next suggestion: dock + fingerprint V3 batch on hardware, then #89 slice 3.
2026-07-12 — undock blackout rescue (interactive follow-up)
- Task: Bernardo: "if I turn the laptop screen off and undock, does the panel come back?" Answer had to be tested, not recalled.
- Did: Built tools/monitor-fallback.nix (softGL desktop VM, crib of
theme-shot): headless "external" + menu's exact disable + output
remove. Verdict: Hyprland 0.55.4 does NOT re-enable → shipped
rescue_blackoutin the display hotplug watcher (immediate + retried keyword re-enable of disabled outputs on zero-active, toast). - Verified: V2 for the hazard (VM reproduced the dead state);
rescue itself is V1+components — the VM crashes before rescue can act
in 4/5 runs (aquamarine ABRT in dispatchIdle on the zero-output
state; control with panel active survives 5/5 — discriminator run).
Crash predates rescue (run with rescue provably inert also crashed).
Also fixed:
grep -c .exit-1-at-zero disabling the rescue's own trigger. flake check green. - Pending: real-dock V3 (HARDWARE-QUEUE, "nothing important open" warning); if real DRM crashes too → rework row (mirror) or wait for Hyprland bump; consider reporting upstream with the coredump.
- Next suggestion: dock V3 results, then #89 slice 3.
2026-07-12 — dock audio auto-follow + docked menu rows (interactive)
- Task: Bernardo's dock test (= #87's V3): audio stayed on speakers, had to hand-tweak EasyEffects; wants docked Display/Audio menu options.
- Did: Root-caused live on Newton: WirePlumber's stored default
(default-nodes) outranks the #87 priority rules (control test: new
sink, no watcher → default pinned), and the running gen lacked the
rules anyway; EE 8 follows the default fine (kcfg default true +
observed links move). Shipped
modules/home/dock-audio.nix(nomarchy.dockAudio.enable, on): pactl-subscribe watcher set-default-sinks new dock-class sinks (regexes imported from dock-audio-rules.nix) + toast + startup sweep. Menu: Display gains laptop-off/screen-on/move-workspace/swap rows (live-only keywords); Audio gains self-gated "Send output → " row. - Verified: V2-equivalent live on Newton — watcher: fake dock-named null sink → default followed, unplug → fell back, EE links moved mid-playback (pw-link); menu: generated script bash -n, dock-row jq exercised against real pactl JSON, dispatchers probed on live Hyprland. flake check green; option-docs green. Beware: kill the subscribe pipe by PID — pkill -f self-matches the test shell.
- Pending: real-dock V3 ×2 in HARDWARE-QUEUE (watcher may miss sinks that pre-exist and only flip route availability — capture pactl subscribe + sink JSON if it fails again).
- Next suggestion: #89 slice 3 (Signal pixmap) or dock V3 feedback.
2026-07-12 — auto-commit sweep before pull/rebuild/home (interactive)
- Task: Bernardo's request (no BACKLOG item): with autoCommit on,
hand edits to
~/.nomarchy(his had 4) stayed forever-dirty — state-sync's commit is pathspec-limited to state.json by design. - Did: New internal
nomarchy-autocommitin nomarchy-lifecycle: live-readssettings.autoCommit, commits everything dirty with messagenomarchy: auto-commit before <label>+ file list in the body; called (|| true, never blocks) at the top of nomarchy-pull / -rebuild / -home. Exposed aspassthru.autocommit; package exported. Docs/comments swept: README, RECOVERY, ROADMAP ✓ entry, rofi toggle text, control-center prompt, state-sync docstring. - Verified: V1+ —
nix flake check --no-buildgreen; new permanentchecks.lifecycle-autocommitbuilds (real binary, sandbox repos: sweep/clean/off/non-repo); end-to-end on a copy of the real ~/.nomarchy via built nomarchy-rebuild with stubbed sudo/rebuild — the 4 real dirty files landed in one commit, tree clean. No VM boot: no session-visible surface. Real-machine confirmation lands after the next nomarchy-pull picks up this rev. - Pending: nothing queued; Bernardo's actual ~/.nomarchy still has its 4 uncommitted files until his next pull/rebuild with the new rev.
- Next suggestion: back to BACKLOG (#89 slice 3, Signal pixmap).
2026-07-12 — #89 slice 2: EasyEffects tray icon themed monochrome (b98248f)
- Task: BACKLOG #89 slice 2 — EasyEffects SNI shows Papirus' full- colour blue equaliser, clashing with the monochrome tray.
- Did: Wrapped the resolved icon set in a
Nomarchy-iconschild theme (theme.nix) that Inherits it + ships a scalable, palette-text- coloured monochrome easyeffects glyph (the app's own -symbolic shape); made it the session icon theme. Single shared layer, so it covers all themes (all resolve to Papirus-); colour tracks each theme viachecked.colors.text. iconTheme feeds stylix+rofi, both fine via Inherits. Fixed a slip:git add -Aswept a settings.local.json.tmp. into the commit → untracked + gitignored (f9d5e2c). - Verified: V3 in Boreal (Bernardo confirmed live). Mechanism pre-validated by GTK IconTheme lookup (override wins 16–32px; udiskie/ nm/folder still Papirus). No theme uses a custom icon pack, so Boreal+ Papirus covers the set. NB: cursor-warp doesn't refresh the tray — needs a waybar restart (new icon-theme cache).
- Pending: slice 3 — Signal (
:1.227, generated pixmap, full-colour blue round icon); pixmap apps can't be fixed by name override. - Next suggestion: #89 slice 3 (Signal) or close #89 if pixmap apps are accepted as documented-not-fixable.
2026-07-12 — tray menus truly fixed: counter-rules must live in waybar.css (8eb672b, 72e53e2)
- Task: Bernardo: icons still missing in the REAL nm-applet menu.
- Did: e8658fe's gtk.css cure worked in a plain GTK app but not in
Waybar: Waybar adds its provider at GTK_STYLE_PROVIDER_PRIORITY_USER
too (src/client.cpp) and wins the tie in practice (GTK 3.24) — proven
by repro at priority 900 matching the live menu exactly. Only rules in
the SAME stylesheet out-specify its
*, so every waybar.css now carries a menu block after the reset: arrow 16px, check/radio 14px, separator 1px,menu, menu *font (labels are matched directly by*, inheritance never applies). D-Bus GetLayout first proved nm-applet exports per-network icon-data. - Verified: V3 on the real menu — opened nm-applet's tray menu via wlrctl virtual-pointer clicks, grim captures: arrows, checkmarks, separators, Inter labels, Pica's icon, and every network's signal icon in the Available-networks submenu. Bar pills intact. NB: cursor-warp hover does not open GTK submenus (no motion events) — click the item.
- Pending: nothing for this item.
- Next suggestion: #89 slice 2 — the override-icon layer.
2026-07-12 — #90 correction: scoping regressed the bar; USER-priority cure (e8658fe)
- Task: Bernardo reports
ac7e6bdbroke Boreal's bar + icons still missing. - Did: Two lessons. (1)
window#waybar *carries id specificity, so the reset started beating the later class rules (pill radius/borders) that plain*correctly lost to — reverted all three stylesheets; arrows restored instead via stylix gtk.css (menu menuitem arrow { min-width/height:16px }) — USER priority (800) outranks waybar's APPLICATION (600) regardless of specificity, same mechanism as the existing check/radio rule. NB comments guard each*block. (2) The "missing icons" were also GTK3'sgtk-menu-imagesdefault-off: setgtk.gtk3.extraConfig.gtk-menu-images = 1. - Verified: V3 — repro (no forced always-show-image): icon, check and arrow all render even with Boreal's reset injected screen-wide; bar screenshot shows pills restored. Flake check green.
- Pending: Bernardo eyeballs the real nm-applet menu (icons + arrow).
- Next suggestion: #89 slice 2 — the override-icon layer.
2026-07-12 — #76 closed: hibernate V3 PASSED on TuringMachine (this commit)
- Task: BACKLOG #76
[human]closure — Bernardo reports the V3 check. - Did: Bernardo ran the real power-cycle on the T14s (LUKS + btrfs
@swapswapfile): hibernate → power off → single LUKS unlock → session restored, "flawlessly". Deleted #76; HARDWARE-QUEUE resume entry pruned (outcome recorded here + ROADMAP ✓-entry updated); Decisions note marked shipped. The no-swap Hibernate notify check stays open in HARDWARE-QUEUE as the one leftover. - Verified: V3 (human, real hardware). Docs-only commit otherwise.
- Pending: no-swap notify check (needs a swapless session or
temporary
swapoff -a). - Next suggestion: #89 slice 2 — the override-icon layer.
2026-07-12 — #90 tray submenu arrows: root cause was waybar CSS (this commit)
- Task: BACKLOG #90
[stuck](interactive, Bernardo driving on T14s). - Did: Diagnosis was wrong — Papirus-Dark resolves
pan-end-symbolicfine via its breeze-dark inheritance (breeze ships inside the nixpkgs papirus output). Real cause: Waybar's stylesheet applies process-wide, and the* { min-height: 0; }block collapsed the arrow node in the SNI tray menus Waybar hosts. Scoped the*block towindow#waybarin boreal + executive-slate waybar.css and waybar.nix generatedStyle (tooltip rules restate the font — tooltips are separate toplevels); removed the go-next-symbolic remap workaround from stylix.nix. - Verified: V3 — live GTK3 repro app popping a dbusmenu-shaped
menu, screenshotted via grim: arrow vanishes with old CSS injected
screen-wide, renders with fixed CSS; property bisect pinned
min-height: 0as the sole culprit. V1 flake check green. - Pending: post-switch check that the real nm-applet menu shows the arrow (needs a human click on the tray icon).
- Next suggestion: #89 slice 2 — the override-icon layer.
2026-07-11 — interactive T14s session: migration follow-ups (50a5586…6967d89)
- Task: Escalation — Bernardo driving, live on the migrated T14s (first full session on real Nomarchy hardware; 7 commits).
- Did: autologin restored (migration missed the LUKS-machine line —
fixed downstream + MIGRATION.md example); SUPER+0 → workspace 10;
VPN tooltip names active VPNs (stuck-shield confusion was Tailscale);
battery "Not charging" hold-band tooltip (+ 4 whole-swap themes);
GTK submenu arrows (bundled SVG — Papirus lacks pan-end-symbolic and
inherits uninstalled breeze); xdg.userDirs.setSessionVariables pinned
(HM 26.05 flip); easyeffects gated on a live tray host (After=
waybar.service was inert — waybar is supervisor-run, not a unit);
#89 slice-1 SNI inventory recorded; #76 unblocked →
[human]. - Verified: V3 throughout — live binds via
hyprctl binds, GTK menu screenshot (arrow + check render), SNI watcher registration, deployed configs inspected; V1 flake check green on every commit. - Pending: Bernardo:
nomarchy-rebuild(autologin + new services), then the #76 hibernate power-cycle. #89 targets narrowed to EasyEffects (slice 2) + Signal (slice 3). - Next suggestion: #89 slice 2 — the override-icon layer.
2026-07-11 — hotfix: Left=Back bound over rofi default → every menu dead
- Task: Escalation — V3 on the migrated T14s: all
nomarchy-menuentry points (main, battery, power-profile, VPN) showed rofi's "Binding 'Left' is already bound" error dialog instead of a menu. - Did:
rofi.nix— releasekb-move-char-backtoControl+bbefore binding-kb-custom-1 Left, in bothrofi_menucopies (menu + vpn). rofi hard-fails on duplicate bindings, and reports it in a GUI dialog, not stderr — stub tests andbash -ncan never catch this class. Filed PROPOSED: EasyEffects 8 blue tray icon; parallel finger/password. - Verified: V3 — real rofi on the T14s: old flags reproduce the
error dialog (screenshot), fixed flags render the menu; after HM
switch,
nomarchy-menurenders end-to-end. V0 flake check green. - Pending: flatpak apps missing from drun = stale session env (relogin), not a code bug. EasyEffects icon + pam items in PROPOSED.
- Next suggestion: V3 sweep of the remaining
05bab55session items.
2026-07-11 — post-migration fix batch (05bab55; entry backfilled)
- Task: Escalation — first real-hardware migration (TuringMachine → Nomarchy) surfaced a batch of annoyances; session crashed before journaling, entry written by the follow-up session.
- Did: Force fprintAuth off unless
fingerprint.pam; first-boot toast waits for swaync + retries; night-light handles masked units; VPN menurofi_menuno-op fixed; ← = Back in list menus; GTK menu contrast; mic-mute LED udev rule + sync; EasyEffects after tray; MIGRATION.md notes. - Verified: V0 flake check; checks.first-boot; checks.hardware-toggles.
- Pending: V3 on the migrated machine. Follow-up found the downstream
~/.nomarchylock still pinned the previous commit — the user's rebuild excluded this batch (mic LED "regression" was just that). Also: HMprograms.chromium.extensionsfrom the old config wasn't carried over, so Chromium externally-uninstalled all extensions and their data (wallets included); recovered from thepre-nomarchy-homebtrfs snapshot. MIGRATION.md browser note rewritten with the real mechanism. - Next suggestion: V3 sweep of the
05bab55items after a locked rebuild.
2026-07-11 — #88 neon-glass polish / finish
- Task: NEXT #88 — finish neon-glass (
VISION § D), not quarantine. - Did: Rewrote
themes/neon-glass/rofi.rasi(was invalidvar()CSS; now Boreal-style glass with@colors, cyan edge, soft selection). btop accent titles/selection; JSON ui rounding 14 + slight glass opacity;preview.pngfrom theme-shot desktop. No waybar.css. - Verified: V2 — contrast 24×7 pass; theme-wholeswap green; theme-shot neon-glass desktop+menu viewed (cyan bar + glass menu); boreal theme-shot regression green (menu/bar intact).
- Pending: —
- Next suggestion: post-install hardware hints PROPOSED, or human HARDWARE-QUEUE.
2026-07-11 — Promote neon-glass → NEXT #88 (Bernardo)
- Task: human triage: promote neon-glass PROPOSED.
- Did: NEXT #88 neon-glass polish/finish (
VISION § D); path = finish (not quarantine). Notes: no broken waybar.css reintro without wholeswap parity; V2 theme-shot required. PROPOSED pitch removed; VISION pointers updated. No implementation this commit. - Verified: V0 (backlog/docs only).
- Pending: —
- Next suggestion: implement #88 (theme-shot V2).
2026-07-11 — VISION hygiene + PROPOSED (queue empty)
- Task: QA/docs loop — NEXT still only #76
[blocked:hw]; no product item to implement without inventing work. - Did: Marked Theme A/B/C shipped rows in
docs/VISION.md(Firmware #43, Fingerprint #55, doctor stack, rebuild errors #56, Boreal default, hibernate confidence #77). Rewrote “Suggested agent slices” to open work only. PROPOSED: post-install hardware hints; neon-glass finish/quarantine[human]. - Verified: V0 — docs/backlog only (no module change). Prior iteration’s V2 suite still stands; no regression claimed here.
- Pending: human triage of PROPOSED; HARDWARE-QUEUE V3.
- Next suggestion: promote post-install hints → NEXT, or human HARDWARE-QUEUE / neon-glass call.
2026-07-11 — QA sweep (queue empty but #76)
- Task: QA sweep — NEXT only has #76
[blocked:hw]; no other actionable items. - Did: option-docs (88 opts) + template-sot green; HM generation has What changed? / doctor float / first-boot unit; rotated JOURNAL.md 41→18 entries (tail → JOURNAL-ARCHIVE). No product code change.
- Verified: V2 —
nix flake check --no-build; rebuilt green: doctor, first-boot, what-changed, clamshell-logind, dock-audio, windowrule-syntax, battery-notify, zram-swap, nightlight-geo. - Pending: #76 V3 hibernate on Nomarchy hardware; #86/#87 V3 dock QA.
- Next suggestion: HARDWARE-QUEUE pass by human, or promote LATER wallpapers split / triage PROPOSED.
2026-07-11 — #87 dock audio sink priority
- Task: NEXT #87 — default audio follows dock plug/unplug.
- Did: WirePlumber
90-nomarchy-dock-audio(HDMI/DP session prio 1100, USB 1050) viamodules/nixos/dock-audio-rules.nix+ default.nix pipewire.checks.dock-audiopure rule asserts + conf-file VM. V3 hotplug steps in HARDWARE-QUEUE. Closed #87. - Verified: V2 —
nix flake check --no-build;checks.dock-audiogreen (pure rule asserts + conf installed under wireplumber.conf.d). - Pending: V3 real HDMI/USB-dock hotplug (HARDWARE-QUEUE).
- Next suggestion: QA sweep or LATER wallpapers split if promoted.
2026-07-11 — #86 clamshell HandleLidSwitchDocked
- Task: NEXT #86 — lid closed + external monitor must not suspend.
- Did: Explicit
HandleLidSwitchDocked=ignoreinmodules/nixos/power.nix(logind settings.Login). Undocked lid behaviour unchanged. idle.nix comment corrected.checks.clamshell-logindasserts conf + active logind. V3 steps in HARDWARE-QUEUE. Closed #86. - Verified: V2 —
nix flake check --no-build;checks.clamshell-logindgreen (HandleLidSwitchDocked=ignore+ logind active). - Pending: V3 real lid+external on laptop (HARDWARE-QUEUE).
- Next suggestion: #87 dock audio sink follow.
2026-07-11 — #85 hardware hall of fame + split #84
- Task: NEXT #85 docs hall of fame; #84 was
[big]→ split. - Did: HARDWARE.md §9 install-tested table (T14s Gen 4 AMD, Latitude 5410/5310) + DMI PR invite; renumbered following sections. #84 → #86 clamshell + #87 dock audio. VISION/ROADMAP; closed #85.
- Verified: V0 (docs only).
- Pending: —
- Next suggestion: #86 clamshell or #87 dock audio (both product).
2026-07-11 — #83 doctor first-boot pre-activate flag
- Task: NEXT #83 — doctor points at failed installer HM pre-activate.
- Did: doctor row: if
/var/log/nomarchy-hm-preactivate.logis present and no Home Manager generation exists → ✖ +home-manager switch --flake ~/.nomarchy -b bak. Skip/ok otherwise. Extendedchecks.doctor(fail arm + recovered gen). Closed #83. - Verified: V2 — checks.doctor green (fail arm + recovered gen); local smoke with NOMARCHY_HM_PREACTIVATE_LOG / empty HOME.
- Pending: —
- Next suggestion: #85 docs hall of fame (cheap) or split #84 dock.
2026-07-11 — #82 generation readability
- Task: NEXT #82 — plain-language “what changed last rebuild”.
- Did:
pkgs/nomarchy-what-changed(nvd → “N added, M removed, K updated”); wired into lifecycle post-nomarchy-rebuild/nomarchy-home(full nvd + notify toast); System › What changed? (toast + floating full report).checks.what-changedwith NOMARCHY_NVD fixture. Closed #82. - Verified: V2 — checks.what-changed green; local smoke on real HM gens (“Desktop: 1 added, 1 removed”) + fixture counts.
- Pending: —
- Next suggestion: #83 doctor pre-activate fail flag or #85 docs.
2026-07-11 — #81 first-boot welcome toast
- Task: NEXT #81 — dismissible “you're set” card (
VISION § B). - Did:
pkgs/nomarchy-first-boot+ user oneshot (modules/home/first-boot.nix): notify once with SUPER+M/T/? + Network- Doctor pointers; marker
settings.firstBootShownvia theme-sync--no-switch(in-checkout state). Skip live hostname. Optionnomarchy.firstBootWelcome.enable(default on).checks.first-boot. ROADMAP/VISION/README; closed #81.
- Doctor pointers; marker
- Verified: V2 —
nix flake check --no-build;checks.first-bootgreen (toast + marker + silent re-run + live skip); local shim smoke; downstream-template-home carries the user unit. - Pending: V3 — real swaync rendering on first installed login (toast body is pure text; not queued unless it misbehaves).
- Next suggestion: #82 generation readability or #85 docs hall of fame.
2026-07-11 — #80 doctor battery health readout
- Task: NEXT #80 — battery health in
nomarchy-doctor(VISION § C). - Did: Doctor row:
cycle_count+ retained capacity (charge_full/designorenergy_*) as% of design; system batteries only; soft warn <70% design; skip when attrs absent.NOMARCHY_POWER_SUPPLY_ROOTfor the VM fixture. Extendedchecks.doctor(fake BAT0 + Device-scope MOUSE0 ignore). HARDWARE §10, ROADMAP ✓, VISION ✓; closed #80. - Verified: V2 —
nix flake check --no-build;checks.doctorgreen; local smoke on real BAT0 (342 cycles, 81% via energy_*) + fixture. - Pending: Power-menu surface left optional/out of scope (doctor is the product surface for report-only health).
- Next suggestion: #81 first-boot welcome card (highest product ROI) or #85 docs-only hall of fame.
2026-07-11 — Triage: VISION-gap PROPOSED → NEXT #80–#85 (Bernardo)
- Task: Bernardo promoted five of the six fresh VISION-gap pitches (all but the wallpapers split, which stays LATER).
- Did: NEXT gains #80 battery health readout, #81 first-boot welcome
card, #82 generation readability, #83 doctor pre-activate fail flag,
#84 dock life polish
[big], #85 hardware hall of fame. PROPOSED placeholder left. No implementation started (explicit instruction). - Verified: V0 (backlog only).
- Pending: —
- Next suggestion: #80 (smallest) or #81 (highest product ROI); #84 must be split first.
2026-07-11 — Quick wins: exit-node locations + geo tooltip
- Task: BACKLOG LATER "VPN exit-node richer display" + a geo-mode tooltip nit from the previous iteration (human asked for quick wins).
- Did: Tailscale Exit node picker rows now "hostname — Country City", sliced by the header's fixed-width column offsets (COUNTRY/CITY are multi-word; never field-split), locationless nodes stay bare, pick strips back to hostname at the first space. Nightlight Waybar tooltip says "follows your location" in geo mode. Queue's VPN entry updated.
- Verified: V1 — awk proven against a fabricated 3-case fixture (Mullvad 1-word + multi-word city + bare node); flake check exit 0; downstream-template-home builds (writeShellScriptBin syntax-gates both scripts). Real tailscale output is V3 (existing VPN queue entry).
- Pending: V3 VPN menu live paths (extended, not new).
- Next suggestion: wallpapers artifact split (LATER, decided).
2026-07-11 — Night-light geo mode (lat/long → wlsunset)
- Task: BACKLOG LATER "Night-light geo mode" (human-picked).
- Did:
nomarchy.nightlight.latitude/.longitude(both set = geo mode):services.wlsunset(location-computed sunrise/sunset,.temperature→ night temp) replaces hyprsunset; the toggle script'sunit=and the live-state ExecCondition follow via oneunitlet-binding. Template example lines, README row, ROADMAP ✓. Newchecks.nightlight-geo: pure-eval asserts on the rendered units (coords + temp in ExecStart, ExecCondition present, hyprsunset off). Declarative-only (no menu writer — coords are machine config like keyboard layout). - Verified: V1 —
nix flake check --no-buildexit 0 (evals the new asserts + option-docs); builtdownstream-template-home(default hyprsunset path unregressed) + the check drv. Caught en route: HM rendersExecStartas a list (toStringneeded in eval asserts). - Pending: V3 queued (HARDWARE-QUEUE § Any machine): visible warm shift at location night + toggle/persistence on the swapped unit.
- Next suggestion: wallpapers artifact split (LATER, decided).
2026-07-11 — Sync-sweep rule + grooming + zram user docs (human-requested)
- Task: Bernardo: groom stale items and codify the check so they don't recur; close the zram user-doc gap.
- Did: LOOP.md §5 gains step 4 Sync sweep (grep item/feature across
agent/+docs/ on ship; prune recorded
[x]queue entries) + an AGENTS.md rule line. Applied it: BACKLOG PROPOSED pruned (auto-theme pitch was stale — shipped as #79; shipped/promoted placeholders removed; v1.0 pointer rewritten; FUTURE promoted-stub dropped). HARDWARE-QUEUE pruned 29 checked[x]entries (363→~250 lines), dangling refs reworded, prune rule in header. README §3 now documents the zram default + hibernation out-of-the-box + MIGRATION pointer. - Verified: V0 (docs/meta only) — grep sweep for dangling refs clean.
- Pending: night-light geo mode next (same session).
- Next suggestion: wallpapers artifact split (LATER, decided).
2026-07-11 — Vendor-neutral agent docs restructure (human-requested)
- Task: Bernardo: de-vendor the agent instructions (multi-model repo), clean stale files, better docs/agent/.claude structure.
- Did: New root
AGENTS.mdentry (CLAUDE.md → symlink). Skill bodies moved toagent/: VERIFICATION.md (enforcement, ex-nomarchy skill), DELEGATION.md (tiers light/standard/frontier + scout/runner contracts + fan-out; consolidates CLAUDE.md table + LOOP §economy + skill §6.5), THEME-DESIGN.md (ex-theme skill, now with frontmatter’d shim)..claude/is a thin adapter (shims route intoagent/). Maps updated (agent/, docs/, README tree). Stale:.gitignoreold_distro entry dropped; local result*/pycache removed. JOURNAL rotated (29 kept, 120 → JOURNAL-ARCHIVE.md). - Verified: V0 —
nix flake check --no-buildexit 0 with the symlink tracked; vendor-name grep clean outside DELEGATION's mapping table. - Pending: nothing; other harnesses add their own adapter row when used.
- Next suggestion: #76/#79 remain [blocked:hw]; otherwise groom PROPOSED.
2026-07-11 — #76 checks.hibernate-swapfile (VM-verify the swapfile+offset)
- Task: Bernardo — push #76's swapfile-resume residual into a VM (like the auto-theme sunset trick).
- Did: Tried a full runtime-swapfile hibernate→resume test; it hit a
bounded, definitive
CanHibernate=no— systemd won't hibernate to a swap that isn't declared in the boot config, and a runtime-computedresume_offsetcan't reach the boot cmdline (the genuine chicken-and-egg). First cut also had an unboundedwait_for_shutdownthat hung → killed it, bounded the wait in a thread (180s) + aCanHibernatepre-check, which is what surfaced the clean verdict. Pivotedchecks.hibernate-swapfileto what a VM can prove deterministically and the partition test can't: the installer swapfile build + offset — NOCOWmkswapfile, file-type swapon, validmap-swapfile -roffset accepted by/sys/power/resume_offset, zram above it. (Device fix:/dev/vdbonceuseNixStoreImagewas dropped.) - Verified: V2 PASS (fresh build, exit 0). BACKLOG/ROADMAP updated; #76 residual narrowed to the literal encrypted power-cycle (dev box runs it).
- Lesson: the sunset-trick spirit applies but not always the full cycle —
when systemd/kernel gates the behaviour (CanHibernate), verify the
construction deterministically and leave only the physical cycle to HW.
Always bound
wait_for_shutdown(no timeout param → thread + join). - Next suggestion: #76/#79 both
[blocked:hw]; QA / PROPOSED otherwise.
2026-07-11 — Code-review fixes (parallel review of the session batch)
- Task: Bernardo asked for parallel work; spawned a fresh-eyes opus
review of
2055842..HEAD(static). It found the batch sound — 2 real LOW edge bugs, 1 false positive, 1 cosmetic. - Did: (1)
cmd_auto— inverted sunrise/sunset (sunrise > sunset) went perpetually day; replaced thenot betweenshortcut with a real wrap-aroundmins >= sunrise or mins < sunset, so a cross-midnight day window switches both ways. (2)rofi.nixautotheme HH:MM guard tightened[0-2][0-9]→[01][0-9]|2[0-3]so 24–29 are rejected. Dismissed thebreezefinding (papirus DOES ship breeze/breeze-dark — verified) and the cosmetic doctor-RAM one. - Verified: py_compile; boundary truth-table (normal + wrap-around);
HH:MM case table (23:00/19:59/20:00 accept, 24/25/30:00 reject);
auto --whichnormal-case unchanged; menu bash -n; flake check green. Normal case unchanged sochecks.auto-themestill holds. - Pending: hibernate-swapfile VM test still running (uncommitted flake.nix).
- Next suggestion: land hibernate-swapfile once its VM test returns.
2026-07-10 — #79 V2: checks.auto-theme (simulated sunset) — was mis-framed V3
- Task: Bernardo challenged the "V3 real-session" framing — a simulated sunset IS VM-testable. He's right; I'd conflated "needs a real desktop" with "needs the generic home-manager switch."
- Did: Added
checks.auto-themerunNixOSTest: installs nomarchy-state-sync, pointsNOMARCHY_DEFAULT_THEMESat presets, stubs the switch viaNOMARCHY_REBUILD(a marker), configures the pair+schedule, then walks the VM clock 19:55→20:05→20:06→next-day 07:30 asserting slug goes summer-day → night (1 rebuild) → night (idempotent, still 1) → day (2). The self-gating I relied on: presets via env, wallpaper/notify no-op headless, run_switch honors NOMARCHY_REBUILD + waybar nudge is check=False. - Verified: V2 PASS —
nix build .#checks…auto-themefresh, exit 0. Dropped #79's[blocked:hw]; it's done (V2). Updated ROADMAP. - Lesson: don't default "timer/session feature" to V3 — stub only the generic step (the real HM switch, covered elsewhere) and simulate the rest (clock) headlessly. Only the literal timer-fires-on-OnCalendar is on-HW, and its schedule is systemd-analyze-validated.
- Next suggestion: NEXT head #76
[blocked:hw]; else QA / PROPOSED.
2026-07-10 — #79 slice 3: Look & Feel › Auto theme menu (#79 complete)
- Task: BACKLOG #79 slice 3 — the menu; completes the feature.
- Did:
rofi.nix— "Auto theme (on/off)" row in Look & Feel + anautotheme)submenu: toggle, pick day/night (fromnomarchy-state-sync list), set sunrise/sunset (HH:MM input, validated). Enable writes the flag + defaults the summer pair--no-switch, thenexec auto --force— one rebuild installs the timer AND applies the right theme. Disable is instant--no-switch(autoself-gates; the lingering timer no-ops). Day/night/times are live--no-switch. - Verified: V1 — HM generation builds (
writeShellScriptBinbash -n on nomarchy-menu passes) + bash -n on the built menu. Logic test (stubbed rofi/theme-sync/notify): selecting "Auto theme (off)" runs exactlyset day summer-day,set night summer-night,set enable true(all--no-switch), thenauto --force— the intended one-rebuild path. Disable path is static-clear (set false--no-switch, noauto); a stateful-stub dynamic test would loop (stub doesn't reflect the flip). V0 flake check green. #79 collapsed to[blocked:hw](all 3 slices done; only live-session switch remains, needs a Nomarchy machine). - Pending: V3 real-session (timer switches day↔night across sunset).
- Next suggestion: NEXT head #76/#79 both
[blocked:hw]; QA/PROPOSED.
2026-07-10 — #79 slice 2: auto-theme systemd timer
- Task: BACKLOG #79 slice 2 — the timer/hook.
- Did:
modules/home/autotheme.nix(imported in home default.nix):systemd.user.{service,timer}.nomarchy-auto-theme, install gated onconfig.nomarchy.settings.autoTheme.enable or false(state-driven, like updates.nix gates on its enable). Service runsnomarchy-state-sync autowith a PATH forhome-manager; timerOnStartupSec=1min+OnCalendar=*:0/15+Persistent. Chose periodic over exact sunrise/sunset timers — robust to suspend/DST, andautois idempotent so ticks are cheap (rebuild only at the transition). - Verified: V1 — real-config eval (state temp-enabled, restored):
settings.autoTheme.enable→true, timerOnCalendar=*:0/15, service ExecStart=… nomarchy-state-sync auto; disabled→no units (isolation eval condition=false).systemd-analyze calendar '*:0/15'valid. V0 flake check green. (Gotcha: a new .nix file is invisible to the flake untilgit add— flake eval only sees tracked files.) - Pending: live timer→
home-manager switchon a real Nomarchy session (needs a Nomarchy machine, like #76). Slice 3 (menu) next. - Next suggestion: #79 slice 3 — Look & Feel › Auto theme menu.
2026-07-10 — #79 slice 1: auto time-of-day theme CLI primitive
- Task: Split BACKLOG #79 (
VISION § D,[big]) into 3 slices (CLI / timer / menu); took slice 1. - Did:
nomarchy-state-sync auto— readssettings.autoTheme.{enable,day,night,sunrise,sunset}, computes day/night by the local clock, and applies the matching preset only if different (idempotent → the slice-2 timer won't rebuild needlessly).--whichprints the decision without switching;--force/--no-switchtoo. Factoredcmd_apply's core intoapply_namedsoautoreuses the exact same one engine (GOALS: no second pipeline). - Verified: V1 package builds; functional tests on the built bin
against scratch state: wide-day→day slug, 00:00–00:01 window→night,
disabled→no-op, missing day/night→die,
auto --no-switchwrites state, re-run→"already on" no-op, plainapplystill writes (refactor intact). V0 py_compile + flake check +checks.state-sync-validategreen. - Pending: slices 2 (systemd sunrise/sunset timers + login apply, V2) and 3 (Look & Feel menu) remain under #79.
- Next suggestion: #79 slice 2 — the timer/hook (V2 runNixOSTest).