# Hardware queue — V3 checks only a human can run

Everything shipped at V1/V2 whose final verification needs real hardware.
Agents **append** (newest at the bottom of a section) with exact steps;
Bernardo runs them and either checks off (`[x]` + date + verdict) or files
the failure as a NOW bug in BACKLOG.md. Checked-off entries are **pruned**
on the next sync sweep (LOOP.md §5) — outcomes live in the journal/ROADMAP;
git history is the archive. Machines: the **AMD dev box** (Ryzen AI
laptop: AMD + fingerprint + NPU), the **Latitude 5310/5410** (Intel QA),
the **T14s** (webcam case).

## Any machine (dev box is fine)

- [ ] **#86 clamshell lid + external display** — V2 asserts
      `HandleLidSwitchDocked=ignore` in logind.conf. On a laptop with a
      real external monitor: open a session, plug external, close lid —
      machine must **stay awake** (no suspend); external panel remains
      usable (or wakes with keyboard if DPMS). Unplug external, close lid
      — should suspend as usual. Optional: with a docked display-profile
      (`eDP-1` disable), confirm clamshell layout still looks right after
      lid close. Pass = no surprise suspend when docked.
- [ ] **#87 round 2: dock audio auto-follow (watcher)** — round 1 result
      (Newton, 2026-07-12): audio stayed on speakers when docking; the
      running generation had no `90-nomarchy-dock-audio` rules yet, and
      live testing showed the priority rules alone can never win anyway —
      WirePlumber's stored default (`default-nodes` state, written by any
      past explicit pick) outranks `priority.session`, and this machine
      (like most) has one. Fix shipped: the `nomarchy-dock-audio` user
      service `pactl set-default-sink`s dock-class sinks on hotplug;
      EasyEffects follows the default (verified live: EE's output links
      moved to a fake dock-named null sink mid-playback). Retest after
      pull+rebuild+home on ≥ this rev: play audio, plug the dock →
      toast "Audio → <monitor/dock>" and sound moves with EE effects
      still active; unplug → sound returns to speakers; while docked,
      picking speakers in the Audio menu sticks until the next replug.
      If it does NOT switch, capture for diagnosis: `pactl subscribe`
      output during the plug, `pactl --format=json list sinks` while
      docked (sink names may not match the dock regexes, or the sink
      node may pre-exist and only flip route availability — the watcher
      keys on new-sink events).
- [ ] **Docked display/audio menu rows** (2026-07-12) — with a real
      external monitor: Display menu shows "Laptop screen off ·
      everything → <ext>" (only with >1 active output), "Screen on ·
      <name>" after a disable, "Move workspace · → next monitor", "Swap
      workspaces" (exactly 2 outputs). Laptop-off must move its
      workspaces to the external; Screen on restores it (preferred/auto —
      declared scale/pos return at the next relogin/switch). Audio menu
      shows "Send output → <dock sink>" when one exists and isn't
      default; picking it moves output + toasts. Pass = rows appear/act
      as described, and none of them show on a single-display session.
      Also — **run this one with nothing important open**: with the
      laptop screen off via the menu, physically unplug the dock. The
      panel should re-enable within ~2s (`rescue_blackout` in the
      display watcher). Known risk from the VM harness
      (tools/monitor-fallback.nix): on Hyprland 0.55.4 the zero-output
      state itself can crash the compositor faster than any rescue
      (softGL VM: 4/5 runs; control with the panel active survives
      always) — a crash on real DRM ends the session to the greeter on
      the re-lit panel. If that happens on hardware, the "Laptop screen
      off" row needs a rework (mirror instead of disable, or drop until
      a Hyprland bump) — file it as a NOW bug with the coredump.
