# AGENTS.md `docs/REQUIREMENTS.md` is the only normative text. All other docs cite IDs; none define requirements. ## Structure contract (read before creating or moving any doc) - Requirements live only in `docs/REQUIREMENTS.md`; milestone scope in `docs/MILESTONES.md`. - Before creating or moving any doc under `docs/`, look up its home in `docs/STRUCTURE.md`. - If no home exists, stop — do not create a new artifact. - To change a requirement: edit the single row in `REQUIREMENTS.md`; update `Test`; if scope changed, update `MILESTONES.md`. Do not create a doc. - Run `python tools/check_requirements.py` after any docs change; it must pass. ## Agent runtime rules - Subagents run on one local GPU and cannot handle concurrency. Invoke one at a time; never in parallel. ## Build & test (verified commands) Frontend (`frontend/`, Svelte 4 + Vite + TS, no router): ``` cd frontend && npm install npm run test # node --import tsx --test src/**/*.test.ts (unit) npm run build # tsc --noEmit && vite build (type-check + build) npm run test:e2e # playwright test (see Pitfalls: mocks the API) ``` Backend (`backend/`, FastAPI + stdlib sqlite, no ORM, deps pinned in `backend/requirements.txt`): ``` cd backend && python -m pytest tests/ -q uvicorn backend.app:app --host 127.0.0.1 --port 18081 ``` No Makefile, no CI workflows, no Gitea CI — nothing runs in a pipeline; the only automation is the local commands above plus the human UAT walk (`deploy/uat_walk.sh`). ## Conventions - The LIVE FastAPI routes in `backend/*.py` are the API source of truth; `docs/contracts/API.md` is aspirational and can drift (it describes a polling model the backend never shipped). Read the router, not the doc, before wiring a client. - Frontend is one Svelte app, no router: `App.svelte` switches on a `writable` flow store. Screens live under `frontend/src//`. - Commit subjects: `feat(scope): …` / `fix(scope): …` / `test(scope): …` / `chore(scope): …`, often citing a requirement ID or Gitea number. ## Gates (must pass before claiming work complete) Run from repo root: ``` python tools/check_requirements.py python tools/check_coverage.py ``` Exit 0 on both = pass. ## Pitfalls - E2E mocks the API: `tests/e2e/*.spec.ts` use Playwright `page.route('**/api/v1/**')` with fixture ids — there is **no live backend** under e2e. A green `test:e2e` is not proof the real backend works; that's the human `deploy/uat_walk.sh` (real Woo, never a mock — QUALITY-105). - Ports on the 5060 UAT host (192.168.1.202): FastAPI `18083`, FE `18082`/`10881` are typically already up (compose on `deploy/docker-compose.yml`). Check before binding; don't assume `18081` is free. - `SLAB_UAT_UNMASK_SECRETS=1` makes `GET /settings` return decrypted Woo/inference secrets — dev-test only, never set in prod (SETTINGS-75 masking is the default). - Never hardcode live Woo category/term ids into app code (QUALITY-105 / METADATA-5); resolve groupers by slug (`species`, `wcat`) at runtime. - `tsc` won't catch Svelte template errors; `npm run build` (which runs `tsc --noEmit`) is the real type gate for the frontend. ## Pointers (read these for everything else) - Docs map and shipped status: `docs/README.md` - Scope and ID subsets: `docs/MILESTONES.md` - M3 behavior: `docs/capabilities/CREATE.md` - Hosts, ports, UAT environment: `docs/DEPLOYMENT.md` and `deploy/INVENTORY.md` - Task ordering for M3: `.planning/milestones/v0.5/M3/task_breakdown.md` - Product invariants and acceptance criteria: the requirement rows in `docs/REQUIREMENTS.md` (cite by ID)