Skip to content

fix(diagnose): stop claiming the CLI will apply fixes it only reports - #382

Open
volen-silo wants to merge 1 commit into
mainfrom
fix/overstated-fix-applicability
Open

volen-silo wants to merge 1 commit into
mainfrom
fix/overstated-fix-applicability

Conversation

@volen-silo

@volen-silo volen-silo commented Sep 11, 2026 •

Copy link
Copy Markdown
Collaborator

What

auto_applicable was a flat bool meaning "rocm fix <id> will carry this out", and it was wrong for two entries:

  • fix-2-unset-override on Linux. run_unset_override splits by platform. The Windows arm takes FixOptions and does the dry-run/confirm dance; run_unset_override_linux takes no options at all — it reads the live override, scans five shell rc files, and reports where it is set. It never writes, so --dry-run is a no-op and --yes is never read.
  • fix-9-igpu-dgpu with no --device-index. Both arms print the query that identifies the discrete GPU and return without acting.

Both were marked auto-applicable, so a user — and an agent reading the same output — was told a change was coming that never came, and got exit 0 confirming it.

The repo already knew. fix_9_without_device_index_is_print_only_and_returns_zero, the comment on the fix-2 dry-run test, and a step comment in the e2e suite all say print-only for exactly these cases. Only the type disagreed.

Why a class, not two corrected booleans

A bool cannot say either of these things: that behaviour differs by platform, or that it is conditional on an argument. auto_applicable is now derived from a per-platform class — AUTO, NEEDS-ARG, PRINT-ONLY, DIAGNOSE-ONLY. Scope and class are held together because they are one fact: fix-2 applies on Linux as print-only and on Windows as auto.

DIAGNOSE-ONLY covers problems that can be detected and explained but have no reliable fix. It has no member yet — all 16 entries have real fixes; twelve are print-only because they need sudo, a reboot, a reinstall or a download. The first member arrives with the conflicting code-object-manager entry, which is where its scenario will land.

Non-obvious decisions

The class says what happens to the machine, not whether a runner runs. Gating the runner on the class would have thrown away fix-2's Linux rc-file report and printed a generic "copy the commands above" in its place. A print-only entry may hold a runner that reports without writing; a_recipe_that_acts_has_a_runner asserts only the direction that matters.

