Files
Nomarchy/agent/BACKLOG.md
Bernardo Magri 2ef0a8b710
All checks were successful
Check / eval (push) Successful in 2m52s
feat(hw): #58 nomarchy-detect-hw post-install re-probe CLI
Package the installer’s pure hardware-db probe as nomarchy-detect-hw:
prints suggested hardwareProfile and system.nix snippets (or --raw
protocol lines). Does not rewrite the flake. On PATH via the distro
module; docs/HARDWARE.md §8 updated. Close #58.

Verified: V1 (build + run on AMD laptop with fingerprint/NPU/IR cam).
2026-07-10 08:41:18 +01:00

568 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 V1V2.
### 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).
## 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** ✓ 2026-07-10.)_
- **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; V1V2.
- **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, dont 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** ✓ 2026-07-10;
V2 pending: live ISO desktop entry smoke.)_
#### 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.