# AGENTS.md: Streamlit app

## Commands
`uv run streamlit run app.py` · `uv run pytest -q` (with `streamlit.testing.v1.AppTest`) · `uv run ruff check .`

## Mental model
- The whole script reruns top to bottom on every interaction. Keep it fast: expensive work must be cached or isolated.

## Rules
- `@st.cache_data(ttl=...)` for data loading and transformations that return serializable data; `@st.cache_resource` for shared clients (DB connections, ML models). Don't cache functions with side effects.
- Persist UI state in `st.session_state` with explicit keys initialized at the top (`st.session_state.setdefault("page", 1)`). Give widgets stable `key=`s.
- Group inputs that should submit together in `st.form` so typing doesn't rerun the app on every keystroke.
- Use `@st.fragment` for parts of the page that update independently (e.g., a live chart).
- Multipage apps with `st.navigation`/`st.Page` (or the `pages/` folder, matching the project).
- Layout with `st.columns`, `st.tabs`, `st.sidebar`, `st.container`; show progress with `st.spinner`/`st.status`.
- Secrets in `.streamlit/secrets.toml` (gitignored) read via `st.secrets`; config in `.streamlit/config.toml`.
- Keep data logic in importable modules (`src/`), not inside the UI script, so it can be unit tested.
- Never display raw exceptions with secrets; use `st.error` with a friendly message and log details.

## Done
Lint and tests pass, and the app loads without warnings in the browser with typical inputs.
