# Agent Guidelines — Mosaic Stack

## Required Load Order

1. `~/.config/mosaic/SOUL.md`
2. `~/.config/mosaic/STANDARDS.md`
3. `~/.config/mosaic/AGENTS.md`
4. `~/.config/mosaic/guides/E2E-DELIVERY.md`
5. `AGENTS.md` (this file)
6. Runtime-specific guide: `~/.config/mosaic/runtime/<runtime>/RUNTIME.md`

## 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.

## Package Map

| 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/cli`     | Unified CLI + Pi TUI            | Ink, Pi SDK                      |
| `plugins/discord`  | Discord channel plugin          | discord.js                       |
| `plugins/telegram` | Telegram channel plugin         | Telegraf                         |

## Architecture Rules

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)

## Development Workflow

```bash
docker compose up -d          # Infrastructure
pnpm install                  # Dependencies
pnpm typecheck && pnpm lint && pnpm format:check  # Quality gates
```

## Repo-Specific Notes

- 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

## docs/TASKS.md — Schema (CANONICAL)

The `agent` column specifies the required model for each task. **This is set at task creation by the orchestrator and must not be changed by workers.**

| Value    | When to use                                                 | Budget                     |
| -------- | ----------------------------------------------------------- | -------------------------- |
| `codex`  | All coding tasks (default for implementation)               | OpenAI credits — preferred |
| `glm-5`  | Cost-sensitive coding where Codex is unavailable            | Z.ai credits               |
| `haiku`  | Review gates, verify tasks, status checks, docs-only        | Cheapest Claude tier       |
| `sonnet` | Complex planning, multi-file reasoning, architecture review | Claude quota               |
| `opus`   | Major cross-cutting architecture decisions ONLY             | Most expensive — minimize  |
| `—`      | No preference / auto-select cheapest capable                | Pipeline decides           |

Pipeline crons read this column and spawn accordingly. Workers never modify `docs/TASKS.md` — only the orchestrator writes it.

**Full schema:**

```
| id | status | description | issue | agent | repo | branch | depends_on | estimate | notes |
```

- `status`: `not-started` | `in-progress` | `done` | `failed` | `blocked` | `needs-qa`
- `agent`: model value from table above (set before spawning)
- `estimate`: token budget e.g. `8K`, `25K`
