All checks were successful
Check / eval (push) Successful in 3m7s
Bernardo, post-reboot: "Use for login" was the wrong question. Whether the
finger works is one decision, not two, and whether login prompts at all is
a different decision that was never in the menu.
System › Fingerprint is now a single Fingerprint (on/off) switch, leading
the menu with enroll/list/verify/delete as the plumbing behind it. It
writes the one settings.fingerprint.pam key, and modules/home/idle.nix now
defaults idle.fingerprint from that same key — so the lock screen and
login/sudo move together instead of drifting apart the way they did until
e2de906. nomarchy-fingerprint does the two rebuilds this needs (sudo
system for PAM, home switch for hyprlock) and refuses to turn on with no
finger enrolled.
System › Auto-login is new (nomarchy-autologin), and it is what decides
whether anything is asked at boot: auto-login on means no prompt whatever
the fingerprint switch says; off means the greeter asks, for a password or
a finger. Installer-seeded ON for LUKS machines — the passphrase already
gates the disk — and off without it, where the greeter is the only thing
between power-on and the desktop.
Both had to become state-owned to be toggleable at all, which surfaced two
real bugs:
* nomarchy.system.greeter.autoLogin defaulted from
`config.nomarchy.settings…` — an attribute that exists ONLY on the Home
Manager side. On NixOS it is absent and `or null` swallowed the error,
so the default silently evaluated to null on every machine ever built.
That is why the installer baked a Nix line: the state path never
worked. Now read via theme-state-read.nix (the hardware.nix/timezone.nix
pattern) and mkDefault'd, so the menu owns it and a hand-set line still
pins it. Two more options read the same phantom bridge — BACKLOG #116.
* `theme-sync get` printed Python's "None" for a JSON null, so every
`case … null)` a caller writes would miss. Now prints "null", as the
comment above it already promised for booleans.
The installer seeds the state instead of emitting the system.nix line,
because that line outranks the state and would strand the toggle.
V1 (V3 pending: HARDWARE-QUEUE). nix flake check --no-build, installer-
safety and option-docs all pass. Proved by eval/build, not assumed: a state
carrying autoLogin yields greetd initial_session {"user":"bernardo"}, the
template state (no autoLogin) yields none, and a hand-set null beats a state
that says otherwise; a state with only fingerprint.pam=true — nothing set by
hand — renders the hyprlock auth.fingerprint block; both new tools pass
bash -n and land in systemPackages (nomarchy-fingerprint only with a
reader); the patcher writes settings.greeter.autoLogin and no system.nix
line; and the get round trip prints null, so the menu reads "Auto-login
(off)" where it would have read "(on)".
The reader itself, the two rebuilds, and the reboot are hardware — queued.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
443 lines
30 KiB
Markdown
443 lines
30 KiB
Markdown
# 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)
|
||
|
||
- [ ] **#96 battery-limit row on threshold-less firmware (Acer M5-481T)** —
|
||
on the Acer (live or installed session with the commit carrying this
|
||
entry): open System (`SUPER+CTRL+I`). **Pass:** a "Battery limit" row
|
||
IS listed (battery present); picking it shows the notification
|
||
explaining the firmware exposes no charge-stop control (not a raw
|
||
error, and the row never silently disappears). On the T14s the row
|
||
must still open the working preset picker.
|
||
- [ ] **#101 charge-limit service survives USB-C power-event bursts**
|
||
(round 2) — round 1 FAILED on TuringMachine 2026-07-13 18:16: a
|
||
*spaced* storm (each run finished before the next AC event) landed 5
|
||
successful starts in 10s → `start-limit-hit`, unit marked failed,
|
||
doctor badge — although every run succeeded. Fixed by exempting the
|
||
unit from start rate limiting (`StartLimitIntervalSec=0`) + a
|
||
spaced-storm guard in `checks.battery-charge-limit` (the commit
|
||
carrying this entry). **Re-check:** after pulling/rebuilding this
|
||
commit, `sudo systemctl reset-failed nomarchy-battery-charge-limit
|
||
.service`, then plug/unplug the powered USB-C dock several times in
|
||
quick succession. **Pass:** `systemctl is-failed
|
||
nomarchy-battery-charge-limit.service` stays false, `Result=success`,
|
||
BAT0's `charge_control_end_threshold` still matches the limit, and the
|
||
journal has no new `start-limit-hit`/`Failed with result` lines.
|
||
- [ ] **Docking recovery round 8 (undock panel restore, 2026-07-14)** —
|
||
round 7 **FAILED** on the AMD dev box (Bernardo, 5–6 consecutive
|
||
unplugs, none recovered). Its whole diagnosis was wrong, and the way it
|
||
was wrong is the lesson: round 6 read `result=enable-timeout` ×2 +
|
||
`result=ok` ×1 as an intermittent race and retried the keyword. But the
|
||
keyword is **inert, not raced** — with ZERO enabled outputs (panel
|
||
disabled by the dock, external gone) Hyprland 0.55.4 accepts
|
||
`keyword monitor` (prints `ok`, exits 0) and never flushes it until a
|
||
DRM event arrives. Retrying an inert command 25×/poll for 6 polls just
|
||
bought 30s of black screen. Every `result=ok` in that journal was
|
||
**Bernardo plugging the cable back in** — his hotplug flushed the queued
|
||
rule and the next poll took the credit. Probed live 2026-07-14: keyword
|
||
inert across 4s and 5s in two runs, `dispatch forcerendererreload` also
|
||
inert, and only `hyprctl reload` worked — 99ms and 289ms, cable out.
|
||
The transition now escalates to `reload` when the keyword proves inert,
|
||
re-asserts the rule, and restores per-device keyboard layouts (a reload
|
||
drops runtime `device[…]:kb_layout` keywords).
|
||
**Already proven on hardware** (2026-07-14, two real unplugs invoking
|
||
the fixed `nomarchy-display-transition undock eDP-1` directly with the
|
||
watcher paused): panel on and workspaces 1–3 home in 1.8s, journal
|
||
`keyword=inert escalate=reload` → `enable=via-reload` → `result=ok`; and
|
||
the keyboard-restore path with a Logitech K400 whose receiver is in the
|
||
laptop — it kept its remembered `us` across the undock, while a control
|
||
`hyprctl reload` with no restore dropped it to the session's `gb`
|
||
(so `restore_keyboards` is load-bearing, not insurance).
|
||
**What is NOT proven, and is this round:** the *watcher-driven* path
|
||
(the running watcher calls the transition by baked store path, so it
|
||
only picks the fix up at relogin — the round-5 trap), and repetition.
|
||
**Re-check:** relogin (mandatory — see below), dock, then unplug the
|
||
cable **at least five times**, plus once with the lid shut.
|
||
**Pass:** the panel comes back every time with workspaces intact, and
|
||
`journalctl --user
|
||
-t nomarchy-display-transition -t nomarchy-display-watch --since
|
||
'-10 min'` shows `result=ok` for each undock with **no**
|
||
`result=enable-failed`. `keyword=inert escalate=reload` on every undock
|
||
is EXPECTED — that is the fix firing, not a fault. A `result=ok`
|
||
**without** a preceding `keyword=inert` line means the keyword flushed
|
||
on its own and the reload was never needed: interesting, worth
|
||
reporting, still a pass.
|
||
- [ ] **Headphone jack-follow (last open count from rounds 4–6,
|
||
2026-07-14)** — rounds 4–6 opened five counts on the AMD dev box; four
|
||
are now **confirmed fixed on hardware** by round 6 (Bernardo): wallpaper
|
||
on the external, automatic dock mode, audio reaching the monitor, and
|
||
the external keyboard prompting **exactly once** (was four times). The
|
||
undock panel is round 7 above. This is the one count **never tested**:
|
||
plugging headphones had stopped moving audio to them, because a pinned
|
||
`default.configured.audio.sink` outranks the priority rules, which kills
|
||
jack-follow on UCM cards where the headphones are their own sink (fixed
|
||
in ce480f3's lineage, unverified). **Re-check:** docked and undocked,
|
||
plug and unplug headphones — audio must move to them and back each time,
|
||
and `journalctl --user -t nomarchy-dock-audio` must show `trigger=jack
|
||
selected=…` on each plug. Worth folding into the round 7 session: the
|
||
dock is already in hand and the two don't interfere.
|
||
|
||
**Historical detail for the four settled counts** (kept only until
|
||
round 7 closes; the fixes themselves are in the log):
|
||
— round 4 was run on the AMD dev box and **failed on four counts**
|
||
(Bernardo): no wallpaper on the external monitor, no automatic dock
|
||
mode (System › Display had to be used by hand), audio staying on the
|
||
laptop speakers while docked, and one dock + one external keyboard
|
||
asking for a layout **four times**. Separately, plugging headphones had
|
||
stopped moving audio to them. Causes and fixes in the commit carrying
|
||
this entry: the display watcher's `socat -T 1` closed Hyprland's IPC
|
||
socket after a second of idle, so a dock plugged into an idle desktop
|
||
lost `monitoradded` in the reconnect gap (wallpaper + dock mode + audio
|
||
all hang off that one event); Hyprland lists every key-capable evdev
|
||
node as a "keyboard"; and a pinned `default.configured.audio.sink`
|
||
outranks the priority rules, which kills jack-follow on UCM cards where
|
||
the headphones are their own sink. **Re-run round 4 below in full**,
|
||
plus: (a) leave the desktop untouched for ~30s, then plug the dock —
|
||
wallpaper, dock mode, and audio must all follow with no manual step;
|
||
(b) the external keyboard must prompt **exactly once**, and never for
|
||
the monitor or the lid/power buttons; (c) docked and undocked, plug and
|
||
unplug headphones — audio must move to them and back each time.
|
||
`journalctl --user -t nomarchy-display-watch` should show
|
||
`outputs-changed added=…`, and `-t nomarchy-dock-audio`
|
||
`trigger=jack selected=…` on a headphone plug.
|
||
|
||
**Round 5 was itself run and failed (2026-07-14); this entry now covers
|
||
round 6.** Two of the four reports were never actually testing the fix:
|
||
both watchers are Hyprland `exec-once`, so `nomarchy-home` swaps the
|
||
config but leaves the *old* processes running — only `nomarchy-dock-audio`
|
||
(a user service) had picked up new code. **Relogin is mandatory before
|
||
testing either watcher**; confirm with `tr '\0' '\n' < /proc/$(pgrep -f
|
||
bin/nomarchy-display-profile-watch)/cmdline | sed -n 2p` and grep the
|
||
script for `outputs-changed`. The other two were real and are fixed in
|
||
the commit carrying this entry: automatic dock mode did not exist at all
|
||
(the watcher auto-*undocked* but only ever matched display profiles on
|
||
plug, and this box has none saved with `displayProfileAuto` unset, so
|
||
nothing happened — `Dock mode` was interactive-only), and the BenQ's
|
||
audio was unreachable because WirePlumber had `alsa_card.pci-0000_c3_00.1`
|
||
pinned to `pro-audio`, whose raw `pro-output-N` sinks have no ports and
|
||
no routing. The BenQ's own USB card is input-only (all profiles
|
||
`sinks: 0`), so DisplayPort is the only path to its speakers.
|
||
**Also check:** no display profile is saved, yet plugging the BenQ must
|
||
now dock by itself; and `journalctl --user -t nomarchy-dock-audio` shows
|
||
`repaired-card=alsa_card.pci-0000_c3_00.1 profile=HiFi` on the first
|
||
plug, after which audio reaches the monitor's speakers. A saved+matching
|
||
display profile must still win over auto-dock.
|
||
- [ ] **Docking recovery round 4 (#100, closed-lid BenQ sequence)** — after
|
||
updating to the commit carrying this entry, run `nomarchy-home` and
|
||
relogin. With the lid open, put visible windows on at least workspaces
|
||
1, 2, and 3 and start audio; plug the BenQ GW2790QT. **Pass on plug:**
|
||
wallpaper appears, audio toasts and moves to a BenQ/GPU HDMI sink, and
|
||
`journalctl --user -t nomarchy-dock-audio -n 10` shows
|
||
`trigger=monitoradded` plus `selected=…` (not only a card event). Open
|
||
System › Display › **Dock mode**. **Pass on dock:** every workspace and
|
||
window is on the BenQ, focus follows, eDP is disabled in `hyprctl
|
||
monitors all -j`, and `systemd-inhibit --list` shows Nomarchy holding
|
||
`handle-lid-switch` for “Safe dock/undock display transition”; there is
|
||
no dangling laptop workspace and no application exits. Close the lid;
|
||
audio/session must stay awake. While still docked, manually choose the
|
||
speakers and change volume/mute: it must stay on speakers. Unplug the
|
||
BenQ **with the lid still closed**, wait 10 seconds, then open it.
|
||
**Pass on undock:** no suspend/crash/hard reset, eDP is already active,
|
||
workspaces 1/2/3 and their windows are intact on it, and the inhibitor
|
||
disappears only after lid-open. `journalctl -b --since '-5 min'` must
|
||
contain no cable-removal `systemd-logind: Suspending...`. Finally close
|
||
the undocked lid normally: the laptop must suspend, proving policy was
|
||
restored. Wake it, replug the BenQ: that fresh plug must move audio back
|
||
to HDMI (manual speakers do not survive a physical replug). If any step
|
||
fails, capture `journalctl --user -t nomarchy-display-watch -t
|
||
nomarchy-display-transition -t nomarchy-dock-audio --since '-10 min'`,
|
||
`systemd-inhibit --list`, `hyprctl monitors all -j`, `hyprctl workspaces
|
||
-j`, and `pactl --format=json list sinks` before changing state again.
|
||
- [ ] **Parallel fingerprint-or-password on the real reader** (AMD dev
|
||
box, 2026-07-12) — **sudo path PASSED 2026-07-14** (Bernardo, dev box,
|
||
gen 422, `fingerprint.pam = true`, parallel default): `sudo -k true`
|
||
showed ONE prompt, the typed password worked, touching the sensor
|
||
instead worked, and wrong-finger ×3 fell back to password.
|
||
**Still open:** hyprlock and the greeter must accept both factors and
|
||
not 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.
|
||
**Do NOT "check password still works with `systemctl stop fprintd`"** —
|
||
that check was in this item and it is a trap that cannot fail. fprintd
|
||
is D-Bus activated, so PAM asks D-Bus and D-Bus starts it straight back
|
||
up: Bernardo ran it and *the fingerprint still authenticated*, which is
|
||
the tell that the daemon never stayed down. It proves nothing about a
|
||
dead reader. The property it was reaching for is structural anyway —
|
||
password is `auth sufficient` at order 11700, independent of the fprintd
|
||
rule at 11400, so no fprintd failure can gate it (verify by eval:
|
||
`nix eval --raw <flake>#nixosConfigurations.<host>.config.security.pam
|
||
.services.sudo.text`), and checks.hardware-toggles asserts that shape in
|
||
the VM with no reader at all. If someone genuinely wants it on hardware
|
||
it needs `systemctl mask` + stop, and masking a working machine's
|
||
authentication daemon to re-prove an evaluated invariant is a bad trade.
|
||
- [ ] **#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.
|
||
Enroll/List/Verify verified on hardware 2026-07-14 (T14s); the
|
||
remaining unknown is a reader-less machine's self-gate.
|
||
- [ ] **fingerprint + auto-login toggles on hardware** (this commit) — on the
|
||
T14s, after removing the pinning lines from `~/.nomarchy/system.nix`
|
||
(`greeter.autoLogin`, `hardware.fingerprint.pam`):
|
||
1. System › Fingerprint shows **Fingerprint (on)** (state already true).
|
||
Toggle it off → terminal opens, sudo system rebuild + home switch →
|
||
toast "Fingerprint off". Expect: sudo now refuses the finger and asks
|
||
only for a password; the lock screen (SUPER+CTRL+L) shows no
|
||
"or scan your finger" line. Toggle back on → both return.
|
||
2. With fingerprint OFF and no finger enrolled, the toggle must REFUSE
|
||
with "Enroll a finger first" and write nothing.
|
||
3. System › Auto-login shows **(on)**. Toggle off → sudo rebuild →
|
||
reboot → tuigreet asks, and accepts password OR finger (fingerprint
|
||
on). Toggle back on → reboot → straight to the session, no prompt.
|
||
Expected throughout: the two are independent, and auto-login on means
|
||
no boot prompt regardless of the fingerprint switch.
|
||
- [ ] **#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.
|
||
- [ ] **Per-device keyboard menu + hotplug restore (re-verify after in-flake
|
||
graduation)** — update to the current `main`, run `nomarchy-home`, and
|
||
relogin with an external keyboard already connected. Open System ›
|
||
Keyboard: both the built-in and external boards must be listed with
|
||
their current layouts. Pick a different layout for the external board;
|
||
it must apply only there and persist in `settings.keyboard.devices`.
|
||
Unplug/replug it: the saved layout must restore without another prompt
|
||
and graduate into a `device{}` block on the next rebuild. Finally plug
|
||
a previously unseen keyboard in after login: the automatic picker must
|
||
appear once and remember that choice too.
|
||
- [ ] **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).
|