From 381eb72721c6736cc27b5009d6a6d0dae2aa1061 Mon Sep 17 00:00:00 2001 From: elwrcl Date: Sat, 3 Oct 2026 03:35:32 +0300 Subject: [PATCH] docs: home-manager module design spec --- .../2026-10-03-valw-home-manager-design.md | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-03-valw-home-manager-design.md diff --git a/docs/superpowers/specs/2026-10-03-valw-home-manager-design.md b/docs/superpowers/specs/2026-10-03-valw-home-manager-design.md new file mode 100644 index 0000000..0becbde --- /dev/null +++ b/docs/superpowers/specs/2026-10-03-valw-home-manager-design.md @@ -0,0 +1,81 @@ +# valw home-manager module (design) + +Date: 2026-10-03 +Status: approved in brainstorming, pending written-spec review +Builds on: every phase on `main`; the config format in `src/config.rs` + +## 1. Goal + +Manage valw from home-manager: install it and write its config from Nix, +with mistakes in the settings caught when the configuration is built, not +when valw runs. + +### Out of scope + +- A NixOS module (valw is per user; `packages.default` installs it). +- niri key bindings (they stay in the user's niri config, i.e. copland). +- The toolbar's remembered choices (`~/.local/state/valw/toolbar.toml`), + which stay writable state. + +## 2. Usage + +```nix +programs.valw = { + enable = true; + settings = { + preview.timeout_secs = 3; + sound.volume = 0.4; + capture.window_shadow = true; + }; +}; +``` + +## 3. Options + +| Option | Type | Default | Meaning | +|---|---|---|---| +| `programs.valw.enable` | bool | `false` | Install valw (`home.packages`) | +| `programs.valw.package` | package | this flake's `packages.${system}.default` | The valw to install and to check the settings with | +| `programs.valw.settings` | `(pkgs.formats.toml { }).type` | `{ }` | Written to `$XDG_CONFIG_HOME/valw/config.toml`; nothing is written when empty, so valw uses its defaults | + +## 4. Checking at build time + +- `settings` becomes a TOML file with `pkgs.formats.toml`. +- The file installed as `xdg.configFile."valw/config.toml".source` is a + derivation that runs `${package}/bin/valw __check-config ` and + copies the file to `$out` only if the check passes. +- `valw __check-config ` (hidden): parses the file exactly as valw + does at run time. An invalid value prints valw's own error (for example + `sound.volume must be between 0 and 1`) and exits non-zero. An unknown + key, which valw only warns about at run time, is an error here, listing + every unknown key (`unknown config key: preview.timout_secs`). A valid + file prints nothing and exits 0. It needs no Wayland, niri or home + directory. + +## 5. Structure + +| File | Change | +|---|---| +| `src/main.rs` | hidden `Command::CheckConfig { file }` | +| `src/config.rs` | `check(path) -> Result<()>`: parse + unknown keys as an error | +| `nix/home-module.ulu.nix` (new) | `flake.homeModules.default` | +| `nix/checks.ulu.nix` | `home-module` (evaluates the module with stub `home.packages` / `xdg.configFile` options and builds the checked config) and `home-module-rejects` (a bad setting fails to build, via `pkgs.testers.testBuildFailure`) | +| `README.md` (new) | what valw is, install (flake package or the module), the module example, niri bind examples, the commands | + +No new flake input: the checks evaluate the module with `lib.evalModules` +and stubs instead of pulling in home-manager. + +## 6. Testing + +- Rust (`cargo nextest`): `check` accepts a valid file and the defaults, + rejects an invalid value with valw's message, rejects unknown keys and + names them; the CLI parses `__check-config FILE` and hides it from help. +- Nix (`nix flake check`): the two module checks above. + +Manual: wiring it into copland happens in the end-of-project test pass +(checklist section). + +## 7. Definition of done + +`cargo clippy -- -D warnings`, `cargo fmt --check`, `cargo nextest run` +and `nix flake check` pass; README written; checklist section added.