Repository navigation
rocm-dash-tui: untangle the scrollbar.rs/actions.rs cycle - #594
jussielo-amd wants to merge 7 commits into
Conversation
rominf
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · b379786
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 — no blocking findings
Full review of the whole change.
This PR covers Instance 2 of ROCMAI-483 (dash-tui scrollbar.rs ↔ actions.rs). Instance 1 (vllm process.rs ↔ state.rs) is left to #593, as the description says. The PR does not claim to close the ticket.
Blocking
None
Non-blocking
- The new
PaneFocusdoc comment gives a reason that is false —crates/rocm-dash-tui/src/app/types.rs:440-442(new)
The comment says the type is "mouse-set there too" (inscrollbar.rs). It also says it lives intypes.rsso that "scrollbar.rs's hit-testing can … depend on this type". Butscrollbar.rsdoes not mentionPaneFocusanywhere, at either the base or the head (grep: 0 hits other than the removed definition). The mouse wheel path inscrollbar.rsonly returnsKeyAction::Move.pane_focusis written only inactions.rs(68–119) andevent_loop.rs:1143. The code is right and the comment is wrong. The real reason is thatPaneFocuswas defined inscrollbar.rswithout being used there, soactions.rshad to import it fromscrollbar.rs. TheScrollTargetcomment attypes.rs:454-457is accurate, becausescrollbar.rsreally does useScrollTarget.
Confidence 85 · mechanical · new · Fix: say thatPaneFocuswas moved out ofscrollbar.rsbecause that file defined it but never used it, and the move removesactions.rs's only import fromscrollbar.rs. Drop "mouse-set there too". - The PR description and the commit message get the cycle's direction backwards — PR body, first bullet; commit
b379786, first paragraph
Both say "scrollbar.rs's mouse hit-testing importedPaneFocus/ScrollTargetfromactions.rs". The base tree shows the reverse. On the base,scrollbar.rs:228definesPaneFocus(andScrollTarget), andactions.rs:14isuse super::scrollbar::{PaneFocus, ScrollTarget};.scrollbar.rsimports onlyKeyAction,handle_mouse,tab_bar_hitandapply_actionfromactions.rs(lines 16–17). The base code governs here, and ROCMAI-483 describes the edges the same way the code does. The description of what the change does (move two types totypes.rs, leavescrollbar.rs→actions.rsas the only edge) is accurate, so this is a wrong account of the starting state, not a wrong scope. It still matters: the repo squash-merges, so this text is likely to end up in the permanent history.
Confidence 85 · mechanical · new · Fix: swap the two directions in the first sentence of both texts. - Two lists of what
types.rsholds now leave out the two moved types —crates/rocm-dash-tui/src/app/types.rs:5-8,docs/architecture.md:42
Both list whattypes.rscontains ("Focus,ResolvedArgs, connection/tab/chat/replay state,Modal,UpdateStatus, and the slash/plan/approval payload types"). Neither includes the pane-focus and scroll-target types this PR moves in. AGENTS.md §5 asks docs to be updated in the same change.
Confidence 70 · mechanical · new · Fix: add the two types to both lists, or reword the lists so they don't try to name every type.
Decisions for the author
None
Positive signals
- The
crate::app::{PaneFocus, ScrollTarget}re-exports are kept inapp/mod.rs. As a result,ui/mod.rs,ui/job_console.rsandui/tabs/instances.rscompile unchanged, and nothing outsideapp/sees the move. - Afterwards
actions.rsdoes not refer toscrollbar.rsat all (grep confirms).apply_scroll_grablives inmod.rs, notscrollbar.rs, so there is no hidden dependency through a method either. The cycle is actually gone at the module level, not just moved.
Deployment notes
None
What this covered
Every file in the change was read completely: actions.rs, event_loop.rs, mod.rs, scrollbar.rs and types.rs under crates/rocm-dash-tui/src/app/. Also checked: every reference to PaneFocus, ScrollTarget and scrollbar:: across crates/ and apps/, the base versions of scrollbar.rs and actions.rs, and docs/architecture.md. Commit range: 2023d76…b3797863 (one commit).
Verification was static only, because of disk constraints on the reviewing host. No cargo build, check, clippy or tests were run. Compile and test correctness rests on CI, which is green on b379786: build-and-test, windows-build-and-test, clippy, Test (affected crates), Coverage (rocm-dash crates), E2E tests and Commit signatures all passed. The self-hosted GPU E2E lanes, skillscope and Sphinx were skipped.
The diff adds and changes no tests, so there were no per-test verdicts to give. This is a pure type move with no change in behaviour, so no scenario is needed (AGENTS.md §3 exempts internal refactors).
What did not run:
- The diff is 44 lines, so the code review was a single pass rather than a fan-out.
- The agent-instruction, history and code-comment passes and the design questions ran in the same context, so they were not independent.
- The prior-changes pass did not run: no review comments from earlier PRs on these files were read.
The PR's discussion was not reconciled here.
|
Addressed all three non-blocking findings in aec0d01:
Left the already-pushed commit message's wording as-is rather than amending/force-pushing an open PR; the corrected PR description is what the squash-merge record should pick up. |
rominf
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · aec0d01
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.
Watcher note: no change request is filed on this round. The one finding below is about doc-comment wording. Merging it would leave an inaccurate rationale in a comment, and it would change no behaviour. The previous round rated the same class of finding non-blocking, so this round publishes as a comment. The finding is new this round. It is in the text the fix commit added.
Review — needs work
Full review of the whole change.
Covers instance 2 of ROCMAI-483 (the scrollbar.rs/actions.rs cycle in rocm-dash-tui). It does not cover instance 1 (the vllm process.rs/state.rs cycle); the description says that one is in #593.
Blocking
- (new) The new doc comments on
PaneFocusandScrollTargetmisdescribe the dependency structure this PR exists to fix —crates/rocm-dash-tui/src/app/types.rs:441-443,crates/rocm-dash-tui/src/app/types.rs:456-459ScrollTargetsays it lives intypes.rsso both modules can see it "without either depending on the other". That is false:scrollbar.rsstill depends onactions.rs(scrollbar.rs:17use super::actions::{KeyAction, handle_mouse, tab_bar_hit};, plusapply_actionundercfg(test)at:16). The PR description says the same thing: that edge "is now the only edge between the two modules".ScrollTargetalso says it lives here "for the same reason as [PaneFocus]". The reason given forPaneFocusis thatscrollbar.rs"defined this type but never used it".scrollbar.rsusesScrollTargetthroughout (:18,:23-38, theScrollDrag/ScrollbarHandlefields), so that reason does not carry over.PaneFocussays moving it "removesactions.rs's only import fromscrollbar.rs". At base, that import wasuse super::scrollbar::{PaneFocus, ScrollTarget};, so movingPaneFocusalone leaves it in place. It only disappears because both types moved.- The code governs here, since the
uselines are what the compiler acts on. These comments are the deliverable of the "fix stale docs" commit (aec0d01). They are also the only in-code statement of the new module boundary, so the next reader of a cycle-untangling change gets the wrong direction from them. - Confidence 85 · mechanical · Fix: say the shared home lets
actions.rsstop depending onscrollbar.rs, and thatscrollbar.rs→actions.rsremains the single edge. GiveScrollTargetits own reason (KeyAction::ScrollGrabcarries it). ForPaneFocus, drop the "only import" clause or say "together withScrollTarget".
Non-blocking
None
Decisions for the author
ScrollTargetnow lives apart fromScrollDragandScrollbarHandle, which embed it — tradeoff- For:
types.rsis already the home for shared pure enums, and puttingScrollTargetthere is the smallest move that breaks the cycle. - Against:
docs/architecture.mddescribesapp/as following full domain extraction. The scrollbar-domain type now sits away from the module that defines the scrollbar state carrying it. - Either is defensible. The ticket calls this "a real ownership/design decision", so confirm it was deliberate.
- For:
- Nothing prevents the cycle from coming back — non-blocking-improvement
- The ticket's failure scenario is "no compiler-enforced boundary".
cargo xtask check-crate-edgeschecks only edges between crates, and the compiler accepts cycles between modules, so the nextuse super::scrollbar::…inactions.rswould go through silently. - Options: a short guard test that greps
actions.rsforsuper::scrollbar, or an explicit "must not importscrollbar.rs" line inactions.rs's module doc, would make the boundary stick.
- The ticket's failure scenario is "no compiler-enforced boundary".
Positive signals
- Both types stay
puband still resolve through thecrate::app::re-export block (mod.rs:51-55). Every outside consumer (ui/*,tests/dash_characterization.rs) compiles unchanged, and the re-export rule from #476 holds. types.rs's module doc anddocs/architecture.mdwere updated in the same change, as AGENTS.md §5 asks.
Deployment notes
None
What this covered
- What was read:
- All 6 changed files in full (
app/{actions,event_loop,mod,scrollbar,types}.rs,docs/architecture.md), at a5e507a (merge-base withprw-base)…aec0d01c. - A repo-wide grep for every reference to
PaneFocus,ScrollTargetandscrollbar. - Base
scrollbar.rs, to check the "never usedPaneFocus" claim (true). - History and earlier-merged-PR passes (#476, #62, #92), run by an independent read-only worker.
- All 6 changed files in full (
- What was run locally:
cargo clippy -p rocm-dash-tui --all-targets -D warningsis clean, andcargo fmt --checkis clean.cargo test -p rocm-dash-tuipasses in full underHOME=/tmp/fakehome. Without that, 3agent::clientstests fail on a root-owned$HOMEin this container, a known environment problem unrelated to this change.
- CI: every check on aec0d01 is green. GPU E2E lanes and the skillscope/Sphinx checks were skipped by path filtering.
- What did not run:
- The code pass and the design questions (Step 7) ran in the driver context, not as independent workers. The change is a 6-file type move, so this was a single pass.
- Agent-instruction adherence was checked by the driver against AGENTS.md: no Gherkin scenario is needed for a pure refactor, and the description says why.
- No added-test verdicts, because the change adds no tests.
- The commit messages were seen during scope resolution, before Step 9.
- Not reconciled against any PR discussion here.
|
Addressed the blocking finding from the 10:38:56Z review, in 03b7698:
On the two "Decisions for the author" items from that same review:
|
scrollbar.rs's mouse hit-testing imported PaneFocus/ScrollTarget from actions.rs, while actions.rs's KeyAction dispatch imported them back from scrollbar.rs. "hit-testing geometry" vs. "key dispatch" read like a clean layer split, but the two modules formed a cycle. PaneFocus and ScrollTarget move to types.rs (already the home for every other shared type/enum this app/ split uses) alongside Focus, ActiveTab, Modal, etc. actions.rs and scrollbar.rs each now depend on types.rs for these two types instead of on each other for anything. scrollbar.rs's existing one-directional use of actions.rs (KeyAction, handle_mouse, tab_bar_hit) is untouched and remains the only edge between the two. Pure move, no behavior change: same variants, same derives, same call sites, same field types throughout AppState/KeyAction. ROCMAI-483 Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…es.rs The PaneFocus doc comment claimed it was still mouse-set in scrollbar.rs and that scrollbar.rs's hit-testing depends on it; neither is true — scrollbar.rs never referenced PaneFocus, so the move just drops actions.rs's only import from scrollbar.rs. Also add PaneFocus and ScrollTarget to the two lists of what types.rs holds (its own module doc comment and docs/architecture.md), which omitted both. ROCMAI-483 Signed-off-by: Jussi Elo <jussi.elo@amd.com>
… add cycle guard ScrollTarget's doc claimed neither module depends on the other, but scrollbar.rs still imports KeyAction/handle_mouse/tab_bar_hit from actions.rs by design — only actions.rs's dependency on scrollbar.rs was removed. ScrollTarget's "same reason as PaneFocus" was also wrong: scrollbar.rs does use ScrollTarget throughout, unlike PaneFocus. PaneFocus's doc overstated it alone as removing actions.rs's import; that only happened because ScrollTarget moved with it. Added a unit test asserting actions.rs never reintroduces an import from scrollbar.rs, since the compiler accepts a module-level cycle here and nothing else would catch it coming back. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
rominf
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 03b7698
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.
Watcher note: no change request is filed on this round. The one blocking-rated finding below is new: the guard test added in 03b7698 checks less than its name, assertion message and the PR description say. Merging leaves a guard that catches the super::scrollbar spelling and misses others. Base has no guard at all, and no runtime behaviour changes. So this round publishes it as a comment. The objection the previous round raised about the PaneFocus/ScrollTarget doc comments was standing. This round's blind review did not re-find it, and it was then put to the reviewer, which found that all three parts are fixed at 03b7698. It is dropped. Separately, GitHub currently reports this PR as conflicting with main (mergeable_state: dirty). It needs a rebase before it can merge.
Review — needs work
Full review of the whole change.
This PR does instance 2 of ROCMAI-483 (the scrollbar.rs/actions.rs cycle). Instance 1 (vllm process.rs/state.rs) is not in it; the description points to #593 for that. The PR does not claim to close the ticket.
Blocking
- (new) The new guard test is weaker than its name, comment and the PR description say —
crates/rocm-dash-tui/src/app/mod.rs:1246-1258- The test is named
actions_does_not_import_from_scrollbarand fails with "actions.rs must not import from scrollbar.rs". The PR description says it asserts thatactions.rs"never reintroduces an import fromscrollbar.rs". - What it actually checks is narrower: whether
actions.rscontains the substringsuper::scrollbar. - I added
use crate::app::scrollbar::ScrollDrag;toactions.rsand rancargo test -p rocm-dash-tui --lib actions_does_not_import_from_scrollbar. It passed (1 passed, exit 0). - A worker also confirmed that
use super::{scrollbar::FooterChip};anduse super::ScrollbarHandle;(through themod.rsre-export) both pass. All three bring the dependency onscrollbar.rsback. - The test comment says "nothing else catches it", so readers will take the dependency direction as protected when the common spellings are not covered.
- The needle can also false-positive: a later comment in
actions.rsthat mentionssuper::scrollbarwould fail the test. I found this by reading the needle, not by running it. - Confidence 100 · logic · Fix: either harden the check or narrow the claims. Hardening means a line-based scan of non-comment
uselines for thescrollbarpath segment, plus the namesScrollbarHandle,ScrollDrag,FooterChipandresolve_mouse. The repo already does a line-based scan like this inno_checker_hand_sets_auto_applicable(crates/rocm-core/src/diagnose.rs:2866). Narrowing means changing the test name, comment and description to say exactly what is checked.
- The test is named
Non-blocking
- (new) The first commit message describes the dependency backwards — commit
b379786- It says "scrollbar.rs's mouse hit-testing imported PaneFocus/ScrollTarget from actions.rs". On
prw-baseboth types were defined inscrollbar.rs, andscrollbar.rsnever usedPaneFocus. - It also says each module now depends on
types.rs"instead of on each other for anything", then a few lines later says thescrollbar.rs→actions.rsedge remains. - The two later commits mostly exist to correct the first one's docs.
- The repo squash-merges, so the fix is to write the squash message fresh rather than concatenating these three.
- Confidence 85 · mechanical · Fix: write an accurate squash commit message.
- It says "scrollbar.rs's mouse hit-testing imported PaneFocus/ScrollTarget from actions.rs". On
Decisions for the author
- Where the guard lives — tradeoff
- It sits in
app/mod.rs's tests, but the invariant belongs toactions.rs. - Putting it in
actions.rs's own test module, asdiagnose.rsdoes for its self-scan, keeps it next to the code it protects. - Keeping it in
mod.rskeeps the layering checks for theapp/split in one place.
- It sits in
- What "cycle removed" means here — non-blocking-improvement
- The direct
useedge is gone.actions.rsstill reachesscrollbar.rstypes indirectly throughAppState, whose fields areScrollbarHandle,ScrollDragandFooterChip(app/mod.rs:126,129,199). That is unavoidable whileAppStatelives inmod.rs. - Calling it a "one-way import rule" rather than "no cycle" would describe the guarantee more exactly.
- The direct
Positive signals
- The
crate::app::*re-exports are kept:PaneFocusandScrollTargetare re-exported fromtypesinapp/mod.rs. So every external user resolves unchanged:ui/dock.rs,ui/tabs/chat.rs,ui/tabs/instances.rsandtests/dash_characterization.rs. docs/architecture.mdand thetypes.rsmodule doc were updated in the same change.
Deployment notes
None
What this covered
- Read: every file in the change, completely:
app/{actions,event_loop,mod,scrollbar,types}.rsanddocs/architecture.md. Also every repo-wide reference toPaneFocusandScrollTarget, and the identifiers defined inscrollbar.rschecked againstactions.rs. Range:prw-base…03b76983. - Ran:
cargo check -p rocm-dash-tui --all-targets(exit 0).- The guard test against three mutations of
actions.rs. I re-ran one myself. - The leak scan over the diff (clean).
- A check of DCO sign-off and signatures on all three commits (present and good).
- CI on the head commit: every check that ran passed. The GPU E2E lanes, Sphinx and skillscope were skipped.
- Not run:
- A full workspace build or test. Only the
rocm-dash-tuicrate was compiled here; CI build/test lanes passed. - The mutation for the comment false-positive. It timed out in the worker, so that point rests on reading the needle.
- A full workspace build or test. Only the
- Process: fanned out as a code pass, a source-reading pass (instructions, history, prior changes, comments) and a design pass. All three ran independently.
- Discussion: not reconciled against the PR's discussion here.
03b7698 to
78da228
Compare
|
Rebased onto origin/main (78da228) to pick up #582's rewrite of docs/architecture.md into markdown-linked citations. One conflict, in the `rocm-dash-tui`/`rocm-dash-core`/... module-map entry: main's rewrite converted every file citation in that paragraph to a link, while this branch's `aec0d01c` had added `PaneFocus`/`ScrollTarget` to the `app/types.rs` type list in the pre-link prose. Resolved by keeping main's link style and folding the two type names into it. `cargo test -p rocm-dash-tui --all-targets`, `cargo clippy -p rocm-dash-tui --all-targets -- -D warnings`, and `cargo fmt -p rocm-dash-tui --check` all pass clean on the rebased head. |
rominf
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 78da228
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.
Watcher note: no change request is filed on this round. The one blocking-rated finding below is standing. The previous round (at 03b7698) raised the same guard-test gap and published it as a comment, not a gate. This round re-found it blind, at the same location and with the same mutation result. Merging still leaves the same thing: the production change is correct, and the guard catches the direct super::scrollbar spelling and misses re-exported or brace-grouped spellings. No runtime behaviour is at stake, so it stays non-gating. The commit-message finding is also standing. The other two findings and the decision item are new. The conflict with main reported last round is gone.
Review — needs work
Full review of the whole change.
The description matches the diff. ROCMAI-483 is named as a bare ID and was not retrieved: no tracker tool was available here. The description says this PR is one of two halves of ROCMAI-483; the other half is #593.
Blocking
-
(standing) The new guard test does not cover what its comment and the description promise —
crates/rocm-dash-tui/src/app/mod.rs:1246-1258
The test comment and the PR's test plan both say the test asserts thatactions.rs"never reintroduces an import fromscrollbar.rs". It does not. The test is a raw substring search forsuper::scrollbar, so any other spelling of the same dependency passes it.- Confirmed by running it: I added
use super::ScrollbarHandle;toactions.rsand rancargo test -p rocm-dash-tui --lib actions_does_not_import_from_scrollbar. It reported 1 passed, exit 0.ScrollbarHandle,ScrollDragandFooterChipare all defined inscrollbar.rsand re-exported fromapp/mod.rs:51. - Also confirmed by a worker, with the same result:
use crate::app::scrollbar::resolve_mouse,use super::{scrollbar::ScrollDrag}anduse super::{scrollbar, AppState}all compile and all pass the test. - The re-exported path is the likeliest way the cycle comes back. Whoever next needs a scroll type in
actions.rswill naturally writesuper::ScrollbarHandle. - The search also scans comments and
actions.rs's own test module, so a harmless comment can fail it. - The test is still worth having: reverting the production change puts back
use super::scrollbar::{PaneFocus, ScrollTarget}, which the test does catch. The problem is that the comment claims coverage of the whole class of imports, which means the next reviewer will stop looking.
Confidence 100 · logic · Fix: either reject every route —
super::scrollbar,app::scrollbar,{scrollbar, and the namesmod.rsre-exports fromscrollbar— and match only onuselines, or narrow the comment and the PR text to "guards the directsuper::scrollbarspelling". - Confirmed by running it: I added
Non-blocking
-
(new) The test comment points at a file and a split that don't exist —
crates/rocm-dash-tui/src/app/mod.rs:1249-1250
The comment refers to "the module cycle this file's split from scrollbar.rs exists to remove". The comment sits inmod.rs, which was never split fromscrollbar.rs. Bothactions.rsandscrollbar.rswere split out ofapp/mod.rsin b1cbc19 (#476), and that split is what created the cycle. What removes the cycle is this PR moving the two types intotypes.rs. The wording looks carried over from a version of the test that lived inactions.rs.
Confidence 85 · mechanical · Fix: say the cycle is removed by movingPaneFocus/ScrollTargetintotypes.rs. -
(new) The
concat()obfuscation does nothing —crates/rocm-dash-tui/src/app/mod.rs:1253
["super", "::", "scrollbar"].concat()only matters when a test scans its own file. This test lives inmod.rsand scansactions.rs. The trick doesn't keep the string out of greps either, because the comment atmod.rs:1249containsuse super::scrollbar::...verbatim. The repo's one precedent iscrates/rocm-core/src/diagnose.rsno_checker_hand_sets_auto_applicable, and that test does scan its own file.
Confidence 85 · mechanical · Fix: use a plain literal, or move the test intoactions.rs's test module, where the trick is actually needed. -
(standing) The first commit's message is false, and the next two commits correct it — commits d321d02, 5f43d40, 78da228
- d321d02 says
scrollbar.rs"imported PaneFocus/ScrollTarget from actions.rs". Atprw-base, both enums are defined inscrollbar.rs, andscrollbar.rsnever imports them. - The same commit says both modules "now depend on types.rs for these two types".
scrollbar.rsimports onlyScrollTarget. - 5f43d40 and 78da228 mostly fix their predecessor's wording.
The repo squash-merges. If the squash body is built from the commit list, it will contradict itself.
Confidence 85 · mechanical · Fix: use the PR description, which is accurate, as the squash message, or squash and reword before merge. - d321d02 says
Decisions for the author
- (new) The new
types.rsrustdoc explains where the types used to live — non-blocking-improvement
ThePaneFocusandScrollTargetdocs attypes.rs:441-443andtypes.rs:456-460explain why each type "lives here, not inscrollbar.rs". That explains the dependency rule, which is useful. It also narrates a past move, which goes stale once nobody remembers the old location. One option is to keep the dependency rule ("visible toactions.rswithout depending onscrollbar.rs") and drop the history.
Positive signals
- Moving the two types into
types.rs, which already holds every other shared app enum, breaks the cycle without adding a new module.crate::app::{PaneFocus, ScrollTarget}still resolves through thetypesre-export, so none of the consumers inui/ortests/dash_characterization.rshad to change.
Deployment notes
None
What this covered
- Read: all six changed files in full. Also every user of
PaneFocus/ScrollTargetacross the repo, theapp/re-export block, andxtask/src/crate_edges.rs, which only checks crate-level edges and so has no module-level check this test duplicates. Diff range: db11e47…78da2287. - Runs: the new test, plus a re-export-spelling mutation. A worker also ran clippy on
rocm-dash-tui(--all-targets -D warnings): clean. CI for 78da228 is all success; the GPU and E2E self-hosted lanes, skillscope and Sphinx were skipped. - Passes: coupled code group, agent-instruction adherence, history, code comments, and design review. The design review ran inline rather than through separate workers because the change is so small. The prior-changes pass did not run, because reading earlier review comments is out of scope for this watcher.
- Ticket: ROCMAI-483 was not retrieved.
- Discussion: not reconciled against any discussion here.
The guard test added in 03b7698 only rejected the literal substring `super::scrollbar`. Review on 78da228 showed three other ways to bring the same dependency back that the test let through: a re-exported-name import (`use super::ScrollbarHandle;`), a full-path import (`use crate::app::scrollbar::resolve_mouse;`), and a brace-grouped import (`use super::{scrollbar::ScrollDrag};`) — all three compile and pass the old test. Hardened the check to scan actions.rs's non-comment `use` lines for the `scrollbar` module name and the three names app/mod.rs re-exports from it (`ScrollbarHandle`, `ScrollDrag`, `FooterChip`), the way `no_checker_hand_sets_auto_applicable` (rocm-core/src/diagnose.rs) scans non-comment lines for a different unenforced invariant. Verified against the reviewer's three mutations plus the original violation. Also fixed the test's own comment, which claimed the cycle was removed by "this file's split from scrollbar.rs" — mod.rs was never split from scrollbar.rs; the cycle is removed by moving PaneFocus/ScrollTarget into types.rs. And dropped the `["super", "::", "scrollbar"].concat()` obfuscation: it only matters for a test scanning its own source, and this one scans actions.rs instead. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
|
Reply to the review at Blocking — guard test weaker than its name/comment/description claim. Confirmed: the old test only matched the literal substring Non-blocking (new) — test comment pointed at a nonexistent file/split. Fixed: it no longer says "this file's split from scrollbar.rs" ( Non-blocking (new) — Non-blocking (standing) — first commit message describes the dependency backwards. Already addressed in the reply on the 11:01:29Z round: leaving the already-pushed commit wording as-is rather than rewriting history on an open PR, since the repo squash-merges and the accurate PR description is what should seed that squash message. Decision for the author — rustdoc narrates history alongside the current invariant. Keeping the current form: the "used to live in scrollbar.rs" context is what makes the dependency rule's why legible to a future reader, and it's a doc comment on a small, stable type rather than documentation that has to track the codebase's evolving layout — a low cost if it ever goes stale, and easy to trim then.
|
rominf
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 4c3bf93
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.
Watcher note: no change request is filed on this round. The one blocking-rated finding below is standing in narrowed form. The four spellings the 78da228 round cited now fail the test, and the comment false-positive is gone. That earlier wording was settled by putting it, with the author's reply, to the reviewer after its blind report was frozen, and the reviewer re-ran all four mutations. That is anchored evidence, not a blind re-find. The remaining gap was re-found blind: a rustfmt-wrapped multi-line use group, pub(crate) use, and inline paths all still pass the guard. Merging leaves the same thing as last round: correct production code, and a guard that claims more than it checks. No runtime behaviour is at stake, so the finding stays non-gating, as it was rated before. The commit-message finding and the types.rs history-in-docs point are standing. The author's reply on both was read; the blind review reached them again independently, and they remain non-blocking. Everything else is new.
Review — needs work
Full review of the whole change.
Implements the rocm-dash-tui half of ROCMAI-483; the description says the engines/vllm half is in #593. The ticket was named but could not be retrieved from here.
Blocking
-
(standing, narrowed) The guard test's comment and the PR description say it catches more than it does —
crates/rocm-dash-tui/src/app/mod.rs:1246-1272
The test only fails when a single line whose trimmed text starts withusecontains one of the four names. Its comment says it catches anyusethat names the scrollbar module "directly, throughcrate::app::scrollbar, or by one of the names app/mod.rs re-exports", and it concludes "nothing else catches it". The description says the test asserts that actions.rs "never reintroduces a dependency onscrollbar.rs".
I mutatedactions.rsand rancargo test -p rocm-dash-tui --lib actions_does_not_import_from_scrollbarafter each change. The test ran every time (1 passed, 821 filtered out) and stayed green for all of these:- A multi-line group:
use super::{\n AppState, ScrollDrag,\n};. This is the one most likely to happen, because rustfmt wraps any longuse super::{…}group this way, and that is the import styleactions.rsalready uses. - A re-export:
pub(crate) use super::scrollbar::ScrollDrag;. - Inline paths with no
useline:super::scrollbar::resolve_mouse(me, s), or&crate::app::ScrollbarHandlein a signature.
It also gives a false positive:
use crate::ui::panel::vertical_scrollbar;fails the test, because it contains the bare substringscrollbar.Reverting the change does make the test fail, so it does test the change. The problem is that its comment claims cases it cannot fail on.
Confidence 100 · logic · Fix: either harden the test or narrow the claim.- Harden: join each
usestatement up to its;before matching, acceptpubandpub(crate) use, and match on the path (scrollbar::) or on word boundaries rather than a bare substring. Scan every non-comment line, not onlyuselines. - Narrow: change the comment and the description to say exactly what the test covers.
- A multi-line group:
Non-blocking
-
(new) The docs say the cycle is gone, but the change only removes the direct import —
crates/rocm-dash-tui/src/app/types.rs:456-460,crates/rocm-dash-tui/src/app/mod.rs:1250-1253, PR description
actions.rsstill works onAppState, which holds three types defined inscrollbar.rs:scroll_drag: Option<ScrollDrag>(mod.rs:129)scrollbars: RefCell<Vec<ScrollbarHandle>>(mod.rs:126)last_footer_chips: Vec<FooterChip>(mod.rs:199)
actions.rs:273writesstate.scroll_drag = None, and a mutation that read all three fields insideactions.rspassed the guard.The code governs here. This PR removes
actions.rs'suseofscrollbar.rs, not every dependency, so "the one edge this module boundary keeps" and "now the only edge between the two modules" overstate it. Breaking the cycle completely would be real work, becauseFooterChipcarries aKeyAction.
Confidence 70 · architectural · Fix: say the PR "removesactions.rs's direct import ofscrollbar.rs", or also moveScrollDragintotypes.rs. -
(standing, extended) Some commit bodies are false, and with a squash-merge they would land on main — commits
d321d02,4c3bf93d321d02says "scrollbar.rs's mouse hit-testing imported PaneFocus/ScrollTarget from actions.rs". Atprw-base, both types were defined inscrollbar.rs, andactions.rsimported them from there.- (new)
4c3bf93cites "The guard test added in 03b7698", butgit cat-filereports no such object. The test was added in78da228. The same commit body also reads as a reply to a review round.
Three of the four commits fix up the PR's own docs and test.
Confidence 85 · mechanical · Fix: when squashing, reduce the squash body to one accurate message instead of concatenating all four. -
(standing) The new type docs explain the move, not the type —
crates/rocm-dash-tui/src/app/types.rs:441-443,456-460
Text like "scrollbar.rsdefined this type but never used it. Moving it out…" will read as stale history once this lands. That belongs in the commit message.
Confidence 70 · mechanical · Fix: keep only what the type is and why it lives intypes.rs.
Decisions for the author
-
(new) Guarding a module boundary by scanning source text — tradeoff
Inside one crate, the compiler cannot forbid a sibling module'suse, so a source scan is the only cheap guard available.- For it: it costs nothing to run and documents the intent.
- Against it: no line-based scan can be complete (see the blocking finding), and a guard believed to be complete stops people looking.
The options are a scan that understands whole statements, a scan documented as best-effort, or dropping the guard and relying on the module docs plus review.
Positive signals
- The re-exports in
app/mod.rsmoved fromscrollbartotypes, so everycrate::app::PaneFocusandcrate::app::ScrollTargetpath inui/andtests/dash_characterization.rsstill resolves unchanged.
Deployment notes
None
What this covered
- Read: every changed file completely (
app/{actions,event_loop,mod,scrollbar,types}.rsanddocs/architecture.md), plus every consumer ofPaneFocus,ScrollTarget,ScrollbarHandle,ScrollDragandFooterChipacrossrocm-dash-tui(ui/,tests/). Range:efcd4800…4c3bf93b. - Runs:
- Tests: the
rocm-dash-tuilib tests had 815 passed and 3 failed. The 3 failures areagent::clientstests that hit a sandbox token-cache-dir permission error, unrelated to this change. The integration test targets passed. - Clippy:
clippy -D warningsis clean. - Mutations: the guard-test mutations described above.
- CI at
4c3bf93b: all green, but the GPU and self-hosted E2E lanes, skillscope and Sphinx were skipped.
- Tests: the
- Not run:
- Ticket ROCMAI-483 could not be retrieved, because no tracker tool is available here.
- The prior-changes pass ran without reading this PR's own review threads, by design.
- Discussion: the review itself is not reconciled against the PR's discussion. The standing-objection check described in the watcher note is the only part that read it.
Review feedback (posted after 4c3bf93) found the previous hardening still missed a rustfmt-wrapped multi-line `use super::{...}` group, a `pub(crate) use` re-export, and an inline fully-qualified path with no `use` statement at all — plus a false positive on an unrelated identifier containing the substring "scrollbar" (`vertical_scrollbar`). Fixed by joining the source into whole statements (split on `;`) before matching, accepting `pub`/`pub(crate) use` prefixes, and matching whole identifier tokens instead of bare substrings. The test's own comment is narrowed to say honestly what it doesn't catch: a fully-qualified path referenced inline with no `use` statement at all, which needs real parsing rather than a source scan — the test's accepted scope limit. Also fixed types.rs's ScrollTarget doc comment, which overclaimed the scrollbar.rs -> actions.rs use edge as "the one edge this module boundary keeps": narrowed to "the one direct use-level edge", since actions.rs still reaches ScrollDrag/ScrollbarHandle/FooterChip indirectly through the fields they type on AppState (defined in mod.rs) without ever needing to import them. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
A fresh review found that an attribute-prefixed `use` (e.g.
`#[cfg(test)] use super::scrollbar::...`) still slipped past
`actions_does_not_import_from_scrollbar`: `is_use_statement` checked
`starts_with("use ")` on the whole statement, but an attributed import's
`;`-delimited segment starts with the attribute token instead. Confirmed
by execution with a mutation, and not hypothetical -- scrollbar.rs
already gates one of its own actions.rs imports this way
(`#[cfg(test)] use super::actions::apply_action;`).
Fixed by stripping any leading `#[...]` attribute(s) before the `use`
check. Verified against all of: the cfg(test)-gated case, the
rustfmt-wrapped multi-line group, the pub(crate) re-export, and the
vertical_scrollbar false positive -- all behave correctly when the
mutation is inserted at a realistic, semicolon-bounded position in the
file (appending raw text past the file's closing braces, as an earlier
verification pass in this same round did, produces a misleading result,
since it merges unrelated code into one `;`-delimited segment).
Also named the `apply_action` edge (test-only) in types.rs's
`ScrollTarget` doc and this test's own comment, where both previously
listed only three of the four imports scrollbar.rs draws from
actions.rs.
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
A fresh review found the guard test's `;`-split approach still had an undisclosed hole: a `use` statement that isn't itself preceded by a semicolon -- e.g. the first statement in a function body -- gets merged into whatever unrelated code sits before it (bounded only by the last real `;` in the file), and the merged chunk no longer starts with "use", so detection silently never runs on it. The same review also pointed out the test had no positive control: it only ever asserted the absence of offenders over clean code, so this and every other hole in the detector were invisible to the test itself. Replaced the whole-file `;`-split with a direct keyword scan: `use` has no other syntactic role in Rust, so every whole-word `use` outside a comment is a `use` item. The test now finds each one by keyword and reads forward, brace-depth aware, to its own terminating top-level `;`. This covers a `use` in any position -- top-level or function-local -- uniformly with every form already handled (attribute-gated, pub/ pub(crate), brace-grouped, multi-line), and is simpler than the attribute/pub-stripping it replaces, since what precedes the `use` keyword no longer matters. Added a positive-control assertion using the exact case the old `;`-split version missed, re-verified against all five mutations tried across this PR's review rounds (cfg(test)-gated, function-local, multi-line brace-group, pub(crate), and the vertical_scrollbar false positive) -- all five now behave correctly. Also fixed a doc overstatement: types.rs's ScrollTarget doc (and the matching PR description bullet) said actions.rs reaches ScrollDrag, ScrollbarHandle, and FooterChip indirectly through AppState's fields. actions.rs only ever touches scroll_drag (ScrollDrag); it never references the ScrollbarHandle- or FooterChip-typed fields. Narrowed to name only the one it actually reaches. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
|
Reply to the review at Blocking — guard test weaker than its comment/description claim. Confirmed and fixed across three rounds, each closing a gap the previous one missed:
The test's comment is honest about what's left uncovered: a fully-qualified path referenced inline with no Non-blocking (new) — test comment pointed at a nonexistent file/split. Fixed in Non-blocking (new) — Non-blocking (new) — doc comment overclaimed the module boundary. Standing — commit-message findings (first commit backwards; Standing — rustdoc narrates history alongside the current invariant. Kept as-is: the "used to live in scrollbar.rs" context is what makes the dependency rule's why legible to a future reader, and it's a doc comment on a small, stable type rather than documentation that must track the codebase's evolving layout. Decision for the author — guarding via source-text scanning. Committed to hardening the scan properly rather than replacing it with a structural/AST-based check or dropping it: the detector now covers every
|
|
review-coverage · 2fbe9be Full-scope review of the whole PR diff (merge-base |
rominf
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 2fbe9be
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.
Watcher note: no change request is filed on this round. This was a full blind review of the whole change. The one blocking-rated finding below is the same class as the standing one from the 4c3bf93 round: the guard test claims more coverage than it has. The spellings that round cited are now handled or listed as known gaps, and this round found a new gap blind (glob imports). Merging still leaves correct production code and a guard that claims more than it checks. No runtime behaviour is at stake, so it stays non-gating, as rated before. The commit-series and the history-in-docs points are standing, and so is the "cycle is gone" overclaim (now at mod.rs). Everything else is new.
Review — needs work
Full review of the whole change.
Implements instance 2 of ROCMAI-483 (the dash-tui scrollbar.rs↔actions.rs cycle), not instance 1 (the vllm process.rs↔state.rs cycle, which the description says is in #593). The PR does not claim to close the ticket.
Blocking
- (standing class, new instance) The guard test says it catches a
use"in any position or form", but a glob import gets past it —crates/rocm-dash-tui/src/app/mod.rs:1250-1280(test comment, and the known-gaps list that leaves globs out),mod.rs:1330(offenders_infilter), themod.rsassertion message ("directly or through app/mod.rs's re-exports"), and the PR description's Test plan.- What I ran: I added
use super::*;plusfn _glob_probe(h: ScrollbarHandle) -> ScrollbarHandle { h }toactions.rs. It compiles, andactions_does_not_import_from_scrollbarstill passes: 1 passed, 821 filtered out, EXIT=0. - A worker got the same result with
use crate::app::*;, and withuse super::{self as app};followed byapp::scrollbar::…. - The claimed coverage is what governs here, because it is what the comment, the assertion message and the description all promise readers. The scanner only matches tokens written out literally, and a glob names none of them.
- Why it blocks: a check that claims coverage it lacks stops the next reviewer from looking.
- Confidence 100 · logic · Fix: also flag any
useinactions.rsthat globs the parent module (super::*,crate::app::*), or switch to the token scan described under Decisions. In either case, list every remaining gap in the comment and the description, or narrow both claims to what the scanner actually catches.
- What I ran: I added
Non-blocking
- (new) The positive control does not cover the re-export names —
mod.rs:1279-1282,mod.rs:1336-1345.- I replaced
"ScrollbarHandle", "ScrollDrag", "FooterChip"inSCROLLBAR_NAMESwith dummy names and the test stayed green (EXIT=0, 1 passed). - The list is also a hand-copy of
pub use scrollbar::{FooterChip, ScrollDrag, ScrollbarHandle}atmod.rs:51. A future re-export fromscrollbar.rswould not be guarded. - Confidence 100 · logic · Fix: add a control case that uses a re-exported name, and consider deriving the list from
include_str!("mod.rs").
- I replaced
- (new) Brace-depth tracking adds nothing for real
useitems, and it silently drops any statement whose;it never finds —mod.rs:1305-1324.- A
usetree cannot contain;. A worker removed the depth tracking and every case stayed green, including the multi-line and known-bad controls. - Its only effect is the
if let Some(end) = endbranch, which discards an item without failing.use super::scrollbar::{resolve_mouse /* { */};compiles and passes the guard (worker run, EXIT=0). That input is contrived. - The comment's justification ("so a brace-grouped
use super::{ ... }is captured whole") is wrong. - Confidence 85 · logic · Fix: drop the depth tracking, or fail when no terminator is found.
- A
- (new) "
useis a reserved keyword with no other syntactic role in Rust" is false —mod.rs:1257-1259and the PR description.- On edition 2024 (
Cargo.toml:24), precise-capturing bounds (impl Iterator<Item = &'a u8> + use<'a>) compile. A worker added one toactions.rs: it compiled, and the detector took it for auseitem. - The error can only cause false positives, never false negatives.
- Confidence 100 · mechanical · Fix: correct the sentence.
- On edition 2024 (
- (standing, extended) Comments describe this PR's own history, which will be stale once it merges —
mod.rs:1263-1268and1337-1340("an earlier version of this test", in both places),types.rs:441-443,types.rs:456-467.- The "earlier version" exists only in this branch's intermediate commits, and rocm-cli squash-merges, so it will never exist on main.
- The
ScrollTargetrustdoc spends most of its length onScrollDrag/ScrollbarHandle/FooterChipcoupling that is unrelated to the type. - Its phrase "the
scroll_dragfield it types onAppState" reads as ifactions.rsdeclares the field type. The field is declared atmod.rs:129. - Confidence 85 · mechanical · Fix: say what the code does now, and move the rationale to the test's doc comment.
- (standing) The test comment says the move removes "the module cycle", but a cycle through
mod.rsremains —mod.rs:1253-1255.- The remaining cycle:
actions.rs→AppState::apply_scroll_graband thescroll_dragfield (mod.rs:526,actions.rs:271-273) →scrollbar.rstypes onAppState(mod.rs:126,129,199) →scrollbar.rsimportsactions.rs. - The code governs here, and the
ScrollTargetrustdoc already words this correctly ("directuse-level edge"). - Confidence 70 · mechanical · Fix: say "direct
useedge" in the test comment as well.
- The remaining cycle:
- (standing) The commit series is a trail of review-round fix-ups, and their messages cite SHAs that will not exist after merge — five of the seven commits ("harden", "close the remaining gaps", "catch an attribute-prefixed use", …).
- The squash merge flattens them, but the default squash body would carry those messages.
- Confidence 70 · mechanical · Fix: write the squash message by hand when merging.
Decisions for the author
- Scan comment-stripped
actions.rsfor whole tokens instead of parsinguseitems — non-blocking-improvement.- A whole-token scan of
actions.rsat HEAD, with comments stripped, forscrollbar|ScrollbarHandle|ScrollDrag|FooterChipfinds 0 hits today (I ran it). - It would also catch the inline fully-qualified path that the comment calls an accepted limit "that would need real parsing". An earlier commit in this series (78da228) checked a broader substring before the check was narrowed to
useitems. - It would remove about 40 lines of keyword and brace scanning. It still needs the glob check from the blocking finding.
- A whole-token scan of
- Where the guard test lives — tradeoff.
- It sits in
app/mod.rstests but readsactions.rs. The repo's one comparable test,no_checker_hand_sets_auto_applicableincrates/rocm-core/src/diagnose.rs, scans its own file, and #476 placed tests by what they exercise. - Keeping it in
mod.rsputs it next to the module tree it describes. Placing it inactions.rsfollows the precedent. Either is defensible.
- It sits in
- Ticket framing — tradeoff.
- ROCMAI-483 says untangling the cycle is "a real ownership/design decision, not a mechanical move". This PR resolves it by moving the two shared types to
types.rs. - That is a reasonable ownership call, since
types.rsalready holds every other pure type in the split. Confirm it is the decision the ticket wanted, rather than a split of responsibilities betweenactions.rsandscrollbar.rs.
- ROCMAI-483 says untangling the cycle is "a real ownership/design decision, not a mechanical move". This PR resolves it by moving the two shared types to
Positive signals
- The re-exports at
mod.rs:51-55keep everycrate::app::PaneFocus/ScrollTargetpath working. Clippy--all-targetspasses over every in-crate caller, includingtests/dash_characterization.rsandui/tabs/pane.rs. docs/architecture.mdand thetypes.rsmodule doc were updated in the same change. A repo-wide grep finds no remaining stale "lives inscrollbar.rs" claim.- The guard test includes a positive control on the detector itself, which is the right instinct for a source-scan test.
Deployment notes
None
What this covered
- What was read:
- All six changed files, against
prw-basec1c2aeb…2fbe9be2. That is the full diff plus the completeactions.rs,scrollbar.rsandtypes.rs, andmod.rslines 1–1360. mod.rs1360–3428 (unchanged existing tests) andevent_loop.rsbeyond its one changed import were checked by grep and compilation, not read line by line.- The PR description, and ROCMAI-483 retrieved by its identifier (title, body and status only).
- All six changed files, against
- What was run:
cargo test -p rocm-dash-tui --lib app::: 228 passed.cargo clippy -p rocm-dash-tui --all-targets -- -D warnings: clean.- 9 mutations of
actions.rsand 5 of the detector. The glob and re-export-name mutations were re-run by the driver. - The leak scan of the diff and commit messages was clean.
- CI at 2fbe9be: all checks succeeded. The GPU E2E lanes and skillscope were skipped.
- Verdicts on the added test:
- (1) With the production change reverted, the test fails: re-adding
use super::scrollbar::…toactions.rsgives EXIT=101. - (2) The production change has no branches. Inside the detector, the word-boundary, depth-tracking, comment-stripping and re-export-name branches can each be broken alone with the test still green.
- (1) With the production change reverted, the test fails: re-adding
- Passes:
- The code, agent-instruction, code-comment, history and prior-changes passes ran as three independent workers.
- Prior changes means review comments on #476 and #382 (source of the comparable
diagnose.rstest) and the source of #337's xtask scan. - The Step 7 design questions (guard mechanism, remaining cycle, test placement) were answered by the driver from the workers' evidence rather than by separate workers.
- No pass was skipped.
- Not done: the full workspace test and clippy gate, and
scripts/smoke_local.py. - The PR's discussion was not reconciled here.
Summary
actions.rs'sKeyActiondispatch importedPaneFocus/ScrollTargetfromscrollbar.rs(KeyAction::ScrollGrab(ScrollTarget, ...)needs the type), whilescrollbar.rs's mouse hit-testing importedKeyAction/handle_mouse/tab_bar_hit/apply_actionback fromactions.rs— a true cycle despite "hit-testing geometry" vs. "key dispatch" reading like a clean layer split.PaneFocusandScrollTargetmove toapp/types.rs, already the shared home for every other pure type/enum thisapp/split uses (Focus,ActiveTab,Modal, etc.).actions.rsandscrollbar.rsnow both depend ontypes.rsfor these two types instead of on each other.scrollbar.rs's existing one-directional use ofactions.rs(KeyAction,handle_mouse,tab_bar_hit) is untouched and is now the only directuse-level edge between the two modules —actions.rsstill reachesScrollDragindirectly, through thescroll_dragfield it types onAppState(defined inmod.rs;actions.rsnever touches theScrollbarHandle/FooterChip-typed fields), which this move doesn't touch.This is one of two separate instances of the same architectural pattern tracked in ROCMAI-483 (the other is
engines/vllm'sprocess.rs/state.rscycle, in a separate PR, #593).Behavior preservation
Pure move — same variants, same derives, same call sites, same field types throughout
AppState/KeyAction. No logic changed.Test plan
cargo test -p rocm-dash-tui --all-targets— all passing (includes a guard test,actions_does_not_import_from_scrollbar, assertingactions.rsnever reintroduces ause-level dependency onscrollbar.rs— the compiler accepts a module-level cycle here, so nothing else would catch it coming back. The test finds everyuseitem inactions.rsby keyword —usehas no other syntactic role in Rust — and reads forward, brace-depth aware, to its own terminating;, so it catches ausenaming thescrollbarmodule or the three namesapp/mod.rsre-exports from it (ScrollbarHandle,ScrollDrag,FooterChip) in any position or form — top-level or function-local, attribute-gated (e.g.#[cfg(test)]),pub/pub(crate), brace-grouped, or rustfmt-wrapped across multiple lines — without false-positiving on an unrelated identifier likevertical_scrollbar. A positive control in the test asserts the detector actually flags a known-bad case. It does not catch a fully-qualified path referenced inline with nousestatement at all, or ausenamed only inside a/* */block comment; both are known, accepted scope limits of a source scan rather than a parser)cargo clippy -p rocm-dash-tui --all-targets -- -D warnings— cleancargo fmt -p rocm-dash-tui --check— cleancargo build --workspace— clean, no downstream breakage