From f851388d810e5b5922c42ad4a5aa1f1f944ebbbd Mon Sep 17 00:00:00 2001 From: Amr Abed <3361565+amrabed@users.noreply.github.com> Date: Thu, 9 Apr 2026 19:28:36 -0400 Subject: [PATCH 1/2] Add AGENTS.md with project guidelines for AI coding agents --- AGENTS.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..03aa667 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,89 @@ +# AGENTS.md + +This file provides guidelines for AI coding agents (e.g., GitHub Copilot, Cursor, Codex) working in this repository. + +## Dependencies + +- Always use Poetry for dependency management (`poetry add `) +- Use Pydantic for data models +- Use Pydantic-settings for environment variable configuration in a `settings.py` file + +## Testing Guidelines + +- Use pytest, not unittest +- Use `pytest` monkeypatch and `pytest-mock` for mocking instead of `unittest.MagicMock` +- Do not cheat! Never modify source code just to make a failing test pass. Fix real bugs in source code and fix incorrect assertions in tests + +## Make Targets + +Use `make` targets for all common workflows: lint, test, run locally, and deploy. Refer to `docs/README.md` for currently available targets. Add new targets to `Makefile` as needed. + +## Notes + +- Python 3.12+ required +- Dependencies are managed via `pyproject.toml` and locked in `poetry.lock` +- Do not edit `poetry.lock` directly; use `make update` to update dependencies + +## Coding Conventions + +### Field descriptions + +Every field in a Pydantic model or pydantic-settings class must be documented using `Field(description="...")`. This makes descriptions machine-readable and visible in generated JSON schemas. + +```python +from uuid import uuid4 +from pydantic import BaseModel, Field + +class Item(BaseModel, populate_by_name=True, alias_generator=to_camel): + id: str = Field(description="Unique item identifier.", default_factory=lambda:str(uuid4())) + name: str = Field(description="Human-readable item name.") +``` + +### camelCase alias convention + +All `BaseModel` subclasses must be defined with `populate_by_name=True` and `alias_generator=to_camel` so that JSON payloads can use camelCase while Python attributes use snake_case. Always serialise with `model_dump(by_alias=True, exclude_none=True)` to produce camelCase JSON output and omit unset optional fields. + +```python +from uuid import uuid4 +from pydantic import BaseModel, Field +from pydantic.alias_generators import to_camel + +class Item(BaseModel, populate_by_name=True, alias_generator=to_camel): + item_id: str = Field(description="Unique item identifier.", default_factory=str(uuid4())) + # Accepts {"itemId": "..."} from JSON; attribute is item.item_id + # model_dump() → {"item_id": ...} + # model_dump(by_alias=True, exclude_none=True) → {"itemId": ...} +``` + +### No `model_config` class attribute + +Do not use `model_config = ConfigDict(...)` or `model_config = SettingsConfigDict(...)`. Pass configuration options as keyword arguments to the base class instead. + +```python +# Good +class Item(BaseModel, extra="allow", populate_by_name=True, alias_generator=to_camel): ... +class Settings(BaseSettings, case_sensitive=False): ... + +# Bad +class Item(BaseModel): + model_config = ConfigDict(extra="allow") +``` + +### Import style + +Do not add unnecessary imports like `from __future__ import annotations`. Always use explicit `from x import y` form: + +```python +from json import dumps, loads +from pytest import fixture, main, raises +from aws_cdk.aws_lambda import Code, Function, Runtime +``` + +### Test file main block + +Every test file must end with: + +```python +if __name__ == "__main__": + main() +``` From 84ffc529e85e23e2f025e9cf9ae71293a6aa3afd Mon Sep 17 00:00:00 2001 From: Amr Abed <3361565+amrabed@users.noreply.github.com> Date: Thu, 9 Apr 2026 19:38:41 -0400 Subject: [PATCH 2/2] Expand AGENTS.md with project overview, structure, setup, and workflow sections --- AGENTS.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 03aa667..45748d4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,132 @@ This file provides guidelines for AI coding agents (e.g., GitHub Copilot, Cursor, Codex) working in this repository. +--- + +## Project Overview + +This is a **Python project template** that provides a pre-configured, production-ready starting point for Python applications. It includes out-of-the-box support for: + +- **Packaging & dependency management** via [Poetry](https://python-poetry.org) +- **CLI** via [click](https://click.palletsprojects.com) +- **Testing & coverage** via [pytest](https://pytest.org) and [coverage](https://coverage.readthedocs.io) +- **Linting, formatting & import sorting** via [ruff](https://docs.astral.sh/ruff) +- **Type checking** via [pyright](https://microsoft.github.io/pyright) +- **Pre-commit hooks** via [pre-commit](https://pre-commit.com) +- **Documentation** via [MkDocs](https://www.mkdocs.org) with [mkdocstrings](https://mkdocstrings.github.io), auto-deployed to GitHub Pages +- **CI/CD** via GitHub Actions +- **Containerisation** via Docker and Dev Containers + +--- + +## Project Structure + +``` +├── .devcontainer/ # Dev container configuration +├── .github/ # GitHub-specific files (Actions, templates, Dependabot) +├── .vscode/ # VS Code settings +├── docs/ # Documentation source +│ ├── README.md # Project README and MkDocs home page +│ ├── CONTRIBUTING.md # Contributing guidelines +│ └── reference/ # Auto-generated API reference pages +├── project/ # Main source package (renamed via `make project`) +│ ├── __init__.py +│ └── app.py # CLI entry point +├── tests/ # Test suite +│ ├── conftest.py # Shared pytest fixtures and hooks +│ └── test_app.py # Sample tests +├── compose.yml # Docker Compose file +├── Dockerfile # App container +├── Makefile # Workflow automation targets +├── mkdocs.yml # MkDocs configuration +├── pyproject.toml # Project metadata, dependencies, and tool configuration +└── poetry.lock # Locked dependency versions (do not edit manually) +``` + +> **Note:** The `project/` folder is the template placeholder. After initialising a real project with `make project NAME=...`, it is renamed to the chosen package name. + +--- + +## Setup + +### Prerequisites + +- Python 3.12+ +- [pipx](https://pipx.pypa.io) (to install Poetry) +- Docker (for Dev Container or containerised runs) + +### First-time setup + +```bash +# 1. Install Poetry (if not already installed) +make poetry + +# 2. Install all dependencies +make install + +# 3. Install pre-commit hooks +make precommit + +# 4. Activate the virtual environment +make venv +``` + +### Rename the template for a new project (run once) + +```bash +make project NAME="my-project" DESCRIPTION="My app" AUTHOR="Your Name" EMAIL="you@example.com" GITHUB="your-username" +``` + +--- + +## Common Commands + +| Task | Command | +|---|---| +| Install dependencies | `make install` | +| Update dependencies | `make update` | +| Lint and format | `make lint` | +| Run tests with coverage | `make test` | +| Run app locally | `app` (after `make venv`) or `poetry run app` | +| Run app in Docker | `docker compose run app` | +| Serve docs locally | `make local` | +| Deploy docs to GitHub Pages | `make docs` | +| Full setup from scratch | `make all` | + +> Refer to `docs/README.md` for the full list of available targets. Add new targets to `Makefile` as needed. + +--- + +## Code Style + +- **Line length**: 120 characters (configured in `pyproject.toml` under `[tool.ruff]`) +- **Linter/formatter**: `ruff` — enforces `E` (pycodestyle errors) and `I` (isort) rules +- **Type checker**: `pyright` — all imports must resolve; missing imports are errors +- **Pre-commit**: hooks run `ruff` automatically before every commit +- Run `make lint` to format, sort imports, and check types manually +- All public functions and classes must have docstrings (used by `mkdocstrings` for API docs) + +--- + +## Testing + +- Tests live in the `tests/` directory and mirror the source structure +- Run the full test suite with coverage using `make test` (runs `pytest` via `coverage`) +- Coverage is measured with branch coverage enabled; the report is printed to the terminal and exported as `coverage.xml` +- Shared fixtures belong in `tests/conftest.py` +- Test files must be named `test_*.py` + +--- + +## Git Workflow + +- Work on feature branches; open a pull request to `main` +- Pre-commit hooks enforce formatting and linting on every commit +- CI (`.github/workflows/check.yml`) runs lint and tests on every push +- Do not commit directly to `main` + +--- + ## Dependencies - Always use Poetry for dependency management (`poetry add `)