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
413 lines
20 KiB
Bash
Executable File
413 lines
20 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Health owns the accepted diagnostic snapshot. A newer unreadable response
|
|
# must degrade diagnostics without discarding the last report that Settings
|
|
# and future health surfaces will render.
|
|
|
|
set -euo pipefail
|
|
|
|
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
source_harness="$repo_dir/config/dot/quickshell/health-harness.qml"
|
|
service="$repo_dir/config/dot/quickshell/services/Health.qml"
|
|
shell="$repo_dir/config/dot/quickshell/shell.qml"
|
|
warning_snapshot='{"schemaVersion":1,"generatedAt":"2026-08-18T00:00:00Z","summary":{"status":"warning","healthy":0,"warnings":2,"errors":0,"unconfigured":0},"context":{"session":"hyprland","versions":[{"id":"quickshell","version":"0.3.0"}]},"checks":[{"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":"warning","detail":"Duplicate inhibitors are active.","action":{"kind":"repair","label":"Release duplicate inhibitors","confirm":false}}]}'
|
|
confirm_snapshot="$(jq -c '
|
|
.summary.status = "error"
|
|
| .summary.errors = 1
|
|
| .checks += [{
|
|
id: "desktop.quickshell",
|
|
group: "desktop-foundation",
|
|
title: "Quickshell",
|
|
status: "error",
|
|
detail: "Panama shell needs to restart.",
|
|
action: {kind: "repair", label: "Restart Panama", confirm: true}
|
|
}]
|
|
' <<<"$warning_snapshot")"
|
|
projection_snapshot="$(jq -c '
|
|
.fixtureSecret = "fixture-secret"
|
|
| .summary.fixtureSecret = "fixture-secret"
|
|
| .context.fixtureSecret = "fixture-secret"
|
|
| .context.versions[0].fixtureSecret = "fixture-secret"
|
|
| .checks[0].fixtureSecret = "fixture-secret"
|
|
' <<<"$warning_snapshot")"
|
|
adversarial_snapshot="$(jq -c '
|
|
.fixtureSecret = "fixture-secret"
|
|
| .summary.fixtureSecret = "fixture-secret"
|
|
| .context.fixtureSecret = "fixture-secret"
|
|
| .context.versions[0].fixtureSecret = "fixture-secret"
|
|
| .checks[0].fixtureSecret = "fixture-secret"
|
|
| .checks[0].action.fixtureSecret = "fixture-secret"
|
|
' <<<"$warning_snapshot")"
|
|
|
|
fail() {
|
|
printf 'health service contract: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
[[ -f "$service" ]] || fail 'Health.qml is missing'
|
|
[[ -f "$source_harness" ]] || fail 'health harness is missing'
|
|
[[ -f "$shell" ]] || fail 'shell.qml is missing'
|
|
rg -q 'target: "wallpaper"' "$shell" \
|
|
|| fail 'wallpaper health target is not exported by the shell'
|
|
|
|
# shell.qml is not started here: it is the active desktop shell. Keep this
|
|
# contract static while pinning the typed, redacted IPC boundary it exports.
|
|
python3 - "$shell" <<'PY' || fail 'health IPC contract is missing or exposes unsafe state'
|
|
import re
|
|
import sys
|
|
|
|
text = open(sys.argv[1], encoding="utf-8").read()
|
|
match = re.search(r'IpcHandler \{\s*target: "health"(?P<body>.*?)\n \}', text, re.S)
|
|
if not match:
|
|
raise SystemExit(1)
|
|
body = match.group("body")
|
|
required = (
|
|
'function refresh(): bool { return Health.refresh(); }',
|
|
'function status(): string {',
|
|
'summary: Health.summary,',
|
|
'busy: Health.busy,',
|
|
'generation: Health.generation,',
|
|
'acceptedGeneration: Health.acceptedGeneration,',
|
|
'checks: Health.checks.map(check => ({ id: check.id, status: check.status }))',
|
|
'ShellState.openSettings("services");',
|
|
'Health.refresh();',
|
|
'function repair(id: string): bool { return Health.repair(id, true); }',
|
|
)
|
|
if any(entry not in body for entry in required):
|
|
raise SystemExit(1)
|
|
if 'Health.snapshot' in body or 'Health.diagnostics' in body:
|
|
raise SystemExit(1)
|
|
status = re.search(r'function status\(\): string \{\s*return JSON\.stringify\(\{(?P<fields>.*?)\n \}\);', body, re.S)
|
|
if not status:
|
|
raise SystemExit(1)
|
|
keys = re.findall(r'^\s*([A-Za-z][A-Za-z0-9]*):', status.group("fields"), re.M)
|
|
if keys != ["summary", "busy", "generation", "acceptedGeneration", "checks"]:
|
|
raise SystemExit(1)
|
|
PY
|
|
|
|
fixture_dir="$(mktemp -d /tmp/panama-health.XXXXXX)"
|
|
config_path="$fixture_dir/quickshell"
|
|
cp -a "$repo_dir/config/dot/quickshell" "$config_path"
|
|
harness="$config_path/health-harness.qml"
|
|
python3 - "$harness" <<'PY'
|
|
import sys
|
|
|
|
path = sys.argv[1]
|
|
source = open(path, encoding="utf-8").read()
|
|
needle = ' function repair(id: string): bool { return Health.repair(id, false); }\n'
|
|
replacement = needle + ''' function externalRepair(id: string): bool { return Health.repair(id, true); }
|
|
function pendingRefreshRace(): string {
|
|
const before = Health.generation;
|
|
Health.finishRepair(0, "panama.caffeine", false, JSON.stringify({
|
|
schemaVersion: 1,
|
|
checkId: "panama.caffeine",
|
|
accepted: true,
|
|
exitCode: 0,
|
|
message: "Fixture repair completed."
|
|
}));
|
|
const accepted = Health.refresh();
|
|
return JSON.stringify({ accepted: accepted, before: before });
|
|
}
|
|
'''
|
|
if needle not in source:
|
|
raise SystemExit("health harness repair seam is missing")
|
|
open(path, "w", encoding="utf-8").write(source.replace(needle, replacement))
|
|
PY
|
|
helper="$fixture_dir/panama-doctor"
|
|
copy_bin="$fixture_dir/bin"
|
|
copy_file="$fixture_dir/copied-report.json"
|
|
repair_mode_file="$fixture_dir/repair-mode"
|
|
repair_log="$fixture_dir/repair.log"
|
|
notification_log="$fixture_dir/notifications.log"
|
|
repair_started_file="$fixture_dir/repair-started"
|
|
repair_release_file="$fixture_dir/repair-release"
|
|
printf 'success\n' >"$repair_mode_file"
|
|
printf '%s\n' \
|
|
'#!/usr/bin/env bash' \
|
|
'printf "%s\n" "$*" >>"$PANAMA_HEALTH_REPAIR_LOG"' \
|
|
'if [[ "$1" == "--json" ]]; then' \
|
|
' sleep 0.2' \
|
|
" printf '%s\\n' '$warning_snapshot'" \
|
|
' exit 0' \
|
|
'fi' \
|
|
'if [[ "$1" == "--repair" ]]; then' \
|
|
' repair_start_time="$(awk '\''{ print $22 }'\'' "/proc/$$/stat")"' \
|
|
' printf "%s|%s\n" "$$" "$repair_start_time" >"$PANAMA_HEALTH_REPAIR_STARTED"' \
|
|
' while [[ ! -e "$PANAMA_HEALTH_REPAIR_RELEASE" ]]; do sleep 0.02; done' \
|
|
'fi' \
|
|
'if [[ "$1" == "--repair" && "$2" == "panama.caffeine" && "$3" == "--json" ]]; then' \
|
|
' case "$(cat "$PANAMA_HEALTH_REPAIR_MODE_FILE")" in' \
|
|
' success) printf "{\"schemaVersion\":1,\"checkId\":\"panama.caffeine\",\"accepted\":true,\"exitCode\":0,\"message\":\"Duplicate inhibitors were released.\"}\\n"; exit 0 ;;' \
|
|
' failed) printf "{\"schemaVersion\":1,\"checkId\":\"panama.caffeine\",\"accepted\":true,\"exitCode\":7,\"message\":\"Duplicate inhibitors could not be released.\"}\\n"; exit 7 ;;' \
|
|
' mismatch) printf "{\"schemaVersion\":1,\"checkId\":\"desktop.vicinae\",\"accepted\":true,\"exitCode\":0,\"message\":\"Wrong row.\"}\\n"; exit 0 ;;' \
|
|
' *) printf "not-json\\n"; exit 0 ;;' \
|
|
' esac' \
|
|
'fi' \
|
|
'if [[ "$1" == "--repair" && "$2" == "desktop.quickshell" && "$3" == "--json" ]]; then' \
|
|
' printf "{\"schemaVersion\":1,\"checkId\":\"desktop.quickshell\",\"accepted\":true,\"exitCode\":0,\"message\":\"Panama shell restart was requested.\"}\\n"' \
|
|
' exit 0' \
|
|
'fi' \
|
|
'exit 2' >"$helper"
|
|
chmod +x "$helper"
|
|
mkdir -p "$copy_bin"
|
|
printf '%s\n' \
|
|
'#!/usr/bin/env bash' \
|
|
'/usr/bin/cat > "$PANAMA_HEALTH_COPY_FILE"' >"$copy_bin/wl-copy"
|
|
printf '%s\n' \
|
|
'#!/usr/bin/env bash' \
|
|
'printf "%s\n" "$*" >>"$PANAMA_HEALTH_NOTIFICATION_LOG"' >"$copy_bin/notify-send"
|
|
chmod +x "$copy_bin/wl-copy" "$copy_bin/notify-send"
|
|
|
|
run() {
|
|
PATH="$copy_bin:$PATH" PANAMA_HEALTH_HELPER="$helper" PANAMA_HEALTH_COPY_FILE="$copy_file" \
|
|
PANAMA_HEALTH_REPAIR_MODE_FILE="$repair_mode_file" PANAMA_HEALTH_REPAIR_LOG="$repair_log" \
|
|
PANAMA_HEALTH_NOTIFICATION_LOG="$notification_log" \
|
|
PANAMA_HEALTH_REPAIR_STARTED="$repair_started_file" PANAMA_HEALTH_REPAIR_RELEASE="$repair_release_file" \
|
|
qs -p "$harness" "$@"
|
|
}
|
|
harness_pid=""
|
|
harness_start_time=""
|
|
|
|
process_identity_matches() {
|
|
local pid="$1" expected_start_time="$2" expected_command="${3:-}" current_start_time
|
|
|
|
[[ "$pid" =~ ^[0-9]+$ && "$expected_start_time" =~ ^[0-9]+$ ]] || return 1
|
|
[[ -r "/proc/$pid/stat" ]] || return 1
|
|
current_start_time="$(awk '{ print $22 }' "/proc/$pid/stat" 2>/dev/null)" || return 1
|
|
[[ "$current_start_time" == "$expected_start_time" ]] || return 1
|
|
if [[ -n "$expected_command" ]]; then
|
|
[[ -r "/proc/$pid/cmdline" ]] || return 1
|
|
tr '\0' '\n' <"/proc/$pid/cmdline" | grep -Fxq "$expected_command"
|
|
fi
|
|
}
|
|
|
|
cleanup() {
|
|
: >"$repair_release_file"
|
|
if [[ -f "$repair_started_file" ]]; then
|
|
IFS='|' read -r repair_pid repair_start_time <"$repair_started_file" || true
|
|
if process_identity_matches "$repair_pid" "$repair_start_time" "$helper"; then
|
|
for _ in $(seq 1 40); do
|
|
! process_identity_matches "$repair_pid" "$repair_start_time" "$helper" && break
|
|
sleep 0.05
|
|
done
|
|
if process_identity_matches "$repair_pid" "$repair_start_time" "$helper"; then
|
|
kill "$repair_pid" >/dev/null 2>&1 || true
|
|
for _ in $(seq 1 20); do
|
|
! process_identity_matches "$repair_pid" "$repair_start_time" "$helper" && break
|
|
sleep 0.05
|
|
done
|
|
if process_identity_matches "$repair_pid" "$repair_start_time" "$helper"; then
|
|
kill -KILL "$repair_pid" >/dev/null 2>&1 || true
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
if process_identity_matches "$harness_pid" "$harness_start_time"; then
|
|
kill "$harness_pid" >/dev/null 2>&1 || true
|
|
for _ in $(seq 1 40); do
|
|
! process_identity_matches "$harness_pid" "$harness_start_time" && break
|
|
sleep 0.05
|
|
done
|
|
if process_identity_matches "$harness_pid" "$harness_start_time"; then
|
|
kill -KILL "$harness_pid" >/dev/null 2>&1 || true
|
|
fi
|
|
fi
|
|
rm -rf "$fixture_dir"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
PATH="$copy_bin:$PATH" PANAMA_HEALTH_HELPER="$helper" PANAMA_HEALTH_COPY_FILE="$copy_file" \
|
|
PANAMA_HEALTH_REPAIR_MODE_FILE="$repair_mode_file" PANAMA_HEALTH_REPAIR_LOG="$repair_log" \
|
|
PANAMA_HEALTH_NOTIFICATION_LOG="$notification_log" \
|
|
PANAMA_HEALTH_REPAIR_STARTED="$repair_started_file" PANAMA_HEALTH_REPAIR_RELEASE="$repair_release_file" \
|
|
qs -p "$harness" --daemonize >/dev/null
|
|
for _ in $(seq 1 40); do
|
|
run ipc show 2>/dev/null | rg -q '^target health-test$' && break
|
|
sleep 0.1
|
|
done
|
|
run ipc show 2>/dev/null | rg -q '^target health-test$' || fail 'test IPC target did not start'
|
|
harness_pid="$(run list | awk '/Process ID:/ { print $3; exit }')"
|
|
harness_start_time="$(awk '{ print $22 }' "/proc/$harness_pid/stat" 2>/dev/null || true)"
|
|
process_identity_matches "$harness_pid" "$harness_start_time" \
|
|
|| fail 'could not capture a stable health harness process identity'
|
|
|
|
[[ "$(run ipc call health-test accept "$warning_snapshot" 0)" == "true" ]] \
|
|
|| fail 'valid warning snapshot was rejected'
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.status == "warning" and .acceptedGeneration == 0 and .checks == ["integration.calendar", "panama.caffeine"] and .diagnosticUnavailable == false' \
|
|
>/dev/null <<<"$state" || fail "valid warning snapshot was not accepted intact: $state"
|
|
|
|
[[ "$(run ipc call health-test accept "$projection_snapshot" 0)" == "true" ]] \
|
|
|| fail 'snapshot with unknown non-action fields was rejected instead of safely projected'
|
|
stored_report="$(run ipc call health-test report)"
|
|
! grep -Fq 'fixture-secret' <<<"$stored_report" \
|
|
|| fail "accepted snapshot retained an unknown secret field: $stored_report"
|
|
[[ "$(run ipc call health-test copy)" == "true" ]] \
|
|
|| fail 'copy report was refused'
|
|
for _ in $(seq 1 40); do
|
|
[[ -f "$copy_file" ]] && break
|
|
sleep 0.1
|
|
done
|
|
[[ -f "$copy_file" ]] || fail 'copy report did not reach wl-copy'
|
|
! grep -Fq 'fixture-secret' "$copy_file" \
|
|
|| fail 'copied report retained an unknown secret field'
|
|
|
|
adversarial_result="$(run ipc call health-test accept "$adversarial_snapshot" 1)"
|
|
[[ "$adversarial_result" == "true" || "$adversarial_result" == "false" ]] \
|
|
|| fail "adversarial action fixture did not return a Boolean: $adversarial_result"
|
|
stored_report="$(run ipc call health-test report)"
|
|
! grep -Fq 'fixture-secret' <<<"$stored_report" \
|
|
|| fail "adversarial snapshot leaked an unknown secret field: $stored_report"
|
|
|
|
[[ "$(run ipc call health-test accept "$warning_snapshot" -1)" == "false" ]] \
|
|
|| fail 'older generation replaced the current snapshot'
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.acceptedGeneration == 0 and .checks == ["integration.calendar", "panama.caffeine"]' \
|
|
>/dev/null <<<"$state" || fail "older generation altered accepted state: $state"
|
|
|
|
[[ "$(run ipc call health-test accept '{not json' 1)" == "false" ]] \
|
|
|| fail 'malformed snapshot was accepted'
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.diagnosticUnavailable == true and .checks == ["integration.calendar", "panama.caffeine"]' \
|
|
>/dev/null <<<"$state" || fail "malformed snapshot discarded the last valid checks: $state"
|
|
|
|
before_generation="$(jq -r .generation <<<"$state")"
|
|
run ipc call health-test queue >/dev/null
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.queuedRefresh == true and .generation == ($before + 1)' --argjson before "$before_generation" \
|
|
>/dev/null <<<"$state" || fail "two refreshes did not retain exactly one follow-up: $state"
|
|
for _ in $(seq 1 120); do
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.busy == false and .generation == ($before + 2) and .queuedRefresh == false' --argjson before "$before_generation" \
|
|
>/dev/null <<<"$state" && break
|
|
sleep 0.1
|
|
done
|
|
jq -e '.busy == false and .generation == ($before + 2) and .queuedRefresh == false' --argjson before "$before_generation" \
|
|
>/dev/null <<<"$state" || fail "queued refresh did not run exactly once: $state"
|
|
|
|
printf 'success\n' >"$repair_mode_file"
|
|
rm -f "$repair_started_file" "$repair_release_file"
|
|
repair_generation="$(jq -r .generation <<<"$state")"
|
|
[[ "$(run ipc call health-test repair panama.caffeine)" == "true" ]] \
|
|
|| fail 'repairable check was refused'
|
|
for _ in $(seq 1 100); do
|
|
[[ -s "$repair_started_file" ]] && break
|
|
sleep 0.05
|
|
done
|
|
[[ -s "$repair_started_file" ]] || fail 'repair helper never reached the started marker'
|
|
run ipc call health-test queue >/dev/null
|
|
working_state="$(run ipc call health-test status)"
|
|
jq -e '.repairingId == "panama.caffeine" and .queuedRefresh == true
|
|
and (.checkStates[] | select(.id == "panama.caffeine") | .status) == "warning"' \
|
|
>/dev/null <<<"$working_state" || fail "repair did not retain the degraded row while working: $working_state"
|
|
: >"$repair_release_file"
|
|
for _ in $(seq 1 120); do
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false' --argjson before "$repair_generation" \
|
|
>/dev/null <<<"$state" && break
|
|
sleep 0.1
|
|
done
|
|
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false
|
|
and .lastRepair == {schemaVersion:1, checkId:"panama.caffeine", accepted:true, exitCode:0, message:"Duplicate inhibitors were released."}
|
|
and (.checkStates[] | select(.id == "panama.caffeine") | .status) == "warning"' \
|
|
--argjson before "$repair_generation" >/dev/null <<<"$state" \
|
|
|| fail "accepted repair was trusted before exactly one observed rescan: $state"
|
|
|
|
# A syntactically valid command failure remains inline for Settings and still
|
|
# receives exactly one observed rescan.
|
|
printf 'failed\n' >"$repair_mode_file"
|
|
failure_generation="$(jq -r .generation <<<"$state")"
|
|
[[ "$(run ipc call health-test repair panama.caffeine)" == "true" ]] \
|
|
|| fail 'second repairable check was refused'
|
|
for _ in $(seq 1 120); do
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.busy == false and .generation == ($before + 1)' --argjson before "$failure_generation" \
|
|
>/dev/null <<<"$state" && break
|
|
sleep 0.1
|
|
done
|
|
jq -e '.lastRepair.checkId == "panama.caffeine"
|
|
and .lastRepair.accepted == true and .lastRepair.exitCode == 7
|
|
and .lastRepair.message == "Duplicate inhibitors could not be released."
|
|
and .generation == ($before + 1)' --argjson before "$failure_generation" \
|
|
>/dev/null <<<"$state" || fail "known repair failure was not retained inline: $state"
|
|
[[ ! -e "$notification_log" || ! -s "$notification_log" ]] \
|
|
|| fail 'Settings-originated repair emitted an external notification'
|
|
|
|
# A malformed or mismatched helper response is contained and cannot masquerade
|
|
# as recovery; it also schedules only one scan.
|
|
printf 'mismatch\n' >"$repair_mode_file"
|
|
mismatch_generation="$(jq -r .generation <<<"$state")"
|
|
[[ "$(run ipc call health-test repair panama.caffeine)" == "true" ]] \
|
|
|| fail 'mismatch repair fixture was refused'
|
|
for _ in $(seq 1 120); do
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.busy == false and .generation == ($before + 1)' --argjson before "$mismatch_generation" \
|
|
>/dev/null <<<"$state" && break
|
|
sleep 0.1
|
|
done
|
|
jq -e '.lastRepair.checkId == "panama.caffeine" and .lastRepair.accepted == false
|
|
and .lastRepair.exitCode == 0 and .generation == ($before + 1)' \
|
|
--argjson before "$mismatch_generation" >/dev/null <<<"$state" \
|
|
|| fail "mismatched repair JSON escaped containment: $state"
|
|
|
|
# A refresh arriving after repair settlement but before the deferred mandatory
|
|
# scan is coalesced into that scan instead of starting an extra generation.
|
|
pending_race="$(run ipc call health-test pendingRefreshRace)"
|
|
jq -e '.accepted == false' >/dev/null <<<"$pending_race" \
|
|
|| fail "refresh escaped the post-repair pending window: $pending_race"
|
|
pending_generation="$(jq -r .before <<<"$pending_race")"
|
|
for _ in $(seq 1 120); do
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false' \
|
|
--argjson before "$pending_generation" >/dev/null <<<"$state" && break
|
|
sleep 0.1
|
|
done
|
|
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false' \
|
|
--argjson before "$pending_generation" >/dev/null <<<"$state" \
|
|
|| fail "pending-window refresh created duplicate scans: $state"
|
|
|
|
# External IPC cannot bypass an authored confirmation. The same current row is
|
|
# still repairable through Settings' external=false path after UI confirmation.
|
|
confirm_generation="$(jq -r .generation <<<"$state")"
|
|
[[ "$(run ipc call health-test accept "$confirm_snapshot" "$confirm_generation")" == "true" ]] \
|
|
|| fail 'confirmation fixture was rejected'
|
|
before_repair_lines="$(wc -l <"$repair_log")"
|
|
[[ "$(run ipc call health-test externalRepair desktop.quickshell)" == "false" ]] \
|
|
|| fail 'external repair bypassed confirmation'
|
|
[[ "$(wc -l <"$repair_log")" == "$before_repair_lines" ]] \
|
|
|| fail 'external confirmation rejection started a process'
|
|
[[ "$(run ipc call health-test repair desktop.quickshell)" == "true" ]] \
|
|
|| fail 'confirmed Settings repair was refused'
|
|
for _ in $(seq 1 120); do
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.busy == false and .generation == ($before + 1)' \
|
|
--argjson before "$confirm_generation" >/dev/null <<<"$state" && break
|
|
sleep 0.1
|
|
done
|
|
jq -e '.lastRepair == {schemaVersion:1, checkId:"desktop.quickshell", accepted:true, exitCode:0, message:"Panama shell restart was requested."}
|
|
and .generation == ($before + 1)' --argjson before "$confirm_generation" \
|
|
>/dev/null <<<"$state" || fail "confirmed Settings repair did not complete safely: $state"
|
|
[[ "$(grep -Fc -- '--repair desktop.quickshell --json' "$repair_log")" == 1 ]] \
|
|
|| fail 'confirmed Settings repair did not start exactly one repair process'
|
|
|
|
[[ "$(run ipc call health-test repair unknown.check)" == "false" ]] \
|
|
|| fail 'unknown check started a repair'
|
|
[[ "$(run ipc call health-test repair integration.calendar)" == "false" ]] \
|
|
|| fail 'non-repairable check started a repair'
|
|
state="$(run ipc call health-test status)"
|
|
jq -e '.repairingId == "" and .generation == ($before + 1)' --argjson before "$confirm_generation" \
|
|
>/dev/null <<<"$state" || fail "rejected repair altered process state: $state"
|
|
|
|
python3 - "$service" <<'PY' || fail 'external repair failure notification is not bounded'
|
|
import sys
|
|
|
|
source = open(sys.argv[1], encoding="utf-8").read()
|
|
assert 'if (failed && external && !failureNotification.running)' in source
|
|
assert '"notify-send", "-a", "Panama", "-i", "dialog-error-symbolic"' in source
|
|
assert '"Panama action failed", "The requested health repair could not be completed."' in source
|
|
PY
|
|
|
|
trap - EXIT
|
|
cleanup
|
|
printf 'health service contract: PASS\n'
|