Skip to content

fix(history,cu): address remaining bot findings for privacy and daemo…

MacroscopeApp / Macroscope - UI Consistency failed Aug 15, 2026 in 49s

UI Consistency: 3 issues found

Reviewed the changed web UI surfaces (ComputerHistorySettings.tsx, ComputerUseSettings.tsx, ComputerUseMoreBrowsers.tsx, browserBrandIcons.tsx, settingsLayout.tsx, settingsSearch.ts, ComposerPendingApprovalPanel.tsx, MessagesTimeline.tsx). Three consistency issues found, all in apps/web/src/components/settings/ComputerHistorySettings.tsx:

  • L433-L453 (and L487-L499) — The Clear 10 min / hour / day / all actions and the per-item Delete permanently remove events and derived memories but use the neutral outline / ghost variants with no confirmation. Settings elsewhere use destructive-outline for irreversible removals and confirm through the shared AlertDialog (ConnectionsSettings, ProjectSettingsPanel, ThemeSettings).
  • L389-L417 — The exclusions reset is rendered in an ad-hoc right-aligned div below the row instead of SettingsRow's resetAction slot, which every other reset in settings uses; this relocates the affordance and re-implements the row padding.
  • L384 (and L420) — {...searchableSetting(...)} is spread into SettingsSection and its title is then overridden, so the catalog title is discarded and the search label drifts from the visible heading. The existing pattern for an intentionally different heading is id={searchableSetting("...").id} (see SourceControlSettings).

Inline comments with suggested fixes were posted.

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.

Previously flagged issues that are resolved in this revision and were not re-reported:

  • Escape in the inline exclusion editor now calls preventDefault() + stopPropagation() so it no longer dismisses the surrounding privacy dialog (L96-L103).
  • The Mirror to Codex skysight switch now carries disabled={!onDesktop}, matching its sibling switches and the Privacy Manage button (L360).
  • The removable exclusion entry is now a plain list row instead of a Badge overridden with h-auto px-2 py-1 font-normal text-left (L129-L139).
  • The duplicated local RowTitle definitions were consolidated into the exported SettingRowTitle in settingsLayout.tsx, alongside the new shared SettingIconAction (which correctly replaces the repeated size="icon-micro" variant="ghost-muted" call sites).

Other areas checked and found acceptable:

  • browserBrandIcons.tsx renders brand artwork as <img> image targets, not a reconstruction of a core primitive.
  • ExtensionStatus is a local inline status label; it is not a duplicate of ConnectionStatusDot (different geometry and no ping/tooltip contract) and uses the shared bg-success / bg-warning tokens.
  • ComputerUseMoreBrowsers composes Collapsible + SettingsRow children correctly; aria-controls matches the panel id.
  • PrivacyExclusionList uses the core Input and Button primitives with preserved disabled/focus behavior.
  • No CSS/Tailwind ownership, theme-variant, scroll-mask, or virtualized-list changes are present in this PR; class-ordering differences in the new files are cosmetic and were not reported.

🔍 Agent activity — 1 tool call

