# 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).