diff --git a/AGENTS.md b/AGENTS.md index 9986c8ca..a15279dd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,48 +11,87 @@ ## Project Context -Mosaic Stack is a self-hosted, multi-user AI agent platform. TypeScript monorepo with NestJS gateway, Next.js web dashboard, Pi SDK agent runtime, and plugin architecture for Discord/Telegram. +Mosaic Stack is a self-hosted, multi-user AI agent platform. It is a TypeScript monorepo with a NestJS gateway, Next.js dashboard, Pi SDK agent runtime, and Discord/Telegram plugin architecture. -## Package Map +### Stack -| Package | Purpose | Key Dependencies | -| ------------------ | ------------------------------- | -------------------------------- | -| `apps/gateway` | NestJS API + WebSocket hub | Fastify, Socket.IO, Pi SDK, OTEL | -| `apps/web` | Next.js dashboard | React 19, Tailwind | -| `packages/types` | Shared TypeScript contracts | class-validator | -| `packages/db` | Drizzle ORM schema + migrations | drizzle-orm, postgres | -| `packages/auth` | BetterAuth configuration | better-auth, @mosaicstack/db | -| `packages/brain` | Data layer (PG-backed) | @mosaicstack/db | -| `packages/queue` | Valkey task queue + MCP | ioredis | -| `packages/coord` | Mission coordination | @mosaicstack/queue | -| `packages/mosaic` | Unified `mosaic` CLI + TUI | Ink, Pi SDK, commander | -| `plugins/discord` | Discord channel plugin | discord.js | -| `plugins/telegram` | Telegram channel plugin | Telegraf | +- **API:** NestJS with Fastify (`apps/gateway`) +- **Web:** Next.js 16 with React 19 (`apps/web`) +- **ORM and database:** Drizzle ORM, PostgreSQL 17, and pgvector (`packages/db`) +- **Authentication:** BetterAuth (`packages/auth`) +- **Agent runtime:** Pi SDK (`apps/gateway`, `packages/mosaic`) +- **Queue:** Valkey 8 (`packages/queue`) +- **Build:** pnpm workspaces and Turborepo +- **CI:** Woodpecker CI +- **Observability:** OpenTelemetry and Jaeger -## Architecture Rules +### Package Map -1. Gateway is the single API surface — all clients connect through it -2. Pi SDK is ESM-only — gateway and CLI must use ESM -3. Socket.IO typed events defined in `@mosaicstack/types` enforce compile-time contracts -4. OTEL auto-instrumentation loads before NestJS bootstrap -5. BetterAuth manages auth tables; schema defined in `@mosaicstack/db` -6. Docker Compose provides PG (5433), Valkey (6380), OTEL Collector (4317/4318), Jaeger (16686) -7. Explicit `@Inject()` decorators required in NestJS (tsx/esbuild doesn't emit decorator metadata) +| Package | Purpose | Key Dependencies | +| ------------------ | ----------------------------- | -------------------------------- | +| `apps/gateway` | NestJS API + WebSocket hub | Fastify, Socket.IO, Pi SDK, OTEL | +| `apps/web` | Next.js dashboard | React 19, Tailwind | +| `packages/types` | Shared TypeScript contracts | class-validator | +| `packages/db` | Drizzle schema and migrations | drizzle-orm, postgres | +| `packages/auth` | BetterAuth configuration | better-auth, @mosaicstack/db | +| `packages/brain` | Structured data layer | @mosaicstack/db | +| `packages/queue` | Valkey task queue and MCP | ioredis | +| `packages/coord` | Mission coordination | @mosaicstack/queue | +| `packages/mosaic` | Unified `mosaic` CLI and TUI | Ink, Pi SDK, commander | +| `plugins/discord` | Discord channel plugin | discord.js | +| `plugins/telegram` | Telegram channel plugin | Telegraf | + +## Architecture and Code Conventions + +1. Gateway is the single API surface; all clients connect through it. +2. Pi SDK is ESM-only; gateway and CLI code must remain ESM. +3. Use `"type": "module"`, NodeNext module resolution, and `.js` extensions in imports. +4. Keep typed Socket.IO events in `@mosaicstack/types` to enforce client/server contracts. +5. Import OTEL tracing before NestJS bootstrap (`import './tracing.js'`). +6. Use explicit `@Inject()` decorators in NestJS because tsx/esbuild does not emit decorator metadata. +7. Keep DTOs in `*.dto.ts` files at module boundaries. +8. BetterAuth owns authentication tables; their schema is defined in `@mosaicstack/db`. +9. Create a task-specific scratchpad for non-trivial work. ## Development Workflow +Requirements: Node.js 20+, pnpm 10.6.2, and Docker Compose when optional local services are needed. + ```bash -docker compose up -d # Infrastructure -pnpm install # Dependencies -pnpm typecheck && pnpm lint && pnpm format:check # Quality gates +pnpm install --frozen-lockfile +pnpm preflight + +# Optional local queue service only; do not start the full Compose stack. +docker compose up -d valkey ``` -## Repo-Specific Notes +The pre-push hook requires: -- DTOs in `*.dto.ts` files at module boundaries -- ESM everywhere (`"type": "module"`, `.js` extensions in imports) -- NodeNext module resolution in all tsconfigs -- Scratchpads are mandatory for non-trivial tasks +```bash +pnpm preflight && pnpm typecheck && pnpm lint && pnpm format:check +``` + +Software delivery also requires the applicable tests. Common repository commands are: + +```bash +pnpm typecheck # TypeScript checks across the workspace +pnpm lint # ESLint across the workspace +pnpm test # Checkout tests and package Vitest suites +pnpm format:check # Prettier check +pnpm build # Build all packages and applications +``` + +## Database and Local Runtime Safety + +- Current local data-layer work uses in-process PGlite; leave `DATABASE_URL` unset. +- PostgreSQL execution is held until KBN-101-00, KBN-101-03, and KBN-101-05 land. +- Do not invoke a migration runner, initialization SQL, or the Compose PostgreSQL service from this checkout. +- Do not start Gateway/Web or run root `pnpm dev` as a local PGlite route. The current dotenv loader can inherit a daemon PostgreSQL DSN; KBN-101-02 must make that path fail closed first. +- Migration artifact generation is offline and does not authorize PostgreSQL access: + +```bash +pnpm --filter @mosaicstack/db db:generate +``` ## docs/TASKS.md — Schema (CANONICAL) diff --git a/CLAUDE.md b/CLAUDE.md index 8876a145..ee90e7ea 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,46 +1,5 @@ -# CLAUDE.md — Mosaic Stack +# Claude Compatibility Pointer -## Project +@AGENTS.md -Self-hosted, multi-user AI agent platform. TypeScript monorepo. - -## Stack - -- **API**: NestJS + Fastify adapter (`apps/gateway`) -- **Web**: Next.js 16 + React 19 (`apps/web`) -- **ORM**: Drizzle ORM + PostgreSQL 17 + pgvector (`packages/db`) -- **Auth**: BetterAuth (`packages/auth`) -- **Agent**: Pi SDK (`packages/agent`, `packages/mosaic`) -- **Queue**: Valkey 8 (`packages/queue`) -- **Build**: pnpm workspaces + Turborepo -- **CI**: Woodpecker CI -- **Observability**: OpenTelemetry → Jaeger - -## Commands - -```bash -pnpm typecheck # TypeScript check (all packages) -pnpm lint # ESLint (all packages) -pnpm format:check # Prettier check -pnpm test # Vitest (all packages) -pnpm build # Build all packages - -# Database -pnpm --filter @mosaicstack/db db:generate # Offline migration artifact generation only -# PostgreSQL execution is held until KBN-101-00/-03/-05 land. Do not invoke a runner, -# init SQL, or Compose PostgreSQL service from this checkout. - -# Dev: local PGlite data-layer work needs no PostgreSQL. Optional local queue service only: -docker compose up -d valkey -# Do not start Gateway/Web or root pnpm dev as a local PGlite route: the current unguarded dotenv -# loader can inherit a daemon PostgreSQL DSN. KBN-101-02 must make that state fail closed first. -``` - -## Conventions - -- ESM everywhere (`"type": "module"`, `.js` extensions in imports) -- NodeNext module resolution -- Explicit `@Inject()` decorators in NestJS (tsx/esbuild doesn't support emitDecoratorMetadata) -- DTOs in `*.dto.ts` files at module boundaries -- OTEL tracing imported before NestJS bootstrap (`import './tracing.js'`) -- All three gates must pass before push: typecheck, lint, format:check +Do not add project guidance here. Keep `AGENTS.md` authoritative so every agent runtime receives the same instructions.