# AGENTS.md — Working Guide for AI Coding Agents

> This file is read by every AI agent (Emergent E1, fork agents, testing agent) at session start.
> Keep it short, opinionated, and enforceable.

---

## 🟥 GOLDEN RULE — read this BEFORE every change

> **Fix root causes, not symptoms. Never apply temporary patches. Refactor and permanently resolve issues before adding related features.**

If a feature is requested on top of a broken module:
1. Diagnose and **permanently** fix the underlying bug first (no `if not None and ...` band-aids, no `try/except Exception: pass`, no commented-out tests).
2. Add a regression test under `/app/backend/tests/` that fails *before* the fix and passes *after*.
3. THEN add the new feature.

If you cannot finish step 1 in the same session, surface the blocker clearly via `ask_human` instead of moving on.

---

## Owner / Product

- **Owner**: RBS Regal Marketing — `regalmarketing2024@gmail.com`
- **Stack**: React 19 + FastAPI + MongoDB (Motor async driver)
- **Language**: Hinglish / Hindi-first user. Responses to the user must be in Hindi or Hinglish.
- **Production URL**: https://offline-billing-pro-2.emergent.host (read-only for agents)
- **Preview URL**: pulled from `frontend/.env::REACT_APP_BACKEND_URL` (the only authoritative source)
- **Branding rule**: ALL Emergent branding stripped. Do not re-add Emergent logos, scripts, or footer credits.

## Environment invariants (do NOT change)

- Backend runs on `0.0.0.0:8001` under supervisor. Hot reload enabled.
- Frontend runs on `:3000` under supervisor. Hot reload enabled.
- MongoDB URL: `os.environ['MONGO_URL']` (never hardcode). DB name: `os.environ['DB_NAME']`.
- All backend routes MUST be prefixed `/api/...` — the K8s ingress only forwards that prefix.
- Restart commands: `sudo supervisorctl restart backend|frontend` (only after `.env` edits or dependency installs — code edits are picked up via hot reload).

## Code conventions

- **Backend**:
  - PyObjectId pattern for all Mongo `_id` fields. Always convert to `str` before returning over HTTP.
  - `datetime.now(timezone.utc)` only. **Never** `datetime.utcnow()`.
  - Use the existing `auth.get_current_user` and `auth.require_admin` dependencies — do not duplicate.
  - Add new routers via `app.include_router(...)` in `server.py`.
  - Lint with ruff: `mcp_lint_python` must report 0 blocking before finishing.
  - Tests live under `/app/backend/tests/test_*.py` and use the `BASE_URL` env var.

- **Frontend**:
  - Path alias `@/` → `/app/frontend/src/`.
  - All UI primitives come from `/app/frontend/src/components/ui/` (shadcn). Do not introduce a second component library.
  - Toasts via `sonner`. Icons via `lucide-react` only — no emoji icons.
  - Every interactive element MUST have a unique `data-testid`.
  - API access via `api` from `@/lib/api` (axios instance with offline guard + 401 refresh). **Never** call `fetch()` directly.
  - State persistence: `localStorage` for user-pref-style state, `sessionStorage` for in-progress drafts.

## Testing protocol (Phase 1 — what we have today)

When you finish any change, you must run at least ONE of:

| Change scope | Required verification |
|---|---|
| Single backend bug fix | `curl` the affected route + response check |
| Single frontend bug fix | screenshot + check for console errors |
| New module / feature | `testing_agent_v3_fork` covering happy path + at least 1 edge case |
| Refactor of shared code (auth, api.js, server.py, ai_assistant.py) | `testing_agent_v3_fork` with explicit regression scenarios |

Test reports live at `/app/test_reports/iteration_{N}.json`.

## Known cross-cutting constraints

- **Offline-first**: every page must render without crashing if the network is down. Use the offline guard in `/app/frontend/src/lib/api.js`. Display "Offline Mode" badges (already wired).
- **Multi-language**: 13 languages live in `/app/frontend/src/lib/i18n.js`. Adding a new `t()` key requires adding all 13 translations OR providing an inline English fallback.
- **Multi-tenant**: every record stores `company_id`. New queries MUST filter by `company_id` to avoid cross-company data leaks.
- **Role-based access**: roles are `superadmin`, `admin`, `manager`, `staff`, `salesman`, `accountant`. Only `superadmin` can delete companies, prefixes, backups, or manage license.

## Forbidden patterns (these have bitten us before)

1. **Lazy dynamic imports of bundled-only deps** — `await import("qrcode")` will silently fail offline because the chunk can't be downloaded. Use static `import QRCode from "qrcode"` for anything needed offline.
2. **Hardcoded credentials in test files** — always read from `os.environ.get("TEST_ADMIN_PASSWORD")` and skip if missing.
3. **Multi-statement single-line Python** (`if x: y; z`) — breaks ruff E701/E702 and is hard to debug. Always expand to multi-line blocks.
4. **`is "string"` / `is 0` / `is True`** — `is` is identity, not equality. Only legal use is `is None` / `is not None`.
5. **Returning raw Mongo docs** with `ObjectId` `_id` — convert via `_safe()` helper or `str(doc["_id"])`.
6. **Silent exception swallowing** — `except Exception: pass` is forbidden. At minimum log to `print(..., file=sys.stderr)` or re-raise with context.
7. **Re-importing emergent libraries via pip** — use the established `emergentintegrations` package only.

## What you CANNOT do in this environment

- Detect USB / Bluetooth / LAN / Wi-Fi printers from the browser (requires native bridge — out of scope for the web app).
- Modify Emergent platform behaviour (deployment gates, rollback UI, environments). The platform already provides Rollback via the chat dock — do not implement a competing rollback.
- Run long-running tasks (> 2 min foreground). Use `&` for background bash and tail logs.
- Push to GitHub directly. Tell the user to use the "Save to GitHub" chat-input button.

## Files of reference

- **Architecture**: `/app/memory/PRD.md`, `/app/memory/CHANGELOG.md`
- **Test credentials**: `/app/memory/test_credentials.md` (must always be kept up-to-date when auth is touched)
- **Test reports**: `/app/test_reports/iteration_*.json`
- **Recent agent decisions**: tail of `PRD.md`
