chore: Update dependency @eslint-react/eslint-plugin to v5#1704
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF ScorecardScorecard details
Scanned Files
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Merging this PR will not alter performance
Comparing Footnotes
|
c6fa7cd to
8a11052
Compare
f3ff4f0 to
aafaa48
Compare
## Summary Adds a cross-PR file-overlap analysis step to the `/review-dep-pr` skill so that batch reviews surface merge conflicts upfront and the user can pick a sequencing strategy before triage. ### What changed - **New Phase 5 — Cross-PR File Overlap Analysis** (skipped for single-PR runs): - Pulls each PR's changed-file list via `gh pr view --json files`. - Builds a per-file conflict map and classifies overlaps as **none / lockfile-only / config / source**. - Treats `package-lock.json`, `pnpm-lock.yaml`, `uv.lock`, `go.sum`, `atlas.sum`, etc. as lockfile-only (rebase needed, not a hard blocker). - Groups PRs into merge **waves** (Wave 1 = parallel-safe, Wave 2+ = sequential after rebase). - **Phase 6 (Present Findings)** now leads with a "Batch Overlap Summary" header and adds a `Files touched / conflicts with` row to each per-PR card. - **Phase 7 (User Decision)** opens with a strategy question whenever ≥ 2 PRs share files: - Wave-based parallel - Strict sequential - Combine into one PR - Defer the conflicting subset - **Phase 8 (Execute Decisions)** honours the chosen strategy when sequencing merges (parallel waves, rebase between waves, etc.). - New rule: multi-PR runs always compute the conflict map; lockfile-only overlaps are acceptable but expect rebase between merges. ### Why Without this, the skill would propose merging in parallel any PRs whose CI is green, then run into surprise conflicts on the second/third merge — most often on workflow YAMLs and lockfiles. The new phase makes the conflict surface explicit before the user picks a strategy, and the strategy choice is then carried through to execution. ### Test plan Dogfooded against the 8 open Renovate PRs in this repo (#1698-#1705). Surfaced three conflict clusters (`docker.yml` between #1698/#1701/#1703, `cli.yml` between #1702/#1703, `web/package.json` between #1700/#1704) plus the expected lockfile-only overlaps. The Wave-based strategy successfully merged 5 PRs sequentially with `--squash --admin` and the lockfile PR (#1705) was rebased via Renovate. ### Review coverage `/pre-pr-review quick` — docs-only change to a `.claude/` skill file, no code/agents required. Pre-commit hooks passed (trailing whitespace, EOF, secrets, em-dashes).
3413f91 to
8f3cfca
Compare
8f3cfca to
650600c
Compare
The lighthouse.yml site filter watches web/package.json and web/package-lock.json so a toolchain-only LHCI bump revalidates the marketing-site Lighthouse score. pages-preview.yml did not mirror those paths, so a web-only Renovate PR would trigger lighthouse-site but never trigger a preview deploy for the new commit. lighthouse-site then sat in its 5-minute wait loop polling for a banner SHA that was never deployed. Mirror the two paths in pages-preview.yml so every PR that the lighthouse-site filter accepts also gets a fresh preview to score against.
Switch web/eslint.config.js from recommended-typescript to recommended-type-checked (requires parserOptions.projectService for the type-aware rules to read inferred types). Add error-level opt-ins beyond the preset: web-api-no-leaked-fetch (detect fetch in effects without AbortController cleanup), no-leaked-conditional-rendering (catch the bug where a falsy 0 renders verbatim, type-aware), and globals (restrict window / document / localStorage in render bodies). Static-components fixes: extract ActivityEventIcon and CatalogEntryIcon as wrapper components doing the lookup internally via createElement. ActivityEventIcon lives in its own file so react-refresh stays happy alongside the utility exports in agents.ts. The risk-icon case keeps the const-Record lookup with a per-line disable since the rule cannot statically prove map identity stability. DepartmentEditDrawer: drop the now-unused eslint-disable set-state-in-effect block (v5 heuristic no longer flags the prop-sync pattern in that effect).
The new opt-in eslint-react v5 rules surfaced 14 leaked-conditional
errors, 2 globals violations, and 2 kicker-state warnings.
Fixes:
- {prop && jsx} where prop is ReactNode | undefined leaks 0 / empty
string verbatim. Replace with { prop != null && prop !== false &&
jsx } across error-banner, input-field, keyboard-shortcut-hint,
list-header, search-filter-sort, NamespaceSection, and
SettingsHealthSection. error-banner s onRetry || action compound
becomes Boolean(onRetry ?? action) and the inner action check uses
an explicit !== undefined guard.
- AppLayout: hoist the window.location.href and
window.dispatchEvent calls out of the useMemo action callbacks
into named useCallback handlers (navigateToDocs,
openNotificationDrawer) so the globals rule sees them as
event-handler bound.
- NodeContextMenu: replace direct window.innerWidth /
window.innerHeight reads inside useMemo with a new useViewportSize
hook backed by useSyncExternalStore over the resize event. Also
makes the bounded-position calc reactive to viewport changes.
- VersionHistorySection: drop the reloadNonce useState that was only
consumed in the effect deps array (no-unused-state). Both the
initial load and the refresh path now route through a useCallback
loadHistory helper, with the existing requestEpochRef gating
stale completions.
- CeremonyPolicyPage: surface isDirty in JSX as a Save-button gate
and an Unsaved changes affordance so the rule sees a real
consumer. Save now requires isDirty in addition to the existing
parse-error and saving guards.
CLAUDE.md updates document the wrapper-icon pattern, the
useViewportSize hook, and the v5 preset / explicit opt-in choices.
Edited/Blocked NotificationRenovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR. You can manually request rebase by checking the rebase/retry box above. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR refactors icon-handling and viewport-sizing patterns across the web codebase. Icon factory helpers like 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/src/components/ui/input-field.tsx (1)
154-157: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueNote:
buildInputClassespadding flags still use!!leadingIcon/!!trailingElement.The render guards on lines 174 and 198 were tightened to
!= null && !== false, butbuildInputClasseson lines 156–157 still deriveshasLeadingIcon/hasTrailingElementvia!!. For the theoretical case whereleadingIconis a falsy-but-non-null value (e.g.0), the icon<span>would render without the compensatingpl-8padding, overlapping the text. In practice icon props are always React elements so there's no real risk, but aligning the flag derivation would keep the logic internally consistent:🔧 Optional consistency fix
const inputClasses = buildInputClasses({ hasError, - hasLeadingIcon: !!leadingIcon, - hasTrailingElement: !!trailingElement, + hasLeadingIcon: leadingIcon != null && leadingIcon !== false, + hasTrailingElement: trailingElement != null && trailingElement !== false, className, })Also applies to: 174-181, 198-202
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/ui/input-field.tsx` around lines 154 - 157, The code uses !!leadingIcon / !!trailingElement when passing hasLeadingIcon/hasTrailingElement to buildInputClasses, which is inconsistent with the stricter render guards (leadingIcon != null && leadingIcon !== false); update the flag derivation so both the buildInputClasses call and any other uses (hasLeadingIcon, hasTrailingElement, and places that check leadingIcon/trailingElement) use the same explicit check: treat a value as present only when (leadingIcon != null && leadingIcon !== false) and likewise for trailingElement, then pass those boolean results into buildInputClasses and use them for padding/spacing decisions (ensure you update all occurrences referencing hasLeadingIcon/hasTrailingElement).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/components/layout/AppLayout.tsx`:
- Around line 129-134: Replace the global CustomEvent call in
openNotificationDrawer with a direct state update: locate openNotificationDrawer
in AppLayout.tsx and change its body from window.dispatchEvent(new
CustomEvent('open-notification-drawer')) to calling the state setter
setNotificationDrawerOpen(true) (the same setter used in the component's
useEffect listener); if other components like Sidebar.tsx currently rely on the
window event, update them to call the same setter (or lift/shared state/context)
so the global event and CustomEvent usage can be removed for consistency.
In `@web/src/components/version-rollback/VersionHistorySection.tsx`:
- Around line 103-108: The component's requestEpochRef isn't advanced on
unmount, so in-flight promises from client.list() can still call
setItems/setError/setLoading after unmount; add an unmount cleanup that
increments requestEpochRef.current (the same epoch-bump mechanism used for
refresh/client-change) inside the useEffect that sets up requestEpochRef (or the
effect around loadHistory/handleLoadMore) so any settled loadHistory or
handleLoadMore results are ignored when the component unmounts; update any
related logic in loadHistory and handleLoadMore to rely on that epoch check to
discard results from client.list().
In `@web/src/hooks/useViewportSize.ts`:
- Around line 1-46: Update the module comment to clarify that readSnapshot()
returns the real window.innerWidth/innerHeight on the first client render
(CSR/Vite) and that the { width: 0, height: 0 } SSR_SNAPSHOT is only used during
server-side rendering or when window is undefined; reference the existing
module-level helpers (readSnapshot, subscribe, SSR_SNAPSHOT, cachedSnapshot, and
useViewportSize) and replace the misleading "before subscription / before
resize" phrasing with a concise statement that the zero snapshot is the SSR
default while the browser snapshot reflects real dimensions on the initial
render.
In `@web/src/pages/approvals/ApprovalRiskGroupSection.tsx`:
- Around line 32-35: Refactor the getRiskLevelIcon factory into a wrapper
component named RiskLevelIcon and use it in ApprovalRiskGroupSection: create a
new file exporting function RiskLevelIcon({ riskLevel }) that performs the const
Record lookup and returns the icon via React.createElement (preserving stable
identity), replace the getRiskLevelIcon(...) call in ApprovalRiskGroupSection
with <RiskLevelIcon riskLevel={riskLevel} />, and follow the existing patterns
used by ActivityEventIcon and catalog icon components; alternatively, if you
intend to keep the getter, add a short file-level comment in
ApprovalRiskGroupSection explaining why the getRiskLevelIcon usage is an
intentional exception to the rule.
In `@web/src/utils/activity-event-icon.tsx`:
- Around line 20-34: The ACTIVITY_ICON_MAP and FALLBACK_ICON in
activity-event-icon.tsx are duplicated from agents.ts; remove the local
ACTIVITY_ICON_MAP and FALLBACK_ICON definitions and update ActivityEventIcon to
delegate to the existing getActivityEventIcon function exported from
web/src/utils/agents.ts (import it if not present), so the component uses
getActivityEventIcon(event.type) for lookup/fallback instead of maintaining its
own map.
---
Outside diff comments:
In `@web/src/components/ui/input-field.tsx`:
- Around line 154-157: The code uses !!leadingIcon / !!trailingElement when
passing hasLeadingIcon/hasTrailingElement to buildInputClasses, which is
inconsistent with the stricter render guards (leadingIcon != null && leadingIcon
!== false); update the flag derivation so both the buildInputClasses call and
any other uses (hasLeadingIcon, hasTrailingElement, and places that check
leadingIcon/trailingElement) use the same explicit check: treat a value as
present only when (leadingIcon != null && leadingIcon !== false) and likewise
for trailingElement, then pass those boolean results into buildInputClasses and
use them for padding/spacing decisions (ensure you update all occurrences
referencing hasLeadingIcon/hasTrailingElement).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3e9b0475-251f-4cb3-a620-819e0534b5e2
⛔ Files ignored due to path filters (1)
web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (24)
.github/workflows/pages-preview.ymlweb/CLAUDE.mdweb/eslint.config.jsweb/package.jsonweb/src/components/layout/AppLayout.tsxweb/src/components/ui/error-banner.tsxweb/src/components/ui/input-field.tsxweb/src/components/ui/keyboard-shortcut-hint.tsxweb/src/components/ui/list-header.tsxweb/src/components/ui/search-filter-sort.tsxweb/src/components/version-rollback/VersionHistorySection.tsxweb/src/hooks/useViewportSize.tsweb/src/pages/agents/ActivityLogItem.tsxweb/src/pages/approvals/ApprovalRiskGroupSection.tsxweb/src/pages/mcp-catalog/CatalogDetailDrawer.tsxweb/src/pages/mcp-catalog/CatalogEntryCard.tsxweb/src/pages/mcp-catalog/catalog-icons.tsxweb/src/pages/org-edit/DepartmentEditDrawer.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/settings/NamespaceSection.tsxweb/src/pages/settings/SettingsHealthSection.tsxweb/src/pages/settings/ceremony-policy/CeremonyPolicyPage.tsxweb/src/utils/activity-event-icon.tsxweb/src/utils/agents.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Dashboard Test
🧰 Additional context used
📓 Path-based instructions (6)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Reuse components fromweb/src/components/ui/before creating new ones (mandatory design system enforcement)
Never hardcode hex colors, font-family, pixel spacing, Motion transitions, or BCP 47 locale strings; use design tokens,@/lib/motionpresets, and helpers in@/utils/format
Locale: never hardcode BCP 47 tags or call bare.toLocaleString()/.toLocaleDateString()/.toLocaleTimeString(); use helpers in@/utils/formatthat readgetLocale()from@/utils/locale
Files:
web/src/pages/mcp-catalog/CatalogEntryCard.tsxweb/src/pages/settings/NamespaceSection.tsxweb/src/pages/agents/ActivityLogItem.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/hooks/useViewportSize.tsweb/src/components/ui/search-filter-sort.tsxweb/src/pages/settings/SettingsHealthSection.tsxweb/src/pages/approvals/ApprovalRiskGroupSection.tsxweb/src/pages/mcp-catalog/CatalogDetailDrawer.tsxweb/src/pages/mcp-catalog/catalog-icons.tsxweb/src/components/ui/input-field.tsxweb/src/components/layout/AppLayout.tsxweb/src/pages/org-edit/DepartmentEditDrawer.tsxweb/src/utils/activity-event-icon.tsxweb/src/components/version-rollback/VersionHistorySection.tsxweb/src/components/ui/keyboard-shortcut-hint.tsxweb/src/components/ui/list-header.tsxweb/src/utils/agents.tsweb/src/pages/settings/ceremony-policy/CeremonyPolicyPage.tsxweb/src/components/ui/error-banner.tsx
{src,web/src}/**/*.{py,tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
{src,web/src}/**/*.{py,tsx,ts}: Currency: never hardcode ISO 4217 codes; backend useDEFAULT_CURRENCYfromsynthorg.budget.currencyor runtimebudget.currencysetting; frontend useDEFAULT_CURRENCYfrom@/utils/currenciesoruseSettingsStore().currency
Never use_usdsuffix on money fields; the type carries money semantics; the value is in the operator's configured currency
Store UTC datetimes; render viaIntlwithout passingtimeZone(browser tz wins)
Always format date/number viaIntl; no hand-rolled templates
Use metric units only; International / British English UI default (colour,behaviour,organise,centred,analyse,cancelled); document deviations
Files:
web/src/pages/mcp-catalog/CatalogEntryCard.tsxweb/src/pages/settings/NamespaceSection.tsxweb/src/pages/agents/ActivityLogItem.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/hooks/useViewportSize.tsweb/src/components/ui/search-filter-sort.tsxweb/src/pages/settings/SettingsHealthSection.tsxweb/src/pages/approvals/ApprovalRiskGroupSection.tsxweb/src/pages/mcp-catalog/CatalogDetailDrawer.tsxweb/src/pages/mcp-catalog/catalog-icons.tsxweb/src/components/ui/input-field.tsxweb/src/components/layout/AppLayout.tsxweb/src/pages/org-edit/DepartmentEditDrawer.tsxweb/src/utils/activity-event-icon.tsxweb/src/components/version-rollback/VersionHistorySection.tsxweb/src/components/ui/keyboard-shortcut-hint.tsxweb/src/components/ui/list-header.tsxweb/src/utils/agents.tsweb/src/pages/settings/ceremony-policy/CeremonyPolicyPage.tsxweb/src/components/ui/error-banner.tsx
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
Always use
createLoggerfrom@/lib/logger; never use bareconsole.warn,console.error, orconsole.debugin application code (exception:logger.tsitself may use bare console methods)Use logger variable name
logconsistently (e.g.,const log = createLogger('module-name'))Pass dynamic/untrusted values to logger as separate arguments (not interpolated into message strings) so they go through
sanitizeArgWrap attacker-controlled fields inside structured objects in
sanitizeForLog()before embedding in logsCallers MUST NOT wrap store mutation calls in try/catch; the store owns the error UX (error handling is the responsibility of the store, not the caller)
Any new caller of health/readiness endpoints must explicitly handle the 503 unavailable path
Keep the async-leak ceiling from exceeding the documented
MAX_ASYNC_LEAKSconstant (currently 90); raise the ceiling only with documented per-PR justificationUse
<StatusBadge>component (defaults torole="img"with aria-label; setdecorativefor adjacent-labeled,announcefor live WebSocket updates) instead of creating status indicator dots inlineUse
<MetricCard>,<Sparkline>,<ProgressGauge>, and<TokenUsageBar>components instead of creating KPI displays inlineUse
<SectionCard>(titled wrapper with icon and action slot),<AgentCard>, and<DeptHealthBar>for domain-specific cards instead of creating them inlineUse form field components (
<InputField>,<SelectField>,<SliderField>,<ToggleField>,<SegmentedControl>,<TagInput>,<SearchInput>) instead of creating form fields inlineUse
<Drawer width="compact|narrow|default|wide">(Base UI) for slide-in panels; do NOT add inlinew-[40vw]overridesUse
<Skeleton>family,<EmptyState>,<ErrorBoundary>,<ErrorBanner>, and<ProgressIndicator>for loading/empty/error states instead of creating them inlineUse
useEmptyStateProps({ filteredCount, totalCount, filterActive, empty, filtered })from ...
Files:
web/src/pages/mcp-catalog/CatalogEntryCard.tsxweb/src/pages/settings/NamespaceSection.tsxweb/src/pages/agents/ActivityLogItem.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/hooks/useViewportSize.tsweb/src/components/ui/search-filter-sort.tsxweb/src/pages/settings/SettingsHealthSection.tsxweb/src/pages/approvals/ApprovalRiskGroupSection.tsxweb/src/pages/mcp-catalog/CatalogDetailDrawer.tsxweb/src/pages/mcp-catalog/catalog-icons.tsxweb/src/components/ui/input-field.tsxweb/src/components/layout/AppLayout.tsxweb/src/pages/org-edit/DepartmentEditDrawer.tsxweb/src/utils/activity-event-icon.tsxweb/src/components/version-rollback/VersionHistorySection.tsxweb/src/components/ui/keyboard-shortcut-hint.tsxweb/src/components/ui/list-header.tsxweb/src/utils/agents.tsweb/src/pages/settings/ceremony-policy/CeremonyPolicyPage.tsxweb/src/components/ui/error-banner.tsx
web/**/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
List page root container should use
space-y-section-gap(the majority pattern;flex flex-col gap-section-gapis equivalent but discouraged)
<ErrorBanner>must land immediately after<ListHeader>, before any filter/pagination rowPages with a one-line mission statement must pass it via
<ListHeader description="..." />Use Kanban grouping for status-flow domains where each row's column conveys lifecycle phase (Tasks, Requests); use a flat scrollable list for queues without explicit phase semantics (Escalations, Approvals)
Use
<ListHeader>,<SearchFilterSort>,<Pagination>,<BulkActionBar>,<MetadataGrid>, and<Breadcrumbs>list-page primitives instead of creating them inline
Files:
web/src/pages/mcp-catalog/CatalogEntryCard.tsxweb/src/pages/settings/NamespaceSection.tsxweb/src/pages/agents/ActivityLogItem.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/settings/SettingsHealthSection.tsxweb/src/pages/approvals/ApprovalRiskGroupSection.tsxweb/src/pages/mcp-catalog/CatalogDetailDrawer.tsxweb/src/pages/mcp-catalog/catalog-icons.tsxweb/src/pages/org-edit/DepartmentEditDrawer.tsxweb/src/pages/settings/ceremony-policy/CeremonyPolicyPage.tsx
web/**/components/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
Always reuse existing components from
web/src/components/ui/before creating new onesNever hardcode hex colors, font-family declarations, pixel spacing, Motion transition durations, BCP 47 locale literals (
'en-US'), or currency symbols/codes; use design tokens,@/lib/motionpresets, helpers in@/utils/format, andDEFAULT_CURRENCYfrom@/utils/currenciesComponent Props interface name must be
<ComponentName>Propsand must be exported from the same file (e.g.,AgentCardPropsinagent-card.tsx)Base UI primitives are imported directly from
@base-ui/react/<subpath>and use the nativerenderprop for polymorphism; the local<Slot>helper is reserved only for<Button asChild>
Files:
web/src/components/ui/search-filter-sort.tsxweb/src/components/ui/input-field.tsxweb/src/components/ui/keyboard-shortcut-hint.tsxweb/src/components/ui/list-header.tsxweb/src/components/ui/error-banner.tsx
web/eslint.config.js
📄 CodeRabbit inference engine (web/CLAUDE.md)
Configure
@eslint-react/eslint-pluginv5+ via therecommended-type-checkedpreset withparserOptions.projectService: trueand enable explicit error-level rules:@eslint-react/web-api-no-leaked-fetch,@eslint-react/no-leaked-conditional-rendering,@eslint-react/globals
Files:
web/eslint.config.js
🔇 Additional comments (20)
web/src/pages/settings/ceremony-policy/CeremonyPolicyPage.tsx (1)
421-432: LGTM — save-row logic is correct.The
isDirty && !savingguard uses two strict booleans, so the short-circuit never produces a truthy non-boolean (no0-leak risk). The extendeddisabledexpression correctly encodes all four blocking conditions:
Condition Effect !isDirtyNo pending edits — nothing to save savingIn-flight save — prevent double submit configParseErrorCorrupt stored JSON — cannot safely overwrite overridesParseErrorSame, for the overrides key
setIsDirty(false)after a successfulPromise.alland preservingisDirty = trueon catch are both the right choices, so the button correctly re-enables on retry.web/src/components/layout/AppLayout.tsx (1)
148-153: LGTM.Both callbacks are stable (memoized with
[]), so adding them to theuseMemodependency array is correct and introduces no spurious recomputation ofglobalCommands. Thenavigatereference from React Router 7 is also stable, keeping the existing dependency correct.web/src/pages/settings/SettingsHealthSection.tsx (1)
84-86: LGTM. The!= null && !== falseguard aligns with the project-mandated pattern forReactNodeslot props.web/src/pages/org-edit/DepartmentEditDrawer.tsx (1)
57-70: LGTM. Removing the now-staleeslint-disable/eslint-enablepair is correct — retaining them would trigger unused-disable-directive warnings under--max-warnings 0.web/src/components/ui/keyboard-shortcut-hint.tsx (1)
65-67: LGTM — the guard correctly prevents''from rendering a label span. Minor note: the project convention forReactNodeslots is!= null && !== false(seeCLAUDE.mdline 112), which additionally suppressesnullandfalse.label={null}orlabel={false}with the current check renders an empty<span>, but sinceReactrenders nothing for those values inside the element the visual impact is nil.web/CLAUDE.md (1)
104-115: LGTM. The new icon-helper, viewport-size, and ESLint rule documentation is accurate and actionable.web/src/components/ui/search-filter-sort.tsx (1)
37-48: LGTM. All four slot guards uniformly follow the!= null && !== falsepattern mandated forReactNodeprops.web/src/components/ui/list-header.tsx (1)
56-62: LGTM. Both action slot guards correctly follow the!= null && !== falsepattern.web/src/pages/settings/NamespaceSection.tsx (1)
178-198: Correct nullish-aware conditional rendering forfooterAction.Both render branches now use
footerAction != null && footerAction !== false, which matches the canonicalReactNode | undefinedguard pattern and satisfies the newly enforced@eslint-react/no-leaked-conditional-renderingrule without suppressing valid falsy nodes like0.web/src/components/ui/error-banner.tsx (1)
195-231: Cluster guard and action rendering are correct.
Boolean(onRetry ?? action)at line 195 correctly prevents the{0 && <div>}leak pattern (satisfies@eslint-react/no-leaked-conditional-rendering) while still rendering the cluster whenever a real action or retry handler is present. Theaction !== undefinednarrowing at line 227 permitsnullthrough, butnullrenders as nothing so this is harmless in practice.web/src/pages/org/NodeContextMenu.tsx (1)
122-126: Viewport clamping correctly migrated touseViewportSize().The
useMemodependency array includesviewport.widthandviewport.heightfrom the reactive hook, so position clamping will recompute on every resize.margin(8) andmenuWidth(180) are render-scope literal constants and their omission from the deps array is safe — no runtime divergence is possible since they never change.web/src/pages/mcp-catalog/catalog-icons.tsx (1)
32-45: Correct wrapper component pattern per coding guidelines.
ENTRY_ICONSis intentionally non-exported so the file's only runtime export isCatalogEntryIcon. ThecreateElement(ENTRY_ICONS[entryId] ?? Package, rest)approach correctly keeps the icon lookup inside the component (satisfyingreact-x/static-components) without creating a new component definition on every render.web/src/pages/mcp-catalog/CatalogDetailDrawer.tsx (1)
42-42: Clean icon usage update.web/src/pages/mcp-catalog/CatalogEntryCard.tsx (1)
49-49: Clean icon usage update.web/eslint.config.js (2)
15-31: Preset and type-aware parser options are correct.
recommended-type-checkedis confirmed as a valid preset: "same as the recommended-typescript preset but enables additional rules that require type information." The separatefiles: ['**/*.ts', '**/*.tsx']block forprojectService: true(lines 17-31) works correctly in ESLint flat config — all matching blocks are merged before rules run, so type-aware rules from the preset have the project service available when processing TS/TSX files.
69-83: All three new rule names are valid in v5.7.1.From the official ESLint React docs and changelog:
globalsis listed in the X Rules group, accessible as@eslint-react/globals✓react-web-api/no-leaked-fetchis a new rule in v5 — exposed as@eslint-react/web-api-no-leaked-fetch✓@eslint-react/no-leaked-conditional-renderingis a confirmed X rule ✓.github/workflows/pages-preview.yml (1)
19-26: LGTM — The added path filters and the accompanying comment are clear and well-justified. Mirroring thelighthouse.ymlsite filter prevents the Lighthouse preview audit from timing out on toolchain-only bumps like this one.web/src/utils/agents.ts (1)
286-290: LGTM — Comment accurately documents the module split and its rationale (react-refresh/only-export-components). No runtime changes.web/src/pages/agents/ActivityLogItem.tsx (1)
1-16: LGTM — Correctly replaces the inlinegetActivityEventIcon()call with the<ActivityEventIcon />wrapper, satisfying thereact-x/static-componentsrule while preserving identical render output.web/package.json (1)
69-69: @eslint-react/eslint-plugin@5.7.1 peer dependencies are compatible with the current toolchain.The package requires
eslint@^10.2.1andtypescript@*, both satisfied by eslint@10.3.0 and typescript@6.0.3 in the stack. No overrides needed.
| const navigateToDocs = useCallback(() => { | ||
| window.location.href = ROUTES.DOCUMENTATION | ||
| }, []) | ||
| const openNotificationDrawer = useCallback(() => { | ||
| window.dispatchEvent(new CustomEvent('open-notification-drawer')) | ||
| }, []) |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | 💤 Low value
openNotificationDrawer could bypass the event bus and call state directly.
The callback dispatches open-notification-drawer on window and relies on the useEffect listener (line 88) in the same component to call setNotificationDrawerOpen(true). This is a self-message via a global event. It is functionally correct (custom events are synchronous), and intentionally mirrors the pattern in Sidebar.tsx (window.dispatchEvent(new CustomEvent('open-notification-drawer'))), so the indirection is justified for cross-component consistency.
If that cross-component consistency argument ever becomes moot (e.g., the Sidebar is refactored to call the state setter directly), consider collapsing this to:
♻️ Simpler alternative (no window access needed)
- const openNotificationDrawer = useCallback(() => {
- window.dispatchEvent(new CustomEvent('open-notification-drawer'))
- }, [])
+ const openNotificationDrawer = useCallback(() => {
+ setNotificationDrawerOpen(true)
+ }, [])📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const navigateToDocs = useCallback(() => { | |
| window.location.href = ROUTES.DOCUMENTATION | |
| }, []) | |
| const openNotificationDrawer = useCallback(() => { | |
| window.dispatchEvent(new CustomEvent('open-notification-drawer')) | |
| }, []) | |
| const navigateToDocs = useCallback(() => { | |
| window.location.href = ROUTES.DOCUMENTATION | |
| }, []) | |
| const openNotificationDrawer = useCallback(() => { | |
| setNotificationDrawerOpen(true) | |
| }, []) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/components/layout/AppLayout.tsx` around lines 129 - 134, Replace the
global CustomEvent call in openNotificationDrawer with a direct state update:
locate openNotificationDrawer in AppLayout.tsx and change its body from
window.dispatchEvent(new CustomEvent('open-notification-drawer')) to calling the
state setter setNotificationDrawerOpen(true) (the same setter used in the
component's useEffect listener); if other components like Sidebar.tsx currently
rely on the window event, update them to call the same setter (or lift/shared
state/context) so the global event and CustomEvent usage can be removed for
consistency.
Implements 5 of the 6 actionable items from the CodeRabbit review on PR #1704. The skipped item is the `openNotificationDrawer` direct-call suggestion (`AppLayout.tsx:129-134`), which the reviewer themselves classified as Trivial / Low-value and acknowledged as intentional cross-component-bus consistency with `Sidebar.tsx`. Changes: - `VersionHistorySection.tsx`: advance `requestEpochRef` on unmount so any in-flight `client.list()` promise that settles after the component is gone discards its result instead of calling `setItems` / `setError` / `setLoading` against an unmounted tree. React 19 silently swallows post-unmount setState, but the explicit cleanup keeps the epoch-based cancellation contract honest. - `useViewportSize.ts`: clarify the module comment. In a browser context `readSnapshot()` is called synchronously during the first render and returns the real `window.inner*` dimensions immediately; the `{ width: 0, height: 0 }` SSR_SNAPSHOT is only the server-snapshot argument to `useSyncExternalStore`. Replaces the misleading "before subscription / before resize" framing. - `ApprovalRiskGroupSection.tsx`: replace the terse per-line `eslint-disable` justification with a longer explanation that documents why this stays a `getRiskLevelIcon` getter rather than the canonical wrapper-component pattern: `SectionCard.icon` expects a `LucideIcon` component reference, not a JSX node, so a parameterised wrapper like `<RiskLevelIcon riskLevel=... />` cannot be plugged in. The const-Record lookup returns a stable reference per level and the rule does not fire because the result is consumed as a prop, not as `<Icon />` JSX in this body. - `activity-event-icon.tsx`: drop the duplicated `ACTIVITY_ICON_MAP` / `FALLBACK_ICON` declarations. Delegate to the existing `getActivityEventIcon()` exported from `@/utils/agents` so the Record stays a single source of truth. - `input-field.tsx`: align the `hasLeadingIcon` / `hasTrailingElement` flags passed to `buildInputClasses` with the stricter `!= null && !== false` render guards on the icon `<span>`s, so the padding flag and JSX presence agree on every legal `ReactNode` value (including `0`, `''`, `false`).
<!-- HIGHLIGHTS_START --> ## Highlights > _AI-generated summary (model: `openai/gpt-4.1-mini` via GitHub Models). Commit-based changelog below._ ### What you'll notice - Frontend and UX polishing improves user interface responsiveness and visual consistency. - API hygiene and validation enhancements provide smoother and more reliable interactions. ### What's new - Introduced typed-boundary helpers enabling better type safety and parse_typed workflows. - Added codebase-audit skill prompt tuning for improved project auditing. ### Under the hood - Eliminated flaky tests caused by module-level state for more stable test outcomes. - Unified image tag management under CLI and Renovate for consistent dependency updates. - Added cross-PR file-overlap analysis to the review dependency pull request skill. - Updated multiple dependencies including Python, Web, CLI, and container libraries. - Improved CI tooling and lock file maintenance for better build reliability. <!-- HIGHLIGHTS_END --> :robot: I have created a release *beep* *boop* --- ## [0.7.8](v0.7.7...v0.7.8) (2026-05-03) ### Features * **api:** typed-boundary helper + codebase-audit skill prompt tuning ([#1712](#1712)) ([40ee65b](40ee65b)) * **boundary:** RFC [#1711](#1711) Phases 2 + 3 — typed boundaries via parse_typed ([#1720](#1720)) ([7b9f409](7b9f409)) ### Bug Fixes * **api:** audit cleanup B -- API hygiene & validation ([#1719](#1719)) ([3d790d9](3d790d9)) * audit cleanup C - persistence, concurrency & data integrity ([#1708](#1708)) ([#1717](#1717)) ([bcce097](bcce097)) * **test:** exterminate xdist-flaky tests with module-level state ([#1713](#1713)) ([#1721](#1721)) ([8d258dd](8d258dd)) * **web:** audit cleanup E -- frontend & UX polish ([#1710](#1710)) ([#1718](#1718)) ([3a3591a](3a3591a)) ### Refactoring * **cli:** single source of truth for DHI image tags + Renovate manager ([#1723](#1723)) ([57980a2](57980a2)) ### Documentation * audit cleanup D -- public-facing & docs sync ([#1709](#1709)) ([#1715](#1715)) ([ade03b7](ade03b7)) ### Tests * **engine:** make TestDrainTimeout deterministic + preserve subclass type in [@Ontology](https://github.com/ontology)_entity ([#1729](#1729)) ([b00fb05](b00fb05)) ### CI/CD * Update CI tool dependencies ([#1703](#1703)) ([355a9ff](355a9ff)) ### Maintenance * add cross-PR file-overlap analysis to review-dep-pr skill ([#1722](#1722)) ([3861d8a](3861d8a)) * **ci:** unify apko-version under workflow env so Renovate manages it everywhere ([#1724](#1724)) ([9c0a7fd](9c0a7fd)) * consolidate DHI image-pin custom regex managers ([#1726](#1726)) ([b8b0cba](b8b0cba)) * **deps:** update dependency chainguard-dev/melange to v0.50.4 ([#1701](#1701)) ([8cbf83a](8cbf83a)) * Lock file maintenance ([#1705](#1705)) ([414cfea](414cfea)) * Lock file maintenance ([#1727](#1727)) ([5cb1212](5cb1212)) * Update CLI dependencies ([#1702](#1702)) ([9fb57b9](9fb57b9)) * Update Container dependencies ([#1698](#1698)) ([6d24fd6](6d24fd6)) * Update dependency @eslint-react/eslint-plugin to v5 ([#1704](#1704)) ([1cb1294](1cb1294)) * Update Python dependencies ([#1699](#1699)) ([8e7af3a](8e7af3a)) * Update Python dependencies to v4.15.0 ([#1725](#1725)) ([69164c8](69164c8)) * Update Web dependencies ([#1700](#1700)) ([715300d](715300d)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: synthorg-repo-bot[bot] <279117679+synthorg-repo-bot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR contains the following updates:
4.2.3→5.7.1Warning
Some dependencies could not be looked up. Check the Dependency Dashboard for more information.
Release Notes
Rel1cx/eslint-react (@eslint-react/eslint-plugin)
v5.7.1Compare Source
🐞 Fixes
allpreset: Fixed an issue where theallpreset accidentally included rules requiring type information (#1744).📝 Documentation
no-unused-staterule wording and examples.🏗️ Internal
nextand@rbxts/react.react-compiler-fixtures-all-preset.jsonlsnapshot generation.Full Changelog: Rel1cx/eslint-react@v5.7.0...v5.7.1
v5.7.0Compare Source
✨ New
react-x/no-unused-state: The rule re-added as a no-op inv5.6.6is now fully implemented. It detects state variables declared viauseState(or similar state hooks) that are defined but never read, or only read inside an effect or effect dependency array (#1741).📝 Documentation
no-unused-statemigration docs and removed rule reasons.Full Changelog: Rel1cx/eslint-react@v5.6.6...v5.7.0
v5.6.6Compare Source
✨ New
react-x/no-unused-state: Re-add thereact-x/no-unused-staterule that was removed in5.0.0as a no-op rule for detecting unused state in function components in a future release.Full Changelog: Rel1cx/eslint-react@v5.6.4...v5.6.6
v5.6.4Compare Source
✨ New
react-x/no-unused-class-component-members: Now flagsshouldComponentUpdatemethods defined in classes extendingPureComponentas unused, sincePureComponentimplements its ownshouldComponentUpdatewith shallow prop and state comparison (#1738).📝 Documentation
jsxpreset documentation to multiple rule docs.🏗️ Internal
ast: Added an optionalstoppredicate tofindParentutility for more control over ancestor traversal (#1736).skottwithsentruxfor architecture linting.Full Changelog: Rel1cx/eslint-react@v5.6.3-beta.0...v5.6.4
v5.6.2Compare Source
🐞 Fixes
react-x/use-memo: Fixed false positives inuseMemodependency analysis by using reference/definition analysis (#1735).📝 Documentation
custom-rules-of-staterecipe.noDirectAccessPropscustom rule example.🏗️ Internal
lucide-reactfrom 1.12.0 to 1.14.0.baseline-browser-mappingto 2.10.24.Full Changelog: Rel1cx/eslint-react@v5.6.0...v5.6.2
v5.6.0Compare Source
This release consolidates all changes since v4.2.1.
💥 Breaking Changes
Core API Refactoring (@eslint-react/core)
component/,function/,hook/,semantic/, andapi/into the root directory.isReactAPI→isAPIisReactAPICall→isAPICallisInitializedFromReact→isAPIFromReactisInitializedFromReactNative→isAPIFromReactNativeComponentDetectionHint→FunctionComponentDetectionHintComponentFlag→FunctionComponentFlaggetComponentCollector→getFunctionComponentCollectorgetComponentCollectorLegacy→getClassComponentCollectortype-is,type-name,type-variant) fromeslint-plugin-react-xto@eslint-react/core.Toolkitinterface in@eslint-react/kitto reflect the naming changes above.Kit API Simplification (@eslint-react/kit)
RuleToolkit.isAPI: Removed pre-built identifier predicates (memo,lazy,forwardRef, etc.) fromRuleToolkit.is. Only*Callvariants andAPI/APICallfactories are now available.initializedFromReact→APIFromReactinitializedFromReactNative→APIFromReactNativeis.memo(node),is.lazy(node), etc. must migrate tois.memoCall(node)or useis.API("memo")(node).Type Alias Removal
RuleDefinitiontype alias: TheRuleDefinitiontype has been completely removed from@eslint-react/kit. UseRuleFunctioninstead.Removed Rules
The following rules have been removed from
eslint-plugin-react-x,eslint-plugin-react-dom, andeslint-plugin-react-debug:component-hook-factoriesreact-xno-redundant-should-component-updatereact-xno-unnecessary-use-callbackreact-xno-unnecessary-use-memoreact-xno-unused-statereact-xprefer-destructuring-assignmentreact-xprefer-namespace-importreact-xprefer-namespace-importreact-domdebug/class-componentreact-debugClass Component Support Deprecation
isClassComponent,isPureComponent, and various lifecycle checkers) have been marked as@deprecated, retaining only minimal compatibility support for existing rules.eslint-plugin-react-web-api, includingno-leaked-event-listener,no-leaked-interval, andno-leaked-timeout, have removed detection for Class Component lifecycles (componentDidMount/componentWillUnmount) and now only report on Hook Effects (useEffect, etc.).✨ New
New Rules
react-x/globals: New rule for restricting usage of global variables in React components.react-x/static-components: New rule for enforcing static component definitions. Enhanced with variable reference tracking and acreatedHerediagnostic to reduce false positives.react-web-api/no-leaked-fetch: New rule that detects leakedfetchcalls in effects, closing #1714.Kit Enhancements
ast.findParentutility to@eslint-react/kitfor traversing AST ancestors.node:crypto randomBytes).Custom Rule Examples
🐞 Fixes
Rule Fixes
react-x/error-boundaries: Fixed false positives on non-React code and resolved catch block over-reporting.react-x/set-state-in-effect: Improved validation accuracy.react-x/use-memo: Added reassignment check, aligned message IDs, and added support forfor-of/for-inloops.Config Fixes
Type Expression Fixes
Extract.unwrapfor type expressions and chain expressions.🪄 Improvements
API & Refactoring
ast: Normalized API naming conventions and rewrote Check helpers.ast: RenamedisJSXLike→isJSXElementOrFragmentandisMethodOrProperty→isPropertyOrMethod.@eslint-react/eslintpackage.@eslint-react/jsxfrom@eslint-react/coreinto a standalone utility package for static analysis of JSX patterns.@and#path aliases and replacedtsxwithvite-node.lib.tsmodules across multiple plugins.RuleConfigwithLinter.RulesRecordfrom ESLint.Core & AST Improvements
ast: UpdatedFunctionInitPathtypes to support method definitions and property arrow functions in class expressions.ast/isNodeEqual: FixedJSXNamespacedNamecomparison logic.Rule Improvements
react-x/static-components: Registered inall,x, anddisable-experimentalconfigs.react-rsc/function-definition: Added directive position and quote checks.lib.tsfiles.Website & Documentation Improvements
/llms.txt,/llms-full.txt,/llms.mdx).Testing
Dependencies
@typescript-eslintpackages to 8.59.1.tsl-dx,tsdown,fumadocs,postcss,lucide-react,eslint-plugin-package-json, and other dependencies.📝 Documentation
no-set-state,no-string-refs).🏗️ Internal
build:pluginsscript and updated build path patterns.publishConfig.accessto packages and marked@local/effas private.major-release-checklist.md.scripts/prepare-release.tsand the accompanyingprepare:releasenpm script.Full Changelog: Rel1cx/eslint-react@v4.2.1...v5.6.0
Configuration
📅 Schedule: (in timezone Etc/UTC)
* 0-6 * * 6)🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.