236 lines
11 KiB
Markdown
236 lines
11 KiB
Markdown
# Panama Health & Recovery Design
|
|
|
|
## Purpose
|
|
|
|
Panama Health & Recovery makes the desktop explain itself. It verifies the
|
|
local services, dependencies, links, and integrations that Panama relies on,
|
|
then presents useful recovery actions without asking the user to read logs or
|
|
diagnose a collection of unrelated Linux processes.
|
|
|
|
The feature is intentionally quiet. A healthy desktop produces no notification,
|
|
banner, or permanent bar ornament. Problems appear in Panama Settings and, when
|
|
actionable, as one restrained bar indicator. User-initiated repairs receive
|
|
immediate Prism OSD or inline feedback.
|
|
|
|
## Product boundaries
|
|
|
|
The first release covers Panama-owned or Panama-integrated functionality:
|
|
|
|
- Hyprland, Quickshell, the notification server, XDG desktop portals, PipeWire,
|
|
Vicinae, the clipboard watcher, wallpaper, idle policy, and Panama's runtime
|
|
configuration links.
|
|
- The Panama command collection, screenshot and OCR dependencies, DDC
|
|
brightness support, and the currently selected terminal and launcher.
|
|
- Nextcloud, RustDesk, KDE Connect, BlueBubbles, Home Assistant, calendar
|
|
aggregation, and the configured autostart entries.
|
|
- Orphaned Panama processes and inhibitors, including duplicate Caffeine locks.
|
|
- Versions and non-sensitive diagnostic context needed for a useful copied
|
|
report.
|
|
|
|
It does not become a package manager, a generic system monitor, or a replacement
|
|
for Fedora's troubleshooting tools. It never installs packages, invokes `sudo`,
|
|
deletes user data, rewrites arbitrary configuration, or repairs services Panama
|
|
does not own.
|
|
|
|
An optional integration that has never been configured is neutral **Not set
|
|
up**, not a warning. A configured integration that cannot operate is degraded.
|
|
This distinction prevents the health UI from pressuring the user to enable
|
|
features they do not want.
|
|
|
|
## Information architecture
|
|
|
|
The existing **Startup & Services** destination becomes **System Health**. This
|
|
avoids two pages reporting the same background services. Its existing Open and
|
|
Refresh actions remain available through the richer health rows.
|
|
|
|
The page has four levels:
|
|
|
|
1. A compact summary hero: **Healthy**, **Needs attention**, or **Action
|
|
required**, the last completed scan time, Refresh, and Copy Report.
|
|
2. An issues-first section shown only when one or more checks are degraded.
|
|
3. Grouped cards for Desktop Foundation, Input & Media, Integrations, and Panama
|
|
Tools. Healthy rows remain visible but visually quiet.
|
|
4. A short boundary note linking to GNOME or Fedora tools for system areas Panama
|
|
does not own.
|
|
|
|
Each row contains a stable title, one-sentence observation, status label, and at
|
|
most one primary action. Actions use concrete language such as **Restart
|
|
Vicinae**, **Repair command link**, **Open Home settings**, or **View setup
|
|
instructions**. There is no generic Fix Everything button.
|
|
|
|
The Settings sidebar's existing health footer becomes real and clickable. It
|
|
shows the aggregate state and opens System Health. The top bar gains a small
|
|
`HealthIndicator` only while an actionable warning or error exists; clicking it
|
|
opens the same page. Background scans never publish Signal Glass events or
|
|
desktop notifications.
|
|
|
|
## Diagnostic engine
|
|
|
|
`config/dot/quickshell/scripts/panama-doctor` is the single operating-system
|
|
boundary. It supports:
|
|
|
|
- `panama-doctor --json` for a complete versioned snapshot.
|
|
- `panama-doctor --summary` for a concise human-readable installer or terminal
|
|
result.
|
|
- `panama-doctor --repair CHECK_ID --json` for an explicitly allow-listed repair.
|
|
|
|
The helper emits one schema:
|
|
|
|
```json
|
|
{
|
|
"schemaVersion": 1,
|
|
"generatedAt": "2026-08-18T12:00:00Z",
|
|
"summary": {
|
|
"status": "warning",
|
|
"healthy": 18,
|
|
"warnings": 1,
|
|
"errors": 0,
|
|
"unconfigured": 2
|
|
},
|
|
"checks": [
|
|
{
|
|
"id": "launcher.panama-commands",
|
|
"group": "panama-tools",
|
|
"title": "Panama Commands",
|
|
"status": "warning",
|
|
"detail": "16 of 17 commands are loaded",
|
|
"action": {
|
|
"kind": "repair",
|
|
"label": "Repair command link"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Allowed statuses are `ok`, `warning`, `error`, and `unconfigured`. Check IDs,
|
|
group IDs, titles, and repair mappings are authored constants. Probe output may
|
|
populate observations but can never become a command or executable argument.
|
|
|
|
Checks run concurrently where doing so is safe, with short per-probe timeouts.
|
|
A failed or timed-out probe yields a check result rather than aborting the whole
|
|
snapshot. Output order is deterministic so tests, copied reports, and visual
|
|
rows do not jump between scans.
|
|
|
|
No secrets are read. The report may state whether a Home Assistant URL or token
|
|
is configured, but never includes either value. It excludes clipboard contents,
|
|
notification bodies, calendar event data, SSIDs, device addresses, environment
|
|
values, file contents, and command output that has not been explicitly parsed.
|
|
|
|
## Quickshell state and refresh model
|
|
|
|
`services/Health.qml` owns the latest accepted snapshot, aggregate severity,
|
|
busy state, last scan time, and the result of the most recent repair. It invokes
|
|
`panama-doctor` with argument arrays through `Process`; UI components never
|
|
construct shell commands.
|
|
|
|
Health performs one delayed scan after the shell reaches a stable startup state.
|
|
It scans again when the System Health page is opened, when the user presses
|
|
Refresh, and after a repair settles. There is no periodic polling loop while the
|
|
desktop is idle. Services that already expose event-driven state remain the
|
|
authoritative source for their own interactive controls; Health is a diagnostic
|
|
snapshot, not a competing live service model.
|
|
|
|
Every scan receives a monotonically increasing generation. Late output from an
|
|
older scan is discarded. A malformed snapshot leaves the last valid result in
|
|
place, marks the diagnostic engine unavailable, and offers a bounded Retry.
|
|
|
|
The shell exposes a typed `health` IPC target with `refresh`, `status`, `open`,
|
|
and `repair(id)` operations. Vicinae gains **Panama: Check System Health**, which
|
|
opens the page and requests a fresh scan through the existing `panama-action`
|
|
dispatcher.
|
|
|
|
## Repair policy
|
|
|
|
Repairs are narrow, reversible, and attached to one check. The first release may:
|
|
|
|
- Restart Panama's user services such as Vicinae, Hyprpaper, or Hypridle.
|
|
- Recreate Panama-owned symlinks when their destination is known and tracked.
|
|
- Reload Vicinae's Panama command collection.
|
|
- Release duplicate user-owned inhibitors whose metadata identifies Panama and
|
|
Caffeine.
|
|
- Restart Quickshell through the verified `panama-action restart-shell` path.
|
|
- Open the exact Panama Settings page required to finish credentials or entity
|
|
selection.
|
|
|
|
Restarting a working service is not presented as a repair. Repairs that interrupt
|
|
visible desktop chrome require a confirmation sheet in Settings. Navigation and
|
|
setup actions do not. Package installation, privileged service changes, display
|
|
mode writes, and destructive cleanup are never automatic; the UI shows concise
|
|
instructions instead.
|
|
|
|
After a repair, Health rescans and judges success from the observed result. A
|
|
zero exit status alone never turns a row green. Failure remains inline on the
|
|
affected row and also produces the existing Panama action-failure notification
|
|
when the action originated outside Settings.
|
|
|
|
## Visual language and interaction
|
|
|
|
System Health uses the established Settings cards and Prism tokens. Healthy
|
|
states use a small muted green dot and subdued **Healthy** copy. Warnings use
|
|
amber; red is reserved for functionality that is configured, required, and
|
|
currently broken. `unconfigured` rows use neutral gray.
|
|
|
|
The summary hero does not use a decorative gauge, percentage score, pulse,
|
|
shimmer, or animated gradient. A desktop is not “82% healthy.” The headline and
|
|
issue count are more understandable and do not create false precision.
|
|
|
|
Rows keep their height stable while refreshing. The previous snapshot remains
|
|
visible with a quiet **Checking…** label rather than replacing the page with a
|
|
spinner. Keyboard focus order reaches Refresh, Copy Report, issue rows, repair
|
|
actions, and external handoffs. Status is always expressed in text as well as
|
|
color.
|
|
|
|
Before production components are edited, the page and degraded bar indicator
|
|
will be shown in several static mocks using the existing Settings geometry. The
|
|
chosen mock must preserve this information architecture and Panama's current
|
|
Prism language rather than introduce a new visual system.
|
|
|
|
## Failure handling
|
|
|
|
- Missing required executables become actionable check results.
|
|
- Missing optional applications remain neutral until configured.
|
|
- A doctor crash, timeout, or malformed JSON does not clear the last good
|
|
snapshot or crash Quickshell.
|
|
- Concurrent refresh requests coalesce into one follow-up scan.
|
|
- A repair request for an unknown or non-repairable ID is rejected before any
|
|
process starts.
|
|
- Copy Report uses only the already-redacted snapshot and reports clipboard
|
|
failure inline.
|
|
- If the Settings window is closed during a scan or repair, the process may
|
|
finish; reopening the page shows the settled result.
|
|
|
|
## Verification
|
|
|
|
- Run the real helper against isolated fake command, config, state, and runtime
|
|
directories and prove every status transition deterministically.
|
|
- Validate the JSON schema, stable check IDs, deterministic ordering, and
|
|
uniqueness of each ID.
|
|
- Prove unconfigured integrations remain neutral while configured failures are
|
|
degraded.
|
|
- Prove reports contain no fixture secrets, clipboard text, calendar data,
|
|
addresses, or unparsed environment values.
|
|
- Exercise every repair through the allow-list, assert its exact command, and
|
|
prove unknown IDs cannot execute anything.
|
|
- Test scan generations, malformed snapshots, refresh coalescing, repair
|
|
rescans, and preservation of the last valid state in a Quickshell harness.
|
|
- Verify Settings routing, search entries, the live sidebar footer, and the
|
|
degraded-only bar indicator without QML warnings.
|
|
- Validate the Vicinae command and typed IPC surface.
|
|
- Run a read-only doctor scan on the real workstation and compare key results to
|
|
direct service checks. State-changing live repair tests require an actually
|
|
degraded disposable target or explicit user approval.
|
|
- Restart the live shell, inspect the fresh log, and visually review healthy,
|
|
warning, error, unconfigured, refreshing, and repair-result states.
|
|
|
|
## Delivery slices
|
|
|
|
1. Diagnostic schema, read-only probes, redaction, and contract tests.
|
|
2. `Health.qml`, typed IPC, startup/manual refresh, and fixture harness.
|
|
3. System Health Settings page, live sidebar footer, search, and report copy.
|
|
4. Degraded-only bar indicator and Vicinae command.
|
|
5. Allow-listed repairs, confirmations, post-repair verification, and live audit.
|
|
|
|
The slices are one feature and land together. Their order keeps the UI backed by
|
|
real diagnostics from its first production render.
|