docs: add AGENTS.md + CLAUDE.md for agent behavioral protocol

This commit is contained in:
John Smith 2026-07-24 07:33:57 -04:00
parent fb810ff7f9
commit 7691fe1487
2 changed files with 218 additions and 0 deletions

137
AGENTS.md Normal file
View file

@ -0,0 +1,137 @@
# Drop Monorepo — Agent Instructions
Dense technical reference for AI coding agents. Keep under 150 lines. If a fact here is wrong, run `ls <path>` to verify before trusting.
## Workspace Map
| workspace | language | framework | entry point |
|---|---|---|---|
| server/ | TS | Nuxt 3 + Nitro | nuxt.config.ts |
| desktop/main/ | TS | Nuxt 4 | nuxt.config.ts |
| desktop/src-tauri/ | Rust | Tauri v2 (workspace, 7 crates) | client/, database/, games/, … |
| cli/ | Rust | clap (downpour) | src/main.rs |
| sites/promo | TS | Next.js 15 | next.config |
| sites/docs | TS | Astro 6 + Starlight | astro.config |
| libraries/base | TS | Nuxt layer | nuxt.config.ts |
| libraries/droplet, droplet_types, libarchive, native_model | Rust | — | Cargo.toml |
| torrential/ | Rust | (experimental) | skip |
## Package Manager: ALWAYS pnpm, NEVER yarn or npm
- Root has `"packageManager": "pnpm@11.17.0"`. yarn 1.x refuses to run.
- `pnpm-workspace.yaml` declare:
- `allowBuilds`: packages that may run install scripts (build-from-source fallbacks)
- `onlyBuiltDependencies`: the **security-allowlisted** subset. Adding to this is a security decision.
- `shamefullyHoist: true` (some plugins need it)
- `pnpm install` in CI requires system `libpng-dev` (apt) for pngquant-bin to compile.
- Root `package.json` has ONLY `"prepare": "husky"`. All scripts live in workspace package.jsons.
## Nuxt Server Double-Nesting (CRITICAL CONFUSION POINT)
`server/server/` is the Nitro server code, not the Nuxt app:
- `server/api/v1/*.ts` — API route handlers (file-based)
- `server/routes/auth/*.ts` — non-API routes (signin, signout, OIDC callback)
- `server/server/api/...` — actually? NO. The structure is: `server/` IS the Nuxt app root. Nitro code lives in `server/server/`. The dot is real. The double-nest is intentional, not a bug.
`server/components/`, `server/composables/`, `server/pages/`, `server/assets/` — Nuxt app frontend code.
`server/server/` — Nitro backend code. `server/server/internal/<domain>/` is the business logic layer.
## Custom ESLint Rules
- `drop/no-prisma-delete` — forbids `prisma.delete()`. Soft-delete is enforced. Use `update` with `deletedAt: new Date()` instead.
- `@intlify/vue-i18n/no-dynamic-keys` and `no-missing-keys` — error level. Hard-coded i18n strings in templates fail lint.
## Metadata Provider Pattern (server/server/internal/metadata/)
- `MetadataProvider` abstract class. Implementations: IGDB, Steam, GiantBomb, PCGamingWiki, Manual.
- `PriorityListIndexed<MetadataProvider>` ordered by `source`. Provider chain fallthrough: if IGDB returns nothing, Steam tries next.
- All external HTTP is mocked via MSW in tests (`server/test/mocks/metadata.ts`).
- Adding a new provider means: (1) implementing the class, (2) adding it to the chain, (3) adding its image CDN to CSP whitelist in `server/nuxt.config.ts`.
## Nitro Plugin Ordering
`server/server/plugins/` files are prefixed `01-` through `09-` for explicit init order. Adding a plugin means inserting at the right numeric prefix. Don't rename existing prefixes.
## Prisma Workflow
- Schema: `server/prisma/schema.prisma`. Migrations: `server/prisma/migrations/`.
- Generated client: `server/prisma/client/`. NEVER edit generated files.
- `server/postinstall`: runs `nuxt prepare && prisma generate && buf generate` — required after schema or `.proto` changes.
- `.env` sets `DATABASE_URL`. Tests need a test DB or transaction-per-test helper (see `server/test/utils/db.ts`).
## Build & Test Commands (per workspace)
```
# server/
pnpm --filter drop dev # nuxt dev
pnpm --filter drop typecheck # nuxt typecheck
pnpm --filter drop test # vitest run
pnpm --filter drop test:e2e # playwright
pnpm --filter drop format:check # prettier --check .
pnpm --filter drop lint # prettier + eslint
pnpm --filter drop lint:fix # eslint --fix + prettier --write
# cli/ (Rust)
cargo test --all-features
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
# desktop/src-tauri/ (Rust)
cargo check --all-features --all
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
```
## CI Workflow Map (`.github/workflows/`)
- `ci.yml` — main CI: typecheck, lint, test, format check (push to main/develop, all paths)
- `server-ci.yml` — server-only: typecheck, lint (push to develop on `server/**` + libs)
- `droplet-ci.yml` — Rust for `libraries/droplet/`, `droplet_types/`, `libarchive/`
- `libraries/native_model/.github/workflows/` — native_model Rust CI (independent)
- `cli-ci.yml` — Rust for `cli/` (added)
- `desktop-ci.yml` — Rust `cargo check` for `desktop/src-tauri/` (added)
- `pages.yml` — promo + docs site builds (push to develop)
- `client-release.yml` / `server-release.yml` — release workflows
- `codeql.yml`, `osv-scanner.yml` — security scanning
- `editorconfig-ci.yml` — setup-sherif .editorconfig enforcement (added)
## Pre-commit Hooks (ACTUAL BEHAVIOR)
- `.husky/pre-commit` (root, ACTIVE): runs `pnpm --filter drop lint-staged && pnpm --filter drop test`
- `server/.husky/pre-commit` (DEAD CODE, will be deleted): Git only honors one hooks directory. This file never fires.
- lint-staged patterns: `*.{ts,vue,json,css,scss,yaml,yml,md,mjs,cjs}` → eslint --fix + prettier --write. `*.rs``cargo fmt -- <file>`.
## Common Gotchas
- **libpng-dev required in CI** (apt) for pngquant-bin native compile. Missing → ELIFECYCLE.
- **tailwindcss vite plugin causes infinite recursion in vitest** under `environment: "nuxt"`. Already fixed: `nuxt.config.ts` conditionally excludes the plugin when `process.env.VITEST === "true"`.
- **TypeScript `noUncheckedIndexedAccess`**: DEFERRED. Enabling this strict flag surfaces 30+ latent TS errors in `server/api/v1/{admin/import/massversion, auth/mfa/webauthn, auth/passkey}/`, `server/internal/{auth/totp, clients/event-handler, metadata/pcgamingwiki, system-data/index, utils/prioritylist}.ts`. Fix each site (`if (!arr[i]) return` or `const item = arr[i]; if (!item) return`). Tracked for follow-up; do not enable the flag until these are fixed.
- **Submodules**: none currently (no `.gitmodules`).
- **`.omo/`** directory: OpenCode run continuation state. Do not commit.
- **Nuxt 4 desktop** uses Nuxt 4 (not 3). Newer patterns may differ from server/.
## Agent Edit Protocol (matches CLAUDE.md)
After editing ANY file, run the appropriate formatter immediately. CI rejects unformatted code:
```
# server/.ts or .vue
pnpm --filter drop exec prettier --write <file>
# Rust
cargo fmt -- <file>
# Markdown, YAML, CSS, etc.
pnpm --filter drop exec prettier --write <file>
```
Before batch commits: `pnpm --filter drop lint:fix` from repo root.
## Verifying Facts in This File
This file is a cache. Before trusting any fact, verify with a direct command:
- Workspace structure: `ls -la <workspace>/`
- Scripts: `cat <workspace>/package.json | jq .scripts`
- CI behavior: `cat .github/workflows/<file>.yml`
- pnpm config: `cat pnpm-workspace.yaml`
- Tsconfig strict mode: `cat server/tsconfig.json | grep strict`

