Files
Panama/tests/quickshell/lock-screen-theme-contract
T
Gabriel Brown e1faaf7a76 Drop the extension, and give the test suite a front door
Phase 6, the last of the fresh-install spec.

159 scripts lose their .sh: 110 contracts, 47 Vicinae commands, 2 compositor
contracts. A shebang and the executable bit already select the interpreter. The
extension only ever added something that had to stay in sync, and the rename
proved the point twice over in the space of an hour.

The spec's stated risk was Vicinae's script discovery. One script was renamed and
reloaded on its own before the other 46 followed; it came back as
scripts:panama.capture and all 47 resolve. What the probe turned up instead is
that the extension was never only a filename: Vicinae's command IDs embed it, so
every ID changed. Nothing in this repository refers to them, so nothing breaks.
The only trace is Vicinae's metadata.json, whose visited map had two Panama
entries that are now orphaned -- two commands lost their usage ranking and will
earn it back. Worth knowing before anyone renames these again on a machine that
has a keybind pointing at one.

Rewriting the references by exact filename missed two things it structurally
could not see: a name built from a variable, settings-$page.sh, and a glob,
-name '*.sh'. Both were in the contract that counts the generated commands, which
promptly reported 47 expected and 0 found. The mechanical part of a rename is the
part that looks finished.

The three subcommands. panama doctor fronts a health check that already existed
and already ran at the end of every install but could not be reached from a
terminal. panama upgrade re-runs the installer from anywhere. panama test runs
the suite, which had no entry point at all -- 121 files that were the main safety
net in this repository and were invisible in it.

Writing that runner found three tests nothing was running.
calendar_agenda_bridge_test, home_assistant_bridge_test and kdeconnect_bridge_test
are unittest suites without the executable bit, so no contract invoked them and
the first draft of the runner skipped them silently. All three pass, and have
passed unobserved for weeks. The runner collects *_test.py as well now, because a
runner with a blind spot is worse than no runner for the same reason a dependency
checker with one is: it reports PASS.

Six worktrees pruned. Each was re-checked rather than trusted to the spec's list,
and two needed it: panama-commands is not on feat/panama-commands but on
feat/gnome-tweaks-parity, and fix/panama-displays-review reads [ahead 3] -- ahead
of its remote, not of main, with every commit patch-equivalent to landed work.
roadmap-completion stays; it has five commits that are genuinely unlanded. The
branches are left alone: pruning a worktree costs nothing, deleting a branch is a
decision.

121 contracts pass.

Claude-Session: https://claude.ai/code/session_01NvgBuSWB5sE43yWmg21ozj
2026-08-20 21:55:55 -04:00

94 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# The lock screen follows the color scheme.
#
# It did not. hyprlock.conf shipped with Tokyo Night Moon hardcoded in six
# places, so choosing light mode left the one screen a user sees most often
# stubbornly dark. Every other surface -- kitty, GTK, the launcher, btop, tmux,
# neovim -- had been taught to follow the scheme; this was the last one.
#
# It is also the worst place to discover a theming bug, because you find out
# while locked out of the machine and cannot fix it from there. Hence a test.
#
# Generated into a fixture, never the live config: this contract must not
# retheme the lock screen of the desktop it is running on.
set -uo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
template="$repo_dir/config/dot/hypr/hyprlock.conf.template"
theme_apps="$repo_dir/config/dot/quickshell/scripts/panama-theme-apps"
fail() {
printf 'lock screen theme contract: %s\n' "$1" >&2
exit 1
}
[[ -r "$template" ]] || fail 'hyprlock.conf.template is missing, so nothing generates the lock screen'
# The committed template must carry no literal colors. One left behind is a
# color that silently stays dark in light mode -- exactly the original bug.
literal="$(grep -vE '^\s*#' "$template" | grep -oE 'rgba\([0-9]+, *[0-9]+, *[0-9]+' || true)"
[[ -z "$literal" ]] \
|| fail "the template still contains hardcoded colors, which will not follow the scheme: $literal"
fixture="$(mktemp -d /tmp/panama-lockscreen.XXXXXX)"
trap 'rm -rf "$fixture"' EXIT
mkdir -p "$fixture/hypr"
cp "$template" "$fixture/hypr/"
for scheme in dark light; do
XDG_CONFIG_HOME="$fixture" "$theme_apps" "$scheme" >/dev/null 2>&1
generated="$fixture/hypr/hyprlock.conf"
[[ -r "$generated" ]] || fail "no hyprlock.conf was generated for $scheme"
# An unsubstituted placeholder is not a parse error to hyprlock; it is an
# invalid color it quietly ignores, falling back to its own default.
leftover="$(grep -oE '@[A-Z_]+@' "$generated" || true)"
[[ -z "$leftover" ]] \
|| fail "$scheme left placeholders unsubstituted: $leftover"
# Every color hyprlock is given must be a complete decimal triple. It
# takes rgba(r, g, b, a), NOT hex, and a hex value here is silently ignored.
while read -r color; do
[[ -n "$color" ]] || continue
grep -qE '^rgba\([0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}$' <<<"$color" \
|| fail "$scheme produced a malformed color: $color"
done < <(grep -vE '^\s*#' "$generated" | grep -oE 'rgba\([^)]*' | sed 's/,[^,]*$//')
# The Pango markup values are hex, and hyprlock wants them doubled-hashed.
while read -r pango; do
[[ -n "$pango" ]] || continue
grep -qE '^##[0-9a-f]{6}$' <<<"$pango" \
|| fail "$scheme produced malformed Pango markup color: $pango"
done < <(grep -vE '^\s*#' "$generated" | grep -oE '##[0-9a-fA-F]{6}')
# The whole background block, not a fixed number of lines after it: the
# color sits near the end, after the blur and noise settings.
background="$(awk '/^background \{/,/^\}/' "$generated" \
| grep -vE '^\s*#' | grep -oE 'color = rgba\([0-9]+' | grep -oE '[0-9]+$' | head -1)"
[[ -n "$background" ]] || fail "$scheme produced no background color"
# The point of the whole exercise: a light lock screen must actually be
# light. 128 splits the two cleanly for these palettes.
if [[ "$scheme" == "light" ]]; then
(( background > 128 )) \
|| fail "light mode produced a DARK lock screen background (red channel $background) -- the original bug"
else
(( background < 128 )) \
|| fail "dark mode produced a LIGHT lock screen background (red channel $background)"
fi
done
# The two schemes must actually differ, or the substitution is a no-op that
# passes every check above.
XDG_CONFIG_HOME="$fixture" "$theme_apps" dark >/dev/null 2>&1
dark_hash="$(sha256sum "$fixture/hypr/hyprlock.conf" | cut -d' ' -f1)"
XDG_CONFIG_HOME="$fixture" "$theme_apps" light >/dev/null 2>&1
light_hash="$(sha256sum "$fixture/hypr/hyprlock.conf" | cut -d' ' -f1)"
[[ "$dark_hash" != "$light_hash" ]] \
|| fail 'the light and dark lock screens are byte-identical, so the scheme is not being applied'
printf 'lock screen theme contract: PASS\n'