Crash-capture logger (M3): - crash-safe JSONL (fsync per sample), size-based rotation, GPU-lost/recovered markers, atomic status file - CLI: record run/start/stop/status/report (run = systemd-ready entrypoint) - shared core.reccontrol so CLI + GUI drive the same recorder - crashlog tests (writer, rotation, reader, summary, recorder) GUI: - Recording/Logs page: start/stop/interval controls, live status, post-crash report - shared render helpers (format_raw/headline, render_summary) Docs/decisions: - GUI-first (D17); CLI keeps full parity - D8 revised: user-local self-updating install primary, .deb optional - planned: M12 session sharing (D16), M13 no-root auto-update from public repo (D18) - versioning + CHANGELOG convention (D19) Infra: - .gitea/workflows/release.yml: build wheel+sdist and publish a Gitea release v<version> on push to main - align version to the 0.0.x release line; bump to 0.0.2 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
RigDoctor — Decisions & Open Questions
Format: each item is OPEN (needs a call) or DECIDED (with date + rationale). Decisions D1–D19 are settled (D1–D15 on 2026-05-21); the original open questions are kept below with their resolutions so the reasoning is traceable. No tracked decisions are currently open.
Decided
D1 — Project name — DECIDED 2026-05-21
RigDoctor. Confirmed as the final name (repo, package, and CLI command rigdoctor).
Alternatives (RigWatch, GameDoc, Penguin Pit Crew, LGD) dropped.
D2 — Language / runtime — DECIDED 2026-05-21
Python 3 + Qt (PySide6).
- Why Python: fastest AI-assisted development (largest codegen corpus) and a perfect fit
for the real workload — parsing
nvidia-smi/sysfs/journalctl, CSV/JSON, subprocess. - Why Qt/PySide6: one toolkit covers both the desktop GUI and the system-tray applet.
- Layering that preserves "low overhead": the core engine, CLI, and crash-logger daemon stay stdlib-only (no hard deps, tiny footprint); only the GUI and tray modules pull in PySide6. This maps cleanly onto the modular installer — a headless/server user never installs Qt.
- Trade-off accepted: the GUI carries a Qt runtime dependency (not a single static binary).
Mitigated by shipping a
.debthat declarespython3+python3-pyside6(see D8).
D3 — Distro priority order — DECIDED 2026-05-21
Ubuntu first, by an explicit margin. Debian comes along for free via apt. Arch
(pacman) / Fedora (dnf) / openSUSE (zypper) are best-effort later. The package-manager
and distro abstraction stays in the design so other distros can be added, but all primary
development, testing, and packaging target Ubuntu.
D4 — GPU vendor priority — DECIDED 2026-05-21
NVIDIA first. It's the seed hardware (RTX 3070) and the source of the motivating crash. AMD and Intel come later behind the vendor abstraction; nothing should hard-code NVIDIA in a way that blocks them.
D5 — MVP scope — DECIDED 2026-05-21
M1 + M3 + M4 (the Essential bundle), NVIDIA-only. This was the first build target — it captures the seed crash and explains the logs before any installer, multi-vendor, etc. work. (The MVP was built CLI-first; per D17 the GUI is now the primary interface going forward — the CLI keeps full parity.)
D6 — Crash-logger trigger model — DECIDED 2026-05-21
Let the user choose. All three modes are supported and selectable (installer + config):
- Always-on
systemd --userservice. - Game-launch-triggered (auto-start when a game/Steam session starts, stop after).
- Manual (CLI command, or the tray applet's "start recording" button). Still open: the exact game-launch detection mechanism — see D12.
D7 — Stress / repro module — DECIDED 2026-05-21
Out of scope. Module M7 is dropped. RigDoctor will not build or bundle stress/load generators. Users who want to reproduce load can run existing tools (gpu-burn, vkmark, stress-ng) themselves alongside the logger.
D8 — Distribution / packaging — DECIDED 2026-05-21; revised 2026-05-21 (see D18)
Primary: a user-local install (pipx/venv or a versioned bundle under ~/.local, owned by
the user) so the app can self-update from the public Gitea releases with no root (D18). A
.deb remains an optional system-install channel for users who prefer it (updated via
apt). Why the revision: the repo is public and we want frictionless, GUI-first self-updates,
which a root-owned system package can't apply silently. The interactive installer (M9) layers
module selection on top of either channel. AUR / Flatpak / COPR still later, if warranted.
D9 — Scope of action (read-only vs apply-fixes) — DECIDED 2026-05-21
Read-only + suggestions. RigDoctor diagnoses, monitors, and suggests actions in plain language (with the exact command where possible), but does not apply changes itself in this stage. Auto-applying fixes (governor, power profile, etc.) is a deliberate later milestone, gated behind explicit user consent when it lands.
D10 — GUI is a first-class deliverable — DECIDED 2026-05-21
The app must run three ways: (a) CLI-only / headless (full functionality from the terminal, works over SSH), (b) a desktop GUI, and (c) a system-tray / top-menu-bar applet with quick actions. This supersedes the original "terminal-first, GUI maybe later" non-goal. GUI and tray are separate optional modules over the shared core engine.
D11 — Tray / menu-bar applet — DECIDED 2026-05-21
A small always-available applet in the Linux top menu bar (system tray / StatusNotifierItem,
via Qt's QSystemTrayIcon; on Ubuntu/GNOME this surfaces through the AppIndicator
extension). Provides quick actions and at-a-glance status.
Still open: the exact set of quick actions/indicators — see D13.
D12 — Game-launch detection mechanism — DECIDED 2026-05-21
Layered approach, no root (logger stays a systemd --user service):
- Wrapper (precise, primary):
rigdoctor wrap %command%for per-game Steam launch options, plus an installer helper that registers RigDoctor as a global Steam compatibility tool (covers all Proton games without per-game edits). The same wrapper field works in Lutris/Heroic. Deterministic start/stop, knows the title, needs no watcher daemon. Build first. - Zero-config watcher (fallback): low-frequency poll of Steam's
RunningAppID(~/.steam/registry.vdf) plus a/procheuristic for non-Steam launchers, for users who won't edit launch options. Build later. - GameMode (opportunistic): if Feral
gamemodedis present, use its D-BusGameRegistered/GameUnregisteredsignals (viagdbus/busctl— no Python dbus dep).
- Explicitly rejected: root-only kernel mechanisms (proc-connector netlink
PROC_EVENTS, eBPF) — they'd force the logger to run as root. - Phasing: wrapper ships with the game-launch trigger mode (Phase 4); watcher + GameMode follow.
D13 — Tray / menu-bar applet: actions & indicators — DECIDED 2026-05-21
Live readouts (from M1) + a Run Diagnostic action.
- At-a-glance live data shown inline in the tray dropdown, refreshed periodically: CPU temp, GPU temp, memory used/total (e.g. "14 GB / 32 GB"). A status dot (normal / throttling / alert) is proposed alongside.
- Run Diagnostic — the primary action. Launches the guided diagnostic session (SPEC §4): prompts which game to focus on, starts a focused log collection for that game's session (M3, scoped via the D12 game detection), then scans/analyzes (M4) and presents the findings.
- Supporting actions (proposed minimal set): Open dashboard (M10), Start/Stop recording (manual trigger), Snapshot now, Quit.
D14 — Final installer module list & bundles — DECIDED 2026-05-21
Use the current MODULES.md catalog and bundles as final. Modules: M1, M2, M3, M4, M5,
M6, M8, M9, M10, M11 (M7 dropped). Bundles: Essential / Monitoring / Diagnostics /
Desktop UI (+ Custom). No further additions planned for v1.
D15 — Distro package-name mapping → apt-only — DECIDED 2026-05-21
What it was: RigDoctor's optional modules need a few system packages (smartmontools,
lm-sensors, dmidecode, python3-pyside6, AppIndicator). The same tool is named differently
per distro (e.g. lm-sensors on apt vs lm_sensors on pacman/dnf; Qt is python3-pyside6
on apt). Supporting multiple distros would require a table mapping each logical dependency to
the right package name per package manager.
Decision: apt-only. We maintain package names for Ubuntu/apt only and do not
build or maintain mappings for other package managers. A thin seam is left in the design so
another package manager could be added later, but multi-distro support is not a planned
deliverable. Revisit only if Ubuntu-only proves too narrow.
D16 — Session sharing / remote assist (M12) — DECIDED 2026-05-21
Build a session-sharing / remote-assist capability (new module M12) so a user (A) can let a helper (B) inspect their machine. Full ladder, built in order:
- Diagnostic bundle export —
share exportpackages inventory (M5) + recent capture log (M3) + a report into one file A sends to B; B opens it in RigDoctor. One-way, no live connection. Safest; build first. - Live read-only view — a small local server serving the live dashboard + logs read-only, reached over a user-chosen tunnel (Tailscale / cloudflared / SSH reverse tunnel — no RigDoctor-hosted relay, to keep the no-telemetry promise). Token-gated, short TTL, A approves and can kill instantly. No terminal.
- Gated interactive terminal — wrap an existing trusted tool (
tmate/sshx) rather than rolling our own; read-only link by default, read-write requires explicit per-session consent. This is a deliberate, consent-gated exception to the read-only stance (D9) — it's full machine access and must be treated as such.
Cross-cutting principles: explicit per-session consent; ephemeral, revocable tokens; clear permission escalation (view ≠ shell); no mandatory central relay; session audit log. Note: this adds M12 on top of the "final" list from D14; the catalog is updated accordingly.
D17 — GUI-first interface emphasis — DECIDED 2026-05-21
The desktop GUI (M10) is the primary, default interface for end users — it's the more user-friendly way in, and every capability (recording, reports, status, …) must be reachable from it. This supersedes the earlier "CLI-first / terminal-first" framing (updates D5 and the SPEC wording).
- The CLI is not removed: it keeps full functionality for headless / SSH / server / scripting use, and it's the engine the background daemon runs on.
- No change to layering (D2): the core, CLI, and daemon stay stdlib-only and must run without Qt. "GUI-first" is about emphasis and front-end parity, not dropping headless support.
D18 — Auto-update (M13) — PLANNED 2026-05-21
RigDoctor should check for a newer version on launch and self-update (new module M13). Mechanism (chosen): user-local, no-root self-update from the public repo.
- Install model (D8 revised): primary install is user-local (
~/.local), so the running app can replace its own files and update with no apt, no root, no password prompt. - Check: on launch, query the public Gitea releases API
(
/api/v1/repos/jessey/rigdoctor/releases/latest) over HTTPS; compare to the running version. - Apply: download the new release bundle, verify checksum/signature, stage it
(e.g.
~/.local/share/rigdoctor/versions/x.y.z), swap a symlink atomically, then restart (including thesystemd --userdaemon). - GUI-first (D17): a non-intrusive "update available" prompt + one-click apply;
rigdoctor updatein the CLI. - Security: HTTPS only; verify checksum/signature before swapping; never run unverified code.
- Privacy (no telemetry): version-check only — no tracking; auto-check is opt-out-able.
.debusers: the optional.debchannel updates via apt instead; auto-update targets the user-local install.- Caveat (to confirm before building): the Gitea instance currently requires sign-in for
API calls (
"Only signed in user is allowed to call APIs."), so anonymous version checks need the instance/repo set to allow anonymous access — or a separate public version endpoint (e.g. a static file or a mirror).
D19 — Versioning & changelog — DECIDED 2026-05-21
Track a version number on every change. SemVer-style MAJOR.MINOR.PATCH (pre-1.0: bump
PATCH for ordinary changes, MINOR for larger milestones). __version__
(rigdoctor/__init__.py) and pyproject.toml are the single source of truth and must match
the git release tag so the auto-updater (D18) can compare versions. Every change updates
CHANGELOG.md (Keep a Changelog style). Note: an early placeholder 0.1.0 was corrected to
follow the released 0.0.x line — first release was V0.0.1; current is 0.0.2.
Open
None currently — all tracked decisions (D1–D19) are resolved. New questions will be added
here as they arise. Remaining detail to flesh out during build: the tray's supporting-action
set (D13), per-module apt package names, M12's tunnel/token specifics, and M13's
update mechanism (APT repo vs. self-installed .deb).