81
CLAUDE.md Normal file
View file

@ -0,0 +1,81 @@
# Drop — Agent Behavioral Rules
Cross-tool behavioral rules. Read by Claude Code, Cursor, Codex, OpenCode, and other AI coding agents. This file governs *behavior*; the dense technical reference is in `AGENTS.md`.
## After editing any file, format it immediately
Do not move on until formatting is applied. CI rejects unformatted code.
```bash
# TypeScript / Vue / Astro (server, sites, desktop/main, libraries/base)
pnpm --filter drop exec prettier --write <file>
# Rust (.rs files in cli/, desktop/src-tauri/, libraries/*)
cargo fmt -- <file>
# Markdown, YAML, JSON, CSS, SCSS
pnpm --filter drop exec prettier --write <file>
```
## Before batch commits
Run the full lint-fix and test suite:
```bash
# Format fix everything
pnpm --filter drop lint:fix
# Run tests (server workspace)
pnpm --filter drop test
# Verify nothing is unformatted
pnpm --filter drop format:check
```
The pre-commit hook runs lint-staged + `pnpm test` automatically. If pre-commit fails, fix the issue, then `git commit --amend --no-edit` (if no new files) or re-stage and commit.
## Do not commit
- `.env` files (use `.env.example` as template)
- `.nuxt/`, `.output/`, `dist/`, `coverage/` (build artifacts)
- `server/prisma/client/` (generated — regenerate with `pnpm --filter drop prisma generate`)
- `server/.nuxt/`, `server/.output/` (Nuxt build artifacts)
- `.omo/` (OpenCode internal state)
- Secrets, tokens, API keys — ever
## Package manager
ALWAYS pnpm. NEVER yarn or npm. The project has `packageManager: pnpm@11.17.0` enforced. yarn 1.x will refuse to run.
## Run commands from workspace directory
For `cd server && pnpm test`-style commands, either:
- `pnpm --filter drop <script>` from root
- `cd server && pnpm <script>` from inside the workspace
Do NOT run `pnpm test` from root (root has no `test` script).
## Verify before claiming completion
Do not say "done" or "fixed" without tool evidence from this session:
- Tests: `pnpm --filter drop test` output showing pass
- Lint: `pnpm --filter drop lint` output showing pass
- Typecheck: `pnpm --filter drop typecheck` output showing pass
- CI: `gh run view <run-id> --json conclusion` returning `success`
## When uncertain
1. Read `AGENTS.md` (technical reference)
2. `ls <path>` to verify directory structure
3. `cat <file>` to verify config
4. If still unclear, ask the user before proceeding
## Edit loops
If a file is repeatedly auto-formatted by linters, the file has a deeper issue. Stop and investigate — do not loop.
## Do not touch
- `server/.husky/pre-commit` (dead code, will be deleted)
- Generated Prisma client (`server/prisma/client/`)
- Lockfiles (`pnpm-lock.yaml`, `Cargo.lock`) — only update via `pnpm install` / `cargo update`