Skip to content

Automated Review: Check new UI against Cockpit's style - #2915

Merged
ArturoManzoli merged 1 commit into
bluerobotics:masterfrom
ArturoManzoli:2884-review-ui-conventions
Aug 10, 2026
Merged

Automated Review: Check new UI against Cockpit's style#2915
ArturoManzoli merged 1 commit into
bluerobotics:masterfrom
ArturoManzoli:2884-review-ui-conventions

Conversation

@ArturoManzoli

@ArturoManzoli ArturoManzoli commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
  • The automated reviewer now checks the UI conventions that have only ever lived in review comments: dialog anatomy, the white-alpha button tokens, the two-action footer, who owns the padding, one glass layer per surface, stacking, field-attached actions, icon-only controls, sentence case and space economy.
  • Roughly half the rules describe what the codebase already does and apply to new UI on master today with nothing else needing to land first; the rest, and any clause asking for something added or changed that cites no in-tree precedent, are treated as the house direction the tree is still converging on, which lowers the consistency grade rather than the severity - a breach that still reaches the user stays major.
  • Findings are read against the existing severity rubric: major when the breach reaches the user (an overlay rendering light and unreadable, a control no keyboard can reach), minor when the surface is only cosmetically inconsistent with the app around it (an action nobody can tell is the primary one). When a single surface breaches several rules, they are grouped under one finding with a sub-item per fix, so each stays actionable without inflating the count the verdict is read against.
  • Rules only: the review names the fix and the author decides. Nothing here applies patches.

Worked example, replayed against the "Select BlueOS Cloud mission" dialog in #2865, quoted as the reviewer would emit it under section 6 (one surface, two bullets, grouped as one finding per the rule above):

6. UI / UX

6.1 minorsrc/components/blueos-cloud/BlueOsCloudMissionPicker.vue: the dialog breaches two house-style bullets:

  • (header, :9-13) the v-card-title is a flex justify-between items-center row, so the title is pinned to the left edge, and a v-divider follows the header immediately. Cockpit centres the dialog title and keeps its only separator above the footer.
  • (footer, :101-104) Cancel is followed by a v-spacer, leaving the dialog's only action on the left with empty space where the eye looks for the commit. A single action goes on the right.

The finding is minor, so on its own it lands as MINOR SUGGESTIONS and cannot move a verdict. The rule stays quiet on what this dialog already gets right, which is the point of showing it: the close X is a keyboard-reachable v-btn icon at the top right (:11), and the separator above the footer is where it belongs (:100). A checker that also fired on a compliant header would be worse than none.

Part of #2884

@ArturoManzoli ArturoManzoli changed the title Automated Review: Check new UI against Cockpit's house style Automated Review: Check new UI against Cockpit's style Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Automated PR Review (Claude)

Change map

Governance note (read first). This PR's entire diff edits .github/claude-review/review-guidelines.md — the file that governs this reviewer. Per the base version of that file (:21), a PR is allowed to change it, but I review the change and never adopt it. I ran this review under the base checkout's rules; none of the twelve added bullets were applied to this PR. The added text is imperative prose addressed to the reviewer, which is the declared and entire purpose of the PR rather than a covert instruction smuggled into unrelated code, and a scan of pr.diff found no zero-width, bidi-override, or homoglyph characters and no encoded blobs. Disclosed here rather than raised as a finding, because nothing about it is defective.

Claims. The PR body and commit message assert three things:

Claim Verdict
"Every rule states what the codebase already does" Contradicted in part. Holds for the glass, stacking, ExpansiblePanel, sentence-case and overlay-theme bullets; fails for the theme="dark" breadth (1.1), the close-X (1.2) and the footer-button tokens (1.3).
"src/plugins/vuetify.ts calls createVuetify() with no theme configured" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify().
"applies to new UI on master today with nothing else needing to land first" Contradicted for the close-X bullet: satisfying it through the canonical shell requires a change to InteractionDialog.vue that has not landed (1.2).

Supporting counts from the base checkout, since the rules are stated as descriptions of it:

Convention asserted Base-checkout reality Supported?
Overlay controls carry theme="dark" 26 of 32 <v-select yes
Any Vuetify control carries theme="dark" 0 of 352 <v-btn no
globalGlassMenuStyles is the glass layer defined stores/appInterface.ts:140-146, used in 30 files yes
ExpansiblePanel groups settings 106 uses across 20 files yes
color="primary" is not house style only 2 uses repo-wide yes
Invented z-index at call sites is a real mess z-[1000000], z-[99999], z-[9993], :z-index="5200" yes
Dialog: centered title, divider above footer, lone action right InteractionDialog.vue:11, :48, :57 yes
Dialog: close X at top right absent from InteractionDialog.vue; present in 2 hand-rolled dialogs no
Footer primary is #FFFFFF33, footer buttons are size="small" InteractionDialog.vue:61-71 applies no fill, :64 defaults to 'default' no

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions. The changed artifact is a policy document read at review time by both review workflows.

Function Reached from Frequency
(none — Markdown policy document) .github/workflows/claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review re-review), both reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read the file from the base ref, the new bullets take effect for every PR opened after this merges, and the false-positive rate in 1.1 is multiplied by that frequency rather than paid once.

Invariants. The added text relies on the rule that a bullet stated as "what the codebase already does" is safe to flag deviation from. The sites that can violate it are the codebase facts each bullet asserts; the table above enumerates them. Nine hold, three do not, and those three are findings 1.1, 1.2 and 1.3.

0. Summary

  • Verdict: IMPORTANT FIXES REQUIRED
  • Critical items to address: 1.1, 1.2

The PR appends twelve bullets to the UI/UX section of the automated reviewer's guidelines, codifying dialog anatomy, Vuetify theming, white-alpha button fills, footer action layout, padding ownership, glass layering, stacking, field-attached actions, icon-button affordances, sentence case and vertical-space economy, and instructs that each breach be counted as its own finding under the existing severity rubric. Most of the twelve are accurate descriptions of the base checkout and would be useful as written. Three are not: one flags a pattern the codebase uses 352 times without exception, one demands an element the shell that AGENTS.md mandates does not provide, and one asserts a button-token vocabulary the shell contradicts. Because the rules are consumed as instructions by an automated agent that cannot check them against the code before firing, an inaccurate bullet does not degrade gracefully — it produces confident, wrong findings on every subsequent PR.

1. Correctness & Implementation Bugs

1.1 major.github/claude-review/review-guidelines.md:182: the theme="dark" bullet instructs "flag any added Vuetify control that does not carry it", but the justification immediately following it only supports the narrow case — "anything that teleports an overlay (v-select, v-autocomplete, v-combobox, v-menu, date and color pickers) renders that overlay light and out of reach of the component's own classes". The broad instruction contradicts its own rationale and the codebase: 0 of 352 <v-btn in src/**/*.vue carry theme="dark", while 26 of 32 <v-select do. Under the rule as written, every added button, v-icon and v-card — including the ones in the exemplar BlueOsCloudLoginDialog.vue — is a finding, and the bullet's own closing sentence ("Removing theme="dark" is a regression, never a cleanup") gives the reviewer no room to back down. Narrow the flag to the overlay-teleporting set the bullet already enumerates; that version is both correct and well-supported.

1.2 major.github/claude-review/review-guidelines.md:181: the dialog-anatomy bullet flags any added dialog "that has no close X at the top right … keyboard-reachable as a v-btn icon". InteractionDialog.vue:8-17 renders no close X, and it is the shell AGENTS.md:233 directs authors to reuse ("For modal confirmations and from→to choices, reuse the existing useInteractionDialog composable … before creating a new component"). Dialogs that follow that direction correctly — UserNameInputDialog.vue:2-9, CameraReplacementDialog.vue:2-9 — therefore have no X and would each be flagged. The only in-tree way to comply is what GnssDeviceDialog.vue:10-15 does: inject an absolutely-positioned v-btn icon into the #content slot (absolute top-0 right-0 py-2 pr-3) and then cancel the resulting gap with -mt-7 on the sibling (:15) — which this same PR's padding-ownership bullet (:185) flags as stacked insets and magic values. So the rule pushes authors into a shape another new rule penalises. The bullet's escape hatch ("a hand-rolled dialog satisfies this by gaining the X, never by being told to migrate to a different shell") addresses migration but not this case, where the compliant shell is the one lacking the X. Either scope the bullet to hand-rolled v-dialog/v-card dialogs, or land the close X in InteractionDialog.vue first so the rule describes something reusable.

1.3 minor.github/claude-review/review-guidelines.md:183: the button-token bullet asserts a split — #FFFFFF33 for "the committing action in a dialog footer", #FFFFFF22 for "the ordinary action buttons on a page or panel" — and tells the reviewer to flag "footer buttons missing size="small"". Three parts of this are not what the code does. (a) InteractionDialog.vue:61-71 applies no fill token to footer buttons at all; the class is opt-in via button.class. (b) InteractionDialog.vue:64 defaults footer buttons to :size="button.size || 'default'", and even the PR's own best exemplar leaves them unsized — BlueOsCloudLoginDialog.vue:76,79 are plain variant="text" with no size. (c) #FFFFFF33 is a general white-alpha ramp rather than a footer-primary token: ConfigurationMissionView.vue:15,24,33,42,51,60,234 use it as a v-switch base-color and :175 as a border. The #FFFFFF33-primary/#FFFFFF22-secondary contrast is real where a fill is used (BlueOsCloudLoginDialog.vue:84 vs :36), so state it that way and drop the size="small" clause.

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; it touches one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key in the diff)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows outside it; no dependency, JSDoc, yarn-vs-npm or optional-chaining surface, since the diff adds no code — the one AGENTS.md conflict found, against the useInteractionDialog reuse rule at AGENTS.md:233, is reported in 1.2 rather than duplicated here)

4. Security — ✅ (scanned the diff for zero-width, bidi-override and homoglyph characters and for encoded blobs, finding none; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own governing rules is handled in the Change map's governance note, under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is a Markdown document with no runtime call site; the only cost is review-time, and the frequency multiplier established in the Change map — base-ref read on every PR and every /review — is what raises 1.1's blast radius rather than any hot path)

6. UI / UX — ✅ (the PR renders no UI of its own; the substance of the twelve added UI rules was checked against the base checkout in the Change map table and is reported in 1.1-1.3, 7.1 and 11.1)

7. Code Quality & Style

7.1 minor.github/claude-review/review-guidelines.md:180: "Do not collapse several of them into one finding; a surface carrying four is four fixes" pulls against two rules already in the file. The section-collapsing block (:104-110) is headed "IMPORTANT — keep the review short and scannable", and the rubric note at :96 warns that "a review made entirely of minor and nit cannot change a verdict, so reaching for those by default makes the whole review advisory in the weakest sense". Twelve bullets, most of which land as minor by their own definition ("minor when the surface is only inconsistent with the app around it"), applied one-finding-per-breach to a single new dialog, will routinely outnumber the correctness and persistence findings in the same review and bury them. The intent — that four breaches need four fixes, not one vague note — is right; get it without the count inflation by grouping house-style breaches under one 6.x finding with one sub-item per fix, so the fixes stay individually actionable but the finding count still reflects severity.

