# Nomarchy Roadmap

This is the mid-term plan for Nomarchy. It exists so future sessions — human or agent — can pick up work without re-deriving context. Items move from **Now** → **Next** → **Later** as priorities shift, and from any column into **Shipped** at the bottom when done. There are no dates: ship-when-ready.

If you're new here, also read [`docs/STRUCTURE.md`](STRUCTURE.md) and [`docs/OPTIONS.md`](OPTIONS.md). Existing-NixOS users should also read [`docs/MIGRATION.md`](MIGRATION.md).

## 1. Vision & guardrails

Nomarchy is a NixOS-based distribution that gives you a polished Hyprland desktop (Hyprland + waybar + walker + a curated theming engine) on a strictly declarative, flake-based foundation. Goal: power-user polish without giving up reproducibility.

Guardrails (apply when adding anything):

- **Declarative-first.** No imperative state in `core/`. Anything mutable lives in `~/.config/nomarchy/state.json` or in NixOS options.
- **Downstream-flake friendly.** Every behavior toggle is a `nomarchy.*` option documented in `docs/OPTIONS.md`. Adding a feature without a corresponding option is a bug.
- **Opt-in by default.** New features default off (or default to the existing behavior). The installer can flip defaults for the user, but the option must read sensibly when set by hand.
- **Reuse before invent.** Before adding a script, grep `core/system/scripts/`, `features/scripts/utils/`, and `themes/engine/scripts/` — there are ~155 of them, and many of the things you want already exist.

## 2. Now / Next / Later board

### Now (ready to pick up)

- **Pillar 8 runtime verification pass.** Every Component 1–10 code sweep has shipped, but each closeout entry flagged behaviour that can only be confirmed on a real install: boot the live ISO and eyeball waybar across panel positions × form factors × all 22 palettes; run every `nomarchy-menu` entry and confirm it does the thing; walk every `nomarchy.*` option's enable→rebuild→observe loop. Run the punch-list, fix any new bugs inline, log structural ones as new roadmap rows.

### Next (bigger lifts that build on Now)

_(empty — all entries shipped or moved to Later)_

### Later (speculative or research-shaped)

