Compare commits

..

6 Commits

Author SHA1 Message Date
Bernardo Magri
28a0e28f2d docs(roadmap): log uwsm-in-virtualization module placement (Later)
core/system/virtualization.nix wires `programs.uwsm` + the Hyprland
session config at the top of the file — loaded unconditionally on every
install, with no actual relationship to libvirt/docker. Cosmetic
mislocation, not a behavior bug; logged as a Later row so it can be
fixed in a dedicated session module without growing this audit PR.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:44 +01:00
Bernardo Magri
0e93639702 fix(hibernate): mkDefault on HandlePowerKey / IdleAction / IdleActionSec
These three settings.Login fields were set at default priority, so a
downstream system.nix that wrote (e.g.) `services.logind.settings.Login.HandlePowerKey = "poweroff"`
would collide with Nomarchy's value instead of overriding it. Same
mkDefault treatment as the other lid-switch settings in this block.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:37 +01:00
Bernardo Magri
0656f33611 chore(schema): drop orphan features.makima
`lib/state-schema.nix` declared `system.features.makima = false` but
the field was never wired anywhere: no matching option in
core/system/options.nix, no consumer in core/system/state.nix, no
references in the wider tree. Schema-only ghost — removed.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:32 +01:00
Bernardo Magri
749f970fb0 fix(impermanence): user must match created account, not hardcoded "nomarchy"
The persistence block at core/system/impermanence.nix:75 read
`users.nomarchy = { directories = [...]; }` — the username was a
literal, not a reference. For any user not literally named "nomarchy"
the block was silently inert and ~/.ssh, ~/.gnupg, ~/.local/share/keyrings,
Documents, Downloads, Pictures, Videos, Projects were wiped on every boot.

Adds `nomarchy.system.impermanence.user` (str, default "nomarchy") and
uses it via `users.${cfg.user}`. The installer now writes the chosen
username alongside `enable` and `mainLuksName` so impermanence installs
with non-default usernames are correct out of the box.

docs/OPTIONS.md: fixes the wrong path on the impermanence row
(documented `impermanence.enable`, real option is
`nomarchy.system.impermanence.enable`) and adds entries for
`mainLuksName` and `user`.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:27 +01:00
Bernardo Magri
bfd95cb40b docs(roadmap): mark Pillar 5 preset rows as Shipped
Laptop, Desktop, Accessibility, and Gaming presets all shipped on
2026-04-26 but were still tagged (Next). Reorders the pillar so the
two genuinely open items (dGPU auto-detect, Surface support) lead.
2026-05-19 17:28:16 +01:00
Bernardo Magri
9283403d8f docs(roadmap): add Pillar 8 QA audit + clean stale Pillar 4 rows
Pillar 3 audited script existence; Pillar 8 audits feature behavior.
Adds a per-component sweep methodology (10 components, one PR each on
wave/qa-<component>) and lists it on the Now board so the next session
can pick it up without re-deriving scope.

Cleanup pass on Pillar 4: removes two "(Now)" entries (software-profile
multi-select, form-factor → laptop preset) already in the Shipped log,
and promotes the two remaining open items ("What's installed?" summary,
non-LUKS branch) to the Now board.
2026-05-19 17:26:22 +01:00
6 changed files with 67 additions and 18 deletions

View File

@@ -15,9 +15,9 @@ in
settings.Login = { settings.Login = {
HandleLidSwitch = lib.mkDefault "suspend-then-hibernate"; HandleLidSwitch = lib.mkDefault "suspend-then-hibernate";
HandleLidSwitchExternalPower = lib.mkDefault "suspend"; HandleLidSwitchExternalPower = lib.mkDefault "suspend";
HandlePowerKey = "hibernate"; HandlePowerKey = lib.mkDefault "hibernate";
IdleAction = "suspend-then-hibernate"; IdleAction = lib.mkDefault "suspend-then-hibernate";
IdleActionSec = toString (cfg.idleMinutes * 60); IdleActionSec = lib.mkDefault (toString (cfg.idleMinutes * 60));
}; };
}; };
}; };

View File

