# Backlog — the prioritized task queue **This is the only executable work list for agents.** Product themes and v1.0 intent live in [`docs/VISION.md`](../docs/VISION.md); design history in [`docs/ROADMAP.md`](../docs/ROADMAP.md); map in [`docs/README.md`](../docs/README.md) and [`agent/README.md`](README.md). **Rules:** - Agents take the topmost actionable item (see LOOP.md). Finished items are **deleted** here — the journal + git log are the record; durable design notes get a ✓-entry in docs/ROADMAP.md (and/or a note in VISION) if worth keeping. - Item numbers are **stable IDs** — never renumbered or reused. A gap in the sequence means shipped (or dropped) work; new items take the next free number regardless of tier. - Tags: `[blocked:hw]` needs real hardware (see HARDWARE-QUEUE.md) · `[human]` needs Bernardo · `[stuck]` two failed attempts, needs help · `[big]` must be split before starting. - Agents may append to **PROPOSED** and **Decisions** freely (include `VISION § …` or `ROADMAP § …` when relevant); only Bernardo moves items *out* of PROPOSED into the tiers. --- ## NOW *(empty — NEXT's top item is the queue head)* ## NEXT ### 14. Automated lock bumps — confirm the first real run Slices b+c shipped 2026-07-05 (`.gitea/workflows/bump.yml`): weekly schedule (Mon 05:17 UTC) + `workflow_dispatch` as the security fast-lane; `nix flake update` → eval gate → pathspec-limited lock commit pushed to `main` on green (that push triggers check.yml as the second net). Update/commit/push logic simulated locally end-to-end in a scratch clone, incl. a real update; today's bumped lock evals green. Remaining (not confirmable from a session): the first scheduled or dispatched run must land — watch that the runner picks up the cron and that the Actions token can push. Then delete this item. Item 20's KVM runner later upgrades the gate from eval-only to the VM suite. ### 20. KVM runner → VM suite in CI `[human]` The remaining stretch of the CI item — checks-on-push is live and **green** (run #58; runner = gitea/act_runner docker, eval tier). Register a second runner on a host with `/dev/kvm` + nix (host-mode label `nix-kvm`), then an agent uncomments the workflow's `vm-checks` job: the `checks.*` VM suite + real toplevel/HM builds on every push that later upgrades item 14's bump gate from eval-only to the full suite. ### 41. Floating-window audit — remaining (needs hardware class checks) (Raised by Bernardo, 2026-07-07 — item 11.) Broaden the `windowrule` float set beyond the conservative first cut. _Conservative cut shipped 2026-07-07 (iteration #63, on Bernardo's "take a conservative approach"):_ float + center the mixer (item 35), **blueman** (manager/adapters) and **system-config-printer** — the only shipped, unambiguous config dialogs whose classes are confident. **Remaining candidates, deliberately deferred because their window class can't be verified headlessly** (a guessed class = dead rule): the polkit auth prompt (hyprpolkitagent — no discoverable class in the package), GTK file-chooser portals (`xdg-desktop-portal-gtk`), and any pinentry dialog. Next slice: on hardware, run `hyprctl clients` while each is open, read the real `class`, then append rules. Also revisit whether blueman/s-c-p actually float once seen (regex tolerance for the `.…-wrapped` form). ### 55. Fingerprint menu: enroll / list (+ optional PAM toggle) VISION § A / HARDWARE.md §5. Installer enables fprintd on known USB VIDs but enroll is CLI-only (`fprintd-enroll`) and PAM is a commented rebuild. Self-gated System row when `fprintd` is present: enroll, list, delete; optional “use for login” that writes `settings`/system intent + rebuild note (Control Center Bluetooth pattern). Full enroll path is `[blocked:hw]` / V3; menu surface + self-gate + dry paths are V1–V2. ### 56. Human rebuild errors VISION § A. On failed `sys-rebuild` / HM switch, point the user at the last log lines + `nomarchy-doctor` instead of a raw Nix wall. Likely home: menu rebuild wrapper and/or control-center path. Cost: medium pkgs/menu; V1 + V2 smoke of the failure path (can force a bad eval). ### 57. Live: one always-visible “Install Nomarchy” action Install is only in: 3s notify-send toast, getty helpLine, and tribal knowledge of `nomarchy-install`. **One** durable surface on the live host only: e.g. `xdg.desktopEntries` (Terminal=true) **or** a single Tools/System menu item that opens a terminal into `nomarchy-install`. Prefer that over more install-time questions. Also fix stale `hosts/live.nix` header (“No installer yet”) if still present. Cost: `live.nix` only; V1 ISO rebuild + V2 smoke. ### 58. `nomarchy-detect-hw` CLI (post-install re-probe) HARDWARE.md §8. Installer already has pure `nomarchy_detect_hw` stdout protocol (MODULE / NOMARCHY / DETAIL). Ship it as a package on PATH that prints suggested `hardwareProfile = [ … ]` and `system.nix` snippets without reinstalling — closes the template/migration gap and “I swapped the Wi‑Fi card.” Does **not** rewrite the flake unless a later `--apply` is explicitly designed. Cost: extract script + package + man/README pointer; V0–V1. ### 63. Generated Waybar: identity-bar affordances (powermenu + logo) Whole-swap bars ship `custom/powermenu` and a left logo → main menu; the generated `waybar.nix` bar has neither. Optional parity add for default-theme users. Cost: small waybar.nix + CSS; **parity rule:** whole-swaps must get the same modules if added. V1 + visual V2. ## LATER - **Wallpapers artifact split** (ROADMAP § Faster switches — decided, deferred): pinned `Nomarchy-wallpapers` input so a state write stops re-copying 86 MB. Follow-on: pre-built theme variants if switches are still slow after. - **Installer round 2** (ROADMAP § Installer): multi-disk BTRFS RAID, impermanence, BIOS/legacy boot. - **Boot-from-snapshot**: a systemd-boot equivalent of grub-btrfs. - **Night-light geo mode**: lat/long auto sunset/sunrise (means wlsunset). - **Per-theme icon overrides** / more icon packs (ROADMAP § Icon themes). - **MIPI/IPU software-ISP camera** support (no-UVC machines). - **VPN exit-node richer display** (country/city) (optional). - **NixOS release bump → v2** `[human]`: deliberate, hand-edited, never automated; the previous attempt was discarded (2026-06-22) over a Hyprland OOM blocker — see MEMORY.md before retrying (NOW#3 should also soften that blocker class). ## PROPOSED (agent suggestions — await human triage) *Agents: append here with a one-paragraph pitch (what/why/cost). Do not implement. Bernardo moves accepted items into a tier.* ### v1.0 track — see `docs/VISION.md` Product themes and the release bar live in **VISION**. Shipped 2026-07-09: #42 boreal default · #43 Firmware menu · #44 doctor hardware · neon-glass quarantine (#53). **Promoted 2026-07-10 → NEXT #55–#63** (A fingerprint / human rebuild / live install · B detect-hw / NVIDIA comments / BAT* · C review source line / whole-swap CSS CI / generated bar affordances). Still PROPOSED for later triage: first-boot tips (partially shipped via #43 MOTD), charge-limit instant apply, theme taste polish. ### Pre-existing - **Battery charge-limit — make the toggle instant** `[blocked:hw]` (follow-up to the preset toggle shipped 2026-07-07, iteration #55). The control-center now has a proper toggle (Off / 80% / 90% / 60% / Custom…) writing `settings.power.batteryChargeLimit` — but that's a baked NixOS option, so it only lands on the next `sys-rebuild`. To make it instant (no rebuild): add a udev rule making system-battery `charge_control_end_threshold` nodes group-writable (`MODE`/`GROUP`) so the menu can `echo N >` it live alongside persisting state (the sysfs oneshot in power.nix still owns boot + AC-replug re-apply), and/or surface a rofi-menu quick row or a Waybar action. `[blocked:hw]`: the sysfs write + no-rebuild effect can only be confirmed on a laptop exposing the threshold. Decide first whether the small privilege grant (a local user can set the charge cap) is acceptable. - **Portal/Flatpak camera picker still lists the internal IR sensor** (ROADMAP § Webcam follow-up). The shipped IR-hide is a *WirePlumber v4l2* rule, but Flatpak/portal apps consume cameras via the **libcamera** path, where both sensors remain visible — a Flatpak Zoom user can still pick the black IR "camera". Options, roughly ascending cost: (a) do nothing — document it (portal camera support is still rare in practice); (b) a WirePlumber *libcamera* monitor rule disabling GREY-only nodes — needs verifying that libcamera monitor rules can match early enough (the v4l2 investigation found only `device.api` binds pre-rule, which is why surgical scoping failed before — same wall likely applies); (c) a libcamera configuration/udev quirk hiding the IR sensor at the libcamera layer itself. Cost: (b)/(c) need a T14s-style RGB+IR machine to verify → pairs with a hardware-queue session. Recommend (a) now, (b) investigated when the T14s is next available. ### Bugs / broken behavior (codebase exam 2026-07-09) _(Waybar doctor indicator, Control Center appearance no-ops, summer-day scroll → #51; neon-glass broken waybar → **fixed** 2026-07-09 by quarantine (removed `waybar.css` → generated bar; render-confirmed).)_ _(Battery charge-limit / powerprofile BAT*-only → **#60** ✓ 2026-07-10; V3 pending on non-BAT* hardware.)_ ### Docs / option-surface drift (codebase exam 2026-07-09) _(i2c option-docs → #48; README/docs drift pack, keybind nmtui label, nomarchy-menu usage string, secondary docs, always-on pieces → #47.)_ - **Template / seed state drift (residual after SoT work)** (1) `templates/downstream/theme-state.json` lacks `border` and `settings` keys present in repo root state (eval merges defaults); (2) no commented `nomarchy.system.snapper.enable` or `hardware.i2c.*` in template `system.nix` despite opt-in convention. Main home/system sync is **Installer consumes template as SoT** below — do that first, then close these residual gaps on the template itself. Cost: small template polish. - **Installer ↔ template SoT — follow-ups** (shipped 2026-07-09: copy + `patch-template.py`). Remaining: (1) optional CI that the install share ships the same template files; (2) V2 `test-install.sh` after ISO rebuild (HM pre-activate now pulls starter packages — larger closure); (3) residual theme-state / i2c comment polish on template (see residual seed drift item). ### Theme polish / completeness (codebase exam 2026-07-09) - **theme preview recapture nicety** (all 24 themes now have `preview.png` as of 2026-07-09 — executive-slate + neon-glass captured via theme-shot). These headless captures are a clean bare desktop+bar, not the theme-shot capture — a clean bare desktop+bar, not the floating-terminal (fastfetch+btop) composition the other 21 use; a real-hardware recapture to match the grid would be nicer (VM is the documented fallback). Optional hand `btop.theme` for the three identity themes still open. Cost: asset capture; V3 visual. _(Generated Waybar missing identity-bar affordances → **#63**.)_ - **summer-* CSS under-styles status module states** summer-day/night include modules in selectors but largely lack `.on` / `.available` / `.recording` polish that boreal, executive-slate, and the generated style have. Functional OK; visual hierarchy weak. Cost: CSS pass; V3. _(Optional CI: whole-swap CSS self-containment → **#62** ✓ 2026-07-10.)_ ### Per-theme design audit (2026-07-09) *Method: `checks.theme-contrast` (all 24×7 pairings pass) + `tools/audit-theme-design.py` + per-theme agent review of JSON roles, ANSI, assets, whole-swaps, and fidelity to canonical sources. Gated WCAG floors are green; items below are fidelity, hierarchy, btop drift, identity semantics, and polish. Identity themes (white, vantablack, lumon, hackerman, matte-black, miasma, neon-glass) are flagged separately from fidelity bugs.* #### Broken / high-ROI fixes _→ promoted as NEXT **#52** (2026-07-09); the six bullets below are its spec (exact hexes). The rest of the per-theme audit stays PROPOSED._ _Residual ANSI drift exposed by the #52 fixes (not yet touched — small follow-up): **vantablack** `ansi[8]` (bright-black) still `#fdfdfd`, now diverging from the new `muted #666666`; **osaka-jade** `ansi[3]` (normal-yellow) still the old warn-green `#459451` while `warn`/`ansi[11]` are now `#E5C736`. Decide per theme whether these are identity or bugs._ - **rose-pine btop is Main-on-Dawn (near-invisible hi_fg)** JSON is **Rosé Pine Dawn** (`mode: light`, base `#faf4ed`, text `#575279`) but `themes/rose-pine/btop.theme` mixes Dawn `main_bg`/`main_fg` with **Main** accents: `hi_fg=#e0def4` on `#faf4ed` ≈ invisible, `selected_bg=#524f67`, love `#eb6f92`, foam/iris Main hexes. **Fix:** rewrite btop entirely to Dawn roles (foam `#56949f`, iris `#907aa9`, love `#b4637a`, gold `#ea9d34`/`#d68a16`, pine `#286983`). Also rename display name to "Rosé Pine Dawn" (or ship a dark Main preset as a separate slug). Cost: one btop rewrite + optional rename; V1 + visual V2. - **everforest + summer-night btop: inactive_fg == main_bg** `themes/everforest/btop.theme` and `themes/summer-night/btop.theme` set `inactive_fg` to `#2d353b` (= `main_bg`) → inactive/disabled labels invisible. **Fix:** `inactive_fg` → grey1/muted range (`#859289` / `#7a8478` / JSON muted). Cost: two lines; V1. - **vantablack role inversion breaks selection / muted** `overlay` and `muted` are near-white `#fdfdfd` while base is `#0d0d0d`. Generated consumers use `overlay` as selected_bg; hand btop has `selected_bg=#fdfdfd` + `selected_fg=#ffffff` (white-on-white) and `inactive_fg=#fdfdfd` (inactive rows scream). Status greys are intentional monochrome identity. **Fix (keep void identity):** `surface #1a1a1a`, `overlay #2a2a2a`, `muted #666666`; btop `selected_bg #333` / `selected_fg #fff` / `inactive_fg` ≈ muted. Cost: JSON + btop; re-run contrast; V1–V2. - **osaka-jade: warn≈good and text/subtext inverted** `warn #459451` is green (same family as `good #549e6a`) → battery warning reads as "ok". `subtext #F6F5DD` is brighter than `text #C1C497` (secondary louder than primary). **Fix:** swap text↔subtext; set `warn #E5C736` (from bright yellow ANSI, already in palette). Keep jade accent + blossom accentAlt. Cost: small JSON retune; contrast re-check; V1. - **catppuccin-latte: ANSI black/white axis inverted + mantle sludge** Latte UI roles mostly match (base/text/accent/good/bad exact), but `ansi[0]=#bcc0cc` (light) and `ansi[7]/[15]` are darkish → terminal "black"/"white" slots misbehave; design-audit flags inverted slots. `mantle #cbcdd0` is import-darken of light base (should be Latte mantle `#e6e9ef`); `accentAlt #d260b5` is not Latte pink/mauve. **Fix:** ``` mantle #e6e9ef; accentAlt #ea76cb (pink); ansi[0] #5c5f77; ansi[7] #acb0be; ansi[8] #6c6f85; ansi[15] #bcc0cc ``` warn keep `#d6860a` if contrast requires, else `#df8e1d`. Cost: JSON only; btop already Latte-correct. V0 contrast + V1. - **catppuccin (Mocha) btop is Frappé-on-Mocha** JSON is exact Mocha; `btop.theme` uses Mocha `main_bg` but Frappé fgs/boxes (`main_fg #c6d0f5`, `hi_fg #8caaee`, mauve/green/maroon Frappé hexes). **Fix:** replace with official Mocha btop hexes (`#cdd6f4`, `#89b4fa`, …). Optional: rename to "Catppuccin Mocha". Cost: btop rewrite; V1. #### Whole-swap / identity themes - **neon-glass** — already queued above (broken waybar.css). JSON palette itself is fine (high-chroma cyber). Finish or quarantine. - **summer-day / summer-night pair polish** Structurally paired (inverted Everforest bar language) but: (1) waybar CSS hexes drift from JSON (day warn/accentAlt; night red/blue/yellow/purple vs JSON); bar follows legacy EF source, Stylix/swaync follow JSON — dual sources of truth; (2) night JSON collapses `subtext`=`muted`=`overlay` `#868d80` (no secondary ladder for generated surfaces); (3) day font 16px vs night 13px; day battery thresholds 30/15 vs night 25/10; day missing `#custom-vpn` in pill selectors; (4) day scroll `e±1` already queued. **Fix:** pick JSON as source of truth and map waybar tokens to it (or document intentional EF split); split night muted darker / subtext lighter; align font + battery thresholds + VPN pill. Cost: CSS/JSON polish pass; V3. - **boreal / executive-slate** — whole-swaps self-define colors and match JSON; best-in-class. Only gaps: `preview.png` + optional `btop.theme` (already queued). - **white (monochrome light)** — identity-ok. Status good/warn/bad are greys by design (audit hue/CVD noise expected). Optional: widen L steps (`good #555`, `warn #777`, `bad #222`), raise `surface #f0f0f0`, split `subtext #404040` while staying hueless. Do not inject traffic-light hues. Cost: optional taste retune. - **lumon (Severance blue mono-status)** — identity-ok. good/warn/bad all blue family by design; CVD collapse expected — rely on glyph/shape (item 28). Optional: dim `subtext` one step (`#9bb0c0`); increase L separation only among blues. Cost: optional; document as identity exemption in audit tooling. - **hackerman** — matrix identity: warn cyan, bad green, ANSI reds are greens. CVD collapse expected. **Keep identity** or optional cyber-semantic UI only: `warn #e8d44f`, `bad #ff5a7a` while leaving ANSI matrix. Raise `surface #1a1c2e` (flat base=surface). Cost: product call + small JSON. - **matte-black** — identity: `good=#FFC107` amber, `warn=#b91c1c` red (inverted traffic-light). Matches Omarchy matte-black. Minimal fix: `subtext #9a9a9d` (text==subtext today). Full semantic remap only if product wants conventional battery colors on this theme. Cost: one-line hierarchy or deliberate status retune. - **miasma** — earthy `bad #685742` (brown, contrast ~2.3 audit-only) is JOURNAL-exempt identity. Optional more readable brown-red `#8b5a4a` / `#a65d4e` without leaving the forest. Cost: optional. #### Fidelity / hierarchy polish (popular ports) - **gruvbox is Material medium, not classic — name + btop split** JSON hexes are Gruvbox **Material** (`text #d4be98`, material green/yellow/red) while name says "Gruvbox" and `btop.theme` is **classic** (`#ebdbb2`, `#d79921`, …). `surface`=`overlay`, `text`=`subtext`. **Fix:** rename to "Gruvbox Material" **or** retune JSON to classic; sync btop to the chosen lineage; `overlay #504945`, `subtext #a89984`. Cost: naming + assets. - **nord** — clean Polar Night. Only nit: `subtext #e5e9f0` is **brighter** than `text #d8dee9` (hierarchy inverted). **Fix:** subtext → nord4-dim or bump text to nord6 `#eceff4`. Cost: one hex. - **tokyo-night** — Night (not Storm), JSON solid. btop `main_fg`/`title` use warm `#cfc9c2` instead of Night `#c0caf5`/`#a9b1d6`. Optional: `text #c0caf5`, `accentAlt #bb9af7` (modern purple). Cost: btop + optional JSON. - **kanagawa** — Wave, clean. No action required; optional rename "Kanagawa Wave"; optional brighter good `springGreen #98bb6c`. - **ethereal** — vibe solid; `surface`=`base`, `muted`=`overlay`. **Fix:** `surface #1a2340` (or Omarchy color0 `#3C486D`); split muted darker than overlay; optional richer good. Cost: small JSON. - **retro-82** — strong synthwave + excellent rofi whole-swap. `surface #00172e` darker than `base #05182e` (inverted raise); `good #028391` teal (reads info not ok). **Fix:** `surface #0a2844`; optional `good #3f8f8a` or phosphor green. Cost: small JSON; keep rofi. - **ristretto** — Monokai Pro Ristretto, ship-quality. Only `subtext`=`text`; btop `main_bg` 1-step drift (`#2c2421` vs `#2c2525`). **Fix:** `subtext #b5a9aa`; align btop bg. Cost: tiny. - **flexoki-light** — best of the Flexoki/import set post item-28. Optional: distinct ANSI bright-black `#575653`; recapture preview if terminal chrome still looks dark-on-paper. Cost: polish only. #### Systemic theme tooling - **Import pipeline collapses hierarchy when ANSI 0==8** `tools/import-palettes.py` maps `surface←color0`, `overlay←color8`, `good/warn/bad←color2/3/1`, `mantle←darken(base)`. When color0==8 (gruvbox, everforest) surface=overlay; light themes get sludge mantle. Long-term: allow explicit role overrides independent of ANSI for identity themes; don't re-import without a hierarchy pass. Cost: tool + convention doc. - **audit-theme-design identity exemptions** Document expected noise for white/vantablack/lumon/hackerman/ matte-black/miasma (hue-family + CVD) so future audits don't "fix" identity into traffic lights. Optional: special-case in the report script. Cost: docs or small script tweak. ### Tooling / CI / installer hardening (codebase exam 2026-07-09) _(py_compile expand, installer pure contracts, hardware-db ∈ nixos-hardware, windowrule dead-syntax guard → #49.)_ - **Installer soft gaps** (1) fingerprint path prefers `lsusb` but package PATH has `pciutils` not `usbutils` (sysfs fallback usually OK); (2) `chown -R 1000:100` on the flake dir assumes first-user UID/GID; (3) flake `packages` exports only theme-sync + install, not doctor / control-center / battery-notify (runtime via overlay is fine — discoverability only). Cost: small each. _(Control Center `/tmp/nomarchy-gens` → mktemp → #50.)_ ### Distro improvement ideas (codebase exam 2026-07-09) - **Fail-closed / friendlier theme-state errors in `mkFlake`** Missing `theme-state.json` fails later at `readFile`; invalid JSON fails at `fromJSON` before theme.nix's field-level validator. A friendly "add theme-state.json" / schema pointer would help downstream authors. Related: `settings.displayProfile*` not in defaults block (consumers use `or`); unknown border role falls through to raw string. Cost: medium lib/theme.nix UX. - **Look & Feel submenu (ROADMAP optional)** Night-light, wallpaper cycle, blur/gaps (once CC appearance is fixed) grouped with Theme once the root stays six entries. Cost: menu structure only; product call. _(Export overlay tools as flake packages → #50.)_ - **Unattended-install test matrix** `test-install.sh` always LUKS+swap; add (or document) no-swap and no-LUKS paths once those contracts are fixed, so swap/LUKS-class bugs cannot recur. Cost: script flags + time on KVM host. _(Document always-on home pieces (easyeffects/udiskie/cliphist) → #47.)_ ### Hardware product (investigation 2026-07-09) *Full write-up: [`docs/HARDWARE.md`](../docs/HARDWARE.md). Install-time autodetect is strong; day-2 lifecycle (firmware, biometrics, re-detect, NVIDIA depth) is still mostly CLI. Items below are product work on top of that doc — design notes live there (§4–§10).* _(`nomarchy-detect-hw` CLI → **#58**; Fingerprint menu → **#55**; Installer NVIDIA commented guidance → **#59** ✓ 2026-07-10.)_ _(hardware-db ∈ nixos-hardware → #49; usbutils on install PATH → #50; i2c README table → #48.)_ - **Post-install hardware hints (MOTD / first session)** When relevant services exist, surface one line each: firmware (`fwupdmgr get-updates`), fingerprint (`fprintd-enroll`), optional “run nomarchy-doctor”. Avoid nagging — once or until dismissed. Spec: HARDWARE.md §4/§5. Cost: small greeter/MOTD or notify; V2/V3. _(Partial: #43 shipped Firmware MOTD/tip 2026-07-09; fingerprint + doctor lines still open.)_ - **NVIDIA first-class options (larger, optional)** Only if a maintainer commits to hybrid testing: thin `nomarchy.hardware.nvidia.*` wrapping common PRIME/power patterns. Prefer NEXT **#59** (commented guidance) first; promote only with hardware-queue coverage. Cost: high; `[big]` + `[blocked:hw]`. ### Installer process (audit 2026-07-09) *Full-path review of live ISO → `nomarchy-install` → disko → config generation → offline/online `nixos-install` → HM pre-activate → first boot. Philosophy applied: **opinionated, stability-first** — prefer safer defaults and fewer install questions over option sprawl. Day-2 firmware / fingerprint / re-detect stay in Hardware product above, not in the installer questionnaire.* #### Already strong (do not “fix” with more choices) - Single whole-disk GPT, UEFI + systemd-boot only; multi-disk RAID / dual-boot / BIOS deferred (ROADMAP LATER). - LUKS2 **default** + greeter auto-login (one gate); type-to-confirm wipe; live medium excluded from disk list; careful pre-wipe. - BTRFS subvols + snapper on by default; hibernation swap default = RAM; hardware autodetection with **safe defaults on, heavy bits commented**. - Offline-capable install (compose-lock, ISO store pin, daemon substituter); HM pre-activate so first boot is themed. - No Secure Boot theater; no install-time app-suite *wizard* / custom partitioner / pbkdf knobs. (Starter apps come from the **template** `home.packages` once the installer consumes the template as SoT — see above; not a separate install questionnaire.) - Live: no idle suspend (avoids mid-install sleep); WiFi via normal desktop NM path. #### Bugs (stability contracts — fix, don’t optionalize) - **Installer swap=0 + unattended LUKS fail-closed** — ✓ shipped (workflow test run 2026-07-09): pass bare `"0"`; disko accepts `"0"`/`"0G"`; unattended needs passphrase or `NOMARCHY_NO_LUKS=1`. _(Offline fail-closed → #54.)_ #### Safety / clarity (one line each — no new install menus) _(Review-panel destructive-data warning → #54.)_ _(Review panel: offline vs online source line → **#61** ✓ 2026-07-10.)_ _(User password minimum length = 8 → #54.)_ #### Live ISO discoverability (one durable cue) _(Live: one always-visible “Install Nomarchy” action → **#57**.)_ #### Generated config / post-install polish _(HM pre-activate failure → durable recovery hint → #54.)_ - **MIGRATION.md: installer snapshot layout vs `@home-snapshots`** Installer creates disko `@snapshots` → `/.snapshots` and a first-boot oneshot for nested `/home/.snapshots`. MIGRATION still speaks of top-level `@home-snapshots` (TuringMachine vocabulary). One paragraph clarifying installer layout vs migration machines prevents wrong expectations. Cost: docs only. #### Test / pure contracts (after P0 bugs) - **Installer pure checks + expanded unattended matrix** — overlaps existing *Tooling* items (disko `swapSize` contract, compose-lock py_compile, hardware-db ∈ nixos-hardware). After swap/LUKS fixes: document or script unattended no-swap and explicit no-LUKS paths in `test-install.sh` (env flags only — no interactive options). Do **not** grow the interactive installer questionnaire. #### Explicit non-goals for the installer (defer) Do **not** add install-time: dual-boot / preserve partitions, multi-disk RAID, Secure Boot/lanzaboote, recovery-key *wizard* (optional silent recovery print is the only recovery-key idea worth considering later), custom partitioner, online/offline user toggle, app suite selection, pbkdf/TRIM knobs, or a second installer frontend. Stability and the single golden path win. ## Decisions `[human]` Open calls only Bernardo can make; agents add options/evidence but never decide. - **Formatter adoption:** repo deliberately has none; `nixfmt-rfc-style` would flatten the aligned hand-formatting of ~33 files. Adopt or declare never? - **Docs site vs Markdown-in-repo** (from the docs-review item). - **zram swap:** faster under pressure and pairs with NOW#3, but it interacts with the hibernation-swapfile story (resume device/priority ordering) — adopt, adopt-with-hibernation-guard, or skip? - **Default browser:** the template comments Firefox out. The shipped mime defaults (item 8, done) point `text/html`/http(s) at `firefox.desktop` as *inert* entries — they activate the moment Firefox is installed and are skipped otherwise, so the remaining call is only: ship a browser active in the suite, or stay browserless-by-default? - **Default power backend — PPD vs TLP:** (raised by Bernardo 2026-07-08: would TLP be more power-efficient, and should it be the default?) TLP does get more *idle* battery life, but only from device-level knobs PPD deliberately omits — PCIe ASPM, disk/NVMe link PM, USB autosuspend, runtime PM — which are the same knobs behind NVMe/USB flakiness that pillar 1 (rock-stable, never fight your machine) guards against. **Evidence (2026-07-08):** no credible hard-watt benchmarks exist — TLP's own maintainer declines to quote any ("measure on your hardware") and says PPD's power-saver gives *similar* savings under load; TLP's edge is idle-only (linrunner.de/tlp/faq/ppd.html — PPD covers a *subset* of TLP, "no settings to reduce consumption when the CPU is idle"). Our sibling distro **Omarchy** ran this exact experiment — a "replace Power Profiles with TLP for battery" guide — and the author **reverted to PPD** ("more headaches and weird issues"); Omarchy shipped PPD auto-switching instead (basecamp/omarchy#3907). PPD 3.4.0 now does AC/battery auto-switching, closing part of TLP's UX gap. **Cost of TLP-default:** TLP has no live D-Bus profile API, so the `powermgmt` menu + Waybar profile indicator + low-battery auto power-saver (all `powerprofilesctl`) would need a rework — it's not a one-line backend swap. **Agent rec (evidence, not a decision): keep PPD default;** chase battery via targeted low-risk tweaks (PCIe ASPM policy, battery-side EPP, the charge *start* threshold, PPD auto-switching) and keep TLP the documented one-line opt-in it already is (`nomarchy.system.power.backend = "tlp"`). Options: (i) status quo + targeted tweaks [rec]; (ii) TLP default (reworks the profile UX); (iii) nothing.