feat(tui): NVIDIA SAT with nvtop, GPU selection, metrics and chart — v1.0.0

- TUI: duration presets (10m/1h/8h/24h), GPU multi-select checkboxes
- nvtop launched concurrently with SAT via tea.ExecProcess; can reopen or abort
- GPU metrics collected per-second during bee-gpu-stress (temp/usage/power/clock)
- Outputs: gpu-metrics.csv, gpu-metrics.html (offline SVG), gpu-metrics-term.txt
- Terminal chart: asciigraph-style line chart with box-drawing chars and ANSI colours
- AUDIT_VERSION bumped 0.1.1 → 1.0.0; nvtop added to ISO package list
- runtime-flows.md updated with full NVIDIA SAT TUI flow documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-03-18 15:18:57 +03:00
parent b965184e71
commit 76a17937f3
14 changed files with 1162 additions and 24 deletions

View File

@@ -255,7 +255,7 @@ func TestOutputScreenReturnsToPreviousScreen(t *testing.T) {
}
}
func TestAcceptanceConfirmFlow(t *testing.T) {
func TestAcceptanceNvidiaSATOpensSetup(t *testing.T) {
t.Parallel()
m := newTestModel()
@@ -265,17 +265,15 @@ func TestAcceptanceConfirmFlow(t *testing.T) {
next, cmd := m.handleAcceptanceMenu()
got := next.(model)
if cmd != nil {
t.Fatal("expected nil cmd")
if cmd == nil {
t.Fatal("expected non-nil cmd (GPU list loader)")
}
if got.screen != screenConfirm {
t.Fatalf("screen=%q want %q", got.screen, screenConfirm)
}
if got.pendingAction != actionRunNvidiaSAT {
t.Fatalf("pendingAction=%q want %q", got.pendingAction, actionRunNvidiaSAT)
if got.screen != screenNvidiaSATSetup {
t.Fatalf("screen=%q want %q", got.screen, screenNvidiaSATSetup)
}
next, _ = got.updateConfirm(tea.KeyMsg{Type: tea.KeyEsc})
// esc from setup returns to acceptance
next, _ = got.updateNvidiaSATSetup(tea.KeyMsg{Type: tea.KeyEsc})
got = next.(model)
if got.screen != screenAcceptance {
t.Fatalf("screen after esc=%q want %q", got.screen, screenAcceptance)
@@ -289,7 +287,6 @@ func TestAcceptanceMenuMapsNewTargets(t *testing.T) {
cursor int
want actionKind
}{
{cursor: 0, want: actionRunNvidiaSAT},
{cursor: 1, want: actionRunMemorySAT},
{cursor: 2, want: actionRunStorageSAT},
}