voting-app/AGENTS.md
2026-05-15 15:16:18 -05:00

97 lines
3.8 KiB
Markdown

# Voting App - Agent Instructions
See `~/.config/opencode/AGENTS.md` for global development principles (container-first, package managers, Dockerfile standards).
## Repo Overview
Flask backend + React TypeScript frontend. Data flow: `User → React Frontend → Flask Backend → Congress.gov v3 API`, with SQLite caching and local GPT-OSS for bill summaries. Backend source is flat under `src/` (no submodules). Vote data: House votes from Clerk XML (fast), Senate votes from senate.gov XML (slow, sequential scan).
## Lockfiles Are Gitignored — Regenerate Before Building
Both `uv.lock` and `frontend/pnpm-lock.yaml` are in `.gitignore`. Dockerfiles copy them during build, so they must exist locally first:
```bash
uv sync # generates uv.lock
cd frontend && pnpm install # generates pnpm-lock.yaml
```
Skip regeneration only if you haven't changed dependencies.
## Port Mapping
Host ports differ from container ports:
| Service | Host Port | Container Port |
|----------|-----------|----------------|
| Backend | 8001 | 8000 |
| Frontend | 5174 | 5173 |
## VITE_API_URL Is Build-Time Only
`VITE_API_URL` is passed as a Docker build arg (`http://backend:8000`) and baked into the frontend bundle at build time. It is NOT a runtime environment variable — changing `.env` after building has no effect. Rebuild the frontend container to pick up URL changes.
## Frontend: Preview Mode, No HMR
`docker-compose.yml` runs `npx vite preview`, serving the production build from `dist/`. There is no hot module reload. For active frontend development, rebuild after every change:
```bash
docker compose down frontend && docker compose up -d frontend --build
```
The `../frontend:/app/frontend` volume mount in docker-compose has no effect in preview mode (serves from baked-in `dist/`).
## Backend Entry Point
Runs as `python -m src.main --port 8000` inside the container. The `--port 8000` flag is hardcoded in docker-compose (mapped to 8001 on host).
## SQLite Cache
Backend caches Congress.gov API responses and GPT-OSS summaries in SQLite at `data/voting_app.db`. The `data/` directory is mounted as a Docker volume to `/app/data`. Not committed to git. Delete stale DB after schema changes (e.g. adding `start_date` column).
## Required External Services
- **Congress.gov API key**: Set `CONGRESS_API_KEY` in `.env`
- **Local GPT-OSS server**: Set `GPT_OSS_BASE_URL` in `.env` (e.g., LM Studio, Ollama, vLLM)
## Quality Gate Commands
Run before building any container:
```bash
# Backend
ruff format .
ruff check --fix .
# Frontend
cd frontend && pnpm lint --fix
cd frontend && tsc
```
Ruff: line-length 120, rules `E W F I N UP B SIM`.
Frontend ESLint: `@typescript-eslint/no-unused-vars` and `no-explicit-any` are `warn`.
Frontend `pnpm build` runs `tsc && vite build` — TypeScript check gates the build.
## Testing
106 tests total: 103 unit/E2E tests (mocked services) + 3 integration tests (real API). All pass.
```bash
# Unit + E2E tests (fast, mocked)
uv run pytest tests/unit/ tests/e2e/
# Integration tests (slow, real API — requires CONGRESS_API_KEY)
uv run pytest tests/integration/
# In container
docker compose exec backend python -m pytest tests/unit/ tests/e2e/
```
The `integration` pytest mark is registered in `pyproject.toml`. Integration tests require a valid `CONGRESS_API_KEY` in `.env` and skip if unset. Senate vote fetching uses XML scanning from senate.gov and can take 2-4 minutes per legislator.
## Backend Dockerfile Note
The backend Dockerfile installs `uv` via `pip` (the `python:3.12-slim` image doesn't include it). Build arg `VITE_API_URL` is set via docker-compose, not `.env`.
## Build Context
`.dockerignore` excludes `tests`, `tools`, `additionaldocs`, `data`, and `.env` from Docker build context. A `.dockerignore.backend` file exists in `docker/` but is not used by Docker (context is project root).