Repository navigation
UI Consistency: 1 issue found
apps/web/src/components/files/fileSaveCoordinator.ts:98-103 β After a failed write, onPendingChange(false) is invoked unconditionally immediately after onRollback, so it overwrites the pending state the rollback handler just set. FilePreviewPanel.tsx:429-433 marks the file pending again when a newer overlay is present (the stated intent of commit dc19c82), but that true is immediately reset to false. Since ChatView.handleFilePendingChange drives pendingFileSurfaceIds (the unsaved marker for file surfaces), the panel keeps showing unsaved text while the tab shows no unsaved state, and nothing re-marks it until the next keystroke. Suggested smallest fix: clear pending before calling onRollback so the handler has final say. An inline comment with a suggested patch was posted.
Previously reported findings that remain open (not re-posted): the squashAtomCommandFailure(result) narrowing at FilePreviewPanel.tsx:436 (flagged on a58ea12).
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.
Scope reviewed: apps/web/src/components/files/FilePreviewPanel.tsx, apps/web/src/components/files/fileSaveCoordinator.ts, apps/web/src/components/files/fileSaveCoordinator.test.ts (all in the check's include patterns), plus consumers apps/web/src/components/ChatView.tsx (handleFilePendingChange, pendingFileSurfaceIds) and the shared runtime helpers isAtomCommandInterrupted / squashAtomCommandFailure in packages/client-runtime/src/state/runtime.ts for context.
Checks performed:
- Traced the new
onRollbackcontract from the coordinator through both call sites (EditableFileSurface,RenderedMarkdownSurface) to the pending-indicator state inChatView. - Confirmed the interrupted-result exclusion added in this PR now matches the repo-wide convention (
isAtomCommandInterruptedbefore any user-facing failure handling). - Confirmed the failure toast now carries the squashed cause, consistent with other
type: "error"toasts inapps/web. - No shared-primitive, Tailwind ownership, theme/variant, scroll/mask, or environment-routing changes are present in this diff; no findings in those areas.
- The new unit tests in
fileSaveCoordinator.test.tsassertonPendingChangelast-callfalsewith a mockedonRollback, which is why the real-call-site ordering interaction is not caught by the suite.
π Agent activity β 8 tool calls
π I want to check FilePreviewPanel.tsx for changes and see whether the previously flagged squashAtomCommandFailure typing issue from commit a58ea12 has been resolved at the current head dc19c82.
1. browse_code β apps/web/src/components/files/fileSaveCoordinator.ts
2. browse_code β apps/web/src/components/files/FilePreviewPanel.tsx
π I'm checking whether the flagged line handling squashAtomCommandFailure's null case has changed between the reviewed commit a58ea12 and the current head dc19c82, and I want to look at that function's signature too.
3. git_tools β f6f2be3..dc19c82
4. git_tools β squashAtomCommandFailure|isAtomCommandInterrupted
π I recall an earlier review comment pointed out a type mismatch at that line, where a nullable result was only narrowed for null but not for the success case, which lacks the required cause field. Since that comment predates the current head commit by one revision, I want to check whether the latest commit actually changed that line.
5. git_tools β dc19c82
π I'm looking at the rollback-after-dispose behavior added in dc19c82 β when the coordinator is disposed, it fires onRollback which calls onPendingChange, the toast manager, and clears the query data. I want to trace whether onPendingChange could try to update parent state after the component has already unmounted. Actually I realize there's a potential ordering bug: in the branch where a newer overlay exists, the callback sets pending to true, but the coordinator then immediately calls onPendingChange with false right after β which would overwrite that true state. I need to trace through the failure-handling logic more carefully to confirm this sequencing. I'm questioning whether this really falls under "UI Consistency" scope, since those rules focus on styling, shared components, and environment routing rather than state-transition bugs. But the rules also mention preserving interaction semantics and requiring tests for state transition changes, and prior runs did flag behavioral consistency issues like toast messaging conventions, so this type of finding seems to fit the precedent.
6. git_tools β onPendingChange|pendingSave|pendingPaths|handlePendingChange
π I've confirmed the ordering issue: the "newer overlay" branch in FilePreviewPanel sets pending to true, but the coordinator then overwrites it with false, so the unsaved indicator disappears while the overlay text still shows unsaved content. Now I want to check handleFilePendingChange in ChatView to understand exactly how this manifests visually in the file tab.
7. git_tools β handleFilePendingChange
π I've confirmed this is a real regression: the "keep this text and mark pending" branch that sets pendingFileSurfaceIds (which drives the unsaved-dot indicator on file tabs) gets immediately undone. This falls within state transitions scope, so I'll leave an inline comment on FilePreviewPanel.tsx line 432, suggesting the smallest fix is to stop the coordinator from forcing pending to false when the rollback callback actually wants it true. The cleanest approach is swapping the call order in fileSaveCoordinator.ts β call onPendingChange(false) first, then onRollback, so the "newer overlay" branch's onPendingChange(true) has the final say. I want to verify the revision check logic still holds since a newer overlay would come from a separate coordinator instance after remount, which seems fine. I'm also double-checking the dispose/rollback path involving clearProjectFileQueryData and the toast notification to see if there's another edge case worth flagging. I'm considering whether a remounted surface with a new coordinator could clash with the old coordinator clearing the overlay, but that scenario feels speculative compared to the concrete pending-ordering bug I already found β no one else has flagged this ordering issue yet, so I'll write up a comment on line 103 of fileSaveCoordinator.ts (an added line in the diff) proposing the swap as a fix. I'll set up a multi-line inline suggestion spanning lines 98-103 that reorders the callback so onPendingChange(false) fires before onRollback, matching the existing indentation. This ordering change is harmless for the normal rollback path, so I'm ready to post the review flagged with a finding.
8. modify_pr β One finding on the new after-dispose rollback path: the coordinator's unconditional onPendingChange(false) cancels the "mark pending again" branch that onRollback uses when a newer overlay is present, so the file tab loses its unsaved indicator while unsaved text is still on screen.
Agent Credits: 151 credits