# dfp-bot — agents.md

Project constitution. Inherits from `/srv/CLAUDE.md` (server scope) and
`/srv/apps/CLAUDE.md` (tenant scope). Only rules meeting the admission rubric
(failure-backed, tool-enforceable, decision-encoding, or triggerable) belong
here — no generic advice a model already applies. Budget: ~200 lines.

Model-independence: this file is the source of truth. `CLAUDE.md` is a symlink
to it so Claude Code loads the same content.

## Read first (in order)
1. **`brief.md`** — what this project is, and the stack decision.
2. **`.logs/planning/`** — the build plan: locked decisions, milestones, gates.
3. **`/srv/projects/standards/README.md`** — server-wide coding standards
   (dispatches by stack: `coding.md` → your stack doc → `frontend.md`).
4. **`.logs/handoff.md`** — newest-first; where the last session left off.

## Project-specific rules
- **Every sentence on the page must be true of the reader as built.** The reader lives in the
  Duty Free Professor app (`app/services/collectors/fetch.py`, `robots.py`, `main/browser/`); when
  its identity string, pacing, robots handling or browser behaviour changes, this page changes in
  the same day, and the footer's version and date move. A retailer reads this page as a promise.
- **Public, always.** The site is marked public in id-auth by decision; a gate here would hide the
  identity page from exactly the people it exists for. If `import id-auth` ever reappears in its
  Caddy conf, fix it with `srv-gw id-gate --site bot.dutyfreeprofessor.com --mode public`.
- **No scripts, no third-party assets, no forms.** The CSP in `nginx.conf` enforces it; keep it.

## Operational
- **Manage:** `srv-gw {deploy,restart,logs,status} --project dfp-bot`.
- **Deploy confirmation:** the page footer carries the reader version and the last-updated date;
  a content change moves the date. Static files are served live from `public/`, so a deploy is
  only needed when `nginx.conf` or the compose file changes.
- **Write access:** `dfp-bot-dev` Unix group (setgid + default ACL). New files need
  `chmod 664` / dirs `775`, or `srv-gw fix-permissions --project dfp-bot`,
  so the service user can read them.
- **Create new subdirectories under `sg dfp-bot-dev`.** If the session's groups
  don't include `dfp-bot-dev`, the kernel silently strips setgid on `chmod 2775`
  and files underneath get the wrong group.

## Layout
```
/srv/apps/dfp-bot/          # workspace — docs and runtime state
├── brief.md  agents.md  CLAUDE.md -> agents.md
├── .logs/{planning/, handoff.md, diary.md}
├── .memory/  .archive/  notes/
└── public/                  # the instance — code only
```
Runtime state (uploads, dumps) belongs at the workspace root, not in
`public/`. The compose file and `.env` sit at the workspace root because
`srv-gw deploy` requires them there — a documented deviation until T3.1.
