docs(agent): file #135/#136 — give the #127 DPMS mitigation an owner
All checks were successful
Check / eval (push) Successful in 3m53s

Reviewing 060bf52 at Bernardo's request. The call is right — the failure
mode is a brick (no wake, no VT, hard power-off with the btrfs risk that
carries), so prevent-over-recover beats a lit panel. Three things it leaves
open, now tracked instead of remembered:

#135 — the mitigation is hardcoded policy with no way back. Docked externals
never blank and hyprlock has no timeout, so they stay lit indefinitely:
~60-100W nightly and OLED burn-in from a near-static lock screen. Add
settings.idle.dpmsWhenDocked (default false = today's behaviour), mostly so
the mitigation has a named surface to DELETE once wake is proven, rather
than a LATER note that quietly becomes the product. Ordered after the
hardware test: if the mitigation is withdrawn, the key never exists.

#136 — the gate is clamshell, not "docked". It skips only when an internal
is present-but-not-enabled; lid-open docked still falls through to dpms off.
Commit body, BACKLOG and journal all claim the broader "docked". Either the
scope is deliberate (fix the wording) or the mitigation misses half the
docked cases. Bernardo's call; the hardware test settles it.

Also recorded in #127 the caveat that outranks both: the fix is a cure for
an UNCONFIRMED cause. If DPMS-off is not the trigger, we hold the cost and
still have the brick.

No code change — #127 stays [blocked:hw] pending the hardware run.
This commit is contained in:
2026-07-15 18:25:47 +01:00
parent be636e14b9
commit 64f7379982

View File

@@ -64,7 +64,16 @@ and never re-enables a disabled internal.
undocked laptops still DPMS-off as before. Bernardo: Ctrl+Alt+F3 did
not yield a usable TTY on the original brick, so prevention > dump path.
- **Revisit later (LATER):** intentional DPMS-when-docked once wake is
proven trustworthy (monitor power-save without a brick).
proven trustworthy (monitor power-save without a brick). Tracked as
**#135** (state key + the surface to delete this by) and **#136** (the
gate is clamshell, not "docked" — lid-open docked still blanks). Both
are downstream of the hardware test below.
- **Caveat the test must settle:** the mitigation is a cure for an
**unconfirmed cause**. "Blanking the only live output caused the brick"
is inference from one incident, shipped at V1. If DPMS-off is not the
trigger, we are paying a permanent behaviour cost (docked externals never
sleep) and the brick is still live — so confirming the cause outranks
#135/#136.
**Pass (current mitigation):** docked on AC, idle past 10+ min → external
stays lit under hyprlock (journal: `dpms-off skipped: docked`); undocked
@@ -73,6 +82,45 @@ DPMS-while-docked) deferred to the LATER revisit.
## NEXT
### 135. Give the #127 DPMS mitigation a state key (and a way back)
The shipped mitigation is hardcoded policy: docked (clamshell) externals now
**never** blank, and hyprlock has no timeout of its own, so they stay lit
indefinitely. Two real costs land on the user — a couple of 27" panels at
~60100W all night, and **OLED burn-in** from a near-static lock screen held
for hours. Today there is no way to opt back in, which also breaks the
in-flake-state rule that settings are menu-writable.
Add `settings.idle.dpmsWhenDocked` (default **false** = today's safe
behaviour), read by `modules/home/idle.nix`'s `dpmsOff` gate, with a
Preferences row. The real point is not the option: it gives the mitigation a
**named surface to delete** once wake is proven, instead of an unowned LATER
note that quietly becomes the product. Whoever removes the mitigation removes
the key in the same commit.
**Order:** after the #127 hardware test. If DPMS-off turns out not to be the
trigger, the mitigation is reverted wholesale and this key never exists —
building it first risks shipping an option for a policy we withdraw.
### 136. `[human]` #127's gate is clamshell, not "docked"
The code skips DPMS-off when a laptop internal is present in `monitors all`
but absent from the enabled list — i.e. **clamshell**. Commit 060bf52, the
#127 entry and the journal all say "docked", which is broader: **docked with
the lid open** (internal + externals all enabled) falls straight through to
`hyprctl dispatch dpms off` and still blanks. So either
- the narrow scope is deliberate (the brick needs the internal disabled, and
lid-open docked is genuinely safe) → fix the wording in 060bf52's
descendants so the docs stop claiming more than the code does; or
- it is an accidental gap → the mitigation misses half the docked cases and
the brick can still fire with the lid open.
Bernardo's call, and the #127 hardware test is what settles it: if the brick
reproduces lid-open, this is a gap. Cheap either way — one `jq` predicate or
one docs sweep. Filed because a doc that overclaims its own fix is how the
next session mis-diagnoses the recurrence.
### 129. Permanent guard for the GTK button-colour trap (#98 follow-up)
The #98 regression (destructive-action at 1.03:1, invisible) was caught only