Files
Panama/tests/quickshell/health-ui-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

431 lines
20 KiB
Bash
Executable File

#!/usr/bin/env bash
# The approved Diagnostic Ledger is exercised in an isolated Quickshell
# harness. It never maps or reloads the user's production shell.
set -euo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
settings_dir="$repo_dir/config/dot/quickshell/modules/settings"
bar_dir="$repo_dir/config/dot/quickshell/modules/bar"
fail() {
printf 'health UI contract: %s\n' "$1" >&2
exit 1
}
for file in HealthPage.qml HealthSummary.qml HealthCheckRow.qml; do
[[ -f "$settings_dir/$file" ]] || fail "$file is missing"
done
[[ -f "$bar_dir/HealthIndicator.qml" ]] || fail 'HealthIndicator.qml is missing'
python3 - "$bar_dir/Bar.qml" <<'PY' || fail 'health indicator is not immediately before activity in the bar'
import re
import sys
source = open(sys.argv[1], encoding="utf-8").read()
match = re.search(r'HealthIndicator\s*\{.*?\}\s*ActivityIndicator\s*\{', source, re.S)
assert match is not None
PY
! rg -n '#[0-9a-fA-F]{3,8}' "$bar_dir/HealthIndicator.qml" >/dev/null \
|| fail 'health indicator introduced colors outside Theme'
! rg -n 'Behavior|Animation|Transition|pulse|shimmer' "$bar_dir/HealthIndicator.qml" >/dev/null \
|| fail 'health indicator introduced motion'
[[ ! -e "$settings_dir/ServicesPage.qml" ]] || fail 'ServicesPage.qml still exists'
rg -Fq 'HealthPage 1.0 HealthPage.qml' "$settings_dir/qmldir" \
|| fail 'HealthPage is not registered in the Settings QML module'
rg -Fq 'HealthSummary 1.0 HealthSummary.qml' "$settings_dir/qmldir" \
|| fail 'HealthSummary is not registered in the Settings QML module'
rg -Fq 'HealthCheckRow 1.0 HealthCheckRow.qml' "$settings_dir/qmldir" \
|| fail 'HealthCheckRow is not registered in the Settings QML module'
! rg -Fq 'ServicesPage 1.0 ServicesPage.qml' "$settings_dir/qmldir" \
|| fail 'retired ServicesPage remains registered in the Settings QML module'
rg -Fq 'label: "System Health"' "$settings_dir/SettingsSidebar.qml" \
|| fail 'sidebar does not label the stable services route System Health'
rg -Fq 'onTapped: root.pageRequested("services")' "$settings_dir/SettingsSidebar.qml" \
|| fail 'health footer does not open the stable services route'
rg -Fq 'height: 54' "$settings_dir/SettingsSidebar.qml" \
|| fail 'health footer lost its 54px target'
rg -Fq 'onClicked: Health.copyReport()' "$settings_dir/HealthSummary.qml" \
|| fail 'Copy Report does not use the redacted Health report path'
rg -Fq 'text: "Checking…"' "$settings_dir/HealthSummary.qml" \
|| fail 'refresh state is not expressed in text'
rg -Fq 'implicitHeight: 126' "$settings_dir/HealthSummary.qml" \
|| fail 'summary hero is not the approved stable 126px height'
rg -Fq 'implicitHeight: 62' "$settings_dir/HealthCheckRow.qml" \
|| fail 'health rows are below the approved 62px target'
rg -Fq 'Health.refresh()' "$settings_dir/HealthPage.qml" \
|| fail 'opening System Health does not request a fresh scan'
rg -Fq 'SystemSettings.openGnomePanel("network")' "$settings_dir/HealthPage.qml" \
|| fail 'Fedora ownership boundary does not open GNOME Settings'
# Users and Sharing are Panama pages now. A handoff here would send someone to
# GNOME for a panel this app owns, which is the opposite of the point -- so the
# assertion is inverted rather than deleted.
rg -Fq 'SystemSettings.openGnomePanel("system", "users")' "$settings_dir/HealthPage.qml" \
&& fail 'System Health still hands Users to GNOME, but Panama owns that page'
rg -Fq 'SystemSettings.openGnomePanel("sharing")' "$settings_dir/HealthPage.qml" \
&& fail 'System Health still hands Sharing to GNOME, but Panama owns that page'
rg -Fq 'SystemSettings.openGnomePanel("color")' "$settings_dir/HealthPage.qml" \
|| fail 'Fedora ownership boundary lost the Color 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" \
|| fail 'authored Settings targets are not routed directly'
! rg -n '#[0-9a-fA-F]{3,8}' \
"$settings_dir/HealthPage.qml" \
"$settings_dir/HealthSummary.qml" \
"$settings_dir/HealthCheckRow.qml" >/dev/null \
|| fail 'health UI introduced colors outside Theme'
python3 - "$settings_dir/HealthPage.qml" "$settings_dir/HealthSummary.qml" \
"$settings_dir/HealthCheckRow.qml" <<'PY' || fail 'approved health structure or accessibility contract is missing'
import sys
page, summary, row = [open(path, encoding="utf-8").read() for path in sys.argv[1:]]
labels = (
'if (status === "ok") return "Healthy";',
'if (status === "warning") return "Needs attention";',
'if (status === "error") return "Action required";',
'return "Not set up";',
)
assert all(label in page for label in labels)
assert 'group: "desktop-foundation"' in page
assert 'group: "input-media"' in page
assert 'group: "integrations"' in page
assert 'group: "panama-tools"' in page
assert 'SettingsCard {' in page and 'SettingsCard {' in summary
assert 'activeFocusOnTab: enabled' in summary
assert 'Keys.onReturnPressed' in summary and 'Keys.onSpacePressed' in summary
assert 'activeFocusOnTab: enabled' in row
assert 'Keys.onReturnPressed' in row and 'Keys.onSpacePressed' in row
assert 'border.width: activeFocus ? 2 : 1' in summary
assert 'border.width: activeFocus ? 2 : 1' in row
assert 'Health.diagnosticUnavailable ? "Retry"' in summary
assert 'Health.lastCopyResult' in summary
assert 'pendingConfirmation' in page
assert 'ddc-permissions' in page
PY
fixture='{"schemaVersion":1,"generatedAt":"2026-08-18T12:00:00Z","summary":{"status":"error","healthy":2,"warnings":2,"errors":1,"unconfigured":1},"context":{"session":"hyprland","versions":[{"id":"quickshell","version":"0.3.0"}]},"checks":[{"id":"desktop.vicinae","group":"desktop-foundation","title":"Vicinae","status":"warning","detail":"The launcher service is stopped.","action":{"kind":"repair","label":"Restart Vicinae","confirm":false}},{"id":"desktop.quickshell","group":"desktop-foundation","title":"Quickshell","status":"error","detail":"Panama shell needs to restart.","action":{"kind":"repair","label":"Restart Panama","confirm":true}},{"id":"input.pipewire","group":"input-media","title":"PipeWire","status":"ok","detail":"Audio graph is responding."},{"id":"integration.bluebubbles","group":"integrations","title":"BlueBubbles","status":"unconfigured","detail":"Messaging integration has not been enabled."},{"id":"integration.calendar","group":"integrations","title":"Calendar","status":"warning","detail":"Calendar probe timed out.","action":{"kind":"open","label":"Open Date & Time","confirm":false,"target":"datetime"}},{"id":"panama.caffeine","group":"panama-tools","title":"Caffeine","status":"ok","detail":"No duplicate sleep inhibitors."}]}'
state_home="$(mktemp -d /tmp/panama-health-ui.XXXXXX)"
config_path="$state_home/quickshell"
harness="$config_path/health-ui-harness.qml"
helper="$state_home/panama-doctor"
shell_log="$state_home/quickshell.log"
fixture_home="$state_home/home"
mkdir -p "$fixture_home"
cp -a "$repo_dir/config/dot/quickshell" "$config_path"
cat >"$helper" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
if [[ "${1:-}" == "--repair" ]]; then
sleep 0.35
printf '{"schemaVersion":1,"checkId":"%s","accepted":true,"exitCode":7,"message":"The authored repair failed."}\n' "$2"
exit 7
fi
sleep 1.5
printf '%s\n' "$PANAMA_HEALTH_FIXTURE"
EOF
chmod +x "$helper"
cat >"$harness" <<'QML'
import Quickshell
import Quickshell.Io
import QtQuick
import "modules/bar" as BarModule
import qs.config
import qs.modules.settings
import qs.services
ShellRoot {
id: root
Component.onCompleted: {
Health.startupScanEnabled = false;
ShellState.settingsPage = "services";
Health.consumeSnapshot(Quickshell.env("PANAMA_HEALTH_FIXTURE"), 100);
}
FloatingWindow {
title: "Panama Health UI Contract"
visible: true
implicitWidth: 980
implicitHeight: 820
SettingsShell {
id: settingsShell
anchors.fill: parent
}
BarModule.HealthIndicator {
id: healthIndicator
objectName: "health-indicator"
}
}
IpcHandler {
target: "health-ui-test"
function state(): string {
return JSON.stringify(settingsShell.healthDiagnostics);
}
function request(id: string): bool {
return settingsShell.requestHealthAction(id);
}
function indicatorMode(mode: string): bool {
const checkStatus = mode === "healthy" ? "ok" : (mode === "unconfigured" ? "unconfigured" : mode);
const overallStatus = mode === "warning" || mode === "error" ? mode : "healthy";
const snapshot = {
schemaVersion: 1,
generatedAt: "2026-08-18T12:00:00Z",
summary: {
status: overallStatus,
healthy: mode === "healthy" ? 1 : 0,
warnings: mode === "warning" ? 1 : 0,
errors: mode === "error" ? 1 : 0,
unconfigured: mode === "unconfigured" ? 1 : 0
},
context: { session: "hyprland", versions: [] },
checks: [{
id: "desktop.vicinae",
group: "desktop-foundation",
title: "Vicinae",
status: checkStatus,
detail: "Fixture observation."
}]
};
return Health.consumeSnapshot(JSON.stringify(snapshot), Health.acceptedGeneration + 1);
}
function indicatorState(): string {
return JSON.stringify({
visible: healthIndicator.visible,
width: healthIndicator.width,
implicitWidth: healthIndicator.implicitWidth,
issueCount: healthIndicator.issueCount,
statusText: healthIndicator.statusText,
accessibleLabel: healthIndicator.accessibleLabel,
tooltipText: healthIndicator.tooltipText,
warningTone: healthIndicator.tone === Theme.warn,
errorTone: healthIndicator.tone === Theme.danger,
activeFocusOnTab: healthIndicator.activeFocusOnTab
});
}
function activateIndicator(): string {
ShellState.settingsPage = "home";
ShellState.settingsOpen = false;
const generation = Health.generation;
healthIndicator.activated();
return JSON.stringify({
page: ShellState.settingsPage,
settingsOpen: ShellState.settingsOpen,
refreshRequested: Health.generation > generation || Health.queuedRefresh
});
}
}
}
QML
run() {
PANAMA_HEALTH_FIXTURE="$fixture" PANAMA_HEALTH_HELPER="$helper" \
HOME="$fixture_home" XDG_STATE_HOME="$state_home" \
qs -p "$harness" "$@"
}
harness_pid=""
cleanup() {
if [[ -n "$harness_pid" ]]; then
kill "$harness_pid" >/dev/null 2>&1 || true
for _ in $(seq 1 40); do
kill -0 "$harness_pid" >/dev/null 2>&1 || break
sleep 0.1
done
else
run kill >/dev/null 2>&1 || true
fi
rm -rf "$state_home"
}
trap cleanup EXIT
PANAMA_HEALTH_FIXTURE="$fixture" PANAMA_HEALTH_HELPER="$helper" \
HOME="$fixture_home" XDG_STATE_HOME="$state_home" \
qs -p "$harness" --daemonize >"$shell_log" 2>&1
for _ in $(seq 1 40); do
harness_pid="$(qs list --all 2>/dev/null | awk -v path="$harness" '
/Process ID:/ { pid = $3 }
index($0, "Config path: " path) { print pid; exit }
')"
[[ "$harness_pid" =~ ^[0-9]+$ ]] && break
sleep 0.1
done
for _ in $(seq 1 60); do
run ipc show 2>/dev/null | rg -q '^target health-ui-test$' && break
sleep 0.1
done
run ipc show 2>/dev/null | rg -q '^target health-ui-test$' \
|| { sed -n '1,200p' "$shell_log" >&2; fail 'isolated fixture did not start'; }
checking_state="$(run ipc call health-ui-test state)"
jq -e '
.renderedRows == [
{objectName:"health-check-row:issue:desktop.vicinae", id:"desktop.vicinae", section:"issue", statusText:"Needs attention"},
{objectName:"health-check-row:issue:desktop.quickshell", id:"desktop.quickshell", section:"issue", statusText:"Action required"},
{objectName:"health-check-row:issue:integration.calendar", id:"integration.calendar", section:"issue", statusText:"Needs attention"},
{objectName:"health-check-row:quiet:input.pipewire", id:"input.pipewire", section:"quiet", statusText:"Healthy"},
{objectName:"health-check-row:quiet:integration.bluebubbles", id:"integration.bluebubbles", section:"quiet", statusText:"Not set up"},
{objectName:"health-check-row:quiet:panama.caffeine", id:"panama.caffeine", section:"quiet", statusText:"Healthy"}
]
and (.renderedRows | map(.id) | length) == 6
and (.renderedRows | map(.id) | unique | length) == 6
and .emptyQuietGroups == ["desktop-foundation"]
and .fedoraHandoffs == [
{id:"color", label:"Color profiles", action:"Open color"},
{id:"wellbeing", label:"Digital wellbeing", action:"Open wellbeing"}
]
and .summaryHeight == 126
and (.rowHeights | length) == 6
and (.rowHeights | all(. >= 62))
and .checking == true
and .checkingText == "Checking…"
' >/dev/null <<<"$checking_state" || fail "checking fixture did not render the approved state: $checking_state"
checking_heights="$(jq -c .rowHeights <<<"$checking_state")"
for _ in $(seq 1 40); do
settled_state="$(run ipc call health-ui-test state)"
[[ "$(jq -r .checking <<<"$settled_state")" == "false" ]] && break
sleep 0.1
done
sleep 0.1
settled_state="$(run ipc call health-ui-test state)"
[[ "$(jq -c .rowHeights <<<"$settled_state")" == "$checking_heights" ]] \
|| fail 'row geometry changed after refresh settled'
jq -e '
(.focusChain | index("health-copy-report-button")) != null
and (.focusChain | index("health-refresh-button")) != null
and (.focusChain | any(startswith("health-row-action:")))
' >/dev/null <<<"$settled_state" || fail "actual focus-chain traversal does not reach hero and row actions: $settled_state"
settled_heights="$(jq -c .rowHeights <<<"$settled_state")"
[[ "$(run ipc call health-ui-test request desktop.vicinae)" == "true" ]] \
|| fail 'inline repair fixture could not be requested'
working_repair_state="$(run ipc call health-ui-test state)"
jq -e '.renderedRows[] | select(.id == "desktop.vicinae") | .statusText == "Working…"' \
>/dev/null <<<"$working_repair_state" || fail "repair row did not show Working state: $working_repair_state"
[[ "$(jq -c .rowHeights <<<"$working_repair_state")" == "$settled_heights" ]] \
|| fail 'repair Working state changed row geometry'
for _ in $(seq 1 40); do
failed_repair_state="$(run ipc call health-ui-test state)"
jq -e '.renderedRows[] | select(.id == "desktop.vicinae") | .statusText == "Repair failed"' \
>/dev/null <<<"$failed_repair_state" && break
sleep 0.1
done
jq -e '.renderedRows[] | select(.id == "desktop.vicinae") | .statusText == "Repair failed"' \
>/dev/null <<<"$failed_repair_state" || fail "repair failure was not shown inline: $failed_repair_state"
[[ "$(jq -c .rowHeights <<<"$failed_repair_state")" == "$settled_heights" ]] \
|| fail 'repair failure changed row geometry'
[[ "$(jq -r '.renderedRows | map(.id) | unique | length' <<<"$failed_repair_state")" == 6 ]] \
|| fail 'repair state duplicated a health action row'
for _ in $(seq 1 40); do
failed_repair_state="$(run ipc call health-ui-test state)"
[[ "$(jq -r .checking <<<"$failed_repair_state")" == "false" ]] && break
sleep 0.1
done
[[ "$(jq -r .checking <<<"$failed_repair_state")" == "false" ]] \
|| fail 'post-repair scan did not settle before the next action'
[[ "$(run ipc call health-ui-test request desktop.quickshell)" == "true" ]] \
|| fail 'restart confirmation fixture could not be requested'
confirmation_state="$(run ipc call health-ui-test state)"
jq -e '
.confirmationVisible == true
and .confirmationId == "desktop.quickshell"
and (.activatedRows | index("health-check-row:issue:desktop.quickshell")) != null
and (.activatedRows | map(select(endswith(":desktop.quickshell"))) | length) == 1
' \
>/dev/null <<<"$confirmation_state" || fail 'Quickshell restart did not open confirmation sheet'
for hidden_mode in healthy unconfigured; do
[[ "$(run ipc call health-ui-test indicatorMode "$hidden_mode")" == "true" ]] \
|| fail "$hidden_mode indicator fixture was rejected"
hidden_state="$(run ipc call health-ui-test indicatorState)"
jq -e '
.visible == false
and .width == 0
and .implicitWidth == 0
and .issueCount == 0
' >/dev/null <<<"$hidden_state" \
|| fail "$hidden_mode state reserved bar space: $hidden_state"
done
[[ "$(run ipc call health-ui-test indicatorMode warning)" == "true" ]] \
|| fail 'warning indicator fixture was rejected'
warning_state="$(run ipc call health-ui-test indicatorState)"
jq -e '
.visible == true
and .width > 0
and .implicitWidth > 0
and .issueCount == 1
and .statusText == "1 system health issue"
and .accessibleLabel == "System Health: 1 issue needs attention"
and .tooltipText == "System Health: 1 issue needs attention"
and .warningTone == true
and .errorTone == false
and .activeFocusOnTab == true
' >/dev/null <<<"$warning_state" || fail "warning indicator is not the approved amber accessible capsule: $warning_state"
[[ "$(run ipc call health-ui-test indicatorMode error)" == "true" ]] \
|| fail 'error indicator fixture was rejected'
error_state="$(run ipc call health-ui-test indicatorState)"
jq -e '
.visible == true
and .issueCount == 1
and .accessibleLabel == "System Health: 1 issue requires action"
and .tooltipText == "System Health: 1 issue requires action"
and .warningTone == false
and .errorTone == true
' >/dev/null <<<"$error_state" || fail "error indicator is not the approved red accessible capsule: $error_state"
activation_state="$(run ipc call health-ui-test activateIndicator)"
jq -e '
.page == "services"
and .settingsOpen == true
and .refreshRequested == true
' >/dev/null <<<"$activation_state" || fail "indicator activation did not open and refresh System Health: $activation_state"
if rg -i 'QQml|ReferenceError|TypeError|binding loop|failed to load component' "$shell_log"; then
fail 'isolated fixture emitted QML errors or warnings'
fi
trap - EXIT
cleanup
printf 'health UI contract: PASS\n'