@softspark/ai-toolkit 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/AGENTS.md +13 -0
  2. package/CHANGELOG.md +23 -0
  3. package/README.md +30 -23
  4. package/app/.claude-plugin/plugin.json +1 -1
  5. package/app/skills/cpp-rules/SKILL.md +275 -0
  6. package/app/skills/csharp-rules/SKILL.md +282 -0
  7. package/app/skills/dart-rules/SKILL.md +299 -0
  8. package/app/skills/golang-rules/SKILL.md +262 -0
  9. package/app/skills/java-rules/SKILL.md +273 -0
  10. package/app/skills/kotlin-rules/SKILL.md +271 -0
  11. package/app/skills/medplum-rules/SKILL.md +271 -0
  12. package/app/skills/php-rules/SKILL.md +292 -0
  13. package/app/skills/python-rules/SKILL.md +257 -0
  14. package/app/skills/ruby-rules/SKILL.md +286 -0
  15. package/app/skills/rust-rules/SKILL.md +276 -0
  16. package/app/skills/swift-rules/SKILL.md +293 -0
  17. package/app/skills/typescript-rules/SKILL.md +249 -0
  18. package/benchmarks/ecosystem-doctor-snapshot.json +14 -14
  19. package/kb/history/completed/deep-coverage-v3-20260423.md +3 -3
  20. package/kb/history/completed/ecosystem-deep-sweep-20260423.md +1 -1
  21. package/kb/procedures/release-preparation-sop.md +4 -4
  22. package/kb/procedures/release-verification-sop.md +11 -12
  23. package/kb/reference/architecture-overview.md +1 -1
  24. package/kb/reference/global-install-model.md +29 -6
  25. package/kb/reference/language-rules.md +54 -18
  26. package/kb/reference/mcp-editor-compatibility.md +4 -3
  27. package/kb/reference/mcp-templates.md +3 -2
  28. package/kb/reference/supported-tools-registry.md +10 -8
  29. package/llms-full.txt +133 -58
  30. package/manifest.json +3 -3
  31. package/package.json +10 -3
  32. package/scripts/codex_skill_adapter.py +19 -3
  33. package/scripts/ecosystem_tools.json +7 -7
  34. package/scripts/generate_cline_rules.py +17 -8
  35. package/scripts/generate_codex_skills.py +33 -96
  36. package/scripts/generate_language_rules_skills.py +232 -0
  37. package/scripts/generate_roo_rules.py +11 -3
  38. package/scripts/install.py +6 -1
  39. package/scripts/install_steps/ai_tools.py +154 -51
  40. package/scripts/install_steps/install_state.py +14 -2
  41. package/scripts/mcp_editors.py +7 -0
