Commit Graph

164 Commits

Author SHA1 Message Date
Bernardo Magri
3510a51492 fix(installer): resolve multi-disk LUKS/BTRFS boot hang
- Move temporary LUKS keyfile to /tmp/ so Disko omits it from runtime config
- Explicitly add x-systemd.requires and x-systemd.device-timeout=0 to BTRFS mount options
- Ensures all LUKS devices are decrypted before BTRFS attempts to mount
2026-05-03 09:13:02 +01:00
Bernardo Magri
7064108ce7 fix(distro): fix /etc/nixos ownership, theme discovery, and CLI wrappers
- installer: set recursive ownership of /etc/nixos to main user post-install
- themes: fix NOMARCHY_PATH and discovery logic for Lua theme menu
- scripts: update CLI wrappers (font, theme, wallpaper) to use Walker menus
- core: remove obsolete NOMARCHY_PATH and cleanup dead code
- features: add pkgs.lua for Walker and remove obsolete switcher.nix
- docs: update ROADMAP.md, SCRIPTS.md and STRUCTURE.md
2026-05-03 08:59:13 +01:00
Bernardo Magri
bef7be01b8 fix(installer): wire HM as a NixOS module, move env-update to system layer
The post-install standalone HM activation kept failing in new ways
(daemon access, git ownership, missing PATH on first boot). Wire HM as
a NixOS module in the generated flake instead, so first-boot dotfiles
are activated by `nixos-install` itself with proper system context. The
standalone `homeConfigurations.<user>` is kept alongside for fast
iteration via `nomarchy-env-update`. Also:

- Drop the chroot HM activation block from the installer entirely.
- Move `nomarchy-env-update` from `features/scripts/utils/` to
  `core/system/scripts/` so it ships in `nomarchy-system-scripts` and
  exists on a freshly-installed system regardless of HM state.
- Set system-wide git `safe.directory` for /etc/nixos and the
  impermanence-relocated /persist/etc/nixos so the user-mode HM run
  doesn't trip on the root-owned flake repo.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 12:24:12 +01:00
