fix(hardware_ai): five wrong conclusions, each with a confidence attached
Running the inference engine on this desktop workstation and reading its report — the method that has found everything else this session — produced five false statements, all carrying explicit confidence numbers. This is the crate's thesis violated a level up: not a zero in a field, but whole conclusions asserted at 0.85. **SSD detection has never worked on Windows.** `Get-PhysicalDisk | ConvertTo-Json` serialises MediaType and BusType as their friendly strings, "SSD" and "NVMe", not as the integers MSFT_PhysicalDisk defines. The code read them with `as_u64()`, got `None` for every disk on every Windows machine, and `unwrap_or(0)` turned a total parse failure into "not an SSD". This host has three NVMe drives and no rotating disk; the report led with "No SSD detected — HDD will severely bottleneck modern workloads" at 0.85, and recommended replacing a drive that does not exist at priority 10. A fallback standing in for a reading nobody took is how a module fails completely and still produces confident output. `wmi_enum` now accepts both forms, and `None` stays `None` for the USB gadget reporting "Unspecified" — which is not the same as "this is a hard disk". **A UPS made a tower into a laptop.** Windows inferred the chassis (virtual, else battery means laptop) while Linux read `/sys/class/dmi/id/chassis_type`. A UPS presents as a `Win32_Battery`, so this enclosure-type-3 Desktop classified as a GamingLaptop. `Win32_SystemEnclosure.ChassisTypes` is the same SMBIOS enumeration, needs no elevation, and reports 3. One platform reading it and the other guessing is how the two arms disagreed about the same hardware. **And the guess outranked the reading even after that.** A battery scored 0.4 in `classify_system` where a read chassis scored 0.3, so battery alone cleared the threshold — and the Desktop branch was gated on `!f.has_battery`, so a desktop with a UPS was not outvoted but absent from the ballot entirely. Chassis now decides; the battery speaks only where the enclosure did not. Same substitution in the thermal model, which had this tower on the laptop cooling curve: headroom "Insufficient" and a cooling score of 15 for a 500W envelope, now "Ample" and 90. **A 2024 CPU dated to 2018.** `infer_cpu_year` matches bare Intel model numbers, and those are not unique to a vendor: "AMD Ryzen 9 9900X" contains "9900", so it matched the 9th-gen Core rule while the correct `ryzen 9 9` rule sat unreached thirty lines below. The test covered "ryzen 7 7800x3d", which happens not to collide. Vendor is checked first now, and `a_model_number_is_read_for_the_right_vendor` covers the collisions in both directions. **WMI pads `Name`.** "AMD Ryzen 9 9900X 12-Core Processor " reached the age `reasoning` string and the hardware fingerprint, so two machines differing only in WMI's padding would fingerprint apart. After: Workstation (0.6), no bottlenecks, no upgrade recommendations, headroom Ample, cpu_year 2024, model trimmed. Ground truth checked independently — `Get-PhysicalDisk` shows three NVMe SSDs, `ChassisTypes` returns 3. Two known-wrong outputs are left alone and neither is a fallback bug: `AdapterRAM` reports 4.29GB for a 24GB RTX 3090 Ti, which is WMI's own 32-bit overflow and needs a different source, and it drives "Insufficient VRAM for ML training". Verified: fmt, clippy, both cross-target checks, 12 hardware_ai unit tests and 59 conformance tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A
Adam Erickson committed
a584dd02f83d45217805279618d5f30cff2e2da5
Parent: 4dd5cce