diff --git a/apps/webapp/app/components/admin/FeatureFlagsDialog.tsx b/apps/webapp/app/components/admin/FeatureFlagsDialog.tsx index 21014f5630d..58b2b7722f1 100644 --- a/apps/webapp/app/components/admin/FeatureFlagsDialog.tsx +++ b/apps/webapp/app/components/admin/FeatureFlagsDialog.tsx @@ -56,6 +56,7 @@ export function FeatureFlagsDialog({ const saveFetcher = useFetcher(); const loadFeatureFlags = loadFetcher.load; const onOpenChangeRef = useRef(onOpenChange); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. onOpenChangeRef.current = onOpenChange; const [overrides, setOverrides] = useState>({}); diff --git a/apps/webapp/app/components/code/JSONEditor.tsx b/apps/webapp/app/components/code/JSONEditor.tsx index b4c3f7a6ed3..0c5153c969f 100644 --- a/apps/webapp/app/components/code/JSONEditor.tsx +++ b/apps/webapp/app/components/code/JSONEditor.tsx @@ -94,6 +94,7 @@ export function JSONEditor(opts: JSONEditorProps) { const editor = useRef(null); const settings: Omit = { ...opts, + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. container: editor.current, extensions, editable: !readOnly, diff --git a/apps/webapp/app/components/code/TSQLEditor.tsx b/apps/webapp/app/components/code/TSQLEditor.tsx index 073ba7f3e55..2beede97cc9 100644 --- a/apps/webapp/app/components/code/TSQLEditor.tsx +++ b/apps/webapp/app/components/code/TSQLEditor.tsx @@ -196,6 +196,7 @@ export function TSQLEditor(opts: TSQLEditorProps) { const settings: Omit = { ...opts, + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. container: editor.current, extensions, editable: !readOnly, diff --git a/apps/webapp/app/components/code/TextEditor.tsx b/apps/webapp/app/components/code/TextEditor.tsx index db16b996462..f81cedabcad 100644 --- a/apps/webapp/app/components/code/TextEditor.tsx +++ b/apps/webapp/app/components/code/TextEditor.tsx @@ -48,6 +48,7 @@ export function TextEditor(opts: TextEditorProps) { const editor = useRef(null); const settings: Omit = { ...opts, + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. container: editor.current, extensions, editable: !readOnly, diff --git a/apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx b/apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx index bd1404e7426..1153cd98126 100644 --- a/apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx +++ b/apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx @@ -123,6 +123,7 @@ export function DashboardAgentChat({ // The path this chat last rendered on. React never unmounts on a page teardown, so an // unmount whose live URL has moved is the router having navigated out from under it. const renderedPathRef = useRef(location.pathname); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. renderedPathRef.current = location.pathname; const transport = useTriggerChatTransport({ @@ -209,6 +210,7 @@ export function DashboardAgentChat({ }); const orderRef = useRef(createTranscriptOrder(initialMessages)); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. const messages = orderTranscript(rawMessages, orderRef.current); // Read here, not in the panel, so it re-reads as each turn settles. @@ -359,6 +361,7 @@ export function DashboardAgentChat({ const navigatedRef = useRef | null>(null); if (navigatedRef.current === null) { navigatedRef.current = new Set(); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. pendingNavigateIntents(initialMessages, navigatedRef.current); } useEffect(() => { @@ -374,6 +377,7 @@ export function DashboardAgentChat({ const watchProposedRef = useRef | null>(null); if (watchProposedRef.current === null) { watchProposedRef.current = new Set(); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. pendingWatchIntents(initialMessages, watchProposedRef.current); } useEffect(() => { @@ -388,6 +392,7 @@ export function DashboardAgentChat({ }, [transport, chatId, aiStop]); const teardownRef = useRef<() => void>(() => {}); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. teardownRef.current = () => { if (status !== "streaming" && status !== "submitted") return; const reason = unmountTeardown({ @@ -401,6 +406,7 @@ export function DashboardAgentChat({ // Read by the settle effect, which must not re-run when the transcript changes. const messagesRef = useRef(messages); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. messagesRef.current = messages; const prevStatus = useRef(status); diff --git a/apps/webapp/app/components/dashboard-agent/DashboardAgentMessages.tsx b/apps/webapp/app/components/dashboard-agent/DashboardAgentMessages.tsx index f3c9382d896..819e11209fd 100644 --- a/apps/webapp/app/components/dashboard-agent/DashboardAgentMessages.tsx +++ b/apps/webapp/app/components/dashboard-agent/DashboardAgentMessages.tsx @@ -126,7 +126,9 @@ export function winningInvestigationOccurrences(messages: UIMessage[]): Map { const previous = useRef>(); const next = useMemo(() => winningInvestigationOccurrences(messages), [messages]); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. previous.current = reuseWinners(previous.current, next); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. return previous.current; } diff --git a/apps/webapp/app/components/dashboard-agent/DashboardAgentPanel.tsx b/apps/webapp/app/components/dashboard-agent/DashboardAgentPanel.tsx index ff7a71e0f93..c034aa0c7cc 100644 --- a/apps/webapp/app/components/dashboard-agent/DashboardAgentPanel.tsx +++ b/apps/webapp/app/components/dashboard-agent/DashboardAgentPanel.tsx @@ -174,6 +174,7 @@ export function DashboardAgentPanel({ const loadHistory = useMemo( () => + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. createCoalescedReload(async () => { try { const res = await fetch(actionPath); diff --git a/apps/webapp/app/components/navigation/SideMenu.tsx b/apps/webapp/app/components/navigation/SideMenu.tsx index 018ec84d02d..3227c021b98 100644 --- a/apps/webapp/app/components/navigation/SideMenu.tsx +++ b/apps/webapp/app/components/navigation/SideMenu.tsx @@ -532,6 +532,7 @@ export function SideMenu({ // object each render, so depending on it would fire the cleanup (flushing the debounce) every // render — and drags re-render constantly — instead of only on unmount. const flushPendingPreferencesRef = useRef<() => void>(); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. flushPendingPreferencesRef.current = () => { if (debounceTimeoutRef.current) { clearTimeout(debounceTimeoutRef.current); diff --git a/apps/webapp/app/components/navigation/useReorderableList.ts b/apps/webapp/app/components/navigation/useReorderableList.ts index bcde7edd1af..48eeb986923 100644 --- a/apps/webapp/app/components/navigation/useReorderableList.ts +++ b/apps/webapp/app/components/navigation/useReorderableList.ts @@ -34,6 +34,7 @@ export function useReorderableList({ const [order, setOrder] = useState(() => initialOrder ?? items.map(itemKey)); const resetOrderRef = useRef({ initialOrder, items, itemKey }); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. resetOrderRef.current = { initialOrder, items, itemKey }; // Only an organization switch resets user-managed order. Keep the latest inputs in a ref so diff --git a/apps/webapp/app/components/primitives/AgentDotMatrix.tsx b/apps/webapp/app/components/primitives/AgentDotMatrix.tsx index f82967828eb..9d1a78d8455 100644 --- a/apps/webapp/app/components/primitives/AgentDotMatrix.tsx +++ b/apps/webapp/app/components/primitives/AgentDotMatrix.tsx @@ -290,7 +290,9 @@ export function AgentDotMatrix({ const playlistKey = playlist.join(","); const paletteObjRef = useRef(paletteObj); const playlistRef = useRef(playlist); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. paletteObjRef.current = paletteObj; + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. playlistRef.current = playlist; useEffect(() => { diff --git a/apps/webapp/app/components/primitives/DateField.tsx b/apps/webapp/app/components/primitives/DateField.tsx index 88350831644..274811412f4 100644 --- a/apps/webapp/app/components/primitives/DateField.tsx +++ b/apps/webapp/app/components/primitives/DateField.tsx @@ -81,6 +81,7 @@ export function DateField({ }); const stateValueRef = useRef(state.value); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. stateValueRef.current = state.value; // Sync only when the passed value or timezone mode changes. Depending on state.value directly diff --git a/apps/webapp/app/components/primitives/Resizable.tsx b/apps/webapp/app/components/primitives/Resizable.tsx index 0bd4f8e86d9..ece2dc77af0 100644 --- a/apps/webapp/app/components/primitives/Resizable.tsx +++ b/apps/webapp/app/components/primitives/Resizable.tsx @@ -100,7 +100,9 @@ function collapsibleHandleClassName(show: boolean) { function useFrozenValue(value: T | null | undefined): T | null | undefined { const ref = useRef(value); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. if (value != null) ref.current = value; + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. return ref.current; } diff --git a/apps/webapp/app/components/primitives/charts/hooks/useZoomSelection.ts b/apps/webapp/app/components/primitives/charts/hooks/useZoomSelection.ts index e34846af00e..4a5f2feea76 100644 --- a/apps/webapp/app/components/primitives/charts/hooks/useZoomSelection.ts +++ b/apps/webapp/app/components/primitives/charts/hooks/useZoomSelection.ts @@ -55,6 +55,7 @@ export function useZoomSelection(): UseZoomSelectionReturn { const stateRef = useRef(state); // Keep ref in sync with state + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. stateRef.current = state; const startSelection = useCallback((label: string) => { diff --git a/apps/webapp/app/components/query/QueryEditor.tsx b/apps/webapp/app/components/query/QueryEditor.tsx index c5665fa88fb..69f9e19a46c 100644 --- a/apps/webapp/app/components/query/QueryEditor.tsx +++ b/apps/webapp/app/components/query/QueryEditor.tsx @@ -505,6 +505,7 @@ export function QueryEditor({ // Use a ref so the effect can read chartConfig without re-firing on every config tweak const chartConfigRef = useRef(chartConfig); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. chartConfigRef.current = chartConfig; // Reset chart config only when a column referenced by the current config is no @@ -562,6 +563,7 @@ export function QueryEditor({ }, []); // Compute current save data for the save render prop + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. const currentQuery = editorRef.current?.getQuery() ?? ""; const saveData: QueryEditorSaveData = { title: queryTitle ?? "Untitled Query", @@ -790,6 +792,7 @@ export function QueryEditor({ onRename={handleRenameTitle} /> } + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. query={editorRef.current?.getQuery() ?? defaultQuery} data={{ rows: results.rows, @@ -844,6 +847,7 @@ export function QueryEditor({ (); @@ -120,6 +121,7 @@ function useChildRunStatusesTooltip({ // Keep the latest loader callback available to the polling interval // without recreating the interval on every render. const loadChildStatusesRef = useRef(loadChildStatuses); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. loadChildStatusesRef.current = loadChildStatuses; const stopPolling = useCallback(() => { diff --git a/apps/webapp/app/components/runs/v3/agent/AgentView.tsx b/apps/webapp/app/components/runs/v3/agent/AgentView.tsx index 72926ac35e9..58797b1f75c 100644 --- a/apps/webapp/app/components/runs/v3/agent/AgentView.tsx +++ b/apps/webapp/app/components/runs/v3/agent/AgentView.tsx @@ -285,6 +285,7 @@ function useAgentSessionMessages({ // `scheduleFlush`. The Map *reference* changes on every flush so React // detects the state update and the downstream `useMemo` recomputes. const [messagesById, setMessagesById] = useState>( + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. () => new Map(pendingRef.current) ); @@ -294,6 +295,7 @@ function useAgentSessionMessages({ const lastFlushAtRef = useRef(0); const pendingTimerRef = useRef | null>(null); const scheduleFlush = useRef<() => void>(() => {}); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. scheduleFlush.current = () => { if (pendingTimerRef.current !== null) return; // already scheduled const now = Date.now(); @@ -670,6 +672,7 @@ function useAgentSessionMessages({ return useMemo(() => { const timestamps = timestampsRef.current; const arr = Array.from(messagesById.values()); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. arr.sort((a, b) => { const ta = timestamps.get(a.id) ?? 0; const tb = timestamps.get(b.id) ?? 0; diff --git a/apps/webapp/app/components/webhookDeliveries/v1/useDeliveriesLiveReload.ts b/apps/webapp/app/components/webhookDeliveries/v1/useDeliveriesLiveReload.ts index aee736a3f16..9cf28d80237 100644 --- a/apps/webapp/app/components/webhookDeliveries/v1/useDeliveriesLiveReload.ts +++ b/apps/webapp/app/components/webhookDeliveries/v1/useDeliveriesLiveReload.ts @@ -124,6 +124,7 @@ export function useDeliveriesLiveReload({ const location = useLocation(); const deliveriesPollFetcher = useTypedFetcher(); const deliveriesPollFetcherStateRef = useRef(deliveriesPollFetcher.state); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. deliveriesPollFetcherStateRef.current = deliveriesPollFetcher.state; const [visibleDeliveries, setVisibleDeliveries] = useState(deliveries); diff --git a/apps/webapp/app/hooks/useAutoRevalidate.ts b/apps/webapp/app/hooks/useAutoRevalidate.ts index 4be50a34e12..eec1f3c34fc 100644 --- a/apps/webapp/app/hooks/useAutoRevalidate.ts +++ b/apps/webapp/app/hooks/useAutoRevalidate.ts @@ -11,6 +11,7 @@ export function useAutoRevalidate(options: UseAutoRevalidateOptions = {}) { const { interval = 5000, onFocus = true, disabled = false } = options; const revalidator = useRevalidator(); const revalidatorRef = useRef(revalidator); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. revalidatorRef.current = revalidator; useEffect(() => { diff --git a/apps/webapp/app/hooks/useChanged.ts b/apps/webapp/app/hooks/useChanged.ts index 430c1605a52..f7e08dd3a48 100644 --- a/apps/webapp/app/hooks/useChanged.ts +++ b/apps/webapp/app/hooks/useChanged.ts @@ -12,7 +12,9 @@ export function useChanged( const itemRef = useRef(); const itemId = item?.id; + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. actionRef.current = action; + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. itemRef.current = item; useEffect(() => { diff --git a/apps/webapp/app/hooks/useDashboardEditor.ts b/apps/webapp/app/hooks/useDashboardEditor.ts index 53fba85c35b..d7fae76383b 100644 --- a/apps/webapp/app/hooks/useDashboardEditor.ts +++ b/apps/webapp/app/hooks/useDashboardEditor.ts @@ -207,6 +207,7 @@ export function useDashboardEditor({ const isInitializedRef = useRef(false); const currentLayoutJsonRef = useRef(JSON.stringify(initialData.layout)); const initialDataRef = useRef(initialData); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. initialDataRef.current = initialData; // Sync queue to prevent race conditions diff --git a/apps/webapp/app/hooks/useDebounce.ts b/apps/webapp/app/hooks/useDebounce.ts index da63330f2a7..b9bb51e48cc 100644 --- a/apps/webapp/app/hooks/useDebounce.ts +++ b/apps/webapp/app/hooks/useDebounce.ts @@ -29,6 +29,7 @@ export function useDebounceEffect(value: T, fn: (value: T) => void, delay: nu const fnRef = useRef(fn); // Update the ref whenever the function changes + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. fnRef.current = fn; useEffect(() => { diff --git a/apps/webapp/app/hooks/useElementVisibility.ts b/apps/webapp/app/hooks/useElementVisibility.ts index 2f1531882ce..44726cece0d 100644 --- a/apps/webapp/app/hooks/useElementVisibility.ts +++ b/apps/webapp/app/hooks/useElementVisibility.ts @@ -8,6 +8,7 @@ export function useElementVisibility({ onVisibilityChange }: UseElementVisibilit const ref = useRef(null); const isVisibleRef = useRef(false); const callbackRef = useRef(onVisibilityChange); + // oxlint-disable-next-line react/react-compiler -- This ref intentionally coordinates an imperative integration outside React state. callbackRef.current = onVisibilityChange; useEffect(() => {