From 77d71b384028410cefa27544559e704013f85ef6 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 13 Oct 2026 11:10:52 +0200 Subject: docs(spec): performance panel from the conky widgets Sub-project 4. An icon in the status pill opens a card grid of CPU, RAM, temperatures, GPU, disks and network, read from the same /proc, /sys and hwmon sources conky uses. The icon warns on temperatures, RAM, disks and a public IP that drifts from a pinned address, since the VPN depends on the ISP's fixed IP. CPU load is left out of the icon because spikes would flicker it. The four conky widgets are removed once the panel is verified beside them. Co-Authored-By: Claude Opus 5.5 --- .../specs/2026-10-13-performance-panel-design.md | 198 +++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-13-performance-panel-design.md (limited to 'docs/superpowers') diff --git a/docs/superpowers/specs/2026-10-13-performance-panel-design.md b/docs/superpowers/specs/2026-10-13-performance-panel-design.md new file mode 100644 index 0000000..a6818c3 --- /dev/null +++ b/docs/superpowers/specs/2026-10-13-performance-panel-design.md @@ -0,0 +1,198 @@ +# Performance panel design + +A performance panel that drops from the island's status pill: CPU, RAM, +temperatures, GPU, disks and network, ported from the four conky widgets that +show them today (`system`, `gpu`, `disks`, `network` in conky-theme-udt). An +icon in the status pill opens it and turns yellow or red when something needs +attention, including the public IP drifting from the address the user's VPN +depends on. This is sub-project 4 of the roadmap in +`2026-10-07-island-core-design.md`. + +Once the panel is verified, the four conky widgets are removed: two dashboards +drawing the same numbers would drift apart. + +## Scope + +In v1: + +- A 3-column card grid: CPU (per-core bars, RAM, temperatures), GPU, network + (rate graph, LAN and public IP, pin button), disks. +- A status-pill icon tinted by the worst severity of temperatures, RAM, disks + and the public IP check. +- A pinned public IP, set from the panel, and a red warning on mismatch. +- Removal of the four conky widgets and their samplers. + +Not in v1: a drawer page (sub-project 6 reuses `Perf.qml`); history beyond the +network graph; process lists; GPU utilisation (the xe driver exposes none, see +below); auto-discovered mounts; a keybind. + +## Where it lives + + desktop/island/perf/ + Perf.js pure parsing and maths, node-tested + test_perf.js node test for Perf.js + Perf.qml singleton: FileViews, Processes, Timers; exposes state + PerfPanel.qml the card grid + desktop/island/StatusPill.qml + the performance icon + desktop/island/Island.qml + panel "perf" + desktop/Prefs.qml + pinnedIp + +## Data sources + +All of these are what conky reads today; nothing new is measured. + +| Figure | Source | When | +| --- | --- | --- | +| CPU load, aggregate | `/proc/stat` deltas | always, 2s | +| CPU load, per core | `/proc/stat` `cpuN` lines | panel open, 2s | +| RAM | `/proc/meminfo`, `MemTotal - MemAvailable` | always, 2s | +| temperatures | hwmon `temp*_input` | always, 2s | +| GPU fan | hwmon `xe` `fan1_input` | panel open, 2s | +| VRAM used | `/proc/[0-9]*/fdinfo/*`, `drm-resident-vram0` summed per `drm-client-id` for `drm-driver: xe` | panel open, 2s | +| disks | `timeout 5 /usr/bin/df -P -B1 ` | always, 60s | +| network rate | `/sys/class/net/br0/statistics/{rx,tx}_bytes` | panel open, 1s | +| LAN address | `ip -4 addr show br0`, memoized on first success | panel open | +| public IP | `curl -fsS --max-time 10 https://ipinfo.io/ip` | 30 min, and on panel open if stale | + +Reads of `/proc` and `/sys` are `FileView`s reloaded by a `Timer`, no +subprocess. `df`, the fdinfo scan, `ip` and `curl` are `Process` calls; each +`Process` reused for a sequence sets `running = false` before each start. + +`Perf.detailed` is true while the panel is open and gates the rows marked +"panel open", the way `Virsh.sampling` gates the VM stats. The always rows +exist so the icon can warn while the panel is closed. + +### Sensors + +hwmon chips are found by their `name` file once at start, because `hwmonN` +numbering changes across boots. The table is conky's: + +| Chip | File | Label | Warn | Crit | +| --- | --- | --- | --- | --- | +| `k10temp` | `temp1_input` | CPU | 75 | 90 | +| `k10temp` | `temp3_input` | CCD1 | 75 | 90 | +| `nvme` | `temp1_input` | NVME | 60 | 70 | +| `gigabyte_wmi` | `temp2_input` | BOARD | 60 | 70 | +| `gigabyte_wmi` | `temp3_input` | BOARD | 60 | 70 | +| `xe` | `temp2_input` | GPU | 75 | 85 | +| `xe` | `temp3_input` | VRAM | 80 | 90 | + +The GPU has no utilisation figure: xe exposes no `gpu_busy_percent` and +`intel_gpu_top` refuses the device. The integrated AMD GPU is not shown. + +### Host constants + +Kept in `Perf.qml`, each marked `ponytail:` with its ceiling, as conky had +them: the mount list (`/`, `/home`, `/data`, `/mnt/nfs/Library`, +`/mnt/nfs/shared`, one NFS mount per server), the interface `br0` (a bridge, so +VM-to-host traffic shows in the graph), and 12 GiB of VRAM (xe puts no +capacity in sysfs). Mount icons are conky's, re-checked in Inconsolata Nerd +Font: Slackware for `/`, house for `/home`, hard disk for `/data`, network +share for NFS, where the label is the server address read from the mount's +device field, so no address is committed. + +## Public IP + +The fetch writes conky's cache format to `~/.cache/udt/pubip.txt` +(`ip ` and `fetched ` lines, atomic), so the existing file is +reused. A response that is not an IPv4 address is discarded and the cache left +alone. A value older than 4 hours is shown as a dash. + +A pin button beside the address stores the current address as +`perf.pinnedIp` in `desktop.json` through `Prefs`, which gains a `pinnedIp` +property and `setPinnedIp()`, written only on change like `setControls()`. The +address lives in the user's state file, never in the repo. Pressing the pin +again with the same address does nothing; a different address replaces it. + +The check: + +| State | Result | +| --- | --- | +| no pin | ok | +| fresh fetch equals pin | ok | +| fresh fetch differs from pin | crit | +| fetch failed, or value stale | ok, address shown as a dash or with its age | + +A failed fetch is never a mismatch: a dropped connection must not raise the +alarm. + +## The icon + +`utilities-system-monitor` through `Quickshell.iconPath`, placed before the +controls icon in the status pill. It is tinted by the worst severity: + +| Input | Warn | Crit | +| --- | --- | --- | +| each temperature | its warn | its crit | +| RAM | 85% | 95% | +| each disk | 90% | 95% | +| public IP | | mismatch with the pin | + +Neutral when ok, `Theme.yellow` on warn, `Theme.red` on crit. Not the accent, +which udt can snap onto a state colour. CPU load is left out: spikes are +normal and would flicker the icon, and sustained load shows up as heat. + +Left-click toggles the panel. No right-click until a drawer page exists. The +status pill expands for `perf` as it does for `sound` and `controls`. + +## The panel + +A grid of three columns, the same palette and type as the other island panels: + +- **CPU**, spanning two rows: aggregate load as the headline, the CPU model, + one bar per core, RAM used and total with a bar, then the temperature rows + for CPU, CCD1, NVME and both BOARD sensors. +- **GPU**: package temperature as the headline, VRAM used and total with a + bar, VRAM temperature, fan rpm. +- **Network**: download and upload as two lines over a 60-point history, + current rates, LAN address, public IP with its pin button. The public IP is + red on mismatch. +- **Disks**, spanning two columns: one row per mount with icon, label, + percentage and bar. + +Colours follow conky's bands so the numbers read as before: load, per-core +bars, RAM and disk bars at 25 and 75; temperatures at each sensor's own warn +and crit. Escape closes the panel, as for the other panels. + +## Errors + +- A missing chip, file or interface shows a dash and counts as ok for the + icon. +- `df` under `timeout 5`: a hung NFS server keeps the last value, or a dash + before there is one. The island never blocks. +- VRAM counts only processes readable by the user, so a system service's GPU + use is missing. Noted as a ceiling, as in conky. +- The network history is cleared when the panel closes; it is not sampled + while closed. + +## Conky removal + +In conky-theme-udt, after the panel is verified on screen beside the conky +widgets, in that repo's own commits: + +- Delete `widgets/system.lua`, `gpu.lua`, `disks.lua`, `network.lua` and their + entries in the `dashboard.lua` layout. +- Drop `disks-sample.sh` and `pubip-sample.sh` from `conky.text` and delete + them; the island owns the public IP fetch, and two fetchers would double the + outside traffic. +- Remove readers in `lib/data.lua` used only by those widgets, each checked + against its remaining callers. +- Leave the other widgets where they are. Rearranging the freed space is the + user's call, on screen. + +## Testing + +- `node desktop/island/perf/test_perf.js`: `/proc/stat` aggregate and per-core + deltas, meminfo, `df -P -B1` parsing, the fdinfo sum with duplicate client + ids, the network rate across a counter reset, severity across every input, + the IP check (no pin, match, mismatch, failed, stale), and the cache file + format both ways. +- A smoke run of `qs -p desktop` reading the log, after the user restarts the + desktop component, since the new directory needs a reindex. +- On screen, by the user: the panel beside the conky widgets before they are + removed, the icon colours, the pin button. + +## AGENTS.md + +Add any gotcha found while building. The island's README gains the panel and +the icon thresholds. -- cgit v1.2.3