- [ ] **Parallel fingerprint-or-password on the real reader** (AMD dev
      box, 2026-07-12) — with a finger enrolled and
      `fingerprint.pam = true` (parallel is the default): `sudo -k true`
      must show ONE prompt ("Enter Password or Place finger…"); typing
      the password immediately works, touching the sensor instead works,
      wrong-finger ×3 falls back to password, and password keeps working
      with fprintd stopped (`systemctl stop fprintd`). Also check
      hyprlock and the greeter accept both factors and don't wedge on a
      leftover prompt after a fingerprint win (known cosmetic quirk of
      the hack — pthread_cancel'd prompt). `fingerprint.parallel = false`
      must restore the old sequential behavior. VM already asserts the
      PAM stack shape + password-only lockout safety with no reader
      (checks.hardware-toggles).
- [ ] **#55 fingerprint enroll on real reader** — with
      `nomarchy.hardware.fingerprint.enable` and a physical reader: System ›
      Fingerprint › Enroll a finger; List shows it; Verify succeeds; optional
      Use for login (on) → `nomarchy-rebuild` → login/sudo accept fingerprint.
      Menu surface is V1/V2 without a reader (self-gate + dry paths).
- [ ] **#60 non-BAT* battery name (if available)** — on a machine whose
      system battery is **not** named `BAT*` (e.g. `CMB0`): confirm
      charge-limit oneshot writes the threshold, System › Battery limit
      and Power profile rows appear, Waybar power-profile module shows,
      doctor charge-limit section runs. On `BAT0`-only machines this is
      a no-op (charge-limit re-apply passed on `BAT0` — Latitude
      2026-07-10).
- [ ] **btop theme fidelity (#52 residual)** — softGL theme-shot cannot
      open Ghostty, so the hand `btop.theme` assets were only guest-file
      asserted (main_bg / inactive_fg keys) + desktop/bar rendered for
      rose-pine, everforest, summer-night, vantablack, catppuccin. On a
      real session: `nomarchy-theme-sync apply <slug>` then `btop` and
      confirm backgrounds/text match the theme (esp. rose-pine Dawn light
      bg `#faf4ed`, vantablack near-black `#0d0d0d`, catppuccin Mocha
      `#1E1E2E`). One pass cycling those five is enough.
- [ ] **SSH_AUTH_SOCK for GUI clients** — after relogin, launch a GUI git
      client (or `rofi`-launched terminal-less app) and confirm it reaches
      gpg-agent's SSH socket without an interactive shell parent.
- [ ] **Notification inhibited-state glyph** (item 28 color-only sweep,
      iteration #69) — have an app hold a notification inhibitor (e.g. run
      a fullscreen video, or `busctl --user call org.freedesktop.Notifications
      … Inhibit`); the Waybar bell must switch to the muted **bell-off** 󰂛
      (same glyph as DND), NOT the normal bell 󰂜/󰂚. Then release it → the
      bell returns. Repeat on a whole-swap bar (summer-day/night use their
      own bell-off glyph, executive-slate/boreal use 󰂛). The glyph itself
      already renders (DND uses it); this only confirms swaync emits the
      `inhibited-*` class and the bar routes it.
- [ ] **Keyboard layout cycle bind** — with a comma layout (e.g.
      `nomarchy.keyboard.layout = "us,de"`), SUPER+SHIFT+K cycles the
      focused keyboard's layout, the Waybar `󰌌` indicator follows, and
      the row shows in the SUPER+? cheatsheet. — 2026-07-04 attempt:
      no comma layout was configured, so the bind wasn't rendered (the
      gate working as designed, not a failure) — retest after setting a
      comma layout + rebuild + relogin. The SUPER+? no-op found en
      route was a real bug → BACKLOG item 26 (fix shipped; SUPER+?
      cheatsheet PASS on Latitude 2026-07-10).
- [ ] **swaync readable on summer-day** (item 25 fix) — on summer-day
      after `home-update`: `notify-send "title" "body text"` shows
      readable body text; open the control centre (SUPER+N), hover a
      notification row and check the Clear button — all text legible
      (body/buttons now @text on tinted chips, not subtext/surface).
- [ ] **Bar + rofi legible on flexoki-light** (item 27 fix) — switch to
      flexoki-light: every Waybar module readable (window title, tray
      row, dimmed inactive workspaces / muted volume visible-but-dim),
      rofi inputbar/alternate rows show text. Spot-check one dark theme
      (e.g. tokyo-night) for no visual regression in the same spots.
- [ ] **Stub-bar themes got the generated bar** (item 28, 90a5104) —
      switch to catppuccin, lumon, nord and retro-82: each now shows
      the generated styled bar in its own palette (workspace pill,
      padded right cluster) instead of the old raw default Waybar.
      Their rofi menus should look unchanged.
- [ ] **Back-audit spot-check** (item 24) — the keybinds cheatsheet
      (SUPER+? / root menu › Keybindings) now ends in ↩ Back and
      returns to the root picker; spot a couple of submenus (Display,
      VPN › Tailscale) still Back correctly after the audit pass.
- [ ] **Keyboard hotplug picker (re-verify after in-flake graduation)** —
      plug an external keyboard post-login, pick a layout in rofi, confirm
      it applies per-device only, persists in `settings.keyboard.devices`,
      and graduates into a `device{}` block on the next rebuild.
- [ ] **Snapshots restore + rollback exercise** (residual — the
      GUI/polkit half passed on hardware 2026-07-04, a47aa3a): in
      `sudo nomarchy-snapshots`, restore a single file (`undochange`)
      and walk a root-config rollback up to (or through) the
      typed-`yes` gate.
- [ ] **Rollback menu (item 9b)** — after a couple of theme changes,
      menu › System › Rollback: recent desktop generations listed
      (newest marked current); picking an older one opens a terminal,
      activates it, and the theme visibly reverts; picking the newer one
      again rolls forward. The two System rows: Snapshots opens the
      snapshot flow, "boot an older generation (how)" fires an
      instruction notification.
- [ ] **Open-a-file smoke (viewers + mime defaults, item 8)** — after
      `nomarchy-home`: from yazi/Thunar, open a PDF (→ zathura, themed to
      the palette), an image (→ imv, NOT GIMP), a video (→ mpv);
      `xdg-open .` on a directory → Thunar; a link → **Chromium**
      (`chromium-browser.desktop` — template default as of 2026-07-10).
- [ ] **Update awareness** — with `nomarchy.updates.enable`, let the timer
      fire (or start the unit): indicator appears only when inputs are
      behind, notification only on count growth, click opens the upgrade
      flow.
- [ ] **VPN menu live paths** — import a real WireGuard `.conf` and an
      `.ovpn` via System → VPN, toggle up/down (● / ○ state), and the
      Tailscale block: up/down + exit-node without sudo (operator grant).
      Exit-node rows now show "hostname — Country City" (2026-07-11,
      header-offset parsing): confirm Mullvad-style nodes carry their
      location, a locationless self-hosted node stays a bare hostname,
      and picking either still sets the node (`tailscale status` shows it).
- [ ] **Printer menu** — with `nomarchy.services.printing`, System →
      Printers opens system-config-printer; add a printer, test page.
- [ ] **GRUB UEFI ISO theme render** — boot the ISO on UEFI hardware:
      composed splash background, palette menu in the lower third, accent
      timeout bar.
- [ ] **Visual theme pass** — live ISO: all six identity themes (bars) +
      the four authored rofi `.rasi` (nord/retro-82/lumon/kanagawa) look
      right, not just parse.
- [ ] **Display profiles, slice a (item 15)** — declare two
      `nomarchy.displayProfiles` (e.g. docked disables eDP-1 + arranges
      the externals; undocked re-enables it), `home-update`, then:
      System › Display › Profiles lists them (● marks active); applying
      is instant (no rebuild) and survives a relogin (the baked
      overlay); "Base layout" restores; a menu resolution pick made
      earlier must NOT re-enable a profile-disabled panel after the
      next rebuild.
- [ ] **Display profiles workspace pins, slice c (item 15)** — give the
      docked profile `workspaces = { "1" = "<ext>"; "9" = "eDP-1"; }`:
      applying the profile moves open workspaces 1/9 to those outputs
      immediately, new visits land there too, and the pins survive a
      relogin (baked `workspace` rules). Switching to a profile without
      pins leaves workspaces where they are (stale session pins are
      expected until reload/rebuild — noted in the applier).
- [ ] **Display profiles auto-switch, slice b (item 15)** — same setup,
      then menu › Profiles › Auto-switch on: plugging the dock/monitor
      applies the matching profile within ~3s (toast names it);
      unplugging switches back; Auto-switch off stops that; with two
      profiles naming the same outputs, no flapping (ties do nothing).
- [ ] **P2 retunes eyeball (item 28b)** — spot-check on top of the P1
      entry below: gruvbox/nord/lumon/everforest/retro-82/white dimmed
      text (inactive workspaces, muted volume) now visible-but-dim;
      latte + rose-pine(dawn) + summer-day warn/battery tint reads on
      the light bases; flexoki-light statuses are the deeper canonical
      600s; latte selected-row/alt-accent pink darker. Anything that
      lost its "dim" feel → reopen 28b.
- [ ] **Retuned palettes eyeball (item 28b P1)** — switch through
      summer-day, flexoki-light, kanagawa, miasma: chips/menus/toasts
      now draw on a *raised* surface (summer-day's was slate-on-cream,
      kanagawa's near-black, miasma's pure black), secondary text
      (tooltips, fastfetch labels) is visible on summer-day +
      flexoki-light, kanagawa floats are lighter than the bg (upstream
      sumiInk4). Anything that reads worse than before → reopen 28b.
- [ ] **Doctor bar tripwire (LATER item)** — with everything healthy
      the bar shows nothing; `systemctl --user start doomed`-style
      induced failure → within ~5 min a red  appears (tooltip lists
      the ✖ lines), clicking opens the sheet in a terminal;
      reset-failed → it disappears on the next poll. Also visible on
      both summer bars.
- [ ] **OCR region (LATER item)** — Tools › Capture › "OCR region →
      clipboard": select a region with visible text → toast reports
      the word count and `wl-paste` yields the text; Esc in slurp
      cancels silently; a text-free region toasts "No text recognized"
      without clobbering the clipboard.
- [ ] **Look & Feel submenu (item 19)** — root menu: "Look & Feel"
      (replacing Theme, root still six rows) → Theme grid opens, Next
      wallpaper cycles instantly, Night light toggles (and is GONE
      from System). SUPER+T / SUPER+SHIFT+T direct binds unchanged.
- [ ] **Launch-or-focus (item 17)** — uncomment the template's
      `nomarchy.launchOrFocus` firefox example (with firefox
      installed), `home-update` + reload: SUPER+B launches firefox
      when closed, FOCUSES the existing window when open (also from
      another workspace); with firefox removed the bind fires a
      "not installed" toast; the row shows under SUPER+?.
- [ ] **Themed greeter + console (item 16)** — after `sys-rebuild` +
      logout: tuigreet renders in theme colors (dark container, accent
      border, themed prompt/time) and a raw tty (CTRL+ALT+F2) shows the
      theme's ANSI palette; on a LUKS machine the passphrase prompt
      follows too. Then switch theme + `sys-rebuild` + logout → the
      greeter follows the new palette. (tuigreet can't run under the
      VM harness — see MEMORY.md — so rendering is hardware-tier.)
- [ ] **Color picker (item 13, final slice)** — SUPER+CTRL+P (or Tools ›
      Color picker): hyprpicker's zoom loupe appears; click a pixel →
      toast shows the hex and `wl-paste` yields it; Esc cancels with no
      toast. Row present in the SUPER+? cheatsheet.
- [ ] **Low-battery toasts (item 13 slice)** — on battery, drain past
      25%: one "Battery low" toast; past 10%: a critical "Battery
      critical" toast that stays up until dismissed (swaync); plug in,
      drain again → it re-notifies; no repeat toasts while it just keeps
      draining. (Crossing logic VM-verified — this checks the real
      swaync rendering in a session.)

- [ ] **Audio opens in Amberol** (iteration #60, item 37) — after
      `nomarchy-home`: double-click an mp3/flac/ogg (or `xdg-open song.mp3`)
      → it opens in Amberol, not mpv; video files still open in mpv.
      (`xdg-mime query default audio/mpeg` → io.bassi.Amberol.desktop.)
- [ ] **rofi menu polish** (iteration #58, item 39 + #56/#57 34/40) —
      after `nomarchy-home`: (a) menu › System › Power profile shows a
      colored icon per profile (performance/balanced/power-saver), not
      just text — icons *render* (not blank); (b) every submenu's ↩ Back
      shows a single arrow, no double; (c) on this single-monitor box,
      System › Display → pick a resolution → Back returns to System
      (not back into the same resolution list).
- [ ] **Screenshot annotation (satty)** (iteration #73) — after `nomarchy-home`:
      hit SUPER+SHIFT+Print (or Tools ▸ Capture ▸ Annotate region) → a region
      select (slurp) appears, then the `satty` UI opens in fullscreen with the
      screenshot loaded. Check that the UI draws on the current theme palette
      (tools colored properly) and hitting save places the screenshot in
      `~/Pictures/Screenshots/` while hitting copy places it in the clipboard.
- [ ] **#76 no-swap Hibernate notify** (#76 itself is closed — the
      hibernate→resume power-cycle **PASSED on TuringMachine 2026-07-12**:
      Bernardo ran the full hibernate → power off → single LUKS unlock →
      session-restored cycle "flawlessly"; this notify check is the one
      remaining leftover) — on a **Nomarchy** machine installed
      with `swap = 0` (or temporarily `sudo swapoff -a` on one): `nomarchy-menu
      → Power → Hibernate` must surface a desktop notification ("Couldn't
      hibernate — likely no swap is configured. See docs/MIGRATION.md →
      Enabling hibernation."), **not** a silent no-op. (`swapon` after, if you
      swapoff'd for the test.)
- [ ] **Night-light geo mode (2026-07-11)** — in `home.nix` set
      `nomarchy.nightlight = { enable = true; latitude = "<lat>";
      longitude = "<long>"; }` (your real coordinates), `nomarchy-home`,
      relogin. Then: `systemctl --user status wlsunset` is running (and
      `hyprsunset` is NOT); after local sunset the screen visibly warms
      (or test by setting coordinates where it's currently night); the
      Waybar moon + menu toggle still flip it instantly and an *off*
      survives relogin (the ExecCondition gate on the swapped unit —
      the eval check proves the wiring, not the runtime gate). **Pass** =
      warm shift at the location's night + toggle/persistence intact.

## AMD dev box only
- [ ] **AMD runtime bits** — VA-API (`vainfo` → radeonsi), amd-pstate EPP
      active and PPD switching governors; opt-ins: ROCm (`rocminfo`, a GPU
      PyTorch/Ollama smoke) and the XDNA NPU driver loading.
- [ ] **Fingerprint** — `fprintd-enroll` + (opt-in PAM) login/sudo.
- [ ] **System ▸ Firmware menu on real LVFS hardware** (item #43,
      `nomarchy-menu firmware`) — on a machine whose firmware/SSD/dock is
      on LVFS: open Menu ▸ System ▸ **Firmware**; confirm the terminal runs
      `fwupdmgr refresh` → lists real `get-updates` → the y/N confirm gates
      correctly → `fwupdmgr update` applies and prints the reboot note when a
      capsule needs one. Verify **no** flash happens on "N"/cancel. (VM only
      proves the menu row + flow renders; a real capsule write is
      hardware-only.)

## Latitude 5310 / 5410 only
- [ ] **v1 QA batch on-hardware pass** (583708d batch was QEMU-verified) —
      general smoke before the next `main → v1` promotion (broader than
      the 2026-07-10 session; include theme/ISO/greeter leftovers).

## T14s only
- [ ] **Webcam IR-hide end-to-end on Nomarchy** — installer detects the
      RGB+IR pair, bakes `hardware.camera.hideIrSensor`; `wpctl status`
      shows one colour source; an app picker lists one camera; Howdy-style
      direct `/dev/video2` reads still work.
- [ ] **Portal/Flatpak libcamera IR (b)/(c)** — after #71 docs: on hardware,
      confirm a Flatpak/portal picker still lists the internal IR node;
      only then investigate (b) WirePlumber libcamera GREY-only monitor
      rule or (c) libcamera/udev-layer hide. Do not ship either without a
      live dual-sensor check (see HARDWARE.md §7 / ROADMAP § Webcam).
