Skip to content

fix(web): a superseded write no longer reports a failure

MacroscopeApp / Macroscope - UI Consistency failed Aug 28, 2026 in 18m 23s

UI Consistency: 1 issue found

1 finding in the in-scope web files.

  • apps/web/src/components/pullRequest/usePullRequestFilesViewed.ts (L113-125): the setFilesViewed failure path treats every AsyncResult.Failure as a server rejection. Interrupt-only causes (RPC client scope closing on reconnect or environment teardown) therefore revert the reader's ticks and raise a bare toastManager error toast, diverging from the repo convention for useAtomCommand failures ({ reportFailure: false } + isAtomCommandInterrupted guard + squashAtomCommandFailure description, as in ServerUpdateAction.tsx and useThreadActionMenu.ts). The toast also duplicates the console warn useAtomCommand still emits by default. Inline comment posted with the minimal fix.

Prior-run findings were verified as addressed: the checkbox now carries its own aria-label="Viewed" (label text is free to become "Changed"), the compact-size override on the Checkbox primitive is gone, truncated is threaded through the hook and flagged in the meta line, and the header render props are stabilized through refs so a tick no longer rebuilds every header portal.

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.

In-scope files examined

  • apps/web/src/components/pullRequest/PullRequestCodeTab.tsx
  • apps/web/src/components/pullRequest/usePullRequestFilesViewed.ts
  • apps/web/src/components/pullRequest/pullRequestFilesViewed.logic.ts (+ test)
  • apps/web/src/components/pullRequest/pullRequestDiff.logic.ts (+ test)

