Repository navigation
feat(examine): show the AMD driver version on Windows and flag old drivers - #680
Conversation
juhovainio
left a comment
There was a problem hiding this comment.
Reviewed the whole diff end to end. This is a well-built addition: the CalendarDate/DriverAge comparison logic in the new windows_driver.rs module is correct and thoroughly tested (including the cutoff-day boundary and Windows' own "unset date" placeholders like 0001-01-01/1601-01-01), the fix-20 score is deliberately kept below the match threshold so it only ever shows as advice, and the catalog/fix.rs/doctor-catalog.json/reference.md/README entries are all mutually consistent. docs/testing.md also does the right thing by explicitly explaining why there's no e2e scenario here, rather than leaving the gap silent. The PR description already flags the merge-order coordination with #677/#679, so no need to repeat that.
Requesting changes on one real, non-blocking-in-the-common-case but inaccurate claim in the new module's own doc comment, left as an inline comment below: it says rocm examine and rocm diagnose "read the verdict from here, so the two cannot disagree" - that's true of the comparison logic, but not of the underlying facts. The two callers get their driver version/date from two separate PowerShell probes with different adapter-selection logic, so on a machine with more than one AMD display adapter they can disagree about which adapter's driver they're even looking at.
| //! | ||
| //! Two callers need the same answer. `rocm examine` prints it, and | ||
| //! `rocm diagnose` raises [`DISPLAY_DRIVER_OLD_FIX_ID`] from it. Both read | ||
| //! the verdict from here, so the two cannot disagree. |
There was a problem hiding this comment.
This guarantee only holds for the comparison logic in this module, not for the facts fed into it. rocm diagnose's check_20 reads Examination.adrenalin_version/adrenalin_date, populated by examine.rs's probe_adrenalin_windows via WIN_ADRENALIN_SCRIPT - a single CIM query that does Where-Object { PNPDeviceID -match 'VEN_1002' -or Name -match 'AMD|Radeon|Instinct' } | Select-Object -First 1, i.e. whichever matching adapter CIM happens to enumerate first.
rocm examine's rendering and rocm install driver's plan text instead read ExamineSummary.driver.windows, populated by host_gpu.rs's detect_driver_summary_with_windows_inventory -> a pnputil-first, video-controller-fallback pipeline that then picks the adapter via WindowsExamineInventory::preferred_amd_display(), which explicitly ranks a ROCm-supported discrete GPU above a recognized-but-unsupported iGPU (the comment there says this is so a gfx90c iGPU "cannot hide a discrete card").
These are two independently-run probes with two different selection algorithms. On exactly the multi-adapter machine preferred_amd_display() is designed to handle (an AMD iGPU plus a discrete AMD GPU), the two pipelines can pick different physical adapters and report different driver versions/dates for what a user perceives as one driver - which is the opposite of "cannot disagree." Worth either having rocm diagnose's check reuse the same inventory-based selection rocm examine uses, or softening this doc comment to describe what's actually guaranteed (shared comparison logic, not shared facts).
tomastola
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · e7aac6b
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review — needs work
Full review of the whole change (one commit, 0cde0aa3…e7aac6bf).
No ticket named; the description notes this needs a rebase and recount after #677 and #679.
Blocking
Five findings, each posted as an inline comment on its first cited line:
rocm diagnosereads the driver from a different probe thanrocm examineandrocm install driver, so they can disagree, though the code says they cannot.- The new video-controller query runs on every Windows inventory call, including the
rocm serve, default-engine and chat pre-draw paths, and its comment says the opposite. - No Gherkin scenario covers the new Windows output, and the stated reason (no Windows lane) does not hold.
- The wiring that puts driver facts into the examine summary, and the date-only re-query branch, are untested.
- The two copies of the fix-20 plan already differ, and the drift guards were not extended to fix-20.
Non-blocking
-
The Microsoft Basic Display Adapter would likely be reported as an "old AMD driver" —
host_gpu.rs:36,examine.rs:3052
With no AMD driver loaded, Windows falls back to the basic display driver. That adapter keepsPCI\VEN_1002, so both probes select it. I believe it reports DriverVersion10.0.<build>with a placeholder DriverDate of 2006-06-21, which the year-before-2000 guard does not catch. This has not been checked on a Windows machine. If it holds, the user is told to update an AMD driver that is not installed. Suggest treating a10.0.version or a Microsoft provider as "no AMD driver", not fix-20. -
An advice-only row replaces diagnose's upstream escalation in text output —
diagnose.rs:2729-2737,:2815-2823,:2039
fix-20 ignores the symptom, so on an old-driver hostmatchedis never empty. The text report then drops "no known misconfiguration matched … file upstream" and ends with "runrocm fix fix-20-display-driver-old(the highest-scoring match)", whatever the user reported. JSON output is unaffected. -
The documented focused test commands miss 8 of the new tests —
docs/testing.md:1163-1167
Thewindows_driver,display_driverandwindows_install_driverfilters miss:- the three probe-output tests in
examine.rs; - four
host_gpu.rstests (examine_prints_no_driver_age_lines_when_no_version_was_read,the_inventory_parser_reads_the_driver_date_and_drops_a_bad_one,an_adapter_missing_its_version_asks_for_a_second_query,a_version_less_adapter_gives_no_driver_info_and_is_filled_from_the_video_controller); the_fix_id_the_install_text_names_is_the_one_diagnose_raisesin the bin.
The filters also pick up an unrelated diagnose test. Confirmed for the rocm-core filters with
cargo test -p rocm-core <filter> -- --list. - the three probe-output tests in
-
The docs give the cutoff as "before July 2023", but the code uses 2023-07-27 —
docs/manual-testing.md:275,:279,:287;docs/testing.md:1172
FIRST_HIP_SDK_FOR_WINDOWSgoverns. A driver dated 2023-07-01 to 07-26 is flagged, while a tester following the doc would expect no flag. -
The README paragraph sits under the
install sdktext —README.md:367-371
"Driver installation" (README.md:440-443) still mentions Linux only. -
The rocm-doctor skill has no rule for advice-only entries —
skills/rocm-doctor/SKILL.mdstep 1,reference.md:125
The skill acts onhas_match, which fix-20 never sets, so an agent following it silently drops advice thatexamineand the README present. Say whether to relay it. -
A stale count in a comment —
fix.rs:2868
"the other 23 fix-ids" should now be 26. It was already wrong before this change.
Decisions for the author
- A date cutoff reaches only some of the supported hardware — tradeoff
The cutoff itself is right: AMD's ROCm 5.5.1 Windows Quick Start is dated 2023-07-27 (https://rocm.docs.amd.com/en/docs-5.5.1/deploy/windows/quick_start.html). That page also answers "Not verified: the cutoff date comes from press and discussion posts". The "no published minimum" claim also holds; AMD's pages only name the driver the HIP SDK installer bundles.
The limit is reach. The check can never fire on gfx120X, gfx1150 or gfx1151, which all launched after mid-2023. It also misses the one driver issue AMD does document: lower performance on Strix Halo with 26.10-branch drivers. It still applies to RDNA2 and early RDNA3. Please confirm that reach is what you intend. - Store the date as
Option<CalendarDate>— non-blocking-improvement
Today it is aStringre-parsed by everyage()call (windows_driver.rs:96-102,:134-139). Thepubfield allows a value that silently reads asUnknown. --jsoncarries the version and date but not the verdict — non-blocking-improvement
A consumer has to re-implement the cutoff itself.
Positive signals
- The install text is computed from the same
WindowsDriverInfoas the verdict, and a test enforces the "minimum is not established" caveat in every statement. - Years before 2000 are rejected, so the unset-date placeholder reads as unknown rather than "very old". Dates are formatted with
InvariantCulture. - fix-20's score is asserted below
MIN_SCORE_FOR_MATCH, and its recipe is print-only, so it cannot fliphas_matchor the unattended install. - The report redaction sweep gained sentinels for the new driver version and date.
Deployment notes
rocm examine --jsongainsadrenalin_dateand an optionalsummary.driver.windows. Both are additive;serde(default)keeps older consumers working.- On Windows,
rocm serve, chat andexaminepay one extra PowerShell spawn (blocking finding 2). doctor-catalog.jsongrows to 27 entries. The downstreamrocm-doctorskill copy needs its hand-sync (AGENTS.md §7).
What this covered
- Read: every file in the change, completely, at
0cde0aa3…e7aac6bf. Also the callers on the serve, chat and default-engine paths, the e2e workflows and feature files, and AGENTS.md. - Passes: history, earlier review comments on these files, impact analysis, and a check of AMD's public docs.
- Ran:
cargo test -p rocm-core --libon this head (687 passed, 0 failed). - Not run: nothing on Windows. The PowerShell paths and their timing are argued from the code.
E2E tests (MI300X)had no result at review time. - Not reconciled: this review was not reconciled against the PR's existing discussion.
| //! The AMD display driver on Windows: what version and date it has, and | ||
| //! whether it is old. | ||
| //! | ||
| //! Two callers need the same answer. `rocm examine` prints it, and |
There was a problem hiding this comment.
Blocking — rocm diagnose reads the driver from a different probe than rocm examine and rocm install driver, so they can disagree, though this comment says they cannot.
Locations: crates/rocm-core/src/windows_driver.rs:8-10, apps/rocm/src/driver_install.rs:827-828, crates/rocm-core/src/examine.rs:3052, crates/rocm-core/src/host_gpu.rs:1687-1693
- Two probes:
examineandinstall drivergo throughExamineSummary::gather→preferred_amd_display(). That ranks adapters, putting a ROCm-capable discrete GPU above a gfx90c iGPU.diagnoseusesWIN_ADRENALIN_SCRIPT. It takesSelect-Object -First 1in WMI order, has noAdapterCompatibilityclause, and uses an 8 s timeout instead of 5 s.- Only the verdict function is shared, not the facts it is given.
- How they disagree:
- On an APU plus dGPU machine whose two drivers carry different dates,
examinecan print "runrocm diagnose(fix-20-display-driver-old)" while diagnose raises nothing, or the reverse. - If the inventory's video-controller query times out,
install driversays the version "could not be read" while diagnose still raises fix-20.
- On an APU plus dGPU machine whose two drivers carry different dates,
- The rule: AGENTS.md §3 requires that a command named in remediation advice "actually clear the condition that printed it".
- The test can't catch it:
the_fix_id_the_install_text_names_is_the_one_diagnose_raisesbuildsExaminationby hand and never renders the install text. It passes with thedriver_install.rschange reverted.
Suggested fix: fill diagnose's adrenalin_* from the same inventory and preferred_amd_display selection. Then rename that test, or make it build both outputs from one probe result.
| { | ||
| inventory.merge_missing_from(pnp); | ||
| } | ||
| // `pnputil` lists the adapter but not its driver version or date, so an |
There was a problem hiding this comment.
Blocking — this second query runs on every Windows inventory call, including the startup paths, and the comment says the opposite.
Locations: crates/rocm-core/src/host_gpu.rs:2503-2511, :2727
- Why it always runs:
push_windows_pnputil_displayalways setsdriver_date: None, and pnputil is the first and normal source. Sopreferred_amd_display_misses_driver_facts()is true on every AMD host, and another PowerShell/CIM process (5 s timeout) starts each time. "A complete inventory costs nothing" never applies in practice. - Who pays:
detect_windows_examine_inventoryis shared, so the cost lands on callers that never use the date:detect_host_gpu_summary_fast(:3056,:3072), behindrocm serveand default-engine resolution;chat_host_facts, whose header (apps/rocm/src/chat_host_facts.rs:15-19) says it must stay cheap because it runs before the dashboard draws;detect_local_windows_host_driver(:509).
Suggested fix: fetch DriverDate only on the driver-summary path (gather / detect_driver_summary_with_windows_inventory), or add it to a query that already runs. Correct the comment either way.
| reconcile path is also non-privileged. It refreshes passive checks and persists | ||
| the `total`/`present`/`missing` check summary without running DKMS commands. | ||
|
|
||
| Windows display driver checks (`fix-20-display-driver-old`) are covered by unit |
There was a problem hiding this comment.
Blocking — no Gherkin scenario covers the new Windows output, and the reason given here does not hold.
Locations: docs/testing.md:1160-1172, docs/manual-testing.md:285-287, the "Tests" section of the description; nothing changed under tests/e2e-cucumber/features/
- What needs a scenario: AGENTS.md §3 asks for one when command output changes. This change adds:
- three
rocm examinelines; - a fix-20 row in
rocm diagnose; - Windows
install drivertext promising "no driver is installed or changed". §3 names that kind of promise specifically.
- three
- The Windows lane already exists:
e2e-gpu-strix-windowsin.github/workflows/e2e-selfhosted.yml:650, whose path filter includescrates/rocm-core/**andapps/rocm/**;- it passed on this head;
@requires-os:windowsscenarios already run on it (install_lifecycle.feature:136).
- What it can check today: only the "older" branch needs a machine with an old driver. The "not older" verdict, the three examine lines, and installs-nothing / no-execution-commands can all be asserted on that lane now.
Suggested fix:
- Add
@requires-os:windowsscenarios forexamineand forinstall driver, both with and without--yes. - Correct this paragraph, the one in
docs/manual-testing.md, and the description, so that only the old-driver branch is named as the gap.
| } | ||
| }); | ||
| return windows_driver_summary(detail); | ||
| let info = windows_inventory.and_then(WindowsExamineInventory::amd_display_driver_info); |
There was a problem hiding this comment.
Blocking — two pieces of the new wiring have no test: the code that puts driver facts into the examine summary, and the date-only re-query branch.
Locations: crates/rocm-core/src/host_gpu.rs:2331-2332, :1699-1700
- The summary wiring:
- Every new examine test builds the summary through
windows_driver_summary(…, info)directly. - This
amd_display_driver_infocall sits behind the runtimeruntime_is_windows()check. - Replace it with
Noneand every test stays green, whileexamineandinstall driversilently lose the version, date and age.
- Every new examine test builds the summary through
- The date-only branch:
an_adapter_missing_its_version_asks_for_a_second_querycovers "no version" and "both present".- Delete
|| d.driver_date.is_none()and it stays green, yet that is the branch the pnputil path actually takes.
Suggested fix: extract a pure "driver summary from Option<&WindowsExamineInventory>" function, test it on every platform, and add a version-present / date-missing case.
| needs_reboot: true, | ||
| fix_id: id.to_owned(), | ||
| verify: "powershell -NoProfile -Command \"Get-CimInstance Win32_VideoController | Where-Object { $_.Name -like '*AMD*' -or $_.Name -like '*Radeon*' } | Select-Object Name,DriverVersion,DriverDate\"".to_owned(), | ||
| notes: vec![ |
There was a problem hiding this comment.
Blocking — the two copies of the fix-20 plan already differ, and the drift guards built for this were not extended to fix-20.
Locations: crates/rocm-core/src/diagnose.rs:2064-2066, crates/rocm-core/src/fix.rs:877-880
- The notes differ: this note adds "AMD publishes no minimum driver version for the HIP SDK or the Lemonade Vulkan backend." The catalog note in
fix.rsstops after the first sentence, sorocm diagnoseandrocm fix fix-20-display-driver-oldprint different notes for the same entry. - The URL is duplicated:
fix.rshard-codeshttps://www.amd.com/en/supporttwice instead of usingwindows_driver::AMD_SUPPORT_URL. - The guards skip fix-20:
diagnosis_remediation_matches_the_fix_catalog_for_shared_fix_idsandassert_plan_matches_the_catalog_copyexist for exactly this drift. Neither covers fix-20.
Suggested fix: make the notes identical, use the constant, and add fix-20 to both guards.
dc6c223 to
9fe6e07
Compare
tomastola
left a comment
There was a problem hiding this comment.
Automated review · pr-review-watcher · 9fe6e07
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review — needs work
Full review of the whole change at 9fe6e07c (one commit on fcc646e9). e7aac6bf, the commit my last review covered, is no longer on the branch, so this is not a diff against it.
Two blocking findings, posted as inline comments: diagnose-41 passes with the change reverted, and the check_22 placement. The third blocking point is in the body:
Blocking
- The description no longer matches the change — PR body, "Change" and "Tests"
It namesfix-20-display-driver-old; the code, catalog, README, skill reference, docs and tests usefix-22-display-driver-old. "No end-to-end scenario covers this" is no longer true: the change addsexamine-29,diagnose-41,driver-install-04/-05, a Windows guard test and step files. "Needs a rebase and a recount" describes work that is already done. Fix: update the description; say only the old-driver branch lacks an end-to-end scenario.
Non-blocking
docs/testing.md:1170says "four modules"; the listed filters match five (diagnose,examine,fix,host_gpu,windows_driver). Say "five" or drop the number.- Two comments narrate the replaced code — the doc comment on
probe_adrenalin_windowsinexamine.rs, andwindows_driver.rs:17-19. State only the current contract.
Decisions for the author
- A date cutoff reaches only some of the supported hardware — tradeoff (unchanged since last round). The 2023-07-27 cutoff can never fire on gfx120X, gfx1150 or gfx1151, which launched later, and it misses the one driver problem AMD documents (Strix Halo with 26.10-branch drivers). Please confirm that reach is intended.
- The new SKILL.md advice-only bullet does not say whether it overrides step 2 — non-blocking-improvement.
skills/rocm-doctor/SKILL.md:121-125says to relay a sub-thresholdfix-22entry;:166-169says a lower cause may be mentioned "only if it also clearsmin_score_for_match". Add a pointer from step 2. - On Windows the chat and freeform planners still frame
install driveras a disruptive install — non-blocking-improvement.apps/rocm/src/main.rs:6984-6991and:12320-12345title it "Install driver", inject--yesand say "privileged or disruptive"; on Windows the command now only reports. driver_host_guard.rsgreps step source text rather than testing behaviour, so it would pass if the helper's assertion were inverted.
Positive signals
- The Microsoft Basic Display Adapter is treated as "no AMD driver" (
is_microsoft_fallback_driver), with tests. InventoryScope(FAST/SUMMARY/DRIVER_ONLY) and theWindowsInventorySourcestrait keep startup paths free of the extra query and let tests count queries on any platform.examine,install driveranddiagnoseread the driver through one function,amd_display_driver_info(); thefix-22plan and URL are shared and both drift guards cover it.
Deployment notes
rocm examine --jsongainsadrenalin_dateand an optionalsummary.driver.windows; both are additive.doctor-catalog.jsongrows to 29 entries; the downstreamrocm-doctorskill copy needs its hand-sync (AGENTS.md §7).- Every
ExamineSummary::gather()caller on Windows (includingrocmd) can now start one extra PowerShell/CIM query; I did not check whether any is a hot path. windows-build-and-test,build-and-test,Test (affected crates),Build Linux PR binariesandAnalyze (rust)had no conclusion when I read the checks; thecfg(windows)code was not compiled by anything I could see.
What this covered
- Read:
windows_driver.rs,driver_install.rsandmain.rscompletely; forhost_gpu.rs,examine.rs,diagnose.rs,fix.rs,report.rs,lib.rsanddoctor-catalog.jsonthe full diff and surrounding code, not every line; every hunk of the e2e files, docs, README and skills. Rangefcc646e9…9fe6e07c. - Ran (Linux only):
cargo test -p rocm-core --libon the touched modules (445 passed, 1 ignored), clippy clean, the e2e-cucumber guard/naming tests,cargo checkof the e2e binary, and the fiverocmbin tests for the install text. - Did not run: anything on Windows; mutation/revert runs (revert verdicts are traced from the code); the history and prior-changes passes.
- Last round: all five earlier blocking objections are answered by the new code (one shared driver read,
InventoryScope, pure tested summary wiring, shared plan with drift guards, four new scenarios). That was checked against my earlier wording after the findings were final. - Not reconciled against the PR's existing discussion.
| # (advice present). The old-driver branch needs such a machine and is not | ||
| # exercised here. | ||
| @id:diagnose-windows-display-driver-advice-follows-the-inspection @requires-os:windows @requires-gpu | ||
| Scenario: diagnose-41 - On Windows the old display driver advice appears only for an old driver |
There was a problem hiding this comment.
Blocking — diagnose-41 passes with the change reverted, and its name overclaims.
Locations: tests/e2e-cucumber/features/diagnose.feature:627, tests/e2e-cucumber/tests/e2e/diagnose_steps.rs:2772 (assert_old_driver_advice_follows_the_inspection)
- The step computes
oldfromwindows_driver_record(&examine)… == Some("predates_first_hip_sdk"). Reverted,examine --jsonhas no/summary/driver/windows, sooldis false. - Reverted,
diagnose --jsonhas nofix-22row either, soassert_eq!(row.is_some(), old)isfalse == falseand the scenario passes. - On a current-driver lane, the only kind the feature comment says exists,
oldis never true, so it only checks that the advice is absent for a current driver. examine-29does this correctly: it panics when the record is missing.
Confidence 85 · logic · Fix: have the step require the record as examine-29 does, so a reverted CLI fails it (if the record can legitimately be absent when no version was read, require it whenever examine's own text shows a driver_version: line). Keep the untested old-driver branch documented.
| /// HIP SDK and a failing `hipInfo` or a symptom. This one needs neither, so it | ||
| /// also covers a machine that only runs the Vulkan backend. Only evidence is | ||
| /// read: the driver date from the examination, never the symptom text. | ||
| fn check_22_display_driver_old(e: &Examination, _symptom: &str) -> Diagnosis { |
There was a problem hiding this comment.
Non-blocking — check_22 and its recipe sit against the repo's placement rule.
Locations: crates/rocm-core/src/diagnose.rs:2207-2246, crates/rocm-core/src/fix.rs (the fix-22 recipe), doctor-catalog.json:399 and :413
The comment at diagnose.rs:650 says: "A new checker goes at the END of this section, next to where its CHECKERS entry was appended." Here check_22 sits before check_21 (:2215 vs :2248), while CHECKERS appends it after. The recipe and catalog entry also precede fix-21, the reverse of the id order.
Confidence 85 · mechanical · Fix: move the constant and function after check_21, reorder the recipe and catalog to match, and re-run cargo xtask catalog --check.
9fe6e07 to
7772b1f
Compare
|
Addressed in 7772b1f.
On the decisions:
Not verified: nothing ran on Windows. The Windows scenarios and the |
tomastola
left a comment
There was a problem hiding this comment.
Automated review · pr-review-watcher · 7772b1f
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review — needs work
Full review of the whole change at 7772b1f0 (one commit on 2d2dfc78). 9fe6e07c, the commit my last review covered, is no longer on the branch, so this is not a diff against it. Last round's description mismatch, the "four modules" count, the narrating comments and the planner wording are answered by this head; the recipe/catalog reordering from last round's placement point is done, which is what exposes blocker 1. Nothing was built or run locally; one finding is backed by CI, the rest are argued from the code.
Blocking
Three are inline: the catalog order (diagnose_steps.rs:130, CI-confirmed), the NoAmdDisplay regression (host_gpu.rs:511, traced by reading, not run), and the untested planner wiring (main.rs:8763). The fourth is here:
chat_install_driver_actionreturnsResultbut can never fail, and part of it is dead —apps/rocm/src/driver_install.rs. It is alwaysOk; the!arg.starts_with("--yes=")clause cannot match, because--yesis a bool flag (main.rs:~798). Confidence 75 · mechanical · Fix: return the action directly and drop the clause.
Non-blocking
- The WSL probe skips the Microsoft-fallback exclusion the module docs say lives in one place —
host_gpu.rs:540-556.amd_display_driver_inforejects10.0.*/ "Microsoft Basic Display";detect_wsl_host_driverstill returnsVersion("10.0.26100.1"), socheck_wsl_6can say "host AMD display driver 10.0.26100.1 is installed" when rocminfo sees no GPU. Confidence 70 · Fix: route the probe throughamd_display_driver_info. - The Windows install plan labels its checks
post_reboot_checks:for a command that installs nothing —driver_install.rs:~893, render at:1592-1680. The plan keepsreboot_required: true, and the render code's own comment says that label would "tell the user to reboot for nothing". Confidence 70 · Fix:reboot_required: falseon the validate-only plan. - Provider-assisted planning still treats Windows
install driveras approval-required —main.rsnear 9360 (provider_planner_args_require_approval). Conservative, not unsafe, but the comments say every planner derives its flags fromhost_install_driver_only_reports. Route it through the helper or narrow the comment. rocm-doctorrationale is inaccurate —skills/rocm-doctor/reference.md:39-40,SKILL.md:121-125say the advice-only entry "is shown to the user byrocm examineand the README";examineprints only adriver_ageline and an agent cannot see the README. Say "relay the entry'stitleandevidenceas advice".docs/testing.mdfilters claim "and nothing else" — the new cross-platform planner test matches none of the listed fragments, whiledisplay_driver/driver_factalso match the startup-path tests (names grepped,--listnot run).diagnose-41— raised last round, still open. The title ("appears only for an old driver") overclaims: on a current-driver host the step only proves the advice is absent. Separately, the score check atdiagnose_steps.rs:~2796comparesOption<i64> < Option<i64>, so a missingscorepasses. Retitle andexpectboth values.- The old-driver branch has no end-to-end seam —
examine-29,diagnose-41anddriver-install-04run against whatever driver the lane has, so breakingassess_date, thePredatesarm or the cutoff stays green; only thewindows_driver.rsunit tests cover it. The description discloses this. driver_host_guard.rs:12-35— raised last round, unchanged. It matches the literalrequire_native_windows();in step source, so a comment satisfies it.CalendarDate::parseis looser than its doc —2021-+1-+4and2023-02-31parse. The cutoff ordering is unaffected.
Decisions for the author
- A PowerShell query on every
ExamineSummary::gathercall — tradeoff. Callers (main.rs:2081,:2714,:2839,:5003;chat.rs:3320;driver_install.rs:49,:84,:147) now pay up to the 5 sWINDOWS_INVENTORY_QUERY_TIMEOUTon AMD Windows hosts, andexamine --jsonruns the inventory twice. One shared source of truth against startup/snapshot paths that don't print the driver; gathering once per run or givinggathera scope would do both. I did not check how often the codex bridge snapshot runs. - The PR bundles several changes — non-blocking-improvement. Catalog entry,
WindowsInventorySourcesrefactor, three scopes, the WSL probe change and theis_advice_onlytext rule; the last two are outside the stated scope (AGENTS.md §11). is_advice_onlyand the platform decision are stringly-typed — non-blocking-improvement. A hard-coded id and anos == "windows"shared by three sites, with the plan builder onexamine.osand the planners on the compile-time host OS; they agree today.
Deployment notes
- Adds print-only
fix-22-display-driver-old(29 catalog entries);contract_versionunchanged; JSON additions areadrenalin_dateandsummary.driver.windows. - #677 touches the same files; whichever merges second needs a rebase and recount, including the
CATALOG_FIX_IDSorder.
What this covered
- Read: every changed file at
pr/680, completely, excepthost_gpu.rs(diff, parser, merge, preferred-adapter, pnputil/video and WSL code, not all ~5,000 lines),main.rs(every changed or driver-related region and consumers), anddiagnose_steps.rs/driver_steps.rs(changed regions and neighbours). Range2d2dfc78…7772b1f0. - CI when read:
E2E testsandE2E tests (Strix Halo, WSL2)failing (the second not opened); Windows and two Ubuntu Strix Halo lanes in progress; MI300X and W7900 queued; the rest passed. - Did not run: anything locally; mutation/revert runs; a full history pass.
- Not reconciled against the PR's existing discussion beyond removing points already raised.
| "fix-wsl-7-wsl1", | ||
| "fix-18-comgr-conflict", | ||
| "fix-19-shm-too-small", | ||
| "fix-22-display-driver-old", |
There was a problem hiding this comment.
Blocking — CATALOG_FIX_IDS is in the wrong order, so diagnose-34 fails on every platform.
RECIPES (fix.rs) and doctor-catalog.json put fix-21-msvc-redist-outdated before fix-22-display-driver-old (the reorder from last round), and rocm fix --json emits that order. The assert at diagnose_steps.rs:2506 is an ordered assert_eq!, so the swapped pair fails. The scenario has no platform tag. CI confirms it: https://github.com/ROCm/rocm-cli/actions/runs/38910065163/job/117006436496 — "Then the catalog names every entry and what the CLI does with each … the published catalog and the documented one disagree". The listing step (assert_catalog_complete) is order-insensitive, so it hides this.
Confidence 100 (CI) · mechanical · Fix: put fix-21-msvc-redist-outdated first, then fix-22-display-driver-old.
| let Some(inventory) = detect_windows_examine_inventory() else { | ||
| // This one reads the driver version, which `pnputil` never reports, so it | ||
| // asks for the driver facts. It is not a startup path. | ||
| let Some(inventory) = detect_windows_driver_inventory() else { |
There was a problem hiding this comment.
Blocking — detect_local_windows_host_driver can no longer answer NoAmdDisplay. Traced by reading the code and origin/main; not run.
The call moved from the FAST inventory to DRIVER_ONLY (host_gpu.rs:2577), which sets system: false. On a Windows host with no AMD adapter no display source returns anything and no CPU/RAM is fetched, so is_empty() (:1651) is true, assemble_windows_inventory returns None (:2612-2653) and this returns Unreachable. On main, the CPU/RAM data made the inventory non-empty and the probe returned NoAmdDisplay. check_wsl_6_host_driver_too_old abstains when the host is unreachable, so its "host reports no AMD display adapter" branch can no longer fire. No test calls this function; the DRIVER_ONLY test uses a host that has an adapter.
Confidence 85 · logic · Fix: make assemble_windows_inventory distinguish "all sources failed" from "sources answered, no adapters", or keep the system query for this caller.
| return plan_driver_request( | ||
| trimmed, | ||
| &lower, | ||
| driver_install::host_install_driver_only_reports(), |
There was a problem hiding this comment.
Blocking — the planner wiring that decides read-only vs. approval on Windows is untested.
This call and chat.rs:2525-2528 pass host_install_driver_only_reports(), but planners_describe_install_driver_as_the_command_behaves_on_each_platform calls the helpers directly with an only_reports value it computes itself, and hybrid_planner_driver_action_includes_yes_for_approved_execution now calls plan_driver_request(.., false) instead of build_freeform_plan("install the linux driver…"). Hard-coding false in either caller, or comparing the wrong OS in the helper, stays green. The same gap covers the cfg(windows) scope wiring in host_gpu.rs (gather, detect_windows_amd_driver_info, probe_adrenalin_windows): nothing asserts which scope each passes. On Windows the chat and freeform planners now drop the approval wording and --yes on this one decision (AGENTS.md §3, §7).
Confidence 85 · logic · Fix: put the OS and the inventory sources behind a parameter or trait so the callers can be tested.
7772b1f to
1302127
Compare
tomastola
left a comment
There was a problem hiding this comment.
Automated review · pr-review-watcher · 1302127
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review: needs a rebase, otherwise answered
All four blocking points from my last review are fixed, and so are almost all the non-blocking ones. One new blocking point: this PR's tests no longer compile on current main, and git does not report it as a conflict.
Blocking
- The PR's new tests don't compile on current
main. File:apps/rocm/src/driver_install.rs, five calls at roughly lines 3026, 3145, 3184, 3199 and 3218 of the merged file.- #705 (
4cd89639, merged tomainon 10-19) removed the test-onlybuild_driver_install_planwrapper. This PR's new tests call it five times. - The textual merge is clean, so neither the GitHub UI nor
git merge-treeshows a conflict. - On a trial merge with
main,cargo test -p rocm --bin rocmfails with 5 × E0425cannot find function build_driver_install_plan. Plaincargo buildsucceeds. - Fix: rebase and call
build_driver_install_plan_at(&examine, "/etc/os-release", "", true, …). I made exactly that change in a scratch tree and all 10 focusedrocmbinary tests passed. - The rebase also clears the one red check (see CI below).
- #705 (
What my last review raised, and where it stands
Blocking:
CATALOG_FIX_IDSorder: fixed.fix-21now comes beforefix-22, anddiagnose-34passes on every lane, including Windows.NoAmdDisplayregression: fixed.detect_local_windows_host_driveruses the full inventory (InventoryScope::SUMMARY) again, so the CPU/RAM answer keeps a host with no AMD adapter from reading as unreachable.- The mapping moved into a pure function,
local_windows_host_driver_probe. A new test covers no adapter, no answer at all, and an adapter present, and it pins that the driver-only inventory reads as empty.
- Untested planner wiring: fixed for the planners.
build_freeform_plan_ontakes the platform decision as a parameter.the_production_planner_…andthe_chat_entry_point_…go through the real entry points and assert results that differ by host OS. A hard-coded value would fail on Linux or Windows CI, and the Windows job (cargo test --workspace --all-targets) ran both and passed.- The
cfg(windows)scope choice is still unasserted per caller. See non-blocking.
chat_install_driver_actionreturned aResultthat could never fail: fixed. It returns the action directly, and the dead--yes=clause is gone.
Non-blocking:
- WSL probe skipped the Microsoft-fallback exclusion: fixed. Both host-driver probes now read
amd_display_driver_version(), which appliesis_microsoft_fallback_driver, and the Basic Display test asserts it. reboot_requiredon the Windows plan: fixed. It isfalse, the label readspost_install_checks:, and the test asserts thatpost_rebootis absent.- Provider-assisted planning: fixed.
provider_planner_args_require_approvalmakes Windowsinstall driverread-only, with a test. - rocm-doctor rationale: fixed. The skill now says to relay the entry's
titleandevidence. It also notes that step 2's threshold rule does not apply to this entry. docs/testing.md"nothing else" claim: fixed. The text now admits neighbouring tests match, and the filter list includes the new tests.diagnose-41: fixed. It is retitled ("agrees with the inspection"), and a missing score or threshold now fails the check.driver_host_guard.rs: fixed for whole-line comments. A trailing comment (foo(); // require_native_windows();) would still satisfy it. That is a nit; I'm not asking for a change.CalendarDate::parsetoo loose: fixed. It accepts digits only and checks days per month, including the leap-year century rule, with tests.- No end-to-end test of the old-driver branch: unchanged, and the description says so.
Non-blocking (new or remaining)
- Nothing asserts which inventory scope each
cfg(windows)caller passes. This is the rest of last round's blocker 3.- Each scope is now one named one-line wrapper (
…_with_driver_facts/detect_windows_driver_inventory/detect_windows_examine_inventory), and the new test documents why the local probe needsSUMMARY. - Changing
detect_local_windows_host_driverback to the driver-only wrapper would still stay green, because those wrappers compile only on Windows and no test calls them. - I accept this as is.
- Each scope is now one named one-line wrapper (
NoAmdDisplaystill depends on the CPU/RAM query succeeding. Ifpnputilanswers with no AMD adapter but that query fails, the result is stillUnreachable.check_wsl_6then abstains, which is the safe direction.- An
--applyexclusion that matches nothing.provider_planner_args_require_approvalskips the read-only path when--applyis present, but I found no--applyflag oninstall driver. It is the same kind of dead clause as the--yes=one removed this round. Drop it, or say what it guards.
Decisions from last round with no reply
None of these block the merge:
- An extra PowerShell query on every
ExamineSummary::gathercall, and the inventory running twice underexamine --json. - The PR bundles the WSL-probe change and the
is_advice_onlyrule with the feature. - The platform decision and
is_advice_onlyare compared as strings.
CI at 13021270
- Failing:
E2E tests (Strix Halo, Windows, current). 149 scenarios: 145 passed, 3 were expected failures (xfail), and 1 failed unexpectedly:diagnose-38.- The step asserts that
setxmust not appear, but the base's fix-6 recipe still printssetx PATH …. - This PR doesn't touch fix-6. #710 (
0acf698d) fixed it onmain, andmain's Windows lane passesdiagnose-38since then (runs 39244601953 and 39389535923). - The rebase above clears it.
- The step asserts that
- Passing on the Windows lane: the new scenarios (
examine-29,diagnose-41,driver-install-04,driver-install-05) anddiagnose-34. - Every other check passes:
windows-build-and-test,build-and-test, MI300X, W7900, WSL2 and both Ubuntu Strix Halo lanes.
Deployment notes
- Unchanged from last round:
- adds the print-only
fix-22-display-driver-old(29 catalog entries); contract_versionis unchanged;- the JSON additions are
adrenalin_dateandsummary.driver.windows.
- adds the print-only
- #677 is still open and touches the same files. Whichever merges second needs a rebase and a recount.
What this covered
- Read: the range-diff
7772b1f0 → 13021270, every hunk; the inventory-scope code inhost_gpu.rs; the Windows CI job logs for the unit tests and the e2e suite;main's Windows lane history fordiagnose-38. - Ran, on a trial merge of the PR head into current
main:- the
rocm-corefilters fromdocs/testing.md, pluslocal_host_driver_probeandcalendar: 39 passed; cargo test -p e2e-cucumber --test driver_host_guard: 2 passed;- the
rocmbinary tests failed to compile (the blocker above). After the one-line-per-call fix, the 10 focused binary tests passed.
- the
- Not run: anything on Windows (the Windows results above are from CI), the full workspace suite, and mutation runs.
1302127 to
04bfbdb
Compare
|
Addressed in 04bfbdb, rebased on current main.
On the Windows lane for the previous head, |
tomastola
left a comment
There was a problem hiding this comment.
Review: needs work — two real new bugs survived a full rewrite; everything from the last round is fixed.
Reviewed the whole diff fresh (not just the rebase delta) since the branch was rewritten. All three points from my last review (5591397855) are resolved: the five tests compile again with build_driver_install_plan_at, and the rebase cleared the one red CI check — everything is green on 04bfbdb5.
Three new blocking issues, each small and fixable:
- Chat can no longer run
install driveron Windows at all.chat_install_driver_actionnow correctly returns a read-only action there, but the in-process dispatcher it's routed through (run_rocm_read_only_in_process) has no case forinstall driver— onlyinstall sdk --dry-run— so it errors with "unsupported in-process read-only rocm command" instead of reporting. (chat.rs:2435,:3440,:3649) - The Microsoft Basic Display Adapter case still reads as "detected." The new
driver_version/date/agefields correctly treat it as no AMD driver, but the olderdriver_status/driver_detailfields (still read byrocm examineandinstall driver's reconciliation output) don't apply the same exclusion, so they still sayamd_display_driver_detected. (host_gpu.rs:1702,:1722,:2538;driver_install.rs:210) - A new advice line has no test. "Advice about this host follows... nothing in it is applied automatically" (
diagnose.rs:3005) isn't asserted anywhere — exactly the kind of CLI-behavior promise AGENTS.md §3 asks to be tested alongside the behavior.
One non-blocking nit: the long "no documented minimum" note is copy-pasted in fix.rs:926/diagnose.rs:2302 instead of hoisted to a shared constant like its neighbor FLOOR_NOTE — a drift-guard test already protects against this diverging, so low risk.
Everything else holds up well: the date-comparison logic, the platform-decision plumbing, and the Windows e2e message+state coupling are all solid. No action needed on the cutoff-reach tradeoff from earlier rounds — still the same open, accepted decision.
04bfbdb to
80f4a25
Compare
|
Addressed in 80f4a25.
Not verified: the changes are checked on Linux; the Windows lane will exercise them. |
80f4a25 to
deee2cb
Compare
Addressed in deee2cb. The module comment now says what is guaranteed (one comparison function, and one device inventory and adapter choice for examine, install driver and diagnose), and what is not (separate queries can fail differently). rocm examine now takes the driver facts from the same inventory selection as the other two commands.
juhovainio
left a comment
There was a problem hiding this comment.
Thanks for the thorough work here, the strict date parsing, the scoped inventory sources and the fact that Windows can never mutate anything are all solid. One thing needs to change before this merges, plus a handful of smaller items.
Blocking: the PR description does not match what the code does
- "Linux and WSL are unchanged" is not accurate. The shared WSL inventory script now selects
DriverDate, and the WSL host-driver probe now excludes the Microsoft fallback driver (crates/rocm-core/src/host_gpu.rs, around lines 527, 552 and 1748). - "One inventory and one adapter choice" only holds within a single command.
rocm examinereads the driver twice (the summary usesInventoryScope::SUMMARY,probe_adrenalin_windowsusesDRIVER_ONLY; thewindows_driver.rsmodule doc concedes the two can disagree).rocm statusand the fallback detail line still use the old first-match query (host_gpu.rs~2496-2504 and ~2559,apps/rocm/src/main.rs~1647), so on an iGPU plus dGPU hoststatuscan print a different driver thanexamine. - Behaviour changes that are not mentioned in the description:
amd_display_driver_detailnow returnsNonefor the Basic Display Adapter, sodriver_statusanddriver_detailgo from "detected" to "not_detected" in existing examine output.- The input to check_14 now takes the preferred adapter and drops the fallback driver, where it used to take the first AMD controller.
- The Windows install plan's
reboot_requiredwent from true to false, the check labels changed frompost_reboot_*topost_install_*, and the checks now also listrocm diagnose. - The
rocm diagnosetext rendering changed (is_advice_only/answers_symptom): with only fix-22 present, the upstream-routing block now prints before the advice. - Chat has a new in-process read-only arm for
install driver, and the provider planner has a new approval bypass on Windows.
- "
rocm install driverprints the fix id" reads as unconditional, but it is only printed for an old driver.
Either amend the description to cover these, or narrow the code. None of the code changes look wrong to me, they just need to be called out so reviewers and release notes see them.
Non-blocking, inline comments cover these: driver date timezone (N1), the missing newer-GPU caveat on outdated: no, extra Windows subprocesses on callers that never show the driver, chat flag handling, a stale count comment, a dead assertion, and a misleading doc comment.
Non-blocking, no inline anchor:
- Nothing runnable on Linux pins the gate that makes Windows install nothing (
apps/rocm/src/driver_install.rs:56). The plan tests only assert plan fields andinstall_driver()is never called, so if the!plan.supported || !plan.mutatingcheck were dropped, Windows--yeswould writestate.jsonand print "driver install completed" with only the Windows lane to catch it. Extracting a pureshould_execute(plan, yes, dry_run)would make this unit-testable. - The date "27 July 2023" is hardcoded in
fix.rs(fix-22 rationale),README.md,skills/rocm-doctor/reference.md,docs/testing.mdanddocs/manual-testing.md. One assertion in the existing recipe test tying it toFIRST_HIP_SDK_FOR_WINDOWSwould keep them in sync. - The "Next step" selector change in
diagnose.rs(find(|d| !is_advice_only(&d.id))) is not tested with a mixed report. The existing mixed test uses a 75-point fix-21, so it takes the HIGH branch. A LIKELY or WEAK real cause plus the old-driver row would cover it. - The date half of examine-29, diagnose-41 and driver-install-04 passes when the date probe returns nothing (a missing date maps to "unknown" and diagnose then expects old=false). If the new PowerShell date script returned empty on the runner, all three would stay green. Asserting the date is present whenever the version is present in examine-29 would close that.
docs/testing.mdfilter list omits three modified tests (diagnosis_remediation_matches_the_fix_catalog_for_shared_fix_ids,needs_reboot_true_fix_ids_match_the_known_set,every_recipe_id_is_unique_and_covers_the_catalog).- driver-install-04/05 have no
@requires-gputag but 04's third step needs an AMD driver, so it would fail on a Windows runner with no AMD adapter. Low risk on the current lanes. windows_driver.rsis not listed in thedocs/architecture.mdmodule list (not enforced).- Design points to confirm: the fallback-driver heuristic (name contains "microsoft basic display" or version starts with "10.0.") is unverified on Windows, and the name is localized so only the version check helps on non-English Windows; fix-22 is identified as advice-only by a hardcoded id with no marker in the catalog JSON;
needs_rebootis true on a recipe that installs nothing.
CI: all checks pass except "E2E tests (MI300X, current)", which fails on therock-next-09-live-install-reports-vllm-rocm10x-discovery-pins (uv cannot resolve vllm against amd-aiter==0.1.24.post1). The same job and scenario fail identically on main at the merge-base, so I am treating it as unrelated to this PR.
Also note #677 touches the same fix recipes, catalog and counts, so whichever lands second will need a rebase and recount.
Limits of this review: I read the Windows-only code by eye and did not run anything on Windows, so the date finding below is unconfirmed.
| const OPTIONAL_COMMAND_TIMEOUT: Duration = Duration::from_millis(1_500); | ||
| const WINDOWS_INVENTORY_QUERY_TIMEOUT: Duration = Duration::from_secs(5); | ||
| const WINDOWS_VIDEO_CONTROLLER_INVENTORY_SCRIPT: &str = r#"$gpus = Get-CimInstance -ClassName Win32_VideoController -Property Name,DriverVersion,PNPDeviceID,AdapterCompatibility | Where-Object { $_.PNPDeviceID -match 'VEN_1002' -or $_.AdapterCompatibility -match 'AMD|Advanced Micro Devices' -or $_.Name -match 'AMD|Radeon|Instinct' }; foreach ($gpu in $gpus) { "GPU`t$($gpu.Name)`t$($gpu.DriverVersion)`t$($gpu.PNPDeviceID)" }"#; | ||
| const WINDOWS_VIDEO_CONTROLLER_INVENTORY_SCRIPT: &str = r#"$gpus = Get-CimInstance -ClassName Win32_VideoController -Property Name,DriverVersion,DriverDate,PNPDeviceID,AdapterCompatibility | Where-Object { $_.PNPDeviceID -match 'VEN_1002' -or $_.AdapterCompatibility -match 'AMD|Advanced Micro Devices' -or $_.Name -match 'AMD|Radeon|Instinct' }; foreach ($gpu in $gpus) { $date = ''; if ($gpu.DriverDate) { $date = $gpu.DriverDate.ToString('yyyy-MM-dd', [System.Globalization.CultureInfo]::InvariantCulture) }; "GPU`t$($gpu.Name)`t$($gpu.DriverVersion)`t$($gpu.PNPDeviceID)`t$date" }"#; |
There was a problem hiding this comment.
DriverDate.ToString('yyyy-MM-dd', Invariant) has no .ToUniversalTime(). The WMI/DMTF driver date carries a UTC offset, and as far as I recall Get-CimInstance hands back a local-time DateTime, so on a machine west of UTC the printed date can be a day earlier than Device Manager shows. That matters at the boundary: a driver dated exactly 2023-07-27 on a UTC-7 host would read 2023-07-26 and trigger fix-22 wrongly. I could not confirm this on Windows, so please verify on a host with a negative timezone offset. If it reproduces, $gpu.DriverDate.ToUniversalTime().ToString(...) should fix it.
| DriverAge::Predates(_) => format!( | ||
| "outdated: yes, dated before the first HIP SDK for Windows ({FIRST_HIP_SDK_FOR_WINDOWS}); {NO_MINIMUM_NOTE}; fix id {DISPLAY_DRIVER_OLD_FIX_ID}, run `rocm diagnose` for the advice, then update from {AMD_SUPPORT_URL} and restart" | ||
| ), | ||
| DriverAge::NotOlder(_) => "outdated: no, the date is not older than the first HIP SDK for Windows; the minimum driver version is not established".to_owned(), |
There was a problem hiding this comment.
outdated: no here drops the caveat that age_summary (above) carries via FLOOR_NOTE: the date cannot judge gfx120X, gfx1150 or gfx1151. A gfx1151 user with a driver dated just after 2023-07-27 will read outdated: no as a clean bill of health, which goes against the 'printed claims must be true as stated' rule. Suggest appending FLOOR_NOTE in this branch, and in the Predates branch and the diagnose evidence string for consistency.
| let windows_inventory = detect_windows_examine_inventory(); | ||
| // Summary callers show the driver version and date. Startup and engine | ||
| // selection use the fast inventory without this extra fact query. | ||
| let windows_inventory = detect_windows_examine_inventory_with_driver_facts(); |
There was a problem hiding this comment.
The comment above says summary callers show the driver, but several ExamineSummary::gather callers never print it (rocmd/common.rs:36, rocmd/mcp.rs:569, rocmd/sandbox.rs:192, chat.rs:3330, runtime_install_finalize.rs:1541). On an AMD Windows host rocm examine goes from about 3 spawns to about 5, and each of pnputil and the video query has a 5s timeout, so a slow host adds seconds to examine, diagnose, the MCP examine tool and the bridge snapshot. Consider giving gather() a scope parameter so only printing callers pay for the extra query, and adding DriverDate to the existing WIN_GPU_SCRIPT instead of re-running the inventory in probe_adrenalin_windows (examine.rs:3203). The startup paths still use FAST and the the_startup_paths_do_not_start_the_driver_fact_query test pins that, which is good.
| [command, subcommand, rest @ ..] | ||
| if command.eq_ignore_ascii_case("install") | ||
| && subcommand.eq_ignore_ascii_case("driver") | ||
| && rest.iter().all(|arg| arg.eq_ignore_ascii_case("--dkms")) => |
There was a problem hiding this comment.
This arm accepts only --dkms, so install driver --dry-run, --reconcile or --yes=true from chat or MCP now hits bail!("unsupported in-process read-only rocm command") on Windows. Before this PR those became an approval that ran in a subprocess. chat_install_driver_action (line 2440) also only strips an exact --yes, whereas the install sdk arm also strips --yes= prefixes. Suggest accepting --dry-run in this arm and stripping --yes= the same way the sdk arm does.
| // fix-21-msvc-redist-outdated, fix-22-display-driver-old and the | ||
| // informational info-20-gpu-no-rocm-support among them) plus the 7 WSL | ||
| // ones. | ||
| assert_eq!(count, 29, "expected 29 catalog entries"); |
There was a problem hiding this comment.
The comment above still says '21 bare-metal/Windows entries ... plus the 7 WSL ones', but the assert is 29. With fix-22 added it should read 22 (22 + 7 = 29).
| "{output}" | ||
| ); | ||
| assert!( | ||
| !output.lines().any(|line| line.trim() == "execution:"), |
There was a problem hiding this comment.
This negative assertion can never fail: the renderer emits execution_commands:, never a bare execution: line. It looks copied from the WSL step at line 67, where it has a different meaning. The other assertions already cover the point, so this can be dropped.
| } | ||
|
|
||
| impl Examination { | ||
| /// Record the AMD display driver, from the one probe result that |
There was a problem hiding this comment.
The doc comment says this reads 'the one probe result that rocm examine and rocm install driver also read', but each command runs its own inventory query (the host_gpu.rs comments around 2720-2721 admit this). Worth rewording so the next reader does not assume a shared cached fact.
tomastola
left a comment
There was a problem hiding this comment.
Review: the last round is answered, nothing blocking
This covers what changed after my last review at 04bfbdb5. The branch was rewritten twice. 80f4a25a holds the fixes (79 lines in 5 files). deee2cb3 rebases that onto current main (1c33248c, 6 commits ahead). The rebase changed only context lines in README.md and skills/rocm-doctor/reference.md, plus the Linux-only / Linux + WSL lists, which now take main's move of fix-17. Nothing was built or run locally. The points below come from reading the code and from CI on deee2cb3.
What my last review raised, and where it stands
Blocking:
- Chat could not run
install driveron Windows: fixed.run_rocm_read_only_in_processhas a new branch forinstall driver(chat.rs:3776-3789). It callsinstall_driver(paths, dkms, false, /*dry_run*/ true), so it can never execute a plan.- It accepts
--dkmsand no other flag. install_driver_read_only_call_runs_in_processchecks both: the call runs in process, and an unknown flag is refused.
- The Basic Display Adapter read as "detected" in the old
driver_status/driver_detailfields: fixed where the inventory is read.amd_display_driver_detail(host_gpu.rs:1703) now appliesis_microsoft_fallback_driver.examineand theinstall driverreconciliation getnot_detectedand no detail.- The existing fallback test asserts both (
host_gpu.rs:5440).
- The new advice line had no test: fixed.
diagnose.rs:7017-7036asserts the exact line, and in the same test asserts that every command in the advice is a#comment. That ties the "nothing is applied automatically" promise to what the code does.
Non-blocking:
- "No documented minimum" note was copied in two places: fixed. Both places now use
windows_driver::NO_MINIMUM_EXPLANATION, likeFLOOR_NOTE.
The description's claims still match the head. For example, the catalog has 29 entries in doctor-catalog.json and in reference.md.
Suggestions (non-blocking)
install driver --dry-runfrom chat on Windows fails (chat.rs:3783). Traced by reading, not run.--dry-runis a real flag oninstall driver(main.rs:810).- On Windows,
chat_install_driver_actionremoves only--yesand returns the rest as a read-only call. - The in-process branch accepts only
--dkms. So when the model asks forinstall driver --dry-run, the user gets "read-only assistant command is not implemented in-process" where they should get the report. - Before this PR, that call went through the approval path and worked.
- Suggestion: accept
--dry-runin the samerest.iter().all(..)test. The call is already a dry run, so the flag changes nothing.
- The Microsoft-fallback exclusion still misses one path.
detect_windows_amd_display_driver(host_gpu.rs:2559) is the raw PowerShell probe. It does not applyis_microsoft_fallback_driver.- It feeds
rocm_core::detect_gpu_driver_version(), which printsGPU driver: …atmain.rs:1647. - It is also the
fallback_detailthatwindows_driver_summary_from_inventoryuses when there is no inventory at all. - On a host running only the Basic Display Adapter, that line can still name the Microsoft driver as the GPU driver. This came before the PR and is outside the three commands it covers.
- Suggestion: filter the probe's result through the same predicate, or say in the description that only
examine,diagnoseandinstall driverare covered.
CI
Every check is green on deee2cb3 except E2E tests (MI300X, current), which has nothing to do with this change.
- The failing scenario is
therock-next-09-live-install-reports-vllm-rocm10x-discovery-pins.uvfinds no version set it can install for the vLLM reinstall. - #724 and #725 fail on the same lane today with the same scenario, plus two vLLM serve scenarios.
The Windows lane passed, which covers examine-29, diagnose-41, driver-install-04/-05 and the cfg(windows) build.
Decisions for the author
- The cutoff only reaches some GPUs: a date check can never fire on gfx120X, gfx1150 or gfx1151. This was accepted in earlier rounds and the docs say so. Nothing more is needed.
1fb235f to
ca001a6
Compare
|
@juhovainio thanks for the thorough review. The branch is now rebased onto current Blocking: description did not match the code. I rewrote the PR description against the code. It now covers the WSL inventory change ( Inline comments
Non-blocking points without an inline anchor
On the overlap with #677: agreed, whichever lands second needs a rebase and a recount. The description says so under "Merge order". |
|
@juhovainio follow-up on the three points I left open in my last comment. Head is now Chat/MCP
Extra Windows queries from
Checked locally on the Windows host before pushing: |
juhovainio
left a comment
There was a problem hiding this comment.
No blocking issues from a read of the diff. The earlier chat install driver --dry-run / --yes= gap is fixed, and the newer-GPU caveat next to outdated: no is in. Non-blocking notes are inline: the lean-gather test can't prove the fast path is used, the manual-testing DriverDate claim differs between local time and UTC, and the 10.0.* fallback-driver heuristic is unverified on real hardware. The PR description is also stale (it still says outdated: no has no caveat and lists the chat --dry-run as a known gap), and the bundled scope plus overlap with #677 will need a rebase and recount. This reflects a diff-only read; CI was still pending when I checked and the Windows GPU lane is not exercised here, so please wait for green before merging.
| let windows_inventory = if driver_facts { | ||
| detect_windows_examine_inventory_with_driver_facts() | ||
| } else { | ||
| detect_windows_examine_inventory() |
There was a problem hiding this comment.
Nothing tests that this branch picks the fast inventory. the_summary_without_driver_facts_keeps_the_gpu_target passes if gather_without_driver_facts fetches the driver facts anyway (on Linux both sides are None; on Windows the assertion allows lean == full). Consider a small pure scope selector that is unit-tested, or an injected inventory source.
| full.compatible_therock_family | ||
| ); | ||
| assert!( | ||
| lean.driver.windows.is_none() || lean.driver.windows == full.driver.windows, |
There was a problem hiding this comment.
This assertion allows lean.driver.windows == full.driver.windows, so it cannot detect that the lean path still ran the video-controller query. It also runs the real gather() twice. Assert lean.driver.windows.is_none() on an AMD Windows host, or test the scope mapping directly.
|
|
||
| Expected result: | ||
|
|
||
| - `rocm examine` prints `driver_version` and `driver_date`. Both match the |
There was a problem hiding this comment.
Get-CimInstance ... DriverDate prints a local-time DateTime, while rocm examine formats the date in UTC. West of UTC the two differ by a day, so "Both match" is not true everywhere. Reword, or print the date in UTC here (and in the fix-22 verify command).
| pub fn is_microsoft_fallback_driver(name: &str, version: &str) -> bool { | ||
| name.to_ascii_lowercase() | ||
| .contains("microsoft basic display") | ||
| || version.trim().starts_with(OS_DRIVER_VERSION_PREFIX) |
There was a problem hiding this comment.
Any version starting 10.0. is treated as the Microsoft fallback driver regardless of adapter name. The docs and tests say this was recalled, not observed, and it also changes legacy driver_status/driver_detail and the WSL host probe. Consider confirming on a machine with only the Basic Display driver, or splitting it out.
nowycondro
left a comment
There was a problem hiding this comment.
Automated high-recall review: 7 inline findings posted on touched lines. Two additional findings fall on code the diff doesn't actually change (so GitHub won't anchor an inline comment there) and are added as a follow-up comment below.
| .and_then(WindowsExamineInventory::amd_display_driver_detail) | ||
| .or_else(|| { | ||
| if windows_inventory.is_none() { | ||
| fallback_detail() |
There was a problem hiding this comment.
Legacy fallback_detail path can report the Microsoft Basic Display Adapter as an AMD driver.
When the new multi-source inventory (windows_inventory) is entirely None (every new query failed/timed out), windows_driver_summary_from_inventory falls back to the legacy detect_windows_amd_display_driver() single first-match PowerShell query. That legacy query never calls is_microsoft_fallback_driver, so on a host where the new pipeline totally fails but this old query still succeeds and matches the fallback driver (by name or 10.0.x version), rocm examine would report driver_status: amd_display_driver_detected with a driver_detail naming a driver that isn't actually an AMD driver — while driver.windows/driver_version/driver_date stay empty, since info is unconditionally None in this branch (windows_inventory.and_then(...) short-circuits on None).
This contradicts the PR's stated goal that a host running only the fallback driver reads as having no AMD driver. Note: the PR description does disclose this gap for rocm version's GPU driver: line, but this is the same underlying legacy query also feeding rocm examine's detail-only fallback — worth confirming that's the intended scope, since rocm examine/rocm diagnose/MCP examine all consume this same ExamineSummary.
| pub fn is_microsoft_fallback_driver(name: &str, version: &str) -> bool { | ||
| name.to_ascii_lowercase() | ||
| .contains("microsoft basic display") | ||
| || version.trim().starts_with(OS_DRIVER_VERSION_PREFIX) |
There was a problem hiding this comment.
Unverified 10.0. version-prefix heuristic could misclassify a real AMD driver as "no driver".
is_microsoft_fallback_driver treats any driver version starting with 10.0. as the Microsoft fallback driver (not a real AMD driver), causing amd_display_driver_info()/amd_display_driver_version() to return None for it. The module's own doc comment admits this is "recalled from how Windows reports this driver, not observed" and "has not been checked on a Windows machine." AMD's driver major version numbering has varied significantly over its history (this repo's own fixtures span 30.x–32.x), so it isn't established that no real AMD driver build ever reported a 10.0.x version string. If one exists, a genuine installed AMD driver would silently be reported as "no AMD driver detected" by rocm examine, rocm diagnose, and rocm install driver alike, since all three route through this one check.
Worth at least a code comment flagging this as a risk area to watch for in the field, or gating the version-prefix check more narrowly (e.g. combined with a known-fallback PNP device ID) if one is available.
| @@ -3058,7 +3129,7 @@ pub fn render_report_text(report: &DiagnoseReport, top: usize) -> String { | |||
|
|
|||
| if let Some(high) = report.matched.iter().find(|d| d.score >= HIGH_CONFIDENCE) { | |||
There was a problem hiding this comment.
The HIGH_CONFIDENCE "Next step" branch doesn't exclude advice-only entries, unlike the sibling else if branch three lines below.
if let Some(high) = report.matched.iter().find(|d| d.score >= HIGH_CONFIDENCE) {
let _ = writeln!(out, "Next step: run `rocm fix {}`.", high.id);
} else if let Some(best) = report.matched.iter().find(|d| !is_advice_only(&d.id)) {The else if branch was deliberately updated to filter out advice-only rows (e.g. fix-22-display-driver-old) so they're never named as "the highest-scoring match." But the first (HIGH_CONFIDENCE) branch has no such filter. Today this is harmless only because DISPLAY_DRIVER_OLD_SCORE = 25 is far below HIGH_CONFIDENCE = 75 — nothing in the code ties the two together. If a future advice-only check (the module doc suggests more may come) is ever given a score ≥ HIGH_CONFIDENCE, this branch would print "Next step: run rocm fix <advice-only-id>" as if it answers the symptom, which is exactly the problem is_advice_only was introduced to prevent in the other branch. Consider applying the same !is_advice_only filter here too, for symmetry and future-proofing.
| /// Such an entry reads only evidence, never the symptom, so it fires whatever | ||
| /// the user reported. The text report must not call it "the highest-scoring | ||
| /// match" nor let it stand in for the upstream escalation. | ||
| fn is_advice_only(fix_id: &str) -> bool { |
There was a problem hiding this comment.
is_advice_only hardcodes a single fix-id rather than a general property on Diagnosis.
fn is_advice_only(fix_id: &str) -> bool {
fix_id == crate::windows_driver::DISPLAY_DRIVER_OLD_FIX_ID
}Diagnosis has no kind/advice_only field; "advice-only" is expressed purely as (a) a score tuned below MIN_SCORE_FOR_MATCH, plus (b) this id-equality check consulted at two call sites in render_report_text. The two mechanisms aren't linked by the compiler or any assertion. A future advice-only entry needs its author to remember to extend this function by name and keep both call sites in sync; forgetting either silently lets an advice row "answer" the symptom. A kind: FindingKind (or advice_only: bool) field set once where the checker builds its Diagnosis would make this structural instead of a growing whitelist — worth considering now while there's only one entry to migrate, even though it's arguably minor with just one instance today.
| /// none or it is the Microsoft fallback driver, which is not an AMD driver. | ||
| /// The host-driver probes read it from here so they apply the same | ||
| /// exclusion as [`Self::amd_display_driver_info`]. | ||
| fn amd_display_driver_version(&self) -> Option<String> { |
There was a problem hiding this comment.
amd_display_driver_version re-implements the preferred-adapter + fallback-filter lookup a third time.
amd_display_driver_detail (line 1703), amd_display_driver_info (line 1732), and this method each independently call preferred_amd_display() and re-apply the Microsoft-fallback-driver exclusion with slightly different code shapes. This method's result is logically just self.amd_display_driver_info().map(|i| i.version) — same adapter lookup, same fallback exclusion, same trimming — so it could delegate instead of hand-rolling the filter a third time, removing one of the three near-duplicate copies and the risk of them drifting apart (e.g. if the fallback-exclusion condition is ever tweaked in one copy but not the others).
| if e.os_family != "windows" { | ||
| return zero(id, TITLE); | ||
| } | ||
| let Some(info) = crate::windows_driver::WindowsDriverInfo::from_probe( |
There was a problem hiding this comment.
Driver date goes through an unnecessary parse → format → re-parse round trip to reach this checker.
Examination::set_windows_driver (examine.rs) takes an already-parsed WindowsDriverInfo (with a structured Option<CalendarDate>), formats the date back to yyyy-MM-dd text, and stores it as the plain adrenalin_version/adrenalin_date strings on Examination. check_22_display_driver_old then calls WindowsDriverInfo::from_probe on those same two strings, re-parsing the date it had as a structured value a few lines of code earlier. DriverSummary.windows on ExamineSummary already stores the structured WindowsDriverInfo directly and avoids this; Examination could carry the same Option<WindowsDriverInfo> (or just the parsed CalendarDate) alongside/instead of the two raw strings, letting this checker use the value directly rather than reparsing text produced from a CalendarDate moments before.
| mut args: Vec<String>, | ||
| only_reports: bool, | ||
| ) -> ChatRocmCommandAction { | ||
| args.retain(|arg| arg != "--yes" && !arg.starts_with("--yes=")); |
There was a problem hiding this comment.
Duplicated --yes stripping logic between this new function and the pre-existing install sdk arm.
args.retain(|arg| arg != "--yes" && !arg.starts_with("--yes="));This exact statement also appears in the install sdk arm of chat_rocm_command_action_from_args further down in this file. Both sites exist for the same reason (stripping a model-supplied --yes/--yes=... before the command may later append its own bare --yes), and this function's own doc comment even says "as the install sdk arm does" — acknowledging the duplication rather than factoring it out. A shared fn strip_model_supplied_yes(args: &mut Vec<String>) helper would keep the logic (and the reasoning behind the exact-match-plus-prefix form, tied to clap's current rejection of an attached value on a bare bool flag) in one place for future edits.
|
Two more findings from the same review pass. Both sit on code this PR doesn't modify, so they can't be anchored as inline diff comments: 1. "examine" | "doctor" => {
let examine = ExamineSummary::gather()?;
let text = render_examine_text()?;
Ok(internal_mcp_tool_success(text, serde_json::json!(examine)))
}
2.
|
|
🤖 Automated review (Claude Code) · 9a5e4e9 Note on scope: I was asked to review at head This supplements the review I already posted (review #5655966524, 7 inline comments) and a follow-up comment (#6422336302, 2 more findings on untouched-but-related code). Summary, most important first: Non-blocking (no hard blockers found)
No correctness-blocking issues found in the What I read / verified: the full PR diff (27 files), the 🤖 Generated with Claude Code |
|
🤖 Automated review (Claude Code) · 9a5e4e9 I read the diff for this PR (Windows driver version/date detection, Two items worth double-checking on the Windows driver-version/date path: (1) Non-blocking notes: 🤖 Generated with Claude Code |
Read the AMD display driver version and date through the preferred adapter in the shared Windows inventory. Examine, diagnose and driver installation use the same selection; independent probe failures can still differ. Startup and engine selection avoid the supplementary driver-fact query. Show date-based advice for drivers older than the first HIP SDK for Windows release on 2023-07-27. No minimum compatible version is established. The new fix-22 entry is print-only and below the match threshold, and advice alone preserves upstream escalation. Windows driver installation remains non-mutating with or without approval. Cover inventory wiring, optional dates, fallback drivers, adapter choice, recipe drift and advice-only reports with unit tests. Add Windows scenarios examine-29, diagnose-41, driver-install-04 and driver-install-05, including version/date assertions and installer-state checks. The two install steps refuse any host that is not native Windows before they run the CLI, because explicit cucumber filters bypass platform tags; a unit test pins that order without running an installer. Update the catalog, skill and behavior docs. Verified on Linux: fmt, workspace clippy and e2e-target clippy with warnings denied, serial workspace tests (the only failure is an xtask lychee test that cannot execute lychee here), crate edges, catalog, local smoke, and focused core and CLI tests. The Windows scenarios were not run: Windows GPU behavior and the old-driver hardware branch remain unverified locally. Signed-off-by: Eugene Volen <Eugene.Volen@amd.com>
Extract the execute gate of install_driver into should_execute so a unit test can assert that a Windows plan is never run, with or without --yes, while a supported mutating plan is. Signed-off-by: Eugene Volen <eugene.volen@amd.com>
Signed-off-by: Eugene Volen <eugene.volen@amd.com>
…l cause plus the old-driver row Signed-off-by: Eugene Volen <eugene.volen@amd.com>
…s read Signed-off-by: Eugene Volen <eugene.volen@amd.com>
The CIM driver date is a local-time DateTime for midnight UTC, so a host west of UTC printed the previous day and could flag a driver dated on the cutoff day. Convert to UTC before formatting. Signed-off-by: Eugene Volen <eugene.volen@amd.com>
… comment Signed-off-by: Eugene Volen <eugene.volen@amd.com>
…tion The count comment above the 29-entry assert said 21 bare-metal/Windows entries plus the 7 WSL ones, which is 28. fix-22 is among them, so it is 22 + 7 = 29. driver-install-04 asserted that no bare `execution:` line is printed. Nothing in the driver plan renderer emits one (it prints `execution_commands:`), so the assertion could never fail. The neighbouring assertions already pin that nothing was executed. Signed-off-by: Eugene Volen <eugene.volen@amd.com>
…ndows On Windows `rocm install driver` only reports, and the chat/MCP action is a read-only in-process call. That arm took only --dkms, so --dry-run (which the arm already does) was refused where it previously ran in a subprocess. Accept --dry-run, and strip an attached --yes=... in chat_install_driver_action the way the install sdk arm does. --reconcile stays refused: it rewrites the saved driver install state, and before the read-only path existed the approval path appended --yes, which the command rejects together with --reconcile. Signed-off-by: Eugene Volen <eugene.volen@amd.com>
`rocm install driver` on Windows printed `outdated: no` without saying the date cannot judge gfx120X, gfx1150 or gfx1151, which `rocm examine` already says on its driver_age line. A bare `no` read as a clean bill of health for exactly the GPUs the date cannot judge. Append FLOOR_NOTE to that verdict. `outdated: yes` and the diagnose evidence are left alone: a date before the floor is old for every GPU, and the fix-22 diagnosis already carries FLOOR_NOTE in its notes. Tests assert the printed caveat together with the NotOlder state, the cutoff day, and that yes/unknown stay without it. Signed-off-by: Eugene Volen <eugene.volen@amd.com>
…ds it ExamineSummary::gather() now always asks the video controller for the Windows driver version and date (one extra PowerShell CIM query, about 2s on a Strix Halo host, 1 -> 2 spawns). Add gather_without_driver_facts() for a caller that reads neither and use it for the post-install host GPU check, which only needs the GPU target. The other gather() callers stay on the full summary on purpose: they print the driver (the freeform examine answer) or serialize the whole summary, including driver.windows, to a client (MCP examine, bridge snapshot, sandbox snapshot, examine --json). Signed-off-by: Eugene Volen <eugene.volen@amd.com>
9a5e4e9 to
c2b7118
Compare
Problem
On Windows,
rocm examineshowed the AMD display driver as a name only, with no version or date. A laptop with a 2021 driver raised no warning inrocm examineorrocm diagnose, androcm install driveronly said to runrocm examine.Cause
The inventory lists the adapter through
pnputil, which has no driver version. The video controller query ran only when that list was empty.check_14needs a HIP SDK and a failinghipInfoor a symptom, and it never compares dates.Change
New output
rocm examineprintsdriver_version,driver_dateanddriver_ageon Windows when a driver version was read. With--jsonit addsadrenalin_dateand an optionalsummary.driver.windows(version, date, age). Both are additive;contract_versionis unchanged.fix-22-display-driver-old. It needs no HIP SDK, scores 25 (below the match threshold) and never setshas_match. Slot 20 belongs toinfo-20-gpu-no-rocm-support, so this entry uses 22. The catalog (doctor-catalog.json,reference.md) now has 29 entries.driver_ageand the advice text say so. Theoutdated: noline inrocm install drivercarries the same caveat;outdated: yesdoes not need it, because a date before the floor is old for every GPU.windows_driver.rs.How the driver is read (what is and is not shared)
rocm examine,rocm diagnoseandrocm install driverread the driver version and date through one function and one adapter choice (preferred_amd_display, which ranks a ROCm-supported discrete GPU above an integrated one). Each command makes its own query, so one run can succeed where another times out.rocm examine --jsonreads the driver twice: once forsummary.driver.windows(with the CPU and RAM facts) and once for theadrenalin_*fields of the examination. On a host with more than one AMD adapter the two reads use the same selection rule, but they are separate queries. Thewindows_driver.rsmodule doc states this.GPU driver:line ofrocm version, and the detail fallback used when no inventory could be read at all. Both still use the older first-match PowerShell query. On a machine with an integrated and a discrete AMD adapter,rocm versioncan therefore name a different adapter's driver thanrocm examinedoes. That query also does not exclude the Microsoft fallback driver (below), so on a machine running only that driverrocm versioncan still print it as the GPU driver.InventoryScope::FAST) and start no driver query.ExamineSummary::gather()starts one extra PowerShell/CIM query on an AMD Windows host (measured about 2 seconds here, with a 5 second timeout). Most callers consume the result: the daemon, its MCP examine tool and sandbox, and the chat snapshot carry the whole summary, includingdriver.windows, into their JSON. Only the post-install host GPU check in runtime install finalize never reads the driver, and it now callsgather_without_driver_facts().rocm examine --jsonandrocm diagnosestill run the inventory twice (once ingather()and once for theadrenalin_*fields); fixing that needs a shared inventory handed intoExamination, which changes the crate API, so it is left for a separate change.Behavior changes beyond the new lines
10.0.driver version, and the name is localised, so on a non-English Windows only the version test applies. This follows from how Windows names the fallback driver and was not observed on a machine. Existing examine fields change with it:driver_statusanddriver_detailgo fromamd_display_driver_detectedtonot_detectedand no detail for a host that runs only that driver. The input tocheck_14takes the preferred adapter and drops the fallback driver, where it used to take the first AMD controller.DriverDate, and the WSL host-driver probe (detect_wsl_host_driver, used byrocm versionand the WSL checks) now excludes the Microsoft fallback driver, so it can report "no AMD display" where it used to report a10.0.*version. The WSL path does not use the date. Linux native output is unchanged.DriverDateis a local-time value for midnight UTC, so without the conversion a host west of UTC would print the previous day and could flag a driver dated exactly 2023-07-27.rocm install driveron Windows:outdated: yes/no/unknownverdict. It namesfix-22-display-driver-oldonly when the verdict isyes, not in every run. When no version could be read it says so and points atrocm examine.--yesor--dry-run. A pureshould_executegate is unit tested for this.reboot_requiredchanges from true to false, its check labels change frompost_reboot_*topost_install_*, and the checks also listrocm diagnose. Linux and WSL plans are unchanged.rocm diagnosetext on Windows: an advice-only row (today only fix-22) is never named "the highest-scoring match" and never replaces the upstream-routing text. With only fix-22 present, the "no known misconfiguration matched ... file upstream" block now prints first, followed by "Advice about this host follows ...", then the fix-22 entry. The "Next step" line comes from the first non-advice row. With a real cause present the report is as before. JSON (matched,has_match) is unchanged.install driveris planned as a read-only call: no--yes, no approval, no "privileged or disruptive" wording. Linux and WSL keep approval and--yes.install driver. It runs the command as a dry run and accepts--dkmsand--dry-run, and strips a model-supplied--yesand--yes=...the way theinstall sdkarm does.--reconcileis still refused there: it rewrites the saved driver install state, and it never worked from chat before this change either, because the approval path appended--yes, which the command rejects together with--reconcile.install driveron Windows only.rocm-doctorskill:SKILL.mdgains a rule for advice-only entries (relay, never apply, keep routing upstream whenhas_matchis false). The downstream copy of the skill needs its hand sync.What "old" means
The check compares the driver date only with the release date of the first HIP SDK for Windows. It cannot fire on gfx120X, gfx1150 or gfx1151, which launched later. It is not a compatibility check.
Tests
fix-22plan drift guards, the planner text next to what the command does on each platform, the Windows host check, and the gate that stops Windows from executing an install plan. A mixedrocm diagnosereport (real cause below HIGH plus the old-driver row) covers the "Next step" selector.examine-29,diagnose-41,driver-install-04anddriver-install-05. They run only on native Windows.examine-29fails if a driver version is read with no date, so a silent date failure cannot leave all three green. Only the old-driver branch (a driver dated before 2023-07-27) has no end-to-end scenario, because it needs such a machine; unit tests cover it.README.md,reference.md,docs/testing.md,docs/manual-testing.mdanddocs/architecture.mdare updated.Verified locally
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test -p rocm-core --all-targetsandcargo test -p rocm --bin rocmpass, and the four scenarios above pass against a real Windows AMD adapter.rocm examineprinted a real version, date and age, and a realDriverDatewas checked to be midnight UTC delivered as local time.cargo test -p rocm-core --liband the driver and WSL-filtered tests pass.cargo test -p e2e-cucumberon Windows: 2 library tests that create symlinks fail with "Access denied" on this host (no symlink privilege). They do not touch this change.Not verified
DriverDateinto a UTC-8 zone in PowerShell, not on a host that is actually west of UTC.Merge order
The verify-command fix (#677) touches the same files (the fix recipes, the catalog,
reference.mdand the fix counts). Whichever merges second needs a rebase and a recount.