docs(agent): Bernardo's calls — #136 settled, #130 decided, #143 waits, #120 deferred
All checks were successful
Check / eval (push) Successful in 3m49s
All checks were successful
Check / eval (push) Successful in 3m49s
#136 CLOSED: he confirms the incident was clamshell (laptop closed), so the gate already matched the evidence and only the words overclaimed. Swept: idle.nix's comment + its journal line (`dpms-off skipped: docked` → `clamshell (internal $m present but off)`), the ROADMAP entry, and #127's own text. Docked-with-lid-open still blanks and is now explicitly untested rather than implicitly covered. #127 gains the exact protocol he asked for — two tests, separated by risk: A) the mitigation holds (safe, unattended, journal line to grep); B) the decisive one, whether DPMS-off was ever the trigger, run by hand because the shipped mitigation would otherwise skip it. B self-recovers after 45s (dpms on + hyprctl reload — #142's hammer re-lights eDP) because this box has no sshd. All three outcomes are written down with what each implies, including "input wakes it" → revert the mitigation and #135 never exists. #130 decided: fix the contrast, we hold ourselves higher than GNOME — matching upstream is no defence at 2.7:1, under even the large-text floor. Recorded with the two candidate shapes and a preference for darkening our label over the user's accent, plus the note that check-theme-contrast.py covers palette pairings only, so it needs its own assertion or it rots exactly like #98. #143 decided: wait for rofi#2317, do not carry a patch — a patched rofi means every machine compiles rofi from source, on every lock bump, to fix a highlight. Now a watch, not work. #120 deferred to PROPOSED intact: the measurements stand, and the no-binary- cache gotcha probably makes cachix the real first step anyway. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
249
agent/BACKLOG.md
249
agent/BACKLOG.md
@@ -58,16 +58,21 @@ and never re-enables a disabled internal.
|
||||
**Progress 2026-07-15:**
|
||||
- Recovery tooling: undock ends with `dpms on`; `nomarchy-display-wake` /
|
||||
`nomarchy-display-dump` (SUPER+SHIFT+D; TTY if it works).
|
||||
- **Mitigation (shipped):** do **not** DPMS-off when docked — if any
|
||||
- **Mitigation (shipped):** do **not** DPMS-off when **clamshell** — if any
|
||||
laptop internal (eDP/LVDS/DSI) exists in `monitors all` but is not
|
||||
enabled, the 10 min listener skips blanking. Lock at 5 min still runs;
|
||||
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
|
||||
- **Scope settled (#136, 2026-07-16):** the gate is *clamshell*, not
|
||||
"docked" — and Bernardo confirms the incident was exactly that, **laptop
|
||||
closed**. So the code matched the evidence and only the wording
|
||||
overclaimed; that is fixed (idle.nix, ROADMAP, and the journal line, now
|
||||
`dpms-off skipped: clamshell`). Docked with the lid **open** still blanks
|
||||
and is untested — not exempted, not claimed safe.
|
||||
- **Revisit later (LATER):** intentional DPMS-when-clamshell once wake is
|
||||
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.
|
||||
**#135** (state key + the surface to delete this by), 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
|
||||
@@ -75,10 +80,67 @@ and never re-enables a disabled internal.
|
||||
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
|
||||
still blanks at 10 min and wakes on input. Full original pass (wake after
|
||||
DPMS-while-docked) deferred to the LATER revisit.
|
||||
**Pass (current mitigation):** clamshell-docked on AC, idle past 10+ min →
|
||||
external stays lit under hyprlock (journal: `dpms-off skipped: clamshell`);
|
||||
undocked still blanks at 10 min and wakes on input. Full original pass (wake
|
||||
after DPMS-while-clamshell) deferred to the LATER revisit.
|
||||
|
||||
---
|
||||
|
||||
### The two tests, exactly (2026-07-16)
|
||||
|
||||
**There is no SSH lifeline on this box** (`sshd` inactive), which is why test B
|
||||
self-recovers instead of relying on one. If you would rather have the net, turn
|
||||
`services.openssh.enable = true` on for the day and keep a phone SSH client
|
||||
open — then a brick is a nuisance, not a reboot.
|
||||
|
||||
**Test A — does the mitigation hold? (safe, ~15 min, unattended)**
|
||||
1. Docked, **lid closed**, on AC. Leave it completely alone for 12 minutes.
|
||||
2. Expect: at 5 min the external shows hyprlock; at 10 min it **stays lit**.
|
||||
3. Then: `journalctl --user -b -t nomarchy-idle --since '-15 min'`
|
||||
→ one `dpms-off skipped: clamshell (internal eDP-1 present but off)`.
|
||||
4. Now open the lid / undock, idle 11 min → the panel **should** blank, and
|
||||
wake on a keypress. That half must still work; the mitigation is not
|
||||
supposed to have disabled blanking everywhere.
|
||||
|
||||
**Test B — was DPMS-off actually the trigger? (the decisive one; bounded)**
|
||||
This is the test that outranks everything else here, because the mitigation is
|
||||
a cure for an *inferred* cause. Docked, **lid closed**, from a terminal on the
|
||||
external:
|
||||
|
||||
```sh
|
||||
( sleep 45
|
||||
hyprctl dispatch dpms on
|
||||
hyprctl reload # re-enables every output (the #142 hammer)
|
||||
) >/tmp/dpms-test.log 2>&1 &
|
||||
hyprctl dispatch dpms off
|
||||
```
|
||||
|
||||
The screen goes black. Then, in order:
|
||||
1. **Press keys / move the mouse** in the first ~40s. Does it come back?
|
||||
(In the incident it did not — this is the exact step that failed.)
|
||||
2. **Wait for the 45s auto-recovery.** Does the external return by itself?
|
||||
3. If it is still dark, **open the lid** — the `reload` should have re-enabled
|
||||
eDP even if the external stayed dead.
|
||||
4. Afterwards:
|
||||
`journalctl --user -b -t nomarchy-idle -t nomarchy-display-watch --since '-5 min'`
|
||||
|
||||
**What each outcome means — all three are useful:**
|
||||
- **Input wakes it** → DPMS-off is **not** the trigger. The mitigation is a
|
||||
permanent behaviour cost buying nothing, the brick is still live and
|
||||
un-diagnosed → revert the skip, **#135 never exists**, and hunt the real
|
||||
cause (hyprlock? hypridle's own resume path? the dock's DP link?).
|
||||
- **Dark until the 45s recovery, then fine** → the compositor was alive and
|
||||
`dpms on` works, so blanking-while-clamshell *is* the trigger and the
|
||||
mitigation is right → **#135 becomes the way to opt back in**.
|
||||
- **Dark even after recovery** (lid needed) → the original brick, reproduced
|
||||
**deterministically and on demand**. That is the best outcome: it turns a
|
||||
once-off incident into something bisectable (try it without hyprlock, with
|
||||
the lid open, on the internal only …).
|
||||
|
||||
Note the deliberate omission: this runs `dpms off` **by hand** rather than
|
||||
waiting for hypridle, precisely because the shipped mitigation would otherwise
|
||||
skip it. Same command, same state, no rebuild.
|
||||
|
||||
**Fallback if the cause resists (Bernardo 2026-07-16):** diagnosing stays the
|
||||
preference — DPMS when docked is the outcome we want. But the mitigation as
|
||||
@@ -111,25 +173,6 @@ the key in the same commit.
|
||||
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
|
||||
@@ -148,10 +191,18 @@ Fallout noted while fixing #98: in light palettes the suggested/destructive
|
||||
labels are base00 (cream) on saturated accent/bad — summer-day measures
|
||||
**2.72:1** (suggested) and **2.74:1** (destructive), under AA 4.5 and even
|
||||
under the 3:1 large-text floor. Not a regression: upstream adw-gtk3 does the
|
||||
same (`color: white` on the accent), so we currently match GNOME. Decide
|
||||
whether Nomarchy holds itself higher — darker label, or a darker accent mix
|
||||
for light palettes — and note `tools/check-theme-contrast.py` covers palette
|
||||
pairings only, never GTK widget surfaces. `[human]` for the aesthetic call.
|
||||
same (`color: white` on the accent), so we currently match GNOME.
|
||||
|
||||
**Decided 2026-07-16 (Bernardo): fix the contrast — we hold ourselves higher
|
||||
than GNOME here.** Matching upstream is not a defence when upstream is under
|
||||
even the large-text floor; "everyone ships it" is how 2.7:1 text becomes
|
||||
normal. Two shapes to pick between while building: darken the *label* (the
|
||||
label is ours; the accent is the user's palette and the thing they chose the
|
||||
theme for), or darken the *accent mix* under the label in light palettes only.
|
||||
Prefer the first unless it looks wrong — it leaves the palette alone.
|
||||
Note `tools/check-theme-contrast.py` covers palette pairings only, never GTK
|
||||
widget surfaces, so whatever lands needs its own assertion or it rots exactly
|
||||
like #98 did.
|
||||
|
||||
### 143. Rofi keeps the selected *row number* when the search changes, so the highlight lands on an unrelated entry
|
||||
|
||||
@@ -199,17 +250,79 @@ sent: the scoping call is the maintainer's, since keeping the index across a
|
||||
*reload* looks deliberate (#1064 asked for exactly that, and got it in 1.7.4).
|
||||
No duplicate found before filing.
|
||||
|
||||
**Options.** (a) Wait for upstream — done, now their move. (b) Carry the patch
|
||||
ourselves in an overlay — a few lines, but it means **building rofi from source
|
||||
on every user's machine**: our derivations are in no binary cache (#120's
|
||||
gotcha), so this trades a real install/rebuild cost for it. (c) Live with it
|
||||
and say nothing — the status quo, and the reason Bernardo hit it cold.
|
||||
Recommend (a) + (b) together if the patch stays small: file it upstream, carry
|
||||
it until it lands, delete on the release that fixes it. `[human]` for whether
|
||||
a source-built rofi is a price worth paying.
|
||||
**Decided 2026-07-16 (Bernardo): wait for upstream. Do not carry a patch.** The
|
||||
overlay option was real but priced badly — our derivations are in no binary
|
||||
cache, so a patched rofi means **every machine compiles rofi from source**, on
|
||||
every lock bump, to fix a highlight. That is a permanent, distro-wide install
|
||||
cost for an annoyance with a free workaround (glance before you press Enter).
|
||||
**This item is now a watch, not work:** the only thing to do is check
|
||||
rofi#2317, and take the fix when a release carries it. If it is still open at
|
||||
the next lock bump, that is fine — nothing here rots meanwhile.
|
||||
|
||||
|
||||
## LATER
|
||||
|
||||
- **DPMS when docked (revisit #127):** today we **skip** display blanking
|
||||
while any laptop internal is present-but-disabled (dock/clamshell), so
|
||||
idle only locks. That avoids blanking the sole external and the brick
|
||||
where wake/TTY failed (2026-07-15). Revisit when we want monitor
|
||||
power-save on dock again: re-enable DPMS-off for that mode only if
|
||||
`nomarchy-display-wake` (or better) reliably restores the external and
|
||||
undock-while-black restores eDP on the AMD dock setup — without
|
||||
depending on SSH. Until then, leave the skip in `modules/home/idle.nix`.
|
||||
- **Wallpapers artifact split** (ROADMAP § Faster switches — decided,
|
||||
deferred): pinned `Nomarchy-wallpapers` input so a state write stops
|
||||
re-copying 86 MB. Follow-on: pre-built theme variants if switches are
|
||||
still slow after.
|
||||
- **Installer round 2** (ROADMAP § Installer): multi-disk BTRFS RAID,
|
||||
impermanence, BIOS/legacy boot.
|
||||
- **Boot-from-snapshot**: a systemd-boot equivalent of grub-btrfs.
|
||||
- **MIPI/IPU software-ISP camera** support (no-UVC machines).
|
||||
- **NixOS release bump → v2** `[human]`: deliberate, hand-edited, never
|
||||
automated; the previous attempt was discarded (2026-06-22) over a
|
||||
Hyprland OOM blocker — see MEMORY.md before retrying.
|
||||
|
||||
## FUTURE (decided deferred — not the agent queue head)
|
||||
|
||||
Work we **intend** someday but explicitly **not** NEXT. Agents do not
|
||||
pick these unless Bernardo promotes one into NEXT/NOW.
|
||||
|
||||
### 20. KVM runner → VM suite in CI `[human]`
|
||||
**Status (2026-07-10):** keep **eval-only** CI on the current Gitea
|
||||
stack (act_runner in docker-compose on the 4c/4 GB IONOS VPS). Nested
|
||||
KVM + RAM headroom on that host are a poor fit next to Gitea; full
|
||||
`checks.*` VMs stay local / promotion-time until a **separate**
|
||||
KVM-capable machine exists.
|
||||
|
||||
**When ready:** register a second runner (host-mode nix + `/dev/kvm`,
|
||||
label `nix-kvm` — not the existing docker eval runner), then uncomment
|
||||
the `vm-checks` job in `.gitea/workflows/check.yml` (`runs-on: nix-kvm`,
|
||||
`nix flake check` + toplevel/HM builds). Do not enable the job until
|
||||
that label is online (Gitea queues forever otherwise).
|
||||
|
||||
### Formatter — adopt later `[human]`
|
||||
**Intent:** add a Nix formatter (likely `nixfmt-rfc-style`) in a dedicated
|
||||
pass: reformat the tree once, document in CONVENTIONS, optional CI
|
||||
check. **Not** the queue head — no drive-by reformats until that pass.
|
||||
|
||||
## PROPOSED (agent suggestions — await human triage)
|
||||
|
||||
*Agents: append here with a one-paragraph pitch (what/why/cost). Do not
|
||||
implement. Bernardo moves accepted items into a tier.*
|
||||
|
||||
*Open work only. Shipped exam/A–C items (#47–#63, #14, #52 theme
|
||||
high-ROI, etc.) live in the journal + ROADMAP — not here.*
|
||||
|
||||
### Product / day-2
|
||||
|
||||
### 120. A netinstall ISO, next to the fat offline one
|
||||
|
||||
**Deferred to PROPOSED 2026-07-16 (Bernardo): not now.** Nothing below is
|
||||
stale — the measurements stand and the decision it needs is unchanged. It sits
|
||||
here because it is the only genuinely large item left, and because the gotcha
|
||||
at the bottom (no binary cache for our own derivations) probably makes a
|
||||
cachix the real first step, not the ISO.
|
||||
|
||||
Bernardo 2026-07-14, after seeing the measured size: **keep the current ISO
|
||||
exactly as it is** — the guaranteed offline install is the feature it buys —
|
||||
and ship a **much lighter netinstall variant alongside it**. Two products, one
|
||||
@@ -268,62 +381,6 @@ Pass = a second, documented ISO target that is *substantially* smaller (state
|
||||
the measured number, both ISOs built from one tree), installs successfully with
|
||||
a network in a QEMU run, says clearly at boot that it needs one, and leaves the
|
||||
offline ISO's behaviour untouched (`checks.*` for the offline path stay green).
|
||||
|
||||
## LATER
|
||||
|
||||
- **DPMS when docked (revisit #127):** today we **skip** display blanking
|
||||
while any laptop internal is present-but-disabled (dock/clamshell), so
|
||||
idle only locks. That avoids blanking the sole external and the brick
|
||||
where wake/TTY failed (2026-07-15). Revisit when we want monitor
|
||||
power-save on dock again: re-enable DPMS-off for that mode only if
|
||||
`nomarchy-display-wake` (or better) reliably restores the external and
|
||||
undock-while-black restores eDP on the AMD dock setup — without
|
||||
depending on SSH. Until then, leave the skip in `modules/home/idle.nix`.
|
||||
- **Wallpapers artifact split** (ROADMAP § Faster switches — decided,
|
||||
deferred): pinned `Nomarchy-wallpapers` input so a state write stops
|
||||
re-copying 86 MB. Follow-on: pre-built theme variants if switches are
|
||||
still slow after.
|
||||
- **Installer round 2** (ROADMAP § Installer): multi-disk BTRFS RAID,
|
||||
impermanence, BIOS/legacy boot.
|
||||
- **Boot-from-snapshot**: a systemd-boot equivalent of grub-btrfs.
|
||||
- **MIPI/IPU software-ISP camera** support (no-UVC machines).
|
||||
- **NixOS release bump → v2** `[human]`: deliberate, hand-edited, never
|
||||
automated; the previous attempt was discarded (2026-06-22) over a
|
||||
Hyprland OOM blocker — see MEMORY.md before retrying.
|
||||
|
||||
## FUTURE (decided deferred — not the agent queue head)
|
||||
|
||||
Work we **intend** someday but explicitly **not** NEXT. Agents do not
|
||||
pick these unless Bernardo promotes one into NEXT/NOW.
|
||||
|
||||
### 20. KVM runner → VM suite in CI `[human]`
|
||||
**Status (2026-07-10):** keep **eval-only** CI on the current Gitea
|
||||
stack (act_runner in docker-compose on the 4c/4 GB IONOS VPS). Nested
|
||||
KVM + RAM headroom on that host are a poor fit next to Gitea; full
|
||||
`checks.*` VMs stay local / promotion-time until a **separate**
|
||||
KVM-capable machine exists.
|
||||
|
||||
**When ready:** register a second runner (host-mode nix + `/dev/kvm`,
|
||||
label `nix-kvm` — not the existing docker eval runner), then uncomment
|
||||
the `vm-checks` job in `.gitea/workflows/check.yml` (`runs-on: nix-kvm`,
|
||||
`nix flake check` + toplevel/HM builds). Do not enable the job until
|
||||
that label is online (Gitea queues forever otherwise).
|
||||
|
||||
### Formatter — adopt later `[human]`
|
||||
**Intent:** add a Nix formatter (likely `nixfmt-rfc-style`) in a dedicated
|
||||
pass: reformat the tree once, document in CONVENTIONS, optional CI
|
||||
check. **Not** the queue head — no drive-by reformats until that pass.
|
||||
|
||||
## PROPOSED (agent suggestions — await human triage)
|
||||
|
||||
*Agents: append here with a one-paragraph pitch (what/why/cost). Do not
|
||||
implement. Bernardo moves accepted items into a tier.*
|
||||
|
||||
*Open work only. Shipped exam/A–C items (#47–#63, #14, #52 theme
|
||||
high-ROI, etc.) live in the journal + ROADMAP — not here.*
|
||||
|
||||
### Product / day-2
|
||||
|
||||
### 134. `unstable.<pkg>` in the downstream — a newer app without a second flake
|
||||
|
||||
Bernardo 2026-07-15, wanting a newer LM Studio (pinned 0.4.15-2 vs unstable
|
||||
|
||||
Reference in New Issue
Block a user