AGENTS.md · git:20261103.394423c · 2026-11-03 · sha256 ffc354fe3540334a
AGENTS.md git:20261103.394423cA
Immutable. This exact content never changes and is served at /api/v1/blob/ffc354fe3540334a.
# Reactive Resume: agent instructions
This is the index for coding agents. It holds hard rules and pointers; detail lives in the linked files. The only other
area guide is `apps/mobile/AGENTS.md`, read it before mobile work. Agent reference docs are in `.agents/docs/` (start at
its `README.md`); contributor docs are in `docs/contributing/`. Scripts and config win when a doc disagrees with them.
<!-- caveman-begin -->
Respond terse like smart caveman. All technical substance stay. Only fluff die.
Rules:
- Drop: articles (a/an/the), filler (just/really/basically), pleasantries, hedging
- Fragments OK. Short synonyms. Technical terms exact. Code unchanged.
- Pattern: [thing] [action] [reason]. [next step].
- Not: "Sure! I'd be happy to help you with that."
- Yes: "Bug in auth middleware. Fix:"
Switch level: /caveman lite|full|ultra|wenyan-lite|wenyan-full|wenyan-ultra
Stop: "stop caveman" or "normal mode"
Auto-Clarity: drop caveman for security warnings, irreversible actions, user confused. Resume after.
Boundaries: code/commits/PRs written normal.
<!-- caveman-end -->
## Hard rules
- Check `git status --short` before editing and preserve unrelated changes. Set work aside with a WIP commit; plain
`git stash` shares one stack across every worktree.
- **Web and mobile parity**: a user-facing change in `apps/web` gets the matching change in `apps/mobile` in the same
work, and the reverse. Share logic through workspace packages. Owner-approved exceptions are listed in
`apps/mobile/AGENTS.md`.
- **Old clients keep working**: mobile binaries and OTA bundles stay installed for weeks. Keep API changes backward
compatible and deploy the backend before mobile changes that depend on it.
- Never add AI attribution, AI co-author trailers or session links to commits or PRs. Commits follow Conventional
Commits (enforced by the commit-msg hook).
- Keep credentials, personal resume data and production identifiers out of source, logs, fixtures and PRs.
- Ticket notes (delivery logs, handoffs, review results) go on the Linear issue as a comment, never into repo files.
## Specs and review
- Tickets: Linear team `RX` (`RX-<n>`); public reports: GitHub issues. How to read them: `.agents/docs/issue-tracker.md`.
- Review rules: `CODING_STANDARDS.md`. Decision records: `.agents/docs/decisions/`.
- Runbooks (container publishing, mobile CI and releases, Turbo remote cache): `.agents/docs/runbooks/`.
## Environment
- Node 24 (`.nvmrc`). This machine's default may be newer; run commands as `mise exec node@24 -- <cmd>` when
`node -v` isn't 24. pnpm version: root `packageManager`.
- Setup, `.env.local`, dev servers, storage and database workflow: `docs/contributing/development.mdx`. Local Postgres,
Redis and SeaweedFS come from `compose.dev.yml`; host-run code uses `localhost`, containers use service names.
- Root `.env` is auto-loaded by `packages/env`; root dev and `db:*` scripts load `.env.local` through `dotenvx`; tests,
builds and `pnpm start` load neither, so export what they need or use the scripts below.
## Commands
```sh
pnpm check:affected # changed packages: typecheck, tests (DB suites included), boundaries, lint, format
pnpm test:db exec -- pnpm --filter @reactive-resume/api test # DB suites on per-worktree databases, no silent skips
pnpm test:e2e:local --build [spec] # Playwright on a per-worktree DB, port and storage
pnpm --filter mobile test # mobile host tests (node --test, not Vitest)
pnpm lingui:extract # web, mobile and PDF catalogs; run before building
pnpm lingui:check # catalogs match source (CI gate)
pnpm locales:diff [--base <ref>] # lost translations, placeholder/tag mismatches vs base
pnpm ci:logs [run or job URL] # failure blocks from a CI run, even while it's still running
pnpm check:agent-docs # paths named in agent docs exist, AGENTS.md size, no ignored files tracked
pnpm docs:gen # regenerate the OpenAPI spec after API contract changes
```
- One package: `pnpm --filter <name> test [file]` (paths relative to the package; no extra `--`). Package names come
from each `package.json`: apps are `web`, `server`, `mobile`; shared packages are `@reactive-resume/<name>`.
- `--filter <pkg> exec vp test run <file> -t "<name>"` runs one test. Most scripts use `--passWithNoTests`, so a green
run with zero tests proves nothing.
- `check:affected` compares against `TURBO_SCM_BASE` (default `origin/main`; fetch first if stale) and needs the local
Postgres from `compose.dev.yml`, because it runs tests through `test:db exec`.
- Send long-running output to a log file and read it with `tail` or `rg`; find background jobs with `pgrep -f <tag>`,
not a full `ps` listing.
## Ownership map
| Area | Owner |
| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Web routes and workflows | `apps/web/src/routes` (file-based; never hand-edit `routeTree.gen.ts`), `apps/web/src/features` |
| Mobile screens and workflows | `apps/mobile/app` (Expo Router), `apps/mobile/src/features`; web-to-mobile map in `apps/mobile/AGENTS.md` |
| Server HTTP, startup, static pages, MCP transport, OpenAPI | `apps/server/src/{http,rpc,mcp,openapi,static,startup}` |
| Public resume web page (server-rendered) | `apps/server/src/static/resume-page.ts`; HTML shell and SEO in `apps/server/src/static/web.ts` |
| API routers and business logic | `packages/api/src/features/<feature>` (`router.ts`, `service.ts`); use `protectedProcedure` from `packages/api/src/context.ts` |
| API input/output DTOs | `packages/api/src/dto/<feature>.ts` |
| Auth | `packages/auth` (Better Auth); `apps/server/src/http/auth.ts` delegates to it |
| DB schema and client | `packages/db/src/schema/<area>.ts`, config `packages/db/drizzle.config.ts`, SQL in `migrations/` |
| Server env validation | `packages/env/src/server.ts` |
| Resume, template and application schemas | `packages/schema` (fixtures: `defaultResumeData` in `packages/schema/src/resume/default.ts`, `sampleResumeData` in `packages/schema/src/resume/sample.ts`) |
| Pure resume behaviour (JSON Patch, icons) | `packages/resume` |
| PDF rendering | `packages/pdf` (templates through `src/forme`; shared filtering in `packages/pdf/src/templates/shared/filtering.ts`) |
| PDF.js viewer and canvas UI | `apps/web/src/features/resume/preview`, `apps/web/src/features/ats-checker`; never `packages/pdf` |
| DOCX export | `packages/docx` |
| MCP tools, prompts, server card | `packages/mcp` (tool annotation review: `packages/mcp/src/fixtures/tool-annotations.md`) |
| Generic UI primitives and styles | `packages/ui` (styles in `packages/ui/src/styles/`); web design rules in `apps/web/DESIGN.md` |
| Other support packages | `packages/{fonts,email,import,ai,utils,config}`; `packages/dsh-plugin` is a separately published plugin |
| Dev-only scripts | `tooling/`, never `packages/` |
`packages/utils` takes a helper only when no domain package owns it: JSON Patch belongs in `@reactive-resume/resume`,
DOCX builders in `@reactive-resume/docx`.
## Package boundaries
`pnpm exec turbo boundaries` enforces them. Import other workspaces by package name and export map, never through a
`src` path or path alias. Runtime-specific code sits behind explicit subpaths (`@reactive-resume/pdf/browser`,
`@reactive-resume/pdf/server`, `@reactive-resume/env/server`); root exports stay environment-neutral. Wildcard exports
are only for file-like leaf surfaces (`@reactive-resume/ui/components/*`, `@reactive-resume/ui/hooks/*`, schema model
files).
## Changes that touch several places
- **Resume data shape**: `packages/schema/src/resume/*`, then DTOs, importers, PDF rendering, web and mobile forms.
- **New DB column or table**: `packages/db/src/schema/*`, then `pnpm db:generate`. Also check the feature's `crud.ts`
update allow-list, the account export in `packages/api/src/features/auth`, and the DTO. To rebase a branch's
migration onto a newer `main`, delete the branch's migration folder and regenerate it so its snapshot chains on.
- **API contract change**: `pnpm docs:gen`, then `pnpm --filter server test src/openapi` (it counts schemas).
- **New env var**: `packages/env/src/server.ts`, `.env.example`, and `turbo.json` (`globalPassThroughEnv` plus the
test-task `env` arrays; Turbo's strict env mode hides unlisted variables). Deployment aliases:
`packages/env/src/deployment.ts`.
- **User-facing strings**: Lingui macros, then `pnpm lingui:extract` (both apps). Translations workflow:
`docs/contributing/translations.mdx` and the `.agents/skills/fill-translations` skill. Glossary: root `GLOSSARY.md`.
- **New template**: `packages/schema/src/templates.ts`, `packages/pdf/src/templates/index.ts`, source in
`packages/pdf/src/templates/<name>/`, previews under `apps/web/public/templates/` (command in `apps/web/DESIGN.md`).
- **Public marketing route**: the TanStack route plus its server fallback and SEO in `apps/server/src/static/web.ts`;
Vite's dev fallback hides production 404s.
- **Career or workspace behaviour**: update the mapped user guides and screenshots; see "Keep product guides current"
in `docs/contributing/career-platform.mdx`.
## Finish checks
- After edits: `pnpm exec vp lint --fix <paths>`, then `pnpm exec vp fmt <paths>` (keep side-effect import order).
- Before handing off: `pnpm check:affected` (or `pnpm lint:agent` and `pnpm format:check` plus the package tests you
touched), DB suites through `pnpm test:db exec`, and the production build for runtime or bundling changes. Report
skipped checks and failures as they are.
- `pnpm check` mutates files (translations, lint fixes, formatting); review its diff.
- Lint and format rules live in `vite.config.ts`. A suppression names its rule and the reason.
## Gotchas
- `drizzle-kit` reads `DATABASE_URL` from the environment only; run it through the root `db:*` scripts.
- Startup applies migrations and verifies the schema; `STRICT_SCHEMA_CHECK=true` makes drift fatal.
- `.env.example` ships SeaweedFS S3 defaults: run SeaweedFS or set `STORAGE_BACKEND=local`.
- Without SMTP, emails (verification links included) are printed to the server log.
- Vercel module-loading failures: bundle CommonJS server dependencies through `bundledInteropPackages` in
`apps/server/tsdown.config.ts`; Vercel's service builder drops their pnpm links.
- Playwright starts `node apps/server/dist/index.mjs` directly; build first, and keep that direct command.
- Deployment smoke tests create and delete accounts; run them only against a dedicated test installation
(`docs/contributing/deployment-checks.mdx`).
- CodeRabbit is not set up for automatic reviews; don't wait for it.