- **Declarative-state migration.** Move the bits of `state.json` that don't actually need runtime mutability (theme, font, isLightMode) into NixOS / home-manager options, leaving only genuinely runtime-only state behind. Reduces the "two sources of truth" surface.
- **Rolling vs pinned channel choice in the installer.** Today the generated flake pins `nomarchy` to a rev. Offer a "rolling" option that follows `main` and a `nomarchy-rollback` helper for stuck rebuilds.
- **Theme creation wizard.** A `nomarchy-theme-new` script that scaffolds a new palette from a base16 hex set (or by sampling a wallpaper), runs `nomarchy-themes-prebuild`, and opens a PR template.
- **CI matrix on Forgejo Actions.** On every push: `nix flake check`, build `nomarchy-installer`, `nomarchy-live`, `default`. On tag: publish ISOs as release artefacts.
- **Golden-image VM tests per palette.** A `nixosTest` per palette that boots the `default` config, takes a screenshot, and diffs against a golden image. Catches Stylix regressions before they hit users.
- **Forgejo release pipeline.** `vYY.MM.x` tags matching the upstream NixOS channel; the pipeline pushes the three ISOs and an updated `flake.lock` snapshot.
- **Optional `nomarchy-installer-vm`** rebuilt as a real flake app (not a one-off shell script) so users can install Nomarchy into a libvirt VM declaratively.
- **Surface support module** via the relevant `nixos-hardware` profile + Surface kernel patches behind a `nomarchy.hardware.isSurface` toggle.
- **High-contrast accessibility palette.** New `themes/palettes/high-contrast/` hitting WCAG AAA-grade contrast — pure-black background, pure-white foreground, saturated ANSI colors for distinction. Ships its own `colors.toml`, `icons.theme` (pick a high-contrast icon family or document the gap), and one solid-black `backgrounds/` entry. Pairs with `nomarchy.accessibility.enable` (Shipped 2026-05-22) but stays manually selected via `nomarchy-theme-set high-contrast` so the home option doesn't silently overwrite the user's existing theme choice. Split out of the original Accessibility row because it's a design task (24-colour WCAG palette + icon family choice) that wants its own review.
- **Publish or replace `Bjarne.{ethereal,hackerman,vantablack}-nomarchy` VSCode theme extensions.** The `ethereal`, `hackerman`, and `vantablack` palettes' `apps/vscode.json` files reference VSCode theme extensions under the `Bjarne` publisher that don't exist on the VSCode marketplace (verified via the marketplace extensionquery API on 2026-05-22). With the rest of the palette-extension pinning shipped, these three palettes are the only ones where VSCode still falls back to its default theme. Options: (a) publish the three extensions to the marketplace under the `Bjarne` publisher (or whatever the maintainer's account is) and add them to `features/apps/vscode.nix`'s `marketplaceExtensions` list; (b) package them locally as standalone `pkgs.vscode-utils.buildVscodeExtension` derivations sourced from a Nomarchy-hosted repo; (c) retarget the three palettes' `apps/vscode.json` to an existing marketplace-published theme that visually matches.

## 3. Pillar: Script & menu audit

Nomarchy ships **~155** `nomarchy-*` scripts across three directories, plus a 379-line `nomarchy-menu` with 23 submenu functions. Some are first-class Nomarchy work; some are direct Omarchy ports that haven't been adapted; some are dangling references the menu calls but no script implements (e.g. `nomarchy-backup`, `nomarchy-debug`, `nomarchy-pkg`, `nomarchy-pkg-aur-add`, `nomarchy-plymouth`, `nomarchy-refresh-hyprland`, `nomarchy-reinstall`, `nomarchy-rollback`, `nomarchy-screenrecord-filename`, `nomarchy-theme`, `nomarchy-update-firmware`, `nomarchy-upload-log`, `nomarchy-version`, `nomarchy-wallpaper`, `nomarchy-skill`, `nomarchy-luks`).

This pillar fixes that. It runs as two phases.

### Phase A — Inventory & triage

Lands as a single PR. Output is `docs/SCRIPTS.md` populated with rows for every script and every menu item.

1. Run a generator (one-shot helper, doesn't have to be checked in) that produces three lists:
   - All `nomarchy-*` scripts under `core/system/scripts/`, `features/scripts/utils/`, `themes/engine/scripts/`.
   - All `nomarchy-*` *callers* (grep `core/`, `features/`, `themes/`, `installer/`, `bin/`).
   - The set difference (orphaned callers ↔ unreferenced scripts).
2. Walk `features/scripts/utils/nomarchy-menu` and list every menu entry with its target script.
3. Tag each row with a status:
   - `kept` — works on Nomarchy, no change needed.
   - `port-from-omarchy` — exists upstream, needs adapting (drop pacman/yay/AUR, repath to NixOS, talk to `nomarchy.system.*` options).
   - `delete-dead` — neither used nor needed; remove and update callers.
   - `stub-with-notify` — temporarily replace with a `notify-send "Not yet implemented in Nomarchy"` so the menu stops looking broken until the work is scheduled.
   - `unknown` — needs a deeper look before tagging.
4. The completed table lives at [`docs/SCRIPTS.md`](SCRIPTS.md). The roadmap links to it; this section just sets the methodology.

### Phase B — Adapt or remove

Lands as PR batches of ~10 scripts each, branch named `wave/audit-<batch>`. Per script:

- For `port-from-omarchy`: rewrite the script for Nomarchy paths (`/etc/nixos`, `nixos-rebuild`, `home-manager`, no Arch idioms), wire it into `nomarchy.system.*` where applicable, and update every caller (menu, waybar, keybindings).
- For `delete-dead`: `git rm` the script *and* fix every caller — a `find` + `sed` pass against `nomarchy-menu`, every `*.conf`, and every nix file.
- For `stub-with-notify`: write the one-liner stub in place. The roadmap row stays open until the real implementation lands.

Each PR description should reference the row(s) in `docs/SCRIPTS.md` it closes, and reviewers spot-check that no caller still points at a stale name.

## 4. Pillar: Installer

- "What's installed?" summary screen on boot of a freshly-installed system, sourced from `state.json` + `nomarchy-system-scripts` introspection (Shipped).
- Richer disk metadata (Shipped).
- `disko-golden.nix` variants for software-RAID and BTRFS-pool-as-root (Shipped).
- Pre-flight resume polish (Shipped).
- Software-profile multi-select (Shipped).
- Form-factor → laptop preset (Shipped).

## 5. Pillar: Power, hardware, presets

- Auto-detect dGPU presence in `installer/hardware-db.sh` and pre-fill `hardware.nvidia.prime.{intel,nvidia}BusId` in the generated `system.nix` (driver stack itself is Shipped — see entry below).
- Surface support behind `nomarchy.hardware.isSurface` (Later).
- Laptop preset: TLP, upower, brightness, lid, hypridle tuning (Shipped).
- Desktop preset: performance governor, no laptop UI (already filtered), ZFS hooks (Shipped).
- Accessibility preset (Shipped).
- Gaming preset (Shipped).
- Vendor matchers in `installer/hardware-db.sh` (Shipped — ROG Ally added; Surface/Framework/Lenovo entries corrected; Steam Deck + Snapdragon X documented as nixos-hardware-unsupported. CI now lints DB references).

## 6. Pillar: Onboarding & docs

- `nomarchy-welcome` first-run wizard (Shipped).
- `docs/KEYBINDINGS.md` auto-generator (Shipped).
- `docs/TROUBLESHOOTING.md` (Shipped).
- `docs/index.md` / README docs index (Shipped — `README.md` links every doc in `docs/`).
- `nomarchy-manual` — opens the local `~/.local/share/nomarchy/README.md` via `xdg-open` (Shipped).

## 7. Pillar: Test, CI, release

- Forgejo Actions workflow:
  - on every push to `main`: `nix flake check` (≈ what we run by hand today).
  - on every PR: also build all three ISOs (cache hit on most of them).
  - on tag `vYY.MM.x`: publish ISOs as release artefacts.
- Versioning scheme: `vYY.MM.x` matching the upstream NixOS channel (e.g. `v25.11.3`).
- `nixosTest` per palette: boots `default` in a VM, screenshots the SDDM splash and the Hyprland desktop, diffs vs golden. Failure surfaces as CI red.
- A small `bin/utils/nomarchy-bench-iso-build` that records ISO build time + size into a per-commit JSON so we notice regressions.

## 8. Pillar: QA audit — features & components

Nomarchy now spans an installer, ~159 `nomarchy-*` scripts, a Hyprland desktop stack (Hyprland + waybar + walker + nightlight + idle), curated apps, a 22-palette theme engine, and two ISO hosts. Pillar 3 audited script *existence*; this pillar audits feature *behavior*. The goal: walk every shipped feature end-to-end on a real install, fix every bug or surprise inline when small, and capture the rest as new roadmap rows.

Runs as **per-component sweeps**. One PR per component, branch `wave/qa-<component>`. Don't grow scope mid-PR — bugs that need a new option, refactor, or missing module become a new **Now**/**Next** row.

Components (each is one sweep):

1. **Installer** — `installer/install.sh`, `installer/hardware-db.sh`, disko configs. Fresh install + `--resume` + `--dry-run`, on laptop and desktop, with FDE (non-LUKS branch is Later). Verify every generated file (`flake.nix`, `system.nix`, `home.nix`, `hardware-selection.nix`, `state.json`) is correct and idempotent.
2. **First-boot UX** — `nomarchy-welcome`, generated `home.nix`, SDDM and Plymouth metadata, default theme/font/panel position. Re-run on a clean VM; note every prompt that confuses and every default that's wrong.
3. **Core system modules** — `core/system/*` (laptop, desktop, accessibility, gaming, hybridGPU, impermanence, network, hardware, branding). For each: enable → rebuild → observe the claimed effect → disable → rebuild → observe it's gone. Cross-check against `docs/OPTIONS.md`.
4. **Core home modules** — `core/home/*` (options, state, behavior, overrides, deployed config). Verify every home-side `nomarchy.*` option does what its description claims; confirm `~/.config/nomarchy/overrides/` actually overrides.
5. **Desktop stack** — Hyprland (keybindings, window rules, monitors, input), waybar (every module × both panel positions × both form factors), walker (every launcher mode), idle, nightlight, notifications (mako). Reconcile `docs/KEYBINDINGS.md` against runtime.
6. **Apps** — `features/apps/*`. Each app: launches, themed via Stylix, configured as expected. Catches the "we package it but nobody configured it" class.
7. **Theme engine + palettes** — `nomarchy-theme-set` across all 22 palettes, font and wallpaper switchers, light-mode toggle. Verify per-palette Stylix targets render correctly across SDDM, Plymouth, GTK, Qt, terminals, browsers, waybar, walker.
8. **Scripts (runtime behavior)** — Pillar 3 confirmed existence; this sweep runs every user-visible script (especially every `nomarchy-menu` entry) on current NixOS and confirms it actually does the thing.
9. **ISOs** — boot `nomarchy-installer` and `nomarchy-live`; verify the `nomarchy-test-live-iso` flow; check the installer ISO ships every tool `install.sh` calls (regression class: `hardware-db.sh` missing, already shipped).
10. **Lib + state schema** — `lib/state-schema.nix`, color resolution, path helpers. Cross every codepath that produces `state.json` (installer, welcome wizard, hand-edit) against the schema; confirm bad inputs are rejected with a useful message.

Per-PR deliverable:

- PR body lists what was tested, what was broken, what was fixed inline, what was deferred (with the new roadmap row linked).
- Doc updates ride with the change per `docs/AGENT.md` §5.4.
- Don't bundle fixes across components — keep one component per branch so reviewers can spot-check end-to-end without context-switching.

Pillar is **done** when every component has a closed `wave/qa-<component>` PR and the roadmap captures every deferred finding.

## 9. Process notes

- **Branch naming:** `wave/<pillar>-<short-slug>`. Examples: `wave/audit-pkg-scripts`, `wave/installer-disk-metadata`, `wave/laptop-preset`.
- **One PR per audit batch.** Reference rows in `docs/SCRIPTS.md`. Smaller PRs review faster.
- **Living roadmap.** When an item ships, move it to the **Shipped** section at the bottom of this file rather than deleting it. Future-us gets a free changelog.
- **Plan files live separately.** Detailed implementation plans (the per-feature design docs Claude writes in plan mode) belong under `~/.claude/plans/` per session, not in the repo. The roadmap is the durable reference; plan files are working notes.
- **Don't widen scope mid-PR.** If the audit reveals a missing feature, file a new roadmap row, don't graft it onto the current PR.

## Shipped

(Move items here when they land — keep them brief, link the commit/PR.)

- _2026-05-29_ — **Pillar 7: opt-in toggle eval matrix in CI.** `nix flake check --no-build` only evaluates the four default `nixosConfigurations`/`homeConfigurations`, so any eval-time bug that *only* fires when a `nomarchy.*` toggle is flipped sailed straight through — exactly how the vscode option rename and the impermanence systemd-stage-1 assertion both reached `main` undetected. New `bin/utils/nomarchy-eval-matrix` layers each opt-in scenario (16 toggles: impermanence single/multi, laptop/desktop presets, accessibility, gaming, hybridGPU, hibernation, docker, fwupd, overrides, panel position, keymap variant, toggles-off — plus home + system halves) onto `nixosConfigurations.default` via `extendModules` and forces `system.build.toplevel.drvPath` (which forces the assertion checks); it also forces all 21 palettes through the system-side Plymouth `base00`→RGB-float math that the home-only `allThemeVariants` never reaches, and both standalone `homeConfigurations`. Per-scenario results come from `builtins.tryEval` so one failure doesn't mask the rest — verified the harness goes red on both a failed assertion (re-injected `boot.initrd.postDeviceCommands`) and a nonexistent-option ref, and green on the current tree (all 39 scenarios pass). Wired into `.gitea/workflows/check.yml` as a step after `flake check`, with `jq` supplied via `nix shell` so it doesn't depend on the runner image. `docs/AGENT.md` §5.5 now instructs: when you add or rename an opt-in `nomarchy.*` option, add a matching scenario to the script's `toggleScenarios` attrset.

- _2026-05-29_ — **Impermanence rollback no longer fails to build.** `core/system/impermanence.nix` implemented the Erase-Your-Darlings root wipe via `boot.initrd.postDeviceCommands`, but `themes/engine/plymouth.nix:63` sets `boot.initrd.systemd.enable = true` distro-wide (Plymouth is imported unconditionally from `core/system/default.nix`), and systemd stage-1 initrd hard-rejects `postDeviceCommands` with a failed assertion. Net effect: **every** install that flipped `nomarchy.system.impermanence.enable = true` — including any user who picked impermanence at the installer prompt — produced a config that wouldn't evaluate, let alone boot. Converted the rollback into a `boot.initrd.systemd.services.nomarchy-rollback` oneshot unit ordered `after = systemd-cryptsetup@${mainLuksName}.service` and `before = sysroot.mount`, with `boot.initrd.systemd.initrdBin` pulling in `btrfs-progs` / `coreutils` / `util-linux` / `findutils` (the systemd initrd doesn't ship them by default, unlike the old scripted initrd). Script body (timestamped `@` → `old_roots` move, 30-day recursive subvolume GC, `root-blank` → `@` snapshot) is unchanged. Verified the assertion is gone and `nixosConfigurations.default` + `impermanence.enable` evaluates fully via `extendModules`. **Runtime-verification caveat:** the boot-time wipe semantics (the `[[ ]]`/function/IFS shell idioms and the cleanup loop under the systemd initrd shell, plus correct ordering vs the LUKS mapping) can only be confirmed by a real wipe-boot cycle on an impermanence install — fold into the Pillar 8 punch-list. `docs/TROUBLESHOOTING.md` persistence-block line reference updated (46-72 → 91-120).

- _2026-05-22_ — **VSCode theme extensions pinned for 10 marketplace palettes.** Before this fix, only the 6 palettes whose theme extensions ship in `pkgs.vscode-extensions` (catppuccin, catppuccin-latte, nord, tokyo-night, rose-pine, gruvbox) had working VSCode theming — every other palette had `workbench.colorTheme` set to a theme VSCode couldn't find, so it silently fell back to the built-in default. Including the default `summer-night` palette (sainnhe.everforest), which meant the default install had broken VSCode theming. Probed all 13 unique extensions against the VSCode marketplace extensionquery API; 10 exist (`sainnhe.everforest`, `shadesOfBuntu.flexoki-light`, `qufiwefefwoyn.kanagawa`, `oldjobobo.{lumon,miasma,retro-82}-theme`, `TahaYVR.matteblack`, `jovejonovski.ocean-green`, `monokai.theme-monokai-pro-vscode`, `Bjarne.white-theme`) and 3 don't (`Bjarne.{ethereal,hackerman,vantablack}-nomarchy` — unpublished custom Nomarchy themes; logged as a new Later row). Fetched the latest version + sha256 for each of the 10 via `nix store prefetch-file` against `https://${publisher}.gallery.vsassets.io/_apis/public/gallery/publisher/${publisher}/extension/${name}/${version}/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage`. Added a `marketplaceExtensions` list to `features/apps/vscode.nix` that wraps each entry in `pkgs.vscode-utils.extensionFromVscodeMarketplace { publisher; name; version; sha256; }` and concatenates with the existing nixpkgs-packaged list. Smoke-built `sainnhe.everforest` end-to-end to confirm the URL pattern + sha256 resolve. Documented the version-bump procedure in the module comment. `docs/OPTIONS.md` updated to drop the "still break" caveat for everything except the three Bjarne palettes.
- _2026-05-22_ — **Chromium static `Default/Preferences` deleted.** `features/apps/chromium/default.nix` was deploying a 204-byte static `Default/Preferences` via Home Manager symlink into Chromium's mutable profile directory. Chromium expects to write that file at runtime, so the symlink-into-store deployment was structurally broken (Chromium either fails to save, or replaces the symlink on first write — losing whatever the static file claimed to set). The contents (`extensions.theme.{use_system,use_custom} = false`, `browser.theme.{color_scheme,user_color} = 2`) are duplicates of the managed-policy intent in `core/system/browser.nix` (`BrowserThemeColor` from palette `base00`, `BrowserColorScheme` from `isLightTheme`) — and worse, the static `color_scheme = 2` hardcoded "dark" while the policy is dynamic, so a light-palette user would have hit a conflict. Removed the whole `features/apps/chromium/` directory (8 lines + the 204-byte file) and dropped the import from `features/default.nix`. Chromium theming continues to flow through the system-level managed policy, which is the canonical chromium-on-NixOS path.
- _2026-05-22_ — **Plymouth boot splash follows the active palette.** `themes/engine/plymouth/nomarchy.script` had `Window.SetBackgroundTopColor(0.101, 0.105, 0.149)` hardcoded — a Tokyo-Night-ish `#1a1b26` — and `nomarchy.plymouth` had a matching `ConsoleLogBackgroundColor=0x1a1b26`. Both were frozen regardless of `nomarchy.system.theme`. Replaced the literals with `@BG_R@`/`@BG_G@`/`@BG_B@`/`@BG_HEX@` placeholders; `themes/engine/plymouth.nix` now reads the active palette via `nomarchyLib.getPalette config.nomarchy.system.theme`, converts `palette.base00` into three 0.0–1.0 floats (Nix has no FP math, so `(byte * 1000) / 255` integer division formatted as `0.XXX`), and `sed`-substitutes during `installPhase`. Smoke-built the derivation against the default `summer-night` palette: emits `0.176, 0.207, 0.231` (matches `0x2d353b`) and `ConsoleLogBackgroundColor=0x2d353b`. Closes the "Plymouth theme variants per palette" Next-column item.
- _2026-05-22_ — **`nomarchy.overrides.*` loader implemented.** The option surface (`enable`, `paths`) had existed in `core/home/overrides.nix` since 2026-05-18 but did nothing — `paths` was a reserved attrset that never reached `xdg.configFile`. Now wired: every entry in `nomarchy.overrides.paths` substitutes the matching `xdg.configFile.<key>.source` at `lib.mkForce` priority, beating Nomarchy's own `lib.mkDefault` writes. Other fields on the original entry (`recursive` etc.) survive via the standard module-system merge. Picked the attrset model from the row's two options rather than runtime `~/.config/nomarchy/overrides/` directory discovery — Nix needs every managed file declared at evaluation time, and the attrset matches the explicit-config shape used everywhere else in the Nomarchy surface. `docs/OPTIONS.md` updated: both `overrides.{enable,paths}` entries gain real content + an example, the `configOverrides` row now contrasts bulk-vs-per-file accurately, and the "Where these are defined" footer drops the (reserved) tag. Closes the Next-column row. Unlocks the future replacement for the removed Setup→Config menu.
- _2026-05-22_ — **Accessibility home-side companion shipped.** New `nomarchy.accessibility.enable` home option (mirror of `nomarchy.system.accessibility.enable`) plus `core/home/accessibility.nix` that, when enabled, contributes a Hyprland `extraConfig` block via `lib.mkAfter`: slows `input.repeat_rate` to 25 (from 40) and `input.repeat_delay` to 1000 ms (from 600) so holding a key isn't a runaway machine-gun for low-mobility users, and binds `SUPER+ALT+S` to launch the Orca screen reader (the system preset already puts `orca` on PATH). The `mkAfter` priority guarantees the input slowdown wins over the templated `input.conf` defaults. Documented in `docs/OPTIONS.md`. The third item from the original Next row — a high-contrast palette — is split into its own Later row because it's a design task (24-colour WCAG AAA palette + icon family choice) that wants its own review.
- _2026-05-22_ — **Gaming preset: flathub remote registered automatically.** `services.flatpak.enable = true` (set inside `core/system/gaming.nix`'s `mkIf cfg.enable` block) shipped flatpak but didn't add any remotes — `flatpak install` and the Discover GUI returned empty results until the user ran the manual `flatpak remote-add` one-liner. nixpkgs has no declarative remote-add API. Added `systemd.services.nomarchy-flathub-init`: a `Type=oneshot`, `RemainAfterExit=true` unit that runs `flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo` after `network-online.target`. The `--if-not-exists` flag keeps it idempotent across reboots and re-runs. Lives under the gaming preset (where flatpak is wired today); lift to a dedicated module when another preset needs flatpak. Closes the "Gaming — declarative flathub remote" Next-column item.
- _2026-05-22_ — **`nomarchy-menu` "Setup → Config" submenu removed.** Of the nine entries, five (`hyprland.conf`, `hypridle.conf`, `hyprsunset.conf`, `walker/config.toml`, `waybar/config.jsonc`) opened Home-Manager-generated files that get clobbered on the next `home-manager switch`; two (`hyprlock.conf`, `swayosd/config.toml`) pointed at paths the modules don't deploy at all; `XCompose` was a HM-managed symlink to the Nix store (read-only). The "edit + restart" pattern was an Omarchy holdover that didn't translate to Nomarchy's declarative-first model. Removed `show_setup_config_menu` entirely and dropped the "  Config" item from `show_setup_menu` (closes the case branch in the parent menu). Persistent settings now go through the matching `nomarchy.*` option in `/etc/nixos/home.nix` (or `system.nix`); when the `nomarchy.overrides.*` loader ships, the menu can come back routed through `~/.config/nomarchy/overrides/`. Side effect: `nomarchy-restart-xcompose` now `unused?` in `docs/SCRIPTS.md` (regenerated) — left as a future Pillar 3 cleanup, not widened into this PR.
- _2026-05-22_ — **`toggles.waybar` is now a Nix-level gate.** `features/desktop/waybar/default.nix` previously set `programs.waybar.{enable,systemd.enable} = lib.mkDefault true` unconditionally, so the bar came back on every rebuild/reboot regardless of `nomarchy.toggles.waybar`. The toggle script consumed `NOMARCHY_TOGGLE_WAYBAR` but only via runtime pkill/exec — purely session-local. Same shape as the just-fixed nightlight: both options now drive their `programs.X.enable` / `services.X.enable` symmetrically with `toggles.idle` → `services.hypridle.enable`. `programs.waybar.{enable,systemd.enable}` now follow `config.nomarchy.toggles.waybar`; the toggle script flips the running unit via `systemctl --user start/stop waybar.service` for instant feedback and writes `.waybar` back to `state.json` so the next rebuild realigns. `nix flake check --no-build` + `bash -n` clean.
- _2026-05-22_ — **Nightlight reconciled: hyprsunset gated on the toggle.** Path (b) from the Later row. `features/desktop/nightlight.nix` previously set `services.hyprsunset.enable = lib.mkDefault true` unconditionally and baked the temperature (4000K or a neutralising 6500K) into `extraArgs` at Nix-eval time, while the toggle script `pkill`'d the daemon on disable and `hyprctl dispatch exec hyprsunset --temperature 4000`'d a new one on enable — racing the systemd unit and hardcoding 4000K regardless of `nomarchy.nightlightTemperature`. Now: `services.hyprsunset.enable = lib.mkDefault config.nomarchy.toggles.nightlight` (symmetric with `services.hypridle.enable` ← `toggles.idle`), `extraArgs` always uses the option value, and the toggle script flips the running unit via `systemctl --user start/stop hyprsunset.service`, reads `nightlightTemperature` from `state.json` for the notification, and writes `.nightlight` back to `state.json` so the next rebuild realigns. Dropped the misleading "Always enabled, we control via IPC and state" comment. `nix flake check --no-build` + `bash -n` clean.
- _2026-05-22_ — **Installer keymap reaches Hyprland's Wayland session.** `core/home/config/nomarchy/default/hypr/input.conf` hardcoded `kb_layout = us`, so the installer's `services.xserver.xkb.layout` / `console.keyMap` writes only reached XWayland and the TTY — native-Wayland apps fell back to US. Option-route fix (path (a) from the Later row): added `nomarchy.keymap.{layout,variant}` to `core/home/options.nix` (defaults `"us"` / `""`); deleted the static `input.conf` from the bulk `nomarchy/` deploy; moved it into `core/home/configs.nix` as an explicit `xdg.configFile."nomarchy/default/hypr/input.conf".text = ''…''` that interpolates the option values. Installer's `home.nix` heredoc now writes `nomarchy.keymap = { layout = "$KEYMAP_LAYOUT"; variant = "$KEYMAP_VARIANT"; };` alongside `nomarchy.formFactor`, so a non-US install propagates the layout consistently to Hyprland, XWayland, and the TTY. Documented in `docs/OPTIONS.md`. `nix flake check --no-build` clean.
- _2026-05-22_ — **`flake.nix` palette imports consolidated through `nomarchyLib`.** `flake.nix` was re-importing `./themes/palettes` and recomputing `themeNames` via `builtins.attrNames` even though `lib/default.nix` already exports both. Two evaluations of the same data set with the same result today — drift risk tomorrow. Added `nomarchyLib = import ./lib { inherit lib; }` once in the outputs `let` and reused it via `inherit (nomarchyLib) themeNames;` for the `allThemeVariants` linkFarm. `lib/default.nix` is now the single source of truth for the theme list — modules that need palette data import `../../lib` the same way and resolve to the same evaluation. `nix flake check --no-build` clean.
- _2026-05-22_ — **`programs.uwsm` moved to `core/system/session.nix`.** The session-manager wiring (uwsm + the Hyprland Wayland-compositor entry that gives Hyprland a proper `graphical-session.target` so user services like `nomarchy-wallpaper`, walker and elephant chain off it) had lived in `core/system/virtualization.nix` by historical accident — loaded unconditionally on every install, nothing to do with libvirt/docker. Lifted into a dedicated `core/system/session.nix` and imported from `core/system/default.nix` between `systemd.nix` and `virtualization.nix`. `virtualization.nix` now contains only the libvirt + docker branches its filename implies. `nix flake check --no-build` clean. No behaviour change.
- _2026-05-22_ — **`themes/templates/*.tpl` pruned.** Deleted 9 of the 11 mustache templates after verifying their output paths are either preempted by Nix-side writes (`hyprland.conf.tpl` shadowed by `themes/engine/files.nix:100`; `kitty.conf.tpl` + `ghostty.conf.tpl` shadowed by the per-palette generators added in commit `8d3ce2d`), unread by anything (`hyprlock.conf.tpl`, `alacritty.toml.tpl`, `btop.theme.tpl`, `chromium.theme.tpl`, `swayosd.css.tpl` — the corresponding apps are themed via Stylix / declarative Home-Manager options / the system policy module, not from the theme symlink), or orphaned (`hyprland-preview-share-picker.css.tpl` lost its consumer when the share-picker dir was deleted in `20de3d4`). Only `obsidian.css.tpl` (consumed by `nomarchy-theme-set-obsidian` to seed every Obsidian vault's theme) and `keyboard.rgb.tpl` (consumed by `nomarchy-theme-set-keyboard-asus-rog` to set the ROG keyboard tint) stay. Rewrote Step 6 of `docs/creating-themes.md` to describe the two remaining templates explicitly and corrected a long-standing path bug ("`~/.config/nomarchy/themed/`" → "`~/.config/nomarchy/themes/templates/`" — the script actually reads the latter). `nix flake check --no-build` clean.
- _2026-05-22_ — **Pillar 4: "What's installed?" first-boot summary.** New `nomarchy-installed-summary` script renders a markdown table (via `gum format`, plain fallback) showing the install shape the user should verify before customising: theme / font / panel position (read from `~/.config/nomarchy/state.json`), timezone / DNS / hybrid-GPU (read from `/etc/nixos/state.json`), form factor (`BAT*` sysfs check — same signal the installer uses), software profiles (heuristic via presence of marker binaries: `docker` → Dev, `steam` → Gaming, `libreoffice` → Office, `obs` → Media, `rg` → CLI Utils), FDE status (any `crypt` entry in `lsblk`), and the drive layout (filtered `lsblk -no NAME,SIZE,TYPE,MOUNTPOINT`). `nomarchy-welcome` now calls it as Step 0 (gated on a `gum input` so the user acknowledges before customisation rewrites anything) and the same command works standalone from any terminal. No installer-side changes — the script is fully self-contained against existing state files and live introspection. Closes the "Installer: What's installed? summary on first boot" Now-column item.
- _2026-05-21_ — **Pillar 8 / Component 9 (ISOs): closeout — Pillar 8 code-audit phase complete.** Code-review-shaped sweep over `hosts/{nomarchy-installer,nomarchy-live}.nix`, the `installation-cd-minimal`/`installation-cd-graphical-base` module chain, and the four ISO build/test scripts. Two minor fixes inline: `nomarchy-build-iso` and `nomarchy-build-live-iso` both ran under `set -e` but then wrapped `nix build` in an `if [ $? -eq 0 ]` block — the `else` branch printing "Error: ISO build failed." was unreachable because `set -e` aborts before the conditional. Removed the dead branches (behaviour identical: the user sees `nix build`'s own error and the script exits). Regression-class check (`hardware-db.sh` precedent): cross-referenced every tool `install.sh` calls against the installer host's `environment.systemPackages` chain — `gptfdisk` (sgdisk) is provided by upstream `profiles/base.nix:21` which `installation-cd-base.nix` chains, `jq` is wrapped in the `nrun` nix-run fallback, and every other direct call (`wipefs`, `dd`, `parted`, `partprobe`, `cryptsetup`, `disko`, `nixos-{install,enter,rebuild}`, `loadkeys`, `timedatectl`, `nmtui`) resolves via either the explicit host packages or the standard base. `nomarchy-live` host shape verified: multi-GPU initrd modules + Xwayland video drivers cover both real hardware and QEMU; auto-login + passwordless sudo + helpful TTY MOTD + Hyprland on-boot exec to a terminal at the install command. `nomarchy-test-live-iso` walks four OVMF candidate paths with KVM detection. With this entry, every code-shaped audit in Pillar 8 has shipped (Components 1–10); the Now-column "Full QA audit" item moves out, replaced by a runtime-verification punch-list entry covering the cross-component "needs runtime verification" notes from each closeout.
- _2026-05-21_ — **Pillar 8 / Component 8 (Scripts runtime behavior): closeout.** Code-review-shaped sweep over `features/scripts/utils/nomarchy-menu` (382 lines, 23 submenu functions), every script referenced from those submenus, the schema↔script field-name cross-check, and cross-cutting typo/stale-reference patterns. Four real fixes inline: **(1)** `nomarchy-menu:70` — "Learn → Nomarchy" still called `nomarchy-launch-webapp https://learn.omacom.io/2/the-nomarchy-manual` (an upstream Omarchy URL — the same one fixed in `nomarchy-manual` back on 2026-05-18). Now calls `nomarchy-manual`, which opens the local docs index. **(2)** `nomarchy-menu:179` — "Style → Hyprland" opened `~/.config/hypr/looknfeel.conf`, a path nothing deploys; the actual file lives at `~/.config/nomarchy/default/hypr/looknfeel.conf` (sourced via the chain from `nomarchy.conf`). Updated the path. **(3)** `nomarchy-menu:258` — `*Overrides*) xdg-open ~/.config/nomarchy/overrides/` case branch with no matching menu option, dead code anticipating the still-unimplemented `nomarchy.overrides.*` loader. Removed (will reappear with the option when the loader ships). **(4)** `nomarchy-theme-bg-next:12` — `jq -r '.theme // "nord"'` defaulted to `"nord"` if `.theme` was missing, while `lib/state-schema.nix:17` defines `"summer-night"` as the schema default. On a fresh-or-empty `state.json` the script looked for backgrounds under `palettes/nord/` while the rest of the system treated `summer-night` as active. Matched to the schema default. Cross-cutting sweeps came back clean: no `$NN[A-Z]+` env var typos elsewhere (the prior pair fixed in `40b6212` was the lot), no references to scripts deleted in earlier Pillar 3 batches (`nomarchy-restart-{hyprctl,mako,tmux}`, `nomarchy-battery-present`, `nomarchy-sudo-keepalive`, `nomarchy-rollback`, `nomarchy-snapshot`, `nomarchy-migrate-state`, `nomarchy-config-direct-boot`, `nomarchy-npx-install`, `nomarchy-webapp-handler-{hey,zoom}`), no stray `omarchy`/`omacom` strings outside historical roadmap entries, and every `state.json` field-write resolves against `lib/state-schema.nix` (or the documented off-schema `welcome_done`). One UX-shaped pattern bug logged separately to Later: `show_setup_config_menu` edits Nix-managed files that get clobbered on the next `home-manager switch`. Runtime verification (run every user-visible menu entry and confirm it does the thing) remains on the user.
- _2026-05-21_ — **Pillar 8 / Component 7 (Theme engine + palettes): closeout.** Code-review-shaped sweep across `themes/engine/{stylix,stylix-compat,loader,files,scripts}.nix`, the 23 theme-engine scripts, and the 21 palettes' file completeness. Three real fixes inline + targeted dead-surface cleanup: **(1)** `nomarchy-theme-set` printed a warning when the named theme directory didn't exist but continued executing — wrote the bad name into `state.json` and ran `nomarchy-env-update` on a broken state. Now `exit 1` after the warning. **(2)** `nomarchy-theme-bg-set` (called by the walker background-selector menu and by the `nomarchy-wallpaper` CLI) updated the live `~/.config/nomarchy/current/background` symlink + restarted swaybg but never wrote `state.json` — so every wallpaper picked via either path silently reverted to the theme default on the next `home-manager switch` (`themes/engine/files.nix` re-resolves `nomarchy.wallpaper` at every rebuild). Now writes the chosen path into `state.json.wallpaper`, mirroring `nomarchy-theme-bg-next`. Added a file-exists check so a bogus path fails loudly instead of leaving a dangling symlink + a crashed swaybg. **(3)** Palette tree dead-surface cleanup: deleted `themes/palettes/{flexoki-light,lumon,retro-82,rose-pine}/apps/chromium.theme` (9-byte RGB strings nothing reads — chromium is themed via managed policies in `core/system/browser.nix`, not per-palette files) and `themes/palettes/summer-day/apps/kitty/{kitty.conf,everforest-light.conf}` (a 76KB stray kitty config at the wrong nested path, superseded by the `kitty.conf` generator added in `8d3ce2d`). Total: 6 files / 2210 lines. Updated the misleading comment in `nomarchy-themes-prebuild` ("the installer wires this up") to reflect reality (the installer only tips the user to run it). Updated the `themes/templates/*.tpl` Later row with a fact-check + concrete categorisation — the templates ARE consumed by `nomarchy-theme-set-templates`, but most write to paths nothing reads or are now superseded by Nix-side generators. Palette completeness matrix: all 21 palettes have `colors.toml`, `backgrounds/`, `icons.theme`, and `apps/`; 5 carry the `light.mode` marker (catppuccin-latte, flexoki-light, rose-pine, summer-day, white); only tokyo-night ships `keyboard.rgb` for the ASUS ROG path, and the keyboard-set chain isn't wired into `nomarchy-theme-set` so it stays manual — niche enough to leave. Runtime verification (switch through all 22 palettes and eyeball SDDM + Plymouth + GTK + Qt + terminals + browsers + waybar + walker rendering) remains on the user.
- _2026-05-21_ — **Pillar 8 / Component 6 (Apps): closeout.** Code-review-shaped sweep over `features/apps/{alacritty,btop,chromium,elephant,ghostty,kitty,lazygit,opencode,swayosd,tmux,vscode,walker}`. Three real theming bugs fixed inline: **(1)** `features/apps/kitty/config/kitty.conf:1` and `features/apps/ghostty/config/config:2` referenced palette-specific include files (`~/.config/nomarchy/current/theme/{kitty,ghostty}.conf`) that didn't exist for any of the 22 palettes — kitty include failed silently, ghostty's was optional (`?`-prefix), and both terminals rendered with their built-in defaults regardless of the active Nomarchy palette. Stylix's `kitty.enable = true` was a no-op because the module uses `xdg.configFile` instead of `programs.kitty`; ghostty has no Stylix target. Added theme-engine generators in `themes/engine/files.nix` mirroring the existing `waybar.css` pattern, mapping `palette.base*` to kitty/ghostty color directives. **(2)** `features/apps/btop/config/btop.conf:5` set `color_theme = "current"` but `themes/engine/loader.nix:72` deploys the active palette's btop theme to `~/.config/btop/themes/nomarchy.theme` — name mismatch, btop fell back to its built-in Default theme on every palette. Renamed to `"nomarchy"`. **(3)** `programs.vscode.profiles.default.userSettings.workbench.colorTheme` was set unconditionally from `themes/palettes/<theme>/apps/vscode.json`, but the matching theme extensions were bundled with `devExtensions` (default `false`) — so VSCode silently fell back to its built-in theme out of the box on every palette. Split `themeExtensions` (always-on, covers the 6 palettes whose theme extension is in nixpkgs) from `devExtensions` (opt-in). The remaining 15 palettes — including the default `summer-night` (`sainnhe.everforest`) — still break because their theme extensions aren't packaged in nixpkgs; logged as a new Later row. Chromium static `Default/Preferences` symlink already had an open Later row; verified the file's contents are duplicate of the managed-policy intent in `core/system/browser.nix`, so the existing entry's hypothesis is correct — left for the user to greenlight deletion. alacritty (Stylix-themed via `programs.alacritty.settings`), elephant (no UI), swayosd (base16 inline), walker (covered in Component 5), lazygit + tmux (terminal ANSI inheritance, transitively fixed by the kitty/ghostty changes), and opencode (minimal opt-in config) are healthy. Runtime verification (launch each app on each palette and eyeball the theming) remains the user's responsibility.
- _2026-05-21_ — **Pillar 8 / Component 5 (Desktop stack): closeout.** Code-review-shaped sweep over Hyprland, waybar, walker, hypridle, hyprsunset, mako, KEYBINDINGS.md (the runtime-rendering subset — waybar across panel positions × form factors × all 22 palettes, walker launcher modes, hypridle timeout feel — stays on the user). Five real bugs fixed inline: **(1)** 9 of 17 `~/.config/nomarchy/default/hypr/apps/*.conf` window-rule files were deployed but never sourced, including `system.conf` (the `tag +floating-window` rules every TUI helper class relies on + `class:org.nomarchy.screensaver` fullscreen rule that hypridle's 150s on-timeout depends on) and `pip.conf` (the PiP pin/size rules). `apps.conf` now sources all 17. **(2)** Two `$NNOMARCHY_TOGGLE_*` typos (double-N) in `nomarchy-menu:330` and `nomarchy-launch-screensaver:16` made `toggles.suspend` and `toggles.screensaver` vacuous — Suspend always showed in the system menu and the screensaver always launched at idle regardless of the documented option. **(3)** 4 broken per-palette waybar `style.css` overrides (`catppuccin`, `lumon`, `nord`, `retro-82`) fully replaced the default style with 2–14 lines of only `@define-color` declarations — picking those palettes produced a waybar with zero structural styling. Default style already imports per-palette colors via `themes/engine/files.nix`-generated `theme/waybar.css`, so deletion restores correct rendering; `summer-day`/`summer-night` kept as legitimate 100+-line redesigns. **(4)** `core/home/config/nomarchy/default/hypr/{bindings,plain-bindings}.conf` were explicitly-labeled deprecated files sourced by nothing (plain-bindings.conf referenced undefined `$terminal`/`$browser`/etc. Hyprland vars) — deleted; `docs/SCRIPTS.md` regenerated to drop stale callers and incidentally corrected 4 Origin columns whose scripts moved from `core/system/scripts/` to `features/scripts/utils/`. **(5)** Mako post-fix (commit `2a301a0`) verified: deployment + the 4 referenced scripts (`nomarchy-notification-dismiss`, `nomarchy-launch-wifi`, `nomarchy-launch-floating-terminal-with-presentation`, `nomarchy-menu-keybindings`) all resolve. Two structural inconsistencies logged to Later: keymap routing (already in 72f7e7b) and the new hyprsunset toggle-vs-systemd reconcile. `KEYBINDINGS.md` regenerated with zero diff — generator already covers both binding source locations. Runtime verification (boot live ISO, eyeball waybar/walker/screensaver flows across panel positions and palettes) remains the user's responsibility before declaring Component 5 fully closed.
- _2026-05-18_ — Hardware DB correctness pass + ROG Ally support + CI lint. Audited every `nomarchy-hardware-db` entry against `inputs.nixos-hardware.nixosModules` and found **21 of 43 entries (49%) referenced modules that don't exist** — `microsoft-surface-pro-8`, `lenovo-thinkpad-x1-carbon-gen11`, `framework-13-11th-gen-intel`, etc. were all eval-time failures waiting for a real user. Rewrote the DB to use only valid module names: Framework gens dropped the "13-" prefix in nixos-hardware (`framework-11th-gen-intel`, not `framework-13-11th-gen-intel`); ThinkPad X1 modules are `x1-Nth-gen`, not `x1-carbon-genN`; Surface Pro 6/7/8/10 all share `microsoft-surface-pro-intel`; Surface Book / Intel Surface Laptop have no module (rows dropped, generic detection still emits sensible `common-pc-laptop` + cpu/gpu). Added matchers for **ROG Ally** (RC71L / RC72LA / "ROG Ally" via `asus-ally-rc71l`). Documented Steam Deck and Snapdragon X as nixos-hardware-unsupported in a footer comment (Steam Deck → Jovian-NixOS; Snapdragon X → installer is x86_64 only). Added a CI step (`.forgejo/workflows/check.yml`) that fails on any DB entry whose module name isn't in `nixos-hardware.nixosModules` — closes this regression class.
- _2026-05-18_ — `nomarchy-manual` re-targeted at local docs. The script's `xdg-open` previously pointed at `https://learn.omacom.io/2/the-nomarchy-manual` — an upstream Omarchy URL that opened an unrelated page when users hit the menu's Help entry. Now opens `~/.local/share/nomarchy/README.md` (the local docs index per `SKILL.md`'s "Out of Scope" note), with a `notify-send` fallback if the source tree isn't synced.
- _2026-05-18_ — Docs hygiene: STRUCTURE.md "Root Directory" + Pillar 6 reality-check. `docs/STRUCTURE.md` listed three top-level files that don't exist (`GEMINI.md`, root-level `STRUCTURE.md`, `TODO.md`) — replaced with an accurate root listing plus a `docs/` sub-tree that names every doc. Pillar 6 in this file had `nomarchy-welcome`, `docs/TROUBLESHOOTING.md`, and the "docs index" bullet still marked Next despite all three shipping on 2026-04-26 — moved to `(Shipped)`. `nomarchy-manual` bullet's "orphaned reference today" claim was stale (the script is called from `nomarchy-menu` and `nomarchy-theme-install`); rewritten to reflect the real remaining issue — its hardcoded `xdg-open https://learn.omacom.io/2/the-nomarchy-manual` is an Omarchy URL.
- _2026-05-18_ — Installer state.json is now schema-driven. Replaced the heredoc in `installer/install.sh` that hardcoded the JSON literal (theme/dns/wifi/features/etc.) with a `nix eval` of `lib/state-schema.nix`'s `system` block, overlaid with the installer-chosen timezone. Closes the last source-of-truth split after the centralization batch — adding a new default in the schema now reaches the installer with no further plumbing. Output is identical modulo alphabetical key ordering (Nix's `builtins.toJSON` sorts keys; toggle scripts read/write via `jq` so it's invisible to them). Dry-run path unchanged (still bind-mounts a fake `/mnt` so the generator's absolute paths resolve correctly). `bash -n` + `shellcheck --severity=error` clean.
- _2026-05-18_ — Complete the hybrid-GPU wiring + fix unoverridable state-derived options. Two related fixes shipped together. **(1)** `nomarchy.system.features.hybridGPU = true` now wires the full NVIDIA driver stack (`services.xserver.videoDrivers = ["nvidia"]`, `hardware.graphics.{enable,enable32Bit}`, `hardware.nvidia.{modesetting,powerManagement}.enable`, `package = nvidiaPackages.stable`, `boot.kernelParams += "nvidia-drm.modeset=1"`) — was previously enabling only `supergfxd` mode-switching while leaving the system with no NVIDIA driver loaded, so mode switches silently no-op'd. All knobs use `lib.mkDefault` so a downstream `system.nix` can pin a beta driver, flip to the open kernel module, etc. Bus-ID prime config (per-machine) stays user-supplied — `docs/OPTIONS.md` has the full recipe. **(2)** Both `core/system/state.nix` and `core/home/state.nix` now use `lib.mkDefault` on every state.json-derived assignment, fixing a class of "I set X in my system.nix but it doesn't take effect" bugs (the state-derived value was at default priority and conflicted with the user's same-priority override). Side-effect cleanup: `core/system/state.nix` now also reads from `lib/state-schema.nix` like `core/home/state.nix` does, completing the schema-centralization started two batches ago. Verified `nix flake check` + an override test that flips hybridGPU via an overlay and confirms the entire driver stack engages.
- _2026-05-18_ — Pillar 4: pre-flight resume polish. Fixed four resume-flow gaps in `installer/install.sh`: (1) `--resume` with a missing state file now errors loudly with a tmpfs explanation instead of silently falling through to a fresh prompt cycle (the most common operator confusion was "rebooted, forgot tmpfs eats /tmp/, watched the installer start over without realising"); (2) on resume, the saved target drive is validated as a block device before any disk-phase step runs — catches the live-ISO USB-unplugged / non-deterministic /dev/sdX class of mid-install failures; (3) `save_state` now stamps an ISO-8601 timestamp and `load_state` shows a `(saved Xm ago)` banner plus a `Target: /dev/X → user @ host` summary line, so the user can `Ctrl-C` if they're resuming onto the wrong host before any destructive prompt fires; (4) `--help` now documents the tmpfs limitation. `shellcheck --severity=error` passes.
- _2026-05-18_ — Declarative-state defaults centralization. Made `lib/state-schema.nix` the single source of truth for every state-default that previously lived in three places (the schema itself, `core/system/options.nix` / `core/home/options.nix` `default = …` clauses, and `core/home/state.nix` `or …` fallbacks). Replaced ~25 hardcoded literals with `schema.<scope>.<key>` reads. Side-effect: fixed a lingering bug where `core/home/options.nix:theme` still defaulted to `"summer-night"` after the system-side was moved to `"nord"` — half the codebase's home option resolved to the wrong theme when state.json was missing/blank. `nix flake check --no-build` confirms zero semantic change for every other field. Doesn't touch the installer-written `state.json` (separate batch — needs schema → JSON generation).
- _2026-05-18_ — Pillar 7 first step: Forgejo Actions CI (eval + lint). New `.forgejo/workflows/check.yml` runs on every push to `main` and every PR: (1) `nix flake check --no-build` to catch eval regressions, (2) `bash -n` + `shellcheck --severity=error` over every `nomarchy-*` bash script (whole-tree, not just changed files — gates branches that bypass the pre-commit hook), (3) `docs/SCRIPTS.md` drift check (fails loudly if a script change didn't regenerate the audit doc). All three checks pass locally on the current tree. Activation requires enabling Actions on the Forgejo repo and registering a `forgejo-runner`; the workflow itself is dormant until then. ISO build job is intentionally deferred — needs a binary cache (Cachix/Attic) to be tractable.
- _2026-05-18_ — **Pillar 3 Phase B: complete.** Final batch (restart/sudo/theme/misc clusters) cleared the last 13 `unused?` rows. Deleted five truly dead scripts: `nomarchy-restart-{hyprctl,mako}` (theme switching calls `hyprctl reload`/`makoctl reload` directly now), `nomarchy-restart-tmux` (one-liner of marginal value), `nomarchy-battery-present` (battery monitor checks `/sys/class/power_supply/BAT*` inline), `nomarchy-sudo-keepalive` (intended-to-be-sourced building block with no users). Surfaced eight useful tools in `SKILL.md` so the audit catches them as `kept` and AI assistants can discover them: `nomarchy-restart-trackpad` (intel_quicki2c reload), `nomarchy-sudo-{passwordless-toggle,reset}`, `nomarchy-theme-{bg-install,refresh,remove}`, `nomarchy-refresh-fastfetch`, `nomarchy-windows-vm` (new Virtualization section). Final state: 159 scripts, all `kept`, `unused?` = 0, missing references = 0.
- _2026-05-18_ — Pillar 3 Phase B: webapp/tui/voxtype install-remove pair triage. Deleted two dead webapp URI handlers (`nomarchy-webapp-handler-hey`, `nomarchy-webapp-handler-zoom`) — no `.desktop` MimeType registration anywhere routed `mailto:`/`zoom:` URIs to them, so the handlers could never fire. Surfaced six useful CLI tools in `SKILL.md` "Common Tasks" so they're discoverable by AI assistants and tagged `kept` by the audit: `nomarchy-webapp-{remove,remove-all}`, `nomarchy-tui-{remove,remove-all}`, `nomarchy-voxtype-{install,remove}`. Script count 166 → 164; `unused?` 21 → 13.
- _2026-05-18_ — Pillar 3 Phase B: dead-code sweep (NixOS-irrelevant Omarchy ports). Deleted five scripts that duplicated NixOS-native facilities or referenced infrastructure Nomarchy doesn't ship: `nomarchy-rollback` (boot-menu generations + `nixos-rebuild rollback` already cover this), `nomarchy-snapshot` (used `snapper`; impermanence and BTRFS subvolumes are the Nomarchy answer), `nomarchy-migrate-state` (one-shot pre-unification migration, no current callers), `nomarchy-config-direct-boot` (added an EFI entry for a UKI we never build), and `nomarchy-npx-install` (Arch idiom — `nix-shell -p nodejs` is the NixOS path). Kept `nomarchy-build-iso` and `nomarchy-build-live-iso` and surfaced them in README §2 so the audit tags them `kept`. Script count 171 → 166.
- _2026-05-18_ — Pillar 3 Phase B: missing-references triage. (1) Wrote `themes/engine/scripts/nomarchy-theme-next` so `SKILL.md`'s documented "cycle to next theme" command resolves; (2) scrubbed three stale `nomarchy-dev-*` references from `core/home/config/nomarchy-skill/SKILL.md`; (3) added a line-context filter to both `nomarchy-docs-scripts` generators that drops `nomarchy-*` tokens appearing in Nix `pname`/derivation idents, `/tmp/` & `/etc/sudoers.d/` paths, `nixosConfigurations.*` / `packages.*` flake outputs, `mktemp -t` prefixes, systemd unit vars, `./result/bin/run-` binaries, and `docker` container references; (4) added a small token-level denylist for five residual non-script identifiers (`nomarchy-plymouth`, `nomarchy-sddm-theme`, `nomarchy-live`, `nomarchy-rev`, `nomarchy-windows`) that survive line filtering. `docs/SCRIPTS.md` "Missing references" section is now empty (was 15).
- _2026-05-04_ — Pillar 8: Distro Branding. (1) Scrubbed remaining "Omarchy" and "Spirit of Omarchy" references from README, scripts, and welcome wizard; (2) Updated `nomarchy-welcome` banner and `nomarchy-version` codename ("Sovereign"); (3) Verified existing `core/system/branding.nix` handles OS-release and bootloader labels; (4) Confirmed SDDM and Plymouth metadata are already Nomarchy-branded.
- _2026-05-04_ — Thorough Out-of-the-Box QA Audit. (1) Restored automatic wallpaper switching by removing image filters from deployed themes; (2) Fixed broken "Style" menu entries by creating missing `about.txt` and `screensaver.txt` branding files; (3) Cleaned up conflicting keybindings by removing deprecated `tiling.conf` and updating the doc generator; (4) Removed legacy Nord theme hack from `nomarchy-theme-set`; (5) Fixed JSON parse error in `summer-day` waybar theme.
- _2026-05-03_ — Fixed multi-disk LUKS/BTRFS boot hang. (1) Moved temporary LUKS keyfile to `/tmp/` so Disko correctly omits it from the runtime configuration; (2) Injected `x-systemd.requires` and `x-systemd.device-timeout=0` into BTRFS mount options to ensure all LUKS drives are decrypted before mounting.
- _2026-05-03_ — Fixed CLI wrappers and removed obsolete code. (1) Updated `nomarchy-font`, `nomarchy-theme`, and `nomarchy-wallpaper` CLI wrappers to use modern Walker menus; (2) Removed the obsolete and broken `themes/engine/switcher.nix` and its associated Nix-inlined scripts; (3) Cleaned up remaining `$NOMARCHY_PATH` references from the Omarchy era.
- _2026-05-03_ — Fixed `/etc/nixos` ownership after installation. Added a `chown -R $USERNAME:users /etc/nixos` step via `nixos-enter` at the end of `installer/install.sh` so the main user owns their configuration and can run `home-manager` commands without `sudo`.
- _2026-05-01_ — Installer & Script Audit Polish. (1) Fixed a critical bash dynamic scoping bug in `installer/install.sh` where `rc=0` assignments inside functions (Impermanence, Form Factor) were clobbering the main loop's return code, causing the installer to abort when "No" was selected; (2) Polished `hosts/nomarchy-live.nix` with auto-login for the `nixos` user and passwordless sudo for the `wheel` group; (3) Repurposed `nomarchy-toggle-suspend` to execute `systemctl suspend` directly and updated `nomarchy-menu` to reflect this; (4) Updated `nomarchy-launch-wifi` to use `nmtui` in Alacritty; (5) Regenerated `docs/SCRIPTS.md` to reflect the updated script mappings.
- _2026-04-30_ — `set -e` sweep across `nomarchy-*` scripts. Added `set -e` to 142 of 169 bash scripts that lacked it (27 already had it). Halts a class of "command failed silently in the middle of a chain, system left in half-applied state" bugs that produced repeat-fix commits. One deliberate exception: `nomarchy-menu` runs without `set -e` because it's an interactive UX loop where action failures should re-display the menu rather than abort the script. Pre-commit hook now enforces `bash -n` + `shellcheck --severity=error` so future scripts can't regress this.
- _2026-04-30_ — Installer disk-phase reliability. Hardened `installer/install.sh` and consolidated the disko configs: (1) `select_disk` now hides the live-ISO boot device(s) so the installer can't format its own boot media (`NOMARCHY_INSTALL_ALLOW_ISO_TARGET=1` to override); (2) added a 10 GiB minimum-capacity preflight; (3) `prewipe_target_drive` enumerates every active dm-crypt mapping backed by the target drive and closes them, drops the silent `|| true` from `wipefs`/`sgdisk`/`dd`, bounds `udevadm settle` to 30s, and refuses to continue if anything is still mounted; (4) wrapped the disko call in `run_disko_with_retry` with last-30-lines + Retry / View full log / Abort dialog on failure; (5) replaced the sed-templated `disko-golden.nix` + `disko-btrfs-multi.nix` pair with a single `disko-config.nix` Nix function called via `--argstr mainDrive … --arg extraDrives '[…]'` — eliminates a class of escaping bugs (cf. `3aadc36`); (6) added an EXIT trap so the tmpfs LUKS key file is removed even on early abort.
- _2026-04-30_ — Gaming home-side companion. New `nomarchy.gaming.enable` option (mirror of `nomarchy.system.gaming.enable`) and `core/home/gaming.nix` module that injects a Hyprland `windowrulev2 = fullscreen, class:^(steam_app_).*$` so Steam-launched games grab the whole screen. Closes the "Gaming — Hyprland window rule" Next-column row.
- _2026-04-26_ — Default to highest resolution (`highres`) for monitors. Updated `features/desktop/hyprland/config/monitors.conf` and forced it in the live ISO (`nomarchy-live`) to resolve issues where some hardware would default to a low resolution (1024x768).
- _2026-04-26_ — First-run welcome wizard (`nomarchy-welcome`). Extended from a one-shot greeter into a guided picker for theme, font, and panel position. Added Step 4 to generate a starter `home.nix` if missing. State is now persisted in `state.json` via `.welcome_done`. Added `nomarchy.panelPosition` option to Waybar.
- _2026-04-26_ — Multi-disk BTRFS support in the installer. Added `installer/disko-btrfs-multi.nix` template and updated `installer/install.sh` to allow selecting multiple drives via `gum choose --no-limit`. Implements BTRFS "single" data + RAID1 metadata across multiple LUKS-encrypted drives.
- _2026-04-26_ — Distro Branding Phase 2. Updated bootloader entries to use "Nomarchy" as the label. Set ISO volume IDs to `NOMARCHY_INSTALLER` and `NOMARCHY_LIVE`. Fixed branding in Plymouth theme metadata and SDDM metadata.
- _2026-04-26_ — Distro Branding Phase 1. Renamed `installerIso` to `nomarchy-installer` and `installerIsoGraphical` to `nomarchy-live`. Updated metadata and host configurations. Scrubbed "Omarchy" from Plymouth and installer messages.
- _2026-04-26_ — Fix `hardware-db.sh` missing in `nomarchy-installer.nix`. Resolved boot error where `install.sh` failed to source the hardware database on the TTY installer ISO.
- _2026-04-26_ — Installer review-then-edit flow (`installer/install.sh`). Review screen now offers Continue / Edit a field / Abort. Edit opens a multi-select of saved fields; chosen fields clear and the next loop iteration re-prompts only those. Benefits both fresh installs (typo fixes without abort+restart) and `--resume` (lands on review immediately, since the loaded vars short-circuit each prompt). LUKS passphrase is held in memory across loop iterations so re-edits don't re-ask for it.
- _2026-04-26_ — `docs/TROUBLESHOOTING.md`. The five most common rebuild errors (option-already-declared, attribute-missing, Stylix target conflict, home-manager `.hm-bak` churn, impermanence path missing) with copy-paste fixes. Linked from `README.md` and `docs/MIGRATION.md`.
- _2026-04-26_ — Gaming preset module (`core/system/gaming.nix`). Opt-in `nomarchy.system.gaming.enable` (default false). Wires `programs.steam` (with `remotePlay`/`localNetworkGameTransfers` firewall holes via `mkDefault`), `programs.gamemode`, and `services.flatpak`. Flathub remote and Hyprland window-rule split into separate Next-column rows.
- _2026-04-26_ — Accessibility preset module (`core/system/accessibility.nix`). New `nomarchy.system.accessibility.{enable,cursorSize}` options (opt-in, default off — accessibility isn't a hardware-derived signal). Enables `services.gnome.at-spi2-core`, installs Orca, and sets `XCURSOR_SIZE=32` (configurable). Hyprland-side companion (key-repeat slowdown, Orca keybinding, high-contrast palette) split into a new Next-column row.
- _2026-04-26_ — Desktop preset module (`core/system/desktop.nix`). New `nomarchy.system.desktop.enable` option; defaults to `formFactor == "desktop"` (mirror of the laptop preset's auto-enable). Pins `powerManagement.cpuFreqGovernor` to `"performance"` and enables `services.zfs.{autoScrub,trim}` so a future ZFS pool gets sensible maintenance for free.
- _2026-04-26_ — Laptop preset module (`core/system/laptop.nix`). New `nomarchy.system.laptop.{enable,thermald}` options; `enable` defaults to `formFactor == "laptop"` so the installer's existing `formFactor` write auto-flips it on. Wires TLP (governors + 75/80 charge thresholds), force-disables `power-profiles-daemon`, enables `upower` and `thermald` (x86_64), adds the brightnessctl udev rule for backlight without root, and sets a logind lid-switch policy that defers to `hibernation.enable`. Closes both the Now item and the largest Next item.
- _2026-04-25_ — Software-profile multi-select in the installer. Users can now pick Dev, Gaming, Office, Media, and CLI Utils profiles during install; logic emits corresponding `home.packages` and system toggles into the generated config.
- _2026-04-25_ — Pillar 3 Phase B: script & menu audit. Ported/implemented/stubbed ~40 scripts including `nomarchy-version`, `nomarchy-debug`, `nomarchy-reinstall`, `nomarchy-rollback`, `nomarchy-update-firmware`, `nomarchy-pkg-*`, and `nomarchy-theme-*` wrappers. Moved desktop scripts to packaged utility directory.
- _2026-04-25_ — Docker & fwupd support. Added `nomarchy.system.virtualization.docker.enable` and `nomarchy.hardware.fwupd` options. Wires system services and adds `docker-compose` and `fwupdmgr` to PATH.
- _2026-04-25_ — Installer VM testing. Added `installerVm` to flake nixosConfigurations, packages, and apps. `nomarchy-test-installer` now uses `nix run .#installerVm`.
- _2026-04-25_ — `docs/KEYBINDINGS.md` auto-generator. New repo-tooling script `bin/utils/nomarchy-docs-keybindings` parses every `bindd =` / `bindeld =` line into a Markdown doc; README's keybinding table slimmed to highlights + link.
- _2026-04-25_ — Installer disk picker shows NAME / SIZE / TYPE / VENDOR / MODEL / SERIAL columns instead of bare `lsblk`. Type derived from `ROTA` + `TRAN` (NVMe / USB / SSD / HDD). Filters loop, ram, zram, sr.
- _2026-04-25_ — Pillar 3 Phase A: script & menu audit. New `bin/utils/nomarchy-docs-scripts` generator produces `docs/SCRIPTS.md` with 136 scripts and the menu walk pre-tagged via heuristics (`kept` / `unused?` / `missing`). Phase B (per-batch porting / removal) opens.
- _2026-04-25_ — Installer prompts for keyboard layout + locale, applies live; new `nomarchy.{system,}.formFactor` option; waybar drops battery widget on desktop; nm-applet visibility fix in default theme; live-ISO baseline keymap/locale (`a7e7fa9`).
- _2026-04-25_ — `docs/OPTIONS.md` reference; `docs/MIGRATION.md` linked from `README.md` (`3cb012b`, `6ef28f0`).