@@ -24,6 +24,18 @@ in
"crypted_main" on multi-disk installs to match the disko layout. "crypted_main" on multi-disk installs to match the disko layout.
''; '';
}; };
user = lib.mkOption {
type = lib.types.str;
default = "nomarchy";
description = ''
Primary user whose home subset (.ssh, .gnupg, keyrings, common
directories) survives the rootfs wipe. Must match the user
created via `users.users.<name>` otherwise the persistence
block is silently inert and the user's home directory is wiped
on every boot. The installer writes this for you.
'';
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
@@ -72,7 +84,7 @@ in
"/etc/machine-id" "/etc/machine-id"
"/etc/supergfxd.conf" "/etc/supergfxd.conf"
]; ];
users.nomarchy = { users.${cfg.user} = {
directories = [ directories = [
".ssh" ".ssh"
".gnupg" ".gnupg"

View File

@@ -153,10 +153,18 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
`bool`, default `false`. Intel IPU7 camera support (kernel modules + firmware). `bool`, default `false`. Intel IPU7 camera support (kernel modules + firmware).
### `impermanence.enable` ### `nomarchy.system.impermanence.enable`
`bool`, default `false`. Erase Your Darlings root wipe on boot. Defined in `core/system/impermanence.nix`. The installer writes the flag based on the impermanence prompt. `bool`, default `false`. Erase Your Darlings root wipe on boot. Defined in `core/system/impermanence.nix`. The installer writes the flag based on the impermanence prompt.
### `nomarchy.system.impermanence.mainLuksName`
`str`, default `"crypted"`. Name of the `/dev/mapper` entry holding the BTRFS root. The disko layout uses `"crypted"` on single-disk installs and `"crypted_main"` once multiple drives are selected — the installer writes the matching value automatically.
### `nomarchy.system.impermanence.user`
`str`, default `"nomarchy"`. Primary user whose home subset (`.ssh`, `.gnupg`, `.local/share/keyrings`, `Documents`, `Downloads`, `Pictures`, `Videos`, `Projects`) survives the rootfs wipe. Must match the user created via `users.users.<name>` — otherwise the persistence block is silently inert and the user's home directory is wiped on every boot. The installer writes this for you.
--- ---
## Home Manager options (`home.nix`) ## Home Manager options (`home.nix`)

View File

@@ -19,7 +19,9 @@ Guardrails (apply when adding anything):
### Now (ready to pick up) ### Now (ready to pick up)
- (Empty for now) - **Full QA audit of shipped features.** Walk every feature/component end-to-end on a real install, fix what's small, log what's not. Runs as per-component PR sweeps — methodology in [Pillar 8](#8-pillar-qa-audit--features--components).
- **Installer: "What's installed?" summary on first boot.** Surface what the installer actually wrote (theme, font, profiles, drives, form factor) from `state.json` + `nomarchy-system-scripts` introspection so the user can verify before they start customising. Detail in [Pillar 4](#4-pillar-installer).
- **Installer: optional non-LUKS branch.** Let users explicitly opt out of FDE during install. Detail in [Pillar 4](#4-pillar-installer).
### Next (bigger lifts that build on Now) ### Next (bigger lifts that build on Now)
@@ -37,6 +39,7 @@ Guardrails (apply when adding anything):
- **Forgejo release pipeline.** `vYY.MM.x` tags matching the upstream NixOS channel; the pipeline pushes the three ISOs and an updated `flake.lock` snapshot. - **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. - **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. - **Surface support module** via the relevant `nixos-hardware` profile + Surface kernel patches behind a `nomarchy.hardware.isSurface` toggle.
- **Move `programs.uwsm` Hyprland session out of `core/system/virtualization.nix`.** Session-manager config is wired in the virtualization module by historical accident — it's loaded unconditionally on every install and has nothing to do with libvirt/docker. Move to a dedicated `core/system/session.nix` (or fold into the Hyprland feature module) so the location matches the responsibility.
## 3. Pillar: Script & menu audit ## 3. Pillar: Script & menu audit
@@ -73,23 +76,23 @@ Each PR description should reference the row(s) in `docs/SCRIPTS.md` it closes,
## 4. Pillar: Installer ## 4. Pillar: Installer
- Software-profile multi-select (Now). - "What's installed?" summary screen on boot of a freshly-installed system, sourced from `state.json` + `nomarchy-system-scripts` introspection (Now).
- Optional non-LUKS branch in the installer for users who explicitly opt out of FDE (Now).
- Richer disk metadata (Shipped). - Richer disk metadata (Shipped).
- Form-factor → laptop preset (Now, depends on Pillar 5).
- `disko-golden.nix` variants for software-RAID and BTRFS-pool-as-root (Shipped). - `disko-golden.nix` variants for software-RAID and BTRFS-pool-as-root (Shipped).
- Pre-flight resume polish (Shipped). - Pre-flight resume polish (Shipped).
- "What's installed?" summary screen on boot of a freshly-installed system, sourced from `state.json` + `nomarchy-system-scripts` introspection. - Software-profile multi-select (Shipped).
- Optional non-LUKS branch in the installer for users who explicitly opt out of FDE. - Form-factor → laptop preset (Shipped).
## 5. Pillar: Power, hardware, presets ## 5. Pillar: Power, hardware, presets
- Laptop preset (Next): TLP, upower, brightness, lid, hypridle tuning.
- Desktop preset (Next): performance governor, no laptop UI (already filtered), ZFS hooks.
- Accessibility preset (Next).
- Gaming preset (Next).
- 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).
- Surface support behind `nomarchy.hardware.isSurface` (Later).
- 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). - 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 ## 6. Pillar: Onboarding & docs
@@ -109,6 +112,33 @@ Each PR description should reference the row(s) in `docs/SCRIPTS.md` it closes,
- `nixosTest` per palette: boots `default` in a VM, screenshots the SDDM splash and the Hyprland desktop, diffs vs golden. Failure surfaces as CI red. - `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. - 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 ## 9. Process notes
- **Branch naming:** `wave/<pillar>-<short-slug>`. Examples: `wave/audit-pkg-scripts`, `wave/installer-disk-metadata`, `wave/laptop-preset`. - **Branch naming:** `wave/<pillar>-<short-slug>`. Examples: `wave/audit-pkg-scripts`, `wave/installer-disk-metadata`, `wave/laptop-preset`.

View File

@@ -1459,7 +1459,7 @@ generate_flake_config() {
if (( ${#_drives[@]} > 1 )); then if (( ${#_drives[@]} > 1 )); then
_main_luks_name="crypted_main" _main_luks_name="crypted_main"
fi fi
impermanence_opt=$'nomarchy.system.impermanence.enable = true;\n nomarchy.system.impermanence.mainLuksName = "'"$_main_luks_name"$'";' impermanence_opt=$'nomarchy.system.impermanence.enable = true;\n nomarchy.system.impermanence.mainLuksName = "'"$_main_luks_name"$'";\n nomarchy.system.impermanence.user = "'"$USERNAME"$'";'
fi fi
local PROFILE_SYSTEM_OPTS="" local PROFILE_SYSTEM_OPTS=""

View File

@@ -50,7 +50,6 @@
fingerprint = false; fingerprint = false;
fido2 = false; fido2 = false;
hybridGPU = false; hybridGPU = false;
makima = false;
}; };
}; };