💭 I'm examining the PR diff to understand what changes were made. This PR is massive, so I'm narrowing my focus to the apps/web/src directory. I need to check if previous comments on ComputerHistorySettings.tsx around lines 101 and 354 were actually resolved, and whether the new changes introduce any additional issues. Let me pull up the list of modified web files to see what I'm working with. The earlier fixes are in place—preventDefault and stopPropagation are now on line 101, the mirrorToCodex switch has the disabled condition, the badge is simplified to a plain row, and RowTitle got consolidated into SettingRowTitle. Now I'm checking the current state of the changed web files for any remaining issues, starting with ComputerHistorySettings.tsx to verify the rem values. I also need to verify that ComputerUseSettings.tsx is using SettingsRow props correctly (status and children), check if ExtensionStatus is duplicated, and confirm those bg-success and bg-warning classes exist. ComputerUseMoreBrowsers.tsx uses SettingsRow with children, so I need to confirm SettingsRow actually accepts children as a prop. The browserBrandIcons.tsx file looks fine with its img elements. Let me pull up settingsLayout.tsx to review SettingIconAction and SettingRowTitle. Looking at the ComputerHistorySettings and ComputerUseSettings files to understand how they're structured, and checking how the searchableSetting helper works—it spreads the id and title, though title can be overridden in specific sections. I'm starting to identify potential consistency issues in how these settings are organized. Now examining the button states and disabled conditions across both files—the timeline and clear buttons use variant="ghost" size="sm" but aren't gated by !onDesktop even though they only appear on desktop anyway. The "Recorder status" refresh button has disabled={busy} but not the desktop check since the status itself is desktop-only. The History section uses a custom flex layout instead of SettingsRow for the clear buttons, which is acceptable but worth noting. The PrivacyExclusionList uses the core Input primitive with SettingIconAction for removal, which looks good. I need to verify whether the design tokens like bg-success, bg-warning, and text-destructive actually exist in the system, and check what Button variants are available. I'm noticing that ExtensionStatus in ComputerUseSettings is creating a status dot with the same styling pattern as the existing ConnectionStatusDot component—using a small rounded circle with success or warning background colors. Let me check if this is duplicating an existing primitive that should be reused instead. ExtensionStatus looks like a minor duplicate—it's just a small inline status label with slightly different sizing than what's already in the codebase. The settings pages already handle status dots in various ways through providerStatus.ts, so I should check if there's an existing settings component that ExtensionStatus is redundantly recreating. Looking at ComputerHistorySettings and ComputerUseSettings, I'm noticing that the "Reveal" and "Delete" buttons in the History section use a ghost variant but aren't being disabled when !onDesktop || busy, whereas the clear buttons in the same section properly handle this condition — that's an inconsistency worth flagging. I'm also checking whether the Input component actually supports the onValueChange prop that's being used, and examining the ComputerUseMoreBrowsers collapsible setup where there's a potential issue with aria-controls — the trigger is manually setting aria-controls to a custom panel id, but Base UI's Collapsible already manages this internally, so passing an explicit id to the panel could cause the trigger's aria-controls to point to the wrong element. Looking at how Base UI's Collapsible.Panel handles IDs — it uses useBaseUiId to generate or register the panel ID, and the Trigger automatically sets aria-controls to that ID. So if I pass an explicit id prop, the aria-controls attribute ends up pointing to the same value anyway, making an explicit aria-controls declaration redundant but harmless. The CollapsibleTrigger's className merges with the Button render prop through Base UI's className merging, so that works fine. I should check if other settings components use Collapsible the same way for consistency, though it's not critical. Now I need to look at how the Input primitive handles onValueChange. Let me pull up the actual ComputerHistorySettings.tsx and ComputerUseSettings.tsx files to see what's really there, since the diff output seems truncated even though it claims to show 521 lines. I'm spotting a couple more issues here. The Delete button in the history list is using variant="ghost" for a destructive action, but the repo convention seems to call for variant="ghost-destructive" or something similar for those kinds of actions. I should verify what button variants are actually available. There's also a prop spreading issue where SettingsSection spreads the title from searchableSetting and then immediately overrides it. I see that searchableSetting returns the item's own id rather than the targetId, and search navigation uses targetId ?? id as the fallback. For "computer-history-enabled", the targetId points to the "computer-history" section, so the pulse focuses the entire section rather than just the row itself—similar to how "color-scheme" works, though here the row has its own matching id that would be the more natural target. Looking at the other items: "computer-history-privacy" and "computer-history-timeline" both use targetIds that match their section ids, which is fine. The Computer Use items mostly work correctly—"computer-use-enabled" and the browser/agent-cursor variants all have matching ids. But there's a potential issue with "computer-use-accessibility" and "computer-use-screen-recording": these rows only render when permissions exist and the user is on desktop, yet the search items exist regardless, so jumping to them fails silently when off-desktop. The entire Permissions section itself is also desktop-only, creating an inconsistency where search can reference items that don't exist in the UI. Now I'm checking whether this is actually a violation by looking at how other settings pages handle section-level ids and shared description components. I want to see if there's a pattern like SettingsSectionDescription that ComputerHistorySettings should be using instead of inline styled paragraphs. I'm noticing the class ordering is inconsistent across the codebase — some components follow a sorted convention while ComputerHistorySettings uses a different order, though this appears to be a harmless inconsistency that shouldn't cause failures. Now I'm wondering if there's a shared component pattern for description text in settings pages, so I'm checking how other settings files like ConnectionsSettings or GeneralSettings structure their descriptive paragraphs to see if there's a reusable pattern I should follow. Now I'm checking the Button primitive to see what variants and sizes are available, particularly looking at whether the "ghost" Delete styling is consistent across the design system and if there's a destructive ghost variant already being used elsewhere for delete actions in settings. Looking at the ComputerUseSettings.tsx file to understand its structure and implementation. I'm noticing an inconsistency in how the master toggles are handled across these settings components. The Computer Use settings allow the main switch to remain enabled even when not on desktop, despite showing a message about remote environments, while the Computer History settings actually disable that same toggle when !onDesktop. Since desktop control settings are persisted server-side and might apply on the host machine, there could be a deliberate reason for keeping the Computer Use toggle editable remotely, but it's creating an odd asymmetry between the two components. Looking at the browsing icons now, I see slight size inconsistencies — the agent cursor icon uses size-6 while the browser icons use size-5. Also checking accessibility: the decorative images in browserBrandIcons have empty alt text which is correct, and the icon placement in SettingRowTitle within the heading looks fine. For the ComputerUseMoreBrowsers section, I'm examining how the SettingsRow sits inside the Collapsible and whether the aria-controls attribute is being set correctly — the CollapsibleTrigger explicitly sets aria-controls="computer-use-more-browsers", but I need to verify if the base UI's Collapsible.Panel is generating its own id properly or if there's a mismatch. I'm noticing a discrepancy between what the diff showed and what's actually at HEAD — the diff indicated ComputerUseSettings was importing and rendering a separate ComputerUseMoreBrowsers component, but the grep at the same commit shows the "more browsers" Collapsible is actually inlined directly in ComputerUseSettings around lines 299-341, so either the diff I'm looking at is stale or there's something off with the comparison. I'm realizing the git_diff and git_grep might be pulling from different revisions or there's a caching issue. Both commands should be using the same commit (7507596), but the imports don't match up — the diff shows a ComputerUseMoreBrowsers import while grep shows a Collapsible import at line 32. Let me view the full file from lines 1-40 and 280-360 to see what's actually there. The git_grep results were pulling from an older revision since the grep tool defaulted to the clone commit rather than the URL ref I passed. My earlier grep searches for things like bg-success might be affected by the same issue, though the ComputerUseSettings.tsx match at lines 60-62 appears consistent with the current head. The inline collapsible component in ComputerUseSettings was extracted to ComputerUseMoreBrowsers.tsx at head, which explains the discrepancy. I need to be more careful about which revision the grep is actually searching — the workspace clone should be at the PR head (7507596), but the grep output showing line 32 for the collapsible import contradicts what I'm seeing in the current view. Let me re-run git_grep for ComputerUseMoreBrowsers to verify whether the file exists in grep's view. Passing the revision explicitly fixes the issue since earlier greps were defaulting to an older commit. Now I'm checking the rest of ComputerUseSettings from lines 198 to 380 at the current head. Looking at the ComputerUseMoreBrowsers component at the current version to see how it's structured with SettingsRow and the CollapsiblePanel children, and checking if there are any issues with the implementation. I'm checking whether the More browsers row's collapsible needs to be gated on desktop.enabled, but since it's just instructions, it should be fine. For the aria-controls attribute pointing to computer-use-more-browsers, I need to verify how Base UI's Collapsible.Trigger and Panel work together — specifically whether the Panel accepts an id prop that gets passed through context so the trigger's aria-controls matches automatically. Either way the manual attribute resolves correctly: if Base UI uses the passed id, it's redundant but harmless; if Base UI generates its own id, the spread props ensure the manual aria-controls points to the actual DOM element. When the panel is closed and unmounted, aria-controls pointing to a nonexistent element is standard Base UI behavior, so that's not a concern. The browserBrandIcons using <img> elements for brand icons is reasonable and doesn't violate the rule against flagging raw elements for image targets. Looking back at the prior findings — the Badge misuse is fixed, the RowTitle duplication is resolved through SettingRowTitle in settingsLayout — so I should check what's changed since the last review to identify any new issues introduced. Since the branch was force-pushed, I need to review the current head from scratch. Looking at the diff, I'm checking for any web-related changes I might have missed across the various files that were modified—assets, component files like ComposerPendingApprovalPanel and MessagesTimeline, settings-related components, and browser configuration files. The path-filtered diff appears complete and accurate based on the commit range, so I can trust what it showed. For MessagesTimeline, the change adds a ShieldIcon and maps "shield" as an icon name, with "wrench" returned for tool work entries. Now I need to examine ComposerPendingApprovalPanel more closely to see if the label additions interact with any color or tone handling based on requestKind that might be inconsistent elsewhere in the component. Checking whether that uppercase pending approval span is new to this change—looking at the merge base, it was already there, so not in scope. The overflow-auto class is also pre-existing. Now I'm comparing the new settings pages against existing ones to spot any UI consistency issues. Looking at how other settings pages handle list rows and actions, I notice ComputerHistorySettings uses custom <li> elements with truncate and ghost buttons instead of the standard SettingsRow component, though that's acceptable since it's displaying data rather than settings. I'm also checking what button variant is typically used for destructive actions in settings lists—I see destructive-outline exists in the repo, so I need to verify whether the Delete buttons with variant="ghost" match the pattern used elsewhere like in ConnectionsSettings. I'm noticing a consistency issue with destructive actions across the settings. The ComputerHistorySettings component uses plain outline or ghost variants for "Delete" and "Clear all" actions, but if the codebase convention is to use a destructive-outline variant for irreversible delete operations, then these buttons should follow that same pattern to maintain consistency. I'm noticing the Computer History page introduces a pattern inconsistency—it uses neutral outline/ghost buttons for destructive actions like "Clear all" and "Delete," while the rest of the codebase consistently applies destructive-outline for similar operations like revoke and delete. This creates a real divergence in how destructive controls are styled, and I'm wondering if this falls under the scope of the variant consistency check. I'd flag this as a single comment on the Clear buttons block, mentioning the Delete action too, with moderate confidence since the destructive variant already exists and serves a purpose. There's also a secondary UX pattern worth noting—destructive settings actions elsewhere typically trigger a confirmation dialog, but "Clear all" and "Delete" here fire immediately. That's more of a UX concern than a UI consistency issue, though I should check if the repo has an established AlertDialog pattern for destructive settings to see if that's worth mentioning alongside the variant inconsistency. I'm noticing the codebase follows a consistent pattern where destructive actions like removing themes or environments trigger an AlertDialog with a destructive-styled confirm button. Let me check how ThemeSettings implements this confirmation flow around lines 992-1003. I've identified a key inconsistency: the ComputerHistorySettings component uses neutral button variants for destructive actions like clearing history and deleting individual items, but these operations lack confirmation dialogs and don't follow the established pattern of using variant="destructive" with AlertDialog for irreversible data removal. The minimal fix is to apply variant="destructive-outline" to the trigger buttons for clarity, then route the irreversible "Clear all" and "Delete" actions through the shared AlertDialog component like ThemeSettings and ConnectionsSettings do. I'll suggest the variant change inline and note the confirmation dialog as the follow-up for truly irreversible operations. I'm also checking other potential issues: the PrivacyExclusionList uses a plain div row which is intentional and acceptable, the panel styling is fine, and I'm examining how SettingResetButton is positioned in the Privacy reset section. There's a real ownership divergence here — the SettingsRow component has a dedicated resetAction slot that reserves space next to the title, and every other settings page uses it, but this PR places the exclusions reset in a custom flex div below the row instead, which misaligns the affordance and duplicates padding. The fix is straightforward: pass the reset as the resetAction prop on the "Excluded apps & websites" row where it belongs. Let me verify whether any other settings pages bypass this slot to confirm this is actually a deviation from the established pattern. I'm noticing that most SettingResetButton components are placed in either resetAction slots within rows or headerAction slots in sections, but the ComputerHistorySettings exclusions reset is an outlier—it's positioned in a standalone right-aligned div instead of following this pattern, which suggests it should be refactored to use the row's resetAction slot like the others. That's the second concrete finding. For the first one, I identified that the destructive variant for Clear/Delete actions needs attention. Looking at a third potential issue: the SettingsSection is spreading searchableSetting("computer-history-privacy") and then overriding its title with title="Privacy", which creates a mismatch—the search catalog shows "Computer History privacy" but the rendered heading displays just "Privacy". The same problem occurs with "computer-history-timeline" showing as "History" in the UI while appearing as "Computer History timeline" in search results. This inconsistency undermines the catalog's purpose as the single source of truth for both anchor IDs and visible titles. The cleanest fix would be to explicitly use id={searchableSetting("computer-history-privacy").id} with title="Privacy" to make the override intentional, though the catalog title would still diverge from what users see. Spreading the object and then overriding a property is dead code that masks this drift—worth flagging as a documentation or design issue. I'm weighing whether to include this as a lower-severity consistency note on lines 384 and 420, but I already have two solid findings that will fail the check. The first one is strong: the Clear buttons are genuinely destructive (they delete events and memories) yet lack the destructive-outline styling and confirmation dialog that the repo convention requires. The per-item Delete buttons also use variant="ghost" inconsistently with that pattern. I'm deciding between posting separate inline comments for the Clear buttons and Delete button, or combining them. To keep noise down while staying precise, I'll post one comment on the Clear button block around line 437 that references the Delete button issue at 487-499, then maybe add the search-title consistency note as a third comment if it seems worth flagging. Now I'm looking at two specific issues: the Clear and Delete buttons use outline and ghost respectively instead of following the destructive pattern seen elsewhere (like in ConnectionsSettings or ThemeSettings with destructive-outline plus AlertDialog), and the reset button is placed in an ad-hoc div rather than using the SettingsRow's resetAction slot. For the second issue, a suggestion would need to span lines 389-417 to restructure how the reset button is positioned. Writing the refactored component... Verifying the indentation for the suggestion on line 435... Writing the replacement code... I'm noticing the PR uses a spread-then-override pattern with {...searchableSetting(...)} title="Privacy" that diverges from the established convention in the codebase, which explicitly uses id={searchableSetting("x").id} alongside the title. This approach silently discards the catalog title, which is worth flagging as a minor consistency issue. I'll add a third comment suggesting the explicit .id pattern for line 384, keeping it brief since the first two comments cover the main concerns. Before finalizing, I'm double-checking that spreading the title prop into SettingsSection and overriding it doesn't cause TypeScript errors—it shouldn't—and verifying that the "computer-history-enabled" spread at line 321 is actually fine since the catalog title matches the intended visible title there. For the first finding about the Clear buttons, I'm reconsidering whether the neutral styling was intentional given the four buttons in a row, but "Clear all" is definitely an irreversible action that warrants destructive styling. I'll suggest at minimum the destructive-outline variant and an AlertDialog confirmation, consistent with how ThemeSettings and ConnectionsSettings handle deletions. The inline suggestion for the variant will apply to all four buttons in the map, which is the desired effect. Now I'm drafting the review comments. The first one addresses the destructive actions needing better visual signaling and confirmation dialogs. The second comment covers the reset button placement in the exclusions row, and the third is about spread/override behavior. I'm preparing the exact suggestion text with proper indentation for the multi-line comment spanning lines 389-417.

1. modify_pr — UI consistency review of the new Computer Use / Computer History settings surfaces. The earlier findings (Escape handling in the inline exclusion editor, disabled={!onDesktop} on the mirror switch, the Badge-as-list-row, and the duplicated RowTitle) are all resolved in this revision. Three remaining consistency issues, all in ComputerHistorySettings.tsx.