Follow-on to the swaync fix (a643391): the generated Waybar CSS colored
the module row and #window @subtext and dim states @muted, and the
generated rofi theme put @fg text on @surface chips — invisible where
palettes use those roles as "on-surface" (flexoki-light: subtext==base,
surface==text; gruvbox: muted/base = 1.27). flexoki-light has no
whole-swap, so it ran this CSS. Generated surfaces only — the summer
whole-swaps are hand-authored and untouched.
- waybar: secondary text → alpha(@text, 0.85); dim states (inactive
workspaces, DND bell, muted volume) → alpha(@text, 0.5).
- rofi: @dim → text+"80", @surface → text+"1a" (#RRGGBBAA fg tints).
- check-theme-contrast.py pairings/docs now cover all three generated
surfaces; status glyphs (good/warn/bad on base, worst 2.05) are
deliberately not held to a text ratio — raising them is palette
design, a human decision.
Verified: V0; V1 (checks.theme-contrast green over 21 themes;
downstream-template-home builds; rendered waybar style has zero
@subtext/@muted/@surface; rendered custom.rasi shows fg-derived
tints). Honesty: NOT visually verified — V3 queued (flexoki-light
eyeball + dark-theme regression spot-check).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Palette roles aren't uniform: summer-day and flexoki-light use subtext
as text-ON-surface (== base) and surface as a dark chip (== text), so
swaync's @subtext-on-@base body text and @surface/@text buttons were
self-colored (caught on the Latitude).
- body/summary: @text on @base — the one text pairing that passes in
every palette (survey: worst WCAG ratio 5.18 across all 21 themes;
subtext/base bottomed at 1.00 twice, muted/base at 1.27).
- hover rows + widget-title buttons: alpha(@text, 0.1) tints —
contrast by construction; subtext/surface defines dropped.
- NEW checks.theme-contrast (tools/check-theme-contrast.py): asserts
the hex-on-hex text pairings across themes/*.json, cheap (no VM).
The audit also found the generated waybar/rofi CSS shares the bug
class, live on flexoki-light (no whole-swap) → BACKLOG item 27.
Verified: V0; V1 (checks.theme-contrast builds green, 21 themes;
rendered services.swaync.style has zero @subtext/@surface). Honesty:
NOT visually verified — V3 queued (notify-send on summer-day).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Pre-activation failure ("desktop pre-activation failed"): the in-chroot
HM build hard-coded `--option substituters ""`, which only works on
OFFLINE installs (where the ISO store is copied in). Online installs
(now common — wifi works) had no pins and built from source. Fix: build
the generation in the live env (its store always has the pins), nix copy
the closure to the target, chroot only activates. In-chroot build kept
as fallback. Uses path: (not git+file:) to sidestep libgit2 ownership.
- Read-only home.nix: templates come out of the store mode 0444 and cp
preserves it — chmod -R u+w after staging so the user can edit it.
- Keyboard + locale selection: gum prompts (localectl layouts/variants +
curated UTF-8 locale list) and NOMARCHY_LOCALE/KB_LAYOUT/KB_VARIANT for
unattended. One choice flows everywhere — services.xserver.xkb (source
of truth) + console.useXkbConfig (tty/greeter) + boot.initrd.systemd
(so the LUKS passphrase prompt uses the layout; script initrd can't) +
the generated home.nix's nomarchy.keyboard.* for the Hyprland session.
- test-install.sh: NOMARCHY_OVMF env override for sandboxed OVMF paths.
Verified end-to-end in QEMU: offline LUKS install completes, boots to a
themed desktop (no autogenerated-config banner), Plymouth renders the LUKS
prompt on the theme-tinted background.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Promotes the throwaway harness that verified the installer into tools/:
- tools/vm/qmp.py QMP keystroke injection / typing / quit
- tools/vm/vncshot.py GL-safe screenshots via VNC readback (QMP
screendump shows "no surface" with virtio-vga-gl)
- tools/vm/gap-analysis.py drv-graph diff that converged the offline
pin set; run it when offline installs build
from source
- tools/test-install.sh the full offline regression: build ISO, boot
offline, unattended LUKS+swap install via a
config disk (typed long commands drop keys),
wait for poweroff, boot the installed disk,
screenshot the first boot for visual verdict
docs/TESTING.md §4 now points at the script.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full replacement of the previous iteration, rebuilt around three ideas:
- Pure evaluation: theme-state.json lives inside the flake and is read
via the nomarchy.stateFile option — no --impure, ever.
- All-Home-Manager theming: `nomarchy-theme-sync apply` writes the JSON
and runs `home-manager switch`; every theme change is one atomic,
rollbackable generation. Wallpaper (swww) is the sole runtime piece.
- Flat, downstream-first layout: modules/{nixos,home} with one
options.nix each, exported as nixosModules/homeModules + overlay +
flake template; system (nixos-rebuild) and desktop (home-manager
switch) rebuild paths are fully split.
Ships 21 themes imported from the previous iteration (palettes,
wallpapers, btop themes, six whole-swap Waybar identities), Stylix for
the GTK/Qt/cursor long tail, a live ISO target with offline theme
switching, and docs/TESTING.md with the QEMU verification workflow.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>