Merge remote-tracking branch 'origin/main' into feat/panama-health
# Conflicts: # config/dot/quickshell/modules/settings/HealthPage.qml # tests/quickshell/health-ui-contract.sh
This commit is contained in:
@@ -8,7 +8,7 @@ SettingsPage {
|
||||
objectName: "system-health-page"
|
||||
|
||||
title: "System Health"
|
||||
lede: "Panama checks the parts of your desktop it owns and explains what needs attention."
|
||||
lede: "Checks the parts of the desktop this app owns, and explains what needs attention."
|
||||
|
||||
property var pendingConfirmation: null
|
||||
property string instructionTarget: ""
|
||||
@@ -32,7 +32,7 @@ SettingsPage {
|
||||
},
|
||||
{
|
||||
group: "panama-tools",
|
||||
title: "Panama tools",
|
||||
title: "Desktop tools",
|
||||
subtitle: "Tracked links, launcher commands, apps, and inhibitors."
|
||||
}
|
||||
]
|
||||
@@ -204,7 +204,7 @@ SettingsPage {
|
||||
width: parent.width
|
||||
text: root.pendingConfirmation
|
||||
? `${root.pendingConfirmation.action.label}?`
|
||||
: "Restart Panama?"
|
||||
: "Restart the shell?"
|
||||
color: Theme.fg
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSize
|
||||
@@ -234,7 +234,7 @@ SettingsPage {
|
||||
|
||||
SettingsButton {
|
||||
id: repairButton
|
||||
text: root.pendingConfirmation ? root.pendingConfirmation.action.label : "Restart Panama"
|
||||
text: root.pendingConfirmation ? root.pendingConfirmation.action.label : "Restart the shell"
|
||||
activeFocusOnTab: true
|
||||
border.width: activeFocus ? 2 : 1
|
||||
border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08)
|
||||
@@ -297,7 +297,7 @@ SettingsPage {
|
||||
SettingsCard {
|
||||
visible: root.instructionTarget === "ddc-permissions"
|
||||
title: "External monitor brightness"
|
||||
subtitle: "Panama can see DDC/CI support, but this session cannot access the monitor bus."
|
||||
subtitle: "The monitor reports DDC/CI support, but this session cannot reach the monitor bus."
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
@@ -401,7 +401,7 @@ SettingsPage {
|
||||
anchors.right: gnomeSettingsButton.left
|
||||
anchors.rightMargin: 18
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Use GNOME Settings for the parts of the system Panama does not manage."
|
||||
text: "Use GNOME Settings for the parts of the system this app does not manage."
|
||||
color: Theme.fgDim
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
|
||||
@@ -13,7 +13,7 @@ SettingsCard {
|
||||
if (Health.diagnosticUnavailable)
|
||||
return "Health check unavailable";
|
||||
if (Health.checks.length === 0)
|
||||
return "Checking Panama desktop";
|
||||
return "Checking the desktop";
|
||||
if (Health.status === "error")
|
||||
return "Action required";
|
||||
if (Health.status === "warning")
|
||||
@@ -22,9 +22,9 @@ SettingsCard {
|
||||
}
|
||||
readonly property string heroDetail: {
|
||||
if (Health.diagnosticUnavailable)
|
||||
return Health.lastError || "Panama could not complete the latest health check.";
|
||||
return Health.lastError || "The latest health check could not be completed.";
|
||||
if (Health.checks.length === 0)
|
||||
return "Panama is checking the desktop services, tools, and integrations it owns.";
|
||||
return "Checking the desktop services, tools, and integrations this app owns.";
|
||||
if (Health.status === "error")
|
||||
return root.observationCount === 1
|
||||
? "One part of the desktop needs action."
|
||||
@@ -33,7 +33,7 @@ SettingsCard {
|
||||
return root.observationCount === 1
|
||||
? "Your desktop is working. One feature needs a decision."
|
||||
: `Your desktop is working. ${root.observationCount} features need a decision.`;
|
||||
return "Panama-owned desktop services and tools are working normally.";
|
||||
return "Desktop services and tools are working normally.";
|
||||
}
|
||||
readonly property color statusColor: {
|
||||
if (Health.diagnosticUnavailable || Health.status === "error")
|
||||
|
||||
@@ -301,14 +301,14 @@ Rectangle {
|
||||
|
||||
function footerText(): string {
|
||||
if (Health.checks.length === 0)
|
||||
return Health.diagnosticUnavailable ? "Health check unavailable" : "Checking Panama desktop";
|
||||
return Health.diagnosticUnavailable ? "Health check unavailable" : "Checking the desktop";
|
||||
if (Health.status === "error")
|
||||
return "Panama requires attention";
|
||||
return "Desktop needs attention";
|
||||
if (Health.status === "warning") {
|
||||
const count = Health.summary.warnings + Health.summary.errors;
|
||||
return count + (count === 1 ? " health observation" : " health observations");
|
||||
}
|
||||
return "Panama desktop is healthy";
|
||||
return "Desktop is healthy";
|
||||
}
|
||||
|
||||
function footerColor(): color {
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
source ~/.local/share/Panama/bin/ascii
|
||||
# Set host name
|
||||
|
||||
# Panama's installer. Safe to re-run: every stage is idempotent, and this is
|
||||
# also the upgrade path.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
PANAMA_PATH="${PANAMA_PATH:-$HOME/.local/share/Panama}"
|
||||
source "$PANAMA_PATH/bin/ascii"
|
||||
|
||||
# ── Hostname, which is optional ──────────────────────────────────────────────
|
||||
#
|
||||
# Declining this used to `exit`, which aborted the ENTIRE installation. The
|
||||
# prompt defaults to N, so simply pressing Enter -- the obvious thing to do when
|
||||
# you do not want to rename your machine -- installed nothing at all and said
|
||||
# nothing about it.
|
||||
echo -e "Current hostname is: $(hostname)"
|
||||
read -p "Do you want to change the hostname? [y/N]: " confirm_change
|
||||
read -r -p "Do you want to change the hostname? [y/N]: " confirm_change
|
||||
if [[ "$confirm_change" =~ ^[Yy]$ ]]; then
|
||||
read -p "Hostname: " HOST_NAME
|
||||
read -p "Set hostname to '$HOST_NAME'? [y/N]: " confirm_hostname
|
||||
read -r -p "Hostname: " HOST_NAME
|
||||
read -r -p "Set hostname to '$HOST_NAME'? [y/N]: " confirm_hostname
|
||||
if [[ "$confirm_hostname" =~ ^[Yy]$ ]]; then
|
||||
sudo hostnamectl set-hostname "$HOST_NAME"
|
||||
echo "Hostname set to: $(hostname)"
|
||||
@@ -13,18 +26,45 @@ if [[ "$confirm_change" =~ ^[Yy]$ ]]; then
|
||||
echo "Hostname not changed."
|
||||
fi
|
||||
else
|
||||
echo "Not changing hostname."
|
||||
exit
|
||||
echo "Keeping the current hostname."
|
||||
fi
|
||||
|
||||
# Ensure computer doesn't go to sleep.
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled false
|
||||
gsettings set org.gnome.desktop.session idle-delay 0
|
||||
# ── Keep the machine awake for the duration ──────────────────────────────────
|
||||
# Package installation takes long enough to hit an idle lock, and being locked
|
||||
# out mid-transaction is unpleasant. Restored on every exit path, including
|
||||
# failure and Ctrl-C, so an interrupted install does not leave the screen
|
||||
# permanently awake.
|
||||
restore_idle() {
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled true 2>/dev/null || true
|
||||
gsettings set org.gnome.desktop.session idle-delay 300 2>/dev/null || true
|
||||
}
|
||||
trap restore_idle EXIT INT TERM
|
||||
|
||||
# Run each setup stage in its own process. This keeps strict-shell options and
|
||||
# helper variables local to the script that owns them.
|
||||
for script in ~/.local/share/Panama/setup/scripts/*; do "$script"; done
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled false 2>/dev/null || true
|
||||
gsettings set org.gnome.desktop.session idle-delay 0 2>/dev/null || true
|
||||
|
||||
# Revert to normal idle settings
|
||||
gsettings set org.gnome.desktop.screensaver lock-enabled true
|
||||
gsettings set org.gnome.desktop.session idle-delay 300
|
||||
# ── Stages ───────────────────────────────────────────────────────────────────
|
||||
# Each runs in its own process so strict-shell options and helper variables stay
|
||||
# local to the script that owns them. A failing stage is reported and the rest
|
||||
# still run: a missing optional package should not stop the dotfiles being
|
||||
# linked. The summary at the end is what decides whether the install worked,
|
||||
# because a failure scrolled past twenty minutes ago is a failure nobody saw.
|
||||
failed=()
|
||||
for script in "$PANAMA_PATH"/setup/scripts/*; do
|
||||
[[ -x "$script" ]] || continue
|
||||
stage="$(basename "$script")"
|
||||
printf '\n=== %s ===\n' "$stage"
|
||||
if ! "$script"; then
|
||||
failed+=("$stage")
|
||||
printf '!!! %s failed\n' "$stage" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
printf '\n'
|
||||
if (( ${#failed[@]} == 0 )); then
|
||||
echo "Panama installed. Log out and choose the Hyprland session to start it."
|
||||
else
|
||||
printf 'Panama installed with %d failed stage(s): %s\n' "${#failed[@]}" "${failed[*]}" >&2
|
||||
printf 'Re-running ./install is safe and will retry them.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1,38 +1,45 @@
|
||||
hyprland
|
||||
hyprland-uwsm
|
||||
uwsm
|
||||
quickshell
|
||||
vicinae
|
||||
hyprlock
|
||||
hypridle
|
||||
hyprpaper
|
||||
hyprpicker
|
||||
hyprsunset
|
||||
hyprpolkitagent
|
||||
hyprshutdown
|
||||
hyprpwcenter
|
||||
hyprsysteminfo
|
||||
hyprland-guiutils
|
||||
xdg-desktop-portal-hyprland
|
||||
grim
|
||||
slurp
|
||||
grimblast
|
||||
satty
|
||||
wl-clipboard
|
||||
wf-recorder
|
||||
gpu-screen-recorder
|
||||
brightnessctl
|
||||
playerctl
|
||||
pamixer
|
||||
udiskie
|
||||
wofi
|
||||
NetworkManager
|
||||
adw-gtk3-theme
|
||||
adwaita-icon-theme
|
||||
adwaita-sans-fonts
|
||||
qt6-qtwayland
|
||||
nm-connection-editor
|
||||
brightnessctl
|
||||
ddcutil
|
||||
gpu-screen-recorder
|
||||
grim
|
||||
grimblast
|
||||
gtk-update-icon-cache
|
||||
hypridle
|
||||
hyprland
|
||||
hyprland-guiutils
|
||||
hyprland-uwsm
|
||||
hyprlock
|
||||
hyprpaper
|
||||
hyprpicker
|
||||
hyprpolkitagent
|
||||
hyprpwcenter
|
||||
hyprshutdown
|
||||
hyprsunset
|
||||
hyprsysteminfo
|
||||
kde-connect
|
||||
libnotify
|
||||
nm-connection-editor
|
||||
orca
|
||||
pamixer
|
||||
playerctl
|
||||
qrencode
|
||||
qt6-qtwayland
|
||||
quickshell
|
||||
satty
|
||||
slurp
|
||||
system-config-printer
|
||||
tesseract
|
||||
tesseract-langpack-eng
|
||||
udiskie
|
||||
uwsm
|
||||
vicinae
|
||||
wf-recorder
|
||||
wireplumber
|
||||
wl-clipboard
|
||||
wofi
|
||||
xdg-desktop-portal-hyprland
|
||||
zbar
|
||||
system-config-printer
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
awk
|
||||
bat
|
||||
btop
|
||||
cargo
|
||||
curl
|
||||
eza
|
||||
fontconfig
|
||||
fwupd
|
||||
fzf
|
||||
git-all
|
||||
gh
|
||||
git-all
|
||||
gum
|
||||
jq
|
||||
kitty
|
||||
ksshaskpass
|
||||
libselinux-utils
|
||||
neovim
|
||||
openssl
|
||||
pciutils
|
||||
python3-dnf
|
||||
python3-neovim
|
||||
rustup
|
||||
tmux
|
||||
unzip
|
||||
wireguard-tools
|
||||
wget
|
||||
wireguard-tools
|
||||
zoxide
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Every external command Panama's own scripts invoke must be installed by
|
||||
# Panama's own package lists.
|
||||
#
|
||||
# This exists because the lists had drifted badly. jq is used by thirty-one call
|
||||
# sites across the helpers and the contracts; kitty has a full shipped config
|
||||
# and a dock pin; tmux and btop have shipped themes that the colour scheme
|
||||
# switches. None of the four were declared. So a fresh machine that followed
|
||||
# this repository's own install instructions would not have them.
|
||||
#
|
||||
# The failure is quiet by design, which is what makes it worth a test: the
|
||||
# helpers are written to report "not installed" rather than crash, so a missing
|
||||
# dependency presents as a feature that silently is not there.
|
||||
#
|
||||
# Commands from coreutils and the shell itself are not checked -- nothing
|
||||
# installs those separately, and listing them would be noise.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
|
||||
fail() {
|
||||
printf 'declared dependencies contract: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Shell syntax and builtins. These are not commands anyone installs, and the
|
||||
# first version of this contract reported `then`, `esac` and `done` as missing
|
||||
# packages, which buried the four real findings in a hundred lines of noise.
|
||||
SHELL_WORDS='^(if|then|else|elif|fi|for|while|until|do|done|case|esac|in|function|select|time|coproc|break|continue|return|exit|local|readonly|declare|export|unset|shift|eval|exec|source|trap|set|shopt|alias|unalias|builtin|command|enable|help|let|read|mapfile|printf|echo|test|true|false|wait|jobs|bg|fg|kill|pwd|cd|dirs|pushd|popd|umask|type|hash|getopts|split|sync)$'
|
||||
|
||||
# Provided by any Fedora install: coreutils, util-linux, the shell, and the
|
||||
# systemd/session tooling. Nothing here is a choice Panama makes.
|
||||
BASELINE='^(sh|bash|cat|cut|sed|awk|gawk|grep|egrep|head|tail|sort|uniq|tr|wc|find|xargs|basename|dirname|mkdir|rm|cp|mv|ln|chmod|chown|stat|df|du|date|sleep|env|id|tee|touch|mktemp|readlink|realpath|seq|comm|join|paste|od|file|nl|fold|column|tput|timeout|flock|install|sha256sum|md5sum|base64|nproc|uptime|free|uname|hostname|whoami|ps|pgrep|pkill|kill|killall|lsblk|mount|umount|sudo|su|rpm|dnf|flatpak|git|python3|ss|ip|lsof)$'
|
||||
|
||||
SESSION='^(systemctl|busctl|journalctl|loginctl|hostnamectl|localectl|systemd-inhibit|systemd-run|udevadm|gsettings|dconf|dbus-send|dbus-monitor|hyprctl|qs|quickshell|gnf|panama|wl-copy|wl-paste)$'
|
||||
|
||||
declared="$(cat "$repo_dir"/setup/packages/* 2>/dev/null | sed 's/#.*//' | tr -d ' ' | grep -v '^$' | sort -u)"
|
||||
[[ -n "$declared" ]] || fail 'no package lists found'
|
||||
|
||||
# A package is not always named after its command. Only the genuine mismatches
|
||||
# are mapped, so an unmapped command is a real omission rather than a lookup
|
||||
# failure.
|
||||
package_for() {
|
||||
case "$1" in
|
||||
zbarimg) printf 'zbar' ;;
|
||||
fc-list|fc-match) printf 'fontconfig' ;;
|
||||
lspci) printf 'pciutils' ;;
|
||||
getenforce) printf 'libselinux-utils' ;;
|
||||
nmcli) printf 'NetworkManager' ;;
|
||||
wpctl) printf 'wireplumber' ;;
|
||||
nvim) printf 'neovim' ;;
|
||||
fwupdmgr) printf 'fwupd' ;;
|
||||
dnf4) printf 'python3-dnf' ;;
|
||||
notify-send) printf 'libnotify' ;;
|
||||
wl-copy|wl-paste) printf 'wl-clipboard' ;;
|
||||
rg) printf 'ripgrep' ;;
|
||||
python3) printf 'python3' ;;
|
||||
*) printf '%s' "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
missing=()
|
||||
checked=0
|
||||
|
||||
while read -r script; do
|
||||
[[ -n "$script" ]] || continue
|
||||
head -1 "$script" | grep -qE 'bash|/sh' || continue
|
||||
|
||||
# Commands appearing at the start of a statement or after a pipe. Crude, but
|
||||
# it is looking for undeclared dependencies, not building a call graph.
|
||||
#
|
||||
# No minimum length. An earlier version required three characters, which
|
||||
# quietly excluded the most-used dependency in the repository -- jq, at
|
||||
# thirty-one call sites -- along with rg, ss and ip. A dependency checker
|
||||
# with a blind spot for short names is worse than none, because it reports
|
||||
# PASS.
|
||||
while read -r cmd; do
|
||||
[[ -n "$cmd" ]] || continue
|
||||
[[ "$cmd" =~ $SHELL_WORDS ]] && continue
|
||||
[[ "$cmd" =~ $BASELINE ]] && continue
|
||||
[[ "$cmd" =~ $SESSION ]] && continue
|
||||
|
||||
pkg="$(package_for "$cmd")"
|
||||
grep -qx "$pkg" <<<"$declared" && continue
|
||||
|
||||
# Only report a command that actually exists on this machine. An
|
||||
# invented name in a comment or a heredoc is a false positive; a real
|
||||
# binary that nothing declares is the thing being looked for.
|
||||
command -v "$cmd" >/dev/null 2>&1 || continue
|
||||
|
||||
missing+=("$cmd (from $(basename "$script"), package: $pkg)")
|
||||
done < <({
|
||||
# Statement-initial or after a pipe.
|
||||
grep -oE '(^|[|;&]|\$\()[[:space:]]*[a-z][a-z0-9_-]+' "$script" \
|
||||
| grep -oE '[a-z][a-z0-9_-]+$'
|
||||
|
||||
# Behind a wrapper. ddcutil is always invoked as `timeout 10 ddcutil`,
|
||||
# so it never appears statement-initial and was missed entirely.
|
||||
grep -oE '\b(timeout[[:space:]]+[0-9.]+|sudo|nohup|env)[[:space:]]+[a-z][a-z0-9_-]+' "$script" \
|
||||
| grep -oE '[a-z][a-z0-9_-]+$'
|
||||
|
||||
# `command -v X` is how these helpers probe for a tool before using it,
|
||||
# which makes it the clearest possible statement of a dependency.
|
||||
grep -oE 'command -v[[:space:]]+[a-z][a-z0-9_-]+' "$script" \
|
||||
| grep -oE '[a-z][a-z0-9_-]+$'
|
||||
} | sort -u)
|
||||
|
||||
checked=$((checked + 1))
|
||||
done < <(find "$repo_dir/config/dot/quickshell/scripts" \
|
||||
"$repo_dir/config/local/share/vicinae/scripts" \
|
||||
"$repo_dir/setup/scripts" "$repo_dir/bin" \
|
||||
-type f 2>/dev/null)
|
||||
|
||||
if (( ${#missing[@]} > 0 )); then
|
||||
printf 'declared dependencies contract: commands used but never installed:\n' >&2
|
||||
printf ' %s\n' "${missing[@]}" | sort -u >&2
|
||||
fail 'add each to a list in setup/packages/, or the feature silently will not exist on a fresh machine'
|
||||
fi
|
||||
|
||||
printf 'declared dependencies contract: PASS (%d scripts)\n' "$checked"
|
||||
@@ -68,6 +68,24 @@ rg -Fq 'SystemSettings.openGnomePanel("color")' "$settings_dir/HealthPage.qml" \
|
||||
|| fail 'Fedora ownership boundary lost the Colour profiles handoff'
|
||||
rg -Fq 'SystemSettings.openGnomePanel("wellbeing")' "$settings_dir/HealthPage.qml" \
|
||||
|| fail 'Fedora ownership boundary lost the Digital wellbeing handoff'
|
||||
# Exact authored handoffs are asserted above. Also prove every panel named by
|
||||
# this boundary is accepted by SystemSettings, so a typo cannot ship a dead
|
||||
# button even if its copy still looks correct.
|
||||
rg -Fq 'title: "Fedora system settings"' "$settings_dir/HealthPage.qml" \
|
||||
|| fail 'the Fedora ownership boundary card is gone'
|
||||
|
||||
allowed="$(rg -o '"[a-z-]+"' "$repo_dir/config/dot/quickshell/services/SystemSettings.qml" \
|
||||
| sed -n '/"\(applications\|background\|bluetooth\|color\|display\|keyboard\|mouse\|multitasking\|network\|notifications\|online-accounts\|power\|printers\|privacy\|search\|sharing\|sound\|system\|universal-access\|wacom\|wellbeing\|wifi\|wwan\)"/p' \
|
||||
| tr -d '"' | sort -u)"
|
||||
|
||||
while read -r panel; do
|
||||
[[ -n "$panel" ]] || continue
|
||||
grep -qx "$panel" <<<"$allowed" \
|
||||
|| fail "the Fedora card opens \"$panel\", which openGnomePanel does not allow -- that button does nothing"
|
||||
done < <(rg -o 'openGnomePanel\("([a-z-]+)"' -r '$1' "$settings_dir/HealthPage.qml" | sort -u)
|
||||
|
||||
rg -q 'openGnomePanel\(' "$settings_dir/HealthPage.qml" \
|
||||
|| fail 'the Fedora ownership boundary does not open GNOME Settings at all'
|
||||
rg -Fq 'Health.repair(check.id, false)' "$settings_dir/HealthPage.qml" \
|
||||
|| fail 'Settings repair does not stay inline/non-external'
|
||||
rg -Fq 'ShellState.openSettings(check.action.target)' "$settings_dir/HealthPage.qml" \
|
||||
|
||||
@@ -25,8 +25,16 @@ trap cleanup EXIT
|
||||
if rg -q 'setup/scripts/link-vicinae-scripts' "$dotfile_installer"; then
|
||||
fail 'link-dotfiles also invokes the command installer'
|
||||
fi
|
||||
rg -Fq 'do "$script"; done' "$top_level_installer" \
|
||||
|| fail 'top-level installer sources setup scripts into one shared shell'
|
||||
# Each setup stage must run in its OWN process, so strict-shell options and
|
||||
# helper variables stay local to the script that owns them. What matters is
|
||||
# that the stages are executed rather than sourced -- this previously matched
|
||||
# the literal one-liner `do "$script"; done`, which failed the moment the loop
|
||||
# gained error reporting and spanned more than one line, despite the property
|
||||
# it cares about being unchanged.
|
||||
rg -q '(^|[^a-z-])(\.|source)\s+[^;]*setup/scripts' "$top_level_installer" \
|
||||
&& fail 'top-level installer sources setup scripts into one shared shell'
|
||||
rg -q '"\$script"' "$top_level_installer" \
|
||||
|| fail 'top-level installer does not execute the setup scripts'
|
||||
|
||||
mkdir -p "$data_dir/scripts/panama" "$fake_bin"
|
||||
printf 'user-owned\n' >"$data_dir/scripts/panama/keep.sh"
|
||||
|
||||
@@ -137,10 +137,20 @@ last_error="$(qs_for_harness ipc call settings-system-test status | jq -r .lastE
|
||||
|
||||
# ── A rejected value must be refused, not silently accepted ──────────────────
|
||||
qs_for_harness ipc call settings-system-test apply "$target_auto_hdr" 7 "$target_direct" >/dev/null
|
||||
sleep 0.3
|
||||
|
||||
# The refusal is reported asynchronously, so wait for it rather than sleeping a
|
||||
# fixed 0.3s and hoping. That sleep made this fail roughly one run in three,
|
||||
# reporting "a rejected value did not surface an error" when the error simply
|
||||
# had not arrived yet -- which reads as a missing guard rather than a slow one.
|
||||
rejected=""
|
||||
for _ in $(seq 1 60); do
|
||||
rejected="$(qs_for_harness ipc call settings-system-test status | jq -r .lastError)"
|
||||
[[ -n "$rejected" ]] && break
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
[[ "$(read_option misc:vrr)" == "$target_vrr" ]] || fail 'an out-of-allow-list VRR value reached the compositor'
|
||||
[[ -n "$(qs_for_harness ipc call settings-system-test status | jq -r .lastError)" ]] \
|
||||
|| fail 'a rejected VRR value did not surface an error'
|
||||
[[ -n "$rejected" ]] || fail 'a rejected VRR value did not surface an error'
|
||||
|
||||
# ── Every getoption answer shape must be handled, not just integers ──────────
|
||||
# The compositor reports each option in a different JSON field depending on its
|
||||
|
||||
Reference in New Issue
Block a user