DIAGNOSE-ONLY exits 0. Exit codes signal outcome, and "explained, nothing to do" is not a failure — 3 already means "not applicable here", a different claim that would send a caller looking for another machine. A caller reads the class from the listing before invoking, so it needs no new code to branch on. Adding one before the exit-code map is formalised would also mean the published skill treating it as an error. Flagging it: this is worth a second opinion. (Raised again in review: the variant has no catalog member yet and costs a Plan::Unfixable arm, a synthetic test fixture, and user-facing prose in README/--help for something nothing produces today. Keeping it per the earlier round's reasoning — rocm diagnose --json already serialises class, so a consumer deserialising that into a fixed enum would reject a variant added later — but leaving the tradeoff open for a second opinion rather than re-deciding it unilaterally.)

auto_applicable is kept, derived. It is redundant once class exists, but it is the field published consumers read, and it now answers its own question truthfully for the first time. Removing it is a type change that belongs with the contract-version work.

The listing is per-machine. The marker shows what the entry does on the host in front of you, so the set marked AUTO is now OS-dependent — which is why the e2e expectation is too.

Killing the duplication

diagnose restated applicability by hand at 21 sites. Those are gone; the class is read off the catalog in one place, keyed on the examined machine's OS rather than the running one. The two copies had already drifted on main — fix-9 was auto_applicable: true in the catalog and false in the Linux arm of its own checker — and nothing compared them, because the existing cross-check compares only the command block.

Rebased onto current main: the skill contract broke, silently

This branch forked before skills/rocm-doctor/ landed on main. The merge onto current main is textually clean in skills/** and the e2e skill-contract steps — nothing in the rebase itself warns about this — but the reclassification breaks the published skill's contract in a way only review caught:

  • tests/e2e-cucumber/tests/e2e/skill_steps.rs's marker parsing recognised only AUTO/PRINT-ONLY; fix-9's new NEEDS-ARG would have been silently dropped from the comparison (_ => continue) rather than reported as a mismatch, producing a red skill-01 on main with the misleading message "reference.md documents fix-9 which rocm fix doesn't offer".
  • skills/rocm-doctor/reference.md's catalog table and prose still claimed a flat, host-independent "auto-applicable" set (four ids, including fix-9), which the per-platform class makes impossible to state as one list — fix-2-unset-override is AUTO on Windows only, and fix-9 is never AUTO at all now.

Fixed both. skill_steps.rs's marker comparison is now host-aware: it reads the catalog's marker plus an optional per-platform override, derives what rocm fix should report on the host the scenario is actually running on (folding in the CLI's own out-of-scope-means-PRINT-ONLY fallback), and recognises all four FixClass markers so an unrecognised one still fails loudly instead of disappearing. reference.md's table now spells the literal marker word rocm fix prints (not yes/no), and its "auto-applicable" prose is a per-host bullet list (linux/windows/wsl). Added tests/skill_reference.rs::catalog_markers_use_the_cli_vocabulary, a plain cargo test (no built binary needed) that catches a stray yes/no cell before the cucumber suite would — proved it can fail by reverting fix-9's cell and watching it go red, then restored it.

The Scope note below ("skills/ ... deliberately untouched") no longer holds; superseded by this section.

Verification

  • cargo fmt --all -- --check, cargo clippy --workspace --all-targets -- -D warnings, cargo clippy -p e2e-cucumber --test e2e -- -D warnings — all clean.
  • cargo test --workspace --all-targets — clean (966 passed). One run hit comfyui::tests::status_reports_stopped_when_saved_comfyui_pid_is_gone, the documented full-suite-parallel-load flake; re-ran once, passed.
  • cargo xtask e2e -- -n skill on a WSL2 dev host — all 6 scenarios pass, including skill-01/02/03 against the new host-aware marker logic (this host resolves to the wsl branch, so that path is exercised for real, not just reasoned about).
  • cargo xtask e2e -- -i diagnose.feature (not -n diagnose, which bypasses the tag-based skip resolution — see the warning in this commit's own message, and docs/testing.md) — 22 scenarios, 16 run and pass, 6 skip. All 6 skips are @requires-bare-metal scenarios (platform.json: "requires a bare-metal host; this one is WSL2"), including @id:diagnose-fix-preview-states-required-flags (diagnose-20) and @id:diagnose-fix-needing-an-argument-says-so (diagnose-22). Both are new/changed by this PR — diagnose-20's @requires-bare-metal tag is added here (it was untagged on main), and diagnose-22 is a new scenario carrying it from the start — so neither is "unchanged from before this PR", and the earlier draft of this section's "3 failures" claim was wrong on both counts (they're skips, not failures, under the harness's actual skip-resolution path). The lanes that exercise these two for real are the self-hosted bare-metal Linux and Windows lanes (not WSL2) — see docs/ci-hardware-testing.md.
  • Both new scenarios were verified to fail, not just to pass. Reverting fix-2's Linux class to Auto fails diagnose-17 (and diagnose-12, which pins the auto set). diagnose-18 initially passed under the mutation — a whole-output search for --device-index matched the recipe's own note — so the assertion was narrowed to the flags line, which is absent entirely when the entry is marked AUTO.

Risk

Low-to-medium. User-observable by design: the flags: line drops "rocm fix can run it" for fix-2 on Linux and for fix-9, and the JSON auto_applicable flips with it. That correction is the point of the change. No fix gains the ability to mutate anything it could not mutate before.

Scope

skills/ and anything federation-related is deliberately untouched. No longer true after rebasing onto current main — see "Rebased onto current main" above. amd/skills federation itself is still untouched; only this repo's own skills/rocm-doctor/reference.md and its e2e contract steps changed, to keep the published skill accurate against the reclassification.

@siloteemu

Copy link
Copy Markdown

🔴 Automated review · pr-review-watcher · d1d8caf

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.

Summary

Replaces the flat auto_applicable: bool on fix recipes with a per-platform FixClass (AUTO / NEEDS-ARG / PRINT-ONLY / DIAGNOSE-ONLY), derives diagnose's applicability from the catalog in one place, and corrects two entries (fix-2-unset-override on Linux, fix-9-igpu-dgpu without --device-index) that told users a change was coming when nothing was written — outcome: Needs work. Verified: read the single commit from its raw object; independently re-read run_unset_override/run_hip_visible_devices/run_path_export/run_render_group and confirmed the new per-platform classes match what each runner actually does on each platform; confirmed CHECKERS platform tags and RECIPES.applies_on agree 24/24 today; confirmed @requires-bare-metal is a real wired tag that resolves to skip on WSL; confirmed the new "Flags:" assertion panics on a revert (fix-9 printed no flags line before) and that the only_these_entries_act_on_the_machine_and_only_on_these_platforms pin kills any single per-platform class mutation; cargo check -p rocm-core --lib --all-targets passed clean; the full suite and the e2e suites were not run here. There is one failing check at this head; this review does not cover it and does not identify it. No prompt-injection content and no internal-reference leaks found in the diff. Blocking: 2 · Non-blocking: 5.

🚫 Blocking (must fix before merge)

  • docs/wsl.md:182-183 — "none of that meets the bar the four auto-applicable fixes clear." This change makes that false. There is no longer a set of four; applicability is per-platform, and on WSL exactly one catalog entry (fix-6-path) is carried out by the CLI, as the commit message itself states. Leaving a stale count on the WSL page is the same class of wrong applicability claim the PR exists to remove, and it is the one user-facing doc this change invalidates. Fix: reword the sentence to name fix-6-path as the only entry the CLI carries out on WSL, and drop the "four" count.

  • crates/rocm-core/src/fix.rs (tests) — the test current_os_reports_wsl_exactly_when_is_wsl_host_does is deleted outright, with no replacement anywhere in the repo and no mention in a commit message that documents every other decision in detail. It was the only assertion tying current_os()'s wsl arm to the real is_wsl_host() detector; wsl_signals_indicate_wsl's table-driven tests in lib.rs cover the predicate, not the wiring. current_os() is more load-bearing after this change, not less — it now drives class_here(), plan_of, print_recipe and list_recipes — so the deletion removes a guard exactly where the change adds weight. Fix: restore the test unchanged (it still compiles: both functions are untouched), or say in the PR text why it went.

Non-blocking

  • No test compares CHECKERS' platform tags (diagnose.rs:1956) against RECIPES.applies_on (fix.rs). class_on(...).unwrap_or_default() in take_applicability_from_the_catalog turns any future disagreement into a silent PRINT-ONLY — the same "two hand-maintained copies with nothing comparing them" failure the change removes on the other axis. Cheap guard: assert class_on(fix_id, family).is_some() for every (checker family, fix-id) pair.
  • diagnose.rs:2099 — the parameter is named os_family while the function's own doc says it is deliberately not os_family; the caller passes platform_family(e). This will mislead the next reader into reaching for e.os_family. Rename the parameter to family.
  • diagnose-20 is vacuous on a Windows lane: platform_split_marker_here() expects AUTO there, which is also the pre-change value, so the scenario passes identically with the production change reverted. Its title ("A fix that only explains itself here…") also states the opposite of what it asserts on Windows. Real coverage comes from the Linux/WSL lanes only; worth saying so, or scoping the scenario.
  • Seven hand-written auto_applicable: false initialisers survive in diagnose.rs (check_19_shm_too_small and the six fix-wsl-* checkers) while every other checker's was removed. They are now dead writes, overwritten by the new derivation, and they re-create the duplication the change eliminates elsewhere.
  • Two comment/text nits: removing auto_applicable: false from the fix-17-torch-dlpack recipe left the multi-line comment block for commands appended to the end of the very long rationale line (fix.rs:522); and fix.rs:1754 refers to "the Epic's scenario 10", which no reader of this repo can resolve — restate it in repo terms or drop it. Separately, the new render_report_text strings ("rocm fix can run it once given an argument", "no reliable fix; rocm fix will only explain it") and the new class field's JSON shape are pinned by nothing.

Check-run conclusions at this head, both when this review started and re-read immediately before posting: 23 success, 1 failure, 1 pending, 1 skipped. A failing check is present at this head and this review does not cover it. Conclusion counts only; no per-lane detail was available, so nothing above is attributed to any named job.

@siloteemu siloteemu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Automated review · pr-review-watcher · d1d8caf

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.

First review of this PR. The change itself is sound: replacing the flat auto-applicable boolean with a per-platform classification, deriving the diagnose report's applicability from the catalog in one place, and correcting the two entries that told users a change was coming when nothing was written. Two counts gate it. The full report, including five non-blocking observations, is in the review comment on this PR.

Blocking 1: the change makes a claim on the WSL page false, and it is the same class of wrong applicability claim this PR exists to remove.

docs/wsl.md:182-183 says none of that meets the bar the four auto-applicable fixes clear. After this change there is no longer a set of four: applicability is per-platform, and on WSL exactly one catalog entry is carried out by the CLI, as this PR's own commit message states. That page is the one user-facing document this change invalidates, and leaving a stale count there re-creates the defect the PR is fixing everywhere else. Suggested fix: reword the sentence to name the single entry the CLI carries out on WSL and drop the count.

Blocking 2: a test tying the platform detector to its only caller is deleted with no replacement and no mention.

current_os_reports_wsl_exactly_when_is_wsl_host_does is removed outright. Nothing in the repo replaces it, and the commit message — which documents every other decision in detail — does not say it went. It was the only assertion tying the wsl arm of the platform lookup to the real host detector; the table-driven tests elsewhere cover the predicate, not that wiring. That lookup is more load-bearing after this change, not less, since it now drives the per-platform class, the plan, the recipe printer and the recipe listing. Removing the guard exactly where the change adds weight is what gates this. Suggested fix: restore the test — both functions it touches are unchanged, so it still compiles — or say in the PR text why it went.

Check-run conclusions when this was filed, and when the review started: 23 success, 1 failure, 1 pending, 1 skipped. A failing check is present at this head; this review does not cover it and makes no claim about what it is. Conclusion counts only; no per-lane detail was available, so nothing here is attributed to any named job.

@juhovainio juhovainio left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and it looks solid overall — the FixClass split correctly fixes the fix-2/fix-9 overstatement bug this PR set out to fix, the new e2e scenarios exercise the right behavior, and I didn't find any functional bugs in the diff.

One thing worth fixing before merge: the doc comment on take_applicability_from_the_catalog (and the PR description) say every checker used to hand-set auto_applicable, and that it's now consolidated in one place. That's not quite accurate — 20 of the 28 checkers (check_1 through check_17) were converted, but the 7 WSL checkers and check_19_shm_too_small still set auto_applicable: false, inline. This doesn't produce wrong output today, since take_applicability_from_the_catalog overwrites whatever those checkers set anyway — but it means the exact kind of catalog/checker drift this PR exists to fix (fix-9 disagreeing with itself on main) is still possible for those 8 entries, just silently masked instead of caught. Worth either converting those 8 too, or softening the comment/PR description to describe what's actually done. Left as an inline comment below.

Two minor things I noticed but wouldn't block on:

  • FixClass::DiagnoseOnly / Plan::Unfixable is fully wired up (enum variant, act_on branch, rendering, 3 tests) even though no catalog entry uses it yet — the comment calls it provisional, so this may be deliberate groundwork for a later PR, just flagging in case it wasn't meant to land yet.
  • format_flags is up to 5 positional params now (three bools plus class plus an Option<&str>) that always travel together — might be worth a small struct if it grows further.

Nothing here is a functional bug; CI looks green apart from the self-hosted hardware lanes, which look unrelated to this change.

/// Fill each finding's applicability from the catalog, for the operating system
/// of the machine that was examined.
///
/// One place, deliberately. Every checker used to state `auto_applicable` by

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says every checker used to hand-set auto_applicable and that it's now read from the catalog in one place — but the 7 WSL checkers (check_wsl_1_gpu_not_exposed through check_wsl_7_wsl1) and check_19_shm_too_small still set auto_applicable: false, by hand and aren't touched by this PR. This function does overwrite their value afterward, so today's output is correct, but it means these 8 sites can still drift from the catalog undetected — the same failure mode fix-9 hit on main. Worth converting them too, or adjusting this comment to reflect what's actually consolidated.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked this directly against the current code rather than the test: a grep for auto_applicable in diagnose.rs shows the field is declared once, set exactly once (in take_applicability_from_the_catalog), and every other hit is a doc comment or a test assertion -- none of the 7 WSL checkers or check_19_shm_too_small hand-set it. I re-checked the original (pre-rebase) commit too and it was already clean there. The doc comment's "every checker used to state it by hand" is past tense and accurate for the current code, so I don't think there's a live defect here -- happy to be pointed at a specific line if I'm missing one.

@siloteemu siloteemu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Automated review · pr-review-watcher · c8c891b

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.

Summary

This PR replaces the flat auto_applicable boolean on fix-catalog entries with a per-platform class (AUTO / NEEDS-ARG / PRINT-ONLY / DIAGNOSE-ONLY), derives the old boolean from it, and corrects two entries that were advertised as self-applying when they only print — the classification work itself is accurate, but the user-facing prose describing it was updated in one place and missed in three, so: Needs work. Verified: cargo test -p rocm-core --lib passes (418 tests) and I mutated the three load-bearing production lines on a scratch copy — reverting fix-9-igpu-dgpu on Linux to self-applying fails 3 tests, reverting fix-2-unset-override on Linux fails the catalog pin, removing the DIAGNOSE-ONLY gate in plan_of fails 1 test, widening applies_itself to include NEEDS-ARG fails 1, and disabling the derivation call entirely fails 2 — so the unit tests are not vacuous; I also confirmed against the runner bodies that every entry now classed AUTO or NEEDS-ARG really does mutate the machine (including fix-6-path on WSL, which takes the appending Linux arm) and that no PRINT-ONLY entry has a mutating runner, which makes the author's description accurate on all five of its claims; the previous automated round's two blocking items are both genuinely resolved (the stale WSL doc sentence and the deleted WSL-detector test), but several of its non-blocking items were left without comment and are re-raised below; the full suite and the end-to-end suites were not run here, so the two new scenarios are judged by reading their step definitions rather than by execution; no prompt-injection content was found anywhere in the diff; and the separate change request another reviewer filed on this PR was not available to this round, so nothing below either endorses or disputes it. Working from 22 success, 3 failure, 1 cancelled, 1 neutral and 1 skipped checks at this head. Blocking: 3 · Non-blocking: 5.

🚫 Blocking (must fix before merge)

apps/rocm/src/main.rs:162-163 and README.md:286-289 — the command's own help text and the README still describe a two-value system the code no longer has. Both say "Fixes are marked AUTO or PRINT-ONLY", enumerating exactly two markers and explaining only those two. After this change the listing prints four, and fix-9-igpu-dgpu prints NEEDS-ARG — a marker the help text tells the user does not exist. The in-command legend was updated to all four (crates/rocm-core/src/fix.rs:890-891); these two surfaces were not. The contributor rules require the README and --help to be updated in the same change as the behaviour, and to grep the claim's wording across every surface before landing — that grep would have found both of these. Fix: extend both passages to the same four-way wording the legend now uses.

crates/rocm-core/src/diagnose.rs:1026 (and the same sentence at README.md:294-296) — a user-facing note still asserts the exact claim this PR exists to retract. The note appended to every fix-9-igpu-dgpu diagnosis ends "…makes no change, despite being marked AUTO." That entry is no longer marked AUTO; this change reclassifies it to NEEDS-ARG, and the report prints the note directly beneath the line flags: needs --device-index before \rocm fix` will run it (render_report_textwritesflags:then eachnote:`). So a single report now tells the user both that the fix is waiting on an argument and that it is marked AUTO. The PR's own test comment identifies "told a change was coming that never came" as the defect, and the machine-readable field and the flags line were both corrected — the prose the user actually reads was not. The renamed test asserts the class and the flags line but nothing about the notes, which is why this survived. Fix: drop the trailing "despite being marked AUTO" clause in both places (the sentence is already complete and correct without it), and consider asserting the note's wording alongside the flags line so the two cannot drift apart again.

tests/e2e-cucumber/tests/e2e/diagnose_steps.rs:1036-1039 — the "changes nothing" half of scenario diagnose-22 is asserted by a string that never appears. The scenario is named "A fix that needs more information says what it needs and changes nothing", and the no-change half rests on assert!(!output.contains("Applied"), …), whose comment claims "the absence of that claim is the assertion". The literal Applied occurs nowhere in the product on either side of this change — the success path reports Appended to {file}… (crates/rocm-core/src/fix.rs:1393, :1503). The assertion therefore cannot fail under any regression, including the one it names, and the only check in the scenario that actually bites is the Flags: line. A test that does not test the thing it names is a blocker here, not a nit. Fix: assert against the real success wording, or better, assert the file the fix would have appended to is unchanged — the suite already does exactly that for the mutating case in a sibling scenario (diagnose_steps.rs:1221), so the pattern is available to reuse.

Non-blocking

  • crates/rocm-core/src/diagnose.rs:1021-1024 — the comment "Marked auto_applicable below, but …" now points at a literal this change deleted from both branches; it reads as describing code that is no longer there.
  • crates/rocm-core/src/fix.rs:1790-1796 — the new comment justifies the empty DIAGNOSE-ONLY class by saying a later member "would be a type change that raises the contract version", but no schema or contract version covers this output, and this change itself adds two serialised fields without one; either add the version or drop the guarantee.
  • crates/rocm-core/src/diagnose.rs:2981 — a comment names the companion test by its pre-rename name, which this change renamed.
  • crates/rocm-core/src/diagnose.rs:1529,1664,1709,1754,1799,1836,1935,1968 — eight hand-written auto_applicable: false initialisers survive and are now unconditionally overwritten by the catalog derivation; raised in the previous round and left unaddressed, and they still imply those checkers decide applicability.
  • crates/rocm-core/src/diagnose.rs:2050 — the derivation's parameter is still named os_family although its own doc explains it is deliberately not the OS family (WSL is its own value); also raised in the previous round and left.

@volen-silo
volen-silo force-pushed the fix/overstated-fix-applicability branch from c8c891b to 842617a Compare September 29, 2026 11:49
@volen-silo
volen-silo dismissed stale reviews from juhovainio and siloteemu September 29, 2026 12:18

Addressed

@volen-silo
volen-silo force-pushed the fix/overstated-fix-applicability branch 2 times, most recently from 436a36a to 71544ea Compare September 30, 2026 06:19
@siloteemu

Copy link
Copy Markdown

🔴 Automated review · pr-review-watcher · 71544ea

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.

Summary

Replaces the flat auto_applicable bool on fix recipes with a per-platform FixClass (AUTO / NEEDS-ARG / PRINT-ONLY / DIAGNOSE-ONLY), derives diagnose's copy from the catalog in one place, and corrects the two entries the old bool was wrong about — the change is behaviourally sound, but it left three stale copies of the very claim it says it removed, so: Needs work. Verified: cargo test -p rocm-core --lib on an untouched copy — 419 passed, 0 failed (the full suite, the e2e suite and the Windows/GPU lanes were not run here); mutation testing on separate scratch copies confirmed both arms of the fix-2 platform split and both arms of fix-9 are individually detectable by the library tests, that the DIAGNOSE-ONLY arm's exit code 0 and its separation from the print-the-steps path are both pinned, and that the per-row listing marker is pinned only by the e2e lane; independently confirmed that the three pre-existing places the PR text cites do say what it claims (the fix-2 dry-run comment, the fix-9 print-only test name, and the e2e step comment noting fix-2 "never calls it on Linux" and that fix-9 "needs only --device-index, which the scenario supplies"), that @requires-bare-metal is a real tag honoured by the expectation filter, that the three strings the new e2e step asserts are absent all match text printed only after a write, and that fix-6-path really is the only entry the CLI carries out on WSL. Checks at review time: success=27, failure=2. I cannot attribute either red check to a defect in this diff. Blocking: 2 · Non-blocking: 5.

🚫 Blocking (must fix before merge)

  • crates/rocm-core/src/fix.rs:564, tests/e2e-cucumber/tests/e2e/diagnose_steps.rs:37, crates/rocm-core/src/diagnose.rs:3005 — the claim this change exists to delete survives in three places, two of them in files the PR rewrote. The contributor rules require grepping a behaviour claim's wording across every surface rather than only the one being edited, and the PR text states the count was removed "everywhere else", which is not the case.

    • fix.rs:564 still reads "none of that meets the bar the four auto-applicable fixes clear" — four lines below the PR's own corrected wording on PRINT_ON_WSL ("the bar an auto-applied fix has to clear") and saying the opposite of the corrected docs/wsl.md sentence. There is no set of four once applicability is per-platform. Fix: delete the comment block at 562–565, which PRINT_ON_WSL's new doc comment now supersedes verbatim.
    • diagnose_steps.rs:37 still reads "Of the four AUTO recipes this is the only one that reaches the confirmation gate", describing MUTATING_FIX_ID — which is fix-9-igpu-dgpu, the entry this PR reclassified out of AUTO entirely. Fix: reword to "Of the entries the CLI carries out, this is the only one …" and drop the count.
    • diagnose.rs:3005 names fix_9_igpu_dgpu_is_auto_applicable_on_linux, a test this PR renamed away, and its reasoning is invalidated by the same commit: it says fix-9's flags line prints "rocm fix can run it" under both the old and new render paths, whereas fix-9 now renders "needs --device-index before rocm fix will run it". Fix: point it at the new test name and restate the contrast, or drop the companion note.
  • crates/rocm-core/src/fix.rs:1789-1796 — the stated justification for shipping a DiagnoseOnly variant with no member is "adding a variant after the catalog manifest is published is a type change that raises its contract version" (repeated in the commit message). No such mechanism exists in this repository: there is no schema file, no version constant, no golden JSON fixture for the diagnose payload, and no emitted version field — the only "manifest" in the tree is the unrelated runtime manifest. This is the sole reason given for a variant that is never constructed outside tests and that README and rocm fix --help now advertise to users as a marker they may encounter, when no entry can produce it. Fix: state the real forward-compatibility concern — that rocm diagnose --json now serialises class, so a consumer deserialising it would reject a variant added later — or drop the variant until its first member arrives. Either way, add one clause to the README and --help wording noting that no catalog entry currently carries this marker, so the docs do not promise output the CLI cannot produce.

Non-blocking

  • crates/rocm-core/src/fix.rs:1952 — dry_run_never_mutates_and_returns_zero_for_auto_linux_fix keeps a name calling fix-2 on Linux an "auto linux fix" immediately after this PR reclassified it PRINT-ONLY, and asserts only the exit code despite the name promising "never mutates"; the gate change also now runs it on Windows, where the mutating path exists and still nothing observes the filesystem.
  • crates/rocm-core/src/diagnose.rs:2126-2136 — the reason given for keying on platform_family rather than os_family ("would look up every WSL recipe under the wrong platform and silently report them all as print-only") describes an outcome that cannot occur: every WSL recipe is print-only, and every checker reachable on WSL resolves to the same class under either key, so swapping them changes no output and no test can fail for it. Keep the guard, but say what it actually protects (bare-metal-only entries such as fix-4-render-group being read as AUTO if a checker's OS list ever widens).
  • crates/rocm-core/src/fix.rs:59-60 — FixClass serialises kebab-case, so rocm diagnose --json emits "needs-argument" while every human-facing surface says NEEDS-ARG; a consumer reading both sees two names for one class.
  • crates/rocm-core/src/fix.rs:1796 — "the Epic's scenario 10" is an internal planning reference a public reader cannot resolve; name the scenario's content instead.
  • crates/rocm-core/src/fix.rs:897 — replacing r.class_here().marker() with a hardcoded "AUTO" leaves all 419 library tests green; the per-row marker is pinned only by the e2e listing scenarios, so a lane that skips them proves nothing about it.

@siloteemu siloteemu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Automated review · pr-review-watcher · 71544ea

Change request filed by the automated review round at this commit. The full round, including non-blocking notes, is in the comment posted alongside it.

🚫 Blocking (must fix before merge)

  • crates/rocm-core/src/fix.rs:564, tests/e2e-cucumber/tests/e2e/diagnose_steps.rs:37, crates/rocm-core/src/diagnose.rs:3005 — the claim this change exists to delete survives in three places, two of them in files the PR rewrote. The contributor rules require grepping a behaviour claim's wording across every surface rather than only the one being edited, and the PR text states the count was removed "everywhere else", which is not the case.

    • fix.rs:564 still reads "none of that meets the bar the four auto-applicable fixes clear" — four lines below the PR's own corrected wording on PRINT_ON_WSL ("the bar an auto-applied fix has to clear") and saying the opposite of the corrected docs/wsl.md sentence. There is no set of four once applicability is per-platform. Fix: delete the comment block at 562–565, which PRINT_ON_WSL's new doc comment now supersedes verbatim.
    • diagnose_steps.rs:37 still reads "Of the four AUTO recipes this is the only one that reaches the confirmation gate", describing MUTATING_FIX_ID — which is fix-9-igpu-dgpu, the entry this PR reclassified out of AUTO entirely. Fix: reword to "Of the entries the CLI carries out, this is the only one …" and drop the count.
    • diagnose.rs:3005 names fix_9_igpu_dgpu_is_auto_applicable_on_linux, a test this PR renamed away, and its reasoning is invalidated by the same commit: it says fix-9's flags line prints "rocm fix can run it" under both the old and new render paths, whereas fix-9 now renders "needs --device-index before rocm fix will run it". Fix: point it at the new test name and restate the contrast, or drop the companion note.
  • crates/rocm-core/src/fix.rs:1789-1796 — the stated justification for shipping a DiagnoseOnly variant with no member is "adding a variant after the catalog manifest is published is a type change that raises its contract version" (repeated in the commit message). No such mechanism exists in this repository: there is no schema file, no version constant, no golden JSON fixture for the diagnose payload, and no emitted version field — the only "manifest" in the tree is the unrelated runtime manifest. This is the sole reason given for a variant that is never constructed outside tests and that README and rocm fix --help now advertise to users as a marker they may encounter, when no entry can produce it. Fix: state the real forward-compatibility concern — that rocm diagnose --json now serialises class, so a consumer deserialising it would reject a variant added later — or drop the variant until its first member arrives. Either way, add one clause to the README and --help wording noting that no catalog entry currently carries this marker, so the docs do not promise output the CLI cannot produce.

@volen-silo
volen-silo force-pushed the fix/overstated-fix-applicability branch from 71544ea to 7a45761 Compare October 1, 2026 13:14
@volen-silo
volen-silo dismissed siloteemu’s stale review October 2, 2026 06:26

Addressed. The three stale count claims are gone from fix.rs, diagnose_steps.rs and diagnose.rs, and the DiagnoseOnly rationale was replaced with the defaulting argument plus the README clause. Verified against the current head rather than the commit this review ran on.

@volen-silo
volen-silo force-pushed the fix/overstated-fix-applicability branch from 7a45761 to 7741445 Compare October 2, 2026 13:13

@juhovainio juhovainio left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and found a few things worth fixing before merge, left inline below.

The one that matters most is not visible in this diff at all: this branch forked before the skills/rocm-doctor/ contract landed on main, and the new NEEDS-ARG marker breaks it. The merge is clean in those files, so nothing here will warn you. The first signal would be a red skill-01 on main, reported misleadingly as "reference.md documents fix-9 which rocm fix doesn't offer".

The core change itself is right, and implemented end to end. fix-2 on Linux and fix-9 without an argument genuinely do stop claiming AUTO, and I confirmed run_unset_override_linux never writes, so the central factual claim behind the PR holds. A few other concerns I chased did not hold up: the #[serde(default)] class field has no production deserializer, every (checker, platform-family) pair maps onto its catalog applies_on so nothing silently degrades, current_os() correctly returns wsl, and main's exit-5-on-decline fix from #149 survives a correct 3-way merge.

Separately, several verification claims in the PR description do not match the diff. Worth correcting before someone relies on them.

"Pass --device-index N to persist the env var; without it, this fix only prints the rocminfo / hipInfo query so you can identify N.",
],
applies_on: LINUX_AND_WINDOWS,
applies_on: NEEDS_DEVICE_INDEX,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the one I'd fix first, and it will not show up in CI on this branch.

origin/main is not an ancestor of this branch (merge-base 9d261bd8, 12 commits behind). #149 landed skills/rocm-doctor/ and wired reference.md as live test data against rocm fix --list. Three concrete breaks, all on origin/main:

  • tests/e2e-cucumber/tests/e2e/skill_steps.rs:157-161 maps markers with "AUTO" => true, "PRINT-ONLY" => false, _ => continue. The new NEEDS-ARG row for fix-9 hits _ => continue and disappears from the parsed CLI map entirely.
  • skill_steps.rs:508 asserts documented.auto == offered.auto, which fails for fix-2: reference.md marks it yes for linux/windows/wsl, this PR makes it PRINT-ONLY on Linux and WSL.
  • skills/rocm-doctor/reference.md:52-54 still reads "Only four fixes are auto-applicable ... fix-2-unset-override, fix-4-render-group, fix-6-path, fix-9-igpu-dgpu". That is verbatim the overstatement this PR exists to delete, sitting in the document agents read.

The merge is clean in skills/** and skill_steps.rs (only fix.rs/diagnose.rs conflict), so there is no conflict marker to catch this.

One trap worth flagging: patching skill_steps.rs with "NEEDS-ARG" => continue turns skill-01 green while silently deleting fix-9's OS-scope coverage, because assert_same_auto_set and assert_same_os_scope both iterate the CLI map. Better to teach parse_fix_listing the NEEDS-ARG and DIAGNOSE-ONLY markers, then rewrite reference.md:52-54, the fix-2/fix-9 Auto-fix cells, and the "Two exceptions" prose at reference.md:63-76 to the per-platform story.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed, and fixed. The rebase surfaced exactly this: fix-9's new NEEDS-ARG marker was getting silently dropped by parse_fix_listing's _ => continue arm, which would have made skill-01 fail on main with the misleading "undocumented" message you called out rather than a marker mismatch.

Took the second route rather than the trap: parse_fix_listing and parse_reference_catalog now recognise all four markers (AUTO/NEEDS-ARG/PRINT-ONLY/DIAGNOSE-ONLY) via a shared normalise_marker, so an unrecognised word still drops a row (defensive against a future 5th marker) but none of the four current ones do. Remediation carries the marker word plus an optional (platform, marker) override for the one entry whose behaviour genuinely depends on more than the host (fix-2-unset-override: PRINT-ONLY on Linux/WSL, AUTO on Windows), and expected_marker(platform) folds in the CLI's own out-of-scope-means-PRINT-ONLY fallback so the comparison is correct on every lane (bare-metal Linux, Windows, WSL2), not just this one.

reference.md rewritten to match: the catalog table's marker column now spells the literal word rocm fix prints (not yes/no), fix-2's cell carries the Windows override explicitly, fix-9's cell is needs-arg, and the "auto-applicable" prose is now a per-host bullet list (linux/windows/wsl) that assert_same_auto_set parses and checks against the current host specifically, using e2e_cucumber::capability::host_capability() (same infra diagnose_steps.rs already uses).

Verified for real: ran cargo xtask e2e -- -n skill on this (WSL2) dev host -- all 6 scenarios pass, including skill-01/02/03 against the new per-host logic exercising the wsl branch concretely. Also added tests/skill_reference.rs::catalog_markers_use_the_cli_vocabulary, a plain cargo test (no built binary needed) that would have caught a stray yes/no cell immediately; proved it can fail by reverting fix-9's cell to yes and watching it go red with the exact message, then restored it.

# `fix-4-render-group` gates its own dry-run on host state ($USER,
# `usermod`/`sudo` on PATH), so unlike PREVIEW_FIX_ID its exit code is not
# guaranteed to be 0 even on Linux.
@id:diagnose-fix-preview-states-required-flags @requires-os:linux @requires-bare-metal

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things here.

Adding @requires-bare-metal narrows an existing scenario's coverage, and it is not mentioned in the PR description. The scenario title still ends "and that it's auto-applicable", which now reads oddly against the change.

The description's e2e claim also does not hold up. It says "the 3 failures are the @requires-bare-metal scenarios that cannot pass on a WSL2 dev host, unchanged from before this PR". But @requires-bare-metal on WSL resolves to Expectation::Skip, never a failure (tests/e2e-cucumber/src/expectation.rs:553-555), and bare_metal_skip_is_not_recorded_as_a_known_bug pins that it is not an xfail row. So those scenarios cannot be in a failure count, and whatever the 3 results actually were is still unexplained. "Unchanged from before this PR" is also false, since this PR adds the tag here and introduces diagnose-22 carrying it.

AGENTS.md:97-100 asks for gated scenarios to be named by @id: plus the lane that will exercise them. The description names neither @id:diagnose-fix-applicability-is-per-machine nor @id:diagnose-fix-needing-an-argument-says-so, and names no lane. The lanes do exist (docs/ci-hardware-testing.md:35-40), so this is a description gap, not dead coverage.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fixed.

The scope gap: retitled diagnose-20 to "...and that it's auto-applicable here" and will call out the @requires-bare-metal addition (on diagnose-20) plus its introduction on diagnose-22 explicitly in the PR description, with the @id:s and the lane per AGENTS.md -- it was a real gap, not mentioned before.

The e2e claim: re-ran properly this time. cargo xtask e2e -- -n diagnose does bypass tag-based skip resolution exactly as you'd expect from the commit message's own warning about -n -- I reproduced that directly: with -n diagnose, diagnose-20 and diagnose-22 run for real on this WSL2 host and fail (exit 3, "Running OS is: wsl"), not skip. Using -i diagnose.feature instead (which doesn't bypass filter_run's skip resolution) gives the real picture: 22 scenarios total, 16 run, 6 skip, 0 fail -- and platform.json confirms all 6 skips are @requires-bare-metal with reason "requires a bare-metal host; this one is WSL2", diagnose-20 and diagnose-22 among them. So your read is right on both counts: the 3-failures claim doesn't hold up (they're skips, and there were never only 3), and "unchanged from before this PR" is false since this PR is what added the tag to diagnose-20 and introduced diagnose-22 carrying it. Updating the PR description with this corrected evidence and the @id:/lane callout.

/// Defaulting to [`FixClass::PrintOnly`] rather than this one is
/// deliberate: a missing class should understate what the CLI will do, and
/// "there is no fix" is a stronger claim than "here are the steps".
DiagnoseOnly,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DiagnoseOnly has zero catalog members by design, and it costs a fair amount: a Plan::Unfixable arm, a Box::leak-ing synthetic unfixable_recipe() fixture, two dedicated tests plus a tripwire, a legend entry, an e2e legend assertion, and user-facing paragraphs in both README.md and --help.

The goal here is to stop overstating applicability, and Auto/NeedsArgument/PrintOnly already discharge that. I would drop the variant until a real member arrives. The serialization argument in the_catalog_has_no_diagnose_only_entry_yet is the only load-bearing reason, and it is thin for a field the repo only just added.

Related: Fix::class and Fix::needs are two new serialized JSON fields. The Risk section only mentions that auto_applicable flips, not that the published payload grows.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this as-is rather than removing the variant -- this was decided deliberately in an earlier review round (see the exchange with the first automated pass, which raised the same question about the empty variant and the provisional framing), and I don't think it's mine to re-decide unilaterally now.

For the record, the concrete reasoning that survived that round: rocm diagnose --json already serialises class, so a consumer deserialising that payload into a fixed enum today would reject a variant added later. Shipping the full set now means that forward-compat concern is something callers already have to tolerate, rather than becoming a breaking addition whenever the first DIAGNOSE-ONLY entry lands. I take your point that the cost (a Plan::Unfixable arm, the synthetic fixture, two tests plus a tripwire, a legend entry, user-facing prose in README/--help) is real and the "no member yet" framing undercuts it -- that's a fair tradeoff to question. Deferring to you on whether that's worth it; happy to pull the variant if you'd rather land it when the first member arrives.

Comment thread crates/rocm-core/src/diagnose.rs Outdated
/// not `os_family`. WSL reports an `os_family` of `linux` but is its own family
/// for catalog purposes, so reading `os_family` here would look up every WSL
/// recipe under the wrong platform and silently report them all as print-only.
fn take_applicability_from_the_catalog(matched: &mut [Diagnosis], os_family: &str) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter is named os_family, but the call site at line 2115 passes platform_family(e), and this function's own doc comment says "Keyed on the examined machine's platform family, not the running host and not os_family".

So the name contradicts both the caller and the doc directly above it. Worth renaming to platform_family.

out.push_str(
" AUTO = `rocm fix <id>` can carry it out; PRINT-ONLY = it prints the steps for you to run.\n",
);
out.push_str(" On this machine: AUTO = `rocm fix <id>` carries it out; NEEDS-ARG = it does once you supply an argument;\n");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This legend restates the marker vocabulary as free text rather than deriving it from marker(). That makes adding a class a scattered edit: marker(), this legend, format_flags, README.md, the Fix doc comment in apps/rocm/src/main.rs, and the e2e marker list in diagnose_steps.rs all have to move together.

Generating the legend by iterating the variants would collapse most of that.

Minor and unrelated, while you are in this file: deleting auto_applicable: false, from fix-17 (around line 522) glued the commands block comment's first line onto the end of the rationale string, so it now reads as a trailing comment on rationale with the rest of the block floating detached. rustfmt will not move it back.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point, and you're right it's out of scope here -- not touching the legend derivation or the broader "six places move together" problem in this PR. Filing it as a follow-up rather than expanding scope: list_recipes's legend (and the note-on-fix-9 duplication a similar pattern already caused once) would both be narrower if the marker's explanation lived next to FixClass::marker() and got iterated rather than restated as free text in six places.

Also noting the fix-17 comment/rationale-string glue you flagged while in that file -- will fix that as part of this same commit, thanks for catching it.

@volen-silo
volen-silo force-pushed the fix/overstated-fix-applicability branch from 7741445 to 7c845c8 Compare October 2, 2026 13:48
`auto_applicable` was a flat bool meaning "rocm fix <id> will carry this
out", and it was wrong for two entries:

- fix-2-unset-override on Linux. `run_unset_override_linux` takes no
  FixOptions and never writes: it reads the live override, scans the shell
  rc files, and reports where it is set. Only the Windows arm mutates, and
  WSL runs the Linux arm.
- fix-9-igpu-dgpu with no --device-index. Both arms print the query that
  identifies the discrete GPU and return without acting.

Both were marked auto-applicable, so a user -- and an agent reading the
same output -- was told a change was coming that never came, and got exit
0 to confirm it. The repo already knew: two test names and a step comment
say "print-only" for exactly these cases. Only the type disagreed.

Replace the bool with a per-platform class (AUTO, NEEDS-ARG, PRINT-ONLY,
DIAGNOSE-ONLY). Scope and class are held together because they are one
fact -- fix-2 applies on Linux as print-only and on Windows as auto, which
a flat flag could not say.

The class says what happens to the machine, not whether a runner runs, so
fix-2 keeps its Linux rc-file report instead of falling back to a generic
"copy the commands above".

diagnose no longer restates applicability per checker. It reads the class
off the catalog in one place, keyed on the examined machine's platform
family. The two copies had already drifted -- fix-9 was auto-applicable in
the catalog and not in the Linux arm of its own checker -- with nothing
comparing them.

Keyed on the family rather than os_family because WSL reports linux there
while being its own catalog family: reading os_family would look up every
WSL recipe under the wrong platform and report them all as print-only.
The seven WSL recipes carry the class directly, all print-only, and
fix-6-path is the only entry the CLI carries out on that platform.

DIAGNOSE-ONLY ships with no member. Reading all 24 entries found none
that qualifies: every one has a real fix, and the print-only ones are so
because carrying the fix out needs sudo, a reboot, a reinstall or a
download -- not because no fix exists. The class still ships now rather
than when a member turns up: `rocm diagnose --json` already serialises
`class`, and a consumer that deserialises that output into a fixed enum
today would reject a payload carrying a variant added later, so shipping
the full set from the start means that variant is already something
callers have to tolerate. README and `rocm fix --help` now say so
explicitly, so neither promises output the CLI cannot currently produce.

That left the branch unreachable from any test. Split the id lookup in
apply from what it does with the recipe, and the decision from the
messages, so the class gate can be driven with a recipe the catalog does
not contain. The decision is now an exhaustive match, which turns an arm
deleted here into a compile error rather than a silent fall-through --
Unfixable and PrintSteps both exit 0, so the exit code alone could not
tell them apart, and a disabled guard would have kept its own test green.

A tripwire test asserts no entry uses the class, so the first real member
fails it and says what to do next.

format_flags, which exists so rocm fix and rocm diagnose word the same
entry the same way, now takes the class instead of the bool. Three of the
four answers are "the CLI will not run it", for different reasons, and a
bool could only carry one of them. diagnose reads the argument name from
the catalog beside the class, so a needs-argument entry names --device-index
from either command rather than one saying "an argument".

docs/wsl.md said none of the WSL remedies meets the bar "the four
auto-applicable fixes" clear. There is no set of four once applicability
is per-platform, and leaving the count there would recreate on the one
user-facing page the wrong claim this change removes everywhere else. The
same stale "four auto-applicable" count and two other claims the class
rewrite invalidated survived uncaught in three more places: fix.rs's own
WSL-recipes comment (now redundant with PRINT_ON_WSL's corrected doc
comment, so dropped), diagnose_steps.rs's MUTATING_FIX_ID comment (still
said "of the four AUTO recipes" about an entry this PR reclassified to
NEEDS-ARG), and a companion-test comment in diagnose.rs naming a test this
PR renamed and a flags-line example fix-9 no longer renders. Reworded all
three to match current behaviour.

The shared-memory checker and all seven WSL checkers still hand-set
`auto_applicable: false,` in their own `Fix` literals instead of leaving
it at `Fix::default()`, so eight of the twenty-eight sites were still
restating what the catalog alone was supposed to decide. Converted the
remaining eight -- the catalog already overwrites the field regardless,
so this changes nothing a user or agent can observe -- and added a test
that fails if any checker's `Fix` literal sets `auto_applicable` again,
so `take_applicability_from_the_catalog` stays the only place that can,
instead of a checker being able to quietly disagree with it a second time
the way fix-9 once did.

Three surfaces still described the old two-value system after the class
landed, and one test could not fail.

The `rocm fix` help said fixes are marked AUTO or PRINT-ONLY, which is a
two-value description of something that now has four. fix-9's own note
ended "despite being marked AUTO" -- true of the flat flag, and precisely
the overstatement this change exists to remove.

The e2e step asserting the CLI reports no change checked that its output
does not contain "Applied". That string appears nowhere in the product,
so the assertion held against every possible regression. It now names
text the CLI prints only after it has acted, and deliberately not the
catalog's own plan, which includes a setx line this path legitimately
shows.

diagnose-20 (fix-preview-states-required-flags) asserted the Flags: line
`rocm fix fix-4-render-group --dry-run` prints, on the premise that
`print_recipe` runs before the fix's own platform gate so the text renders
identically on every lane. That held for the flat bool; it stopped holding
here, because the Flags: line now comes from `class_here()`, which looks up
the catalog entry for the *running* host's OS. fix-4-render-group is
`applies_on: AUTO_ON_LINUX` only, so bare-metal Linux renders "AUTO" and
every other host falls back to PRINT-ONLY -- the generic "does not apply
here" answer diagnose-11 already covers, not a second platform-specific
behaviour worth asserting under this scenario's name. Gated the scenario
`@requires-os:linux @requires-bare-metal`, matching the sibling scenarios
for this same fix-id (diagnose-08, -15, -16), and corrected the stale
comment. Verified against the Strix Halo WSL2 and Windows CI logs (both
failed on this exact assertion) and reproduced/fixed locally by running
the real cucumber harness (not the `-n` scenario filter, which bypasses
the tag-based skip resolution) against this repo's own WSL2 host.

This branch forked before `skills/rocm-doctor/` landed on main. Rebasing
onto current main surfaced the gap review caught: the skill's catalog table
and `rocm fix`'s own listing used to agree on a flat yes/no per id, and the
class rewrite breaks that for any id whose class is not the same on every
platform it applies to -- `fix-2-unset-override` (print-only on Linux/WSL,
auto on Windows) and `fix-9-igpu-dgpu` (reclassified from AUTO to NEEDS-ARG
outright). `skill_steps.rs`'s marker comparison is now host-aware: it reads
the catalog's base marker plus an optional per-platform override, derives
what `rocm fix` should report on the host the scenario is actually running
on (folding in the CLI's own out-of-scope-means-PRINT-ONLY fallback), and
compares that against the real listing instead of a flat bool. A silent trap
in the obvious fix -- mapping an unrecognised marker to "drop the row" would
have made fix-9 vanish from the comparison instead of failing on a mismatch --
is closed by recognising all four markers explicitly.
`skills/rocm-doctor/reference.md` gained the same per-host story in prose
(which platform's auto set is which) and in the catalog table (every cell
now spells the marker word the CLI prints, not a yes/no this change retired).
A new `tests/skill_reference.rs` guard, run in the ordinary `cargo test` set
with no built `rocm` binary needed, catches a cell still using the retired
vocabulary before the cucumber suite would.

Three smaller review corrections in the same spirit: `diagnose.rs`'s
`os_family` parameter renamed to `platform_family` to match both its own doc
comment and its call site, which both already said "family, not os_family";
the regression test comparing `diagnose`'s applicability against the catalog
now reads `fix::class_on` instead of a removed flat accessor, same claim,
current API; and diagnose-20's title now says "auto-applicable here" rather
than a bare "auto-applicable", matching the per-host story introduced above.

A trailing comment on fix-17's `rationale` string (explaining the
commands block below it) was glued to the end of that string by an earlier
edit that deleted the line between them, leaving the rest of the comment
floating detached from what it describes. Moved onto its own lines directly
above `commands:`, where rustfmt will keep it.

Signed-off-by: Eugene Volen <Eugene.Volen@amd.com>
@volen-silo
volen-silo force-pushed the fix/overstated-fix-applicability branch from 7c845c8 to e7f9b7f Compare October 2, 2026 13:53
@volen-silo

Copy link
Copy Markdown
Collaborator Author

Addressed this round's review (all 6 inline comments replied to individually):

Fixed (code):

  • The skill-contract break your fix.rs:394 comment flagged: skill_steps.rs's marker parsing now recognises all four FixClass markers (was silently dropping NEEDS-ARG), and the comparison is host-aware for fix-2-unset-override's genuinely per-platform behaviour. reference.md rewritten to match, plus a new plain-cargo test drift guard.
  • diagnose.feature:294: retitled diagnose-20, and corrected the PR description's e2e verification claim (it was wrong — -n diagnose bypasses skip resolution; -i diagnose.feature gives the real picture: skips, not failures).
  • diagnose.rs:2140: renamed the os_family parameter to platform_family.
  • The fix-17 rationale/comment glue you flagged in passing while reviewing fix.rs:905.

Replied only (no code change):

  • diagnose.rs:2142: checked directly against current code — no hand-set auto_applicable sites exist (verified with a grep, not by trusting the existing test). Disputed with evidence; happy to be pointed at a specific line.
  • fix.rs:87 (DiagnoseOnly): this was a deliberate call from an earlier round. Left it, restated the reasoning, and left the tradeoff open for you rather than re-deciding it myself.
  • fix.rs:905 (legend derivation): agreed it's out of scope here; filed as a follow-up rather than expanding this PR.

PR description's Verification section rewritten with the corrected e2e evidence and the @id:/lane callout AGENTS.md asks for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants