fix(monitor): switch monitors off through hyprctl eval and check the reply #15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/dpms-lua-eval"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes MON-14
Problem
apply_monitorsranhyprctl dispatch dpms off <name>for monitors that should be off. Stock Hyprland configured withhyprland.luaparseshyprctl dispatcharguments as Lua, so that fails ("')' expected near 'off'"), and breadmon only checked that the process spawned, so the monitor stayed on with no error.Change
hyprctl eval "hl.dispatch(hl.dsp.dpms({ action = 'off', monitor = '<name>' }))"per monitor (dpms_off_expr, with quote and backslash escaping) and return an error unless the reply isok.hyprland.lua; reworded.Verification
dpmsfieldsactionandmonitorchecked against~/.config/hypr/hyprland-api.lua(dpms fun(opts: { action?: "toggle"|"on"|"off", monitor?: string|integer })). The generated expression form also parses underHyprland --verify-configon a temporary file (no running session touched).cargo fmt --check,cargo clippy --all-targets --locked -- -D warnings,cargo test --locked(29 tests) all pass.No capability removed or narrowed.
Independent review: CHANGES REQUESTED at exact head
056f0b0b29(basefe0e6fb9b7). Read MON-14/MON-15 and all comments/links, complete 2-file diff and exhausted PR/file pagination. No existing reviews/change requests; no branch protections.Criteria: (1) named eval/hl.dsp.dpms action=off and ordinary quote/backslash escaping: source/unit checks pass at src/monitor.rs:392-422; action/monitor fields match the local upstream API stub. (2) failure detection: FAIL. Independent Rust harness imports immutable monitor.rs and substitutes fake hyprctl: ok/exit0 -> Ok; Lua refusal/exit0 -> Err with message; ok/exit7 -> Ok, which wrongly lets main.rs:205-225 emit success and persist configuration. stderr/status are discarded. Tracked as MON-16 (high confidence). (3) actual isolated DPMS off and monitor targeting: UNVERIFIED. No hidden nested compositor exists locally; documented setup requires live compositor operations prohibited by this task. No live desktop/monitor commands executed.
Required repair checklist:
Independent cargo test --locked: 29/29 pass; cargo fmt --check and cargo clippy --all-targets --locked -- -D warnings pass. Exact-head check / check (push) success, Actions run57 at this SHA success. Authenticated read-only review API returned []. A later credential-read command was flagged for human review; not retried. Existing green CI lacks process-level failure regression coverage. Preserve PR15 and branch; move MON-14 to todo for repair, not done. Merge not performed despite authorization because acceptance fails. Worktree ~/.worktrees/breadmon/fix/dpms-lua-eval preserved; reproduction /tmp/opencode/review-lua/mon-harness.rs.
Independent exact-head review: CHANGES REQUESTED. SHA
056f0b0b29; basefe0e6fb9b7. Complete 2-file diff reviewed; PR/file pagination exhausted; MON-14/MON-15 links/comments read. No prior reviews/change requests or branch protections.Criteria: eval DPMS named targeting and quote/backslash escaping source/unit checks pass (src/monitor.rs:392-422); fields match upstream API stub. Failure detection FAILS: exact-module fake-process harness returns Ok for stdout ok with exit7. Refusal text with exit0 correctly returns Err. stderr and status are discarded. Defect filed MON-16, high confidence. Real isolated DPMS state and targeting UNVERIFIED; only live compositor exists locally and documented nested setup requires prohibited live operations. No live Hyprland or monitors touched.
Repair checklist:
Independent cargo test --locked: 29 pass; cargo fmt --check and cargo clippy --all-targets --locked -- -D warnings pass. Exact-head check / check (push) and Actions run57 success. Authenticated read-only reviews API returned []; later credential access flagged and not retried. Green CI has no process-level failure coverage. Preserve PR/branch, move MON-14 todo for repair. No merge despite authorization: acceptance fails. Worktree ~/.worktrees/breadmon/fix/dpms-lua-eval and harness /tmp/opencode/review-lua/mon-harness.rs preserved.
hyprctl dispatch dpms off, which fails when Hyprland is configured with hyprland.lua #14CHANGES REQUESTED at
056f0b0b29. Criterion mapping, commands, src/monitor.rs:398-401 repair requests and runtime blocker: #15 (comment) . MON-16 tracks reproduced failure-status defect. Preserve PR/branch; no merge.Review repair for the MON-14 review (MON-16), new head
63bd598c36.Changes in src/monitor.rs:
hyprctl evalcall sites (the monitor batch and each DPMS-off expression) now go through one helper. It succeeds only when the process exits 0 and the trimmed stdout is exactlyok.hyprctlscript in a temp dir (no live compositor): ok/exit 0 succeeds, surrounding whitespace is trimmed, refusal/exit 0 errors, ok/exit 7 errors, empty output errors, and a missing binary errors.Checks:
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warningsandcargo test --workspace(35 passed) all pass. These ran directly on the host with the dev-deps step from check.yml applied. Theci/build.shDocker wrapper could not run here because the Docker daemon is not running on this host, so the container build step is still unverified.VM compositor evidence at
63bd598c(coordinator)Isolated BOS test VM, headless TEST-1 created inside the guest. Transcript: /tmp/opencode/vm-hypr/evidence-MON-14.md on hermes.
hl.dispatch(hl.dsp.dpms({ action = 'off', monitor = 'NOPE-9' }))replies ok and turns off ALL outputs, so the exact-ok check passes. On a real desktop a mistyped or unplugged name blanks the whole session. Validate the name againsthyprctl monitors -j(orhlmonitor lookup) before dispatching and return an error if it is not present.apply_monitorshas no DPMS-on path:dpms_on=truereturns Ok and leaves the monitor off. Either implement on or document that the caller must restore.Fix: check the monitor name before DPMS, add DPMS on (head
031e0ff)MON-14 review: unknown monitor names blank every output. The fix is in
src/monitor.rsonly.apply_monitorsreadshyprctl monitors all -jfirst. It checks the exit status and the JSON parse. A name that is not in the list returns an error, and no dpms dispatch is sent.dpms=truethat Hyprland reports as off getshl.dsp.dpms({ action = 'on', monitor = ... }). Monitors already in the requested state get no dispatch, so a plain apply no longer sendsonto every output.dpms_expr(action, name)replacesdpms_off_expr, with the same escaping.hyprctlrecording its argv): unknown name is an error with no dpms or monitor eval dispatched; off dispatches for the target only; restore from off dispatchesonfor the target only; already-on dispatches nothing; query failure (exit 3, or valid JSON with non-zero exit) stops before any dispatch.Checks (
--locked):cargo fmt --checkclean,cargo clippy --workspace --all-targets -- -D warningsclean,cargo test --workspace42 passed.VM read-back (Hyprland 0.56.2, hyprland.lua, headless TEST-1 created in the guest):
TEST-1 removed afterwards (
[('Virtual-1', True)]). Harness was a scratch copy of the branch'ssrc/monitor.rs, driving the realapply_monitors. The TUIakey path was not run.Fixed the run 59 flake (
known_monitor_off_dispatches_dpms_off_for_that_name_only: ETXTBSY spawning fake hyprctl).Root cause is not a shared path. I reproduced it locally with plain
std::process::Command: exec of a freshly-written script fails with ETXTBSY ~1-8% of spawns when other threads concurrently write scripts, even with unique closed paths (single-threaded: 0/3000; pre-created scripts under identical concurrency: 0/9600+). So the old per-test write-then-exec plus per-module locks could not fix it.Fix (
5436297,src/monitor.rsonly): all 11 fake-hyprctl scripts are created once under a process-wideOnceLockbefore any test spawns; tests then only exec, append to their per-test eval log, and clean up. Dirs stay unique per process (pid + start time + ASLR address) so concurrent CI jobs sharing /tmp cannot collide. Scripts are still written via dotfile + rename.Proof:
cargo test --workspaceand--lockedpass (42/42); test binary with--test-threads=16passes 40/40 consecutive runs with zero ETXTBSY;cargo fmt --checkandcargo clippy --workspace --all-targets -- -D warningsclean.Independent exact-head review: PASS. Reviewed SHA
543629730c, basefe0e6fb9b7. Complete diff reviewed (README.md +4/-4, src/monitor.rs +418/-38); PR/file pagination exhausted; MON-14/MON-16 and all comments read. No outstanding reviews; check.yml is the only workflow.Criterion mapping:
031e0ff(production code identical at this head, 031e0ff..5436297 is test-harness only): NOPE-9 rc=1 with both monitors on.Independent checks in scratch worktree ~/.worktrees/breadmon/review-mon14-5436297 (primary checkout untouched): cargo fmt --check clean; cargo clippy --workspace --all-targets --locked -- -D warnings clean; cargo test --locked --workspace 42 passed. Required check check / check (push) success at exact head (Actions run 60). No live desktop touched; VM evidence is coordinator-supplied transcript plus comment 4505 read-back.
Merged
42e11c6b21under merge authorization. MON-14/MON-16 left in review for coordinator verification, not done.hyprctl dispatch dpms off, which fails when Hyprland is configured with hyprland.lua #14