diff --git a/.claude/agents/api-feature-developer.md b/.claude/agents/api-feature-developer.md index e01a8ff..4455258 100644 --- a/.claude/agents/api-feature-developer.md +++ b/.claude/agents/api-feature-developer.md @@ -15,13 +15,14 @@ You are an expert Python SDK developer specializing in building the Bloomy Growt 4. Ensure proper error handling using BloomyError hierarchy 5. Write comprehensive docstrings for mkdocstrings auto-generation -## Codebase Patterns You MUST Follow +## Codebase Patterns ### Architecture Overview - **Client**: `src/bloomy/client.py` (sync) and `src/bloomy/async_client.py` (async) - **Operations**: `src/bloomy/operations/` (sync) and `src/bloomy/operations/async_/` (async) - **Models**: `src/bloomy/models.py` - Pydantic models with PascalCase aliases - **Base Classes**: `BaseOperations` (sync) and `AsyncBaseOperations` (async) +- **Transform Mixins**: `src/bloomy/operations/mixins/_transform.py` - response-shaping logic shared by the sync and async classes ### Step-by-Step Feature Implementation @@ -35,44 +36,11 @@ class NewFeatureModel(BloomyBaseModel): created_date: datetime | None = Field(default=None, alias="CreateDate") ``` -**Step 2: Create Sync Operations** (`src/bloomy/operations/.py`) -```python -from ..models import NewFeatureModel -from ..utils.base_operations import BaseOperations - -class NewFeatureOperations(BaseOperations): - """Operations for managing new features.""" - - def list(self, user_id: int | None = None) -> list[NewFeatureModel]: - """List all items for a user. - - Args: - user_id: User ID. Defaults to authenticated user. +**Step 2: Create a Transform Mixin** (`src/bloomy/operations/mixins/_transform.py`) - Returns: - List of NewFeatureModel objects. - """ - uid = user_id or self.user_id - response = self._client.get(f"endpoint/{uid}") - response.raise_for_status() - return [NewFeatureModel.model_validate(item) for item in response.json()] -``` - -**Step 3: Create Async Operations** (`src/bloomy/operations/async_/.py`) -```python -from ...models import NewFeatureModel -from ...utils.async_base_operations import AsyncBaseOperations - -class AsyncNewFeatureOperations(AsyncBaseOperations): - """Async operations for managing new features.""" - - async def list(self, user_id: int | None = None) -> list[NewFeatureModel]: - """List all items for a user.""" - uid = user_id or await self.get_user_id() - response = await self._client.get(f"endpoint/{uid}") - response.raise_for_status() - return [NewFeatureModel.model_validate(item) for item in response.json()] -``` +**Step 3: Create Sync and Async Operations** (`src/bloomy/operations/.py`, `src/bloomy/operations/async_/.py`) +- Each class inherits its base class and the mixin: `class FeatureOperations(BaseOperations, FeatureOperationsMixin)` +- Model them on an existing resource, e.g. `operations/headlines.py`, `operations/async_/headlines.py`, and `operations/mixins/headlines_transform.py` **Step 4: Register in Clients** - Add import and attribute to `src/bloomy/client.py` @@ -103,8 +71,8 @@ Always use the BloomyError hierarchy: ## Quality Checklist Before Completion - [ ] Pydantic model defined with proper aliases -- [ ] Sync operations class created -- [ ] Async operations class created (mirrors sync exactly) +- [ ] Transform mixin created +- [ ] Sync and async operations classes created, each inheriting its base class and the mixin (async mirrors sync exactly) - [ ] Both clients updated with new attribute - [ ] All `__init__.py` exports updated - [ ] Google-style docstrings on all public methods diff --git a/.claude/agents/code-quality-reviewer.md b/.claude/agents/code-quality-reviewer.md index 4044ca9..7f5792f 100644 --- a/.claude/agents/code-quality-reviewer.md +++ b/.claude/agents/code-quality-reviewer.md @@ -9,7 +9,7 @@ You are a senior code reviewer ensuring the Bloomy Python SDK maintains high sta ## Your Responsibilities -1. Run all quality gate checks (ruff, pyright, pytest) +1. Run all quality gate checks (ruff, basedpyright, pytest) 2. Review code for patterns, security, and maintainability 3. Identify issues and provide actionable feedback 4. Ensure SDK patterns are followed consistently @@ -27,7 +27,7 @@ uv run ruff format . uv run ruff check . --fix # 3. Type checking (strict mode) -uv run pyright +uv run basedpyright # 4. Run all tests with coverage uv run pytest @@ -36,36 +36,9 @@ uv run pytest uv run mkdocs build --strict ``` -## Ruff Configuration (from pyproject.toml) - -**Enabled Rules:** -- E, W: PEP 8 style -- F: Pyflakes (real errors) -- I: isort (import sorting) -- B: Bugbear (likely bugs) -- C4: Comprehensions -- UP: PyUpgrade (modern syntax) -- C901: McCabe complexity (max 10) -- SIM: Simplify -- N: PEP 8 naming -- DOC, D: Docstring format -- ARG: Unused arguments -- PERF: Performance -- ASYNC: Async best practices - -**Line Length**: 88 characters -**Quote Style**: Double quotes - -## Pyright Configuration - -- **Mode**: Strict -- **Python Version**: 3.12 -- **Scope**: `src/` only (excludes tests) -- **Key Checks**: - - reportMissingImports - - reportUnknownMemberType - - reportUnknownArgumentType - - reportUnknownVariableType +## Tool Configuration + +Ruff and basedpyright settings (rule selection, line length, strict mode, `src/`-only type checking) live in `pyproject.toml`, and the CI checks are in `.github/workflows/quality.yml`. Consult them when a rule or setting is in question. ## Code Review Checklist diff --git a/.claude/agents/sdk-test-engineer.md b/.claude/agents/sdk-test-engineer.md index 148da44..9f755a1 100644 --- a/.claude/agents/sdk-test-engineer.md +++ b/.claude/agents/sdk-test-engineer.md @@ -40,7 +40,7 @@ uv run pytest uv run pytest tests/test_users.py # Run specific test -uv run pytest tests/test_users.py::TestUserOperations::test_details -v +uv run pytest tests/test_users.py::TestUserOperations::test_details_basic -v # Run with verbose output uv run pytest -v @@ -54,16 +54,11 @@ uv run pytest --cov=bloomy --cov-report=term-missing ## Fixtures (from conftest.py) -### HTTP Client Mocks -```python -@pytest.fixture -def mock_http_client() -> Mock: - """Mock httpx.Client for sync tests.""" +Read `tests/conftest.py` for exact signatures. -@pytest.fixture -def mock_response() -> Mock: - """Mock httpx.Response.""" -``` +### HTTP Client Mocks +- `mock_response`: a mocked `httpx.Response` that reports success +- `mock_http_client`: a mocked `httpx.Client` whose methods return `mock_response` ### Sample Data Fixtures ```python @@ -79,11 +74,7 @@ def sample_meeting_data() -> dict[str, Any]: ``` ### User ID Mock (Important!) -```python -@pytest.fixture -def mock_user_id() -> Mock: - """Prevents lazy-loading API calls to /users/mine.""" -``` +`mock_user_id` patches `BaseOperations.user_id` to return 123, which prevents lazy-loading API calls to `/users/mine`. ## Sync Test Pattern diff --git a/.claude/agents/version-control-engineer.md b/.claude/agents/version-control-engineer.md index 40f6625..af951dd 100644 --- a/.claude/agents/version-control-engineer.md +++ b/.claude/agents/version-control-engineer.md @@ -48,7 +48,7 @@ fix(async): resolve race condition in concurrent requests docs(guide): add async bulk operations documentation -chore: bump version to 0.19.0 +chore(release): bump version to 0.19.0 ``` ## Version Management @@ -62,25 +62,6 @@ chore: bump version to 0.19.0 - **MINOR** (0.X.0): New features, backward compatible - **PATCH** (0.0.X): Bug fixes, backward compatible -### Version Bump Process - -```bash -# 1. Ensure all changes are committed -git status - -# 2. Update version in pyproject.toml -# Edit: version = "0.20.0" - -# 3. Update CHANGELOG.md (see Changelog section below) - -# 4. Commit version bump and changelog -git add pyproject.toml CHANGELOG.md -git commit -m "chore: bump version to 0.20.0" - -# 5. Create git tag -git tag -a v0.20.0 -m "Release v0.20.0" -``` - ## Changelog Management ### Changelog Location @@ -169,7 +150,7 @@ EOF ### PR Review Checklist - All CI checks pass (when available) -- Quality gates pass locally (`ruff`, `pyright`, `pytest`) +- Quality gates pass locally (`ruff`, `basedpyright`, `pytest`) - Documentation is updated - Tests are included - Follows SDK patterns @@ -186,35 +167,32 @@ git pull origin main # 2. Run full quality check uv run ruff format . uv run ruff check . --fix -uv run pyright +uv run basedpyright uv run pytest uv run mkdocs build --strict -# 3. Verify all tests pass -# 4. Review recent commits for changelog -git log --oneline v0.19.0..HEAD +# 3. Review recent commits for changelog +git log --oneline "$(git describe --tags --abbrev=0)"..HEAD ``` ### Release Steps -```bash -# 1. Update CHANGELOG.md -# - Move items from [Unreleased] to new version section -# - Add release date: ## [0.20.0] - 2025-12-10 -# - Update comparison links at bottom +The release commit goes through a PR like any other change (see Safety Rules). -# 2. Update version in pyproject.toml -# version = "0.20.0" +```bash +# 1. Create the release branch +git checkout -b chore/release-vX.Y.Z -# 3. Commit release +# 2. Update CHANGELOG.md (see "During Release" above) and set version = "X.Y.Z" in pyproject.toml git add CHANGELOG.md pyproject.toml -git commit -m "chore: release v0.20.0" - -# 4. Create annotated tag (simple message - changelog is in CHANGELOG.md) -git tag -a v0.20.0 -m "Release v0.20.0" - -# 5. Push with tags -git push origin main --tags +git commit -m "chore(release): bump version to X.Y.Z" +git push -u origin chore/release-vX.Y.Z +gh pr create --title "chore(release): bump version to X.Y.Z" --body "..." + +# 3. After the PR merges, tag the merge commit and push only the tag +git checkout main && git pull origin main +git tag -a vX.Y.Z -m "Release vX.Y.Z" # simple message - changelog is in CHANGELOG.md +git push origin vX.Y.Z ``` ### Automated GitHub Release @@ -238,7 +216,7 @@ When you push a tag matching `v*`, the GitHub Actions workflow (`.github/workflo git log --oneline -20 # View changes since last tag -git log --oneline v0.18.0..HEAD +git log --oneline "$(git describe --tags --abbrev=0)"..HEAD # Check current status git status @@ -246,9 +224,6 @@ git status # View diff of staged changes git diff --staged -# Interactive rebase (clean up commits) -git rebase -i HEAD~3 - # Amend last commit (careful!) git commit --amend diff --git a/CLAUDE.md b/CLAUDE.md index 611bbed..30cb0fd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,24 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Subagent Delegation (Manager Mode) -**IMPORTANT**: You should act as a manager, delegating implementation work to specialized subagents while focusing on coordination and review. - -### Available Subagents - -| Subagent | Use For | -|----------|---------| -| `api-feature-developer` | New SDK operations, API features, sync/async implementations | -| `mkdocs-documentation-writer` | Guides, API docs, README updates, changelog | -| `code-quality-reviewer` | Quality gates (ruff, pyright, pytest), code review | -| `sdk-test-engineer` | Writing tests, debugging failures, coverage | -| `version-control-engineer` | Commits, PRs, version bumping, releases | - -### Delegation Guidelines - -1. **PROACTIVELY delegate** to subagents for their specialized domains -2. **Chain workflows**: e.g., implement feature → write tests → review → commit -3. **Review outputs** rather than implementing directly -4. **Use parallel agents** when tasks are independent (e.g., tests + docs simultaneously) +Act as a manager: delegate implementation work to the project subagents in `.claude/agents/` and spend your own effort on coordination and review. The subagents carry this repo's conventions, and delegating keeps the main context free for reviewing their output. Changes of a line or two are faster to make directly. Run subagents in parallel when their tasks are independent, such as tests and docs for the same feature. ### Example Workflows @@ -42,7 +25,7 @@ uv run pytest uv run pytest tests/test_users.py # Run a specific test -uv run pytest tests/test_users.py::test_user_details -v +uv run pytest tests/test_users.py::TestUserOperations::test_details_basic -v # Format code uv run ruff format . @@ -51,7 +34,7 @@ uv run ruff format . uv run ruff check . --fix # Type checking (strict mode) -uv run pyright +uv run basedpyright # Build documentation uv run mkdocs serve diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d35f486..e56fbe3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,7 +61,7 @@ As for coding style guidelines make sure you: - Include type annotations for all public APIs - Run `uv run ruff format .` before committing - Run `uv run ruff check . --fix` to auto-fix linting issues -- Run `uv run pyright` for type checking +- Run `uv run basedpyright` for type checking ### Pull Request Process diff --git a/README.md b/README.md index 67a7404..7b7ade3 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ except BloomyError as e: This SDK uses: - **uv** for package management - **ruff** for formatting and linting -- **pyright** for type checking +- **basedpyright** for type checking - **pytest** for testing To set up the development environment: @@ -247,7 +247,7 @@ uv run ruff format . uv run ruff check . --fix # Type checking -uv run pyright +uv run basedpyright ``` ## Requirements