-
Notifications
You must be signed in to change notification settings - Fork 23
docs: restructure AI instruction files #486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,78 +1,178 @@ | ||
| # GitHub Copilot Instructions | ||
| # Copilot Instructions | ||
|
|
||
| > **⚡ Token Efficiency Note**: This is a minimal pointer file (~500 tokens, auto-loaded by Copilot). | ||
| > For complete operational details, reference: `#file:AGENTS.md` (~2,500 tokens, loaded on-demand) | ||
| > For specialized knowledge, use: `#file:SKILLS/<skill-name>/SKILL.md` (loaded on-demand when needed) | ||
| ## Project Summary | ||
|
|
||
| ## 🎯 Quick Context | ||
| RESTful API with Python 3.13 + FastAPI demonstrating modern async patterns. Player registry with CRUD operations, SQLite + SQLAlchemy 2.0 (async), Pydantic validation, containerization. Part of multi-language comparison study (Java, .NET, TypeScript, Python, Go, Rust). Target: 80%+ test coverage. | ||
|
|
||
| **Project**: FastAPI REST API demonstrating modern Python async patterns | ||
| **Stack**: Python 3.13 • FastAPI • SQLAlchemy (async) • SQLite • Docker • pytest | ||
| **Pattern**: Routes → Services → Database (layered architecture) | ||
| **Philosophy**: Learning-focused PoC emphasizing async/await and type safety | ||
| ## Quick Start | ||
|
|
||
| ## 📐 Core Conventions | ||
| ```bash | ||
| # Install dependencies | ||
| pip install -r requirements.txt | ||
| pip install -r requirements-lint.txt | ||
| pip install -r requirements-test.txt | ||
|
|
||
| # Run development server | ||
| uvicorn main:app --reload --port 9000 | ||
| # Access: http://localhost:9000/docs | ||
|
|
||
| - **Naming**: snake_case for functions/variables, PascalCase for classes | ||
| - **Type Hints**: Mandatory throughout (enforced by mypy if enabled) | ||
| - **Async**: All I/O operations use `async`/`await` | ||
| - **Testing**: pytest with fixtures and async support | ||
| - **Formatting**: black (opinionated), flake8 (linting) | ||
| # Run tests with coverage | ||
| pytest --cov=./ --cov-report=html | ||
|
|
||
| ## 🏗️ Architecture at a Glance | ||
| # Lint and format | ||
| flake8 . | ||
| black --check . # or: black . (to auto-format) | ||
|
|
||
| ```text | ||
| Route → Service → Database | ||
| ↓ ↓ | ||
| Cache Session | ||
| # Docker | ||
| docker compose up | ||
| docker compose down -v # Reset database | ||
| ``` | ||
|
|
||
| - **Routes**: FastAPI endpoints with dependency injection | ||
| - **Services**: Async database operations via SQLAlchemy | ||
| - **Database**: SQLite with async support (`aiosqlite`) | ||
| - **Models**: Pydantic for validation, SQLAlchemy for ORM | ||
| - **Cache**: aiocache SimpleMemoryCache (TTL: 600s / 10 min) | ||
| ## Stack | ||
|
|
||
| ## ✅ Copilot Should | ||
| - Python 3.13.3 (`.python-version` - auto-detected by pyenv/asdf/mise) | ||
| - FastAPI 0.128.6, Uvicorn | ||
| - SQLite + SQLAlchemy 2.0 (async) + aiosqlite | ||
| - pytest + pytest-cov + httpx | ||
| - Flake8 + Black | ||
| - aiocache (in-memory, 10min TTL) | ||
|
|
||
| - Generate idiomatic async FastAPI code with proper type hints | ||
| - Use SQLAlchemy async APIs (`select()`, `scalars()`, `session.commit()`) | ||
| - Follow dependency injection pattern with `Depends()` | ||
| - Write tests with pytest async fixtures | ||
| - Apply Pydantic models for request/response validation | ||
| - Use structured logging (avoid print statements) | ||
| - Implement proper HTTP status codes and responses | ||
| ## Architecture | ||
|
|
||
| ## 🚫 Copilot Should Avoid | ||
| ``` | ||
| Request → Routes → Services → SQLAlchemy → SQLite | ||
| (API) (Logic) (Async ORM) (Storage) | ||
| ↓ | ||
| Pydantic (Validation) | ||
| ``` | ||
|
|
||
| - Synchronous database operations | ||
| - Mixing sync and async code | ||
| - Missing type hints on functions | ||
| - Using `print()` instead of logging | ||
| - Creating routes without caching consideration | ||
| - Ignoring Pydantic validation | ||
| **Key Directories:** | ||
| - `routes/` - API endpoints (player_route.py, health_route.py) | ||
| - `services/` - Business logic (player_service.py) | ||
| - `models/` - Pydantic validation (camelCase JSON API) | ||
| - `schemas/` - SQLAlchemy ORM models | ||
| - `databases/` - Async DB setup, session factory | ||
| - `storage/` - SQLite file (pre-seeded, 26 players) | ||
| - `tests/` - pytest suite (test_main.py, conftest.py) | ||
|
|
||
| **Config Files:** | ||
| - `.flake8` - Linter (max-line-length=88, complexity=10) | ||
| - `pyproject.toml` - Black formatter (line-length=88) | ||
| - `.coveragerc` - Coverage config (80% target) | ||
| - `compose.yaml` - Docker orchestration | ||
| - `Dockerfile` - Multi-stage build | ||
|
|
||
| ## API Endpoints | ||
|
|
||
| All async with `AsyncSession` injection: | ||
| - `POST /players/` → 201|409|422 | ||
| - `GET /players/` → 200 (cached 10min) | ||
| - `GET /players/{player_id}` → 200|404 | ||
| - `GET /players/squadnumber/{squad_number}` → 200|404 | ||
| - `PUT /players/{player_id}` → 200|404|422 | ||
| - `DELETE /players/{player_id}` → 200|404 | ||
| - `GET /health` → 200 | ||
|
|
||
| JSON: camelCase (e.g., `squadNumber`, `firstName`) | ||
|
|
||
| ## CI/CD | ||
|
|
||
| **python-ci.yml** (push/PR to master): | ||
| 1. Lint: commitlint → `flake8 .` → `black --check .` | ||
| 2. Test: `pytest -v` → coverage | ||
| 3. Upload to Codecov | ||
|
|
||
| **python-cd.yml** (tags `v*.*.*-*`): | ||
| 1. Validate semver + coach name | ||
| 2. Run tests | ||
| 3. Build Docker (amd64/arm64) | ||
| 4. Push to GHCR (3 tags: semver/coach/latest) | ||
| 5. Create GitHub release | ||
|
|
||
| ## Critical Patterns | ||
|
|
||
| ### Async Everywhere | ||
| ```python | ||
| # Always use async/await | ||
| async def get_player(async_session: AsyncSession, player_id: int): | ||
| stmt = select(Player).where(Player.id == player_id) | ||
| result = await async_session.execute(stmt) | ||
| return result.scalar_one_or_none() | ||
| ``` | ||
| - All routes: `async def` | ||
| - Database: `AsyncSession` (never `Session`) | ||
| - Driver: `aiosqlite` (not `sqlite3`) | ||
| - SQLAlchemy 2.0: `select()` (not `session.query()`) | ||
|
|
||
| ### camelCase API Contract | ||
| ```python | ||
| class PlayerModel(BaseModel): | ||
| model_config = ConfigDict(alias_generator=to_camel) | ||
| squad_number: int # Python: snake_case | ||
| # JSON API: "squadNumber" (camelCase) | ||
| ``` | ||
|
|
||
| ## ⚡ Quick Commands | ||
| ### Database Schema Changes | ||
| ⚠️ No Alembic yet - manual process: | ||
| 1. Update `schemas/player_schema.py` | ||
| 2. Manually update `storage/players-sqlite3.db` (SQLite CLI/DB Browser) | ||
| 3. Preserve 26 players | ||
| 4. Update `models/player_model.py` if API changes | ||
| 5. Update services + tests | ||
|
|
||
| ```bash | ||
| # Run with hot reload | ||
| uvicorn main:app --reload --host 0.0.0.0 --port 9000 | ||
| ### Caching | ||
| - Key: `"players"` (hardcoded) | ||
| - TTL: 600s (10min) | ||
| - Cleared on POST/PUT/DELETE | ||
| - Header: `X-Cache` (HIT/MISS) | ||
|
|
||
| # Test with coverage | ||
| pytest --cov=. --cov-report=term-missing | ||
| ## Common Issues | ||
|
|
||
| # Docker | ||
| docker compose up | ||
| 1. **SQLAlchemy errors** → Always catch + rollback in services | ||
| 2. **Test file** → `test_main.py` excluded from Black (preserves long names) | ||
| 3. **Database location** → Local: `./storage/`, Docker: `/storage/` (volume) | ||
| 4. **Pydantic validation** → Returns 422 (not 400) | ||
| 5. **Import order** → stdlib → third-party → local | ||
|
|
||
| ## Validation Checklist | ||
|
|
||
| # Swagger: http://localhost:9000/docs | ||
| ```bash | ||
| flake8 . # Must pass | ||
| black --check . # Must pass | ||
| pytest # All pass | ||
| pytest --cov=./ --cov-report=term # ≥80% | ||
| curl http://localhost:9000/players # 200 OK | ||
| ``` | ||
|
|
||
| ## 📚 Need More Detail? | ||
| ## Code Conventions | ||
|
|
||
| - Files: snake_case | ||
| - Functions/vars: snake_case | ||
| - Classes: PascalCase | ||
| - Type hints: Required everywhere | ||
| - Logging: `logging` module (never `print()`) | ||
| - Errors: Catch specific exceptions | ||
| - Line length: 88 | ||
| - Complexity: ≤10 | ||
|
|
||
| ## Commit Messages | ||
|
|
||
| **For operational procedures**: Load `#file:AGENTS.md` | ||
| **For Docker expertise**: *(Planned)* `#file:SKILLS/docker-containerization/SKILL.md` | ||
| **For testing patterns**: *(Planned)* `#file:SKILLS/testing-patterns/SKILL.md` | ||
| Follow Conventional Commits format (enforced by commitlint in CI): | ||
|
|
||
| **Format:** `type(scope): description (#issue)` | ||
|
|
||
| **Rules:** | ||
| - Max 80 characters | ||
| - Types: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`, `ci`, `perf`, `style`, `build` | ||
| - Scope: Optional (e.g., `api`, `db`, `service`, `route`) | ||
| - Issue number: Required suffix | ||
|
|
||
| **Examples:** | ||
| ``` | ||
| feat(api): add player stats endpoint (#42) | ||
| fix(db): resolve async session leak (#88) | ||
| ``` | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| --- | ||
| **CI Check:** First step in python-ci.yml validates all commit messages | ||
|
|
||
| 💡 **Why this structure?** Copilot auto-loads this file on every chat (~500 tokens). Loading `AGENTS.md` or `SKILLS/` explicitly gives you deep context only when needed, saving 80% of your token budget! | ||
| Trust these instructions. Search codebase only if info is incomplete/incorrect. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.