Skip to content

Commit 3c01ab6

Browse files
authored
chore: add codex instructions guide (#147)
Add codex instructions file for customized and better codex generation.
1 parent 3a2a134 commit 3c01ab6

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

.github/codex-instructions.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# .github/codex-instructions.md
2+
3+
> **Scope:** These instructions tune our **Codex** code-generation agent (LLM via API/CLI) for this monorepo. They are **authoritative**: follow them over generic best practices. Output must compile, pass linters/tests, and fit our structure.
4+
5+
---
6+
7+
## 1) Repository at a glance
8+
9+
* **Monorepo:** Python backends + Vue 3/TypeScript frontend.
10+
* **Structure:**
11+
12+
* `libs/` – reusable Python packages (APIs, domain/services, repositories, schemas, utils)
13+
* `services/` – thin Python apps composing `libs`; Vue/Nx frontend
14+
* `infrastructure/` – Helm/Tilt/K3d, Terraform, values under `infrastructure/rag/values.yaml`
15+
* `docs/` – docs & UI customization
16+
* **Config:** Env-driven via `.env` (dev tooling only). Never hardcode secrets.
17+
18+
> **Rule of thumb:** Business logic lives in **`libs`**. **`services`** only do bootstrapping, DI, routing, and wiring.
19+
20+
---
21+
22+
## 2) Languages & toolchain
23+
24+
* **Python:** 3.13, **FastAPI**, **Pydantic v2**, **Poetry**
25+
* **Style/Quality:** `black` (line length **120**), `isort` (profile `black`), `flake8` (plugins), NumPy docstrings, type hints (PEP 484), absolute imports only
26+
* **Testing:** `pytest` (+ coverage), optional `pytest-asyncio` for async code
27+
* **Frontend:** Vue 3, TypeScript, Vite, Nx, Tailwind, Pinia, Vue I18n (Vitest + Cypress; ESLint)
28+
29+
---
30+
31+
## 3) Codex behavior (important)
32+
33+
* **Do not invent** secrets/URLs/paths. Use placeholders and `TODO:` comments.
34+
* **Prefer libs over services:** Add APIs/logic in `libs/*`, wire in `services/*` (keep `main.py` thin: app import + container registration).
35+
* **Always emit tests** with new Python code (≥1 happy path + ≥1 edge case). Keep unit tests isolated and fast.
36+
* **Ask via comments if uncertain:** Start the diff with a short `# Assumptions:` block.
37+
* **Respect performance & readability:** Small cohesive functions, avoid deep nesting/complexity.
38+
39+
---
40+
41+
## 4) Output contract
42+
43+
When asked to modify or add code, follow **one** of these formats:
44+
45+
* **Single file (new):**
46+
47+
```md
48+
## path: libs/<pkg>/src/<pkg>/module.py
49+
```
50+
51+
```python
52+
# file content here
53+
```
54+
55+
* **Single file (edit):** provide a **unified diff**:
56+
57+
```diff
58+
--- a/libs/<pkg>/src/<pkg>/module.py
59+
+++ b/libs/<pkg>/src/<pkg>/module.py
60+
@@
61+
- old line
62+
+ new line
63+
```
64+
65+
* **Multiple files:** repeat the above per file, in logical order (libs first, then services, then tests).
66+
67+
* **Test plan:** end with a short block:
68+
69+
```txt
70+
Build/Test
71+
- poetry install
72+
- pytest -q --maxfail=1 --cov
73+
- black . && isort . && flake8
74+
```
75+
76+
---
77+
78+
## 5) Python specifics
79+
80+
### Typing & style
81+
82+
* Use modern typing (`list[str]`, `dict[str, Any]`), avoid `Any` unless necessary.
83+
* NumPy-style docstrings for public APIs. No wildcard imports. **Absolute imports only.**
84+
85+
### FastAPI
86+
87+
* Endpoints are **thin**; DI via `Depends`/container; no business logic in routers.
88+
* Every route defines `response_model=...` and sanitizes outputs.
89+
* Centralize exception mapping; never leak stack traces in prod.
90+
* Prefer **async** endpoints for I/O-bound work.
91+
92+
### Validation & config
93+
94+
* **Pydantic v2**: use `field_validator`/`model_validator`; strict models at boundaries.
95+
* **Configuration:** use `pydantic-settings` for environment-driven settings. `.env` is dev-only (Tilt/tests). Do not auto-load `.env` in production app code.
96+
97+
### HTTP & concurrency
98+
99+
* Use `httpx.AsyncClient` with explicit timeouts and retry/backoff. No `requests` in async code.
100+
* Never use `time.sleep()`; use `asyncio.sleep()` (or anyio) in async contexts.
101+
102+
### Repositories & services
103+
104+
* Repositories are ports/adapters for DB/HTTP/queues. Services depend on repositories; routers depend on services.
105+
* Transactions via context manager; avoid autocommit. Do not use raw SQL with f-strings.
106+
107+
### Logging
108+
109+
* Use `logging` (or `structlog`) with structured/contextual fields (`event`, `service`, `request_id`). No PII/secrets in logs.
110+
111+
### File layout for new Python code
112+
113+
* `libs/<package>/src/<package>/...` → APIs, services, repositories, schemas, utils
114+
* `libs/<package>/tests/` → tests for the above
115+
* `services/<service>/` → bootstrap, DI container, runtime config
116+
117+
---
118+
119+
## 6) Testing
120+
121+
* `pytest` with fixtures and mocks (`unittest.mock`, `pytest-mock`). No real network in unit tests; mock `httpx` (e.g., `respx`).
122+
* Aim for **high coverage on core libs**. Mark slow tests with `@pytest.mark.slow`.
123+
* Suggested `pytest.ini`:
124+
125+
```ini
126+
[pytest]
127+
addopts = -q --strict-markers --strict-config --maxfail=1 --cov=libs --cov-report=term-missing
128+
markers =
129+
slow: marks tests as slow (deselect with '-m "not slow"')
130+
asyncio_mode = strict
131+
```
132+
133+
---
134+
135+
## 7) Frontend quick rules
136+
137+
* Use `<script setup lang="ts">` + Composition API. Strong typing (avoid `any`).
138+
* State with **Pinia**; i18n with **Vue I18n**. Keep components small/presentational; move logic to composables/stores.
139+
* Use Tailwind utilities; avoid inline styles. Unit tests with **Vitest**; E2E with **Cypress**.
140+
* Use tsconfig path aliases (e.g., `@shared/utils`); expose stable public APIs via `index.ts` in libs.
141+
142+
---
143+
144+
## 8) Anti‑patterns (forbidden)
145+
146+
* Business logic in FastAPI routers or Vue components
147+
* Relative imports; wildcard imports; raw SQL with f-strings
148+
* `requests` in async code; `time.sleep()` in app/tests
149+
* Logging secrets/PII; exposing stack traces to clients
150+
151+
---
152+
153+
## 9) Examples Codex should imitate
154+
155+
**Pydantic v2 model (NumPy docstring):**
156+
157+
```python
158+
"""
159+
User model.
160+
161+
Parameters
162+
----------
163+
id : str
164+
User ID.
165+
name : str
166+
Full name.
167+
active : bool
168+
Whether the user is active.
169+
"""
170+
from pydantic import BaseModel, field_validator
171+
172+
class User(BaseModel):
173+
id: str
174+
name: str
175+
active: bool = True
176+
177+
@field_validator("name")
178+
@classmethod
179+
def not_empty(cls, v: str) -> str:
180+
if not v.strip():
181+
raise ValueError("name must not be empty")
182+
return v
183+
```
184+
185+
**Router + DI outline (service stays thin):**
186+
187+
```python
188+
from fastapi import APIRouter, Depends
189+
from .schemas import User
190+
from ..services.user_service import UserService
191+
from ..container import get_user_service
192+
193+
router = APIRouter(prefix="/users", tags=["users"])
194+
195+
@router.get("/", response_model=list[User])
196+
async def list_users(svc: UserService = Depends(get_user_service)):
197+
return await svc.list_users()
198+
```
199+
200+
**httpx AsyncClient (timeouts + retry/backoff skeleton):**
201+
202+
```python
203+
import httpx
204+
from tenacity import retry, stop_after_attempt, wait_exponential
205+
206+
DEFAULT_TIMEOUT = httpx.Timeout(5.0, connect=2.0)
207+
208+
@retry(wait=wait_exponential(multiplier=0.2, max=5), stop=stop_after_attempt(3))
209+
async def fetch_json(url: str) -> dict:
210+
async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client:
211+
resp = await client.get(url)
212+
resp.raise_for_status()
213+
return resp.json()
214+
```
215+
216+
---
217+
218+
## 10) Review & quality gates
219+
220+
* Python: run `black`, `isort`, `flake8`, and `pytest --cov` before PR.
221+
* Frontend: run ESLint + Vitest; add Cypress flows as needed.
222+
* Keep PRs small and focused; update docs and `.env.template` when adding config.
223+
224+
---
225+
226+
## 11) Handy prompts for this repo
227+
228+
* "Create a router in `libs/rag-core-api` for collections (list/create/delete) and wire it in `services/rag-backend`."
229+
* "Add Pydantic settings for S3 credentials and inject into the admin backend repository."
230+
* "Generate a Vue component using Pinia that renders chat messages and emits an event on send, with Vitest tests."
231+
232+
---
233+
234+
## 12) Quick checklist (for every Codex suggestion)
235+
236+
* ✅ Fits `libs/` vs `services/` boundaries and file layout
237+
* ✅ Compiles and passes linters (black/isort/flake8) and tests
238+
* ✅ Uses Pydantic v2, FastAPI DI, httpx async
239+
* ✅ No secrets/PII in code or logs; no stack traces in client responses

0 commit comments

Comments
 (0)