The seed use case end to end, orchestrating M3 + M4 (ARCHITECTURE §7.1).
- core/diagnostic.py: start(game) runs a focused, game-tagged capture into a
dedicated diagnostic log (window-scoped report, separate from the always-on
crash log); finish() stops it and combines the capture summary (M3) with the
health findings (M4). Game recorded as a log event so it survives crash+reboot.
- CLI: rigdoctor diagnose start --game/--appid | status | finish.
- recorder/record run gained an optional --game tag; reccontrol passes it through.
- Tests for game recovery + the finish() combination.
GUI/tray "Run Diagnostic" button and auto start/stop (D12 wrapper) come next.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Make the environment report actionable, not just advisory.
Install (reuses M9 installer):
- Add GameMode, MangoHud, cpupower to the component catalog (so they also show
on the Setup page); catalog.by_id() lookup.
- "tool not installed" findings (GameMode/MangoHud) get an Install button.
Apply runtime-reversible tunables (D22, realizing the D9 consent-gated milestone):
- core/fixes.py: dropdown of live options + Apply for CPU governor, NVIDIA
persistence, PCIe ASPM policy, vm.swappiness, THP. One pkexec command each,
no reboot, reverts on reboot; chosen value validated against live options;
writes go to sysfs/procfs/nvidia-smi, never GRUB. GRUB/mitigations stay
suggestion-only.
- Finding gained optional action (install) + fix (apply) ids; shared
finding_card renders the matching control; Environment page wires both and
re-checks after a change.
Tests for fixes (parse, command builders, value validation, gameenv wiring).
Docs: D22 added (amends D9); SPEC/MODULES/ROADMAP updated. 0.9.0 -> 0.10.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The evaluate-and-suggest half of M6: a read-only findings report (D9) over
system settings that affect gaming stability/performance, each with the exact
fix command.
- core/gameenv.py: PCIe ASPM, NVIDIA persistence mode, CPU governor (the three
seed-case contributors to GPU bus-drop / Xid 79), GameMode, MangoHud,
vm.swappiness, shader disk cache, THP, CPU mitigations, Proton versions.
Pure evaluate_* helpers split from IO for testing; reuses the M4 Finding model.
- steam.proton_versions(): surfaces installed Proton builds for the report.
- CLI: rigdoctor gameenv (text / --json); render_health() gained a title arg.
- GUI: new Environment page; extracted a shared finding_card widget and switched
the Health page to it.
- Tests for the pure evaluators + aggregate.
Also fix: desktop notifications now use the RigDoctor icon (installed theme copy
-> bundled asset -> stock fallback) instead of a generic stock icon, matching
the app/dock icon.
Docs (MODULES/ROADMAP) updated; version 0.8.0 -> 0.9.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first slice of M6 (gaming-environment checks): detect a user's Steam
libraries and the games installed in each — also the D12 "pick a game"
foundation.
- core/steam.py: multi-install/library discovery (libraryfolders.vdf, symlink
dedupe, native/Flatpak/Snap), appmanifest_*.acf scan with runtime/Proton/
redist filtering, scan cache + new-game diff. Stdlib only. VDF keys read
case-insensitively (e.g. lastupdated vs SizeOnDisk).
- Libraries are opt-in (config steam_libraries); the flat TOML writer now
emits list/array values.
- GUI Games page: library checkboxes with per-library counts, game list,
background rescan on every launch, NEW badge + sidebar count for games
installed since the last scan (acknowledged when viewed).
- CLI: rigdoctor games / games libraries [--enable|--disable|--all|--json]
(headless-complete, D17).
- Tests for VDF parse, scan, tool filter, cache diff, config list round-trip.
- Docs (MODULES/ROADMAP) updated; version 0.7.3 -> 0.8.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- feat(share): host-consented interactive terminal over the relay. The host shares
a real PTY shell (core/pty_session.py); the guest renders it with pyte and sends
keystrokes (gui/terminal_widget.py) — vim/top/tab-completion/Ctrl-C work. Runs as
the host's user (never root). The host reads along live and can type too, e.g. a
sudo password, which stays local and is never sent to the guest. Off by default.
Guest also pulls inventory on join (req_full).
- fix(gui): style all form controls (QLineEdit/QPlainTextEdit/spin boxes/combo/
terminals) dark-on-light-text — Fusion defaulted them to unreadable light-on-light.
- replaces the command/response shell with the full PTY; adds pyte to the gui extra.
Verified end-to-end against the deployed relay (guest keystroke ran on host PTY).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a Share tab that hosts or joins a read-only live session through the
rigdoctor-relay over WebSocket (QtWebSockets), gated by the Gitea access token.
- gui/share_page.py: Start shared session (host: get a code, stream snapshot +
health + inventory) and Enter share code (guest: view a host's data read-only)
- core/share.py: host_full_frame / host_snapshot_frame + guest_html renderer
- config: relay_url (default wss://rigdoctor.jesseyvanofferen.com)
- setup: token now powers updates AND sharing — hint asks for read:user +
read:repository scopes (relay validates the account via Gitea)
- main_window: Share nav tab + socket cleanup on close
- tests for the relay frame builders and guest HTML
Verified end-to-end against the deployed relay (host code -> guest frame).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- feat(alerts): desktop notifications (notify-send) for overheat (GPU/CPU past a
configurable threshold), GPU-lost, and a new-version-available alert (once per
version). Edge-triggered with cooldown so it doesn't spam (core/alerts.py)
- feat(gui): Notifications page to configure alerts (enable, GPU/CPU thresholds,
Send test); changes apply live and persist via config.save_config/update_config
- feat(gui): ship a RigDoctor icon; the GUI self-registers the icon + .desktop on
launch and sets the Wayland app-id, so the dock shows it after an update + relaunch
(no installer re-run); installer/uninstaller updated to manage the icon
- config: alerts_enabled, gpu_temp_alert, cpu_temp_alert; flat-TOML writer
- tests for the alert monitor and config round-trip
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First milestone release — a complete, installable, self-updating RigDoctor:
live monitoring, crash capture + health report, desktop GUI, user-local
install/uninstall, and token-gated self-update with real release notes.
- feat(gui): in-app uninstaller — Setup "Uninstall RigDoctor" button and
`rigdoctor uninstall [--purge]`; removes venv/launchers/desktop entry
(detached so it can delete its own venv), with optional purge of
settings/token/logs (core/uninstall.py)
- feat(gui): in-app changelog — sidebar "Changelog" link listing release
history fetched from the update server (updates.list_releases)
- chore: versioning rules + automation (D21) — git-cliff --bumped-version,
packaging/bump.sh, cliff.toml [bump] (pre-1.0: breaking -> minor)
- chore(release): stamp 0.1.0; milestone policy recorded in D19
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- feat(ci): set each Gitea release body from the matching CHANGELOG section
(was hardcoded "Automated release for…")
- feat(updater): show "What's new" — release notes dialog before applying (GUI)
and in `rigdoctor update` (CLI); fetch_latest/update_state now return notes
- feat(gui): "Restart now" button relaunches the app after an update is applied
- fix(packaging): build the self-extracting .run with a pure-Python extractor
(packaging/make_run.py) instead of makeself, so it attaches to every release
(it was silently skipped before)
- chore: adopt Conventional Commits + git-cliff (cliff.toml, packaging/
changelog.sh) for changelog generation going forward (D20)
- chore(gui): drop internal module refs (M4, M5, …) from Setup descriptions
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PySide6/Qt front-end over the stdlib sensor core (only gui/ imports Qt).
- sidebar navigation + stacked pages (Dashboard live; Logs/Health/Inventory
placeholders for M3-M5)
- live dashboard: circular gauges (GPU temp/load, CPU temp, memory) plus
collapsible per-subsystem cards with progress bars and metric rows
- background sampling thread -> Qt signal so the UI stays responsive
- temperature colors: icey-blue (cold) -> green -> orange -> red (hot)
- dark theme via QSS + Fusion
Supporting changes:
- cpu source: order temps as package, then cores numerically (fixes CLI too)
- render: expose format_value/metric_label, shared by CLI and GUI
- cli: `rigdoctor gui` (lazy import; prints install hint if PySide6 missing)
- pyproject: rigdoctor-gui script + [gui] extra (PySide6)
- gitignore: *.egg-info/, build/, dist/
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>