first
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user