Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and `merge --ff-only` refuses while tracked paths are dirty. Discard is not available here (workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed. - `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new prose — the commit exists so the trunk merge can proceed. - `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat owns (AGENTS.md § Live-sync tiers). `ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the inert all-zero AWS example id — and they appear inside the two skill pages that teach that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal dies with this landing. No `--no-verify` was used: the gate ran and its verdict is recorded here. Refs #61
4.1 KiB
name, description
| name | description |
|---|---|
| niri-monitor-flap-refresh-triage | Diagnose niri/amdgpu monitor failures on blankpad — panel dropping, wrong refresh rate, black/flickering output — and fix the refresh without reloading the compositor or logging Frank out. |
niri monitor triage: flaps, phantom modes, 60 Hz fallback
Frank's reaction to a broken display is immediate and loud; the fix must never log him out.
Box: blankpad (Cezanne APU, card1, s2idle only), compositor niri --session as a user unit.
Step 1 — separate three different diseases (do this before touching anything)
niri msg outputs # name, mode, position, full mode list per output
for c in /sys/class/drm/card*-*/status; do echo "$(basename $(dirname $c)) $(cat $c)"; done
systemctl --user show niri.service -p ExecMainStartTimestamp -p NRestarts # did niri restart?
journalctl --user -b --no-pager | grep -iE 'disconnecting connector|new connector|Page flip commit failed|DMCUB|falling back to preferred'
journalctl -k -b --no-pager | grep -iE 'amdgpu|PM: suspend exit|\*ERROR\*'
Reading it:
disconnecting connector: "X"thennew connector: X→ link-level drop (cable/dock/monitor/driver). Count them:grep -c 'disconnecting connector'.Page flip commit failed … EINVALbursts + kerneldc_dmub_srv_log_diagnostic_data: DMCUB errorright afterPM: suspend exit→ amdgpu display-engine state broken by s2idle resume. Only a reboot clears it; never reboot without an explicit per-run OK.configured mode M could not be found, falling back to preferred→ config asks for a mode the panel does not offer; the panel silently runs at EDID-preferred (usually 60 Hz). This is the one you can fix instantly.- Config mtimes older than the symptom + no
nirirestart ⇒ the config did not cause it. Say so explicitly; agents get blamed for display problems they didn't cause.
Step 2 — the phantom-mode trap (niri fails soft, so it looks like hardware)
output { mode "…" } with a refresh the EDID never advertised does not error. niri logs a WARN and drops to preferred on every connect → janky 60 Hz ultrawide, blamed on the monitor.
Compare the requested mode against the panel's real list:
niri msg outputs | sed -n '/<monitor name>/,/^$/p' | grep -E '^\s+[0-9]+'
Step 3 — apply the mode WITHOUT a config reload (the no-logout path)
niri msg output "<EDID output name from niri msg outputs>" mode "WxH@refresh"
niri msg outputs | grep -A1 '<monitor>' # confirm the new mode
pgrep -c niri # compositor still alive, same PID
niri msg output … is documented as temporary ("not saved into the config file") — it changes one output and cannot log the session out. Avoid niri action reload-config when Frank is working: it reloads his whole config.
Step 4 — persist, and check you edited the file that is actually live
Live niri config is a symlink chain: ~/.config/niri/config.kdl → cfg/display.kdl → cfg/desk-<profile>.kdl, and cfg/desk-*.kdl are symlinks into the repo:
ls -l ~/.config/niri/cfg/display.kdl # -> desk-1-home.kdl
grep -n '239\|180' ~/.config/niri/cfg/display.kdl # prove YOUR edit is in the live chain
niri validate # parses the live config; touches nothing
dotfiles/ is on the live-sync.sh heartbeat allowlist, so an edited tracked dotfile stays dirty until the hourly heartbeat commits it — that is the designed state, do not commit it on main yourself.
Desk config law (its own header): panels keyed by EDID identity, not connector name — but connector-keyed leftovers (DP-1, DP-2) survive in desk-1-home.kdl, and a reconnect that comes back without an EDID string hits those instead. Align them to the same mode, or a flap silently changes your refresh rate.
Escalate honestly
Reboot clears DMCUB/EINVAL state → schedule it, don't take it. Persistent drops after a reboot → cable / dock / monitor DP-version setting, i.e. hardware, not config. Report which of the three diseases you found and which you did not fix.