From 7691fe14879edac18e92329326e87fbf552ab52d Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 24 Jul 2026 07:33:57 -0400 Subject: [PATCH] docs: add AGENTS.md + CLAUDE.md for agent behavioral protocol --- AGENTS.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..3c370056 --- /dev/null +++ b/AGENTS.md @@ -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 ` 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//` 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` 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 -- `. + +## 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 + +# Rust +cargo fmt -- + +# Markdown, YAML, CSS, etc. +pnpm --filter drop exec prettier --write +``` + +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 /` +- Scripts: `cat /package.json | jq .scripts` +- CI behavior: `cat .github/workflows/.yml` +- pnpm config: `cat pnpm-workspace.yaml` +- Tsconfig strict mode: `cat server/tsconfig.json | grep strict` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..c161378d --- /dev/null +++ b/CLAUDE.md @@ -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 + +# Rust (.rs files in cli/, desktop/src-tauri/, libraries/*) +cargo fmt -- + +# Markdown, YAML, JSON, CSS, SCSS +pnpm --filter drop exec prettier --write +``` + +## 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