You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(instructions): upgrade to Claude Code-optimized agent instructions
Rewrite copilot-instructions.md for agentic use: expand the models
design decision rationale, clarify integration-test architecture,
add release tag format with valid coach names, tighten Agent Mode
buckets with specific file references, add commit/branch review gate,
and add the no-cross-project-justification guideline.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .github/copilot-instructions.md
+84-27Lines changed: 84 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,9 @@
2
2
3
3
## Overview
4
4
5
-
REST API for managing football players built with Python and FastAPI. Implements async CRUD operations with SQLAlchemy 2.0 (async), SQLite, Pydantic validation, and in-memory caching. Part of a cross-language comparison study (.NET, Go, Java, Rust, TypeScript).
5
+
REST API for managing football players built with Python and FastAPI. Implements
6
+
async CRUD operations with SQLAlchemy 2.0 (async), SQLite, Pydantic validation,
7
+
and in-memory caching.
6
8
7
9
## Tech Stack
8
10
@@ -31,23 +33,49 @@ tools/ — standalone seed scripts (run manually, not via Alembic)
31
33
tests/ — pytest integration tests
32
34
```
33
35
34
-
**Layer rule**: `Routes → Services → SQLAlchemy → SQLite`. Routes handle HTTP concerns only; business logic belongs in services.
-**Async**: All routes and service functions must be `async def`; use `AsyncSession` (never `Session`); use `aiosqlite` (never `sqlite3`); use SQLAlchemy 2.0 `select()` (never `session.query()`)
-**Models**: `PlayerRequestModel` (no `id`, used for POST/PUT) and `PlayerResponseModel` (includes `id: UUID`, used for GET/POST responses); never use the removed `PlayerModel`
43
-
-**Primary key**: UUID surrogate key (`id`) — opaque, internal, used for GET by id only. UUID v4 for API-created records; UUID v5 (deterministic) for migration-seeded records. `squad_number` is the natural key — human-readable, domain-meaningful, used for all mutation endpoints (PUT, DELETE) and preferred for all external consumers
-**API contract**: camelCase JSON via Pydantic `alias_generator=to_camel`;
47
+
Python internals stay snake_case
48
+
-**Models**: `PlayerRequestModel` (no `id`, used for POST/PUT) and
49
+
`PlayerResponseModel` (includes `id: UUID`, used for GET/POST responses).
50
+
One request model intentionally covers both POST and PUT — per-operation
51
+
differences (conflict check on POST, mismatch guard on PUT) are handled at
52
+
the route layer, not by duplicating the model. Never reintroduce the removed
53
+
`PlayerModel`; it was removed because a single flat model conflated ORM,
54
+
request, and response concerns.
55
+
-**Primary key**: UUID surrogate key (`id`) — opaque, internal, used for GET
56
+
by id only. UUID v4 for API-created records; UUID v5 (deterministic) for
57
+
migration-seeded records. `squad_number` is the natural key —
58
+
human-readable, domain-meaningful, used for all mutation endpoints (PUT,
59
+
DELETE) and preferred for all external consumers
60
+
-**Caching**: cache key `"players"` (hardcoded); clear on POST/PUT/DELETE;
61
+
`X-Cache` header (HIT/MISS)
62
+
-**Errors**: Catch specific exceptions with rollback in services; Pydantic
63
+
validation returns 422 (not 400); squad number mismatch on PUT returns 400
64
+
(not 422 — it is a semantic error, not a validation failure)
46
65
-**Logging**: `logging` module only; never `print()`
47
66
-**Line length**: 88; complexity ≤ 10
48
67
-**Import order**: stdlib → third-party → local
49
-
-**Tests**: naming pattern `test_request_{method}_{resource}_{context}_response_{outcome}`; docstrings single-line, concise; `tests/player_stub.py` for test data; `tests/test_main.py` excluded from Black
50
-
-**Avoid**: sync DB access, mixing sync/async, `print()`, missing type hints, unhandled exceptions
68
+
-**Tests**: integration tests against the real pre-seeded SQLite DB via
- Breaking API contract changes (field renames, type changes, removing fields)
161
+
- Global error handling middleware
162
+
- HTTP status codes assigned to existing error conditions
112
163
113
164
### Never modify
114
165
115
166
-`.env` files (secrets)
167
+
-`storage/players-sqlite3.db` directly — schema changes go through
168
+
`schemas/player_schema.py` and `tools/` seed scripts
116
169
- Production configurations
117
-
- Async/await patterns (mandatory throughout)
118
-
- Type hints (mandatory throughout)
119
-
- Core layered architecture
120
170
121
171
### Key workflows
122
172
123
-
**Add an endpoint**: Add Pydantic model in `models/` → add async service method in `services/` with error handling → add route in `routes/` with `Depends(generate_async_session)` → add tests following naming pattern → run pre-commit checks.
173
+
**Add an endpoint**: Add Pydantic model in `models/` if the request/response
174
+
shape is new → add async service method in `services/` with error handling and
175
+
rollback → add route in `routes/` with `Depends(generate_async_session)` →
176
+
add tests following the naming pattern → run pre-commit checks.
124
177
125
-
**Modify schema**: Update `schemas/player_schema.py` → manually update `storage/players-sqlite3.db` (preserve 26 players) → update `models/player_model.py` if API changes → update services and tests → run `pytest`.
`storage/players-sqlite3.db` (preserve all 26 seeded players) → update
180
+
`models/player_model.py` if the API shape changes → update services and tests
181
+
→ run `pytest`.
126
182
127
-
**After completing work**: Suggest a branch name (e.g. `feat/add-player-stats`) and a commit message following Conventional Commits including co-author line:
183
+
**After completing work**: Propose a branch name and commit message for user
184
+
approval. Do not create a branch, commit, or push until the user explicitly
0 commit comments