|
| 1 | +# .github/copilot-instructions.md |
| 2 | + |
| 3 | +> **Scope:** This file tailors GitHub Copilot (Chat/Code/Review) to this monorepo. It encodes *non-negotiable* conventions so Copilot generates code that builds, tests, and deploys with our Tilt/Helm setup. |
| 4 | +
|
| 5 | +--- |
| 6 | + |
| 7 | +## 1) Repository at a glance |
| 8 | + |
| 9 | +* **Monorepo:** Python services + Vue 3/TypeScript frontend |
| 10 | +* **Services:** `services/rag-backend`, `services/admin-backend`, `services/document-extractor`, `services/mcp-server`, `services/frontend` |
| 11 | +* **Libs:** Reusable APIs/logic in `libs/*-api` and `libs/*-lib` consumed by services |
| 12 | +* **Infra:** `infrastructure/rag` (Helm chart, K3d/Tilt config, Terraform). Local orchestration via **Tilt**; env loaded from `.env`. |
| 13 | +* **Vector DB & extras:** Qdrant, KeyDB/Redis, Langfuse (observability). LLM provider via OpenAI-compatible APIs (STACKIT/ollama). |
| 14 | + |
| 15 | +**Rule of thumb:** *Business logic lives in **libs**; services are thin assemblies (routing/DI/bootstrap only).* |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## 2) Languages & toolchain |
| 20 | + |
| 21 | +* **Python:** 3.13, **FastAPI**, **Pydantic v2**, **Poetry** |
| 22 | +* **Formatting/Linting:** `black` (line length **120**), `isort` (profile `black`), `flake8` (plugins configured in repo) |
| 23 | +* **Testing:** `pytest` (+ coverage), prefer `pytest-asyncio` for async |
| 24 | +* **Frontend:** Vue 3, TypeScript, Vite, Nx, Tailwind, Pinia, Vue I18n; tests via Vitest + Cypress; lint via ESLint |
| 25 | + |
| 26 | +--- |
| 27 | + |
| 28 | +## 3) Copilot behavior (important) |
| 29 | + |
| 30 | +* **Follow this file strictly.** Do not invent secrets/URLs/paths. Use placeholders/TODOs. |
| 31 | +* **Prefer libs over services:** New endpoints and business logic go to `libs/*-api` & `libs/*-lib`; services only import/wire. |
| 32 | +* **Always emit tests** with new Python code (1 happy + 1 edge case). |
| 33 | +* **Ask via comments if uncertain**: Add a short `# Assumptions:` block at top of the diff. |
| 34 | + |
| 35 | +--- |
| 36 | + |
| 37 | +## 4) Python conventions |
| 38 | + |
| 39 | +* **Typing:** Use modern typing (`list[str]`, `dict[str, Any]`), avoid `Any` unless necessary. Pydantic v2 validators (`field_validator`, `model_validator`). |
| 40 | +* **Imports:** **Absolute imports only** (no `from .x import y`). Group per isort. No wildcard imports. |
| 41 | +* **FastAPI:** |
| 42 | + |
| 43 | + * Endpoints are **thin**; DI via `Depends`/container; no business logic in routers. |
| 44 | + * Every route sets `response_model=...`; sanitize outputs. |
| 45 | + * Centralize exception mapping; do not leak stack traces in prod. |
| 46 | + * Prefer **async** endpoints for I/O-bound paths. |
| 47 | +* **HTTP client:** Use `httpx.AsyncClient` with timeouts/retries. **Never** use `requests` in async code. |
| 48 | +* **Config:** Use environment variables via `pydantic-settings` (document required vars; load `.env` in dev tooling only). Do **not** hardcode secrets. |
| 49 | +* **Logging:** Use `logging` (or `structlog` if present). Produce structured, contextual logs (`event`, `service`, `request_id`). Do not log PII. |
| 50 | +* **Repositories/Adapters:** Implement external I/O (DBs, HTTP, object storage) behind repository interfaces. Services call repositories; routers call services. |
| 51 | +* **File layout for new code:** |
| 52 | + |
| 53 | + * `libs/<package>/src/<package>/...` → APIs, services, repositories, schemas, utils |
| 54 | + * `libs/<package>/tests/` → tests for the above |
| 55 | + * `services/<service>/` → service bootstrap, DI container, runtime config |
| 56 | + |
| 57 | +**Flake8 style (align with repo):** max line length **120**; `max-complexity: 8`; `annotations-complexity: 3`; `ignore: E203, W503, E704`; **double quotes** for code & docstrings; docstrings **NumPy style**; absolute imports only. |
| 58 | + |
| 59 | +--- |
| 60 | + |
| 61 | +## 5) Testing |
| 62 | + |
| 63 | +* **pytest** with fixtures/mocks (`unittest.mock`, `pytest-mock`). |
| 64 | +* Keep unit tests fast and isolated; integration tests go through defined interfaces. |
| 65 | +* No real network in unit tests; for `httpx` use `respx` (or equivalent) to mock. |
| 66 | +* Target **high coverage on core libs**; measure with coverage in CI. |
| 67 | + |
| 68 | +**pytest.ini (suggested):** |
| 69 | + |
| 70 | +```ini |
| 71 | +[pytest] |
| 72 | +addopts = -q --strict-markers --strict-config --maxfail=1 --cov=libs --cov-report=term-missing |
| 73 | +markers = |
| 74 | + slow: marks tests as slow (deselect with '-m "not slow"') |
| 75 | +asyncio_mode = strict |
| 76 | +``` |
| 77 | + |
| 78 | +--- |
| 79 | + |
| 80 | +## 6) Frontend quick rules |
| 81 | + |
| 82 | +* Use `<script setup lang="ts">`, Composition API; strong typing (avoid `any`). |
| 83 | +* State via **Pinia**; i18n via **Vue I18n**. Small, presentational components; move logic to composables/stores. |
| 84 | +* Use Tailwind utilities; avoid inline styles. Tests via **Vitest** (unit) and **Cypress** (E2E). |
| 85 | +* Use tsconfig path aliases (e.g., `@shared/utils`); avoid deep relative chains. |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +## 7) Infra & local dev hooks (read-only for Copilot) |
| 90 | + |
| 91 | +* Local dev via **Tilt** (`tilt up`); initial `helm dependency update` under `infrastructure/rag` may be required. |
| 92 | +* `.env.template` documents required env vars; copy to `.env` for local dev. |
| 93 | +* Features (frontend, keydb, langfuse, qdrant) must be enabled in Tilt when needed. |
| 94 | + |
| 95 | +**Do not** have Copilot modify Helm/Terraform unless explicitly asked; surface TODOs instead. |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +## 8) Anti-patterns (forbidden) |
| 100 | + |
| 101 | +* Business logic in FastAPI routers or Vue components |
| 102 | +* Relative imports; wildcard imports; raw SQL with f-strings |
| 103 | +* `requests` in async code; `time.sleep()` in app/tests (use `asyncio.sleep`) |
| 104 | +* Logging secrets/PII; exposing stack traces to clients |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## 9) Examples Copilot should imitate |
| 109 | + |
| 110 | +**Pydantic v2 model (NumPy docstring):** |
| 111 | + |
| 112 | +```python |
| 113 | +""" |
| 114 | +User model. |
| 115 | +
|
| 116 | +Parameters |
| 117 | +---------- |
| 118 | +id : str |
| 119 | + User ID. |
| 120 | +name : str |
| 121 | + Full name. |
| 122 | +active : bool |
| 123 | + Whether the user is active. |
| 124 | +""" |
| 125 | +from pydantic import BaseModel, field_validator |
| 126 | + |
| 127 | +class User(BaseModel): |
| 128 | + id: str |
| 129 | + name: str |
| 130 | + active: bool = True |
| 131 | + |
| 132 | + @field_validator("name") |
| 133 | + @classmethod |
| 134 | + def not_empty(cls, v: str) -> str: |
| 135 | + if not v.strip(): |
| 136 | + raise ValueError("name must not be empty") |
| 137 | + return v |
| 138 | +``` |
| 139 | + |
| 140 | +**Router + DI outline (service stays thin):** |
| 141 | + |
| 142 | +```python |
| 143 | +from fastapi import APIRouter, Depends |
| 144 | +from .schemas import User |
| 145 | +from ..services.user_service import UserService |
| 146 | +from ..container import get_user_service |
| 147 | + |
| 148 | +router = APIRouter(prefix="/users", tags=["users"]) |
| 149 | + |
| 150 | +@router.get("/", response_model=list[User]) |
| 151 | +async def list_users(svc: UserService = Depends(get_user_service)): |
| 152 | + return await svc.list_users() |
| 153 | +``` |
| 154 | + |
| 155 | +--- |
| 156 | + |
| 157 | +## 10) Review & quality gates |
| 158 | + |
| 159 | +* Python: run `black`, `isort`, `flake8`, `pytest --cov` before PR. |
| 160 | +* Frontend: run ESLint + unit tests (Vitest), add Cypress E2E as needed. |
| 161 | +* Keep PRs small and focused; update docs and `.env.template` when adding config. |
| 162 | + |
| 163 | +--- |
| 164 | + |
| 165 | +## 11) Copilot prompts for this repo |
| 166 | + |
| 167 | +* "Generate a router in `libs/rag-core-api` for collections (list/create/delete) and wire it in `services/rag-backend`." |
| 168 | +* "Create Pydantic settings for S3 credentials and inject them into the admin backend repository." |
| 169 | +* "Build a Vue 3 component using Pinia that renders chat messages and emits an event on send, with Vitest unit tests." |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +## 12) Quick checklist (Copilot output) |
| 174 | + |
| 175 | +* Builds locally under Tilt? Lints? Tests? |
| 176 | +* Respects this file (paths, libs>services, typing, async)? |
| 177 | +* Uses structured logging, env-driven config, and does **not** leak secrets? |
0 commit comments