# AGENTS.md

Guide for agentic coding assistants working in the Officer monorepo.

## Quick Start Commands

### Development

```bash
bun dev              # Dashboard + API server (port 5000)
bun dev:tracking    # Tracking server (port 5001)
bun dev:experiments # Experiments server
bun dev:emailer     # Emailer workspace
```

### Building & Database

```bash
bun run prebuild              # Run prebuild tasks
bun run build:dashboard       # Build dashboard
bun run build:editor          # Build editor (app + extension + runtime)
bun run build:runtime         # Build all runtime scripts
bun run db:gen && db:push     # Generate & push officer_db migrations
bun run db:gen:stats && db:push:stats  # Generate & push statistics_db
```

### Code Quality

```bash
bun format          # Format all files (Prettier, required before commit)
bun format:check    # Check formatting without writing
bunx tsgo           # TypeScript type checking (comprehensive, slow)
```

**Note:** No automated tests configured yet. Always run `bun format` before committing.

## Code Style Guide

### Imports

Order: **types → external → workspace → relative**

```ts
import type { Experiment } from 'types';
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useExperiment } from 'hooks/use-experiment';
import { formatDate } from '../helpers';
```

### TypeScript

- Strict mode always - no `any`
- Prefer `type` over `interface`
- Colocate prop types with components as named exports
- Early returns for null/undefined guards
- Use optional chaining and nullish coalescing: `obj?.prop ?? fallback`

### Functions

- Arrow functions for simple/one-liners
- Regular functions for complex multi-line logic
- Named exports only (never default exports)

```ts
export const formatDate = (ts: number) => new Date(ts).toLocaleDateString();
export function calculateStats(data: DataPoint[]) {
  /* ... */
}
```

### React Components

- Functional components with named prop types
- Arrow function syntax
- No useMemo/useCallback (React 19 compiler handles optimization)

```tsx
type CardProps = { title: string; onClick: () => void };
export const Card = ({ title, onClick }: CardProps) => <div onClick={onClick}>{title}</div>;
```

### State Management

- **Manager pattern** for complex hooks - return object with state + methods
- **Colocation** - all feature state in one hook
- **Derived state** - compute in hook, not in components

```ts
export const useExperimentManager = (id: number) => {
  const [exp, setExp] = useState<Experiment | null>(null);
  const isActive = exp?.status === 'running';
  return {
    exp,
    isActive,
    update: (data) => {
      /* ... */
    },
  };
};
```

### Naming Conventions

- **Components**: `PascalCase.tsx` (e.g., `ExperimentCard.tsx`)
- **Everything else**: `kebab-case.ts` (e.g., `use-experiment.ts`, `format-date.ts`)
- **Hooks**: `use-*.ts` or `useFeatureName.ts`

### Formatting (Prettier)

- Semicolons: always
- Quotes: single (JS/TS), double (JSX)
- Trailing commas: all
- Indent: 2 spaces
- Line width: 120 characters

### Error Handling

- Use try/catch for async operations
- Include context in error messages (IDs, resource names)
- Log with `console.error` and re-throw appropriately
- Handle database connection errors explicitly

### Async/Await

- Always use async/await (never .then() chains)
- Minimize nesting

## Project Structure

- `src/apps/dashboard/` - Admin UI (React 19)
- `src/apps/editor/` - Visual editor
- `src/servers/api/` - REST API (Hono, port 5000)
- `src/servers/tracking/` - Event collection (port 5001)
- `src/databases/` - PostgreSQL schemas (3 DBs: officer_db, statistics_db, ephemeral_db)
- `src/workspaces/` - Shared: components, hooks, helpers, types

## Path Aliases

- `@/` → `src/apps/dashboard/`
- `@@/` → `src/servers/`

## Tech Stack

- **Runtime**: Bun
- **Language**: TypeScript 5.9 (strict mode)
- **Frontend**: React 19, React Router, React Query, Tailwind CSS, shadcn/ui
- **Backend**: Hono, PostgreSQL, Drizzle ORM
- **Build**: Vite

## General Guidelines

- **Database-first** approach - schema → API → UI
- **Self-documenting code** - clear naming, minimal comments
- **Explicit over implicit** - no magic
- **Workspace dependencies** - use `workspace:*`
- **Environment variables** - use `.env`, access directly in code