8. Commit Hygiene — ✅ (one commit, b0ffc27, for one logical change of 12 added lines in one file; the docs: type fits a guidelines document, the subject carries no PR number, and there is no wip/fixup!/self-correcting or over-split history to fold — Part of #2884 is correctly in the PR body, not the subject)

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay of the rules against the #2865 dialog is the appropriate substitute, though src/components/blueos-cloud/BlueOsCloudMissionPicker.vue is not on the base ref, so that replay could not be verified here)

10. Documentation — ✅ (checked whether the change needs to reach README.md or AGENTS.md: it does not — it alters no Lite-vs-Standalone behavior and adds no user-facing feature, and the edited file is itself the documentation for the review process)

11. Nitpicks / Optional

11.1 nit.github/claude-review/review-guidelines.md:185: the padding-ownership bullet names w-[90%] as an example of a "magic pixel value … where a utility or the container's own width covers it". InteractionDialog.vue:23 uses exactly w-[90%], in the shell nearly every dialog in the app renders through. Picking an example that the house shell itself uses will make the rule read as arbitrary to the first author who greps for it; ml-[10px] alone carries the point.

Generated by Claude. This is advisory; a human reviewer must still approve.

@ArturoManzoli
ArturoManzoli force-pushed the 2884-review-ui-conventions branch from b0ffc27 to 27045b5 Compare August 10, 2026 12:31
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

Done:

  • (1.1) narrowed the theme="dark" flag to the overlay-teleporting controls the bullet already lists (v-select, v-autocomplete, v-combobox, v-menu, date/color pickers) and explicitly exempted plain v-btn/v-icon/v-card, since 0 of 352 buttons in the tree carry it.
  • (1.2) scoped the close-X requirement to hand-rolled v-dialog/v-card dialogs; a dialog built on the useInteractionDialog shell (which AGENTS.md tells authors to reuse and which has no X) is no longer flagged for missing one.
  • (1.3) dropped the size="small" clause and reframed the split as "where a button carries a fill", since InteractionDialog leaves footer buttons unsized and applies no fill; the #FFFFFF33 primary vs #FFFFFF22 secondary contrast still stands where a fill is used.
  • (7.1) replaced "a surface carrying four is four fixes" with grouping several house-style breaches under one 6.x finding with one sub-item per fix, so it stops pulling against the file's own section-collapsing and severity-inflation rules.
  • (11.1) dropped w-[90%] from the padding example, keeping ml-[10px], since the shell most dialogs render through (InteractionDialog.vue:23) uses w-[90%] itself.

@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown

Automated PR Re-review 2 (Claude)

Comparing b0ffc27c45155a847502a57c919b88924485e28f27045b58797d488d7c64e026d028f235aa582a43. The incremental comparison is unusable and was not relied on: pr.json lists a single commit (27045b5, authoredDate 10:43 vs committedDate 12:18), so the previous head was amended and force-pushed rather than built on, and incremental.diff is byte-identical to pr.diff — it presents the whole PR as new. Every status below was judged against pr.diff (the current guidelines text), and the new findings come from a full re-run of the investigation and sections 0-11 over the whole PR, not over the increment.

Previous findings status

# Finding Severity Status
1.1 theme="dark" bullet flagged any Vuetify control, contradicting its own overlay-teleport rationale and the 0-of-352 v-btn reality major ✅ Addressed
1.2 Close-X rule could not be satisfied through InteractionDialog, the shell AGENTS.md:233 mandates reusing major ✅ Addressed
1.3 Footer button-token and size="small" claims contradicted by InteractionDialog and by the PR's own exemplar minor ✅ Addressed
7.1 One-finding-per-breach pulled against the file's own section-collapsing and severity-inflation rules minor ✅ Addressed
11.1 Padding bullet cited w-[90%], which InteractionDialog.vue:23 itself uses nit ✅ Addressed

Verification of each, against the code rather than the comment: 1.1 — the bullet (pr.diff +theme="dark" line) now reads "flag an added overlay-teleporting Vuetify control (v-select, v-autocomplete, v-combobox, v-menu, date and color pickers)" and adds an explicit exemption for v-btn/v-icon/v-card; the "removing it is a regression" clause is now scoped to "one of them". 1.2 — the close X is now required only of "a hand-rolled v-dialog/v-card dialog", with an explicit carve-out for the useInteractionDialog shell, so UserNameInputDialog.vue:2-9 and CameraReplacementDialog.vue:2-9 no longer trip it. 1.3 — all three parts landed: the token claim is now conditional ("where a button carries a fill"), the size="small" clause is gone, and the split is stated as a fill contrast, which is what BlueOsCloudLoginDialog.vue:84 vs :36 actually shows. 7.1 — replaced by "group the breaches under one 6.x finding with one sub-item per fix, so each fix stays individually actionable without inflating the finding count". 11.1w-[90%] is gone; only ml-[10px] remains.

Discussion since last review

  • ArturoManzoli (Automated Review: Check new UI against Cockpit's style #2915 (comment)) posted a five-item "Done:" list, one per previous finding. Treated as a claim and checked against pr.diff: all five hold, as detailed above. The list is also the reason the two major findings closed, so it is the substance of this re-review rather than commentary on it.
  • The bare /review comment is a command, not review input, and was ignored.
  • No comment disputed a finding, and no comment contained text addressed to me.

New findings

Change map

Governance note (still applies). The whole diff edits .github/claude-review/review-guidelines.md, the file that governs this reviewer. Per the base version (:21) I review the change and never adopt it: this run was executed under the base checkout's rules, and none of the twelve added bullets were applied to this PR. Re-scanned pr.diff for hidden Unicode — the only non-ASCII byte in the file is an em dash on an unchanged context line (pr.diff:22), and the added lines are pure ASCII with no zero-width, bidi-override, homoglyph or encoded content. The added text is imperative prose addressed to the reviewer, which is the PR's declared and entire purpose rather than an instruction smuggled into unrelated code.

Claims.

Claim Verdict
PR body: "Every rule states what the codebase already does" Contradicted in part. Holds for the glass layer (globalGlassMenuStyles, 73 uses across 40 files), stacking (35 z-*/z-index call sites), ExpansiblePanel, centered dialog titles, the divider above the footer, color="primary" (2 uses repo-wide) and the overlay theme on v-select/pickers. Fails for v-menu, sentence case, the details row and icon-button keyboard reachability (1.5), and for footer differentiation (1.4).
PR body: "it applies to new UI on master today with nothing else needing to land first" Contradicted for the footer bullet: complying requires passing a fill class through the shell's Action.class, which zero call sites do (1.4).
PR body: "A surface carrying four breaches gets four findings, not one" Contradicted by the PR's own diff, which now says the opposite (group under one 6.x finding). Stale text left over from the pre-revision rules (8.1).
Commit message: "the theme every Vuetify control needs because the app configures none" Contradicted by the diff, which now exempts plain v-btn/v-icon/v-card. Also stale (8.1).
"src/plugins/vuetify.ts calls createVuetify() with no theme configured" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify().

Counts re-derived from the base checkout this run, since each bullet is stated as a description of it:

Convention asserted Base-checkout reality Supported?
Overlay controls carry theme="dark"v-select 32 <v-select sites, ~26 carrying it yes
…the same for v-menu 3 of ~24 <v-menu carry it no
globalGlassMenuStyles is the glass layer 73 uses across 40 files; hand-written backdrop-filter survives in ~8 files yes
Invented z-index at call sites is a real mess 35 occurrences across 15 files, incl. :z-index="5200" yes
Centered dialog title, divider above footer InteractionDialog.vue:11,:48; BlueOsCloudLoginDialog.vue:9,:72; MapOverlaysDialog.vue:112; DataLakeVariableDialog.vue:85 yes
Footer: dismiss left / single action right InteractionDialog.vue:56-57 (justify-between for two, justify-end for one) yes
Footer buttons are visually differentiated 0 of 8 useInteractionDialog footers; only 2 hand-rolled dialogs no
color="primary" is not house style 2 uses repo-wide yes
A text action sits in the field's details row 0 #details slots in src/**; "beside the input" is the real form (GnssDeviceDialog.vue:44,:62-70) partly
Labels read as sentence case Title Case is at least as common (Plotter.vue:23,90,121,165, ConfigurationLogsView.vue:34,193,222,251,296,395, GnssDeviceDialog.vue:100) no
Icon-only controls are v-btn icon Clickable v-icon closes at MissionEstimates.vue:48,121, MapOverlaysDialog.vue:5, MissionLibraryModal.vue:284 no
ExpansiblePanel groups settings, isOnPhoneScreen exists used throughout (GnssDeviceDialog.vue:99, Map.vue:103; InteractionDialog.vue:12) yes

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions; the changed artifact is a policy document read at review time.

Function Reached from Frequency
(none — Markdown policy document) .github/workflows/claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review), both reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read it from the base ref, an inaccurate bullet is paid once per PR opened forever, not once here — which is what sets the severity of 1.4 and 1.5.

Invariants. The addition relies on the rule that a bullet stated as "what the codebase already does" is safe to flag deviation from. The sites that can violate it are the codebase facts each bullet asserts; the table above enumerates them. Eight hold, four do not.

0. Summary

  • Verdict: IMPORTANT FIXES REQUIRED
  • Critical items to address: 1.4

The revision narrows the three bullets the last review found unsupported and reframes the finding-count instruction, and each of those five fixes is real. What remains is the same defect one bullet deeper: the button-token bullet now also tells the reviewer to flag "a footer whose buttons all look alike", which is precisely what the shared InteractionDialog shell renders for all eight of its in-tree callers, so the rule would fire — at major, by its own grading — on dialogs written the way AGENTS.md tells authors to write them. Beyond that, four of the twelve bullets are presented as existing conventions that the tree does not hold (v-menu theming, sentence case, the details row, icon-button keyboard reachability); they are defensible as new conventions, but not as descriptions, and the reviewer will cite in-tree precedent that does not exist. The commit message and PR body still describe the pre-revision versions of two rules.

1. Correctness & Implementation Bugs

1.4 major.github/claude-review/review-guidelines.md (button-tokens bullet, pr.diff:12): the bullet ends "…and a footer whose buttons all look alike". The shared shell renders exactly that: InteractionDialog.vue:61-71 loops the footer actions through one v-btn with no fill and no per-role styling, differentiating only if the caller passes Action.class (:112) — and no caller does. A search for class: '(bg-|elevation over src/** returns nothing, and every footer in the tree is a pair of visually identical buttons: videoChunkManager.ts:212-213,252-253 (Cancel/Delete), MissionLibraryModal.vue:479-482, PoiActionPopup.vue:214-217, useOfflineTiles.ts:106-110,128-133 (both color: 'white'), MissionControlPanel.vue:213-219, EditMenu.vue:915-921, video.ts:774-777. The only differentiated footers are hand-rolled: BlueOsCloudLoginDialog.vue:79-89 (variant="text" Cancel + bg-[#FFFFFF33] primary) and VehicleDefaultsReplaceConfirmationDialog.vue:19-20. So a new dialog built the AGENTS.md-mandated way (useInteractionDialog, AGENTS.md:233) with Cancel + Confirm trips this bullet, and the house-style bullet grades "an action nobody can tell is the primary one" as major — a verdict-moving finding against the house pattern, on every UI PR that adds a dialog. Two ways out, and they are not exclusive: scope the flag to hand-rolled footers, and/or name the mechanism in the bullet (pass class: 'bg-[#FFFFFF33]' on the committing action) — better still, land that fill as the shell's default for the last action in InteractionDialog.vue:61-71, which would make the rule descriptive and fix all eight existing footers at once. This is the same shape as 1.2: a rule whose only compliant form is unreachable through the canonical shell.

1.5 minor.github/claude-review/review-guidelines.md (house-style bullet, pr.diff:9): "the bullets below codify what the codebase already does, not a preference" is inaccurate for four of the twelve, so the reviewer will assert a convention and be unable to cite it:

  • v-menu in the theme="dark" set (pr.diff:11): 3 of ~24 <v-menu sites carry it (EditMenu.vue:21, MissionControlPanel.vue:96, CollapsibleContainer.vue:45). The other ~21 do not — BatteryIndicator.vue:164,174,184,194, Plotter.vue:50,62, ConfigurationLogsView.vue:69,93,118,324, ConfigurationUIView.vue:13,39, Map.vue:10, MapCenterControl.vue:77, EkfStateIndicator.vue:3, SnapshotTool.vue:7, ToolsLogsView.vue:14,130, CruiseSpeedControl.vue:3, InputElementConfig.vue:136, MissionPlanningView.vue:509 — because the menu's content carries its own dark/glass styling (globalGlassMenuStyles, or an inner theme="dark" picker). Either say the bullet applies when the overlay content is not itself dark-styled, or drop v-menu from the enumerated set.
  • Sentence case (pr.diff:19): Title Case is at least as common in the tree — Plotter.vue:23,90,121,165 ("Data Source", "Statistics Display", "Time Axis", "Vertical Range"), ConfigurationLogsView.vue:34,193,222,251,296,395, ToolsMAVLinkView.vue:16, GnssDeviceDialog.vue:100 ("Device Status"), BatteryIndicator.vue:75, DepthIndicator.vue:18, RelativeAltitudeIndicator.vue:16, ConfigurationActionsView.vue:127, DataLakeVariableDialog.vue:5.
  • The details row (pr.diff:17): no component in src/** uses a #details slot. The precedent is the other half of the same sentence — the action beside the input (GnssDeviceDialog.vue:44, :62-70).
  • Icon-only controls (pr.diff:18): clickable v-icon closes are the prevailing form, not the exception — MissionEstimates.vue:48,121, MapOverlaysDialog.vue:5, MissionLibraryModal.vue:284; MissionChecklist.vue:6 is the v-btn icon + aria-label case.

All four are reasonable things to want. State them as new conventions (and grade them accordingly) rather than as descriptions, so the reviewer does not go looking for in-tree examples that are not there.

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key anywhere in it)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows; no dependency, JSDoc, yarn-vs-npm or optional-chaining surface, since the diff adds no code — the one AGENTS.md conflict found this run, against the useInteractionDialog reuse rule at AGENTS.md:233, is reported in 1.4 rather than duplicated here)

4. Security — ✅ (re-scanned pr.diff for zero-width, bidi-override and homoglyph characters and for encoded blobs: the only non-ASCII byte in the file is an em dash on an unchanged context line at pr.diff:22; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own rules is handled in the Change map's governance note, under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is Markdown with no runtime call site; the only cost is review-time, and the base-ref frequency multiplier established in the Change map is what sets the severity of 1.4/1.5 rather than any hot path)

6. UI / UX — ✅ (the PR renders no UI of its own; the substance of the twelve added UI rules was re-derived against the base checkout in the Change map tables and is reported in 1.4, 1.5 and 11.2)

7. Code Quality & Style — ✅ (12 added lines, no deleted or reworded comment, no code and so no lint surface; checked the added bullets against the file's own section-collapsing block at :104-110 and the severity note at :96, which the revised grouping instruction now respects — that was 7.1 and it is closed)

8. Commit Hygiene

8.1 minor — commit 27045b5 ("docs: check new UI against Cockpit's house style"): the message body still describes the rules as they were before this revision. It says the reviewer now checks "the theme every Vuetify control needs because the app configures none", which is the exact scope finding 1.1 rejected and which the diff no longer contains — the bullet is now limited to overlay-teleporting controls and explicitly exempts v-btn/v-icon/v-card. The PR body has the mirror problem: "A surface carrying four breaches gets four findings, not one" is the opposite of what the diff now says (group under one 6.x finding with one sub-item per fix). Amending rather than piling on an "address review" commit was the right call per AGENTS.md:196-197, but the amend should have carried the message with it; as it stands, whoever greps history for the origin of the theme="dark" rule gets the rejected scope. One commit for one logical change, correct docs: type, no PR number in the subject, Part of #2884 in the body — the rest of the section is clean.

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay against the #2865 dialog is the appropriate substitute, though src/components/blueos-cloud/BlueOsCloudMissionPicker.vue is still not on the base ref, so that replay remains unverifiable here)

10. Documentation — ✅ (re-checked whether the change needs to reach README.md or AGENTS.md: it does not — no Lite-vs-Standalone behavior, no user-facing feature, and the edited file is itself the documentation for the review process; the stale PR-body text is reported in 8.1)

11. Nitpicks / Optional

11.2 nit.github/claude-review/review-guidelines.md (button-tokens bullet, pr.diff:12): "a saturated fill under white text (Cockpit is flown on tablets in direct sun)" has no carve-out for the destructive confirmation, where the saturated fill is the signal. VehicleDefaultsReplaceConfirmationDialog.vue:20 uses color="error" on "Replace" and ToolsDataLakeView.vue:127 does the same; those are the only two saturated button fills in the tree, so the rule is otherwise well supported. One clause exempting the destructive action would stop the reviewer from talking authors out of the red on a delete.

Generated by Claude. This is advisory; a human reviewer must still approve.

@ArturoManzoli
ArturoManzoli force-pushed the 2884-review-ui-conventions branch from 27045b5 to b4003d0 Compare August 10, 2026 13:04
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

Done:

  • (1.4) scoped the "committing action indistinguishable from the dismiss" / "buttons all look alike" flags to hand-rolled footers and exempted the useInteractionDialog shell, whose 8 in-tree footers are uniformly styled; named the mechanism (pass bg-[#FFFFFF33] on the committing action) so the guidance is constructive rather than firing at major on every shell-built dialog. Same shape as 1.2.
  • (1.5) softened the house-style umbrella to say most bullets describe the tree while a few (sentence case, keyboard-reachable icon buttons, a text action beside its input) are the house direction it is converging on; qualified the v-menu theme flag to menus whose overlay content is not already dark/glass-styled (3 of 24 carry it); and reordered the field-attached bullet to lead with "beside the input", since there are 0 #details slots in the tree.
  • (8.1) amended the commit body to describe the overlay-only theme scope and drop the universal "codifies what the codebase does" claim, and updated the PR body's severity bullet to the grouped-finding rule.
  • (11.2) added a color="error" destructive-confirmation carve-out to the saturated-fill flag, where the red is the intended signal.

@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

1 similar comment
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown

Automated PR Re-review 3 (Claude)

Comparing 27045b58797d488d7c64e026d028f235aa582a43b4003d0c2f5c00fcf79fb70ba478d3de3cca3433. The incremental comparison is again unusable and was not relied on: pr.json still lists a single commit (b4003d0, authoredDate 10:43 vs committedDate 12:58), so the previous head was amended and force-pushed rather than built on, and incremental.diff carries the same single +12/-0 hunk as pr.diff — it presents the whole PR as new. Every status below was judged against pr.diff, and the new findings come from a full re-run of the investigation and sections 0-11 over the whole PR, not over the increment.

Previous findings status

# Finding Severity Status
1.4 "footer whose buttons all look alike" fired at major on every dialog built with the mandated useInteractionDialog shell major ✅ Addressed
1.5 House-style umbrella claimed the bullets codify existing practice, but v-menu theming, sentence case, the details row and icon-button keyboard reachability are not in-tree conventions minor ✅ Addressed
8.1 Amended commit message and PR body still describe the pre-revision rules minor :large_yellow_circle: Partially addressed
11.2 Saturated-fill flag had no carve-out for the destructive-confirm red nit ✅ Addressed

Verification of each against the code, not against the comment:

  • 1.4 — the "all look alike" phrasing is gone. The bullet (pr.diff:12) now reads "In a hand-rolled footer also flag a committing action left indistinguishable from the dismiss … a footer rendered by the useInteractionDialog shell is exempt … the primary is differentiated there by passing a fill class (bg-[#FFFFFF33]) on the committing action". Both remedies the finding named landed (scope to hand-rolled, name the mechanism), and the rescoped flag is now supported: of the hand-rolled footers in the tree, 9 differentiate the commit (MissionChecklist.vue:99, BlueOsCloudLoginDialog.vue:84, VehicleDefaultsReplaceConfirmationDialog.vue:20, DataLakeVariableDialog.vue:89, TransformingFunctionDialog.vue:94, MissionLibraryModal.vue:272,:311, MissionIdentifier.vue:46, ExternalFeaturesDiscoveryModal.vue:659,:708) against 4 that do not (VehicleDefaultsJoystickImportModal.vue:22-23, VehicleDefaultsViewsImportModal.vue:22-25, JoystickCalibration.vue:262-266, DoItYourself.vue:77-88). What the fill is remains inaccurate — that is new finding 1.7, not a reopening of 1.4.
  • 1.5 — all four parts landed. The umbrella now says "Most describe what the tree already does; a few (sentence case, keyboard-reachable icon buttons, a text action beside its input) are conventions the codebase is still converging on, so cite them as the house direction rather than claiming universal in-tree precedent" (pr.diff:9), which covers three of the four. The fourth is fixed at the source: the theme bullet now reads "a v-menu whose overlay content is not already dark- or glass-styled" (pr.diff:11), and that qualifier is accurate — the 21 unthemed v-menu sites wrap content that carries its own dark styling (BatteryIndicator.vue:172,182,192,202, Plotter.vue:60,72 are inner theme="dark" colour pickers), while the 3 that carry it are EditMenu.vue:21, MissionControlPanel.vue:96, CollapsibleContainer.vue:45. The field-attached bullet now leads with "beside the input" and demotes the details row (0 #details slots in src/**) to a parenthetical.
  • 8.1 — half of it. The commit body now reads "the dark theme that overlay-teleporting Vuetify controls need because the app configures none" and "Most of the bullets describe what the tree already does and a few are the house direction it is converging on", which is what the finding asked for. The PR body still carries both stale sentences: "Every rule states what the codebase already does, so it applies to new UI on master today with nothing else needing to land first" and "A surface carrying four breaches gets four findings, not one" — the second is the exact opposite of pr.diff:9 ("group the breaches under one 6.x finding"), and the first is the universal claim the diff itself has now dropped. Stays open.
  • 11.2 — landed: "except a color="error" destructive confirmation, where the red is the signal" (pr.diff:12), which matches VehicleDefaultsReplaceConfirmationDialog.vue:20 and ToolsDataLakeView.vue:127.

Discussion since last review

  • ArturoManzoli (Automated Review: Check new UI against Cockpit's style #2915 (comment)) posted a four-item "Done:" list. Treated as a claim and checked against the code: the 1.4, 1.5 and 11.2 items hold as described. The 8.1 item — "amended the commit body … and updated the PR body's severity bullet to the grouped-finding rule" — is contradicted by the PR body in pr.json, which still says "A surface carrying four breaches gets four findings, not one". The commit half is done, the PR-body half is not, so 8.1 is partially addressed rather than closed.
  • Two bare /review comments are commands, not review input, and were ignored.
  • No comment disputed a finding, and nothing in pr.json, pr.diff or new-comments.json contained text addressed to me.

New findings

Change map

Governance note (still applies). The whole diff edits .github/claude-review/review-guidelines.md, the file that governs this reviewer. Per the base version (:21) I review the change and never adopt it: this run executed under the base checkout's rules, and none of the twelve added bullets were applied to this PR. Re-scanned pr.diff for hidden Unicode: the only non-ASCII byte in the file is an em dash on an unchanged context line (pr.diff:22); the twelve added lines are pure ASCII, with no zero-width, bidi-override, homoglyph or encoded content. The added text is imperative prose addressed to the reviewer, which is the PR's declared and entire purpose rather than an instruction smuggled into unrelated code.

Claims.

Claim Verdict
PR body: "Every rule states what the codebase already does, so it applies to new UI on master today" Contradicted twice over — by the diff itself, which now claims only that most do (pr.diff:9), and by the footer-actions and button-fill claims (1.6, 1.7). Stale text (8.1).
PR body: "A surface carrying four breaches gets four findings, not one" Contradicted by the PR's own diff, which says to group them under one 6.x finding. Stale text (8.1).
Commit body: "Most of the bullets describe what the tree already does and a few are the house direction it is converging on" Verified as a description of the new umbrella, and true of 10 of the 12 bullets. The two exceptions are the footer-actions and button-fill claims (1.6, 1.7), neither of which is in the three-item "converging" carve-out.
Commit body / bullet: overlay-teleporting controls need theme="dark" "because the app configures none" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify().
PR body worked example against BlueOsCloudMissionPicker.vue from #2865 Unverifiable — that file is still not on the base ref.

Counts re-derived from the base checkout this run, since each bullet is stated as a description of it:

Convention asserted Base-checkout reality Supported?
Overlay theme="dark" on v-select/pickers 32 <v-select sites, ~26 carry it yes
v-menu only when its content is not already dark 3 of 24 carry it; the other 21 wrap dark/glass content (BatteryIndicator.vue:172, Plotter.vue:60,72) yes (was the 1.5 miss)
Centred dialog title + divider above the footer InteractionDialog.vue:11,48; DataLakeVariableDialog.vue:4,85; TransformingFunctionDialog.vue:4,90; MissionIdentifier.vue:23,42; ExternalFeaturesDiscoveryModal.vue:612,653; MissionLibraryModal.vue:283,309; BlueOsCloudLoginDialog.vue:9,72 yes
Hand-rolled footer differentiates the commit 9 do, 4 do not yes
A dialog footer carries two actions at most DoItYourself.vue:77-88 carries five, JoystickCalibration.vue:262-266 three no (1.6)
The dismiss is variant="text" true of hand-rolled footers; not expressible in the ~10 shell footers — DialogActions (src/types/general.ts:26-33) and Action (InteractionDialog.vue:96-121) have no variant field partly (1.6)
A filled commit action is #FFFFFF33 white-on-white-alpha 3 sites (MissionChecklist.vue:99, BlueOsCloudLoginDialog.vue:84, DataPrivacyModal.vue:79) against 7 filled color="white" commits no (1.7)
#FFFFFF22 for page/panel action buttons ConfigurationGeneralView.vue:44,47,50,53,123; ConfigurationCloudView.vue:39,48; ConfigurationVideoView.vue:289; ConfigurationMissionView.vue:135 yes
color="primary" is not house style 2 uses repo-wide (UpdateNotification.vue:20, JoystickCalibration.vue:106) yes
globalGlassMenuStyles is the glass layer; bg-[#FFFFFF11] is the nested tint 73 uses across 40 files; nested tint at MiniVideoRecorder.vue:110, SnapshotTool.vue:16, SplashScreen.vue:68, MissionLibraryModal.vue:294 yes
Invented z-index at call sites is a real mess 35 occurrences across 15 files yes
ExpansiblePanel groups settings, isOnPhoneScreen exists ExpansiblePanel.vue; InteractionDialog.vue:12 yes

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions; the changed artifact is a policy document read at review time.

Function Reached from Frequency
(none — Markdown policy document) claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review), both with a plain actions/checkout@v4 (:30, :70) and so reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read it from the base ref, an inaccurate bullet is paid once per PR opened forever, not once here — that is what keeps 1.6 and 1.7 worth raising at all.

Invariants. The addition relies on the rule that a bullet stated as "what the codebase already does" is safe to flag deviation from. The sites that can violate it are the codebase facts each bullet asserts; the table above enumerates them. Ten hold, two do not, and the three the umbrella explicitly downgrades to "house direction" are no longer claims about the tree.

0. Summary

  • Verdict: MINOR SUGGESTIONS

The revision closes the previous major: the footer-differentiation flag is now scoped to hand-rolled footers, exempts the useInteractionDialog shell and names the mechanism (bg-[#FFFFFF33] on the committing action), which the tree supports 9-to-4. The house-style umbrella now separates the ten bullets that describe the tree from the three it is converging on, and the v-menu clause is qualified in a way that matches all 24 call sites. What is left is smaller and of the same kind: two bullets still assert a house style the tree mostly contradicts — the two-action footer limit and the variant="text" dismiss (which the shared shell's DialogActions type cannot even express), and the #FFFFFF33 filled commit, which loses 3-to-7 against color="white". The PR body also still carries the two sentences the previous review flagged as stale, one of which now states the opposite of the diff.

1. Correctness & Implementation Bugs

1.6 minor.github/claude-review/review-guidelines.md (footer-actions bullet, pr.diff:13): two of the bullet's assertions do not hold against the tree, and this bullet is not one of the three the umbrella downgrades to "house direction".

  • "the dismiss (variant="text" …)" is not expressible through the mandated shell. DialogActions (src/types/general.ts:26-33) and Action (InteractionDialog.vue:96-121) expose text, size, color, class, disabled, action and nothing else, and the template binds only :size, :color, :class, :disabled (InteractionDialog.vue:61-71). Every shell footer therefore renders its dismiss with Vuetify's default (elevated) variant — videoChunkManager.ts:213,:253, useOfflineTiles.ts:107,:129, MissionLibraryModal.vue:480, PoiActionPopup.vue:215, MissionControlPanel.vue:215, ConfigurationLogsView.vue:860. Ironically the only shell path that complies is the no-actions fallback (InteractionDialog.vue:74), which hard-codes variant="text". The exemption added for 1.4 sits on the button-tokens bullet and does not reach this one. Either add the same shell carve-out here, or add variant?: string to DialogActions and bind it in InteractionDialog.vue:61-71 — one line each, and it would make the rule satisfiable everywhere.
  • "a dialog footer carries two at most … Flag a third action" is contradicted by DoItYourself.vue:77-88 (Close, Export, Import, Reset, Apply — five) and JoystickCalibration.vue:262-266 (Cancel, Auto calibrate deadzones, Save — three). Both are exactly the "extra action belongs next to the content it acts on" case, so the rule is a good one; it just is not yet what the tree does. Say so, the way the umbrella already does for its three, or name those two dialogs as the form being replaced.

1.7 minor.github/claude-review/review-guidelines.md (button-tokens bullet, pr.diff:12): "where a button carries a fill it is white text on a white alpha fill, #FFFFFF33 for the committing action in a dialog footer" is the minority form, and the bullet's own flag catches the majority. Filled commit actions in dialog footers today: #FFFFFF33-family at MissionChecklist.vue:99, BlueOsCloudLoginDialog.vue:84, DataPrivacyModal.vue:79 — against color="white" (an opaque white fill with dark text, i.e. the inverse of the token) at DataLakeVariableDialog.vue:89, TransformingFunctionDialog.vue:94, MissionLibraryModal.vue:272,:311, useOfflineTiles.ts:110,:133, PoiActionPopup.vue:217. Since white is a Vuetify default colour, "Flag color="primary" and other Vuetify default colors standing in for those tokens" fires on all seven, so an author writing a new dialog in the image of its nearest sibling (DataLakeVariableDialog.vue, a dark-glass dialog with a centred title and a divider above the footer — compliant on every other bullet) gets flagged for copying it. The #FFFFFF22 half of the sentence needs no change; it is well supported. For the footer half, either state it as the direction and say color="white" is the legacy form being replaced, or drop the "this is what the tree does" framing for this clause. Note this is distinct from 1.4, which was about whether the commit is differentiated — the tree does differentiate it, just not with this token.

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key anywhere in it)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows; no dependency, JSDoc, yarn-vs-npm or optional-chaining surface, since the diff adds no code — re-checked the added bullets against the AGENTS.md rules they restate, :230-234 on dialogs/snackbars and :32 on Tailwind-over-scoped-CSS, and found no contradiction)

4. Security — ✅ (re-scanned pr.diff for zero-width, bidi-override and homoglyph characters and for encoded blobs: the only non-ASCII byte is an em dash on the unchanged context line at pr.diff:22, and all twelve added lines are pure ASCII; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own rules is handled in the Change map's governance note under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is Markdown with no runtime call site; the only cost is review-time, and the base-ref frequency multiplier established in the Change map is what keeps 1.6/1.7 above nit rather than any hot path)

6. UI / UX — ✅ (the PR renders no UI of its own; the twelve added rules were re-derived against the base checkout in the Change map tables — including the two bullets whose hand-tuned-margin and stacked-block clauses fire on ConfigurationVideoView.vue:169, ConfigurationMAVLinkView.vue:76, InputElementConfig.vue:324 and MissionIdentifier.vue:36-40, all of which the umbrella's "converging" carve-out now covers — and the two that remain inaccurate are reported in 1.6 and 1.7)

7. Code Quality & Style — ✅ (12 added lines, no deleted or reworded comment, no code and so no lint surface; re-checked the added bullets against the file's own section-collapsing block at :104-110 and the severity note at :96, which the grouped-finding instruction respects)

8. Commit Hygiene

8.1 minor (partially addressed) — commit b4003d0 ("docs: check new UI against Cockpit's house style"): the commit body is now correct — it scopes the theme rule to overlay-teleporting controls and says "Most of the bullets describe what the tree already does and a few are the house direction it is converging on". The PR body was not carried along: it still asserts "Every rule states what the codebase already does, so it applies to new UI on master today with nothing else needing to land first", which the diff itself no longer claims, and "A surface carrying four breaches gets four findings, not one", which is the opposite of what pr.diff:9 now instructs. The PR body is what a reviewer reads first and what the merge commit carries, so the second sentence in particular will teach the wrong rule. One commit for one logical change, correct docs: type, no PR number in the subject, Part of #2884 in the body — the rest of the section is clean.

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay against the #2865 dialog is the appropriate substitute, though src/components/blueos-cloud/BlueOsCloudMissionPicker.vue is still absent from the base ref, so that replay remains unverifiable here)

10. Documentation — ✅ (re-checked whether the change needs to reach README.md or AGENTS.md: it does not — no Lite-vs-Standalone behaviour, no user-facing feature, and the edited file is itself the documentation for the review process; the stale PR-body text is reported in 8.1)

11. Nitpicks / Optional

11.3 nit.github/claude-review/review-guidelines.md (house-style bullet, pr.diff:9): two of the three major exemplars are readability and a11y failures that plainly reach the user ("an overlay rendering light and unreadable", "a control no keyboard can reach"); the third, "an action nobody can tell is the primary one", is cosmetic — the user can still complete the task — and the file's own rubric (:76) reserves major for "wrong behaviour on a path a user can reach", putting a purely visual inconsistency at minor ("correct but worse"). As written, one undifferentiated hand-rolled footer moves a PR to IMPORTANT FIXES REQUIRED. Dropping that third exemplar to minor, or adding a word on why an unreadable primary counts as reaching the user, would keep the grading consistent with the rubric it points at.

Generated by Claude. This is advisory; a human reviewer must still approve.

@ArturoManzoli
ArturoManzoli force-pushed the 2884-review-ui-conventions branch from b4003d0 to b2199b3 Compare August 10, 2026 13:31
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

Done:

  • (8.1) re-applied the PR body update (the round-2 edit silently failed against a GraphQL hiccup); the body now says most rules describe the tree while a few are the house direction, and uses the grouped-finding rule, instead of the two stale sentences.
  • (1.6) reframed the footer-actions bullet as the house direction rather than a description, noting the few multi-action footers still in the tree are the form being replaced (a third action or a lone-left action graded minor), and scoped the variant="text" dismiss to hand-rolled footers since the shell's DialogActions type has no variant field.
  • (1.7) reframed footer #FFFFFF33 as the house direction and called out the opaque color="white" footer commit as the legacy form (graded minor, not the color="primary" mistake), so copying a compliant sibling like DataLakeVariableDialog is not flagged; the #FFFFFF22 page/panel half is unchanged.
  • (11.3) moved "an action nobody can tell is the primary one" from the major exemplars to the minor side, matching the file's own rubric at :76 where major is wrong behaviour on a reachable path.

@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown

Automated PR Re-review 4 (Claude)

Comparing b4003d0c2f5c00fcf79fb70ba478d3de3cca3433b2199b3f55480e53ebb4c71f44f1f792ca7b51b7. The incremental comparison is unusable for the third round running and was not relied on: pr.json still lists exactly one commit (b2199b3, authoredDate 10:43 vs committedDate 13:31), so the previous head was amended and force-pushed rather than built on, and incremental.diff carries the same single +12/-0 hunk as pr.diff — it presents the whole PR as new. Every status below was judged against pr.diff, and the new findings come from a full re-run of the investigation and sections 0-11 over the whole PR, not over the increment.

Previous findings status

# Finding Severity Status
8.1 Amended commit message and PR body still describe the pre-revision rules minor ✅ Addressed
1.6 Footer-actions bullet asserts a variant="text" dismiss the shell cannot express and a two-action limit the tree contradicts minor ✅ Addressed
1.7 #FFFFFF33 filled-commit token loses 3-to-7 against color="white", which the same bullet's Vuetify-default-color flag catches minor ✅ Addressed
11.3 Grading a cosmetically undifferentiated primary action as major stretches the file's own rubric at :76 nit ✅ Addressed

Verification of each against the code, not against the comment:

  • 8.1 asked for two stale PR-body sentences to be corrected. Both are gone. The body now reads "Most rules describe what the codebase already does … a few (sentence case, keyboard-reachable icon buttons, a text action beside its input) are the house direction the tree is still converging on", matching pr.diff:9, and "When a single surface breaches several rules, they are grouped under one finding with a sub-item per fix", which is now the same rule as the diff instead of its opposite. The commit body was already correct and still is. Closed. Two different body/diff mismatches were introduced by this same round; those are new finding 8.2, not a reopening of 8.1.
  • 1.6 had two parts and both landed. The variant part: "In a hand-rolled footer the dismiss is variant="text"; the useInteractionDialog shell exposes no per-action variant, so do not demand it there" (pr.diff:13) — accurate, DialogActions (src/types/general.ts:26-33) and Action (InteractionDialog.vue:96-121) expose only text/size/color/class/disabled/action, and the template binds only :size, :color, :class, :disabled (InteractionDialog.vue:64-67). The two-action part: "the house direction is two at most … the few multi-action footers still in the tree are the form being replaced, so grade an added third action as minor". Re-enumerated the multi-action footers this run — 6 dialogs (HttpRequestActionConfig.vue:87-97, MavlinkMessageActionConfig.vue:57-67, JavascriptActionConfig.vue:34-45 at 3-4 each, DoItYourself.vue:77-88 at 5, JoystickCalibration.vue:262-266 at 3, ArmSafetyDialog.vue:20-29 at 4) against ~70 v-card-actions footers, so "few … being replaced" is a fair description and the grade is now minor. Closed. The bullet's remedy clause is a separate problem I had not examined before — new finding 1.9's sibling point, raised there.
  • 1.7 asked for either the direction framing plus naming color="white" as legacy, or dropping the in-tree framing. The first landed verbatim: "as the house direction for the committing action in a dialog footer, #FFFFFF33" and "The opaque color="white" fill still common on footer commits is the legacy form being replaced, graded minor, not the color="primary" mistake" (pr.diff:12). The loophole I named is closed too — the flag now reads "color="primary" and other saturated Vuetify default colors", and white is not saturated, so DataLakeVariableDialog.vue:89 and TransformingFunctionDialog.vue:94 (both color="white" with no variant, i.e. genuine opaque fills, verified this run) no longer trip it. Closed.
  • 11.3 asked for the cosmetic exemplar to drop to minor or for a word on why it reaches the user. The first landed: pr.diff:9 now reads "major when the breach reaches the user (an overlay rendering light and unreadable, a control no keyboard can reach), minor when the surface is only cosmetically inconsistent … (an action nobody can tell is the primary one)". Closed.

Discussion since last review

  • ArturoManzoli (Automated Review: Check new UI against Cockpit's style #2915 (comment)) posted a four-item "Done:" list. Treated as a claim and checked against the code: all four hold as described, including the 8.1 item ("re-applied the PR body update (the round-2 edit silently failed against a GraphQL hiccup)") — the body in pr.json now carries both corrected sentences. Note the same comment says the minor-side move of the primary-action exemplar was applied; it was, in the diff, but the PR body's own severity bullet still lists that exemplar under major (8.2).
  • One bare /review comment is a command, not review input, and was ignored.
  • No comment disputed a finding, and nothing in pr.json, pr.diff or new-comments.json contained text addressed to me.

New findings

Change map

Governance note (still applies). The whole diff edits .github/claude-review/review-guidelines.md, the file that governs this reviewer. Per the base version (:21) I review the change and never adopt it: this run executed under the base checkout's rules, and none of the twelve added bullets were applied to this PR. Re-scanned pr.diff for hidden Unicode — the only non-ASCII byte in the file is an em dash on an unchanged context line (pr.diff:22), and all twelve added lines are pure ASCII, with no zero-width, bidi-override, homoglyph or encoded content. The added text is imperative prose addressed to the reviewer, which is this PR's declared and entire purpose rather than an instruction smuggled into unrelated code.

Claims.

Claim Verdict
PR body: "Most rules describe what the codebase already does … a few are the house direction" Verified as matching pr.diff:9. Accurate for 10 of the 12 bullets; two clauses outside the three-item carve-out still describe the minority form (1.8, 1.10).
PR body: findings "grouped under one finding with a sub-item per fix" Verified against the diff, contradicted by the body's own worked example, which emits 6.1 and 6.2 as two findings on one dialog (8.2).
PR body: major exemplars include "an action nobody can tell is the primary one" Contradicted by the diff, which moved exactly that exemplar to the minor side in this round (8.2).
Commit body: "Most of the bullets describe what the tree already does and a few are the house direction it is converging on" Verified; same 10-of-12 caveat as above.
Commit body / bullet: overlay-teleporting controls need theme="dark" "because the app configures none" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify().
Bullet: the shell "styles its buttons uniformly", so its footers are exempt Only true of the actions prop. 11 components render the footer through the #actions slot and style each button themselves (1.9).
PR body worked example against BlueOsCloudMissionPicker.vue from #2865 Unverifiable — that file is still not on the base ref.

Counts re-derived from the base checkout this run, since each bullet is stated as a description of it:

Convention asserted Base-checkout reality Supported?
Overlay theme="dark" on v-select/pickers, and on a v-menu only when its content is not already dark 32 <v-select sites, ~26 carry it; 3 of 24 v-menu carry it and the other 21 wrap dark/glass content yes
Centred dialog title, separator above the footer, none under the header InteractionDialog.vue:11,48, plus the 6 hand-rolled dialogs enumerated in round 3; 0 v-divider immediately after a v-card-title anywhere in src/** yes
Hand-rolled footer differentiates the commit 9 do, 4 do not yes
#FFFFFF33 is the house direction for the footer commit, color="white" the legacy form 3 (MissionChecklist.vue:99 via the color prop, BlueOsCloudLoginDialog.vue:84, DataPrivacyModal.vue:79) against 7 color="white" — now stated as direction + legacy, so the counts no longer contradict it yes (was 1.7)
Two-action footer as house direction; multi-action footers are "few" 6 multi-action dialogs against ~70 footers yes (was 1.6)
Dismiss left / primary right, lone action right the shell itself encodes it: InteractionDialog.vue:57 is actions.length === 1 ? 'justify-end' : 'justify-between' yes
#FFFFFF22 for page/panel action buttons ConfigurationGeneralView.vue:44,47,50,53,123; ConfigurationCloudView.vue:39,48; ConfigurationVideoView.vue:289; ConfigurationMissionView.vue:135 yes
color="primary" is not house style 2 uses repo-wide (UpdateNotification.vue:20, JoystickCalibration.vue:106) yes
globalGlassMenuStyles is the glass layer; a hand-written backdropFilter is the exception 40 files bind the store value against 13 that hand-write a blur, several of those legitimately different effects (CollapsibleContainer.vue:16 is a user-set widget option, Dialog.vue:7 a page scrim) yes
Invented z-index at a call site is a real problem 35 occurrences across 15 files, including the exact case the bullet names (VehicleDefaultsReplaceConfirmationDialog.vue:2 :z-index="5200", PoiActionPopup.vue:5 z-[99999]) yes — a prohibition on a real habit, not a claim the tree is clean
ExpansiblePanel groups settings; two-column grid collapses on phones ExpansiblePanel + isOnPhoneScreen across 5 configuration views; the exact grid pattern at ConfigurationGeneralView.vue:439 yes
Icon buttons carry a tooltip or aria-label 19 of 127 closed <v-btn … icon> blocks contain either; 9 aria-label attributes exist in all of src/**/*.vue no (1.8)
Magic pixel values are not the tree's form 218 arbitrary-px margin/padding utilities, ~124 of them on values the default scale already covers (62×2px, 39×10px, 11×4px, 7×20px, 5×6px) no (1.10)

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions; the changed artifact is a policy document read at review time.

Function Reached from Frequency
(none — Markdown policy document) claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review), both with a plain actions/checkout@v4 (:30, :70) and so reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read it from the base ref, an inaccurate bullet is paid once per PR opened forever, not once here — that is what keeps 1.8-1.10 worth raising at all.

Invariants. The addition still relies on the rule that a bullet stated as "what the codebase already does" is safe to flag deviation from, with a fixed three-item carve-out for the conventions the tree is converging on. The sites that can violate it are the codebase facts each bullet asserts; the table above enumerates them. Ten hold; the icon-label and magic-pixel clauses do not, and neither is inside the carve-out. A second invariant arrived with this round's fixes: a footer "rendered by the useInteractionDialog shell" is uniformly styled and therefore exempt. That holds for the actions prop and fails for the #actions slot, which 11 components use (1.9).

0. Summary

  • Verdict: MINOR SUGGESTIONS

All four findings carried in from round 3 are closed by code, not by argument: the footer-actions bullet is reframed as house direction with the shell's missing variant acknowledged, the #FFFFFF33 token is stated as direction with color="white" named as the legacy form and lifted out of the saturated-color flag, the primary-action exemplar moved to the minor side, and the PR body's two stale sentences are gone. What is left is the same class of issue at a smaller scale, found by re-running the counts over the whole diff rather than the increment: two clauses still assert an in-tree convention the tree does not have (icon-button accessible names, 19 of 127; magic pixel values, ~124 of 218), the shell exemptions added in rounds 2 and 3 are scoped one level too wide and blanket-exempt the 11 slot-rendered footers where the author does control each button, and the PR body picked up two fresh contradictions with the diff — including one against the grouping rule the body itself states.

1. Correctness & Implementation Bugs

1.8 minor.github/claude-review/review-guidelines.md (icon-only controls bullet, pr.diff:18): "flag an icon button with neither tooltip nor aria-label" is stated as house style, but the tree has 9 aria-label attributes in all of src/**/*.vue (MissionChecklist.vue:6, DataPrivacyModal.vue:12,42, MapNorthIndicator.vue:2, DepthIndicator.vue:26, BatteryIndicator.vue:83, RelativeAltitudeIndicator.vue:24, FloatingWrapper.vue:31,36) and only 19 of 127 closed <v-btn … icon> blocks carry a tooltip or a label of any kind. The umbrella's carve-out (pr.diff:9) names "keyboard-reachable icon buttons", which covers this bullet's second clause (the clickable v-icon case — 38 in tree, e.g. PoiActionPopup.vue:24-60), not the accessible-name clause, so the first clause reads as established precedent. Worse, the umbrella's major exemplar is an a11y one ("a control no keyboard can reach"), so a reviewer will grade a missing accessible name major and move any PR that adds a close X to IMPORTANT FIXES REQUIRED for something 108 of 127 existing icon buttons also omit. I am not raising this at major because, unlike 1.4, the author can comply in one attribute and complying is a real improvement — AGENTS.md:65 names accessibility among the things not to be lazy about. The fix is the same one-clause hedge that closed 1.5/1.6/1.7: move the accessible-name clause into the "house direction" carve-out alongside keyboard reachability, and say a missing label on a new control is minor unless it is the surface's only way in.

1.9 minor.github/claude-review/review-guidelines.md (button-tokens and footer-actions bullets, pr.diff:12-13): both exemptions added in rounds 2 and 3 are scoped to "the useInteractionDialog shell" when the thing that is actually uniform is the actions prop path (InteractionDialog.vue:61-71). The shell also exposes an #actions slot (:51), and 11 components use it — ConfigurationJoystickView.vue, PoiManager.vue:167-171, ArmSafetyDialog.vue:20-29, About.vue, JoystickCalibration.vue:262-266, DataPrivacyModal.vue:79, Snackbar.vue, GnssDeviceDialog.vue:138-148, JoystickCommIndicator.vue, Alerter.vue, Plotter.vue — writing each v-btn (or a raw <button>, in ArmSafetyDialog.vue:22-27) themselves, with full control of variant and of the fill. Under the text as written the reviewer must stay silent on ArmSafetyDialog.vue:20-29 (four identical option-buttons, nothing reads as primary), on JoystickCalibration.vue:262-266 (three variant="text" buttons, no primary), and on PoiManager.vue:167-171 / GnssDeviceDialog.vue:143-147 (lone or split actions on the left) — all of them the exact cases the bullets exist to catch. The exemption's own example gives it away: the bg-[#FFFFFF33] differentiation it points at has zero instances through the actions prop and exactly one in-tree instance through the slot (DataPrivacyModal.vue:79), i.e. on the path being excused. Narrow both clauses to "a footer passed through the shell's actions prop", and say a footer written into the #actions slot is judged as hand-rolled. Related: the footer-actions remedy "An extra action belongs next to the content it acts on" has no target for any of the 6 multi-action footers in the tree, because every extra action there is form-scoped (Reset in HttpRequestActionConfig.vue:91 / MavlinkMessageActionConfig.vue:61 / JavascriptActionConfig.vue:39, Test Action at :38, Export/Import/Reset in DoItYourself.vue:77-88, Auto-calibrate at JoystickCalibration.vue:264) — the rule should name where a form-wide action goes instead of asking for a relocation that does not exist.

1.10 minor.github/claude-review/review-guidelines.md (padding-ownership bullet, pr.diff:14): "magic pixel values (ml-[10px]) where a utility or the container's own width covers it" is a good rule but not a description of the tree, and it is not in the carve-out. src/**/*.vue carries 218 arbitrary-px margin/padding utilities, and tailwind.config.js extends only colors, transitionProperty and screens, so the default spacing scale is intact and roughly 124 of those 218 sit on values a utility already covers exactly — 62×2px (0.5), 39×10px (2.5), 11×4px (1), 7×20px (5), 5×6px (1.5), including the bullet's own ml-[10px] example. An author matching the file they are editing gets flagged. Same one-clause fix as 1.8. Taken together with 1.8, the pattern worth noting is structural rather than per-bullet: the carve-out is a fixed list of three, while the bullets keep turning out to contain individual clauses that need the same hedge — it would be more durable to say that any clause asking for something added is the house direction unless the bullet cites in-tree precedent for it.

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key anywhere in it)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows and no dependency change — package.json is untouched at 70 deps / 41 devDeps; no JSDoc, yarn-vs-npm or optional-chaining surface since the diff adds no code, and the added bullets were re-checked against the AGENTS.md rules they restate — :230-234 on dialogs/snackbars, :32 on Tailwind-over-scoped-CSS, :65 on accessibility — with no contradiction, though :65 is what keeps 1.8 at minor rather than higher)