Bernardo Magri
d4f50afc62 fix(installer): start nix-daemon and trust flake repo for HM activation
HM activation inside `nixos-enter` failed with `big.lock: Permission
denied` because the chroot has no systemd and therefore no nix-daemon —
the user-level `nix run` fell back to single-user mode and couldn't
write /nix/var/nix/db. Launch nix-daemon manually for the activation
window and force NIX_REMOTE=daemon. Also mark /etc/nixos (and the
impermanence path) as a git safe.directory so HM doesn't trip over
git's dubious-ownership check on the root-owned repo. Make
nomarchy-env-update self-bootstrap via `nix run home-manager` when
home-manager isn't on PATH so the recovery hint actually works on a
freshly-installed system.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 11:56:22 +01:00
Bernardo Magri
2f18d4efcf fix(installer): unblock disko, bootloader, HM activation, hyprland res
- Pass --yes-wipe-all-disks to disko so the silent gum-spin path no
  longer hangs forever waiting on a hidden "yes" confirmation prompt
  (added in disko 1.13's destroy,format,mount mode).
- Stop threading an externally-built pkgs into the user flake's
  nixosSystem; configure nixpkgs through the module system instead so
  core/system/default.nix's nixpkgs.config.allowUnfree stops conflicting
  with the assertion "system configures nixpkgs with an externally
  created instance".
- Enable boot.loader.systemd-boot in the generated system.nix so the
  installed system has an actual bootloader (disko already lays out a
  1 GiB ESP at /boot).
- Bump nix.settings.download-buffer-size to 512 MiB to silence the
  "download buffer is full" warning on large NAR fetches.
- Activate home-manager via `runuser -l` instead of `runuser -u … --
  env HOME=…`. The latter only switches uid and leaves \$USER=root, so
  HM's activation script saw root, warned, and wrote dotfiles into
  /root/ — meaning the user's first login had no Hyprland config.
- Revert default Hyprland monitor line back to highres (live ISO and
  user default) — preferred falls back to EDID's 1024x768 in QEMU and
  on several laptop panels, which is the bug highres was put there to
  defeat.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 11:07:02 +01:00
Bernardo Magri
329dc009b6 fix(installer): repair git init, LUKS reprompt, impermanence-no exit, quiet disko
- nrun git git init -q passed 'git' as a subcommand to git itself,
  failing the post-disko repo init. Drop the duplicated arg.
- disko's luks module reads passwordFile at the top level; placing it
  under settings.* meant it was silently ignored and disko fell back
  to askPassword=true, prompting the user again on luksOpen. Move the
  option to the right scope.
- configure_impermanence now uses local rc, nrun gum confirm, and an
  explicit case (0/1/130) with a final return 0 so a No answer no
  longer aborts the installer.
- run_disko_with_retry hides disko's chatty output behind a gum spin
  by default and surfaces the captured log on failure. Set
  NOMARCHY_VERBOSE_DISKO=1 to stream output live.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:48:37 +01:00
Bernardo Magri
0af1395df2 fix(themes): complete summer-day with Everforest Light palette
colors.toml and icons.theme were copy-pasted from summer-night (a dark
theme). Repalette to Everforest Light, mark as light via light.mode,
switch icons to Yaru-blue, fix the broken Waybar import, and add the
btop/neovim/vscode/rofi/walker app configs the sibling themes ship.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:48:21 +01:00
Bernardo Magri
f2b99e0f75 adding summer-day theme 2026-05-02 09:16:58 +01:00
Bernardo Magri
6411395d9f fix(qa): comprehensive out-of-the-box audit and repair
- Fix critical bash dynamic scoping bug in install.sh (Impermanence/Form Factor).
- Polished Live ISO with auto-login and passwordless sudo.
- Repurposed nomarchy-toggle-suspend to directly execute systemctl suspend.
- Updated nomarchy-launch-wifi to use nmtui in alacritty.
- Optimized nomarchy-welcome to avoid redundant rebuilds via --no-update flag.
- Enabled nomarchy-welcome in Hyprland autostart.
- Wrapped Live ISO-modifying steps in welcome wizard to prevent failures.
- Removed obsolete hardware auto-detection from nomarchy-on-boot.
- Hardened script doc generator against false-positive wildcard tokens.
- Regenerated docs/SCRIPTS.md and updated docs/ROADMAP.md.
2026-05-01 20:03:04 +01:00
Bernardo Magri
39b1a9c1b3 style(hyprland): set default monitor to 'preferred' resolution
Updated the default Hyprland monitor configuration to 'monitor=,preferred,auto,1'. This ensures the best resolution is selected automatically while maintaining a 1x scale by default.
2026-05-01 17:00:57 +01:00
Bernardo Magri
c5544e56c8 feat(system): default to latest stable kernel
Set boot.kernelPackages to pkgs.linuxPackages_latest by default. This ensures Nomarchy users benefit from the latest hardware support and security features in the mainline kernel.
2026-05-01 16:54:01 +01:00
Bernardo Magri
0306dff092 feat(installer): implement single-input flake architecture
- Refactor generated flake.nix to use the Appliance Model.
- Downstream flake now only defines the 'nomarchy' input.
- Dependencies (nixpkgs, home-manager) are inherited from nomarchy.inputs to ensure maximum stability and version alignment with upstream.
2026-05-01 16:51:53 +01:00
Bernardo Magri
3b977f181d fix(installer): resolve disko evaluation crash and infinite loops
- Fix disko-config.nix signature by adding '...' to handle unexpected CLI arguments.
- Update disko mode to 'destroy,format,mount' for the modern API and to avoid deprecation warnings.
- Fix infinite loops in 'configure_impermanence' and 'confirm_form_factor' caused by misinterpreting 'No' (rc=1) as an abort.
2026-05-01 16:43:05 +01:00
Bernardo Magri
61cd993e54 fix(githooks): skip bash linting on non-bash nomarchy-* scripts
The nomarchy-* prefix is a name convention, not a language guarantee:
nomarchy-haptic-touchpad is Python. Without a shebang filter, the
pre-commit hook would run `bash -n` on it and abort every commit
that touched the Python helper. Filter to scripts whose shebang
matches `bash` before linting; everything else passes through.

Found via the set -e sweep (1e94818) — the survey caught
nomarchy-haptic-touchpad as a "broken" bash script when it was
just non-bash.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:50:32 +01:00
Bernardo Magri
1e9481849b chore: add 'set -e' to every nomarchy-* bash script that lacks it
Sweep across the three script directories: features/scripts/utils,
core/system/scripts, themes/engine/scripts. 142 of 169 bash scripts
gained `set -e`; 27 already had it; the one Python helper
(nomarchy-haptic-touchpad) was skipped via shebang detection.

Why: bash's default behavior is to continue past a failed command,
which means a script that does "do A; do B; do C" leaves the system
in a half-applied state when B fails - and the user gets no signal.
Several recent fix commits (theme partial-apply, waybar reload race,
installer prewipe silent failures) all trace back to this. set -e
turns silent corruption into a loud abort the user can act on.

The 11 scripts with explicit `|| true` markers stay safe under set -e
because || true coerces the exit to zero; the markers continue to
mean "I deliberately tolerate this failure here."

Deliberate exception: nomarchy-menu runs WITHOUT set -e. It is an
interactive UX loop where action branches do `cmd; back_to <self>`
so a failed action would abort the script under set -e and the menu
would disappear without feedback. Soft-failure - menu re-displays,
user picks again - is the right semantic. Documented inline.

Validation: bash -n on every modified script (zero failures). The
new pre-commit hook (27f5663) was just updated to filter by shebang
so it doesn't try to bash-syntax-check the Python helper - that
filter was uncovered by this sweep.

Risk: set -e can surface latent bugs in scripts that previously
relied on silent continuation. If anything breaks, it's a real bug
that was already broken and is now visible. Easy per-script revert
if any UX glitches show up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:50:13 +01:00
Bernardo Magri
27f5663cdf chore(githooks): lint changed nomarchy-* scripts on commit
Adds two-tier linting before the existing docs/SCRIPTS.md regenerate
step:

- bash -n on every changed nomarchy-* script. Catches syntax errors
  that would otherwise be discovered at runtime by an unlucky user.
  Always fatal.
- shellcheck --severity=error when shellcheck is on PATH. Catches
  unquoted-var, use-before-define, missing-shebang, and other
  bug-shaped patterns. Only error-level issues block - the long
  tail of pre-existing warnings stays as a known cleanup task,
  not a commit blocker. Hook silently skips this step when
  shellcheck isn't installed (so contributors without it can still
  commit).

