From 03968e5d0df15816638a4666066219eb07715390 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Mon, 18 May 2026 18:18:25 +0100 Subject: [PATCH] fix(installer): generate state.json from lib/state-schema.nix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the last source-of-truth split after the state-defaults centralization batches. The installer's heredoc was the only remaining place that hardcoded the state.json literal — adding a default to the schema previously required a parallel edit here, and silent drift was exactly the bug class we kept fixing. Before: cat > /mnt/etc/nixos/state.json < /mnt/etc/nixos/state.json Uses the flake's own pinned `inputs.nixpkgs` (matching what the rest of Nomarchy resolves against), so the schema evaluates with the same `lib` the consumer modules see. `nrun jq` pretty-prints for human inspection. Behavioural notes: - Output is identical to the old heredoc modulo alphabetical key ordering — `builtins.toJSON` sorts keys, the heredoc was in declaration order. Toggle scripts read/write via `jq` so it's invisible to them. - Dry-run path unchanged. `execute_dry_run` already bind-mounts a fake /mnt for the generator; the generator's absolute paths still resolve. - New schema fields show up automatically on the next install; no parallel edit needed. - `bash -n` + `shellcheck --severity=error` clean. Co-Authored-By: Claude Opus 4.7 --- docs/ROADMAP.md | 1 + installer/install.sh | 43 +++++++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 5cb797d..0a25edc 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -121,6 +121,7 @@ Each PR description should reference the row(s) in `docs/SCRIPTS.md` it closes, (Move items here when they land — keep them brief, link the commit/PR.) +- _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..` 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). diff --git a/installer/install.sh b/installer/install.sh index b5ced6c..fd00da5 100755 --- a/installer/install.sh +++ b/installer/install.sh @@ -1799,30 +1799,29 @@ EOF } EOF - # state.json — consumed by core/system/state.nix at every nixos-rebuild and - # mutated by toggle scripts (nomarchy-tz-select, nomarchy-setup-fido2, + # state.json — consumed by core/system/state.nix at every nixos-rebuild + # and mutated by toggle scripts (nomarchy-tz-select, nomarchy-setup-fido2, # nomarchy-toggle-hybrid-gpu, nomarchy-wifi-powersave, ...). Those scripts - # `jq` the file in place and fail hard if it doesn't exist or isn't valid - # JSON, so a fresh install MUST ship one. Shape must match lib/state-schema.nix. - # Quoted heredoc — no shell expansion except the explicit $TIMEZONE below. + # `jq` the file in place and fail hard if it doesn't exist or isn't + # valid JSON, so a fresh install MUST ship one. + # + # Source of truth: lib/state-schema.nix. We eval its `system` block and + # overlay the installer-chosen timezone, so this generator no longer + # drifts from the schema or the *.nix consumers — the previous heredoc + # was the last source-of-truth split after the state centralization. + # Adding a new default in the schema now reaches the installer without + # any further plumbing. local _state_tz="${TIMEZONE:-UTC}" - cat > /mnt/etc/nixos/state.json < /mnt/etc/nixos/state.json } # ============================================================================