vscode_optimizer: detect Intel iGPUs as Intel, not AMD

_detect_gpu matched every _VENDOR_KW key against the whole lspci line.
Every display line contains "VGA compATIble controller", so the "ati" key
fired unconditionally and "intel" was never reached: Intel iGPUs were
reported as AMD, switching on the GPU-accelerated terminal and the
AMD-only Electron flags.

Match against hw.gpu_model — the description after the last colon, which
the line above already extracts — instead of the whole line.

The strict=True xfail guarding this is removed and becomes a normal
passing regression test, and the two parametrised cases that
characterised the bug (Intel -> AMD, unknown vendor -> AMD) are corrected
to Intel and Unknown. Added this machine's real second display device,
"[AMD/ATI] Raphael", which must still resolve to AMD.

Verified by real run: --dry-run still reports the RTX 3090 as NVIDIA with
24576 MB VRAM and still proposes 18 changes, matching the pre-fix
baseline. Full gate: 1984 passed, 100% coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
This commit is contained in:
Krzysztof Rudnicki 2026-08-17 14:49:43 +02:00
parent 52f3452ba6
commit 2d7d322881
3 changed files with 65 additions and 20 deletions

View File

@ -0,0 +1,44 @@
{
"intent": "Detect Intel iGPUs as Intel instead of AMD, so an Intel machine no longer enables the GPU-accelerated terminal and the AMD-only Electron flags that were chosen for a GPU it does not have.",
"scope": [
"python_pkg/vscode_optimizer/_hardware.py — _detect_gpu vendor matching",
"python_pkg/vscode_optimizer/tests/test_gpu_disk.py — one strict xfail removed, one parametrised characterisation test corrected",
"Non-goal: the _VENDOR_KW table itself is unchanged; only what it is matched against changed"
],
"changes": [
"_detect_gpu now matches vendor keywords against hw.gpu_model (the device description after the last colon) rather than against the whole lspci line. Every display line contains 'VGA compATIble controller', so the 'ati' key matched unconditionally and 'intel' was unreachable.",
"Removed the strict=True xfail from test_detect_gpu_should_recognise_an_intel_igpu and renamed it to test_detect_gpu_recognises_an_intel_igpu; it now asserts the fixed behaviour as a regression guard.",
"test_detect_gpu_maps_each_vendor_keyword: the Intel case now expects 'Intel' (was 'AMD') and the unlisted-vendor case now expects 'Unknown' (was 'AMD').",
"Added a case for this machine's real second display device, 'Advanced Micro Devices, Inc. [AMD/ATI] Raphael', whose description carries both AMD and ATI and must still resolve to AMD."
],
"verification": [
{
"command": "python3 -m python_pkg.vscode_optimizer --dry-run",
"result": "pass",
"evidence": "GPU still reported as 'NVIDIA - NVIDIA Corporation GA102 [GeForce RTX 3090] (rev a1) (24576 MB VRAM)' and still '18 change(s) proposed.' — byte-identical to the pre-fix baseline captured on the same machine."
},
{
"command": "python3 -m pytest python_pkg/vscode_optimizer/tests/test_gpu_disk.py -q --no-cov",
"result": "pass",
"evidence": "17 passed in 0.03s; no xfail/xpass remaining in the file."
},
{
"command": "systemd-run --user --scope -p MemoryMax=2G -p MemorySwapMax=0 python3 -m pytest -q",
"result": "pass",
"evidence": "1984 passed in 22.14s; TOTAL 6560 statements, 1630 branches, 100% coverage; 'Required test coverage of 100.0% reached.'"
},
{
"command": "lspci | grep -iE 'vga|3d'",
"result": "pass",
"evidence": "Two display devices present: the RTX 3090 at 01:00.0 and an AMD Raphael iGPU at 0d:00.0. _detect_gpu breaks after the first line, so this machine reports NVIDIA either way; the real lines were used to build the test cases."
}
],
"risks": [
"A device whose vendor name appears only in the bus/class prefix and not in the description after the last colon would now fall through to 'Unknown'. No such lspci format is known; every display line puts the vendor in the description.",
"A description containing a stray 'ati' substring (for example a product name ending in -ati-) would still map to AMD. This is the pre-existing keyword-matching design, deliberately left alone in this commit."
],
"rollback": [
"git revert the commit; _detect_gpu returns to matching the whole line and the xfail returns with it.",
"After rollback, re-run python3 -m python_pkg.vscode_optimizer --dry-run and confirm 18 changes are still proposed, then run pytest and confirm the xfail is reported as expected-fail rather than as a failure."
]
}