Catches the class of bug that's bit us repeatedly: a script ships,
the runtime path that exercises the broken line is rare, and the bug
sits latent until a user trips it. Cheaper to catch at commit time.

Caveat: 156 nomarchy-* scripts already have shellcheck warnings
(severity warning/info/style); we deliberately ship around them via
the --severity=error gate. A future per-script audit can dial the
severity up as scripts get cleaned up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:43:37 +01:00
Bernardo Magri
28cc41abdd fix(restart-app): wait for SIGTERM to take effect before respawning
Previous behavior: `pkill -x $1` (no wait) followed by an immediate
background `setsid uwsm-app`. The new instance attached its wayland
surface while the old one's surface was still mapped. Layer-shell
apps got the same visible ghosting that waybar showed on theme switch
before the SIGUSR2 fix (386da51), and non-layer apps got brief double
instances.

Fix:
- Quote $1 (was unquoted, breaks if app name has whitespace - rare
  but cost-free to fix while we're here).
- After SIGTERM, poll pgrep for up to ~1.5s in 100ms ticks.
- If anything is still alive after the poll window, SIGKILL it -
  prevents a misbehaving process from holding the surface forever.
- Only spawn the new instance after the old one is confirmed gone.

Affects every caller that hits the non-systemd-managed restart path
(menu's update-process actions, voxtype install/remove, font-change
follow-ups, etc.).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:09:15 +01:00
Bernardo Magri
5fc9f5ee34 fix(theme): surface partial-apply failures instead of swallowing them
nomarchy-theme-set chains six optional "tell each app the theme changed"
steps. Each used `command -v X && X || true`, which collapsed two very
different outcomes into the same silent path:

  - X isn't installed -> skip (correct, expected, fine)
  - X exists but returned non-zero -> skip (wrong - user just got a
    half-applied theme with zero feedback about which app didn't refresh)

Replaced the inline guards with a small helper that distinguishes
absent from failed and accumulates real failures into a list. At the
end of the run, if anything failed, we notify-send a single message
naming the apps that didn't refresh ("Did not refresh: Waybar, btop")
and echo the same to stderr. The theme apply itself still completes -
we don't abort the chain on one failure - so the user gets the partial
benefit AND the diagnostic.

Same pattern as the waybar SIGUSR2 fix (386da51): make the hot path
loud about real problems while staying quiet about expected
no-installed states.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:08:39 +01:00
Bernardo Magri
5c5b377bd6 fix(menu): quick-state actions return to their submenu instead of exiting
After the cancel-branch sweep, the remaining UX inconsistency was in
action branches: changing one setting kicked the user out of the menu,
forcing a relaunch to change the next. Brought 16 actions across 5
submenus into the same return-to-self pattern theme/background got.

Classification rule applied:

- Quick-state actions (toggle, set, restart-service - finishes in
  milliseconds, no window opens) -> back_to <self>, so the user can
  chain "toggle nightlight, then toggle gaps, then restart waybar"
  without rerunning nomarchy-menu each time.
- Window-opening actions (editor, floating terminal, audio/wifi/bt
  launcher, browser, hyprpicker overlay, screenshot, screenrecord,
  share dialogs, lock/shutdown/logout) stay as one-shot exits -
  re-popping the menu over the new window would be visual noise.

Submenus changed:

- show_toggle_menu (8 toggles): screensaver, nightlight, idle, top
  bar, workspace layout, window gaps, 1-window ratio, display scaling.
- show_setup_power_menu: powerprofilesctl set returns; cancel still
  goes up to show_setup_menu (different destinations on each branch,
  so the if/else stays).
- show_font_menu: nomarchy-font-set returns; cancel still goes up.
- show_setup_system_menu: the suspend toggle (quick) returns;
  hibernate enable/disable (terminal) still exit.
- show_update_process_menu (5 service restarts): hypridle, hyprsunset,
  swayosd, walker, waybar.

For dynamically-rendered menus (show_setup_system_menu rebuilds its
options each invocation based on current state) this also gives free
visual feedback - the toggle's label flips between "Enable Suspend"
and "Disable Suspend" when the menu re-renders.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:01:48 +01:00
Bernardo Magri
4b99fa3846 fix(menu): route every cancel branch through back_to for direct-keybinding consistency
Audit of all show_*_menu functions after the theme/background fix found
11 more cancel branches that called their parent directly instead of
back_to. None are reachable from current keybindings (today's direct
invocations target submenus that already use back_to), so the bug is
latent — but any future `nomarchy-menu <area>` keybinding into one of
these would bounce the user into the parent on Esc instead of exiting
cleanly, the exact bug that prompted the previous commit's fix to
show_theme_menu / show_background_menu.

Mechanical sweep:

  *) show_main_menu   ;;  ->  *) back_to show_main_menu   ;;   (5 sites)
  *) show_setup_menu  ;;  ->  *) back_to show_setup_menu  ;;   (3 sites)
  *) show_update_menu ;;  ->  *) back_to show_update_menu ;;   (3 sites)