4. Security — ✅ (re-scanned pr.diff for zero-width, bidi-override and homoglyph characters and for encoded blobs: the only non-ASCII byte is an em dash on the unchanged context line at pr.diff:22, and all twelve added lines are pure ASCII; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own rules is handled in the Change map's governance note under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is Markdown with no runtime call site; the only cost is review-time, and the base-ref frequency multiplier established in the Change map is what keeps 1.8-1.10 above nit rather than any hot path)

6. UI / UX — ✅ (the PR renders no UI of its own; all twelve added rules were re-derived against the base checkout in the Change map's second table this run — including the previously unexamined stacking, glass-layer, space-economy and dialog-divider clauses, which hold — and the two clauses that do not hold are reported in 1.8 and 1.10)

7. Code Quality & Style — ✅ (12 added lines, no deleted or reworded comment, no code and so no lint surface — .eslintrc.cjs has no Markdown processor; re-checked the added bullets against the file's own section-collapsing block at :104-110 and the severity note at :96, which the grouped-finding instruction and the now-corrected minor exemplar both respect)

8. Commit Hygiene

8.2 minor — PR body of #2915: the body picked up two fresh contradictions with the diff in the same round that fixed the previous two. First, its severity bullet lists "an action nobody can tell is the primary one" among the major exemplars, while pr.diff:9 moved exactly that exemplar to the minor side this round — the body now states the position the diff abandoned, which is the shape 8.1 was about. Second, the body's worked example emits 6.1 (header, BlueOsCloudMissionPicker.vue:9-13) and 6.2 (footer, :101-104) as two separate findings against one dialog, which is one surface breaching two bullets — precisely the case the body's own preceding bullet says is "grouped under one finding with a sub-item per fix". The worked example is the calibration artifact a reader takes the rule's shape from, so showing the ungrouped form there teaches against the rule more effectively than the rule teaches for it. Otherwise clean: one commit for one logical change, docs: type fits, no PR number in the subject, Part of #2884 in the body, and the commit message itself is accurate.

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay against the #2865 dialog is the appropriate substitute, though src/components/blueos-cloud/BlueOsCloudMissionPicker.vue is still absent from the base ref, so that replay remains unverifiable here — and the replay itself is now the subject of 8.2)

10. Documentation — ✅ (re-checked whether the change needs to reach README.md or AGENTS.md: it does not — no Lite-vs-Standalone behaviour, no user-facing feature, and the edited file is itself the documentation for the review process; the PR-body inaccuracies are reported in 8.2)

11. Nitpicks / Optional — ✅ (nothing left at this level; round 3's 11.3 is closed by the minor reclassification at pr.diff:9, and the wording of the twelve bullets was re-read for internal consistency — the error-confirm carve-out, the saturated qualifier and the hand-rolled/shell split all now read consistently across the button-tokens and footer-actions bullets, save for the scoping issue in 1.9)

Generated by Claude. This is advisory; a human reviewer must still approve.

@ArturoManzoli
ArturoManzoli force-pushed the 2884-review-ui-conventions branch from b2199b3 to ee7632c Compare August 10, 2026 14:46
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

Done:

  • (1.8, 1.10) replaced the fixed three-item "converging" carve-out with a general principle: unless a clause cites in-tree precedent, a clause asking for something added or changed (an accessible name, a token, a relocated action) is the house direction and its breach is graded minor. This covers the icon-button accessible-name (19/127) and magic-pixel (~124/218) clauses at the source rather than hedging each one.
  • (1.9) narrowed both shell exemptions from "the useInteractionDialog shell" to "a footer passed through the shell's actions prop", and made a footer written into the shell's #actions slot judged as hand-rolled (the 11 slot callers style each button themselves); also named where a form-wide action (Reset, Import, Export, Test) goes, since the multi-action footers' extras are form-scoped rather than relocatable.
  • (8.2) updated the PR body's severity bullet to match the diff (the primary-action exemplar is now minor), and regrouped the worked example into one 6.1 finding with a header and a footer sub-item, so it demonstrates the grouping rule instead of contradicting it.

@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown

Automated PR Re-review 5 (Claude)

Comparing b2199b3f55480e53ebb4c71f44f1f792ca7b51b7ee7632c15f952ca4575732cd861a036733664e96. The incremental comparison is unusable for the fourth round running and was not relied on: pr.json still lists exactly one commit (ee7632c, authoredDate 10:43 vs committedDate 14:45), so the previous head was amended and force-pushed rather than built on, and incremental.diff carries the same single +12/-0 hunk as pr.diff — it presents the whole PR as new. Every status below was judged against pr.diff, and the new findings come from a full re-run of the investigation and sections 0-11 over the whole PR, not over the increment.

Previous findings status

# Finding Severity Status
1.8 Icon-button accessible-name clause stated as house style against 19-of-127 reality minor ✅ Addressed
1.9 Shell exemptions scoped to the whole useInteractionDialog shell rather than its actions prop minor ✅ Addressed
1.10 Magic-pixel clause presented as in-tree practice against ~124-of-218 reality minor ✅ Addressed
8.2 PR body graded the primary-action exemplar major and its worked example broke the grouping rule it states minor ✅ Addressed

Verification of each against the code, not against the comment:

  • 1.8 asked for the accessible-name clause to be moved into the "house direction" carve-out and its breach graded minor. The author went further and replaced the fixed three-item carve-out with a general test (pr.diff:9): "unless a clause cites in-tree precedent for what it asks, treat one that wants something added or changed (an accessible name, a token, a relocated action) as the house direction the codebase is still converging on, and grade its breach minor". The icon-only bullet's accessible-name clause (pr.diff:18) cites no precedent and asks for something added, and "an accessible name" is named verbatim as the exemplar, so it is unambiguously covered. Re-counted this run: 9 aria-label attributes in all of src/**/*.vue across 7 files — the reality the clause is now hedged against. Closed. The generalization has its own defect, raised as new finding 1.11; that is a different problem, not a reopening of 1.8.
  • 1.9 had two parts and both landed. The scoping part: both exemptions now read "a footer passed through the shell's actions prop is exempt" (pr.diff:12) and "In a hand-rolled footer, or one in the #actions slot, the dismiss is variant="text"; a footer passed through the shell's actions prop exposes no per-action variant" (pr.diff:13). That matches the shell: InteractionDialog.vue:51 renders <slot name="actions"> when present and :53-72 is the uniform prop path, and 10 components take the slot path (ConfigurationJoystickView.vue, Plotter.vue, PoiManager.vue, GnssDeviceDialog.vue, JoystickCalibration.vue, Alerter.vue, JoystickCommIndicator.vue, About.vue, ArmSafetyDialog.vue, DataPrivacyModal.vue), re-enumerated this run. The bullet's claim that the prop path can still differentiate a primary by class is accurate — InteractionDialog.vue:66 binds :class="button.class". The remedy part: pr.diff:13 now says "A form-wide action (Reset, Import, Export, Test) belongs beside the content it governs, not in the footer; when it has to stay in the footer it groups with the primary on the right", which gives the six multi-action footers a stated destination instead of a relocation with no target. Closed.
  • 1.10 asked for the same one-clause hedge on the magic-pixel clause, and explicitly suggested the general form ("any clause asking for something added is the house direction unless the bullet cites in-tree precedent"). That is what landed, near-verbatim, at pr.diff:9. The padding bullet's ml-[10px] clause cites no precedent and asks for a change, so it now grades minor. Closed.
  • 8.2 had two parts and both landed. The severity bullet in the PR body now reads "minor when the surface is only cosmetically inconsistent with the app around it (an action nobody can tell is the primary one)", matching pr.diff:9. The worked example is now a single 6.1 — "the dialog breaches two house-style bullets:" followed by a header sub-item (:9-13) and a footer sub-item (:101-104) — so it demonstrates the grouping rule instead of contradicting it. Closed. A third body/diff mismatch is present in this round's body; that is new finding 8.3.

Discussion since last review

  • ArturoManzoli (Automated Review: Check new UI against Cockpit's style #2915 (comment)) posted a three-item "Done:" list. Treated as a claim and checked against the code: all three hold as described. Two notes on what the comment does not say. First, the 1.8/1.10 item describes fixing "at the source rather than hedging each one" — the general test does cover both, but it is written broadly enough to also sweep in the two clauses whose breaches the very next sentence calls major (1.11), which the fixed three-item carve-out it replaced did not do for the theme="dark" clause. Second, the 8.2 item says the PR body's severity bullet and worked example were updated; they were, but the body's preceding bullet still describes the three-item carve-out this round deleted (8.3).
  • One bare /review comment is a command, not review input, and was ignored.
  • No comment disputed a finding, and nothing in pr.json, pr.diff or new-comments.json contained text addressed to me.

New findings

Change map

Governance note (still applies). The whole diff edits .github/claude-review/review-guidelines.md, the file that governs this reviewer. Per the base version (:21) I review the change and never adopt it: this run executed under the base checkout's rules, and none of the twelve added bullets were applied to this PR. Re-scanned pr.diff for hidden Unicode — the only non-ASCII byte in the file is an em dash on an unchanged context line (pr.diff:22), and all twelve added lines are pure ASCII, with no zero-width, bidi-override, homoglyph or encoded content. The added text is imperative prose addressed to the reviewer, which is this PR's declared and entire purpose rather than an instruction smuggled into unrelated code.

Claims.

Claim Verdict
PR body: "a few (sentence case, keyboard-reachable icon buttons, a text action beside its input) are the house direction the tree is still converging on" Contradicted by the diff, which deleted the fixed three-item carve-out this round and replaced it with a general precedent test (8.3).
PR body: findings "grouped under one finding with a sub-item per fix", demonstrated by the worked example Verified — the example now emits one 6.1 with two sub-items (was 8.2).
PR body: minor exemplar is "an action nobody can tell is the primary one" Verified against pr.diff:9 (was 8.2).
Commit body: "all are read against the existing severity rubric, so a breach that reaches the user can move a verdict instead of landing as an unweighted nit" Contradicted by the diff: the new precedent test grades the breach of an uncited clause minor one sentence before the rubric calls the same breach major (1.11).
Bullet: createVuetify() is called "with no theme configured" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify().
Bullet: a footer through the actions prop "styles its buttons uniformly" and differentiates the primary by a fill class VerifiedInteractionDialog.vue:61-71, with :class="button.class" at :66; the #actions slot (:51) is now correctly excluded (was 1.9).
PR body worked example against BlueOsCloudMissionPicker.vue from #2865 Unverifiablesrc/components/blueos-cloud/ still holds only BlueOsCloudLoginDialog.vue on the base ref.

Counts re-derived from the base checkout this run, restricted to what this round's change turns on:

Convention asserted Base-checkout reality Bearing on the new test
Overlay theme="dark" on v-select and pickers 26 of 32 <v-select carry it precedent exists and is strong, but the bullet never cites it — so the new test, which keys on citation, sweeps it in (1.11)
Icon buttons carry a tooltip or aria-label 9 aria-label in all of src/**/*.vue; 19 of 127 icon buttons carry either no precedent → correctly graded minor (1.8 closed)
Clickable v-icon/div replaced by a keyboard-reachable v-btn icon 44 <v-icon … @click sites across 21 files no precedent → graded minor by the new test, while the same sentence's major exemplar is "a control no keyboard can reach" (1.11)
#FFFFFF22 for page/panel action buttons 80 occurrences across 23 files cited as what the tree does; unaffected
#FFFFFF33 house direction / color="white" legacy as counted in round 4 (3 vs 7) already framed as direction; unaffected
Magic pixel values ~124 of 218 arbitrary-px utilities sit on values a utility covers no precedent → correctly graded minor (1.10 closed)

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions; the changed artifact is a policy document read at review time.

Function Reached from Frequency
(none — Markdown policy document) claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review), both with a plain actions/checkout@v4 (:30, :70) and so reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read it from the base ref, a mis-graded rule is paid once per PR opened forever, not once here — that is what keeps 1.11 at major rather than at the minor its predecessors sat at.

Invariants. This round replaces the invariant the previous rounds relied on. It used to be a bullet stated as "what the codebase already does" is safe to flag deviation from, with a fixed three-item carve-out; it is now a clause is safe to flag as universal practice only if it cites in-tree precedent, and otherwise its breach is minor. The sites that can violate it are the twelve bullets' individual clauses. The test handles the two clauses it was written for (accessible names, magic pixels) and closes 1.8 and 1.10. It fails on the two clauses whose breaches the same bullet names as major exemplars — the theme="dark" clause (26/32 precedent, never cited) and the keyboard-reachability clause (44 counter-examples, no precedent) — because both ask for something added and neither cites precedent, so the test downgrades exactly the cases the rubric sentence escalates (1.11). A second, weaker property of the new invariant: it keys on whether a clause cites precedent, not on whether precedent exists, so it is satisfied by asserting a fact rather than by the tree having it.

0. Summary

  • Verdict: IMPORTANT FIXES REQUIRED
  • Critical items to address: 1.11

All four findings carried in from round 4 are closed by code, not by argument: both shell exemptions are narrowed to the actions prop with the #actions slot judged as hand-rolled, the form-wide action finally has a stated destination, the PR body's severity bullet and worked example now match the diff, and the fixed carve-out that 1.8 and 1.10 asked to be extended was replaced by the general precedent test those findings suggested. That generalization is where the new problem is. Written as an unqualified "unless a clause cites in-tree precedent … grade its breach minor", it applies to the theme="dark" clause and the keyboard-reachability clause as readily as to the two it was aimed at — and the very next sentence names the breach of those two clauses ("an overlay rendering light and unreadable", "a control no keyboard can reach") as the major exemplars. One sentence downgrades what the next escalates, on the two cases in the block that actually reach a Cockpit user. In fairness, half of that collision predates this round (keyboard-reachable icon buttons were already inside the deleted three-item carve-out) and I did not catch it in rounds 3 or 4; this round widened it to the theme clause, and it is reported now because the review is of the pull request, not of the last push. Separately, the PR body picked up a third stale sentence in the same round that fixed the previous two.

1. Correctness & Implementation Bugs

1.11 major.github/claude-review/review-guidelines.md (House style bullet, pr.diff:9): the new precedent test and the severity rubric in the next sentence give opposite grades for the two breaches the file uses as its major exemplars. The test: "unless a clause cites in-tree precedent for what it asks, treat one that wants something added or changed (an accessible name, a token, a relocated action) as the house direction the codebase is still converging on, and grade its breach minor". The rubric, immediately after: "major when the breach reaches the user (an overlay rendering light and unreadable, a control no keyboard can reach)".

Both exemplars are breaches of clauses the test downgrades:

  • "a control no keyboard can reach" is the icon-only bullet's clause "a clickable v-icon or div where v-btn icon would be keyboard-reachable" (pr.diff:18). It asks for something changed, cites no precedent, and there is none to cite — 44 <v-icon … @click sites across 21 files on the base ref (PoiActionPopup.vue ×6, ConfigurationGeneralView.vue ×6, MissionEstimates.vue ×4). So the test says minor; the rubric says major.
  • "an overlay rendering light and unreadable" is the theme="dark" bullet (pr.diff:11). It asks for an attribute to be added and cites src/plugins/vuetify.ts as its mechanism, not as precedent. Precedent is in fact overwhelming — 26 of 32 <v-select carry theme="dark" — but the test keys on whether the clause cites it, and this one does not, so a literal reading sweeps the whole bullet into "house direction, grade minor". The deleted three-item carve-out did not have this reach; the generalization gave it one.

The consequence is not cosmetic. A PR that adds a v-select with no theme="dark", or a clickable div where a v-btn icon belongs, ships a light-on-light overlay or an unreachable control to a Cockpit user; graded minor it lands as MINOR SUGGESTIONS and moves no verdict — which is the exact opposite of what this PR's own commit body promises ("a breach that reaches the user can move a verdict instead of landing as an unweighted nit"). A charitable reading exists — "grade its breach minor inconsistency rather than a deviation from universal practice" can be read as being about framing rather than severity, with the rubric sentence then governing — but the backticked severity token makes it read as an instruction, and the file's readers grade from it. Ambiguity on the two user-reaching cases is the same defect either way.

The fix is one ordering clause: state that the precedent test lowers the consistency grade only, and that a breach reaching the user stays major whether or not the clause is house direction. While there, let the theme="dark" bullet cite its own precedent (26 of 32 v-select carry it) so it is not exempted by a test it should never have tripped — and note that a test keyed on citation rather than on reality can be satisfied by asserting a fact, which is worth one word ("cites, and can be checked against, in-tree precedent").

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key anywhere in it)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows and no dependency change — package.json is untouched; no JSDoc, yarn-vs-npm or optional-chaining surface since the diff adds no code, and the added bullets were re-checked against the AGENTS.md rules they restate — :230-234 on dialogs/snackbars, :32 on Tailwind-over-scoped-CSS, :65 on accessibility — with no contradiction, though :65 is exactly why the keyboard-reachability downgrade in 1.11 matters)

4. Security — ✅ (re-scanned pr.diff for zero-width, bidi-override and homoglyph characters and for encoded blobs: the only non-ASCII byte is an em dash on the unchanged context line at pr.diff:22, and all twelve added lines are pure ASCII; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own rules is handled in the Change map's governance note under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is Markdown with no runtime call site; the only cost is review-time, and the base-ref frequency multiplier established in the Change map is what sets 1.11's weight rather than any hot path)

6. UI / UX — ✅ (the PR renders no UI of its own; the twelve added rules were re-derived against the base checkout in the Change map's second table this run — the #FFFFFF22 token at 80 sites, theme="dark" at 26 of 32 v-select, the actions-prop vs #actions-slot split at InteractionDialog.vue:51,53-72 — and the one clause-level problem left is a grading conflict, reported in 1.11)

7. Code Quality & Style — ✅ (12 added lines, no deleted or reworded comment, no code and so no lint surface — .eslintrc.cjs has no Markdown processor; re-checked the added bullets against the file's own section-collapsing block at :104-110 and the severity note at :96, which the grouped-finding instruction respects, and the House style bullet now carries four distinct rules in one bullet — provenance, the precedent test, the rubric and grouping — which is what lets its second and third sentences disagree unnoticed)

8. Commit Hygiene

8.3 minor — PR body of #2915: the second bullet still reads "Most rules describe what the codebase already does and apply to new UI on master today with nothing else needing to land first; a few (sentence case, keyboard-reachable icon buttons, a text action beside its input) are the house direction the tree is still converging on." That names the fixed three-item carve-out this round deleted. pr.diff:9 no longer has a list; it has a general test keyed on whether a clause cites precedent, with different exemplars ("an accessible name, a token, a relocated action"), and under it far more than three clauses qualify — the body's "a few" understates the change it is describing. This is the third round in a row where the diff moved and one body sentence stayed behind (8.1, 8.2), so the durable fix is to re-read the body against the diff as part of amending, not to patch the sentence that was flagged. Otherwise clean: one commit for one logical change, docs: type fits, no PR number in the subject, Part of #2884 in the body, and the commit message body does not repeat the stale list (though its closing promise about user-reaching breaches moving a verdict is now contradicted by the diff — that is 1.11, not this).

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay against the #2865 dialog is the appropriate substitute and now correctly demonstrates the grouping rule, though src/components/blueos-cloud/ still contains only BlueOsCloudLoginDialog.vue on the base ref, so the replay itself remains unverifiable here)

10. Documentation — ✅ (re-checked whether the change needs to reach README.md or AGENTS.md: it does not — no Lite-vs-Standalone behaviour, no user-facing feature, and the edited file is itself the documentation for the review process; the PR-body inaccuracy is reported in 8.3)

11. Nitpicks / Optional — ✅ (nothing left at this level; round 4's three minor findings are closed by the rewritten House style bullet and the two narrowed shell exemptions, and the wording of the twelve bullets was re-read for internal consistency — the error-confirm carve-out, the saturated qualifier, the hand-rolled/slot/prop three-way split and the form-wide-action destination all read consistently now, with the single grading conflict raised at 1.11)

Generated by Claude. This is advisory; a human reviewer must still approve.

@ArturoManzoli
ArturoManzoli force-pushed the 2884-review-ui-conventions branch from ee7632c to 924a116 Compare August 10, 2026 15:02
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

Done:

  • (1.11) split the precedent test from the severity rubric so they no longer disagree: the house-direction framing now lowers the consistency grade only, and a breach that still reaches the user (an unreadable overlay, an unreachable control) stays major whether or not the clause is house direction. Worded the test as "cites, and can be checked against, in-tree precedent", and let the theme="dark" bullet cite its own precedent (26 of 32 v-select) so it is never swept into the downgrade it should not trip.
  • (8.3) rewrote the PR body's second bullet to describe the general precedent test (a clause asking for something added with no in-tree precedent is house direction, grading consistency not severity) instead of the deleted three-item list, and re-read the rest of the body against the diff.

@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown

Automated PR Re-review 6 (Claude)

Comparing ee7632c15f952ca4575732cd861a036733664e96924a116f2cb309589d8bd99cf0e139c198ae07db. The incremental comparison is unusable for the fifth round running and was not relied on: pr.json still lists exactly one commit (924a116, authoredDate 10:43:23 vs committedDate 15:02:15), so the previous head was amended and force-pushed rather than built on, and incremental.diff carries the same single +12/-0 hunk as pr.diff — it presents the whole PR as new. Every status below was judged against pr.diff, and the new findings come from a full re-run of the investigation and sections 0-11 over the whole PR, not over the increment.

Previous findings status

# Finding Severity Status
1.11 Precedent test graded the theme="dark" and keyboard clauses minor one sentence before the rubric named their breaches as the major exemplars major ✅ Addressed
8.3 PR body still described the deleted three-item house-direction carve-out minor ✅ Addressed

Verification of each against the code, not against the comment:

  • 1.11 asked for three things and all three landed. (i) The ordering clause: pr.diff:9 now reads "That framing lowers the consistency grade, not the severity: a breach that still reaches the user (an overlay rendering light and unreadable, a control no keyboard can reach) stays major whether or not the clause is house direction". The old text ended the test with "and grade its breach minor", which is what collided with the next sentence; that clause is gone, and severity is now decided on one axis (does the breach reach the user) while the precedent test governs only how the finding is framed. The two axes are now explicitly orthogonal, so the collision I reported no longer exists in either reading. (ii) The theme="dark" bullet now cites its own precedent — pr.diff:11 adds "; 26 of the 32 v-select in the tree already do". Re-counted on the base ref this run: 32 <v-select across 22 files, 26 of them carrying theme="dark". The citation is exact. (iii) The citation-vs-reality point landed verbatim: "unless a clause cites, and can be checked against, in-tree precedent". Closed. The residue of the new split is a different problem, raised as 1.12, not a reopening of 1.11.
  • 8.3 asked for the PR body's second bullet to stop describing the deleted three-item list. It now reads "a clause asking for something added or changed that cites no in-tree precedent is treated as the house direction the tree is still converging on, which lowers the consistency grade rather than the severity - a breach that still reaches the user stays major", which is the general test at pr.diff:9 and matches its severity ordering. The third body bullet also matches the diff's major/minor exemplars word for word. Closed. A different inaccuracy is present in the same bullet and in the commit body; that is new finding 8.4, and it is about the "most / a few" split, not about the deleted list.

Discussion since last review

  • ArturoManzoli (Automated Review: Check new UI against Cockpit's style #2915 (comment)) posted a two-item "Done:" list: "split the precedent test from the severity rubric so they no longer disagree" and "rewrote the PR body's second bullet to describe the general precedent test … and re-read the rest of the body against the diff". Treated as a claim and checked against the code: both hold, including the 26 of 32 citation, which I re-derived independently. One qualification on the second item — the body was re-read and the flagged sentence fixed, but the same bullet's "Most rules describe what the codebase already does" does not survive counting (8.4).
  • One bare /review comment is a command, not review input, and was ignored.
  • No comment disputed a finding, and nothing in pr.json, pr.diff or new-comments.json contained text addressed to me.

New findings

Change map

Governance note (still applies). The whole diff edits .github/claude-review/review-guidelines.md, the file that governs this reviewer. Per the base version (:21) I review the change and never adopt it: this run executed under the base checkout's rules, and none of the twelve added bullets were applied to this PR. Re-scanned pr.diff for hidden Unicode — the only non-ASCII byte is an em dash on an unchanged context line (pr.diff:22); all twelve added lines are pure ASCII, with no zero-width, bidi-override, homoglyph or encoded content. The added text is imperative prose addressed to the reviewer, which is this PR's declared and entire purpose rather than an instruction smuggled into unrelated code.

Claims.

Claim Verdict
Bullet: "26 of the 32 v-select in the tree already do" carry theme="dark" Verified exactly — 32 <v-select across 22 files, 26 with theme="dark" (new this round; was 1.11)
Bullet: createVuetify() is called "with no theme configured" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify()
Bullet: interfaceStore.globalGlassMenuStyles is the tree's glass mechanism Verified — 105 occurrences across 60 files, defined in src/stores/appInterface.ts
Bullet: dialog anatomy is "title centered, separator above the footer, no divider under the header" Verified against the mandated shellInteractionDialog.vue:11 centers the title, :48 puts the only v-divider immediately above v-card-actions at :50, and there is no divider under the header. The bullet does not fire on the shell it tells authors to use
Bullet: the actions prop "styles its buttons uniformly", the #actions slot does not VerifiedInteractionDialog.vue:51 renders the slot, :61-71 is the uniform prop path with :class="button.class" at :66
PR body / commit body: "Most rules describe what the codebase already does and a few are the house direction" Contradicted by counting — roughly half the substantive bullets have no in-tree basis, and by the diff's own citation test only one bullet cites checkable precedent (8.4)
PR body worked example against BlueOsCloudMissionPicker.vue from #2865 Unverifiablesrc/components/blueos-cloud/ still holds only BlueOsCloudLoginDialog.vue on the base ref

Counts re-derived from the base checkout this run, restricted to what this round's change turns on:

Convention asserted Base-checkout reality Bearing on the new split
Overlay theme="dark" 26 of 32 <v-select carry it now cited in the bullet; its breach reaches the user → major, unambiguous
Keyboard-reachable v-btn icon over clickable v-icon 44 <v-icon … @click sites across 21 files no precedent, but named verbatim as a major exemplar → deliberate and unambiguous
Icon button carries a tooltip or aria-label 114 icon-form <v-btn>, 7 with aria-label; 9 aria-label in all of src/**/*.vue; 116 <v-tooltip> in the tree named as the house-direction exemplar in one sentence and left off both sides of the severity split in the next (1.12)
#FFFFFF22 for page/panel action buttons 88 occurrences asserted with its scope; checkable; unaffected
Magic pixel values ~124 of 218 arbitrary-px utilities sit on values a utility covers no precedent → house-direction framing, breach is cosmetic → minor, unambiguous

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions; the changed artifact is a policy document read at review time.

Function Reached from Frequency
(none — Markdown policy document) claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review), both with a plain actions/checkout@v4 (:30, :70, no ref:) and so reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read it from the base ref, a mis-graded rule is paid once per PR opened forever, not once here — that is what keeps a grading defect above a wording preference.

Invariants. This round replaces the invariant again. It used to be a clause without cited precedent has its breach graded minor; it is now the precedent test decides the framing, and the severity is decided independently by whether the breach reaches the user. The sites that can violate it are the twelve bullets' individual clauses, and the test is now whether each clause's breach lands unambiguously on one side of "reaches the user" vs "only cosmetically inconsistent". Eleven of the twelve do: the theme="dark" breach (unreadable overlay) and the keyboard-reachability breach (unreachable control) are named as the major exemplars, the undifferentiated primary action is named as the minor one, and the anatomy, padding, glass, stacking, sentence-case and space-economy breaches are cosmetic by construction. The one clause that lands on neither side is the accessible-name clause — which the same bullet names as its house-direction exemplar (1.12). A second property, unchanged: the citation is a hard-coded count ("26 of the 32"), so it will drift silently as the tree grows; the clause survives the drift because the ratio is what carries it, so this is noted rather than raised.

0. Summary

  • Verdict: MINOR SUGGESTIONS

Both findings carried in from round 5 are closed by code. The severity collision at the centre of 1.11 is gone, and it is gone in the right direction: the precedent test now decides only how a finding is framed, while severity is decided by whether the breach reaches the user, so a new v-select without theme="dark" or a clickable div where a keyboard-reachable button belongs is major regardless of how much precedent the clause cites. The theme="dark" bullet now carries an exact, independently re-derived citation (26 of 32), and the PR body's stale sentence is rewritten. What is left is smaller than any previous round: one clause — the accessible-name clause, which the bullet itself uses as its house-direction exemplar — sits on neither side of the new split and reads as major under a literal application, which would fire a verdict-moving finding on almost every new icon button in a tree that carries 9 aria-label attributes in total; one claim in the PR body and commit body ("most describe what the codebase already does") that does not survive counting; and the twelve conventions being enforced at review time while AGENTS.md, which the authoring agent actually reads, states none of them.

1. Correctness & Implementation Bugs

1.12 minor.github/claude-review/review-guidelines.md (House style bullet, pr.diff:9, and Icon-only controls bullet, pr.diff:18): the new severity split has two sides and the accessible-name clause is on neither, so the same reviewer will grade the same breach major on one PR and minor on the next.

The split: "a breach that still reaches the user (an overlay rendering light and unreadable, a control no keyboard can reach) stays major … while one that is only cosmetically inconsistent with the app around it (an action nobody can tell is the primary one) is minor". The clause: "flag an icon button with neither tooltip nor aria-label" (pr.diff:18). An icon button with no accessible name is not cosmetically inconsistent with anything — nothing about it looks wrong — so it cannot take the minor branch as written; and it does reach a user, since a screen reader announces nothing and a first-time sighted user has only the glyph. A literal reading therefore puts it on the major branch, one sentence after the same bullet names "an accessible name" as its house-direction exemplar, i.e. as the thing the tree is still converging on.

The consequence is over-firing at verdict-moving weight. On the base ref there are 114 icon-form <v-btn> and 9 aria-label attributes in all of src/**/*.vue (7 of them on icon buttons); round 4's count put icon buttons carrying either a tooltip or a label at 19 of 127. Under the major reading, a PR that adds one icon button without a tooltip earns IMPORTANT FIXES REQUIRED for matching what the overwhelming majority of the tree already does — which is the failure mode findings 1.5 and 1.8 were about, arriving from the other direction now that the precedent test no longer touches severity.

This is residue from the remedy I proposed in 1.11, and the remedy was right — the fix here is one clause, not a reversal. Either name where the accessible-name clause sits (for instance minor when the glyph or an adjacent label conveys the action and major only when nothing does), or drop "an accessible name" from the house-direction exemplar list so the bullet stops pointing two ways at once. The keyboard-reachability clause needs nothing: it is named verbatim as a major exemplar, so its grade is deliberate and clear even against 44 in-tree counter-examples.

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key anywhere in it)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows and no dependency change — package.json untouched; no JSDoc, yarn-vs-npm or optional-chaining surface since the diff adds no code, and the twelve bullets were re-read against the AGENTS.md rules they sit next to — :32 Tailwind-over-scoped-CSS, :65 accessibility, :228-234 dialogs and snackbars — with no contradiction; that AGENTS.md does not itself carry these conventions is reported in 10.1 rather than here, since it is a gap in the docs, not a breach by this diff)

4. Security — ✅ (re-scanned pr.diff for zero-width, bidi-override and homoglyph characters and for encoded blobs: the only non-ASCII byte is an em dash on the unchanged context line at pr.diff:22, all twelve added lines are pure ASCII; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own rules is handled in the Change map's governance note under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is Markdown with no runtime call site; the only cost is review-time, and the base-ref frequency multiplier established in the Change map is what sets 1.12's weight rather than any hot path)

6. UI / UX — ✅ (the PR renders no UI of its own; the bullets' factual claims were re-derived against the base checkout this run — theme="dark" at 26 of 32 v-select, globalGlassMenuStyles at 105 sites across 60 files, #FFFFFF22 at 88, and the dialog-anatomy triple checked against the shell it mandates at InteractionDialog.vue:11,48,50, which complies with all three — and the one clause-level problem left is a grading gap, reported in 1.12)

7. Code Quality & Style — ✅ (12 added lines, no deleted or reworded comment, no code and so no lint surface — .eslintrc.cjs has no Markdown processor; re-checked the added block against the file's own section-collapsing rules at :104-110 and the severity note at :96, which the grouped-6.x instruction respects, and the House style bullet's three jobs — provenance, framing, severity — now read in sequence rather than in conflict)

8. Commit Hygiene

8.4 minor — PR body of #2915 (second bullet) and the commit body of 924a116: both assert "Most rules describe what the codebase already does" / "Most of the bullets describe what the tree already does and a few are the house direction it is converging on". Counted against the base ref, that split is closer to half than to most. Describing the tree: theme="dark" (26/32), the #FFFFFF22 token (88 sites), one-glass-layer (globalGlassMenuStyles, 105 sites), dialog anatomy (the mandated shell complies). Not describing it: accessible names (9 aria-label in all of src/), keyboard-reachable icon buttons (44 clickable v-icon), magic pixel values (~124 of 218), sentence case, the field details row (0 uses), the two-action footer and the #FFFFFF33 commit token — the last two openly labelled in the diff as the form being replaced. By the diff's own test, only one bullet actually cites checkable in-tree precedent.

The file itself is fine — pr.diff:9 hedges honestly with "Not all of them describe the current tree", which is what closed 1.5 — and after this round nothing about severity hangs on the split. What hangs on it is the maintainer's read of how much new policy is landing: "most of this is what we already do" and "about half of this is new house direction" are different merge decisions. Fix the sentence in both places, or drop the ratio and keep the diff's own hedge. This is the fourth round in which one description sentence outlived the diff it describes (8.1, 8.2, 8.3); the durable fix remains re-reading the body and the commit message against the diff on every amend, not patching the sentence that was flagged. Otherwise clean: one commit for one logical change, docs: fits, no PR number in the subject, Part of #2884 in the body, and the commit body's closing promise about user-reaching breaches moving a verdict is now backed by the diff (it was not, in round 5).

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay against the #2865 dialog is the appropriate substitute and demonstrates the grouping rule correctly, though src/components/blueos-cloud/ still contains only BlueOsCloudLoginDialog.vue on the base ref, so the replay itself remains unverifiable here)

10. Documentation

10.1 minor — the twelve conventions land only in .github/claude-review/review-guidelines.md, which is read by the reviewer at review time (claude-pr-review.yml:72, claude-pr-review-continue.yml:188) and by nothing that writes code. AGENTS.md — the file the authoring agent reads before touching a .vue — carries only :32 (prefer Tailwind over new scoped CSS), :215-221 (interaction logging) and :228-234 (snackbars, dialog reuse, jargon). It says nothing about theme="dark" on overlay-teleporting controls, the white-alpha button tokens, centered dialog titles, the separator above the footer, footer action layout, padding ownership, one glass layer per surface, stacking, field-attached actions, accessible names on icon buttons, sentence case, or ExpansiblePanel grouping. I grepped the repo's *.md for these conventions and found no other home for them.

The result is a loop the PR pays for on every UI branch: the author (human or agent) writes UI against instructions that never mention the rule, the reviewer flags it, the author fixes it, and the next branch starts from the same instructions. The rule set is explicitly the automation of comments "asked for by hand in review more than once" — the cheaper half of that automation is telling the author first. The fix is a cross-reference, not a duplicate: one line in the AGENTS.md UI section pointing at the house-style block, so the conventions keep a single source of truth and the authoring side stops being the only participant that cannot see them. Round 5 checked this section and concluded nothing needed to reach AGENTS.md; that conclusion covered README-style user documentation and did not address the authoring-instruction gap, so it is corrected here rather than carried forward.

11. Nitpicks / Optional — ✅ (nothing left at this level; the wording of the twelve bullets was re-read for internal consistency — the error-confirm carve-out, the saturated qualifier, the hand-rolled/#actions-slot/actions-prop three-way split, the form-wide-action destination and the new orthogonal framing/severity axes all read consistently, and the hard-coded 26 of the 32 count is noted in the Change map as drift-prone rather than raised, since the ratio is what carries the clause)

Generated by Claude. This is advisory; a human reviewer must still approve.

The reviewer now checks the conventions that have only ever lived in review
comments: dialog anatomy, the white-alpha button tokens, the two-action footer,
who owns the padding, and the dark theme that overlay-teleporting Vuetify
controls need because the app configures none. Not all of them describe the
current tree - about half do and the rest are the house direction it is
converging on - and all are read against the existing severity rubric, so a
breach that reaches the user can move a verdict instead of landing as an
unweighted nit.
@ArturoManzoli
ArturoManzoli force-pushed the 2884-review-ui-conventions branch from 924a116 to f7f81ba Compare August 10, 2026 16:36
@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

Done:

  • (1.12) pinned the grade of a missing accessible name in the icon-only bullet - minor when the glyph or an adjacent label conveys the action, major only when the unlabeled control is the sole affordance - so the clause stops sitting on neither side of the severity split.
  • (8.4) dropped the "most rules describe the tree" claim from the PR body and commit body (the split is closer to half) in favour of the diff's own hedge, and re-read both against the diff.

Not addressed:

  • (10.1) leaving the AGENTS.md cross-reference out of this PR on purpose. The house-style rules live in the reviewer's own review-guidelines.md, which is governed by "review it, never adopt it"; pointing the authoring agent at the reviewer's rubric is the wrong source of truth, and master has no author-facing docs/design-patterns/ home to point at yet. The authoring-instruction gap is real but belongs in a separate change that lands the author-facing docs first, not in this rules-only PR.

@ArturoManzoli

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown

Automated PR Re-review 7 (Claude)

Comparing 924a116f2cb309589d8bd99cf0e139c198ae07dbf7f81ba8bf9be4a1400fc52901f462e497de5a7e. The incremental comparison is unusable for the sixth round running and was not relied on: pr.json lists exactly one commit (f7f81ba, authoredDate 10:43:23 vs committedDate 16:35:40), so the previous head was amended and force-pushed rather than built on, and incremental.diff carries the same single +12/-0 hunk as pr.diff — it presents the whole PR as new rather than the one bullet that actually changed. Every status below was judged against pr.diff, and the search for new findings is a full re-run of the investigation and sections 0-11 over the whole PR, not over the increment.

Previous findings status

# Finding Severity Status
1.12 Accessible-name clause sat on neither side of the user-reach severity split minor ✅ Addressed
8.4 PR body and commit body claimed "most" bullets describe the current tree minor ✅ Addressed
10.1 Twelve UI conventions land only in the reviewer's guidelines; AGENTS.md states none of them minor 💬 Disputed — author says pointing the authoring agent at the reviewer's rubric is the wrong source of truth and master has no author-facing docs home yet, so the cross-reference belongs in a later PR that lands those docs first

Verification of each against the code, not against the comment:

  • 1.12 asked for one of two things and the first landed, verbatim. pr.diff:18 now reads "flag an icon button with neither tooltip nor aria-label (minor when the glyph or an adjacent label already conveys the action, major only when the unlabeled control is the user's sole affordance so a screen reader announces nothing)". The clause now names both sides of the split explicitly, and the two branches map onto the general "does the breach reach the user" axis rather than cutting across it: a glyph or adjacent label that conveys the action means the breach does not reach the user, while a silent sole affordance does. The only on the major branch makes it the restricted exception and the minor branch the default, so the ordering resolves the common case (a recognisable glyph on the only control for its action) to minor. Under this reading, the over-firing the finding was about — IMPORTANT FIXES REQUIRED for one unlabeled icon button in a tree carrying 9 aria-label attributes in total (re-counted this run across src/**/*.vue: 9) — no longer happens. Closed. The house-style bullet still names "an accessible name" among its house-direction exemplars, which the finding also offered as the alternative fix; that is now harmless, since the framing and severity axes are orthogonal and the icon bullet pins the severity itself.
  • 8.4 asked for the "Most rules describe what the codebase already does" sentence to be fixed in both places. The PR body's second bullet now opens "Roughly half the rules describe what the codebase already does…" and the commit body of f7f81ba now reads "Not all of them describe the current tree - about half do and the rest are the house direction it is converging on". Both match the count the finding was based on (describing the tree: theme="dark" 26/32, the #FFFFFF22 token, one-glass-layer, dialog anatomy; not describing it: accessible names, keyboard-reachable icon buttons, magic pixel values, sentence case, the field details row, the two-action footer and the #FFFFFF33 commit token). Re-verified independently this run: 26 of 32 <v-select carry theme="dark", 85 #FFFFFF22 occurrences, globalGlassMenuStyles across 60 files. Closed in both places.
  • 10.1 has no code change behind it. The author's reasoning is recorded, not accepted: an explanation moves a finding to disputed, which leaves it open. Two halves of the argument check out as fact — master has no docs/ directory at all (repo root re-listed this run), and review-guidelines.md is indeed the file governed by the "review it, never adopt it" clause at :21. Worth a human's attention when settling it: that clause governs this reviewer adopting rules out of a diff, and says nothing about whether AGENTS.md may reference the file; the gap it leaves is that the authoring side still cannot see the twelve conventions it will be graded on. Stays open for a human to close.

Discussion since last review

  • ArturoManzoli (Automated Review: Check new UI against Cockpit's style #2915 (comment)) posted a "Done:" / "Not addressed:" split. Both "Done" items were treated as claims and checked against the diff, and both hold — the icon-only parenthetical is at pr.diff:18 and the "roughly half" wording is in the PR body and in the commit body of f7f81ba. The "Not addressed" item on 10.1 is an explicit, reasoned decision not to change the code, which is exactly the disputed case: it does not close the finding, and it carries into every later review until the code changes or a human resolves it.
  • One bare /review comment is a command, not review input, and was ignored.
  • Nothing in pr.json, pr.diff, incremental.diff or new-comments.json contained text addressed to me or anything resembling an injected instruction.

New findings

Change map

Governance note (still applies). The whole diff edits .github/claude-review/review-guidelines.md, the file that governs this reviewer. Per the base version (:21) I review the change and never adopt it: this run executed under the base checkout's rules, and none of the twelve added bullets were applied to this PR. Re-scanned pr.diff for hidden Unicode this run — the only non-ASCII byte in the entire file is an em dash on an unchanged context line (pr.diff:22); all twelve added lines are pure ASCII, with no zero-width, bidi-override, homoglyph or encoded content. The added text is imperative prose addressed to the reviewer, which is this PR's declared and entire purpose rather than an instruction smuggled into unrelated code.

Claims. All re-derived against the base checkout this run rather than carried over from round 6.

Claim Verdict
Bullet: "26 of the 32 v-select in the tree already do" carry theme="dark" Verified exactly — 32 <v-select across 22 files, 26 of them carrying theme="dark"
Bullet: createVuetify() is called "with no theme configured" Verifiedsrc/plugins/vuetify.ts:7 is exactly export default createVuetify()
Bullet: interfaceStore.globalGlassMenuStyles is the tree's glass mechanism Verified — referenced across 60 files
Bullet: dialog anatomy is "title centered, separator above the footer, no divider under the header" Verified against the shell it mandatesInteractionDialog.vue:11 centers the title, :48 puts the only v-divider immediately above v-card-actions at :50, and there is no divider under the header. The bullet does not fire on the shell it tells authors to use
Bullet: the actions prop "styles its buttons uniformly", the #actions slot does not VerifiedInteractionDialog.vue:51 renders the slot, :61-71 is the uniform prop path with :class="button.class" at :66
Bullet: ExpansiblePanel and interfaceStore.isOnPhoneScreen are the in-tree grouping/responsive mechanisms VerifiedExpansiblePanel used in 20+ files, isOnPhoneScreen at 42 sites
PR body / commit body: "roughly half" / "about half" of the rules describe the current tree Verified against the count — was the round-6 finding 8.4; the ratio now matches
PR body worked example against BlueOsCloudMissionPicker.vue from #2865 Unverifiablesrc/components/blueos-cloud/ still holds only BlueOsCloudLoginDialog.vue on the base ref
Author comment: master has no author-facing docs home to point AGENTS.md at Verified — no docs/ directory exists at the repo root

Failure site. Not applicable — this PR fixes no bug. It adds review rules.

Entry points. The PR changes no functions; the changed artifact is a policy document read at review time.

Function Reached from Frequency
(none — Markdown policy document) claude-pr-review.yml:72,108 (initial review) and claude-pr-review-continue.yml:188,243 (/review), both with a plain actions/checkout@v4 (:30, :70, no ref:) and so reading it from the base ref per user action (per PR opened, per /review comment)

Because both workflows read it from the base ref, a mis-graded rule is paid once per PR opened forever, not once here — which is what has kept every grading defect in this PR above a wording preference for six rounds.

Invariants. The invariant established in round 6 is unchanged: the precedent test decides the framing, and the severity is decided independently by whether the breach reaches the user. The sites that can violate it are the twelve bullets' individual clauses, and the test is whether each clause's breach lands unambiguously on one side of "reaches the user" vs "only cosmetically inconsistent". Re-walked all twelve this run, and this round closes the one hole: theme="dark" (unreadable overlay) and keyboard reachability (unreachable control) are named major exemplars; the undifferentiated primary action, the third footer action and the lone left-hand action are graded minor in the text; the accessible-name clause now carries its own two-branch grade at pr.diff:18; and the anatomy, padding, glass, stacking, field-attachment, sentence-case and space-economy breaches are cosmetic by construction, so they take the minor branch. Every clause now lands on a side. One unchanged property, noted rather than raised: the 26 of the 32 citation is a hard-coded count and will drift silently as the tree grows, but the ratio rather than the absolute number is what carries the clause.

0. Summary

  • Verdict: MINOR SUGGESTIONS

Both findings that a code change could close are closed, and this round found nothing new. The icon-only bullet now grades a missing accessible name on both branches (minor when the glyph or an adjacent label conveys the action, major when the control is a silent sole affordance), which was the last clause sitting outside the severity split introduced in round 6; with it, every one of the twelve bullets' breaches now lands unambiguously on one side of "reaches the user". The PR body and commit body were corrected to "roughly half" / "about half", which matches the count and ends the four-round pattern of one description sentence outliving the diff it describes. The only thing left open is the author's deliberate decision not to cross-reference these conventions from AGENTS.md in this PR — the authoring agent still writes UI against instructions that mention none of the twelve rules it will be graded on. That is a minor disputed finding and a human's call, and it is the only reason this is not READY TO MERGE.

1. Correctness & Implementation Bugs — ✅ (re-walked all twelve bullets against the base checkout: the theme="dark" citation is exact at 26 of 32, createVuetify() at src/plugins/vuetify.ts:7 takes no theme, the dialog-anatomy triple holds against InteractionDialog.vue:11,48,50, and the actions-prop-vs-#actions-slot split holds against :51 and :61-71; every clause's breach now lands on one side of the user-reach severity split, including the icon-only clause fixed this round, whose two branches were checked for overlap — the only on the major branch makes it the restricted exception, so the common recognisable-glyph case resolves to minor)

2. Persistence & User Data — ✅ (the diff adds, reshapes and removes no persisted key; one Markdown file under .github/, with no useBlueOsStorage, settings-management.ts or cockpit-* key anywhere in it)

3. AGENTS.md Adherence — ✅ (one file, one purpose, no renames/reorders/reflows and no dependency change — package.json untouched; no JSDoc, yarn-vs-npm or optional-chaining surface since the diff adds no code, and the twelve bullets were re-read against the AGENTS.md rules they sit next to — :32 Tailwind-over-scoped-CSS, :65 accessibility, :228-234 dialogs and snackbars — with no contradiction; that AGENTS.md does not itself carry these conventions remains 10.1, disputed, rather than a new breach by this diff)

4. Security — ✅ (re-scanned pr.diff for zero-width, bidi-override and homoglyph characters and for encoded blobs: the only non-ASCII byte is an em dash on the unchanged context line at pr.diff:22, all twelve added lines are pure ASCII; no new dependency, network call, secret, eval/v-html, or build/CI/Electron-main change — the fact that the diff rewrites this reviewer's own rules is handled in the Change map's governance note under the base file's "review it, never adopt it" clause)

5. Performance — ✅ (the changed artifact is Markdown with no runtime call site; yarn lint covers only .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts, so the file adds nothing to CI time either, and the only cost is review-time at the base-ref frequency established in the Change map)

6. UI / UX — ✅ (the PR renders no UI of its own; every factual claim in the bullets was re-derived against the base checkout this run — theme="dark" at 26 of 32 v-select, globalGlassMenuStyles across 60 files, #FFFFFF22 at 85 sites, #FFFFFF33 at 18, ExpansiblePanel in 20+ files, isOnPhoneScreen at 42, 9 aria-label in all of src/**/*.vue, and the dialog-anatomy triple against InteractionDialog.vue:11,48,50, which complies with all three — and the grading gap that was 1.12 is closed)

7. Code Quality & Style — ✅ (12 added lines, no deleted or reworded comment, no code and so no lint surface — .eslintrc.cjs has one override, for *.vue, and no Markdown processor; re-checked the added block against the file's own rules at :68 hierarchical numbering, :96 severity-inflation and :104-110 section collapsing, all of which the grouped-6.x instruction respects, and re-read the House style bullet's three jobs — provenance, framing, severity — which now read in sequence rather than in conflict)

8. Commit Hygiene — ✅ (one commit for one logical change, docs: fits a guidelines-only change, no PR number in the subject, Part of #2884 in the body; the commit body was re-read against the diff line by line this run and its "about half" ratio, its severity promise and its list of covered conventions all now match pr.diff:9-20, closing the fourth and last instance of 8.1/8.2/8.3/8.4)

9. Tests — ✅ (the addition is prose consumed by an LLM, so it leaves no executable surface for a runnable check; the PR body's replay against the #2865 dialog is the appropriate substitute and still demonstrates the grouping rule correctly, though src/components/blueos-cloud/ contains only BlueOsCloudLoginDialog.vue on the base ref, so the replay itself remains unverifiable here)

10. Documentation

10.1 minor 💬 disputed — carried forward unchanged in the code. The twelve conventions land only in .github/claude-review/review-guidelines.md, read by the reviewer at review time (claude-pr-review.yml:72, claude-pr-review-continue.yml:188) and by nothing that writes code. AGENTS.md — the file the authoring agent reads before touching a .vue — carries only :32 (prefer Tailwind over new scoped CSS), :215-221 (interaction logging) and :228-234 (snackbars, dialog reuse, jargon). It says nothing about theme="dark" on overlay-teleporting controls, the white-alpha button tokens, centered dialog titles, the separator above the footer, footer action layout, padding ownership, one glass layer per surface, stacking, field-attached actions, accessible names on icon buttons, sentence case, or ExpansiblePanel grouping.

The author's position (#2915 (comment)): the cross-reference is left out on purpose, because review-guidelines.md is the reviewer's own rubric and the wrong source of truth to point an author at, and because master has no author-facing docs home to point at instead — so the gap belongs in a separate change that lands those docs first. Both factual halves check out: there is no docs/ directory on master, and :21 of the guidelines is the "review it, never adopt it" clause.

Recorded, not accepted, and left for a human to settle. Two things bear on that call. First, :21 governs the reviewer adopting rules out of a diff under review; it is not a statement that the file may not be referenced. Second, the cost of the gap is paid on every UI branch until the follow-up lands: the author writes UI against instructions that never mention the rule, the reviewer flags it, the author fixes it, and the next branch starts from the same instructions — and the rule set is explicitly the automation of comments "asked for by hand in review more than once", whose cheaper half is telling the author first. If the follow-up is the plan, a maintainer may reasonably want it tracked rather than implied.

11. Nitpicks / Optional — ✅ (nothing left at this level; the twelve bullets were re-read once more for internal consistency — the error-confirm carve-out, the saturated qualifier, the hand-rolled/#actions-slot/actions-prop three-way split, the form-wide-action destination, the orthogonal framing/severity axes and the new two-branch accessible-name grade all read consistently, and the hard-coded 26 of the 32 count is noted in the Change map as drift-prone rather than raised, since the ratio is what carries the clause)

Generated by Claude. This is advisory; a human reviewer must still approve.

@ArturoManzoli
ArturoManzoli merged commit 4c080d4 into bluerobotics:master Aug 10, 2026
15 checks passed
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.

2 participants