@@ -0,0 +1,292 @@
1
+ ---
2
+ name: php-rules
3
+ description: "PHP coding rules from ai-toolkit: coding-style, frameworks, patterns, security, testing. Triggers: .php, composer.json, Laravel, Symfony, PHPUnit, PSR-12, Composer. Load when writing, reviewing, or editing PHP code."
4
+ effort: medium
5
+ user-invocable: false
6
+ allowed-tools: Read
7
+ ---
8
+
9
+ # PHP Rules
10
+
11
+ These rules come from `app/rules/php/` in ai-toolkit. They cover
12
+ the project's standards for coding style, frameworks, patterns,
13
+ security, and testing in PHP. Apply them when writing or
14
+ reviewing PHP code.
15
+
16
+ # PHP Coding Style
17
+
18
+ ## Standards
19
+ - Follow PSR-12 extended coding style.
20
+ - Use `declare(strict_types=1)` at the top of every file.
21
+ - Use PHP 8.1+ features: enums, fibers, readonly properties, intersection types.
22
+ - Use PHP CS Fixer or Pint for automated formatting.
23
+
24
+ ## Naming
25
+ - PascalCase: classes, interfaces, traits, enums.
26
+ - camelCase: methods, functions, variables.
27
+ - UPPER_SNAKE: class constants (`public const MAX_RETRIES = 3`).
28
+ - snake_case: not used for methods. PSR convention is camelCase.
29
+ - Suffix interfaces with `Interface` or prefix with contract name (project convention).
30
+
31
+ ## Type System
32
+ - Use typed properties: `private readonly string $name;`.
33
+ - Use union types: `string|int`. Use intersection types: `Countable&Iterator`.
34
+ - Use `enum` (PHP 8.1) for fixed sets of values. Use backed enums for persistence.
35
+ - Use `readonly` classes (PHP 8.2) for immutable DTOs.
36
+ - Use constructor promotion: `public function __construct(private string $name)`.
37
+ - Use `never` return type for functions that throw or exit.
38
+
39
+ ## Functions
40
+ - Use typed parameters and return types on all functions/methods.
41
+ - Use named arguments for readability: `new User(name: 'Ada', age: 36)`.
42
+ - Use null-safe operator: `$user?->address?->city`.
43
+ - Use match expression over switch for value mapping.
44
+ - Use first-class callable syntax: `array_map($this->transform(...), $items)`.
45
+
46
+ ## Imports and Namespaces
47
+ - Use PSR-4 autoloading via Composer.
48
+ - Group `use` statements: classes, functions, constants.
49
+ - Never use `require`/`include` for class loading. Use Composer autoloader.
50
+ - Use one class per file. File name matches class name.
51
+
52
+ ## Error Handling
53
+ - Use exceptions for error conditions. Never return error codes.
54
+ - Create domain exception hierarchies extending `RuntimeException` or `LogicException`.
55
+ - Use `match` with `throw` for exhaustive error mapping.
56
+ - Log exceptions with context using PSR-3 logger.
57
+
58
+ ## Configuration
59
+ - Use PHPStan at level 8+ for static analysis.
60
+ - Use Rector for automated code upgrades and refactoring.
61
+ - Use `.php-cs-fixer.dist.php` for formatting rules.
62
+ - Run `composer analyse` (PHPStan) and `composer format` (Pint) in CI.
63
+
64
+ # PHP Frameworks
65
+
66
+ ## Laravel
67
+ - Use route model binding: `Route::get('/users/{user}', ...)`.
68
+ - Use Form Requests for validation: `class StoreUserRequest extends FormRequest`.
69
+ - Use Eloquent scopes for reusable query constraints: `scopeActive()`.
70
+ - Use API Resources for response transformation: `UserResource::collection($users)`.
71
+ - Use `config()` helper for configuration. Never access `env()` outside config files.
72
+ - Use middleware groups for auth, throttling, and CORS.
73
+
74
+ ## Eloquent ORM
75
+ - Use relationships: `hasMany`, `belongsTo`, `belongsToMany`, `morphMany`.
76
+ - Use eager loading: `User::with('posts.comments')->get()` to prevent N+1.
77
+ - Use `$fillable` or `$guarded` on models. Prefer `$fillable` (explicit whitelist).
78
+ - Use model events or observers for lifecycle hooks.
79
+ - Use `upsert()` for bulk insert-or-update operations.
80
+ - Use `cursor()` for memory-efficient iteration over large result sets.
81
+
82
+ ## Symfony
83
+ - Use attributes for route definitions: `#[Route('/api/users', methods: ['GET'])]`.
84
+ - Use autowiring for dependency injection. Register services in `services.yaml`.
85
+ - Use Symfony Forms for complex validation and data mapping.
86
+ - Use Messenger component for async message handling (commands, events).
87
+ - Use Doctrine ORM with repository pattern and query builders.
88
+
89
+ ## Doctrine ORM
90
+ - Use entity classes with annotations or attributes for mapping.
91
+ - Use repositories for data access: `$em->getRepository(User::class)`.
92
+ - Use DQL for type-safe queries. Use QueryBuilder for dynamic queries.
93
+ - Use migrations: `bin/console doctrine:migrations:diff` and `migrate`.
94
+ - Use lifecycle callbacks (`@PrePersist`, `@PostUpdate`) for entity events.
95
+
96
+ ## Symfony Serializer
97
+ - Default behavior uses property names as-is. Combined with PSR-12 `camelCase` property names, JSON output is `camelCase` with zero configuration.
98
+ - Avoid adding `api_platform.name_converter: CamelCaseToSnakeCaseNameConverter` globally. Known side-effect ([api-platform/core #6101](https://github.com/api-platform/core/issues/6101)): overrides the project-wide `MetadataAwareNameConverter`, affecting Messenger serializers, custom normalizers, and CLI JSON output — not just the HTTP API.
99
+ - Use `#[SerializedName]` only when justified: legacy field alias during rename, external contract mapping, ObjectNormalizer cross-version stabilization. Community practice ([Symfony docs](https://symfony.com/doc/current/serializer.html), Sylius, SymfonyCasts): prefer clean property/getter naming over aliases. When using, document the reason next to the attribute.
100
+ - Symfony 7.3.5+ `ObjectNormalizer` produces `isActive` natively for a `isActive(): bool` getter ([symfony/symfony #62353](https://github.com/symfony/symfony/issues/62353)). Older `#[SerializedName('isActive')]` aliases added for pre-7.3.5 `ObjectNormalizer` (which produced `active`) are redundant after upgrade — remove them.
101
+ - Avoid duplicate getters like `isActive()` + `getIsActive()` on the same property — `ObjectNormalizer` treats them as two fields and serializes ambiguously. Keep one (`isXxx()` for booleans, `getXxx()` otherwise).
102
+
103
+ ## API Platform
104
+ - Use API Platform for rapid REST/GraphQL API generation from entities.
105
+ - Use `#[ApiResource]` attribute for automatic CRUD endpoint generation.
106
+ - Use custom state providers and processors for business logic.
107
+ - Use serialization groups for controlling response shape.
108
+ - Use filters for query parameter support: pagination, search, ordering.
109
+ - Property names on `ApiResource` DTOs drive JSON keys directly (see Symfony Serializer above). Write them in `camelCase` — that is both the Symfony default and the dominant JSON API convention.
110
+ - Use `operation_name` in `extraProperties` for dispatch metadata (e.g., `extraProperties: ['operation_name' => 'club_activate']`). The key `operation_name` and its `snake_case` values are framework metadata, not JSON wire keys — keeping them `snake_case` is expected.
111
+
112
+ ## Livewire (Laravel)
113
+ - Use Livewire components for reactive UI without JavaScript.
114
+ - Use `wire:model` for two-way data binding on form inputs.
115
+ - Use `$rules` property for inline validation on component properties.
116
+ - Use component actions for server-side event handling.
117
+ - Use `wire:loading` for loading state indicators.
118
+
119
+ ## Queues and Workers
120
+ - Use Laravel Horizon for Redis queue monitoring and management.
121
+ - Use Symfony Messenger with transports (Redis, AMQP, Doctrine).
122
+ - Use dead letter queues for failed job inspection and replay.
123
+ - Use rate limiting on queue workers to prevent downstream overload.
124
+
125
+ # PHP Patterns
126
+
127
+ ## Error Handling
128
+ - Use custom exception hierarchies: `class DomainException extends RuntimeException`.
129
+ - Add context to exceptions: `throw new UserNotFoundException(userId: $id)`.
130
+ - Use `match` with `default => throw` for exhaustive error mapping.
131
+ - Use `set_exception_handler()` for global uncaught exception handling.
132
+ - Log exceptions with PSR-3 logger and structured context.
133
+
134
+ ## Enums and Value Objects
135
+ - Use backed enums for database-persisted values: `enum Status: string`.
136
+ - Use `from()` for strict conversion, `tryFrom()` for nullable safe conversion.
137
+ - Implement methods on enums for behavior: `public function label(): string`.
138
+ - Use readonly classes for value objects: `readonly class Money { ... }`.
139
+ - Use constructor promotion for concise value object definitions.
140
+
141
+ ## Repository Pattern
142
+ - Abstract data access behind repository interfaces.
143
+ - Repositories return domain entities, not Eloquent models or arrays.
144
+ - Use constructor injection for repository dependencies.
145
+ - Use specifications or criteria objects for complex query building.
146
+ - Keep repository methods focused: one query per method.
147
+
148
+ ## Service Layer
149
+ - Use service classes for business logic. Keep controllers thin.
150
+ - Use action classes (single-method services) for discrete operations.
151
+ - Use DTOs for data transfer between layers. Never pass request objects to services.
152
+ - Use command/query separation: commands mutate, queries read.
153
+ - Inject dependencies via constructor. Never use `app()` helper in services.
154
+
155
+ ## Collections and Iterators
156
+ - Use Laravel Collections or standalone `illuminate/collections` for data manipulation.
157
+ - Chain `map()`, `filter()`, `reduce()` for declarative data transformation.
158
+ - Use `LazyCollection` for memory-efficient processing of large datasets.
159
+ - Use generators (`yield`) for lazy iteration over large result sets.
160
+ - Prefer `collect()` pipeline over nested loops.
161
+
162
+ ## Async Patterns
163
+ - Use Laravel Queues for background job processing.
164
+ - Use `dispatch()` for fire-and-forget. Use `Bus::chain()` for sequential jobs.
165
+ - Use `ShouldQueue` interface on jobs, listeners, and mailables.
166
+ - Set `$tries`, `$timeout`, `$backoff` on job classes.
167
+ - Use `batch()` for parallel job execution with completion callback.
168
+
169
+ ## Event-Driven
170
+ - Use events and listeners for decoupled side effects.
171
+ - Use domain events for cross-boundary communication.
172
+ - Use `ShouldQueue` on listeners for async event handling.
173
+ - Use event subscribers for grouping related listeners.
174
+ - Keep event payloads minimal: IDs and timestamps, not full objects.
175
+
176
+ ## Anti-Patterns
177
+ - Fat controllers: move logic to services/actions.
178
+ - God models: split into focused models with traits or separate classes.
179
+ - Using `DB::raw()` without parameterization: SQL injection risk.
180
+ - Static method calls for testable dependencies: use DI instead.
181
+ - Returning mixed types: use typed returns or Result objects.
182
+
183
+ # PHP Security
184
+
185
+ ## SQL Injection
186
+ - Use PDO prepared statements with bound parameters for all queries.
187
+ - Use Eloquent/Doctrine ORM for type-safe query building.
188
+ - Never concatenate user input into SQL strings. Never use `DB::raw($input)`.
189
+ - Use `whereIn()` with arrays, not string interpolation for IN clauses.
190
+ - Audit raw queries: `DB::select(DB::raw(...))` must use `?` placeholders.
191
+
192
+ ## XSS Prevention
193
+ - Blade templates auto-escape with `{{ }}`. Never use `{!! !!}` with user data.
194
+ - Use `htmlspecialchars()` with `ENT_QUOTES` when outputting outside Blade.
195
+ - Set `Content-Security-Policy` headers to restrict inline scripts.
196
+ - Sanitize rich-text input with HTMLPurifier before storage.
197
+ - Use `strip_tags()` only as a secondary measure, not primary defense.
198
+
199
+ ## CSRF Protection
200
+ - Use `@csrf` directive in all Blade forms.
201
+ - Use `VerifyCsrfToken` middleware (enabled by default in Laravel).
202
+ - Use `X-CSRF-TOKEN` header for AJAX requests from SPA frontends.
203
+ - Exclude only webhook endpoints from CSRF verification (with careful validation).
204
+
205
+ ## Authentication
206
+ - Use `password_hash()` with `PASSWORD_ARGON2ID` or `PASSWORD_BCRYPT`.
207
+ - Use Laravel Sanctum for SPA/mobile API authentication.
208
+ - Use Laravel Passport for full OAuth2 server implementation.
209
+ - Implement rate limiting on login endpoints: `ThrottleRequests` middleware.
210
+ - Use multi-factor authentication for admin accounts.
211
+
212
+ ## Authorization
213
+ - Use Laravel Gates and Policies for authorization logic.
214
+ - Use `$this->authorize('update', $post)` in controllers.
215
+ - Check resource ownership in policies, not just role membership.
216
+ - Default deny: use `Gate::before()` for super-admin bypass, nothing else.
217
+ - Use middleware `can:permission` for route-level authorization.
218
+
219
+ ## File Upload
220
+ - Validate file MIME type server-side. Do not trust `Content-Type` header.
221
+ - Store uploads outside the web root. Use `storage/` with `Storage::disk()`.
222
+ - Generate random filenames. Never use original user-provided filenames.
223
+ - Set maximum file size limits in validation and PHP `upload_max_filesize`.
224
+ - Scan uploaded files for malware in production environments.
225
+
226
+ ## Mass Assignment
227
+ - Use `$fillable` on Eloquent models. Never use `$guarded = []`.
228
+ - Use Form Requests to whitelist fields before model assignment.
229
+ - Use DTOs for data transfer. Never pass `$request->all()` to `create()`.
230
+ - Audit `forceFill()` and `forceCreate()` usage (bypasses guarding).
231
+
232
+ ## Secrets and Configuration
233
+ - Use `.env` files for local secrets. Use Vault or SSM for production.
234
+ - Never commit `.env` to version control. Commit `.env.example` as template.
235
+ - Use `config()` helper, never `env()` outside of config files (caching issue).
236
+ - Never log request content containing passwords or tokens.
237
+ - Use `APP_DEBUG=false` in production. Debug mode leaks sensitive data.
238
+
239
+ # PHP Testing
240
+
241
+ ## Framework
242
+ - Use PHPUnit 10+ as the primary test framework.
243
+ - Use Pest PHP for expressive, minimal-boilerplate testing (built on PHPUnit).
244
+ - Use Mockery for flexible mocking. Use PHPUnit built-in mocks for simple cases.
245
+ - Use Testcontainers (via Docker) for integration tests with databases.
246
+
247
+ ## File Naming
248
+ - Test files: `FooTest.php` in `tests/` mirroring `src/` namespace structure.
249
+ - Unit tests: `tests/Unit/`. Integration tests: `tests/Integration/` or `tests/Feature/`.
250
+ - PHPUnit config: `phpunit.xml.dist` at project root.
251
+ - Use `@group` annotations for test categorization.
252
+
253
+ ## Structure (PHPUnit)
254
+ - Use `#[Test]` attribute (PHP 8) or `test` prefix for test methods.
255
+ - Use `setUp()` / `tearDown()` for per-test initialization and cleanup.
256
+ - Use `#[DataProvider('dataMethodName')]` for parameterized tests.
257
+ - Name tests: `testMethodName_Scenario_ExpectedResult` or descriptive snake_case.
258
+
259
+ ## Structure (Pest)
260
+ - Use `test('description', function () { ... })` for test cases.
261
+ - Use `it('should do something', ...)` for BDD-style descriptions.
262
+ - Use `beforeEach()` / `afterEach()` for setup and teardown.
263
+ - Use `dataset()` for shared test data across multiple tests.
264
+ - Use `->with([...])` for inline parameterized tests.
265
+
266
+ ## Assertions
267
+ - Use `$this->assertSame()` for strict equality (type + value).
268
+ - Use `$this->assertInstanceOf(Foo::class, $result)` for type checks.
269
+ - Use `$this->expectException(FooException::class)` before the throwing call.
270
+ - Use `$this->assertCount()`, `$this->assertContains()` for collections.
271
+ - Pest: use `expect($value)->toBe()`, `->toBeInstanceOf()`, `->toThrow()`.
272
+
273
+ ## Mocking (Mockery)
274
+ - Create mocks: `$mock = Mockery::mock(UserRepository::class)`.
275
+ - Stub: `$mock->shouldReceive('find')->with(1)->andReturn($user)`.
276
+ - Verify: `$mock->shouldHaveReceived('save')->once()`.
277
+ - Use `Mockery::close()` in `tearDown()` or `afterEach()`.
278
+ - Use `spy()` to verify interactions without stubbing.
279
+
280
+ ## Laravel Testing
281
+ - Use `RefreshDatabase` trait for database test isolation.
282
+ - Use `$this->actingAs($user)` for authenticated request testing.
283
+ - Use `$this->getJson('/api/users')->assertOk()->assertJsonCount(3)`.
284
+ - Use factories: `User::factory()->create()` for test data.
285
+ - Use `Bus::fake()`, `Event::fake()`, `Mail::fake()` for side-effect assertion.
286
+
287
+ ## Best Practices
288
+ - Test behavior, not implementation. Do not test private methods.
289
+ - Use in-memory SQLite for fast database tests when schema is compatible.
290
+ - Run `php artisan test --parallel` for faster Laravel test execution.
291
+ - Use `--coverage-html` for visual coverage reports.
292
+ - Keep tests fast: mock external HTTP calls with `Http::fake()`.
@@ -0,0 +1,257 @@
1
+ ---
2
+ name: python-rules
3
+ description: "Python coding rules from ai-toolkit: coding-style, frameworks, patterns, security, testing. Triggers: .py, .pyi, pyproject.toml, requirements.txt, Pipfile, FastAPI, Django, Flask, pytest, SQLAlchemy, ruff, mypy. Load when writing, reviewing, or editing Python code."
4
+ effort: medium
5
+ user-invocable: false
6
+ allowed-tools: Read
7
+ ---
8
+
9
+ # Python Rules
10
+
11
+ These rules come from `app/rules/python/` in ai-toolkit. They cover
12
+ the project's standards for coding style, frameworks, patterns,
13
+ security, and testing in Python. Apply them when writing or
14
+ reviewing Python code.
15
+
16
+ # Python Coding Style
17
+
18
+ ## Type Hints
19
+ - Type all public function signatures (parameters + return).
20
+ - Use `str | None` (PEP 604) over `Optional[str]` on Python 3.10+.
21
+ - Use `from __future__ import annotations` for forward references.
22
+ - Use `TypeAlias` or `type` (3.12+) for complex type aliases.
23
+ - Use `Protocol` for structural subtyping instead of ABCs where possible.
24
+
25
+ ## Naming
26
+ - snake_case: variables, functions, methods, modules.
27
+ - PascalCase: classes, type aliases, Protocols.
28
+ - UPPER_SNAKE: module-level constants.
29
+ - Prefix private: `_internal_helper`. No double underscore unless name mangling needed.
30
+ - Prefix unused: `_` for intentionally unused variables.
31
+
32
+ ## Functions
33
+ - Prefer keyword arguments for functions with >2 params.
34
+ - Use `*` to force keyword-only: `def fetch(*, limit: int, offset: int)`.
35
+ - Return early to reduce nesting. Avoid deep if/else chains.
36
+ - Use `@staticmethod` only for pure utility. Prefer module-level functions.
37
+
38
+ ## Imports
39
+ - Group: stdlib, third-party, local. Separated by blank lines.
40
+ - Use absolute imports. Relative imports only within packages.
41
+ - Never `from module import *`. Be explicit.
42
+ - Use `if TYPE_CHECKING:` for import-only-for-types to avoid circular imports.
43
+
44
+ ## Data Structures
45
+ - Use `dataclasses` for plain data containers.
46
+ - Use Pydantic `BaseModel` for validated data / API schemas.
47
+ - Use `NamedTuple` for lightweight immutable records.
48
+ - Use `Enum` for fixed sets of values. Prefer `StrEnum` on 3.11+.
49
+ - Prefer `dict` / `list` literals over `dict()` / `list()` constructors.
50
+
51
+ ## Modern Python
52
+ - Use f-strings for formatting. Never `.format()` or `%` for new code.
53
+ - Use `pathlib.Path` over `os.path` for file operations.
54
+ - Use `contextlib.suppress(KeyError)` over bare try/except for simple cases.
55
+ - Use walrus operator `:=` when it genuinely improves readability.
56
+ - Use `match/case` (3.10+) for complex conditionals on structured data.
57
+
58
+ ## Tooling
59
+ - Formatter: `ruff format` or `black`. No manual formatting.
60
+ - Linter: `ruff check`. Fix all errors before committing.
61
+ - Type checker: `mypy --strict` or `pyright` in CI.
62
+
63
+ # Python Frameworks
64
+
65
+ ## FastAPI
66
+ - Use Pydantic v2 models for request/response schemas.
67
+ - Use dependency injection (`Depends()`) for shared logic (auth, DB sessions).
68
+ - Use `APIRouter` to organize routes by domain.
69
+ - Return Pydantic models directly -- FastAPI handles serialization.
70
+ - Use `BackgroundTasks` for non-critical async work (emails, logging).
71
+ - Use `lifespan` context manager for startup/shutdown (not `on_event`).
72
+
73
+ ## Django
74
+ - Use class-based views for CRUD, function-based for custom logic.
75
+ - Use `select_related` and `prefetch_related` to prevent N+1 queries.
76
+ - Use Django REST Framework serializers for API validation.
77
+ - Use Django ORM migrations. Never modify database schema manually.
78
+ - Use `transaction.atomic()` for multi-model operations.
79
+ - Use signals sparingly: prefer explicit service calls.
80
+
81
+ ## SQLAlchemy 2.0
82
+ - Use the 2.0-style with `select()` statements, not legacy `query()`.
83
+ - Use `Mapped[type]` annotations for typed column definitions.
84
+ - Use `sessionmaker` with `expire_on_commit=False` for API responses.
85
+ - Use `async_sessionmaker` with `asyncpg` for async applications.
86
+ - Always use `session.begin()` context manager for transaction scope.
87
+
88
+ ## Pydantic v2
89
+ - Use `model_validator(mode="before")` for cross-field validation.
90
+ - Use `field_validator` for single-field validation.
91
+ - Use `model_config = ConfigDict(strict=True)` for strict type coercion.
92
+ - Use `Annotated[str, Field(min_length=1)]` for reusable constrained types.
93
+ - Use `model_dump(exclude_unset=True)` for PATCH operations.
94
+
95
+ ## CLI (click / typer)
96
+ - Use Typer for new CLI tools (type-hint-driven, less boilerplate).
97
+ - Use `click.group()` for multi-command CLIs.
98
+ - Use `rich` for formatted terminal output (tables, progress bars).
99
+
100
+ ## Task Queues
101
+ - Use Celery with Redis/RabbitMQ for background job processing.
102
+ - Use `arq` for lightweight async job queues.
103
+ - Always set task timeouts. Never let tasks run indefinitely.
104
+ - Use idempotent tasks: safe to retry on failure.
105
+
106
+ ## Package Management
107
+ - Use `uv` for fast dependency resolution and virtual environments.
108
+ - Use `pyproject.toml` for all project configuration (no setup.py/setup.cfg).
109
+ - Pin dependencies with lockfile (`uv.lock`, `poetry.lock`).
110
+
111
+ # Python Patterns
112
+
113
+ ## Error Handling
114
+ - Catch specific exceptions, never bare `except:` or `except Exception`.
115
+ - Use custom exception hierarchies: `class AppError(Exception)` as base.
116
+ - Add context when re-raising: `raise AppError("context") from original`.
117
+ - Use `contextlib.suppress()` for expected, ignorable exceptions.
118
+ - Log exceptions with `logger.exception("msg")` to include traceback.
119
+
120
+ ## Context Managers
121
+ - Use `with` for any resource that needs cleanup (files, connections, locks).
122
+ - Create custom context managers with `@contextmanager` decorator.
123
+ - Use `contextlib.AsyncExitStack` for dynamic async resource management.
124
+ - Use `atexit.register()` for process-level cleanup only.
125
+
126
+ ## Async
127
+ - Use `asyncio` for I/O-bound concurrency. Use `multiprocessing` for CPU-bound.
128
+ - Use `asyncio.gather()` for concurrent independent operations.
129
+ - Use `asyncio.TaskGroup` (3.11+) for structured concurrency.
130
+ - Never mix `asyncio.run()` inside already-running event loops.
131
+ - Use `async for` and `async with` for streaming and resource patterns.
132
+
133
+ ## Dataclass Patterns
134
+ - Use `frozen=True` for immutable value objects.
135
+ - Use `field(default_factory=list)` for mutable defaults, never `field(default=[])`.
136
+ - Use `__post_init__` for validation, not complex logic.
137
+ - Use `slots=True` (3.10+) for memory efficiency in high-volume objects.
138
+
139
+ ## Functional Patterns
140
+ - Use `functools.lru_cache` for pure function memoization.
141
+ - Use `itertools` for efficient iteration (chain, islice, groupby).
142
+ - Use generators (`yield`) for lazy sequences and large data processing.
143
+ - Prefer comprehensions over `map/filter` with lambdas.
144
+ - Use `functools.partial` to create specialized versions of functions.
145
+
146
+ ## Dependency Injection
147
+ - Use constructor injection: pass dependencies as `__init__` params.
148
+ - Use `Protocol` classes to define dependency interfaces.
149
+ - Use factory functions to wire dependencies at application startup.
150
+ - Avoid global state and singletons. Use module-level instances if needed.
151
+
152
+ ## Anti-Patterns
153
+ - Mutable default arguments: use `None` and create inside function.
154
+ - Catching `Exception` broadly: masks bugs and interrupts.
155
+ - Using `type()` for type checking: use `isinstance()`.
156
+ - Nested try/except: flatten with early returns or separate functions.
157
+ - Using `global` keyword: pass state through parameters or classes.
158
+
159
+ # Python Security
160
+
161
+ ## Input Validation
162
+ - Validate all input with Pydantic models at API boundaries.
163
+ - Use `constr`, `conint`, `conlist` for constrained types.
164
+ - Never use `eval()`, `exec()`, or `compile()` with user input.
165
+ - Never use `pickle.loads()` on untrusted data (arbitrary code execution).
166
+
167
+ ## SQL Injection
168
+ - Use ORM query builders (SQLAlchemy, Django ORM) for all queries.
169
+ - For raw SQL, always use parameterized queries: `cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))`.
170
+ - Never use f-strings or `.format()` to build SQL queries.
171
+ - Use `text()` with `:param` syntax in SQLAlchemy raw queries.
172
+
173
+ ## SSTI (Server-Side Template Injection)
174
+ - Use Jinja2 with autoescaping enabled: `Environment(autoescape=True)`.
175
+ - Never render user input as a template string.
176
+ - Use `markupsafe.Markup` only for trusted HTML content.
177
+
178
+ ## Command Injection
179
+ - Never use `os.system()` or `subprocess.run(shell=True)` with user input.
180
+ - Use `subprocess.run()` with list arguments: `subprocess.run(["ls", "-la", path])`.
181
+ - Use `shlex.quote()` if shell=True is absolutely necessary.
182
+
183
+ ## Path Traversal
184
+ - Use `pathlib.Path.resolve()` and verify the result is within allowed directory.
185
+ - Never concatenate user input into file paths without validation.
186
+ - Use `os.path.commonpath()` to verify path containment.
187
+
188
+ ## Secrets
189
+ - Use `secrets` module for tokens: `secrets.token_urlsafe(32)`.
190
+ - Use `hashlib.scrypt` or `bcrypt` for password hashing.
191
+ - Use `hmac.compare_digest()` for constant-time secret comparison.
192
+ - Load secrets from environment: `os.environ["SECRET_KEY"]`, never hardcode.
193
+
194
+ ## Dependencies
195
+ - Run `pip-audit` or `safety check` in CI.
196
+ - Use `uv` or `pip-compile` for reproducible dependency resolution.
197
+ - Avoid installing packages with native extensions from untrusted sources.
198
+ - Pin all dependency versions. Review dependency updates carefully.
199
+
200
+ ## Deserialization
201
+ - Never deserialize untrusted data with `pickle`, `yaml.load()`, or `marshal`.
202
+ - Use `yaml.safe_load()` instead of `yaml.load()`.
203
+ - Use `json.loads()` for untrusted data (safe by default).
204
+ - Validate deserialized data with Pydantic before use.
205
+
206
+ ## Django-Specific
207
+ - Set `DEBUG = False` in production. Never expose debug pages.
208
+ - Use `django.utils.html.escape()` for manual HTML escaping.
209
+ - Use `CSRF_COOKIE_HTTPONLY = True` and `SESSION_COOKIE_SECURE = True`.
210
+ - Keep `SECRET_KEY` unique per environment and out of version control.
211
+
212
+ # Python Testing
213
+
214
+ ## Framework
215
+ - Use pytest as the default test framework. No unittest for new code.
216
+ - Use pytest-asyncio for async test functions.
217
+ - Use pytest-cov for coverage measurement.
218
+ - Use hypothesis for property-based testing on parsing/validation logic.
219
+
220
+ ## File Naming
221
+ - Test files: `test_*.py` in `tests/` directory.
222
+ - Conftest: `conftest.py` at each test directory level for shared fixtures.
223
+ - Mirror source: `src/auth/service.py` -> `tests/auth/test_service.py`.
224
+
225
+ ## Fixtures
226
+ - Use `@pytest.fixture` for setup. Prefer fixtures over setup/teardown methods.
227
+ - Scope fixtures appropriately: `function` (default), `module`, `session`.
228
+ - Use `yield` fixtures for setup + teardown: `yield resource; cleanup()`.
229
+ - Use `tmp_path` fixture for temporary files, not manual `tempfile`.
230
+ - Use `monkeypatch` for patching env vars, attributes, and dict items.
231
+
232
+ ## Parametrize
233
+ - Use `@pytest.mark.parametrize` for testing multiple inputs/outputs.
234
+ - Use `pytest.param(..., id="descriptive_name")` for readable test IDs.
235
+ - Combine parametrize decorators for cross-product testing.
236
+
237
+ ## Mocking
238
+ - Use `unittest.mock.patch` or `monkeypatch` for dependency replacement.
239
+ - Mock at the import location: `patch("myapp.service.http_client")`.
240
+ - Use `MagicMock(spec=ClassName)` to get attribute checking.
241
+ - Use `AsyncMock` for async functions.
242
+ - Prefer dependency injection over patching when possible.
243
+
244
+ ## Markers
245
+ - Use `@pytest.mark.slow` for tests >1s. Exclude from default runs.
246
+ - Use `@pytest.mark.integration` for tests requiring external services.
247
+ - Register all custom markers in `pyproject.toml` to avoid warnings.
248
+
249
+ ## Async Testing
250
+ - Use `@pytest.mark.anyio` or `@pytest.mark.asyncio` for async tests.
251
+ - Use `httpx.AsyncClient` for testing FastAPI/Starlette apps.
252
+ - Use `aiosqlite` or test containers for async database tests.
253
+
254
+ ## Configuration
255
+ - Configure pytest in `pyproject.toml` under `[tool.pytest.ini_options]`.
256
+ - Set `addopts = "--strict-markers -ra"` for strict mode.
257
+ - Set `testpaths = ["tests"]` to avoid scanning the entire repo.