|
| 1 | +{"id":"fastsqla-0nf","title":"Add Agent Skills to FastSQLA","description":"Add Agent Skills (agentskills.io) to FastSQLA so AI coding agents can discover and use FastSQLA more effectively. Skills are SKILL.md files in folders under skills/ that teach agents how to perform specific tasks with the library. Each skill follows the Agent Skills spec: YAML frontmatter (name, description) + markdown instructions with progressive disclosure.\n\n## Skills to create\n\n1. **fastsqla-setup** — Installation, env var configuration, lifespan setup, composing lifespans\n2. **fastsqla-session** — Session dependency, open_session(), flush vs commit, IntegrityError handling\n3. **fastsqla-pagination** — Paginate dependency, Page/Item/Collection models, new_pagination() customization\n4. **fastsqla-models** — Base (DeclarativeBase + DeferredReflection), SQLModel integration, reflection patterns\n5. **fastsqla-testing** — Fixture chains, ASGI testing with httpx + asgi-lifespan, teardown, SQLModel test marks\n\n## Directory structure\n\n```\nskills/\n├── fastsqla-setup/\n│ └── SKILL.md\n├── fastsqla-session/\n│ └── SKILL.md\n├── fastsqla-pagination/\n│ └── SKILL.md\n├── fastsqla-models/\n│ └── SKILL.md\n└── fastsqla-testing/\n └── SKILL.md\n```\n\n## References\n\n- Spec: https://agentskills.io/specification\n- Examples: https://github.com/anthropics/skills\n- FastSQLA source: src/fastsqla.py (single 437-line module)","status":"in_progress","priority":2,"issue_type":"epic","owner":"hadrien@ectobal.com","created_at":"2026-02-26T17:32:20Z","created_by":"Hadrien David","updated_at":"2026-02-26T17:35:40Z"} |
| 2 | +{"id":"fastsqla-0nf.1","title":"Create fastsqla-setup skill","description":"Create `skills/fastsqla-setup/SKILL.md` covering:\n\n- Installation (`pip install FastSQLA`, optional `[sqlmodel]` extra)\n- Required async driver packages (asyncpg, aiosqlite, aiomysql) and URL schemes\n- **Environment variable configuration** (`fastsqla.lifespan`): `SQLALCHEMY_URL` required, all `SQLALCHEMY_*` env vars passed to `async_engine_from_config`, case-insensitive\n- **Programmatic configuration** (`new_lifespan()`): same args as `create_async_engine`\n- **Composing multiple lifespans** with `AsyncExitStack` pattern\n- What the lifespan does on startup (engine creation, `Base.prepare()`, `SessionFactory.configure()`) and shutdown\n- Warning about stray `SQLALCHEMY_*` env vars\n- Startup error message when URL is missing\n\n## Acceptance criteria\n\n- SKILL.md has valid frontmatter (name matches directory, description \u003c 1024 chars)\n- Content \u003c 500 lines\n- Covers both env var and programmatic setup paths\n- Includes lifespan composition example","status":"in_progress","priority":2,"issue_type":"task","owner":"hadrien@ectobal.com","estimated_minutes":30,"created_at":"2026-02-26T17:32:31Z","created_by":"Hadrien David","updated_at":"2026-02-26T17:35:43Z","dependencies":[{"issue_id":"fastsqla-0nf.1","depends_on_id":"fastsqla-0nf","type":"parent-child","created_at":"2026-02-26T12:32:30Z","created_by":"Hadrien David","metadata":"{}"}]} |
| 3 | +{"id":"fastsqla-0nf.2","title":"Create fastsqla-session skill","description":"Create `skills/fastsqla-session/SKILL.md` covering:\n\nThis is the **highest-value skill** — session management is the most error-prone area for users.\n\n- **Session dependency** (`Session`): type annotation for endpoint injection, auto-commit on success, rollback on exception, close always\n- **flush() vs commit()**: never call `session.commit()` in endpoints, use `session.flush()` to get server-generated data (auto-increment IDs). Include correct and incorrect examples.\n- **IntegrityError handling**: catch after `flush()`, re-raise as `HTTPException` to trigger automatic rollback. Explain why silent catch leaves session in broken state.\n- **open_session()**: async context manager for background tasks, scripts, startup routines. Same commit/rollback/close semantics. Document the edge case: if context body succeeds but `commit()` fails, it rolls back and re-raises.\n- Summary of rules\n\n## Source reference\n\nSession lifecycle: `src/fastsqla.py:205-258` (`open_session`)\nSession dependency: `src/fastsqla.py:260-320` (`new_session`, `Session`)\n\n## Acceptance criteria\n\n- SKILL.md has valid frontmatter\n- Content \u003c 500 lines\n- Includes both correct and incorrect code examples for flush vs commit\n- Covers IntegrityError pattern from test_session_dependency.py","status":"in_progress","priority":1,"issue_type":"task","owner":"hadrien@ectobal.com","estimated_minutes":30,"created_at":"2026-02-26T17:32:42Z","created_by":"Hadrien David","updated_at":"2026-02-26T17:35:44Z","dependencies":[{"issue_id":"fastsqla-0nf.2","depends_on_id":"fastsqla-0nf","type":"parent-child","created_at":"2026-02-26T12:32:42Z","created_by":"Hadrien David","metadata":"{}"}]} |
| 4 | +{"id":"fastsqla-0nf.3","title":"Create fastsqla-pagination skill","description":"Create `skills/fastsqla-pagination/SKILL.md` covering:\n\n- **Response models**: `Page[T]` (data + meta with offset/total_items/total_pages/page_number), `Item[T]` (single item), `Collection[T]` (unpaginated list)\n- **Default Paginate dependency**: adds `offset` (default 0, min 0) and `limit` (default 10, min 1, max 100) query params. Show basic usage with `select(Model)`.\n- **Adding filters**: combine Paginate with additional query parameters\n- **new_pagination() factory**: 4 parameters (`min_page_size`, `max_page_size`, `query_count_dependency`, `result_processor`)\n- **Custom page sizes**: example with `Annotated[PaginateType, Depends(new_pagination(...))]`\n- **Custom count query**: `query_count_dependency` is a FastAPI dependency returning `int`. Default is `SELECT COUNT(*) FROM (subquery)`. Provide example for joins.\n- **Custom result processor**: default is `lambda r: iter(r.unique().scalars())`. Show `lambda result: iter(result.mappings())` for multi-column select.\n- **PaginateType[T]** type alias: `Callable[[Select], Awaitable[Page[T]]]`\n- **SQLModel example**: models serve as both ORM and response models\n\n## Source reference\n\nPagination: `src/fastsqla.py:323-437`\nTest examples: `tests/integration/test_pagination.py`\n\n## Acceptance criteria\n\n- SKILL.md has valid frontmatter\n- Content \u003c 500 lines\n- Includes both default and custom pagination examples\n- Shows the Annotated + Depends pattern for custom pagination","status":"in_progress","priority":2,"issue_type":"task","owner":"hadrien@ectobal.com","estimated_minutes":30,"created_at":"2026-02-26T17:32:56Z","created_by":"Hadrien David","updated_at":"2026-02-26T17:35:44Z","dependencies":[{"issue_id":"fastsqla-0nf.3","depends_on_id":"fastsqla-0nf","type":"parent-child","created_at":"2026-02-26T12:32:55Z","created_by":"Hadrien David","metadata":"{}"}]} |
| 5 | +{"id":"fastsqla-0nf.4","title":"Create fastsqla-models skill","description":"Create `skills/fastsqla-models/SKILL.md` covering:\n\n- **fastsqla.Base**: inherits from `DeclarativeBase` + `DeferredReflection` (`__abstract__ = True`)\n- **Fully declared models**: standard SQLAlchemy ORM with `Mapped` and `mapped_column`\n- **Reflected models**: declare only `__tablename__`, columns auto-reflected from DB during `Base.prepare()` at lifespan startup\n- **How DeferredReflection works**: attributes not available until `Base.prepare()` is called inside a connection during lifespan\n- **Pydantic response models**: separate `BaseModel` with `ConfigDict(from_attributes=True)` when using Base\n- **SQLModel alternative**: `pip install FastSQLA[sqlmodel]`, no need for Base, models are both ORM and Pydantic\n- **SQLModel session swap**: when sqlmodel is installed, FastSQLA silently uses SQLModel's AsyncSession\n- **extend_existing**: `__table_args__ = {'extend_existing': True}` for SQLModel when table already exists\n- **Comparison table**: Base vs SQLModel tradeoffs (reflection, validation, dependencies, relationships)\n\n## Source reference\n\nBase: `src/fastsqla.py:57-85`\nSQLModel import: `src/fastsqla.py:23-27`\n\n## Acceptance criteria\n\n- SKILL.md has valid frontmatter\n- Content \u003c 500 lines\n- Shows both fully declared and reflected model patterns\n- Includes Base vs SQLModel comparison","status":"in_progress","priority":2,"issue_type":"task","owner":"hadrien@ectobal.com","estimated_minutes":25,"created_at":"2026-02-26T17:33:06Z","created_by":"Hadrien David","updated_at":"2026-02-26T17:35:45Z","dependencies":[{"issue_id":"fastsqla-0nf.4","depends_on_id":"fastsqla-0nf","type":"parent-child","created_at":"2026-02-26T12:33:06Z","created_by":"Hadrien David","metadata":"{}"}]} |
| 6 | +{"id":"fastsqla-0nf.5","title":"Create fastsqla-testing skill","description":"Create `skills/fastsqla-testing/SKILL.md` covering:\n\n- **Test dependencies**: pytest, pytest-asyncio, pytest-cov, httpx, asgi-lifespan, aiosqlite, faker\n- **pytest config**: `asyncio_mode = 'auto'`, `asyncio_default_fixture_loop_scope = 'function'`\n- **Fixture chain** (critical ordering): `sqlalchemy_url` → `environ` (patched with clear=True) → `engine` → `setup_tear_down` (CREATE TABLE via raw SQL) → `app` (define models + routes) → `client` (LifespanManager + httpx)\n- **ASGI client pattern**: `LifespanManager(app)` triggers startup/shutdown, `ASGITransport` + `AsyncClient` for HTTP\n- **Critical teardown** (autouse fixture): `Base.metadata.clear()` + `clear_mappers()` after every test to prevent model leakage\n- **Direct data verification**: separate `session` fixture bound to same engine for querying DB outside the app\n- **SQLModel test marks**: `@mark.require_sqlmodel` with autouse `check_sqlmodel` fixture that skips when not installed\n- **Table setup**: raw SQL in fixtures, not ORM (tables must exist before Base.prepare)\n\n## Source reference\n\nRoot conftest: `tests/conftest.py`\nIntegration conftest: `tests/integration/conftest.py`\nSession tests: `tests/integration/test_session_dependency.py`\nPagination tests: `tests/integration/test_pagination.py`\nSQLModel tests: `tests/integration/test_sqlmodel.py`\n\n## Acceptance criteria\n\n- SKILL.md has valid frontmatter\n- Content \u003c 500 lines\n- Documents the full fixture chain with dependency ordering\n- Includes teardown fixture (this is the most common testing pitfall)","status":"in_progress","priority":2,"issue_type":"task","owner":"hadrien@ectobal.com","estimated_minutes":30,"created_at":"2026-02-26T17:33:19Z","created_by":"Hadrien David","updated_at":"2026-02-26T17:35:45Z","dependencies":[{"issue_id":"fastsqla-0nf.5","depends_on_id":"fastsqla-0nf","type":"parent-child","created_at":"2026-02-26T12:33:18Z","created_by":"Hadrien David","metadata":"{}"}]} |
0 commit comments