Design Panama Health and Recovery
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user