diff --git a/.gitignore b/.gitignore index 3c3629e..97ef1eb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +docs/archive node_modules diff --git a/AGENTS.md b/AGENTS.md index e51daef..e93a813 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,10 +4,12 @@ ``` gadget/ -├── packages/ai/ @gadget/ai — AI API abstraction (source of truth) -├── gadget-code/ Web service + browser IDE -├── gadget-drone/ Worker process (agentic workflow loop) -└── pnpm-workspace.yaml Monorepo workspace definition +├── packages/ +│ ├── ai/ @gadget/ai — AI API abstraction (Ollama + OpenAI) +│ ├── api/ @gadget/api — Shared TypeScript interfaces +│ └── config/ @gadget/config — Env config loader +├── gadget-code/ Web service — Express 5, React 19, browser IDE +└── gadget-drone/ Worker process — Agentic workflow loop ``` ## Rules for AI Code @@ -24,72 +26,90 @@ The ecosystem speaks **one** AI API language defined by `@gadget/ai`. All rules ```bash pnpm install # Install all workspace packages pnpm -r build # Build all packages + +# Per-package build pnpm --filter @gadget/ai build +pnpm --filter @gadget/api build +pnpm --filter @gadget/config build +pnpm --filter gadget-code build:backend # backend → dist/ + resolves @/* aliases pnpm --filter gadget-drone build -pnpm --filter gadget-code build:backend -pnpm --filter gadget-code dev -pnpm --filter gadget-drone dev + +# Run dev servers +pnpm --filter gadget-code dev # Backend on https://localhost:3443 +pnpm --filter gadget-drone dev # Drone worker + +# In gadget-code/frontend +pnpm dev # Frontend on https://localhost:5174 + +# Typecheck +pnpm --filter @gadget/ai typecheck # Only package with a typecheck script ``` ## Key Conventions - All packages are **ES modules** (`"type": "module"`). -- `@gadget/ai` uses `moduleResolution: NodeNext` and emits to `dist/`. +- `@gadget/ai`, `@gadget/api`, `@gadget/config` use `moduleResolution: NodeNext` and emit to `dist/`. - gadget-drone uses `moduleResolution: NodeNext`. -- gadget-code uses `moduleResolution: bundler` with `@/*` path aliases. +- gadget-code uses `moduleResolution: bundler` with `@/*` path aliases → `src/*`. +- **gadget-code build requires `tsc-alias`** to resolve `@/*` path aliases in output. - Dependency versions are pinned in `package.json` — no ranges. Use the workspace protocol (`workspace:*`) for internal package references. -- pnpm version is enforced at the workspace root (`packageManager` field). +- pnpm version enforced at the workspace root (`packageManager` field). +- **No lint scripts exist** in any package. ## TypeScript Strictness -| Package | Strictness | -| ------------ | ---------------------------------------------------------------------------------- | -| `@gadget/ai` | `strict: true` | -| gadget-drone | `strict: true` | -| gadget-code | `strict: true`, `noUnusedLocals`, `noUnusedParameters`, `noUncheckedIndexedAccess` | - -## Adding Code - -When adding a new feature or service, determine its scope: - -- **Shared AI concern** (AI logging, config schema) → goes in `@gadget/ai` -- **Drone-only** (Bull queue, workspace file operations) → goes in gadget-drone -- **Web-only** (Express routes, Mongoose models, session management) → goes in gadget-code - -If code is needed by both consumer packages, it belongs in `@gadget/ai`. Do not copy-paste shared logic across packages. +| Package | Strictness | +| -------------- | ---------------------------------------------------------------------------------- | +| `@gadget/ai` | `strict: true` | +| `@gadget/api` | `strict: true` | +| `@gadget/config` | `strict: true` | +| `gadget-drone` | `strict: true` | +| `gadget-code` | `strict: true`, `noUnusedLocals`, `noUnusedParameters`, `noUncheckedIndexedAccess` | ## GadgetId -All entity IDs use the `GadgetId` type (a string alias) defined in `@gadget/api`. This eliminates MongoDB `ObjectId` conversion throughout the codebase. - -### Interfaces - -Always specify `{ _id: GadgetId }` in interfaces: +All entity IDs use `GadgetId` (a string alias) from `@gadget/api`. Never use `ObjectId`. ```ts import { GadgetId } from "@gadget/api"; interface IMyEntity { _id: GadgetId; - // ... other fields } ``` -### Mongoose Schemas - -Always use this pattern for `_id`: - +**Mongoose schema pattern:** ```ts _id: { type: String, default: () => nanoid() } ``` -**Never add `unique: true` or `required: true` to `_id`**: -- `unique: true` causes duplicate index errors at startup (MongoDB auto-creates a unique index on `_id`) -- `required: true` causes save failures because the default is assigned AFTER validation +**Never add `unique: true` or `required: true` to `_id`**: MongoDB auto-creates a unique index on `_id` (causes duplicate index errors if `unique` is also set), and the default is assigned after validation (causes save failures if `required` is set). -### Rules +See `gadget-code/docs/gadget-id.md` for full documentation. -1. All `_id` fields are `GadgetId` (string) -2. No `ObjectId` usage in application code -3. No `createFromHexString()` or `toHexString()` conversions -4. Never `unique` or `required` on `_id` in schemas +## Testing + +- `gadget-code`: Vitest unit tests (`pnpm test`). Vitest config excludes `tests/e2e/`. +- E2E tests: Playwright targets `https://code-dev.g4dge7.com:5174` (requires running dev servers). +- Seed test drones: `cd gadget-code && npx tsx scripts/seed-test-drones.ts` +- `gadget-drone`: No tests configured. + +## Adding Code + +When adding a new feature or service, determine its scope: + +- **Shared AI concern** (AI logging, config schema) → goes in `@gadget/ai` +- **Shared types** → goes in `@gadget/api` +- **Config loading** → goes in `@gadget/config` +- **Drone-only** (Bull queue, workspace file operations) → goes in `gadget-drone` +- **Web-only** (Express routes, Mongoose models, session management) → goes in `gadget-code` + +If code is needed by both consumer packages, it belongs in the appropriate shared package. Do not copy-paste shared logic across packages. + +## Prerequisites + +- Node.js 22+ +- pnpm (version enforced at root `packageManager` field) +- MongoDB on `localhost:27017` +- Redis on `localhost:6379` +- SSL certificates in `gadget-code/ssl/` directory (for dev servers)