feat(doctor): first-boot pre-activate fail flag (#83)
Some checks failed
Check / eval (push) Has been cancelled

If the installer left /var/log/nomarchy-hm-preactivate.log and no Home
Manager generation exists, doctor reports ✖ with the recovery one-liner
(home-manager switch --flake ~/.nomarchy -b bak). Clears once a
generation is present. checks.doctor covers both arms.

Verified: V2 — checks.doctor green; local smoke.
This commit is contained in:
Bernardo Magri
2026-07-11 10:28:14 +01:00
parent 639f553cb7
commit fe0b972171
7 changed files with 68 additions and 9 deletions

View File

@@ -55,12 +55,6 @@ runtime-computed `resume_offset` into the boot cmdline, and the dev box runs
exactly this layout (`/proc/cmdline` verified) but isn't Nomarchy. Steps in
HARDWARE-QUEUE. Close #76 on PASS.
### 83. Doctor first-boot section: pre-activate fail flag (`VISION § A`)
The installer leaves `/var/log/nomarchy-hm-preactivate.log` on the
target when the theme bake fails, but nothing on the installed system
points at it. Doctor gains a first-boot line: if the log shows failure
and the HM generation is missing, print the recovery one-liner.
### 84. Dock life polish (`VISION § C`) `[big]`
Split before starting: (a) clamshell — lid closed with external monitor
connected must not suspend (logind lidSwitchDocked/ExternalPower audit +
@@ -126,8 +120,8 @@ high-ROI, etc.) live in the journal + ROADMAP — not here.*
2026-07-10). Keep #59 commented install guidance; no
`nomarchy.hardware.nvidia.*` until a hybrid maintainer + queue.
_(#80#82 shipped 2026-07-11. Remaining promoted: pre-activate flag,
dock life, hall of fame → **NEXT #83#85**.)_
_(#80#83 shipped 2026-07-11. Remaining promoted: dock life `[big]`,
hall of fame → **NEXT #84#85**. Split #84 before starting.)_
### v1.0 pointer

View File

@@ -19,6 +19,17 @@ Template:
---
## 2026-07-11 — #83 doctor first-boot pre-activate flag
- **Task:** NEXT #83 — doctor points at failed installer HM pre-activate.
- **Did:** doctor row: if `/var/log/nomarchy-hm-preactivate.log` is present
and no Home Manager generation exists → ✖ +
`home-manager switch --flake ~/.nomarchy -b bak`. Skip/ok otherwise.
Extended `checks.doctor` (fail arm + recovered gen). Closed #83.
- **Verified:** **V2** — checks.doctor green (fail arm + recovered gen);
local smoke with NOMARCHY_HM_PREACTIVATE_LOG / empty HOME.
- **Pending:** —
- **Next suggestion:** #85 docs hall of fame (cheap) or split #84 dock.
## 2026-07-11 — #82 generation readability
- **Task:** NEXT #82 — plain-language “what changed last rebuild”.
- **Did:** `pkgs/nomarchy-what-changed` (nvd → “N added, M removed, K

View File

@@ -392,6 +392,7 @@ fix command.
| fwupd | daemon active; optional “updates pending” warn | `fwupdmgr get-updates` |
| Battery threshold | if laptop + limit set, sysfs reports it | power docs / restart charge-limit unit |
| Battery health | cycle_count and/or charge\|energy_full÷design % when sysfs exports them | report-only (warn if <70% of design) |
| First-boot pre-activate | installer log present + no HM generation | `home-manager switch --flake ~/.nomarchy -b bak` |
| Hibernate / zram | disk swap + resume=; zram active | docs/MIGRATION.md → Enabling hibernation |
## 11. Option quick reference

View File

@@ -381,6 +381,11 @@ Design/decision records and a running log of shipped work (items marked
toast from `nomarchy-rebuild` / `nomarchy-home`; System What changed?
(toast + floating full report). `checks.what-changed` fixtures nvd via
`NOMARCHY_NVD`.
✓ **Doctor first-boot pre-activate (#83, `VISION § A`):** if
`/var/log/nomarchy-hm-preactivate.log` exists and no Home Manager
generation is present, doctor ✖ with
`home-manager switch --flake ~/.nomarchy -b bak`. Skips when log absent;
ok once a generation exists. `checks.doctor` covers both arms.
- ✓ **Hibernate double-unlock:** on resume from hibernate the LUKS
passphrase already gates the machine, but locking hyprlock before sleep
meant a second password. Fixed by *not locking* before an encrypted

View File

@@ -59,7 +59,7 @@ The install is already strong. The gap is **after** first boot.
| **Doctor hardware section** | NM, sink, optional GPU smoke, fprintd, fwupd pending, charge threshold | BACKLOG Hardware product |
| **Machine health entry** | One System row → doctor (not five submenus) | Menu / doctor |
| **Human rebuild errors** | On failed switch, point at last log lines + `nomarchy-doctor` | pkgs / menu |
| **HM pre-activate fail flag** | Durable recovery one-liner on target if bake failed | Installer |
| **HM pre-activate fail flag** | Durable recovery one-liner on target if bake failed | ✓ shipped #83 — doctor first-boot row + install-time hint |
Reference: [HARDWARE.md](HARDWARE.md) §4§5, §10.

View File

@@ -461,6 +461,27 @@
"NOMARCHY_POWER_SUPPLY_ROOT=/tmp/fake-ps nomarchy-doctor 2>&1"
)
assert "MOUSE0" not in bat2, f"doctor reported Device-scope battery:\n{bat2}"
# #83 first-boot pre-activate fail flag: log present, no HM gen .
machine.succeed(
"mkdir -p /var/log && "
"echo 'error: activation failed' > /var/log/nomarchy-hm-preactivate.log"
)
# Bare test VM has no per-user HM profile for root.
pre = machine.fail("nomarchy-doctor 2>&1")
assert "pre-activat" in pre.lower() or "Home Manager generation" in pre, (
f"doctor missing pre-activate fail line:\n{pre}"
)
assert "home-manager switch" in pre, f"doctor missing recovery one-liner:\n{pre}"
# Once a generation exists, the flag clears (recovered).
machine.succeed(
"mkdir -p /nix/var/nix/profiles/per-user/root && "
"ln -sfn /run/current-system "
"/nix/var/nix/profiles/per-user/root/home-manager"
)
pre_ok = machine.succeed("nomarchy-doctor 2>&1")
assert "desktop generation is present" in pre_ok, (
f"doctor should ok when HM gen exists:\n{pre_ok}"
)
'';
};

View File

@@ -127,6 +127,33 @@ else
skip "snapper (not enabled on this machine)"
fi
# ── first-boot HM pre-activate (installer fail flag, BACKLOG #83) ────
# Installer writes /var/log/nomarchy-hm-preactivate.log on the target.
# If that log exists and there is still no Home Manager generation, the
# desktop never baked — print the recovery one-liner. Override log path
# with NOMARCHY_HM_PREACTIVATE_LOG for checks.doctor.
pre_log="${NOMARCHY_HM_PREACTIVATE_LOG:-/var/log/nomarchy-hm-preactivate.log}"
hm_gen_present=0
uid_name="${USER:-$(id -un 2>/dev/null || echo)}"
for d in \
"${XDG_STATE_HOME:-${HOME:-}/.local/state}/nix/profiles" \
"/nix/var/nix/profiles/per-user/${uid_name}"; do
[ -n "$d" ] || continue
if [ -e "$d/home-manager" ] \
|| ls -d "$d"/home-manager-[0-9]*-link >/dev/null 2>&1; then
hm_gen_present=1
break
fi
done
if [ ! -r "$pre_log" ]; then
skip "first-boot pre-activate (no installer log — not a failed bake)"
elif [ "$hm_gen_present" -eq 1 ]; then
ok "first-boot pre-activate: desktop generation is present"
else
bad "desktop was not pre-activated at install (no Home Manager generation)" \
"home-manager switch --flake ~/.nomarchy -b bak (details: $pre_log)"
fi
# ══ hardware ═════════════════════════════════════════════════════════
# Every check below self-gates: it skips cleanly when the tool, service,
# or device isn't present, so the section shrinks to fit the machine and