# AGENTS.md — Ooru

Vendor-neutral agent guide for this repository. Mirrors `docs/CLAUDE.md`.
The durable reference (audit + competitor analysis) is `docs/NOTES.md`.

---

## Project

Ooru: a Bangalore house-hunting assistant. Landmark in → geocode → nearby metro +
ICSE schools → rank alternative localities by air quality (AQI) → (intended) rental
listings → LLM advisory report (Moonshot Kimi K2.6). Surfaces: CLI (`chatbot.py`) and
FastAPI API (`backend/app.py`).

## Current direction — v2 (read first)

The architecture verdict (docs/architecture.html §04, docs/MIGRATION.md) replaces the
v1 stack below with the og-coach PocketBase pattern: one `pocketbase` binary + one
`pb_hooks/main.pb.js` hook (sequential calls, server-only LLM key) + `pb_migrations/` +
a vanilla `pb_public/` PWA + `tools/deploy.sh`. This eliminates v1's two bugs by
construction — fabrication (one linear hook passes only verified fields; no `return {}`
to drop data) and the hardcoded JWT secret (PocketBase auth is built-in). Target flow:
geocode → schools → metro → AQI → rank → LLM. v2 is NOT built yet; v1 still runs. Build
per MIGRATION.md; the v1 detail below is the audit being migrated away from. Data
sources/endpoints: docs/DATA_SOURCES.md §8 (OSM Overpass, Nominatim/Ola, Open-Meteo +
CPCB, Apify; NO Google scraping).

## Stack

FastAPI · SQLAlchemy (not Prisma) · LangGraph · OpenAI SDK → Kimi K2.6 · Mapbox ·
Foursquare · Open-Meteo · Apify · JWT + bcrypt. Python 3.11 via uv.

## Data model (backend/database.py)

- `User` (id, username, email, password_hash) 1──N `HouseRental`
- `HouseRental` (id, user_id FK nullable, user_location, top_matches JSON,
  top_matches_coordinates JSON)
- `APICache` (id, api_name, cache_key unique, response_data JSON, created_at)

## File map

| Path | Role |
|---|---|
| `main.py` | external API integrations + (print-heavy) logic |
| `workflow.py` | LangGraph nodes/edges |
| `chatbot.py` | CLI loop, Kimi streaming, simulation fallback |
| `backend/app.py` | FastAPI routes |
| `backend/services.py` | auth, JWT, workflow execution, persistence |
| `backend/database.py` | engine + models + cache helpers |
| `backend/models.py` | Pydantic schemas (misnamed) |
| `backend/schemas.py` | DEAD duplicate — delete |
| `test_api.py`, `test_chatbot.py` | non-hermetic tests (hit live APIs/DB) |
| `docs/` | guides + NOTES.md + strategy HTML |

## Hard rule: data honesty

The advisory may only assert what the pipeline computed. Known bug: school/metro nodes
`return {}` (workflow.py:33-52); their data never reaches the LLM prompt
(services.py:139-146); the report's school/metro claims are hardcoded
(chatbot.py:31-39) and therefore fabricated. Fix path = roadmap item 0.1. Never add
report copy that isn't backed by real state; when data is missing, state that plainly.

## Conventions

- uv + Python 3.11. `uv venv --python 3.11 .venv`.
- All `requests.get()` need `timeout=` (currently missing — known gap).
- Route new external calls through `APICache`.
- LangGraph nodes RETURN dict state updates; a working node that returns `{}` is a bug.
- Secrets from env only; no hardcoded defaults (services.py:22 currently violates).
- No Alembic — prefer extending `top_matches` JSON over new columns.

## Commands

    uv venv --python 3.11 .venv && source .venv/bin/activate && uv pip install -r requirements.txt
    python chatbot.py
    python workflow.py <landmark>
    uvicorn backend.app:app --reload
    python test_api.py            # needs DATABASE_URL + live keys

## Working agreement

- State exact files before multi-file edits.
- No code changes until the user approves a specific roadmap item.
- Report blockers honestly; never fabricate tool output or results.
- Terse status; full technical detail and exact numbers preserved.

## Roadmap (Horizon 0, do first)

0.1 wire schools+metro into state + prompt (honesty fix) · 0.2 JWT secret from env ·
0.3 .gitignore + untrack .env/__pycache__ + rotate keys · 0.4 delete dead code ·
0.5 request timeouts · 0.6 pin deps · 0.7 non-blocking /chat.
Highest leverage: 0.1. Detail in `docs/NOTES.md`.

## .gitignore

Installed skill dirs `.agents/ .claude/ .cursor/ .gemini/ .opencode/` plus `.env`,
`__pycache__/`, `.venv/` belong in `.gitignore` (Horizon-0 item 0.3).
