feat(doctor): #147 — flag machine state the flake never set; linger is the worked example
Some checks failed
Check / eval (push) Has been cancelled

/var/lib survives a migration untouched, and a stray pre-Nomarchy
Linger=yes marker shaped the QA box's session behavior for six months
with nothing in the flake to show for it. Ship the class as guards:

- nomarchy-doctor: new machine-state-drift check after the flake-checkout
  check — loginctl show-user -p Linger; "yes" warns (nothing is broken —
  it is drift) and prints the disable-linger fix; unknown-to-logind skips.
- docs/MIGRATION.md § Post-migration cleanup: "/var/lib machine state
  survives migration" — the worked example and the general suspicion rule.
- checks.doctor: linger sub-case — warn fires under enable-linger, exit
  stays 0, warning clears after disable-linger.

Deliberately NOT hardening the session wiring against the portal-gtk
restart race linger enabled: a clean install cannot reach that state.
The Waybar exec-once loose thread survives as BACKLOG #149.

Verification: V2 — shellcheck clean, nix flake check --no-build green,
nix build .#checks.x86_64-linux.doctor green (both branches exercised).
Implementation by a Sonnet subagent; design and review on Fable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 07:44:43 +01:00
parent 8fc0a9bc29
commit e324876eb7
6 changed files with 80 additions and 57 deletions

View File

@@ -110,6 +110,19 @@ if [ -d "$flake/.git" ]; then
fi
fi
# ── machine-state drift (survives migration, unseen by the flake) ────
# Worked example: systemd linger. The flake never sets it anywhere, so
# a "yes" here is leftover state from a previous OS/install, not
# something Nomarchy configured — it can cause months of divergent
# session behavior that no amount of flake auditing will explain.
linger=$(loginctl show-user "${USER:-$(id -un)}" --property=Linger --value 2>/dev/null || true)
case "$linger" in
'') skip "user linger (user unknown to logind — no session)" ;;
yes) warn "user linger is enabled but Nomarchy never sets it (machine state the flake can't see)" \
"loginctl disable-linger ${USER:-$(id -un)}" ;;
*) ok "no user linger (matches the flake)" ;;
esac
# ── generation age ───────────────────────────────────────────────────
# The profile SYMLINK's own mtime is the generation's creation time
# (store paths themselves are all epoch-1).