Checks that passed

  • Shared primitives: the tick uses ui/checkbox with no geometry/focus-ring/radius overrides; the caveat uses Tooltip/TooltipTrigger render={<span/>}/TooltipPopup, identical to the adjacent pre-existing withheld-diff and commit-scope tooltips in the same meta line. The <label>-wrapping-Checkbox composition matches the existing pattern in ConnectOnboardingDialog.tsx:251-257.
  • Tailwind/token ownership: text-amber-600 dark:text-amber-500 on the new TriangleAlertIcon and the "Changed" text mirrors the neighbouring line in the same component (PullRequestCodeTab.tsx:1170) and the wider pullRequest/* convention; no new global CSS, no theme-variant changes, no filter on app chrome.
  • Diff-viewer shadow DOM / portals: the new header content is rendered through the viewer's slot portal like the existing stat, the header's onClickCapture fold handler is correctly excluded via data-viewed-toggle (and already bails on HTMLButtonElement, which covers the Base UI checkbox button and keyboard-activated clicks), and renderHeaderMetadata keeps a stable identity ([omittedFileStats]) with the tick state read through refs plus a viewedMark folded into each item's version \u2014 so only the file whose tick moved redraws.
  • Environment routing: usePullRequestFilesViewed takes environmentId explicitly and gates the query on detail.capabilities.viewedFiles; no active-environment fallback is introduced.
  • Scroll/virtualization and layout: no mask, overflow-ownership, or virtualizer changes; the new meta-line segment follows the existing shrink-0 + icon-caveat structure.

Verification notes

  • useEnvironmentQuery(null) is a supported disable path, so the capability gate is safe.
  • The serial command scheduler queues rather than interrupts, so the interrupt exposure in the finding comes from transport/environment teardown rather than from overlapping presses.

🔍 Agent activity — 26 tool calls

💭 Looking at the diff, it seems the earlier feedback was addressed—the aria-label is now present, the truncated prop is threaded through, and memoization uses refs instead of unstable identities, with the Checkbox size override removed. Now I want to check the rest of the changed files for any remaining UI consistency issues. I'm reviewing PullRequestCodeTab.tsx, the diff and filesViewed logic files, and the usePullRequestFilesViewed hook, checking that the Checkbox primitive usage is fine, that renderHeaderMetadata's version key properly includes the viewedMark, and tracing through the accessibility behavior around the viewed-toggle label—specifically whether keyboard activation (space key) on the checkbox fires a click event that could get intercepted by the header's capture listener despite the data-viewed-toggle guard. I'm now questioning whether the label actually toggles Base UI's Checkbox, since it renders a button rather than a native input—unlike native inputs, a <label> wrapping a button won't automatically forward clicks to it, so clicking the label text likely won't toggle the checkbox as intended.

1. browse_code — apps/web/src/components/ui/checkbox.tsx

2. git_tools — Checkbox

💭 I'm trying to recall how Base UI's Checkbox.Root handles its hidden native input for form submission, and want to check other call sites to see how labels are wired up there.

3. browse_code — apps/web/src/components/settings/ProviderInstanceCard.tsx

4. browse_code — apps/web/src/components/GitActionsControl.tsx

💭 I should check other call sites like WelcomeWizard and ConnectOnboardingDialog to see how they pair labels with checkboxes.

5. browse_code — apps/web/src/components/cloud/ConnectOnboardingDialog.tsx

6. browse_code — apps/web/src/components/onboarding/WelcomeWizard.tsx

💭 The label-wrapping-Checkbox pattern is already established elsewhere in the repo, so that's not a finding here. Now I want to look at the actual PullRequestCodeTab changes in the current head for full context.

7. git_tools — data-viewed-toggle

💭 Tracing through the composedPath logic, I realize clicking directly on the checkbox button returns early since it's an HTMLButtonElement, so the header stays expanded and the checkbox's own toggle handles the state change via setFileViewed. Now I need to check what happens when the click lands on the label text instead of the checkbox itself. I recall Radix's hidden input uses pointer-events: none, meaning label clicks wouldn't actually target it, so I'm uncertain about the toggle behavior — but since this label-wrapping pattern already exists elsewhere in the repo, it's a pre-existing convention rather than a new issue, so I'll skip it. Now I want to check whether amber colors are used elsewhere in the repo, since the warning styling uses raw palette colors instead of the semantic text-warning token that's already established in the codebase. I'm also looking at other items: the label's cursor/select styling seems fine, and the filesViewed dependency in the items memo is intentional since it drives version-based re-rendering when files get marked viewed. The last thing I'm weighing is whether rendering the tooltip trigger as a non-focusable span hurts keyboard accessibility — but I see the same pattern already used elsewhere in this same file, so it may just be following existing convention rather than being a new problem introduced by this PR. I want to verify that by grepping for existing TooltipTrigger render-as-span usage across the repo. Beyond that, the enabled-gating on the query hook and the environment routing both look correct, and the filePaths memo seems fine too. Now I want to double check the amber color choices against the semantic token system.

8. git_tools — amber-(500|600)

9. git_tools — text-warning|--color-warning|bg-warning

💭 I'm noticing the codebase already uses raw amber colors elsewhere, like in PullRequestDetailPanel and another spot in PullRequestCodeTab around line 1170, which makes me wonder whether that usage predates this diff or falls outside the changed hunks. The line 1170 pattern seems to be pre-existing rather than new, so the code I'm reviewing is actually consistent with adjacent conventions in the same file rather than introducing something novel. I want to verify this by checking the broader 1130-1180 range and looking at how tooltip triggers are typically structured there.

10. browse_code — apps/web/src/components/pullRequest/PullRequestCodeTab.tsx

💭 The truncated tooltip lines up with the existing pattern, so that's good. Next I want to check the items/version memo region and the setFileViewed/refs area to see if the filesViewed dependency in the items memo could be problematic compared to using refs.

11. browse_code — apps/web/src/components/pullRequest/PullRequestCodeTab.tsx

12. browse_code — apps/web/src/components/pullRequest/PullRequestCodeTab.tsx

💭 The renderHeaderMetadata identity issue is resolved through refs with the omittedFileStats dependency. I'm now checking whether reading filesViewedRef.current at render time causes problems—since the ref assignment happens during the render body, this should be safe, and version changes correctly trigger re-renders of that file's header. I'm now tracing how filesViewed is used elsewhere to make sure there's no similar staleness issue. Recomputing items on every press changes their array identity, which cascades to fileKeys and collapsedFileKeys, but this mirrors existing behavior with toggledFiles so it's likely fine. I'm also checking the checkbox sizing in the header (18px/16px depending on breakpoint) against the small metadata text—previously flagged size overrides were removed, so this should be resolved now. I'm digging into whether clicking the label text actually toggles the checkbox, given the stopPropagation and data-viewed-toggle attributes used to prevent the fold from collapsing—this depends on how Base UI's Checkbox.Root wires up its underlying button and hidden input. Base UI renders a visually hidden input alongside the checkbox button, and that hidden input has an onChange handler wired to setChecked, so a click on a wrapping label should activate the hidden input and toggle state correctly without double-firing. Since clicking a button nested inside a label doesn't cause the browser to re-forward activation to the label's target control in modern browsers, this is a pre-existing pattern and not a new concern here. The environment routing with environmentId threading through looks fine, and usePullRequestFilesViewed correctly gates setViewed calls behind the enabled flag. I want to double check the cleanup effect in usePullRequestFilesViewed that depends on scopeKey, since that's where a subtle bug could hide. I trace through how scope.current gets set on mount versus when flush reads it, and it looks consistent since flush reads via a ref rather than a stale closure. The reference prop being a new object each render just means flush is recreated per render but that's fine since it's accessed through a ref. Checking query.refresh stability, theming, and the checkbox styling (cursor-pointer on the label, no cursor class needed on the Checkbox primitive itself) — all consistent with the ConnectOnboardingDialog pattern. Now I'm considering whether having both an aria-label on the checkbox and wrapping label text creates a duplicate announcement issue for screen readers. Since aria-label overrides the label text as the accessible name, the checkbox will announce as "Viewed" while the visible "Changed" text becomes purely decorative and unannounced — a minor inconsistency but not a blocking issue given it was already addressed in an earlier review comment. I also want to check the tooltip trigger rendered as a span with amber styling inside that label, verifying it behaves properly on hover without needing to be a button element. Since the tooltip popup content renders in a portal at the document root, clicking the "Changed" word itself shouldn't interfere with the label's normal behavior of forwarding clicks to the checkbox — that seems intentional and correct. But I want to check where the header actually lives in the DOM structure, since there was a comment about it being inside the viewer's shadow tree. Since PullRequestDiffStat already renders fine there with Tailwind classes, styles must already be handled correctly for that shadow root, and since the tooltip popup portals to document.body by default, its positioning across the shadow boundary should work fine too. Let me check whether the error toast call for viewed files uses the correct API pattern compared to other toast usages, and whether useEnvironmentQuery actually supports being passed null — if it doesn't, that could be a real bug worth flagging.

13. browse_code — In apps/web (or packages/client-runtime), what is the signature of useEnvironmentQuery and does it accept null to disable the query? Also show how toastManager.add is typically called (fields) in apps/web, and the signature of useAtomCommand and whether the returned function resolves to a Result with _tag: "Failure".

💭 I'm wondering if the default failure reporting in useAtomCommand combined with the hook's own toast could cause a duplicate toast, so I want to check what reportAtomCommandResult actually does in runtime.ts—whether it logs or shows a toast itself. I also want to trace the interruption case, since the command scheduler runs serially per key and an interrupted command could behave differently if the component unmounts mid-flight.

14. browse_code — In apps/web/src, show examples of call sites that call a command from useAtomCommand and then inspect result._tag === "Failure" to show an error toast. Do they use isAtomCommandInterrupted or squashAtomCommandFailure before toasting? Also: does reportAtomCommandResult (packages/client-runtime/src/state/runtime.ts) itself display a user-visible toast on failure, or just log? Quote the code.

💭 I'm checking whether the new hook's failure path handles command interruption correctly — it reverts the overlay and shows a toast without checking isAtomCommandInterrupted, so I'm considering whether interruption is even plausible given the command scheduler is serial per key and this fires from a flush. If the environment gets torn down mid-flight (disconnect, or last consumer unmounting), the running effect could get interrupted, which would cause a spurious "Could not update viewed files" toast plus a visible checkbox snap-back — that seems like a real consistency gap compared to how other commands in the repo handle interrupted results and error descriptions.

15. browse_code — In packages/client-runtime/src/state, explain createEnvironmentRpcCommand and the concurrency: { mode: "serial", key } option: does a new command with the same key interrupt an in-flight one, or queue it? Also, under what conditions can these environment RPC commands fail with an interrupt-only cause (e.g. environment teardown, disconnect, registry dispose)? Quote relevant code.

💭 On disconnect/reconnect, a pending setFilesViewed request gets interrupted and the hook reverts the reader's ticks while showing an error toast — inconsistent with the repo's isAtomCommandInterrupted guard convention and missing the failure message. It also lacks reportFailure: false, so a console warn fires alongside the toast. This is a legitimate finding, though it's more about user-facing error consistency than strict UI styling scope. Now I want to check whether genuinely new UI-consistency issues exist. I'm looking at the checkbox in the diff header, which portals into shadow DOM — I need to verify the Tooltip renders correctly there, since Base UI portals to document.body by default, which should keep styling fine, but focus and aria behavior inside a shadow root is worth double-checking. I'm also checking whether other tooltips already exist in the diff header (via renderHeaderPrefix) to see if this pattern was already established, so I'm looking at how StyledDiffCodeView handles header slots.

16. browse_code — apps/web/src/components/pullRequest/PullRequestCodeTab.tsx

17. browse_code — Where is StyledDiffCodeView defined in apps/web? Explain how renderHeaderMetadata / renderHeaderPrefix content is mounted: is it rendered via React portal into the diff viewer's shadow DOM, and how are Tailwind styles applied there? Do any existing header slot renderers use Base UI Tooltip or other portal-based popups inside those slots?

💭 I'm checking whether the header tooltip pattern used elsewhere in DiffPanel applies here — it does, so that's not a concern. But I notice the "Changed" tooltip trigger is a non-focusable span inside a label, which could block keyboard users from reaching it, though similar spans already exist elsewhere in this same file. I confirm the checkbox hit target and click-to-fold handling are fine, since the capture listener already bails out on button elements, so both the checkbox click and Space-key activation are correctly handled without accidentally triggering the fold. Then I notice a wrinkle in the meta line: the existing comment justifies using icons instead of spelled-out text because that strip is too narrow and text truncates to nothing. Adding a "N / M viewed" count text there seems to go against that reasoning, so I want to check the container's overflow behavior to see if this new shrink-0 text element would push out or truncate the existing file-count display.

18. git_tools — export function PullRequestMetaLine

19. browse_code — apps/web/src/components/pullRequest/PullRequestCodeTab.tsx

💭 I'm checking the flex layout structure — since both the meta segment and file-count span are set to shrink-0 within a min-w-0 container, the content will overflow rather than truncate, so I need to reconsider how the left group interacts with the shrink-0 right-side toolbar group under justify-between. Actually, there's a code comment implying items previously "truncated to nothing" on narrow panels, which contradicts the shrink-0 setup I'm seeing now — it's possible that comment refers to an earlier version of the layout, so I'm wary of drawing a firm conclusion here without more concrete evidence of an actual overflow bug. I want to focus on stronger, more confirmable issues instead. Going back through usePullRequestFilesViewed, I'm weighing two real concerns: a failure path that could produce a spurious error toast plus revert on reconnect since it skips checking for interruption, and whether the scope-change effect's cleanup timing could interact badly with pending timers — though that actually seems fine since timers fire after effects run. I'm also checking whether calling setOverlay(NO_OVERLAY) during cleanup on a still-mounted component is safe, which it should be under React 18, and now I'm scrutinizing the settleFileViewedOverlay effect that depends on [states] to see whether an unsettled computation could misfire when a query refresh completes while nothing is actually pending. I'm also examining whether disabling the feature properly hides the checkbox, and whether the fold-on-view behavior intentionally excludes updates that came from the host's own UI or an initial load — that looks like a deliberate design choice rather than a bug. Then I'm checking whether filesViewed being read via ref inside renderHeaderMetadata versus via memo dependency creates any staleness, since the version marker is meant to keep that in sync, and now I'm tracing whether the viewer actually re-invokes renderHeaderMetadata whenever the item version changes. I should narrow the scope to PullRequestCodeTab.tsx, pullRequestDiff.logic.ts, and usePullRequestFilesViewed.ts, keeping in mind that the hook explicitly takes environmentId per the environment routing rule. I also want to check whether that checkbox label with stopPropagation should instead use an existing shared checkbox/label primitive from the ui package.

20. browse_code — apps/web/src/components/ui/*.tsx

21. browse_code — apps/web/src/components/ui/label.tsx

💭 I'm checking whether using a raw label with custom typography classes instead of the Label primitive is consistent with existing patterns—since other components like ConnectOnboardingDialog do the same, I won't flag this as an issue. Now I'm looking at whether the Checkbox nested inside the label has proper height handling. For the labeling question, Base UI's Checkbox.Root actually renders a hidden native <input type="checkbox"> alongside the visible button for form participation and accessibility purposes, which means wrapping it in a <label> should work correctly since the label targets that hidden input rather than the unlabelable button element. That confirms the toast/interrupt finding is likely the main issue to focus on. I want to double-check whether there's a separate problem with the initial loading state causing a "0 / N viewed" count to flash briefly before the real data arrives. That checks out as low risk since the diff itself loads more slowly than the viewed count, so it's unlikely to actually manifest. Now I'm tracing what happens when a user unticks a dismissed file — the overlay marks it unviewed and not stale, flipping the label from "Changed" back to "Viewed" with the checkbox unchecked, and I need to see how the host reacts to that state change. I'm rechecking the earlier concern about renderHeaderMetadata's identity — using refs resolved it, but there's a subtler issue: it reads filesViewedRef.current during portal render, and the header only re-renders when an item's version changes, which is fine since the viewed mark is baked into the version. Still, assigning filesViewedRef.current during render itself is worth scrutinizing for timing issues.

22. git_tools — ^ [a-zA-Z]+Ref.current = [a-zA-Z]

💭 My main finding is the toast/interrupt handling in usePullRequestFilesViewed.ts, so I want to re-read that block with line numbers to comment inline. I'm also noticing a second possible issue: when the revert-on-failure logic resets the checkbox, it doesn't restore the file's fold state that setFileViewed toggled, leaving the file collapsed while the checkbox unchecks—an inconsistency since ticking and folding are meant to be one gesture, but the revert only undoes part of it. I'm weighing whether this fold-state issue is worth flagging alongside the toast finding, since it's minor and arguably acceptable given the reader can expand it themselves; I lean toward focusing primarily on the interrupt/toast issue to avoid over-reporting, though I still see the spurious error toast as a genuine user-facing regression tied to the shared toastManager convention for command failures. I'll flag this as a single inline comment recommending an interrupt guard plus setting reportFailure to false, since the current behavior deviates from the repo's established convention of staying silent on interrupt-caused failures and risks double reporting via both console warning and toast. I should guard with isAtomCommandInterrupted and pass { reportFailure: false } along with a description from squashAtomCommandFailure(result), mirroring the pattern in ServerUpdateAction.tsx. Now I need to find the exact line numbers of the failure block in usePullRequestFilesViewed.ts at HEAD.

23. browse_code — apps/web/src/components/pullRequest/usePullRequestFilesViewed.ts

💭 I'm planning to leave an inline comment on line 123 flagging the interrupt guard, with a suggested diff since the file is new and every line is part of the changeset. I need to track down where the helper functions like isAtomCommandInterrupted and squashAtomCommandFailure are actually exported from before writing the fix.

24. git_tools — import|isAtomCommandInterrupted|squashAtomCommandFailure|useAtomCommand

25. browse_code — apps/web/src/components/ServerUpdateAction.tsx

💭 I'm drafting a review comment explaining that an interrupt-only failure—like a reconnect or teardown closing the RPC scope mid-flush—gets misread as a real _tag === "Failure", causing the UI to snap back ticks and show a bare error toast for something the server never actually rejected. I'm working through the fix logic now, weighing whether to return early on isAtomCommandInterrupted before both the overlay revert and toast, or only skip the toast. The tricky part is that returning early leaves the overlay pinned since sentBy was already deleted, which only resolves once the settle effect reconciles with the host's answer or lingers forever if the write never lands—so keeping the revert but suppressing just the toast seems like the safer suggestion. Letting the checkbox snap back on interrupt actually feels honest, since it signals we don't know the outcome and the reader can just retry. I'll suggest gating the toast with an added !isAtomCommandInterrupted(result) check, plus noting the { reportFailure: false } option and its description, keeping it a clean single-hunk diff around line 123. I've done another pass over the rest of the logic file—countViewedFiles and the fold-toggle logic look fine and pure, no other issues stand out. I'm settling on posting just this one comment, though I'm weighing whether a single moderate finding is enough to justify a failure state versus passing with a note. Since the toast reconnect issue is a real user-visible regression from an established convention, and the instructions say the check defaults to failure unless everything is clean, I'll mark this as a failure with a measured summary and post the review comment now.

26. modify_pr — One finding on the new viewed-files hook: the command-failure path surfaces an error toast for interrupt-only failures, which diverges from the repo's established useAtomCommand failure convention. Everything else in the web scope (Checkbox/Tooltip primitive use, the amber caveat icon matching the adjacent meta-line pattern, header portal render-prop stability via refs, explicit environmentId threading) looks consistent.


Agent Credits: 835 credits