Let the contracts assert properties, not the machine they were written on

The first run of the suite on a laptop found five contracts asserting the
desktop instead of the code. settings-system pinned DP-2 at 4500x3000 in
XRGB2101010; it now asks Hyprland what is actually primary. ssh-keys hardcoded
id_ed25519; it now uses whichever key exists. switcher's live half stepped a
session with one window, which step() deliberately refuses. displays raced the
service's revert readback -- the compositor looks restored while verification
still holds busy, so an immediate apply was refused with its error already
cleared; the harness now exposes settled and the contract waits for it.

declared-dependencies gets an OPTIONAL list for docker: the aliases serve
machines that run Docker deliberately, Panama's runtime is rootless podman,
and a missing docker fails by naming the command, which is loud enough.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
This commit is contained in:
Gabriel Brown
2026-08-23 10:32:17 -04:00
parent 6510fdda0f
commit 12f6b2a310
6 changed files with 58 additions and 8 deletions
+8 -1
View File
@@ -32,7 +32,14 @@ ShellRoot {
canConfirm: Displays.canConfirm, canConfirm: Displays.canConfirm,
secondsLeft: Displays.secondsLeft, secondsLeft: Displays.secondsLeft,
lastError: Displays.lastError, lastError: Displays.lastError,
overridden: monitor ? Displays.isOverridden(monitor.name) : false overridden: monitor ? Displays.isOverridden(monitor.name) : false,
// The compositor being visually restored is not the service
// being done: revert verification keeps its own readback
// running for a few ticks, and busy blocks a new apply until
// it settles. A caller that only watched `awaiting` raced
// this and got a refusal with no error text.
settled: !Displays.busy && !Displays.revertVerificationActive
&& !Displays.awaitingConfirmation
}); });
} }
@@ -47,6 +47,15 @@ SESSION='^(systemctl|busctl|journalctl|loginctl|hostnamectl|localectl|systemd-in
# Anything added here needs a matching install block and a stated reason. # Anything added here needs a matching install block and a stated reason.
SELF_INSTALLED='^(bun|claude|node|npm|pnpm)$' SELF_INSTALLED='^(bun|claude|node|npm|pnpm)$'
# Tools an alias may lean on without Panama installing them anywhere. The
# docker aliases serve the machines that run Docker by deliberate choice;
# Panama's container runtime is rootless podman (development-packages), and
# declaring docker in a list would put a second container daemon on every
# fresh machine to keep five aliases company. Where docker is absent the
# aliases fail by naming the missing command, which is the honest outcome.
# Anything added here needs that same property: absence must be loud.
OPTIONAL='^(docker)$'
# jq programs are quoted arguments, but the scanner is line-based and cannot # jq programs are quoted arguments, but the scanner is line-based and cannot
# tell a filter from a command. `not` is a jq builtin appearing inside one. # tell a filter from a command. `not` is a jq builtin appearing inside one.
JQ_BUILTINS='^(not|empty|error|env|input|inputs)$' JQ_BUILTINS='^(not|empty|error|env|input|inputs)$'
@@ -105,6 +114,7 @@ while read -r script; do
[[ "$cmd" =~ $BASELINE ]] && continue [[ "$cmd" =~ $BASELINE ]] && continue
[[ "$cmd" =~ $SESSION ]] && continue [[ "$cmd" =~ $SESSION ]] && continue
[[ "$cmd" =~ $SELF_INSTALLED ]] && continue [[ "$cmd" =~ $SELF_INSTALLED ]] && continue
[[ "$cmd" =~ $OPTIONAL ]] && continue
[[ "$cmd" =~ $JQ_BUILTINS ]] && continue [[ "$cmd" =~ $JQ_BUILTINS ]] && continue
pkg="$(package_for "$cmd")" pkg="$(package_for "$cmd")"
+9 -1
View File
@@ -309,7 +309,10 @@ target_scale=$(awk -v s="$original_scale" 'BEGIN { print (s == 1.25) ? 1.5 : 1.2
run ipc call displays-test revertChange >/dev/null run ipc call displays-test revertChange >/dev/null
immediate_reverted=false immediate_reverted=false
for _ in $(seq 1 60); do for _ in $(seq 1 60); do
if display_is_restored && [[ "$(status | jq -r .awaiting)" == "false" ]]; then # settled, not awaiting: the compositor can look restored while the
# service's revert verification is still reading back, and an apply in
# that window is refused as busy. See the settled field in the harness.
if display_is_restored && [[ "$(status | jq -r .settled)" == "true" ]]; then
immediate_reverted=true immediate_reverted=true
break break
fi fi
@@ -345,6 +348,11 @@ done
[[ "$(status | jq -r .overridden)" == "false" ]] || fail 'an unconfirmed change was written to the settings store' [[ "$(status | jq -r .overridden)" == "false" ]] || fail 'an unconfirmed change was written to the settings store'
# ── A confirmed change is what writes ──────────────────────────────────────── # ── A confirmed change is what writes ────────────────────────────────────────
# Wait out the revert readback before applying again -- same race as above.
for _ in $(seq 1 40); do
[[ "$(status | jq -r .settled)" == "true" ]] && break
sleep 0.2
done
[[ "$(run ipc call displays-test applyScale "$target_scale")" == "true" ]] \ [[ "$(run ipc call displays-test applyScale "$target_scale")" == "true" ]] \
|| fail 'the confirmed-change fixture could not apply' || fail 'the confirmed-change fixture could not apply'
+13 -2
View File
@@ -41,8 +41,19 @@ for _ in $(seq 1 40); do
fi fi
sleep 0.1 sleep 0.1
done done
jq -e '.monitorName == "DP-2" and .width == 4500 and .height == 3000 and .scale == 1.5 and .format == "XRGB2101010"' <<<"$status" >/dev/null \ # Against the live compositor, not a named machine: this once asserted DP-2 at
|| fail "live monitor data was not normalized: $status" # 4500x3000 in XRGB2101010, which pinned the desktop it was written on and
# could never pass on a laptop's eDP-1. The property is that SystemSettings
# mirrors whatever monitor is actually primary, normalized -- so ask Hyprland
# what that is.
live_monitor="$(hyprctl -j monitors | jq -c '.[0]')"
jq -e --argjson live "$live_monitor" '
.monitorName == $live.name
and .width == $live.width
and .height == $live.height
and ((.scale - $live.scale) | fabs) < 0.001
and (.format | length) > 0' <<<"$status" >/dev/null \
|| fail "live monitor data was not normalized: $status (compositor: $live_monitor)"
[[ "$(qs_for_harness ipc call settings-system-test panelAllowed '__definitely_not_a_panel__' | jq -r .)" == "false" ]] \ [[ "$(qs_for_harness ipc call settings-system-test panelAllowed '__definitely_not_a_panel__' | jq -r .)" == "false" ]] \
|| fail 'unsupported GNOME panel was accepted' || fail 'unsupported GNOME panel was accepted'
+10 -1
View File
@@ -96,9 +96,18 @@ grep -q 'durableRemoval' "$helper" \
kind="$(printf '%s' "$state" | field "['agent'].get('kind','')")" kind="$(printf '%s' "$state" | field "['agent'].get('kind','')")"
if [[ "$kind" == "gnome-keyring" ]]; then if [[ "$kind" == "gnome-keyring" ]]; then
reason="$(printf '%s' "$("$helper" agent-remove "$HOME/.ssh/id_ed25519")" | field "['error']")" # Whichever key this machine actually has. This used to hardcode
# id_ed25519, which asserted the author's machine: any other key name
# earned "That key no longer exists" instead of the refusal under test.
# No key at all means the property cannot be exercised here, not that it
# failed.
real_key="$(compgen -G "$HOME/.ssh/id_*.pub" | head -1)"
real_key="${real_key%.pub}"
if [[ -n "$real_key" ]]; then
reason="$(printf '%s' "$("$helper" agent-remove "$real_key")" | field "['error']")"
[[ "$reason" == *"does not stick"* ]] \ [[ "$reason" == *"does not stick"* ]] \
|| fail "removal against a keyring agent was not refused with its reason (got: $reason)" || fail "removal against a keyring agent was not refused with its reason (got: $reason)"
fi
grep -q 'does not stick' "$page" \ grep -q 'does not stick' "$page" \
|| fail 'the page does not say that removing a key from this agent has no effect' || fail 'the page does not say that removing a key from this agent has no effect'
fi fi
+6 -1
View File
@@ -73,7 +73,12 @@ grep -q 'WlrKeyboardFocus.None' "$window" \
# ── Live ──────────────────────────────────────────────────────────────────── # ── Live ────────────────────────────────────────────────────────────────────
if command -v qs >/dev/null 2>&1 && qs ipc call switcher cancel >/dev/null 2>&1; then # Stepping refuses to open with fewer than two windows (see step() in the
# state service) -- that is designed behavior, not a failure, so a session
# with one window skips the live half rather than failing against it.
open_windows="$(hyprctl -j clients 2>/dev/null | jq length 2>/dev/null || echo 0)"
if command -v qs >/dev/null 2>&1 && (( open_windows >= 2 )) \
&& qs ipc call switcher cancel >/dev/null 2>&1; then
qs ipc call switcher next >/dev/null 2>&1 qs ipc call switcher next >/dev/null 2>&1
sleep 0.6 sleep 0.6
mapped="$(hyprctl layers -j 2>/dev/null | grep -c 'qs-switcher' || true)" mapped="$(hyprctl layers -j 2>/dev/null | grep -c 'qs-switcher' || true)"