@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.
Files changed (81) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +94 -253
  3. package/package.json +1 -1
  4. package/skills/{spec-orchestrator → atelier-orchestrator}/SKILL.md +3 -3
  5. package/skills/atelier-setup/SKILL.md +80 -0
  6. package/skills/code-review/references/reviewers.md +3 -3
  7. package/skills/code-review/references/rq.md +6 -6
  8. package/skills/spec-brainstorm/SKILL.md +5 -5
  9. package/skills/spec-implement/SKILL.md +2 -3
  10. package/skills/spec-plan/SKILL.md +21 -29
  11. package/skills/spec-plan/references/plan_template.md +77 -0
  12. package/skills/python-architecture/SKILL.md +0 -148
  13. package/skills/python-architecture/references/data-modeling.md +0 -558
  14. package/skills/python-architecture/references/ddd.md +0 -569
  15. package/skills/python-architecture/references/functional-core.md +0 -337
  16. package/skills/python-build-tools/SKILL.md +0 -153
  17. package/skills/python-build-tools/references/basedpyright.md +0 -321
  18. package/skills/python-build-tools/references/ruff.md +0 -225
  19. package/skills/python-build-tools/references/uv.md +0 -257
  20. package/skills/python-fastapi/SKILL.md +0 -184
  21. package/skills/python-fastapi/references/api-design.md +0 -563
  22. package/skills/python-fastapi/references/dependencies.md +0 -479
  23. package/skills/python-fastapi/references/middleware.md +0 -475
  24. package/skills/python-fastapi/references/validation.md +0 -497
  25. package/skills/python-modern-python/SKILL.md +0 -201
  26. package/skills/python-modern-python/references/async.md +0 -76
  27. package/skills/python-modern-python/references/pattern-matching.md +0 -89
  28. package/skills/python-modern-python/references/typing.md +0 -96
  29. package/skills/python-monorepo/SKILL.md +0 -146
  30. package/skills/python-monorepo/references/docker.md +0 -515
  31. package/skills/python-monorepo/references/namespace-packages.md +0 -426
  32. package/skills/python-monorepo/references/workspace-config.md +0 -341
  33. package/skills/python-sqlalchemy/SKILL.md +0 -119
  34. package/skills/python-sqlalchemy/references/async.md +0 -51
  35. package/skills/python-sqlalchemy/references/models.md +0 -67
  36. package/skills/python-sqlalchemy/references/queries.md +0 -57
  37. package/skills/python-temporal/SKILL.md +0 -128
  38. package/skills/python-temporal/references/patterns.md +0 -87
  39. package/skills/python-temporal/references/testing.md +0 -54
  40. package/skills/python-testing/SKILL.md +0 -161
  41. package/skills/python-testing/references/boundaries.md +0 -449
  42. package/skills/python-testing/references/mocking.md +0 -449
  43. package/skills/python-testing/references/pytest.md +0 -524
  44. package/skills/typescript-api-design/SKILL.md +0 -396
  45. package/skills/typescript-api-design/references/error-responses.md +0 -469
  46. package/skills/typescript-build-tools/SKILL.md +0 -447
  47. package/skills/typescript-build-tools/references/biome.md +0 -436
  48. package/skills/typescript-build-tools/references/bun.md +0 -432
  49. package/skills/typescript-build-tools/references/turborepo.md +0 -426
  50. package/skills/typescript-build-tools/references/vitest.md +0 -518
  51. package/skills/typescript-drizzle-orm/SKILL.md +0 -398
  52. package/skills/typescript-drizzle-orm/references/cloudflare.md +0 -392
  53. package/skills/typescript-drizzle-orm/references/entity-pattern.md +0 -412
  54. package/skills/typescript-drizzle-orm/references/postgresql.md +0 -191
  55. package/skills/typescript-drizzle-orm/references/repository-pattern.md +0 -479
  56. package/skills/typescript-drizzle-orm/references/sqlite.md +0 -291
  57. package/skills/typescript-dynamodb-toolbox/SKILL.md +0 -370
  58. package/skills/typescript-dynamodb-toolbox/references/entity-layer.md +0 -574
  59. package/skills/typescript-dynamodb-toolbox/references/error-handling.md +0 -495
  60. package/skills/typescript-dynamodb-toolbox/references/modeling.md +0 -332
  61. package/skills/typescript-dynamodb-toolbox/references/repository-layer.md +0 -631
  62. package/skills/typescript-dynamodb-toolbox/references/testing.md +0 -718
  63. package/skills/typescript-dynamodb-toolbox/references/transactions.md +0 -423
  64. package/skills/typescript-effect-ts/SKILL.md +0 -341
  65. package/skills/typescript-effect-ts/references/core.md +0 -412
  66. package/skills/typescript-effect-ts/references/error-handling.md +0 -468
  67. package/skills/typescript-effect-ts/references/resources.md +0 -476
  68. package/skills/typescript-effect-ts/references/schema.md +0 -536
  69. package/skills/typescript-effect-ts/references/services.md +0 -461
  70. package/skills/typescript-fastify/SKILL.md +0 -405
  71. package/skills/typescript-fastify/references/plugins.md +0 -329
  72. package/skills/typescript-fastify/references/typeid.md +0 -315
  73. package/skills/typescript-functional-patterns/SKILL.md +0 -402
  74. package/skills/typescript-functional-patterns/references/adts.md +0 -497
  75. package/skills/typescript-functional-patterns/references/branded-types.md +0 -542
  76. package/skills/typescript-functional-patterns/references/migration-guide.md +0 -695
  77. package/skills/typescript-functional-patterns/references/option-result.md +0 -585
  78. package/skills/typescript-testing/SKILL.md +0 -353
  79. package/skills/typescript-testing/references/mocking.md +0 -675
  80. package/skills/typescript-testing/references/msw.md +0 -852
  81. 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.