v0.308.0: controller batch 2026-10-12 — clear-address warning (R-922), secret sweep over every page (R-255), read_failed (R-266), no NVMe heat band (R-333), share globe (R-577), Hungarian dates and numbers (R-562), lost-drive option pinned (R-521)
Operator rulings 2026-10-12, 09 §3 decisions 196, 204-207, 223, 227. MinAgent 0.131.0 unchanged. R-255's sweep found one leak, fixed here: an optional-config secret_input was rendered into its settings page; it is now revealed on demand. Hungarian parity fixtures re-captured once for R-562. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -59,7 +59,7 @@ type DiskPrior struct {
|
||||
//
|
||||
// 1. nil / "" / UNKNOWN -> Nincs adat
|
||||
// 2. Health == FAILING -> Hiba (drive self-reports)
|
||||
// 3. temperature_c >= 60 -> Hiba
|
||||
// 3. temperature_c >= 60 (NOT for NVMe — R-333) -> Hiba
|
||||
// 4. critical_warning > 0 (NVMe's own flag: a declaration) -> Hiba
|
||||
// 5. percentage_used >= 100 -> Hiba
|
||||
// 6. unreadable > 0 AND prior.SawUncorrectable -> Hiba (SUSTAINED)
|
||||
@@ -69,7 +69,7 @@ type DiskPrior struct {
|
||||
// 10. reallocated > 0 -> Figyelmeztetés
|
||||
// 11. media_errors > 0 -> Figyelmeztetés
|
||||
// 12. percentage_used >= 90 -> Figyelmeztetés
|
||||
// 13. temperature_c >= 55 -> Figyelmeztetés
|
||||
// 13. temperature_c >= 55 (NOT for NVMe — R-333) -> Figyelmeztetés
|
||||
// 14. otherwise -> Rendben
|
||||
//
|
||||
// WHY rows 2-8 exist at all: smart_status.passed CANNOT fail on unreadable sectors. Attributes 187,
|
||||
@@ -82,6 +82,12 @@ type DiskPrior struct {
|
||||
// drive sustain fires a full day earlier (12 Aug) than the count threshold (13 Aug). Row 8 exists for
|
||||
// a box that was powered off or restarted across the sustain window and so has no prior.
|
||||
//
|
||||
// WHY rows 3 and 13 skip an NVMe drive (R-333, `09` §3 decision 206, v0.308.0): the 55/60 °C bands are
|
||||
// SPINNING-DISK bands. A healthy NVMe idles at 53 °C (measured on demo-hp) and routinely passes 60 °C
|
||||
// under load with no fault, so the bands would tell a household "Hiba" about a working drive. An NVMe
|
||||
// drive judges its own heat: critical_warning bit 1 is the device's temperature alarm, and row 4 still
|
||||
// turns any critical_warning bit into Hiba. Pinned by TestDiskVerdict_NVMeHasNoHeatBand.
|
||||
//
|
||||
// Pure: no clock, no I/O, no logging. Everything it needs arrives as an argument.
|
||||
func DiskVerdictFor(s *SmartSummary, prior DiskPrior) DiskVerdict {
|
||||
// 1 — no data. Never alarms.
|
||||
@@ -94,8 +100,9 @@ func DiskVerdictFor(s *SmartSummary, prior DiskPrior) DiskVerdict {
|
||||
}
|
||||
// Health == PASSED (or any non-empty non-FAILING value we treat as passing): inspect the counters,
|
||||
// because the overall verdict is structurally unable to report this class of fault.
|
||||
nvme := IsNVMe(s)
|
||||
switch {
|
||||
case atLeast(s.TemperatureC, TemperatureFailC): // 3
|
||||
case !nvme && atLeast(s.TemperatureC, TemperatureFailC): // 3
|
||||
return DiskVerdictFail
|
||||
case positive(s.CriticalWarning): // 4
|
||||
return DiskVerdictFail
|
||||
@@ -118,7 +125,7 @@ func DiskVerdictFor(s *SmartSummary, prior DiskPrior) DiskVerdict {
|
||||
return DiskVerdictWarn
|
||||
case atLeast(s.PercentageUsed, percentageUsedWarn): // 12
|
||||
return DiskVerdictWarn
|
||||
case atLeast(s.TemperatureC, temperatureWarnC): // 13
|
||||
case !nvme && atLeast(s.TemperatureC, temperatureWarnC): // 13
|
||||
return DiskVerdictWarn
|
||||
}
|
||||
return DiskVerdictOK // 14
|
||||
@@ -190,12 +197,21 @@ func DegradedAttributes(s *SmartSummary) []string {
|
||||
if atLeast(s.PercentageUsed, percentageUsedWarn) {
|
||||
out = append(out, "elhasználódás")
|
||||
}
|
||||
// Newly able to trigger a verdict on its own (rows 3 and 13), so it must be nameable.
|
||||
if atLeast(s.TemperatureC, temperatureWarnC) {
|
||||
// Newly able to trigger a verdict on its own (rows 3 and 13), so it must be nameable. Not for an
|
||||
// NVMe drive (R-333): its heat never triggers a verdict, so naming it would give a wrong reason.
|
||||
if !IsNVMe(s) && atLeast(s.TemperatureC, temperatureWarnC) {
|
||||
out = append(out, "hőmérséklet")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// IsNVMe reports whether the summary came from an NVMe drive. The agent fills critical_warning,
|
||||
// percentage_used and media_errors ONLY from smartctl's nvme_smart_health_information_log
|
||||
// (felhom-agent internal/storage/smart.go), so any of them present means NVMe; a SATA or USB drive
|
||||
// carries none of them.
|
||||
func IsNVMe(s *SmartSummary) bool {
|
||||
return s != nil && (s.CriticalWarning != nil || s.PercentageUsed != nil || s.MediaErrors != nil)
|
||||
}
|
||||
|
||||
func positive(p *int) bool { return p != nil && *p > 0 }
|
||||
func atLeast(p *int, n int) bool { return p != nil && *p >= n }
|
||||
|
||||
Reference in New Issue
Block a user