fix(docking): make workspace and lid transitions atomic
All checks were successful
Check / eval (push) Successful in 3m19s
All checks were successful
Check / eval (push) Successful in 3m19s
Restore the old flake's external-only workspace handoff, protect closed-lid cable removal with a verified low-level logind inhibitor, and use monitor-added as the settled audio reprobe boundary. Verified: V2 — nix flake check --no-build; docking-ux, option-docs, and template-sot checks; KVM tools/monitor-fallback.nix lifecycle test. V3 pending: closed-lid BenQ round 4 in agent/HARDWARE-QUEUE.md.
This commit is contained in:
@@ -402,14 +402,15 @@ Design/decision records and a running log of shipped work (items marked
|
||||
built-in. Rules in `modules/nixos/dock-audio-rules.nix`;
|
||||
`checks.dock-audio` pure + conf-file VM. Real hotplug V3 in
|
||||
HARDWARE-QUEUE.
|
||||
✓ **Dock audio round 2 — auto-follow watcher (2026-07-12):** the T14s
|
||||
✓ **Dock audio round 2 — auto-follow watcher (2026-07-12, superseded by
|
||||
#100 below):** the T14s
|
||||
dock test showed priority rules alone can't deliver "just works":
|
||||
WirePlumber's *stored* default (default-nodes state, written by any
|
||||
past explicit device pick — every real machine has one) outranks
|
||||
`priority.session`, so the default never moves on plug. Fix:
|
||||
`nomarchy-dock-audio` (modules/home/dock-audio.nix,
|
||||
`nomarchy.dockAudio.enable`, default on) — a `pactl subscribe` watcher
|
||||
that `set-default-sink`s new dock-class sinks (regex data imported
|
||||
`nomarchy.dockAudio.enable`, default on) — initially a `pactl subscribe`
|
||||
watcher that selected new/card-changed dock-class sinks (regex data imported
|
||||
from dock-audio-rules.nix, single source) + toasts; startup sweep for
|
||||
login-while-docked (only when the default isn't already dock-class, so
|
||||
restarts don't override a manual pick). EasyEffects needs nothing: EE 8
|
||||
@@ -437,7 +438,7 @@ Design/decision records and a running log of shipped work (items marked
|
||||
DRM is session-to-greeter on the re-lit panel, not a black brick).
|
||||
Also fixed in the rescue: `grep -c .` exits 1 at count 0 — an `||`-guard on that
|
||||
pipeline silently disabled the rescue exactly when it mattered.
|
||||
✓ **Docking hardware-QA correction (2026-07-13):** real clamshell QA
|
||||
✓ **Docking hardware-QA correction (2026-07-13, superseded by #100):** real clamshell QA
|
||||
confirmed every warned residual: Rofi's default `monitor=-5` followed
|
||||
the mouse pointer onto the hidden laptop workspace; the profile watcher
|
||||
(and blackout rescue) was not launched with default
|
||||
@@ -445,17 +446,47 @@ Design/decision records and a running log of shipped work (items marked
|
||||
it, with application loss consistent with the known zero-output crash;
|
||||
audio did not arrive as a new sink; and the keyboard picker was disabled
|
||||
by an empty optional-candidate list. Correction: Rofi targets the focused
|
||||
output (`monitor=-1`); interactive **Dock mode** explicitly moves eDP
|
||||
workspaces/focus to the external but keeps eDP logically active as the
|
||||
unplug fallback; the reconnecting display watcher runs unconditionally
|
||||
output (`monitor=-1`); the first correction's interactive **Dock mode**
|
||||
moved eDP workspaces/focus but kept eDP logically active as a fallback;
|
||||
the reconnecting display watcher runs unconditionally
|
||||
and watches through the racy removal snapshot; keyboard hotplug runs by
|
||||
default, searches the pinned XKB catalog without D-Bus, persists
|
||||
per-device, and has a manual System › Keyboard path; dock audio handles new sinks and
|
||||
card/profile/port-availability changes while ignoring volume/default
|
||||
changes so manual picks stick; and monitor-added re-applies the current
|
||||
per-device, and has a manual System › Keyboard path; that correction's dock
|
||||
audio reacted to new sinks and card/profile/port changes (replaced by
|
||||
#100's monitor-event boundary); and monitor-added re-applies the current
|
||||
awww wallpaper after the output settles (new outputs do not inherit the
|
||||
existing image). `checks.docking-ux` guards the generated default-session
|
||||
artifacts; the corrected real sequence remains V3.
|
||||
✓ **Dock transition recovery (#100, 2026-07-13):** the second T14s pass
|
||||
exposed why keeping eDP active was not safe: Hyprland requires an active
|
||||
workspace on every active output, so one workspace necessarily dangled.
|
||||
Cable removal with the lid closed was independently proven in the previous
|
||||
boot journal to make logind enter s2idle, explaining the apparent crash.
|
||||
`nomarchy-display-transition` now follows the old working flake's ordering:
|
||||
dock is one batch (enable external, move all internal workspaces, focus
|
||||
external, disable internal); undock enables internal first, waits boundedly,
|
||||
then moves every workspace back. Named profiles that disable the internal
|
||||
panel use the same transition when they have an external target.
|
||||
`nomarchy-display-profile-watch` owns a block-mode, low-level
|
||||
`handle-lid-switch` inhibitor from external detection through internal
|
||||
restoration and physical lid-open; it uses process substitution so state
|
||||
stays in the parent shell, verifies acquisition through logind, kills a
|
||||
private process group on cleanup, and validates/cleans a stale runtime PID
|
||||
after an unclean exit. Normal undocked lid-close suspend resumes after
|
||||
release. Audio now uses `monitoradded` as the fresh-plug intent boundary:
|
||||
after a debounce and two-second hardware settle it restarts PipeWire,
|
||||
PipeWire Pulse, and WirePlumber, then explicitly selects the highest-priority
|
||||
available sink using the original WirePlumber regex data. Generic
|
||||
`change:sink`/card events never select, so a manual speaker choice sticks;
|
||||
the subscription loop reconnects after graph restarts. Journal lines record
|
||||
the trigger and selected/no-candidate result. `checks.docking-ux` syntax- and
|
||||
invariant-checks generated artifacts; `tools/monitor-fallback.nix` is now a
|
||||
bounded KVM test for workspace/output/inhibitor transitions and passed V2.
|
||||
QEMU's headless backend aborts Hyprland if its final active synthetic output
|
||||
is deleted while the DRM output is disabled, so the harness explicitly runs
|
||||
the internal-first recovery before deletion and leaves real cable-removal
|
||||
timing to V3. V3 is queued as round 4; no speculative audio power policy was
|
||||
added.
|
||||
✓ **Parallel fingerprint-or-password (2026-07-12, Bernardo promoted
|
||||
from PROPOSED):** `nomarchy.hardware.fingerprint.parallel` (default
|
||||
**true** — the better UX is what opting into fingerprint PAM gets you;
|
||||
|
||||
Reference in New Issue
Block a user