git:20260313.239e27b to git:20260416.5b3255e

16 added, 0 removed. Audit A to A.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## GenAI Engine UI
React-based frontend for the GenAI Engine, providing interfaces for task management, prompt playground, dataset management, trace visualization, and model provider configuration.
### Common Commands
```bash
# Install dependencies
yarn install
# Development server (localhost:3000)
yarn dev
# Build for production
yarn build
# Preview production build
yarn preview
# Type checking
yarn type-check
# Linting
yarn lint
# Run both type checking and linting
yarn check
# Format code
yarn format
yarn format:check
# Generate API client from backend OpenAPI spec
yarn generate-api:clean
```
### Architecture
**Tech Stack**: React 19, TypeScript 5.9, Vite, Material-UI (MUI), Tailwind CSS 4, React Router v7, TanStack Query, Yarn Berry v4
**Core Structure**:
- **Components** (`src/components/`): Feature-based organization (prompts, datasets, traces, weaviate, common)
- **Contexts** (`src/contexts/`): React Context for global state (AuthContext, TaskContext)
- **Hooks** (`src/hooks/`): Custom React hooks for API interactions and shared logic
- **API Client** (`src/client/`): Auto-generated TypeScript client from backend OpenAPI spec
- **Pages** (`src/pages/`): Top-level route components
- **Router** (`src/router.tsx`): React Router v7 configuration with protected routes
**Key Patterns**:
- **Auto-Generated API Client**: The TypeScript API client is generated from the GenAI Engine's OpenAPI spec using `yarn generate-api:clean`. Never manually edit files in `src/client/` - regenerate instead
- **Context + Hooks Architecture**: Global state (auth, tasks) lives in Context, accessed via custom hooks
- **Protected Routes**: AuthContext wraps the router and guards routes requiring authentication
- **Material-UI + Tailwind**: MUI components provide the foundation, Tailwind CSS handles custom styling
- **React Query**: TanStack Query manages server state, caching, and data synchronization
- **Monaco Editor**: Embedded code editor for prompt and rule editing
- **Type Safety**: Strict TypeScript mode enabled, all API responses are typed via generated client
**Component Organization**:
- **Common components** (`src/components/common/`): Reusable UI elements (buttons, inputs, dialogs)
- **Feature components**: Organized by domain (prompts, datasets, traces, weaviate)
- Each feature typically has: list view, detail view, create/edit forms
**Routing**:
- React Router v7 with client-side navigation
- Protected routes check authentication status before rendering
- Lazy loading for code splitting (not yet implemented but supported)
**API Integration**:
- Backend runs on configurable base URL (default: localhost:5005)
- All API calls go through the generated client
- Request/response interceptors handle authentication headers
- Error handling via React Query's error boundaries
+ ### useEffect Discipline
+
+ Before writing a `useEffect`, ask: **"Is this synchronizing with an external system?"** If not, you probably don't need it. See [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect).
+
+ **Do NOT use `useEffect` to:**
+
+ - **Derive or transform state** from props/state — compute it during rendering (`const x = a + b`)
+ - **Cache expensive calculations** — use `useMemo` instead
+ - **Reset state when a prop changes** — pass a `key` to the component instead
+ - **Run event-specific logic** (form submits, button clicks) — put it in the event handler
+ - **Notify parent components of state changes** — call parent callbacks directly in event handlers
+ - **Chain effects** that set state to trigger other effects — batch updates in a single event handler or compute during render
+ - **Fetch data** — use TanStack Query (`useQuery`/`useMutation`) which handles caching, race conditions, and loading states; raw `useEffect` fetches are error-prone
+
+ **Legitimate `useEffect` uses:** synchronizing with browser APIs or third-party libraries, analytics on mount, subscriptions to external stores (prefer `useSyncExternalStore`).
+
### TanStack Form
The codebase uses TanStack Form via custom wrappers in `src/components/traces/components/filtering/hooks/form.tsx`.
**Core hooks:**
- `useAppForm(options)` — creates a form with typed field components. Options: `defaultValues`, `validators`, `onSubmit`
- `withForm({ ...formOpts, props?, render })` — HOC for child components receiving the form. `props` declares extra props (with defaults) passed to render alongside `form`. Use named functions for render to satisfy ESLint hook rules. Prefer `withForm` over `withFieldGroup` for sub-components that need to display validation errors (proper error types via form-level validators).
- `withFieldGroup({ defaultValues, props?, render })` — HOC for reusable field groups. Render receives `group` with scoped `AppField`. **Caveat:** error types resolve to `never` — no `.message` property. Use `withForm` with absolute field paths instead when error display is needed.
**Field rendering:**
- `form.AppField name="path"` — typed field; children receive `field` with `state.value`, `handleChange`, `handleBlur`, `state.meta.errors`
- `form.Subscribe selector={fn}` — reactive subscription for conditional rendering
- `useStore(form.store, selector)` — direct store read (import from `@tanstack/react-form`)
**Validation:**
- Zod v4 schemas — use `{ error: "..." }` for custom messages (not `{ message: "..." }`). Use `path: ["field"]` on `.refine()` to target a specific nested field.
- `formApi.parseValuesWithSchema(schema)` (form-level) or `fieldApi.parseValueWithSchema(schema)` (field-level)
- Form-level validators can return `{ fields: { "path": error }, form: { key: error } }` — field errors auto-propagate to `field.state.meta.errors`
- Display: `error={field.state.meta.errors.length > 0}` + `helperText={field.state.meta.errors[0]?.message}` on MUI TextField
- **Clearing stale form-level errors:** `resetField()` does NOT clear errors from form-level validators (`parseValuesWithSchema`). Use `setFieldMeta` to explicitly clear `errorMap.onSubmit`:
```tsx
form.setFieldMeta(path, (prev) => ({ ...prev, errorMap: { ...prev.errorMap, onSubmit: undefined } }));
```
**Form state:**
- `form.state.isDirty` — persistent dirty (true once any field changed, even if reverted)
- `form.state.isSubmitting`, `form.state.canSubmit`, `form.state.isValid`
**Multi-step pattern:**
- A `section` field tracks the current step. Forward navigation uses `form.handleSubmit()` (triggers validation). Back navigation sets section directly via `form.setFieldValue("section", prev)` (skips validation).
### Before Committing (REQUIRED - CI Enforced)
Always run and ensure these pass before committing UI changes:
```bash
yarn check # Runs type-check, lint, and format:check
```
Fix any errors before committing. CI will block PRs with failures.
If you need to auto-fix formatting issues, run `yarn format` first.
### Development Notes
- The API client must be regenerated after backend OpenAPI spec changes
- Follow the component patterns in AGENTS.md for consistency
- Use MUI's sx prop or Tailwind classes for styling, avoid inline styles
- Authentication token is stored in localStorage and managed by AuthContext
- The app is a SPA - no server-side rendering