fabro/apps/fabro-web/app/lib
Bryan Helmkamp 62f0b3e7d1
refactor(web): improve React Doctor score (#405)
## Summary

Improves the web UI's React Doctor audit score by separating reusable
helpers from React component modules, tightening effect/state ownership,
and extracting real component boundaries in the install wizard, stage
activity view, run-files diff browser, RunDetail route, and Runs
workspace. The branch removes the previously deferred RunDetail and Runs
giant-component diagnostics without changing RunDetail UX, route
contracts, action ordering, or Runs workspace behavior.

| Metric | Main baseline | Initial PR | Current PR |
|--------|---------------|------------|------------|
| React Doctor score | 63 | 71 | 99 |
| React Doctor errors | 123 | 0 | 0 |
| React Doctor warnings | 241 | 163 | 3 |
| React Doctor diagnostics | 364 | 163 | 3 |

## Changes

- Moves exported helper logic out of component files so Fast
Refresh/component-export rules no longer dominate the audit.
- Adds a targeted React Doctor config exception for React Router route
modules, where non-component exports like route metadata are
intentional.
- Refactors low-risk state/effect patterns: keyed interview question
state, reducer-backed editable run title state, event-owned preview
opening, route-keyed insights editor initialization, refresh timer
ownership, and selection/derived list cleanup.
- Reworks `InstallApp` around an install reducer, a controller hook for
install lifecycle state, and focused wizard step components for LLM,
server, object-store, sandbox, and GitHub setup.
- Moves `RunStages` selected-stage activity into a keyed boundary for
panel/debug detail state while preserving stage activity filters across
navigation.
- Extracts the `RunFiles` loaded diff-browser view from route/query
coordination so the route owns data/URL state and the loaded view owns
rendering.
- Splits `RunDetail` into route-local header, actions, tab shell, docked
controls, model, and lifecycle-toast modules; the actions menu now uses
grouped descriptors instead of a large boolean/callback prop matrix.
- Extracts Runs workspace preference ownership into
`useRunsWorkspacePreferences` and moves toolbar rendering into
`RunsToolbar`, leaving the route focused on data, DnD state, filtering,
and view selection.
- Guards `InsightsEditor` query execution with a latest-run id and
timeout cleanup so stale or unmounted mock query runs cannot overwrite
newer results.
- Adds regression coverage for archived-run deletion from RunDetail and
stale-result handling in InsightsEditor.
- Improves semantic/accessibility coverage with labeled controls, native
meter/section semantics, decorative status dots, and clearer unavailable
copy.
- Removes dead UI code and applies local suppressions only where the
rule is a documented false positive or an intentional imperative
integration boundary.

## Remaining React Doctor warnings

Current score is 99 with 0 errors and 3 warnings. The remaining warnings
are intentionally left for separate judgment rather than mechanical
churn:

- `prefer-useReducer` (3): `AutomationsNew`, `InsightsEditor`, and
`CreateSecretForm` need reducers only if they encode real coupled
transitions, not simple field setters.

## Verification

- `cd apps/fabro-web && bun test app/routes/run-detail.test.ts` -> `22
pass`, `0 fail`
- `cd apps/fabro-web && bun test app/routes/insights-editor.test.tsx
app/routes/runs.preferences.test.tsx` -> `7 pass`, `0 fail`
- `cd apps/fabro-web && bun run typecheck`
- `cd apps/fabro-web && bun test --isolate` -> `490 pass`, `0 fail`
- `cd apps/fabro-web && bunx react-doctor@latest --full --json >
/tmp/fabro-react-doctor-runs-insights.json` -> score `99`, `0` errors,
`3` warnings
- Earlier branch verification also included `cd apps/fabro-web && bun
run build`
- `git diff --check`

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 (context not reported, default reasoning) via
[Codex](https://openai.com/codex)
2026-05-25 22:41:37 -04:00
..
api-client.test.ts fix(api): type interview answer submissions 2026-05-08 09:18:35 -07:00
api-client.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
ask-fabro-layout.tsx refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
ask-fabro-runtime.test.ts fix: render Ask Fabro session responses 2026-05-22 12:32:59 -04:00
ask-fabro-runtime.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
board-cache.ts feat(web): upgrade Children sub-tab to use the runs list view 2026-05-25 12:48:18 -04:00
board-events.test.tsx Runs list view: table layout, server-side sort/pagination, redesigned toolbar (#367) 2026-05-23 14:25:58 -04:00
board-events.ts Replace queued with pending/runnable and add approval flow (web + API s… (#371) 2026-05-23 15:34:33 -04:00
chats-runtime.test.ts feat(fabro-web): port /chats/new + /chats/:id from prototype (#289) 2026-05-16 17:10:16 -04:00
chats-runtime.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
chats-script.ts feat(fabro-web): port /chats/new + /chats/:id from prototype (#289) 2026-05-16 17:10:16 -04:00
chats-store.test.tsx feat(fabro-web): port /chats/new + /chats/:id from prototype (#289) 2026-05-16 17:10:16 -04:00
chats-store.tsx refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
chats-types.ts feat(fabro-web): port /chats/new + /chats/:id from prototype (#289) 2026-05-16 17:10:16 -04:00
cross-tab-sse.test.ts fix(web): recover cross-tab SSE coordination after fallback 2026-05-04 15:52:18 -04:00
cross-tab-sse.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
demo-mode.test.tsx feat: wire web UI to real server with demo mode toggle 2026-04-08 04:46:08 -04:00
demo-mode.tsx refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
format.ts feat(web): add models table to /settings/models 2026-05-25 15:21:40 -04:00
graph-theme.ts refactor(web): drop light mode, go dark-only 2026-04-20 09:27:08 -04:00
live-events.test.tsx feat(web): build live events page in settings 2026-05-10 14:05:10 -04:00
live-events.ts refactor: remove compatibility shims (#281) 2026-05-16 15:29:25 -04:00
mutations.test.ts Replace queued with pending/runnable and add approval flow (web + API s… (#371) 2026-05-23 15:34:33 -04:00
mutations.ts feat: remove demo-mode toggle button and endpoint 2026-05-25 15:35:37 -04:00
pierre-diffs-worker.ts fix(web): virtualize run file diffs consistently 2026-05-05 16:41:39 -04:00
plural.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
queries.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
query-keys.test.ts Fold context-window data into agent.message, remove snapshot event (#390) 2026-05-24 15:48:21 -04:00
query-keys.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
run-actions.test.ts Allow retrying cancelled runs 2026-05-24 18:28:16 -04:00
run-actions.ts feat(web): add More menu with Approve + Delete to bulk toolbar 2026-05-25 12:57:05 -04:00
run-events.test.tsx Fold context-window data into agent.message, remove snapshot event (#390) 2026-05-24 15:48:21 -04:00
run-events.ts Fold context-window data into agent.message, remove snapshot event (#390) 2026-05-24 15:48:21 -04:00
run-phases.test.ts Replace queued with pending/runnable and add approval flow (web + API s… (#371) 2026-05-23 15:34:33 -04:00
run-phases.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
run-settings-snapshot.ts refactor: remove compatibility shims (#281) 2026-05-16 15:29:25 -04:00
sandbox-state.ts feat(web): show sandbox status dot on the run overview panel 2026-05-21 11:28:39 -04:00
session-stream.test.ts fix: render Ask Fabro session responses 2026-05-22 12:32:59 -04:00
session-stream.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
sse.ts Runs list view: table layout, server-side sort/pagination, redesigned toolbar (#367) 2026-05-23 14:25:58 -04:00
stage-sidebar.test.ts Sidebar polish: visit syntax, multi-select archive, settings logos, workspace prefs (#376) 2026-05-23 19:14:06 -04:00
stage-sidebar.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
test-utils.tsx feat(fabro-web): port /chats/new + /chats/:id from prototype (#289) 2026-05-16 17:10:16 -04:00
time.ts refactor(web): improve React Doctor score (#405) 2026-05-25 22:41:37 -04:00
unknown.ts refactor(web): narrow event property reads via shared helpers 2026-04-30 22:45:38 -04:00