Skip to content

Commit 3a2a134

Browse files
chore: add copilot style guide (#146)
Add copilot instructions file for customized and better copilot generation. --------- Co-authored-by: Andreas Klos <aklos@outlook.de>
1 parent d8ea798 commit 3a2a134

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

.github/copilot-instructions.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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

Comments
 (0)