@martinffx/atelier 2.0.0 → 3.0.1
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.
- package/CHANGELOG.md +21 -0
- package/README.md +94 -253
- package/package.json +1 -1
- package/skills/{spec-orchestrator → atelier-orchestrator}/SKILL.md +3 -3
- package/skills/atelier-setup/SKILL.md +80 -0
- package/skills/code-review/references/reviewers.md +3 -3
- package/skills/code-review/references/rq.md +6 -6
- package/skills/spec-brainstorm/SKILL.md +5 -5
- package/skills/spec-implement/SKILL.md +2 -3
- package/skills/spec-plan/SKILL.md +21 -29
- package/skills/spec-plan/references/plan_template.md +77 -0
- package/skills/python-architecture/SKILL.md +0 -148
- package/skills/python-architecture/references/data-modeling.md +0 -558
- package/skills/python-architecture/references/ddd.md +0 -569
- package/skills/python-architecture/references/functional-core.md +0 -337
- package/skills/python-build-tools/SKILL.md +0 -153
- package/skills/python-build-tools/references/basedpyright.md +0 -321
- package/skills/python-build-tools/references/ruff.md +0 -225
- package/skills/python-build-tools/references/uv.md +0 -257
- package/skills/python-fastapi/SKILL.md +0 -184
- package/skills/python-fastapi/references/api-design.md +0 -563
- package/skills/python-fastapi/references/dependencies.md +0 -479
- package/skills/python-fastapi/references/middleware.md +0 -475
- package/skills/python-fastapi/references/validation.md +0 -497
- package/skills/python-modern-python/SKILL.md +0 -201
- package/skills/python-modern-python/references/async.md +0 -76
- package/skills/python-modern-python/references/pattern-matching.md +0 -89
- package/skills/python-modern-python/references/typing.md +0 -96
- package/skills/python-monorepo/SKILL.md +0 -146
- package/skills/python-monorepo/references/docker.md +0 -515
- package/skills/python-monorepo/references/namespace-packages.md +0 -426
- package/skills/python-monorepo/references/workspace-config.md +0 -341
- package/skills/python-sqlalchemy/SKILL.md +0 -119
- package/skills/python-sqlalchemy/references/async.md +0 -51
- package/skills/python-sqlalchemy/references/models.md +0 -67
- package/skills/python-sqlalchemy/references/queries.md +0 -57
- package/skills/python-temporal/SKILL.md +0 -128
- package/skills/python-temporal/references/patterns.md +0 -87
- package/skills/python-temporal/references/testing.md +0 -54
- package/skills/python-testing/SKILL.md +0 -161
- package/skills/python-testing/references/boundaries.md +0 -449
- package/skills/python-testing/references/mocking.md +0 -449
- package/skills/python-testing/references/pytest.md +0 -524
- package/skills/typescript-api-design/SKILL.md +0 -396
- package/skills/typescript-api-design/references/error-responses.md +0 -469
- package/skills/typescript-build-tools/SKILL.md +0 -447
- package/skills/typescript-build-tools/references/biome.md +0 -436
- package/skills/typescript-build-tools/references/bun.md +0 -432
- package/skills/typescript-build-tools/references/turborepo.md +0 -426
- package/skills/typescript-build-tools/references/vitest.md +0 -518
- package/skills/typescript-drizzle-orm/SKILL.md +0 -398
- package/skills/typescript-drizzle-orm/references/cloudflare.md +0 -392
- package/skills/typescript-drizzle-orm/references/entity-pattern.md +0 -412
- package/skills/typescript-drizzle-orm/references/postgresql.md +0 -191
- package/skills/typescript-drizzle-orm/references/repository-pattern.md +0 -479
- package/skills/typescript-drizzle-orm/references/sqlite.md +0 -291
- package/skills/typescript-dynamodb-toolbox/SKILL.md +0 -370
- package/skills/typescript-dynamodb-toolbox/references/entity-layer.md +0 -574
- package/skills/typescript-dynamodb-toolbox/references/error-handling.md +0 -495
- package/skills/typescript-dynamodb-toolbox/references/modeling.md +0 -332
- package/skills/typescript-dynamodb-toolbox/references/repository-layer.md +0 -631
- package/skills/typescript-dynamodb-toolbox/references/testing.md +0 -718
- package/skills/typescript-dynamodb-toolbox/references/transactions.md +0 -423
- package/skills/typescript-effect-ts/SKILL.md +0 -341
- package/skills/typescript-effect-ts/references/core.md +0 -412
- package/skills/typescript-effect-ts/references/error-handling.md +0 -468
- package/skills/typescript-effect-ts/references/resources.md +0 -476
- package/skills/typescript-effect-ts/references/schema.md +0 -536
- package/skills/typescript-effect-ts/references/services.md +0 -461
- package/skills/typescript-fastify/SKILL.md +0 -405
- package/skills/typescript-fastify/references/plugins.md +0 -329
- package/skills/typescript-fastify/references/typeid.md +0 -315
- package/skills/typescript-functional-patterns/SKILL.md +0 -402
- package/skills/typescript-functional-patterns/references/adts.md +0 -497
- package/skills/typescript-functional-patterns/references/branded-types.md +0 -542
- package/skills/typescript-functional-patterns/references/migration-guide.md +0 -695
- package/skills/typescript-functional-patterns/references/option-result.md +0 -585
- package/skills/typescript-testing/SKILL.md +0 -353
- package/skills/typescript-testing/references/mocking.md +0 -675
- package/skills/typescript-testing/references/msw.md +0 -852
- package/skills/typescript-testing/references/snapshot-testing.md +0 -774
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: python-temporal
|
|
3
|
-
description: Temporal workflow orchestration in Python. Use when designing workflows, implementing activities, handling retries, managing workflow state, or building durable distributed systems.
|
|
4
|
-
user-invocable: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Temporal Workflow Orchestration
|
|
8
|
-
|
|
9
|
-
Temporal SDK patterns for building durable, distributed workflows in Python.
|
|
10
|
-
|
|
11
|
-
## Worker Setup
|
|
12
|
-
|
|
13
|
-
```python
|
|
14
|
-
from temporalio.client import Client
|
|
15
|
-
from temporalio.worker import Worker
|
|
16
|
-
|
|
17
|
-
async def main():
|
|
18
|
-
client = await Client.connect("localhost:7233")
|
|
19
|
-
|
|
20
|
-
worker = Worker(
|
|
21
|
-
client,
|
|
22
|
-
task_queue="my-task-queue",
|
|
23
|
-
workflows=[MyWorkflow],
|
|
24
|
-
activities=[my_activity],
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
await worker.run()
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Workflow Definition
|
|
31
|
-
|
|
32
|
-
```python
|
|
33
|
-
from temporalio import workflow
|
|
34
|
-
from datetime import timedelta
|
|
35
|
-
|
|
36
|
-
@workflow.defn
|
|
37
|
-
class MyWorkflow:
|
|
38
|
-
@workflow.run
|
|
39
|
-
async def run(self, name: str) -> str:
|
|
40
|
-
"""Workflow run method"""
|
|
41
|
-
# Execute activity
|
|
42
|
-
result = await workflow.execute_activity(
|
|
43
|
-
my_activity,
|
|
44
|
-
name,
|
|
45
|
-
start_to_close_timeout=timedelta(seconds=30),
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
return f"Hello {result}"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Activity Implementation
|
|
52
|
-
|
|
53
|
-
```python
|
|
54
|
-
from temporalio import activity
|
|
55
|
-
|
|
56
|
-
@activity.defn
|
|
57
|
-
async def my_activity(name: str) -> str:
|
|
58
|
-
"""Activity - can fail and retry"""
|
|
59
|
-
# Do work (database, API, etc.)
|
|
60
|
-
return name.upper()
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Starting Workflows
|
|
64
|
-
|
|
65
|
-
```python
|
|
66
|
-
from temporalio.client import Client
|
|
67
|
-
|
|
68
|
-
async def start_workflow():
|
|
69
|
-
client = await Client.connect("localhost:7233")
|
|
70
|
-
|
|
71
|
-
handle = await client.start_workflow(
|
|
72
|
-
MyWorkflow.run,
|
|
73
|
-
"World",
|
|
74
|
-
id="my-workflow-id",
|
|
75
|
-
task_queue="my-task-queue",
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
result = await handle.result()
|
|
79
|
-
print(result) # "Hello WORLD"
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Error Handling
|
|
83
|
-
|
|
84
|
-
```python
|
|
85
|
-
from temporalio.exceptions import ActivityError
|
|
86
|
-
|
|
87
|
-
@workflow.defn
|
|
88
|
-
class MyWorkflow:
|
|
89
|
-
@workflow.run
|
|
90
|
-
async def run(self) -> str:
|
|
91
|
-
try:
|
|
92
|
-
result = await workflow.execute_activity(
|
|
93
|
-
risky_activity,
|
|
94
|
-
start_to_close_timeout=timedelta(seconds=30),
|
|
95
|
-
retry_policy=RetryPolicy(maximum_attempts=3),
|
|
96
|
-
)
|
|
97
|
-
except ActivityError as e:
|
|
98
|
-
# Handle failure after retries exhausted
|
|
99
|
-
return "Failed"
|
|
100
|
-
|
|
101
|
-
return result
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Signals and Queries
|
|
105
|
-
|
|
106
|
-
```python
|
|
107
|
-
@workflow.defn
|
|
108
|
-
class OrderWorkflow:
|
|
109
|
-
def __init__(self):
|
|
110
|
-
self.status = "pending"
|
|
111
|
-
|
|
112
|
-
@workflow.run
|
|
113
|
-
async def run(self, order_id: str) -> str:
|
|
114
|
-
await workflow.wait_condition(lambda: self.status == "approved")
|
|
115
|
-
return "Order processed"
|
|
116
|
-
|
|
117
|
-
@workflow.signal
|
|
118
|
-
def approve(self):
|
|
119
|
-
"""Signal to approve order"""
|
|
120
|
-
self.status = "approved"
|
|
121
|
-
|
|
122
|
-
@workflow.query
|
|
123
|
-
def get_status(self) -> str:
|
|
124
|
-
"""Query current status"""
|
|
125
|
-
return self.status
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
See references/ for testing patterns and common workflow patterns.
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Common Temporal Workflow Patterns
|
|
2
|
-
|
|
3
|
-
## Saga Pattern
|
|
4
|
-
|
|
5
|
-
```python
|
|
6
|
-
@workflow.defn
|
|
7
|
-
class SagaWorkflow:
|
|
8
|
-
@workflow.run
|
|
9
|
-
async def run(self, order_id: str):
|
|
10
|
-
"""Saga with compensations"""
|
|
11
|
-
try:
|
|
12
|
-
# Step 1: Reserve inventory
|
|
13
|
-
await workflow.execute_activity(
|
|
14
|
-
reserve_inventory,
|
|
15
|
-
order_id,
|
|
16
|
-
start_to_close_timeout=timedelta(seconds=30),
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
# Step 2: Charge payment
|
|
20
|
-
await workflow.execute_activity(
|
|
21
|
-
charge_payment,
|
|
22
|
-
order_id,
|
|
23
|
-
start_to_close_timeout=timedelta(seconds=30),
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
# Step 3: Ship order
|
|
27
|
-
await workflow.execute_activity(
|
|
28
|
-
ship_order,
|
|
29
|
-
order_id,
|
|
30
|
-
start_to_close_timeout=timedelta(seconds=30),
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
except Exception:
|
|
34
|
-
# Compensate in reverse order
|
|
35
|
-
await workflow.execute_activity(release_inventory, order_id)
|
|
36
|
-
await workflow.execute_activity(refund_payment, order_id)
|
|
37
|
-
raise
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Fan-Out/Fan-In
|
|
41
|
-
|
|
42
|
-
```python
|
|
43
|
-
@workflow.defn
|
|
44
|
-
class FanOutWorkflow:
|
|
45
|
-
@workflow.run
|
|
46
|
-
async def run(self, items: list[str]):
|
|
47
|
-
"""Process items in parallel"""
|
|
48
|
-
# Fan-out: start all activities
|
|
49
|
-
tasks = [
|
|
50
|
-
workflow.execute_activity(
|
|
51
|
-
process_item,
|
|
52
|
-
item,
|
|
53
|
-
start_to_close_timeout=timedelta(seconds=30),
|
|
54
|
-
)
|
|
55
|
-
for item in items
|
|
56
|
-
]
|
|
57
|
-
|
|
58
|
-
# Fan-in: wait for all
|
|
59
|
-
results = await asyncio.gather(*tasks)
|
|
60
|
-
return results
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Long-Running Approval
|
|
64
|
-
|
|
65
|
-
```python
|
|
66
|
-
@workflow.defn
|
|
67
|
-
class ApprovalWorkflow:
|
|
68
|
-
def __init__(self):
|
|
69
|
-
self.approved = False
|
|
70
|
-
|
|
71
|
-
@workflow.run
|
|
72
|
-
async def run(self, request_id: str):
|
|
73
|
-
"""Wait for approval (can wait days/weeks)"""
|
|
74
|
-
await workflow.wait_condition(
|
|
75
|
-
lambda: self.approved,
|
|
76
|
-
timeout=timedelta(days=7),
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
if self.approved:
|
|
80
|
-
await workflow.execute_activity(process_request, request_id)
|
|
81
|
-
else:
|
|
82
|
-
await workflow.execute_activity(reject_request, request_id)
|
|
83
|
-
|
|
84
|
-
@workflow.signal
|
|
85
|
-
def approve(self):
|
|
86
|
-
self.approved = True
|
|
87
|
-
```
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Testing Temporal Workflows
|
|
2
|
-
|
|
3
|
-
## Test Environment
|
|
4
|
-
|
|
5
|
-
```python
|
|
6
|
-
from temporalio.testing import WorkflowEnvironment
|
|
7
|
-
from temporalio.worker import Worker
|
|
8
|
-
|
|
9
|
-
async def test_workflow():
|
|
10
|
-
"""Test workflow in test environment"""
|
|
11
|
-
async with await WorkflowEnvironment.start_time_skipping() as env:
|
|
12
|
-
# Create worker
|
|
13
|
-
async with Worker(
|
|
14
|
-
env.client,
|
|
15
|
-
task_queue="test-queue",
|
|
16
|
-
workflows=[MyWorkflow],
|
|
17
|
-
activities=[my_activity],
|
|
18
|
-
):
|
|
19
|
-
# Execute workflow
|
|
20
|
-
result = await env.client.execute_workflow(
|
|
21
|
-
MyWorkflow.run,
|
|
22
|
-
"World",
|
|
23
|
-
id="test-workflow",
|
|
24
|
-
task_queue="test-queue",
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
assert result == "Hello WORLD"
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Activity Mocking
|
|
31
|
-
|
|
32
|
-
```python
|
|
33
|
-
from unittest.mock import Mock
|
|
34
|
-
|
|
35
|
-
async def test_workflow_with_mock_activity():
|
|
36
|
-
"""Mock activity in test"""
|
|
37
|
-
mock_activity = Mock(return_value="MOCKED")
|
|
38
|
-
|
|
39
|
-
async with await WorkflowEnvironment.start_time_skipping() as env:
|
|
40
|
-
async with Worker(
|
|
41
|
-
env.client,
|
|
42
|
-
task_queue="test-queue",
|
|
43
|
-
workflows=[MyWorkflow],
|
|
44
|
-
activities=[mock_activity],
|
|
45
|
-
):
|
|
46
|
-
result = await env.client.execute_workflow(
|
|
47
|
-
MyWorkflow.run,
|
|
48
|
-
"World",
|
|
49
|
-
id="test-workflow",
|
|
50
|
-
task_queue="test-queue",
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
assert result == "Hello MOCKED"
|
|
54
|
-
```
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: python-testing
|
|
3
|
-
description: Stub-Driven TDD and layer boundary testing with pytest. Use when writing tests, deciding what to test, testing at component boundaries, or implementing test-driven development.
|
|
4
|
-
user-invocable: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Testing with pytest
|
|
8
|
-
|
|
9
|
-
Stub-Driven TDD and layer boundary testing patterns for Python applications.
|
|
10
|
-
|
|
11
|
-
## Core Principle: Stub-Driven TDD
|
|
12
|
-
|
|
13
|
-
Test at component boundaries, not internal implementation:
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
Router → Service → Repository → Entity → Database
|
|
17
|
-
↓ ↓ ↓ ↓
|
|
18
|
-
Test Test Test Test
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Follow the **Stub → Test → Implement → Refactor** workflow:
|
|
22
|
-
|
|
23
|
-
1. **Stub** - Create function signature with `pass`
|
|
24
|
-
2. **Test** - Write test for expected behavior
|
|
25
|
-
3. **Implement** - Make test pass
|
|
26
|
-
4. **Refactor** - Clean up code
|
|
27
|
-
|
|
28
|
-
```python
|
|
29
|
-
# 1. Stub
|
|
30
|
-
def calculate_discount(total: Decimal) -> Decimal:
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
# 2. Test
|
|
34
|
-
def test_discount_for_large_order():
|
|
35
|
-
result = calculate_discount(Decimal("150"))
|
|
36
|
-
assert result == Decimal("15")
|
|
37
|
-
|
|
38
|
-
# 3. Implement
|
|
39
|
-
def calculate_discount(total: Decimal) -> Decimal:
|
|
40
|
-
if total > 100:
|
|
41
|
-
return total * Decimal("0.1")
|
|
42
|
-
return Decimal("0")
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Layer Boundary Testing Overview
|
|
46
|
-
|
|
47
|
-
Test **what crosses layer boundaries**, not internal implementation:
|
|
48
|
-
|
|
49
|
-
- **Entity Layer**: Domain logic, validation, transformations (from_request, to_response, to_record)
|
|
50
|
-
- **Service Layer**: Business workflows, error handling, dependency orchestration
|
|
51
|
-
- **Repository Layer**: CRUD operations, query logic, entity ↔ record transformations
|
|
52
|
-
- **Router Layer**: Request validation, response serialization, status codes
|
|
53
|
-
|
|
54
|
-
See references/boundaries.md for comprehensive layer-specific examples.
|
|
55
|
-
|
|
56
|
-
## Entity Testing Example
|
|
57
|
-
|
|
58
|
-
Test transformations and business logic:
|
|
59
|
-
|
|
60
|
-
```python
|
|
61
|
-
def test_product_from_request():
|
|
62
|
-
"""Test creation from request"""
|
|
63
|
-
request = CreateProductRequest(name="Widget", price=Decimal("9.99"))
|
|
64
|
-
product = Product.from_request(request)
|
|
65
|
-
|
|
66
|
-
assert product.name == "Widget"
|
|
67
|
-
assert product.price == Decimal("9.99")
|
|
68
|
-
assert isinstance(product.id, UUID)
|
|
69
|
-
|
|
70
|
-
def test_product_apply_discount():
|
|
71
|
-
"""Test business logic"""
|
|
72
|
-
product = Product(id=uuid4(), name="Widget", price=Decimal("100"))
|
|
73
|
-
discounted = product.apply_discount(Decimal("0.1"))
|
|
74
|
-
|
|
75
|
-
assert discounted.price == Decimal("90")
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Service Testing Example
|
|
79
|
-
|
|
80
|
-
Test orchestration with stubbed dependencies:
|
|
81
|
-
|
|
82
|
-
```python
|
|
83
|
-
from unittest.mock import Mock
|
|
84
|
-
|
|
85
|
-
def test_create_product_service():
|
|
86
|
-
"""Test with mocked repository"""
|
|
87
|
-
mock_repo = Mock()
|
|
88
|
-
mock_repo.save.return_value = Product(id=uuid4(), name="Widget")
|
|
89
|
-
|
|
90
|
-
service = ProductService(repo=mock_repo)
|
|
91
|
-
result = service.create(CreateProductRequest(name="Widget", price=Decimal("9.99")))
|
|
92
|
-
|
|
93
|
-
mock_repo.save.assert_called_once()
|
|
94
|
-
assert result.name == "Widget"
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Repository Testing Example
|
|
98
|
-
|
|
99
|
-
Test data access with real test database:
|
|
100
|
-
|
|
101
|
-
```python
|
|
102
|
-
@pytest.fixture
|
|
103
|
-
def test_db():
|
|
104
|
-
"""In-memory test database"""
|
|
105
|
-
engine = create_engine("sqlite:///:memory:")
|
|
106
|
-
Base.metadata.create_all(engine)
|
|
107
|
-
return sessionmaker(bind=engine)()
|
|
108
|
-
|
|
109
|
-
def test_repository_save(test_db):
|
|
110
|
-
"""Test database operations"""
|
|
111
|
-
repo = ProductRepository(test_db)
|
|
112
|
-
product = Product(id=uuid4(), name="Widget", price=Decimal("9.99"))
|
|
113
|
-
|
|
114
|
-
saved = repo.save(product)
|
|
115
|
-
|
|
116
|
-
assert saved.id == product.id
|
|
117
|
-
assert test_db.query(ProductRecord).count() == 1
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Router Testing Example
|
|
121
|
-
|
|
122
|
-
Test HTTP layer with TestClient:
|
|
123
|
-
|
|
124
|
-
```python
|
|
125
|
-
from fastapi.testclient import TestClient
|
|
126
|
-
|
|
127
|
-
def test_create_product_endpoint():
|
|
128
|
-
"""Test POST endpoint"""
|
|
129
|
-
client = TestClient(app)
|
|
130
|
-
|
|
131
|
-
response = client.post(
|
|
132
|
-
"/products",
|
|
133
|
-
json={"name": "Widget", "price": 9.99},
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
assert response.status_code == 201
|
|
137
|
-
assert response.json()["name"] == "Widget"
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Test Organization Basics
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
tests/
|
|
144
|
-
├── unit/
|
|
145
|
-
│ ├── test_entities.py # Entity + Value object tests
|
|
146
|
-
│ └── test_services.py # Service tests (with mocks)
|
|
147
|
-
├── integration/
|
|
148
|
-
│ ├── test_repositories.py # Repository tests (with DB)
|
|
149
|
-
│ └── test_endpoints.py # Router tests (with client)
|
|
150
|
-
└── conftest.py # Shared fixtures
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Reference Documentation
|
|
154
|
-
|
|
155
|
-
For comprehensive patterns and examples, see:
|
|
156
|
-
|
|
157
|
-
- **references/boundaries.md** - Layer boundary testing patterns with complete examples for each layer
|
|
158
|
-
- **references/mocking.md** - Mock strategies, verification methods, and anti-patterns
|
|
159
|
-
- **references/pytest.md** - Configuration, fixtures, markers, parametrization, and debugging
|
|
160
|
-
|
|
161
|
-
Progressive disclosure: SKILL.md provides quick reference, references/ contain full details.
|