Behavior under nested navigation (BACK_TO_EXIT=false) is unchanged:
back_to falls through to calling the parent function by name. Only
direct-invocation cancel paths gain the correct exit-0 behavior.

Action branches and go_to_menu's dispatch table intentionally still use
direct calls — those are forward navigation, not cancel.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:53:41 +01:00
Bernardo Magri
a741b0936c fix(menu): theme and background submenus return to parent instead of exiting
The menu navigation contract: a submenu invoked directly via keybinding
(BACK_TO_EXIT=true, set by go_to_menu when nomarchy-menu is launched
with a target argument) should `exit 0` after the user's action; a
submenu invoked from a parent menu (BACK_TO_EXIT=false) should call
`back_to <parent>` to return where the user came from. back_to() honors
both modes.

Three submenus violated the contract:

- show_theme_menu and show_background_menu shell out to walker's
  Elephant plugin and don't call back_to. After picking a theme or
  wallpaper from Main -> Style -> Theme, the script exits silently
  instead of returning to Style; the user has to relaunch the menu
  from scratch to change anything else.

- show_hardware_menu's cancel branch called show_trigger_menu directly
  instead of back_to show_trigger_menu, which would have bounced a
  direct-keybinding caller into Trigger instead of exiting cleanly.

Adds the missing back_to call to the two walker-backed submenus
(parented to show_style_menu) and converts the hardware cancel branch
to back_to. The 16 other show_*_menu functions already conform.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:50:36 +01:00
Bernardo Magri
f318585dc4 fix(installer): harden disk selection and partitioning phase
The disk phase was the dominant source of incomplete installs. Six
concrete failure modes addressed in one pass:

1. Live-ISO USB excluded from the disk picker. select_disk previously
   filtered loop|ram|zram|sr but not the device the installer booted
   from; picking it would format the boot media mid-install. New
   detect_live_iso_devices walks /, /iso, /run/initramfs/live,
   /nix/.ro-store, /nix/store and resolves each backing device to its
   parent disk via lsblk -no PKNAME. Override with
   NOMARCHY_INSTALL_ALLOW_ISO_TARGET=1 for the developer case.

2. 10 GiB minimum-capacity preflight. Disko fails late and obscurely
   on undersized media; surface it while the picker is still open.

3. prewipe_target_drive rewritten:
   - Enumerates every active dm-crypt mapping via dmsetup ls and
     closes those whose backing device is on the target drive. The
     old version only knew about the hardcoded names "crypted" /
     "crypted_main" so an aborted multi-disk run or a non-Nomarchy
     install would leave a holder open and silently break the wipe.
   - Drops `|| true` from wipefs / sgdisk / dd. After the LUKS and
     swap teardown above, a real failure means something is still
     holding the device — surface that instead of papering over it.
   - udevadm settle bounded to 30s so a flapping USB can't hang.
   - Post-wipe sanity check: refuse to hand the disk to disko if
     anything is still mounted off it.

4. run_disko_with_retry wraps the disko call. On failure, shows the
   last 30 lines of output via gum style and offers Retry /
   View full log / Abort. set -e is suspended for the disko call so
   the exit code can be inspected. The previous bare `disko --mode
   disko` aborted the whole installer with output scrolled past.