View File

@ -65,8 +65,12 @@ def _detect_gpu(hw: _Hw) -> None:
if "vga" not in low and "3d" not in low:
continue
hw.gpu_model = line.rsplit(":", maxsplit=1)[-1].strip()
# Match the device description only. The full line always contains
# "VGA compATIble controller", so matching *low* lets "ati" fire on
# every display device and hides every vendor checked after it.
model_low = hw.gpu_model.lower()
for kw, vendor in _VENDOR_KW.items():
if kw in low:
if kw in model_low:
hw.gpu_vendor = vendor
break
if hw.gpu_vendor == "NVIDIA":

View File

@ -63,13 +63,16 @@ def test_detect_gpu_tolerates_nvidia_smi_being_absent(
[
("03:00.0 VGA compatible controller: AMD Radeon RX 7900", "AMD"),
("03:00.0 VGA compatible controller: ATI Technologies Inc", "AMD"),
# Characterisation, not endorsement: see the xfail below. Every real
# lspci display line contains "VGA compATIble", so "ati" matches first
# and both of these are reported as AMD.
("00:02.0 VGA compatible controller: Intel UHD Graphics 630", "AMD"),
("04:00.0 VGA compatible controller: Some Unlisted Vendor", "AMD"),
# A 3D controller line has no "compatible" in it, so it escapes the trap.
("00:02.0 VGA compatible controller: Intel UHD Graphics 630", "Intel"),
("04:00.0 VGA compatible controller: Some Unlisted Vendor", "Unknown"),
("04:00.0 3D controller: Some Unlisted Vendor", "Unknown"),
# This machine's second display device: the description carries both
# "AMD" and "ATI", and either key gives the same answer.
(
"0d:00.0 VGA compatible controller: "
"Advanced Micro Devices, Inc. [AMD/ATI] Raphael",
"AMD",
),
],
)
def test_detect_gpu_maps_each_vendor_keyword(
@ -84,21 +87,15 @@ def test_detect_gpu_maps_each_vendor_keyword(
assert hw.gpu_vendor == vendor
@pytest.mark.xfail(
reason=(
"Pre-existing bug carried verbatim through the move: _VENDOR_KW's 'ati' "
"key is a substring of 'VGA compatible controller', which appears in "
"every lspci display line, so it matches before 'intel' is ever tried. "
"Intel iGPUs are misreported as AMD, which wrongly enables the "
"GPU-accelerated terminal and AMD-only Electron flags. Fixing it is a "
"behaviour change and does not belong in a move commit."
),
strict=True,
)
def test_detect_gpu_should_recognise_an_intel_igpu(
def test_detect_gpu_recognises_an_intel_igpu(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""An Intel iGPU ought to be detected as Intel."""
"""An Intel iGPU is detected as Intel, not as AMD.
Regression guard: matching the whole lspci line let "ati" — a substring of
"VGA compATIble controller" — claim every display device before "intel"
was tried, so Intel iGPUs enabled the AMD-only Electron flags.
"""
line = "00:02.0 VGA compatible controller: Intel UHD Graphics 630"
monkeypatch.setattr(subprocess, "run", _fake_run({"lspci": line}))
hw = _Hw()