Finish the wonderland: System told truthfully, in eight tabs instead of ten
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -33,8 +33,13 @@ state_home="$home/.local/state"
|
||||
runtime_dir="$fixture/runtime"
|
||||
bin_dir="$fixture/bin"
|
||||
data_home="$home/.local/share"
|
||||
# The updates check reads the Updates page's cache out of XDG_CACHE_HOME rather
|
||||
# than through DoctorConfig, so without this the fixture would read the real
|
||||
# machine's update state and report whatever happened to be pending today.
|
||||
cache_home="$home/.cache"
|
||||
|
||||
mkdir -p "$config_home" "$state_home" "$runtime_dir" "$bin_dir" "$data_home/vicinae/scripts"
|
||||
mkdir -p "$config_home" "$state_home" "$runtime_dir" "$bin_dir" "$data_home/vicinae/scripts" \
|
||||
"$cache_home/panama"
|
||||
|
||||
# A mount table with the document portal present, which is the healthy state the
|
||||
# rest of this file assumes. Written rather than read from /proc so the contract
|
||||
@@ -114,6 +119,7 @@ run_doctor() {
|
||||
HOME="$home" \
|
||||
PATH="$bin_dir" \
|
||||
XDG_CURRENT_DESKTOP=Hyprland \
|
||||
XDG_CACHE_HOME="$cache_home" \
|
||||
PANAMA_HOME_ASSISTANT_URL='https://fixture.invalid' \
|
||||
PANAMA_HOME_ASSISTANT_TOKEN='fixture-secret-token' \
|
||||
PANAMA_DOCTOR_ROOT="$repo_dir" \
|
||||
@@ -803,4 +809,177 @@ for rejected_id in unknown.check integration.home-assistant input.brightness \
|
||||
[[ "$(fixture_state)" == "$before_state" ]] || fail "$rejected_id mutated the filesystem"
|
||||
done
|
||||
|
||||
# ── Every check in the order has a title ────────────────────────────────────
|
||||
#
|
||||
# `unavailable_check` is the doctor's own containment: a probe that raises
|
||||
# becomes a warning row rather than a crashed report. It reads the title out of
|
||||
# CHECK_TITLES by key, and `panama.updates` was never added there -- so the one
|
||||
# path that exists to keep a failing probe from taking the report down was
|
||||
# itself a KeyError, raised inside the `except` handler that was catching the
|
||||
# original failure, from where it escaped `collect_checks`, hit `snapshot`'s
|
||||
# outer guard, and raised again building the all-unavailable fallback.
|
||||
#
|
||||
# Nobody saw it, because it needs the updates probe to fail, and the updates
|
||||
# probe reads a cache file and almost never does. Both halves are asserted:
|
||||
# the invariant, which is cheap and total, and the path, which is the one that
|
||||
# actually ran.
|
||||
/usr/bin/python3 - "$doctor" <<'PY' || fail 'a check in CHECK_ORDER has no title, so a failing probe raises KeyError from inside the handler that exists to contain it'
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
import sys
|
||||
|
||||
loader = importlib.machinery.SourceFileLoader("panama_doctor_titles", sys.argv[1])
|
||||
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
loader.exec_module(module)
|
||||
|
||||
missing = [check for check in module.CHECK_ORDER if check not in module.CHECK_TITLES]
|
||||
if missing:
|
||||
raise SystemExit(f"no title for {missing}")
|
||||
for check in module.CHECK_ORDER:
|
||||
module.unavailable_check(check)
|
||||
PY
|
||||
|
||||
/usr/bin/python3 - "$doctor" "$fixture/unavailable-home" <<'PY' || fail 'a probe that raises does not become a warning row; it takes the whole report with it'
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
doctor_path, home_text = sys.argv[1:]
|
||||
loader = importlib.machinery.SourceFileLoader("panama_doctor_unavailable", doctor_path)
|
||||
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
loader.exec_module(module)
|
||||
|
||||
home = Path(home_text)
|
||||
home.mkdir(parents=True)
|
||||
config = module.DoctorConfig(home, home, home / "config", home / "state", home / "runtime", "", 0.05)
|
||||
|
||||
|
||||
def raising(_config):
|
||||
raise TimeoutError("fixture probe timeout")
|
||||
|
||||
|
||||
module.check_updates = raising
|
||||
report = module.snapshot(config)
|
||||
ids = [check["id"] for check in report["checks"]]
|
||||
if ids != list(module.CHECK_ORDER):
|
||||
raise SystemExit("a raising probe changed the shape of the report")
|
||||
row = next(check for check in report["checks"] if check["id"] == "panama.updates")
|
||||
if row["status"] != "warning" or not row["title"]:
|
||||
raise SystemExit(f"the contained row is not a titled warning: {row}")
|
||||
PY
|
||||
|
||||
# ── The updates check knows where Software Update is ────────────────────────
|
||||
#
|
||||
# Two of its four states offered "Open Software Update" with no target, so the
|
||||
# button rendered and did nothing. Adding the target is only half the change --
|
||||
# Health.settingsTargets has to accept it, or the whole report is rejected --
|
||||
# and health-service-contract pins the other half against this same file.
|
||||
/usr/bin/python3 - "$cache_home/panama/updates.json" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
|
||||
json.dump({
|
||||
"checkedAt": int(time.time()),
|
||||
"dnf": {"count": 5, "securityCount": 3},
|
||||
"flatpak": {"count": 0},
|
||||
"firmware": {"count": 0},
|
||||
}, open(sys.argv[1], "w"))
|
||||
PY
|
||||
pending_updates="$(run_doctor --json)"
|
||||
check_status "$pending_updates" panama.updates warning
|
||||
jq -e '.checks[] | select(.id == "panama.updates")
|
||||
| .action == {kind:"open", label:"Open Software Update", confirm:false, target:"updates"}' \
|
||||
>/dev/null <<<"$pending_updates" || fail 'the updates action carries no Settings target, so the button does nothing'
|
||||
assert_schema_and_redaction "$pending_updates"
|
||||
|
||||
# ── A repair row says what it will run ──────────────────────────────────────
|
||||
#
|
||||
# The command is the literal from REPAIR_COMMANDS and nothing else: derived
|
||||
# from the table rather than restated here, so a repair whose argv changes
|
||||
# cannot leave the row describing the old one, and probe output can never reach
|
||||
# this field.
|
||||
repairable="$(PANAMA_DOCTOR_MOUNTINFO="$fixture/mountinfo-unmounted" run_doctor --json)"
|
||||
check_status "$repairable" desktop.document-portal warning
|
||||
printf '%s' "$repairable" >"$fixture/repairable-report.json"
|
||||
/usr/bin/python3 - "$doctor" "$fixture/repairable-report.json" <<'PY' || fail 'a repairable check does not carry the exact authored repair command'
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
|
||||
loader = importlib.machinery.SourceFileLoader("panama_doctor_repair_command", sys.argv[1])
|
||||
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
loader.exec_module(module)
|
||||
|
||||
report = json.load(open(sys.argv[2], encoding="utf-8"))
|
||||
expected = {check: " ".join(command) for check, command in module.REPAIR_COMMANDS.items()}
|
||||
|
||||
seen = 0
|
||||
for check in report["checks"]:
|
||||
rendered = check.get("repairCommand")
|
||||
if check["id"] in expected and check.get("action", {}).get("kind") == "repair":
|
||||
if rendered != expected[check["id"]]:
|
||||
raise SystemExit(f'{check["id"]} shows {rendered!r}, expected {expected[check["id"]]!r}')
|
||||
seen += 1
|
||||
elif rendered is not None and rendered != expected.get(check["id"]):
|
||||
raise SystemExit(f'{check["id"]} shows a command that is not its authored one: {rendered!r}')
|
||||
if not seen:
|
||||
raise SystemExit("no repairable check carried a command, so this proves nothing")
|
||||
PY
|
||||
|
||||
# ── One check, asked for on its own ─────────────────────────────────────────
|
||||
#
|
||||
# The whole scan is thirty probes. Re-checking the one row somebody just fixed
|
||||
# should not wait on the other twenty-nine, so there is a verb that runs one --
|
||||
# and it answers in the same envelope as a full report, because the consumer is
|
||||
# the same parser and a second response shape is a second thing to get wrong.
|
||||
single="$(run_doctor check desktop.hyprpaper)" || fail 'a single-check run failed'
|
||||
jq -e '.schemaVersion == 1
|
||||
and (.generatedAt | type == "string")
|
||||
and (.summary.status | IN("healthy", "warning", "error"))
|
||||
and (.context.session | IN("hyprland", "other"))
|
||||
and (.context.versions | type == "array")
|
||||
and (.checks | length) == 1
|
||||
and (.checks[0] | has("id") and has("group") and has("title") and has("status") and has("detail"))
|
||||
and .checks[0].id == "desktop.hyprpaper"' \
|
||||
>/dev/null <<<"$single" || fail "a single check is not the full report shape: $single"
|
||||
[[ "$(jq -r '.summary | [.healthy, .warnings, .errors, .unconfigured] | add' <<<"$single")" == "1" ]] \
|
||||
|| fail 'the single-check summary counts something other than the one check it ran'
|
||||
! grep -Fq 'fixture-secret-token' <<<"$single" || fail 'a single check exposed a fixture secret'
|
||||
|
||||
# An id nobody authored is refused rather than answered with an empty
|
||||
# snapshot, which would look valid and say nothing. The refusal is an exit
|
||||
# status and a message, not a report: a caller that asked for a check that does
|
||||
# not exist has a bug, and handing it a well-formed reply hides it.
|
||||
for rejected_id in unknown.check ../../escape 'desktop.vicinae;touch injected' ''; do
|
||||
before_state="$(fixture_state)"
|
||||
set +e
|
||||
single_rejected="$(run_doctor check "$rejected_id" 2>"$fixture/single-check-error")"
|
||||
single_status=$?
|
||||
set -e
|
||||
[[ "$single_status" != 0 ]] \
|
||||
|| fail "the single-check verb accepted \"$rejected_id\""
|
||||
[[ -z "$single_rejected" ]] \
|
||||
|| fail "the single-check verb printed a report for \"$rejected_id\": $single_rejected"
|
||||
[[ -s "$fixture/single-check-error" ]] \
|
||||
|| fail "the single-check verb refused \"$rejected_id\" without saying why"
|
||||
rm -f "$fixture/single-check-error"
|
||||
[[ "$(fixture_state)" == "$before_state" ]] \
|
||||
|| fail "the single-check verb mutated the filesystem for \"$rejected_id\""
|
||||
done
|
||||
|
||||
# And it is not a second way to run the whole scan, or to run a repair.
|
||||
run_doctor check desktop.hyprpaper --summary >/dev/null 2>&1 \
|
||||
&& fail 'the single-check verb accepted a second output mode'
|
||||
run_doctor check desktop.vicinae --repair desktop.vicinae >/dev/null 2>&1 \
|
||||
&& fail 'the single-check verb accepted a repair alongside it'
|
||||
|
||||
printf 'panama doctor contract: PASS\n'
|
||||
|
||||
Reference in New Issue
Block a user