5. Sed-templated disko-golden.nix + disko-btrfs-multi.nix pair
   replaced by a single disko-config.nix Nix function of
   { mainDrive, extraDrives ? [] } called via --argstr / --arg.
   Templating Nix via shell-escaped string substitution caused at
   least one production bug (3aadc36 fixed embedded-newline
   escaping); function arguments are the right shape and eliminate
   the entire class of escaping concerns. Single-disk path is
   `extraDrives = []`; multi-disk gets BTRFS `-d single -m raid1`
   plus the additional /dev/mapper/* devices. Hosts that shipped
   /etc/disko-golden.nix now ship /etc/disko-config.nix.

6. EXIT trap added so the tmpfs LUKS key file (/dev/shm/nomarchy-
   luks.key) is removed even if the script aborts between key-write
   and the explicit unset. Replaced redundant `shred -u` on tmpfs
   with `rm -f` (already in RAM).

Verification: bash -n on install.sh, nix-instantiate parse + strict
eval on disko-config.nix in both single and multi shapes, full
nix flake check --no-build evaluating all three NixOS configurations
(default, nomarchy-installer, nomarchy-live) plus the installerVm.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:42:00 +01:00
Bernardo Magri
386da51178 fix(waybar): SIGUSR2 reload to avoid surface-recreate ghost on theme switch
Theme-switching ran systemctl --user restart waybar.service, which tears
down waybar's wayland layer-shell surface and creates a new one
back-to-back. Hyprland needs a frame to clear the destroyed surface; the
new instance attaches its surface immediately, so for a frame or two the
old waybar pixels remain visible behind/under the new bar - the
"artifacts and old colors on top of new" symptom most visible on the
fresh compositor of the live ISO.

Switch to SIGUSR2 reload, which makes waybar re-read config.jsonc and
CSS (including @import-ed files like ~/.config/nomarchy/current/theme/
waybar.css that theme-switch rewrites) without destroying the surface.
Full systemctl start is kept for the cold-start case.

Drive-by: replace the `systemctl list-unit-files` presence check with
`systemctl cat` - list-unit-files returns 0 even on no-match, so the
old check would always pick the systemctl branch and never fall through
to the pkill fallback on systems where waybar isn't a systemd unit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:24:25 +01:00
Bernardo Magri
d06ef86bb9 feat(gaming): add nomarchy.gaming.enable home-side window rule
Mirror of nomarchy.system.gaming.enable. When on, injects a Hyprland
windowrulev2 = fullscreen, class:^(steam_app_).*$ so games launched
through Steam grab the whole screen instead of opening windowed.

Gated via lib.mkIf so the rule is absent when the option is off
(AGENT.md guardrail: features must be option-gated). The rule is
appended to wayland.windowManager.hyprland.extraConfig (types.lines)
so it composes cleanly with the existing source-line entry point in
features/desktop/hyprland/default.nix.

Closes the "Gaming - Hyprland window rule" Next-column roadmap row.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:14:21 +01:00
Bernardo Magri
3aadc36bff fix(installer): implement robust step-based navigation and fix multi-line sed error
- Implement a step-based state machine in main loop to support 'Back' navigation via Esc.
- Refactor all prompts to use safe exit-code capture (rc -eq 130/1) and handle 'not submitted' output.
- Add input flushing after Esc events to prevent cascading backtrack signals.
- Add short-circuit checks to every wizard stage for reliable skip-forward behavior.
- Fix sed error when generating multi-disk configurations by escaping newlines in additional_disks.
- Add explicit 'Set a hostname' message to the hostname prompt.
- Convert unsafe short-circuit lists to safe if statements to prevent set -e crashes.
2026-04-26 22:17:00 +01:00
Bernardo Magri
55f0653e59 feat(desktop): default to highest monitor resolution
- Change default monitor rule from 'preferred' to 'highres' in monitors.conf.
- Explicitly force 'highres' in the live ISO (nomarchy-live) to avoid low-res fallbacks on some hardware.
- Update roadmap.
2026-04-26 20:03:46 +01:00
Bernardo Magri
dd48411013 feat(scripts): extend nomarchy-welcome into a guided wizard
- Added nomarchy.panelPosition option and state persistence.
- Updated Waybar to respect the panelPosition setting.
- Refactored nomarchy-welcome to use state.json instead of a flag file.
- Added prompts for theme, font, panel position, and starter home.nix generation.
- Updated documentation and roadmap.
2026-04-26 20:02:52 +01:00
Bernardo Magri
c66f0b19cd feat(installer): add multi-disk BTRFS support
- Allow selecting multiple drives in the TTY installer using gum choose --no-limit.
- Add installer/disko-btrfs-multi.nix template for BTRFS RAID/Single setups.
- Dynamically generate multi-disk disko configurations with LUKS-on-every-disk.
- Default to BTRFS 'single' data and 'raid1' metadata for maximum capacity across mismatched drives (e.g., 20GB + 120GB SSDs).
- Update roadmap and structure documentation to reflect the new capabilities.
2026-04-26 19:44:34 +01:00
Bernardo Magri
6de8ecd093 feat(distro): rename ISO targets and fix UEFI boot in live test script
- Rename installerIso and installerIsoGraphical to nomarchy-installer and nomarchy-live.
- Update host configurations with proper Nomarchy branding and volume IDs.
- Fix nomarchy-test-live-iso QEMU launch by using -drive if=pflash for UEFI firmware.
- Add nomarchy-build-live-iso utility script.
- Scrub remaining Omarchy references in Plymouth, installer messages, and docs.
- Regenerate docs/SCRIPTS.md to reflect new and renamed utilities.
2026-04-26 15:29:04 +01:00
Bernardo Magri
21230a05eb feat(installer): review-then-edit loop with field-level re-prompt
Previously the review screen only offered Confirm/Abort, so a typo or
wrong-disk choice meant aborting the whole run and starting over (or
hand-editing /tmp/nomarchy-install.state.sh). On --resume the situation
was worse: every prompt re-runs (each short-circuits when its var is
set), the user lands on a review they can't change.

review_configuration() now offers Continue / Edit a field / Abort. Edit
opens a multi-select of every saved field; chosen fields clear and the
next loop iteration in main() re-prompts only those. The LUKS passphrase
short-circuits when already set, so editing other fields doesn't
re-prompt for it.

Net flow change:
- Fresh install: same prompts, then review with Edit option (typo fixes
  without restarting).
- --resume: state loads, every prompt skips (vars set), lands straight on
  review — exactly what the roadmap entry called for.

Verified via `bash -n`. Live VM dry-run not exercised in this session.
2026-04-26 09:21:40 +01:00
Bernardo Magri
4b2f16c2f0 docs: add TROUBLESHOOTING.md for the five common rebuild errors
Covers: option-already-declared (duplicate mkOption), attribute-missing
(forgot to import nomarchy.nixosModules.system), Stylix target conflict
(needs lib.mkForce, not bare bool), home-manager .hm-bak churn (left over
from backupFileExtension after first install), and impermanence path
missing (dir not in environment.persistence list).

Each entry has the literal error text, the cause, and a copy-paste fix.
Linked from README.md and docs/MIGRATION.md so users hit it before
guessing.
2026-04-26 09:16:40 +01:00
Bernardo Magri
21ee9c6035 feat(system): add gaming preset module
Opt-in `nomarchy.system.gaming.enable` (default false). Wires
`programs.steam` (with `remotePlay` and `localNetworkGameTransfers`
firewall holes opened via `mkDefault`), `programs.gamemode` (the
launching user must be in the `gamemode` group), and
`services.flatpak`.

Two pieces of the original roadmap entry split into separate
Next-column rows so the system-side preset ships now:

  1. Hyprland fullscreen-on-Steam-launch window rule (home-side).
  2. Declarative flathub remote (nixpkgs has no API for this; needs
     either an overlay or a one-shot systemd unit).

The flatpak service is enabled but the user must add flathub
manually after first boot — documented in OPTIONS.md.
2026-04-26 09:10:52 +01:00
Bernardo Magri
8266dc7ee2 feat(system): add accessibility preset module
Opt-in `nomarchy.system.accessibility.enable` (default false —
accessibility is a personal preference, not hardware-derived). Wires
`services.gnome.at-spi2-core`, installs `pkgs.orca`, and sets
`XCURSOR_SIZE` to a configurable `accessibility.cursorSize` (default
32, up from NixOS's 24).

The original roadmap entry bundled Hyprland-side bits (slower
key-repeat, Orca launch keybinding, high-contrast palette). Those
require touching home-manager / theme files and a new palette
directory; split into a separate Next-column row so the system-side
preset ships now and the desktop integration follows independently.
2026-04-26 09:06:02 +01:00
Bernardo Magri
16ed8f1df1 docs(agent): require docs to ship with the change that triggers them
Adds an 8th guardrail and replaces §5.4 with an explicit "if you change
X, update Y" mapping covering options, scripts, keybindings, structure,
installer, themes, roadmap, conventions, and flake-level changes.

Each row names the doc to touch. The closing line forces a one-pass
check before declaring a change done — eliminates "docs catch-up" PRs
and keeps the distro and its docs from drifting apart.
2026-04-26 08:53:58 +01:00
Bernardo Magri
e9c9342965 feat(system): add desktop preset module
Mirror of the laptop preset for the desktop form factor. New
`nomarchy.system.desktop.enable` defaults to `formFactor == "desktop"`,
so the installer's existing formFactor write auto-flips it on without
installer changes (same pattern as laptop).

The module pins `powerManagement.cpuFreqGovernor` to `"performance"`
(via mkDefault) and enables `services.zfs.{autoScrub,trim}` so a
future ZFS pool gets sensible maintenance for free. The ZFS knobs are
no-ops until the user adds zfs to `boot.supportedFilesystems`.

Battery widget filtering is already driven by `formFactor` itself in
`features/desktop/waybar/default.nix`, so the preset doesn't repeat
it. Closes the "Desktop preset module" Next item.
2026-04-26 08:51:28 +01:00
Bernardo Magri
5b014cfa29 chore(audit): refine docs-scripts detector and lock in via pre-commit
Two detector bugs fixed:

1. grep_includes missed *.lua, *.ini, *.desktop, *.json — so callers in
   elephant providers (lua), mako on-button-* hooks (ini), and any future
   MimeType-registered URL handlers (.desktop) were invisible. Adding them
   reclassifies nomarchy-notification-dismiss and nomarchy-theme-bg-set
   from `unused?` to `kept` (true callers in mako/core.ini and the
   elephant background_selector lua).

2. The all_refs regex `nomarchy-[a-z0-9][a-z0-9-]+` greedily captured
   trailing dashes, producing junk missing-tokens like `nomarchy-pkg-`,
   `nomarchy-cmd-`, `nomarchy-restart-`, etc. from glob references like
   `for c in nomarchy-pkg-*`. Tightened to require an alphanumeric end
   character. Also restricted to grep_includes so the binary tmpfile
   path `nomarchy-menu-rows` no longer leaks in.

New .githooks/pre-commit re-runs the generator and stages docs/SCRIPTS.md
whenever a nomarchy-* script changes. Enable per clone with
`git config core.hooksPath .githooks` (now mentioned in docs/AGENT.md).

Net audit shift after regen: unused? scripts 31→29, missing tokens 30→28,
no false-positive prefix tokens remain.
2026-04-26 08:44:13 +01:00
Bernardo Magri
034da701a3 feat(system): add laptop power preset module
New `nomarchy.system.laptop.{enable,thermald}` options. `enable`
defaults to `formFactor == "laptop"`, so the installer's existing
formFactor write auto-flips the preset on without installer changes.

The module wires TLP (governors + 75/80 charge thresholds),
force-disables power-profiles-daemon (mutually exclusive with TLP),
enables upower and thermald (x86_64), adds the brightnessctl udev
rule so the existing brightness scripts work without root, and sets
a logind lid-switch policy that resolves to suspend-then-hibernate
when `hibernation.enable` is on, plain suspend otherwise.

Closes the "Form-factor → laptop preset auto-enable" Now item and
the "Laptop preset module" Next item from docs/ROADMAP.md in one
change.
2026-04-26 08:31:19 +01:00
Bernardo Magri
7086a6f29c feat(installer): add software-profile multi-select
- Add select_profiles step with gum choose --no-limit
- Implement state persistence and review for selected profiles
- Map profiles to home.packages and system-level toggles (Docker, Steam)
- Update generate_flake_config to emit profile-specific Nix snippets
- Fix duplicate environment.systemPackages in virtualization.nix
- Update ROADMAP.md
2026-04-25 22:44:24 +01:00
Bernardo Magri
1545e63c7d docs: update roadmap and scripts audit status after phase B 2026-04-25 22:40:33 +01:00
Bernardo Magri
f965f0be2c feat(audit): address batch 4 and finalize script audit
- Implement nomarchy-skill, nomarchy-manual, nomarchy-backup, nomarchy-install
- Implement nomarchy-install-docker-dbs (stub)
- Port nomarchy-docs-keybindings and nomarchy-docs-scripts to packaged scripts
- Add installerVm to flake.nix nixosConfigurations, packages, and apps
- Update nomarchy-test-installer to use nix run .#installerVm
- Add docker support to virtualization.nix and options.nix
- Add glow to script dependencies
- Finalize docs/SCRIPTS.md update
2026-04-25 22:39:11 +01:00
Bernardo Magri
fb22e390e8 feat(audit): address batch 3 of missing scripts
- Implement nomarchy-pkg-install, nomarchy-pkg-drop, nomarchy-pkg-aur-add (stub)
- Implement nomarchy-theme, nomarchy-font, nomarchy-wallpaper wrappers
- Update docs/SCRIPTS.md with 'kept' status for new scripts
2026-04-25 22:37:06 +01:00
Bernardo Magri
074dc3576c feat(audit): address batch 2 of missing scripts
- Implement nomarchy-version, nomarchy-debug, nomarchy-reinstall, nomarchy-rollback, nomarchy-upload-log
- Implement nomarchy-refresh-hyprland and nomarchy-refresh-waybar
- Update docs/SCRIPTS.md with 'kept' status for new scripts
2026-04-25 22:36:19 +01:00
Bernardo Magri
0728da4374 feat(audit): address batch 1 of missing scripts and enable fwupd
- Move 18 Hyprland/desktop scripts from features/desktop/scripts/ to packaged directories
- Add nomarchy.hardware.fwupd option (default false) and enable service
- Implement nomarchy-update-firmware wrapper for fwupdmgr
- Add hyprland, swayosd, and fwupd to nomarchy-system-scripts dependencies
- Update docs/SCRIPTS.md with 'kept' status for ported scripts
2026-04-25 22:34:04 +01:00
Bernardo Magri
983ade0f55 fix(theme): wire obsidian sync into theme-set; drop vscode placeholder
Phase B verdict on two unused? entries in the theme-engine scripts.

- nomarchy-theme-set-obsidian: real script that copies the active
  theme's obsidian.css into every Obsidian vault under
  ~/.config/obsidian/obsidian.json. Wires it into nomarchy-theme-set
  next to the btop/opencode hot-reloads. Self-gates twice (no
  obsidian.css → exit 0; no .obsidian dir → continue), so it's a
  no-op for users without Obsidian.

- nomarchy-theme-set-vscode: delete-dead. Its own comment admitted
  it was "mostly a placeholder"; its only action (nomarchy-env-update)
  is already done unconditionally upstream by nomarchy-theme-set.
  The NOMARCHY_TOGGLE_SKIP_VSCODE_THEME env var it gated on is
  exported by features/scripts/default.nix:73 from
  nomarchy.toggles.skipVsCodeTheme, but with this script gone there
  are no consumers; the toggle survives as a public option until a
  follow-up wires it through the VSCode module properly.

SCRIPTS.md regenerated: unused? 34 → 32, kept 165 → 166. nix flake
check clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 22:18:03 +01:00
Bernardo Magri
d2b508485a fix(theme): hot-reload btop and opencode on theme switch
Phase B verdict on two unused? scripts — both inline comments
claimed they were "used by the Nomarchy theme switching", but the
switcher (themes/engine/scripts/nomarchy-theme-set) only restarted
walker, waybar, and the wallpaper service. So btop and opencode
stayed on the old palette after `nomarchy-theme-set <foo>` until
the user closed and reopened them by hand.

Wires both into nomarchy-theme-set, alongside the existing walker /
waybar restart calls. The check-then-call (`command -v ... &&`)
matches the surrounding style — a missing helper is a no-op, not a
fatal.

SCRIPTS.md regenerated: unused? 36 → 34, kept 163 → 165.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 22:13:52 +01:00
Bernardo Magri
cc93491232 chore(audit): delete-dead — unused nomarchy-hw-* detection scripts
Phase B verdict on four core/system/scripts/nomarchy-hw-* entries
flagged `unused?` in the Phase A inventory. Wide grep confirmed
the only references were the audit doc itself.

Removed:
  - nomarchy-hw-framework16 (superseded by `nomarchy-hw-match "Laptop 16"`
    in nomarchy-on-boot)
  - nomarchy-hw-surface     (no caller; "Surface" string would route
    through nomarchy-hw-match if needed)
  - nomarchy-hw-intel       (no caller; vendor detection isn't a public
    API — installer/hardware-db.sh handles install-time dispatch and
    nomarchy.hardware.* options handle build-time)
  - nomarchy-hw-intel-ptl   (same — Panther Lake GPU detection isn't
    used anywhere)

Kept: nomarchy-hw-match (the dispatcher), nomarchy-hw-asus-rog
(called by nomarchy-on-boot), nomarchy-hw-vulkan (called by
nomarchy-voxtype-install).

SCRIPTS.md regenerated: unused? 40 → 36; nix flake check clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 22:11:47 +01:00
Bernardo Magri
aa20399210 docs(audit): generator discovers references in *.md, README, and txt
Scope: small Phase B improvement to the discovery heuristic so the
audit table stops false-flagging documented user-CLI tools as unused.

The generator now grep -r searches *.md, *.txt, *.sample alongside
*.nix / *.conf / *.sh, and explicitly walks README.md. SCRIPTS.md,
ROADMAP.md, and AGENT.md are excluded from the search (they document
the scripts but aren't callers — including them would promote every
script to `kept`).

Status histogram: 158 → 163 kept, 45 → 40 unused?, 75 → 85 missing
(the missing bump comes from grepping aspirational scripts named in
ROADMAP — wait, that doc is excluded — so the new missing rows are
references in MIGRATION/STRUCTURE/creating-themes that name scripts
which don't exist).

Per-script triage of the remaining 40 unused? rows is the next Phase
B batch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 22:02:45 +01:00
Bernardo Magri
86bc0e570b docs: Pillar 3 Phase A — script & menu audit inventory
bin/utils/nomarchy-docs-scripts walks features/scripts/utils,
core/system/scripts, and themes/engine/scripts; emits a populated
SCRIPTS.md with three tables:

- Scripts (136): location, top callers, status (kept / unused?).
- Missing references: tokens grepped from code with no script file
  (75 rows tagged missing).
- Menu items: every case arm in nomarchy-menu's show_*_menu
  functions, mapped to its target command and tagged.

Status histogram: 158 kept, 75 missing, 45 unused?. Phase B opens
per-batch PRs that refine missing → port-from-omarchy /
delete-dead / stub-with-notify, and unused? → kept / delete-dead.

Roadmap and AGENT.md updated to point at the generator and
explain the Phase B workflow. Now-column row replaced with the
Phase B handoff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 21:59:06 +01:00
Bernardo Magri
bf30cd07d8 feat(installer): richer disk picker (vendor, model, serial, type)
Replaces the bare `NAME SIZE` lsblk listing in select_disk with a
six-column table — NAME, SIZE, TYPE, VENDOR, MODEL, SERIAL — aligned
via column -t. TYPE is derived from ROTA + TRAN (NVMe / USB / SSD /
HDD). Empty vendor/model/serial fields render as `--` instead of
collapsing the alignment. Filters loop, ram, zram, sr devices.

Roadmap row moves to Shipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 21:49:36 +01:00
Bernardo Magri
c9ff6f26f3 docs: add KEYBINDINGS.md generated from Hyprland bindings
bin/utils/nomarchy-docs-keybindings parses every bindd= / bindeld=
line in the core + feature binding files into a six-section Markdown
table (Utilities, Tiling, Tiling v2, Clipboard, Media keys, Apps).
233 bindings rendered. code:NN keycodes and XF86* media keys are
prettified.

README's keybinding table is slimmed to five highlights and now
links the generated doc; the roadmap's Now-column row moves to
Shipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 21:47:15 +01:00