From b13f2790df75718535a8993208f3aac168c9fe02 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Sun, 26 Jul 2026 06:47:08 +0200 Subject: [PATCH] chore(gui): document intentional react-doctor policy disables Keep doctor.config.json rule disables and the rationale in .react-doctor-ignores.md separate from the code-fix PR so reviewers can weigh SPA architecture tradeoffs without blocking correctness/a11y landings. --- gui/.react-doctor-ignores.md | 19 +++++++++++++++++++ gui/doctor.config.json | 20 ++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 gui/.react-doctor-ignores.md diff --git a/gui/.react-doctor-ignores.md b/gui/.react-doctor-ignores.md new file mode 100644 index 000000000..8dc330195 --- /dev/null +++ b/gui/.react-doctor-ignores.md @@ -0,0 +1,19 @@ +# Intentional React Doctor rule disables + +Documented rationale for `rules` set to `"off"` in `doctor.config.json`. +Re-enable a rule when the matching architecture debt is paid down. + +| Rule | Why off | +| --- | --- | +| `no-fetch-in-effect` | Vite SPA dashboard with no React Query/SWR; effects use AbortController. Validation prompt allows this for small apps without a data layer. | +| `no-giant-component` | Provider workspace / Models shells are multi-panel surfaces; splitting is a separate refactor, not a doctor pass. | +| `prefer-useReducer` | Same shells; converting multi-`useState` to reducers is a behavior-sensitive refactor. | +| `no-pass-live-state-to-parent` / `no-pass-data-to-parent` / `no-prop-callback-in-effect` | Parent/child sync for Codex pool + dirty flags is intentional lift until those flows are redesigned. | +| `no-derived-state` / `no-derived-state-effect` | JSON config editor keeps an editable `draft` that starts from `config` then diverges — classic controlled-draft pattern. | +| `only-export-components` | `QuotaBars` / `ProviderRail` co-locate small helpers with the component for Fast Refresh tradeoff accepted in this app. | +| `prefer-html-dialog` | Several overlays already use native ``; remaining `role="dialog"` shells need a dedicated migration (focus + open state). | +| `js-hoist-intl` | Locale-keyed formatters are created with varying options; module-level caches are partial. Low user impact vs churn. | +| `no-loading-flag-reset-outside-finally` | Many hits already reset inside `finally` with generation/`silent` guards the detector does not accept; others intentionally keep loading across retries. | +| `rerender-state-only-in-handlers` | Dirty/modal id state is used for control flow outside JSX text. | +| `prefer-use-effect-event` | Optional React 19 polish; deferred to avoid mixed patterns mid-cleanup. | +| `js-combine-iterations` | Readability preferred over micro one-pass rewrites on small lists. | diff --git a/gui/doctor.config.json b/gui/doctor.config.json index 98b61f782..f9bd272c2 100644 --- a/gui/doctor.config.json +++ b/gui/doctor.config.json @@ -1,9 +1,25 @@ { "$schema": "https://react.doctor/schema/config.json", - "scope": "changed", - "base": "origin/main", + "scope": "full", "blocking": "none", "ignore": { "files": ["dist/**", "node_modules/**"] + }, + "rules": { + "react-doctor/no-fetch-in-effect": "off", + "react-doctor/no-giant-component": "off", + "react-doctor/prefer-useReducer": "off", + "react-doctor/no-pass-live-state-to-parent": "off", + "react-doctor/no-pass-data-to-parent": "off", + "react-doctor/no-prop-callback-in-effect": "off", + "react-doctor/no-derived-state": "off", + "react-doctor/no-derived-state-effect": "off", + "react-doctor/only-export-components": "off", + "react-doctor/prefer-html-dialog": "off", + "react-doctor/js-hoist-intl": "off", + "react-doctor/no-loading-flag-reset-outside-finally": "off", + "react-doctor/rerender-state-only-in-handlers": "off", + "react-doctor/prefer-use-effect-event": "off", + "react-doctor/js-combine-iterations": "off" } }