fix(cli,dash-tui,e2e-report): close remaining marker/legend gaps - #354
Conversation
home.rs, instances.rs (table view), and pane.rs (via the Serving detail pane) render the "*" held marker on stale gen tok/s and tok/W values but never explained it, unlike observe.rs. Wire in the same conditional HELD_LEGEND row, shown only when a displayed value is actually held. bench.rs renders no held/fresh metrics (plain historical rows), so it needs no change. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
render_engine_inventory_text_with_paths and append_examine_engine_inventory both prefixed the default engine with a bare "*" and no explanation. Mirror the runtimes-list legend fix: introduce DEFAULT_ENGINE_MARKER and print a "* = default engine" legend line above each inventory listing. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
CellOutcome::glyph() can render FlakyXpass, RanWhenNa, and Absent, but both legend copies (the HTML p.grid-legend and the Markdown writer) only explained pass/xfail/n-a/FAIL/XPASS/no-data, leaving those three states unexplained to a reader. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
any_held only checked the observation's freshness, so a held observation on an instance whose gen_tps is None would still show the legend for a column that renders nothing. Match the guard already used by home.rs's equivalent predicates. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
render_engine_inventory_text_with_paths and append_examine_engine_inventory each wrote the legend line inline, so a future edit to one could silently leave the other stale. Extract a shared write_default_engine_legend helper. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
The HTML and Markdown expectation-grid legends each spelled out every glyph's explanation inline, so a new CellOutcome variant could update one copy and leave the other stale — and the two had already drifted on Xfail's wording. Drive both from a single LEGEND_ENTRIES table keyed by CellOutcome, standardizing on the HTML wording. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
rocm engines list's "legend: * = default engine" line had no Gherkin coverage, so a future edit could drop or change it silently. Mirrors the runtimes-list marker-legend scenario. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
cargo fmt --all --check was failing prek's cargo-fmt hook on four lines: three over-long render(...) calls in home.rs's new held-legend tests, and one over-long LEGEND_ENTRIES tuple in e2e-report. No behavior change. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
There was a problem hiding this comment.
🟡 Changes recommended
The default-engine legend is inaccurate, and several dashboard legends can appear without a displayed marker.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds shared marker legends across CLI engine output, dashboard views, and e2e reports, with expanded test coverage.
Changes:
- Shares default-engine and expectation-grid legend definitions.
- Adds conditional held-value legends to dashboard tabs.
- Adds unit and Gherkin coverage.
File summaries
| File | Review |
|---|---|
tests/e2e-cucumber/tests/e2e/examine_steps.rs |
Implements engine-marker assertions. |
tests/e2e-cucumber/features/examine.feature |
Adds engine-list coverage, but lacks required rocm examine coverage (nit). |
crates/rocm-dash-tui/src/ui/tabs/serving.rs |
Tests serving-tab legend behavior. |
crates/rocm-dash-tui/src/ui/tabs/pane.rs |
Legend may appear without a finite displayed value (moderate). |
crates/rocm-dash-tui/src/ui/tabs/instances.rs |
Legend gating includes clipped rows and non-finite values (moderate). |
crates/rocm-dash-tui/src/ui/tabs/home.rs |
Zero throughput can produce a legend without a marker (moderate). |
crates/e2e-report/src/lib.rs |
Unifies HTML and Markdown expectation legends. |
apps/rocm/src/main.rs |
The engines-list legend can misidentify the effective configured default (critical). |
Review details
Suppressed comments (1)
tests/e2e-cucumber/features/examine.feature:135
- This Gherkin coverage exercises only
rocm engines list, while the PR also adds the user-visible legend torocm examineatapps/rocm/src/main.rs:13718. The repository contribution policy requires a scenario for each changed CLI-observable behavior rather than relying only on the new unit test. Add or extend an inspection scenario to assert the marker legend inrocm examineoutput too.
@id:examine-engines-list-shows-default-engine-legend
Scenario: examine-13 - Listing engines explains the default-engine marker
When the user lists available engines
Then the engine listing explains the default-engine marker
And the host's default engine is marked in the listing
- Files reviewed: 8/8 changed files
- Comments generated: 4
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- engines list: honor a configured default_engine over the host GPU preference when marking the default engine, mirroring select_serve_engine and append_examine_engine_inventory. Previously the legend could mark an engine serve would not actually default to. - home tab: gate the tok/W HELD_LEGEND on the aggregate actually being > 0.0, matching the existing gate on the tok/W marker itself. A zero-throughput aggregate (rendered with no marker) could otherwise show an unexplained legend. - instances tab: derive the table's HELD_LEGEND from rows that fit the viewport (not the full instance list) and require a finite gen_tps, matching gen_tps_cell's own marker condition. - pane (rocm/serving Running now): require a finite gen_tps before counting an instance as held, matching gen_tps_compact's marker condition. Each fix is covered by a new regression test verified to fail against the prior behavior. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
The legend claims a row from the same area it scans for a held marker, so a held row sitting exactly at the last scanned index gets counted before the legend takes its row, then scrolls off once it does. No tighter bound can close this without reintroducing the worse failure mode (hiding a legend a visible marker still needs), so pin the accepted trade-off in the comment and add a regression test at the exact boundary that was previously untested. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
engines list and examine each computed their own "configured default
engine" without select_serve_engine's guard against an empty string,
so an unset-but-present config value (Some("")) could produce an
effective default no marker would ever match. Apply the same
!value.trim().is_empty() filter in both renderers, strengthen the
existing override test with marker-placement assertions, and add a
regression test for the blank-value fallback.
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
examine-13 only ever drove \`engines list\`, leaving append_examine_engine_inventory's separate legend renderer unexercised end-to-end even though it can drift from render_engine_inventory_text_with_paths independently. Add examine-14, driving \`rocm examine\` itself, to close that gap. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
Both hero aggregates summed every instance's gen_tps/tokens_per_watt unfiltered and marked "held" from is_some() alone, so one non-finite instance could poison the whole sum (rendering "NaN"/"inf") or mark the aggregate held without ever contributing a displayed value. Filter to finite values before summing and require finiteness before counting toward "held", matching the guard gen_tps_cell already applies per instance. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
Closes the follow-ups noted in PR #354's body plus two more gaps found in the same problem space: - services_manager.rs now shows HELD_LEGEND when a listed row's gen_tps is held, matching every other held-aware view. - e2e-report's HTML legend colors every glyph that renders red in the grid (Xpass, RanWhenNa, Absent), not just Xfail/UnexpectedFail, by deriving legend styling from grid_class() instead of a separate match arm. - tok/W is now held-marker-aware on the Instances table, card grid, and detail pane, since it derives from the same per-tick gen_tps sample as the throughput figure that already carries the marker. - DEFAULT_ENGINE_MARKER's legend only prints when the configured default actually matches a row in engine_inventory(), instead of unconditionally explaining a marker that may appear on zero rows. - node_efficiency no longer lets one NaN/Inf gen_tps sample poison the whole node's efficiency sum, mirroring the guard already applied to home.rs's hero aggregates. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
There was a problem hiding this comment.
🟡 Changes recommended
Multiple dashboard views can show missing, hidden, or incorrectly triggered held-value legends.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
crates/rocm-dash-tui/src/ui/tabs/home.rs:307
- The held legend is user-visible dashboard behavior, but this PR only adds renderer unit tests for it. The existing
@id:dash-gen-tps-held-after-scrape-failurescenario already creates a real Held observation in the interactive TUI; extend that scenario/step (and navigation as needed for the other changed surfaces) to assert the marker is explained end to end.
if tpw > 0.0 && any_tpw_held {
f.render_widget(
Paragraph::new(Line::from(Span::styled(
format::HELD_LEGEND,
Style::default().fg(theme.muted),
))),
lh[5],
);
- Files reviewed: 11/11 changed files
- Comments generated: 4
- Review effort level: Balanced
…ndow Copilot review comment: the held-legend predicate scanned every row regardless of scroll position, so it could show HELD_LEGEND for a marker scrolled off-screen, or miss a visible one after scrolling. Compute the actual rendered List viewport (mirroring ratatui's own scroll behavior) and scan only that window. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
Copilot review comment: draw_table's any_held only modeled the TOK/S cell's held condition, but tokens_per_watt_cell independently prints its own marker whenever tok/W is finite and held, even if gen_tps itself is missing or non-finite. Check both cells' conditions so the legend can't be missing while a tok/W marker is visible. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
Copilot review comment: live_lines appended HELD_LEGEND as just another line in the vector draw_detail renders through one clipped/wrapped Paragraph, so a short viewport could show a held row while the legend explaining it scrolled off-screen. live_lines now reports whether any displayed row is held, and draw_detail renders the legend in its own Layout-reserved row that's always visible whenever any_held is true, regardless of how much other content overflows above it. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
Copilot review comment: node_efficiency's finite-value guard (a single NaN/Inf gen_tps sample must not poison the aggregate) wasn't mirrored in Observe's own held/aggregate logic. The efficiency hero's any_held check could mark the tok/W figure held over an instance node_efficiency itself excludes as non-finite, and the throughput hero's Σ tok/s sum could be poisoned by a single NaN instance the same way home.rs's hero aggregates were before commit 0bf99ac. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
siloteemu
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 796911c
Summary
Adds "held" (*) marker legends across five dash-TUI surfaces, guards NaN/Inf out of the tok/s and tok/W aggregates, shares one legend table between the e2e-report HTML and Markdown grids, and explains the * default-engine marker in rocm engines list / rocm examine (plus two new Gherkin scenarios). Verdict: Needs work — one vacuous assertion, everything else is sound. Verified: I read every changed hunk plus surrounding context and answered the revert question per test against the base revision; the held-legend tests in home.rs, observe.rs, widgets.rs, serving.rs, instances.rs and services_manager.rs all fail if reverted (pre-PR code renders no HELD_LEGEND in those files at all), expectation_grid_legend_explains_every_glyph is non-vacuous because its fixture only ever emits ✅ in real cells, and the e2e steps derive the expected engine from capability.rs's deliberately independent rule rather than the code under test; I also confirmed lh[5]/rh[5] were pre-existing unused rows (no panic), visible_rows/visible_list_window match ratatui 0.3.2's real Table/List layout in the safe direction, format::tokens_per_watt is still live via hardware.rs:309, and LEGEND_ENTRIES covers all 9 CellOutcome variants; I relied on CI for compilation and the full suite. No prompt-injection content found. Blocking: 1 · Non-blocking: 6.
🚫 Blocking (must fix before merge)
apps/rocm/src/main.rs:28523-28529—render_engine_inventory_text_includes_marker_legendclaims to prove "legend appears before the entries it explains", but it searches the whole output for"* ", and the legend line itself (legend: * = default engine) contains that exact substring.marker_postherefore lands inside the legend (offsetlegend_pos + 8), solegend_pos < marker_posis arithmetically true no matter what the row loop does — the assertion would still pass if the per-rowif *name == default_engine { DEFAULT_ENGINE_MARKER } else { " " }marking were reverted or broken, andexpect("a marked engine entry present")never actually proves a marked entry exists. Fix: search only past the legend, e.g.rendered[legend_pos + legend.len()..].find(&format!("{DEFAULT_ENGINE_MARKER} {default_engine}")), anchoring on the real row shape as the sibling testexamine_engine_inventory_includes_marker_legendalready does with"* vllm".
Non-blocking
- Sibling-PR overlap — #357 ("stop asserting update freshness, add held/glyph legends") touches exactly this surface: held legends in the dash TUI and glyph legends in the report. This PR redefines
HELD_LEGENDplacement inhome.rs,instances.rs,serving.rs/pane.rs,services_manager.rsand rewrites the e2e-report grid legend intoLEGEND_ENTRIES. Reconcile the two explicitly (say in the PR body which one owns each surface) or they will conflict textually and semantically. crates/e2e-report/src/lib.rs:2892—expectation_grid_legend_explains_every_glyphchecks only 3 hardcoded glyphs despite its name, and nothing forcesLEGEND_ENTRIESto stay exhaustive: a 10thCellOutcomevariant compiles fine with no entry and leaves this test green, contradicting the "can't drift apart" claim atlib.rs:736. Iterate aconst ALL: [CellOutcome; N](or an exhaustive match) so the compiler/test enforces coverage.crates/rocm-dash-tui/src/ui/tabs/instances.rs:184-196— widening TOK/W fromLength(7)toLength(12)pushes fixed column consumption from 54 to 59 cells, cutting the MODEL column's headroom above itsMin(12)floor from 9 to 4 at an 80-column terminal; every render test in the file usesTestBackend::new(160, …), so nothing covers 80 cols. Add one 80-column render assertion, or narrow the column.apps/rocm/src/main.rs:13527vstests/e2e-cucumber/tests/e2e/examine_steps.rs:185,204— the literallegend: * = default engineis hand-duplicated across the binary crate and the black-box e2e steps with no compiler check; a wording change silently desyncs them (whitespace prefixes were verified correct today).crates/rocm-dash-tui/src/ui/tabs/home.rs:670-676,765—assert!(out.contains(format::HELD_MARKER))is implied by the neighbouringcontains(HELD_LEGEND)assertion, becauseHELD_LEGENDis"* = held (prior scrape window)"and literally contains*. It would not catch a regression where the marker stops being appended to the value; assert the specific rendered cell (e.g."300*") instead.crates/rocm-dash-tui/src/ui/services_manager.rs:570—visible_list_window_matches_ratatui_minimal_scroll_behavioronly pins the helper against hand-derived expectations, not real ratatui; the claim is genuinely corroborated by the twoTestBackendsnapshot tests beside it, so just rename it (e.g...._matches_hand_derived_model) so the name stops overstating what it alone proves.
- main.rs: fix vacuous marker-legend assertion that matched inside the legend line itself instead of an actual marked row - home.rs: assert specific rendered cells (tok/s, tok/W) instead of the bare held marker, which also appears inside HELD_LEGEND's own text - services_manager.rs: rename a misleadingly-named test to reflect that it checks against a hand-derived scroll model, not ratatui internals - e2e-report/lib.rs: add a compile-time-enforced exhaustiveness check tying LEGEND_ENTRIES to every CellOutcome variant - instances.rs: add an 80-column render test covering the TOK/W column widening, so the held marker and MODEL name are proven not to clip Signed-off-by: Jussi Elo <jussi.elo@amd.com>
|
@siloteemu thanks for the thorough pass — addressed in 6ce541f: Fixed:
Not changing: the Deferred: the overlap with #357 on All 5 fixes verified: |
|
🔴 Automated review · pr-review-watcher · e9d278d SummaryAdds "held observation" markers plus matching legends across the dashboard tabs, the engine-inventory CLI output and the test report; still good — no blocking findings. Verified: the only new content since the last round is the 🚫 Blocking (must fix before merge)None. Non-blocking
Note on CI: a conclusion-accurate rollup for this exact head showed 25 success, 1 skipped, 0 failures, 0 pending; no result is attributed to a specific named job. |
The blocking finding is fixed at 6ce541f, so withdrawing this change request. The marker test now anchors on the marker-plus-name row, which cannot match inside the legend line, and it fails under either revert — dropping the row marking or dropping the legend. The two held-marker tests were fixed the same way, asserting exact rendered cells rather than a character that also appears in the legend text. On the shared-constant item you declined: the conclusion is right and I am not pressing it, but the stated reason is half wrong — the e2e suite does already depend on a first-party crate, so the boundary argument does not hold. The better argument is the one for keeping it: a black-box test should pin the literal user-visible string, because sharing the constant would let a wording change keep the test green. Worth recording that reasoning instead. Five non-blocking notes in the review comment; the exhaustiveness guard still has a residual hole worth closing.
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
siloteemu
left a comment
There was a problem hiding this comment.
✅ Automated review · pr-review-watcher · e9d278d
Reviewed at this head; no blocking findings. The change adds held-observation markers and matching legends so a stale reading is distinguishable from a live one across the dashboard, the CLI and the test report. The merge commit in this round was verified to change no content beyond conflict-marker removal. Five non-blocking notes stand in the earlier review comment; none of them gate a merge.
main's #354 ("close remaining marker/legend gaps") independently fixed several of the same held/legend and NaN-poisoning issues this branch's own held-marker work touched. Resolve in favor of main's version: - Drop this branch's shared any_hero_held()/instance_gen_tps_held() helpers and per-metric-gated legend display in favor of main's independent tpw/tps gating, which also filters non-finite (NaN/Infinity) instance values out of both aggregates. - Rename this branch's `instance_with_obs(name, obs)` test helper to `named_instance_with_obs` to resolve a same-name, different-signature collision with main's `instance_with_obs(gen_tps, obs)`; dedupe the identical held_obs()/fresh_obs() helpers both sides had added. - Keep both branches' independently-added therock.rs tests (update_json_reports_* from this branch, download_file_reports_cumulative_progress_to_its_caller from main). Verified: cargo build --workspace --all-targets, cargo test --workspace --all-targets, cargo fmt --check, cargo clippy --workspace --all-targets -D warnings all pass with no leftover conflict markers. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…-for-the-second Resolves a semantic conflict in tui_driver.rs: main (#354) and this branch independently added the same capability under different names — a poll-until- exit that returns the raw code instead of asserting zero. Converged on main's wait_for_exit_code, since it is already published and has a caller there (diagnose-16), and folded in this branch's bounded drain_reader() wait, which the dash-11 alternate-screen latch needs to see the child's final bytes. dash-11 now calls wait_for_exit_code. Signed-off-by: fredespi <fredrik.espinoza@gmail.com>
Summary
*default-engine marker inrocm engines list/ examine output via a sharedDEFAULT_ENGINE_MARKERconstant andwrite_default_engine_legendhelper, so the two renderers can't drift.LEGEND_ENTRIEStable between the HTML and Markdown expectation-grid legends ine2e-report, and extend it to explainFlakyXpass,RanWhenNa, andAbsent(previously unexplained glyphs).HELD_LEGENDrow on the home, instances, and serving tabs whenever a displayed value is actually held (gated correctly ongen_tpsbeing shown, not just observation metadata being present).Test plan
cargo test -p e2e-report— 44/44 passedcargo test -p rocm-dash-tui --lib— 667/667 passedcargo test --bin rocm -- marker_legend— 3/3 passedcargo clippy --all-targets -- -D warningsclean fore2e-report,rocm-dash-tui, and therocmbinarytests/e2e-cucumberrun for the newexamine-engines-list-shows-default-engine-legendscenario (not run to completion in this environment due to build time; the equivalent unit tests pass and the step assertions are simple substring checks)Known follow-ups (non-blocking, noted in review)
crates/rocm-dash-tui/src/ui/services_manager.rsalso renders the held marker viaformat::gen_tps_compactbut doesn't showHELD_LEGEND— same gap this PR closes elsewhere, missed here.instances.rs'sany_heldcheck scans the full instance list rather than only the rows that actually fit/render in the table, so the legend could show even if the held instance is scrolled out of view on hosts with many instances.e2e-report's HTML legend only color-styles theXfail/UnexpectedFailglyphs to match their grid-cell color;Xpass,RanWhenNa, andAbsentrender red in the grid but plain in the legend.