@martinffx/atelier 1.2.2 → 1.3.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 (57) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +22 -24
  3. package/agents/architect.md +1 -1
  4. package/agents/oracle.md +1 -1
  5. package/dist/atelier.js +12 -14
  6. package/package.json +1 -1
  7. package/skills/code-commit/SKILL.md +5 -13
  8. package/skills/code-pull-request/SKILL.md +36 -0
  9. package/skills/code-pull-request/references/common.md +76 -0
  10. package/skills/code-pull-request/references/create-pr.md +122 -0
  11. package/skills/code-pull-request/references/default-template.md +25 -0
  12. package/skills/code-pull-request/references/leave-comment.md +53 -0
  13. package/skills/code-pull-request/references/merge-pr.md +94 -0
  14. package/skills/code-pull-request/references/read-comments.md +61 -0
  15. package/skills/code-pull-request/references/respond-to-comment.md +66 -0
  16. package/skills/code-review/SKILL.md +21 -12
  17. package/skills/code-review/references/reviewers.md +142 -41
  18. package/skills/code-review/references/rq.md +48 -32
  19. package/skills/oracle-debug/SKILL.md +218 -0
  20. package/skills/{code-debug → oracle-debug}/references/bug-patterns.md +3 -3
  21. package/skills/oracle-domain-modelling/SKILL.md +84 -0
  22. package/skills/oracle-grill-me/SKILL.md +20 -0
  23. package/skills/spec-brainstorm/SKILL.md +91 -71
  24. package/skills/spec-finish/SKILL.md +20 -14
  25. package/skills/spec-implement/SKILL.md +3 -2
  26. package/skills/spec-orchestrator/SKILL.md +4 -15
  27. package/skills/spec-plan/SKILL.md +1 -1
  28. package/agents/scout.md +0 -40
  29. package/skills/code-commit/references/pr-workflow.md +0 -145
  30. package/skills/code-debug/SKILL.md +0 -199
  31. package/skills/code-docs/SKILL.md +0 -171
  32. package/skills/code-docs/references/api-docs.md +0 -116
  33. package/skills/code-docs/references/changelog.md +0 -64
  34. package/skills/code-docs/references/readme-structure.md +0 -94
  35. package/skills/oracle-architect/SKILL.md +0 -327
  36. package/skills/oracle-architect/references/api-design.md +0 -345
  37. package/skills/oracle-architect/references/data-modeling.md +0 -318
  38. package/skills/oracle-architect/references/ddd-patterns.md +0 -348
  39. package/skills/oracle-architect/references/interface-design.md +0 -203
  40. package/skills/oracle-challenge/SKILL.md +0 -126
  41. package/skills/oracle-doubt/SKILL.md +0 -252
  42. package/skills/oracle-doubt/references/adversarial-prompt.md +0 -47
  43. package/skills/oracle-grillme/SKILL.md +0 -160
  44. package/skills/oracle-security/SKILL.md +0 -225
  45. package/skills/oracle-security/references/security-patterns.md +0 -236
  46. package/skills/oracle-security/references/threat-modeling-guide.md +0 -137
  47. package/skills/oracle-testing/SKILL.md +0 -237
  48. package/skills/oracle-testing/references/anti-patterns.md +0 -618
  49. package/skills/oracle-testing/references/boundaries.md +0 -579
  50. package/skills/oracle-testing/references/core-testing.md +0 -691
  51. package/skills/oracle-testing/references/edge-testing.md +0 -794
  52. package/skills/oracle-testing/references/stub-driven-tdd.md +0 -322
  53. package/skills/oracle-thinkdeep/SKILL.md +0 -164
  54. /package/skills/{code-debug → oracle-debug}/references/language-tools.md +0 -0
  55. /package/skills/{code-debug → oracle-debug}/references/techniques.md +0 -0
  56. /package/skills/{oracle-grillme → oracle-domain-modelling}/references/ADR-FORMAT.md +0 -0
  57. /package/skills/{oracle-grillme → oracle-domain-modelling}/references/CONTEXT-FORMAT.md +0 -0
@@ -1,345 +0,0 @@
1
- # API Design Reference
2
-
3
- REST conventions, request/response contracts, and error handling patterns.
4
-
5
- ## REST Conventions
6
-
7
- ### Resource-Oriented Endpoints
8
-
9
- **Standard CRUD operations:**
10
- ```
11
- GET /orders # List orders
12
- POST /orders # Create order
13
- GET /orders/:id # Get single order
14
- PATCH /orders/:id # Update order
15
- DELETE /orders/:id # Delete order
16
- ```
17
-
18
- **Nested resources:**
19
- ```
20
- GET /orders/:orderId/items # List order items
21
- POST /orders/:orderId/items # Add item to order
22
- GET /orders/:orderId/items/:itemId # Get order item
23
- PATCH /orders/:orderId/items/:itemId # Update order item
24
- DELETE /orders/:orderId/items/:itemId # Delete order item
25
- ```
26
-
27
- ### Actions (Non-CRUD Operations)
28
-
29
- **Use POST for state transitions:**
30
- ```
31
- POST /orders/:id/cancel # Cancel order
32
- POST /orders/:id/ship # Ship order
33
- POST /orders/:id/confirm # Confirm order
34
- ```
35
-
36
- **Reasoning:** These modify state but aren't CRUD operations. They represent domain actions.
37
-
38
- **Avoid:**
39
- ```
40
- PATCH /orders/:id { "action": "cancel" } # Unclear what changed
41
- GET /orders/:id/cancel # GET shouldn't have side effects
42
- ```
43
-
44
- ## Request/Response Contracts
45
-
46
- ### Request Types
47
-
48
- **Create request (POST /resource):**
49
- ```typescript
50
- interface CreateOrderRequest {
51
- customerId: string;
52
- items: Array<{
53
- productId: string;
54
- quantity: number;
55
- }>;
56
- shippingAddress?: {
57
- street: string;
58
- city: string;
59
- zipCode: string;
60
- };
61
- }
62
- ```
63
-
64
- **Update request (PATCH /resource/:id):**
65
- ```typescript
66
- interface UpdateOrderRequest {
67
- status?: 'pending' | 'confirmed' | 'shipped';
68
- shippingAddress?: Address;
69
- // Only fields that can be updated
70
- }
71
- ```
72
-
73
- **Query parameters:**
74
- ```
75
- GET /orders?customerId=cust-123&status=pending&limit=20&offset=0
76
-
77
- interface ListOrdersQuery {
78
- customerId?: string;
79
- status?: OrderStatus;
80
- limit?: number; // Default 20, max 100
81
- offset?: number; // Pagination offset
82
- }
83
- ```
84
-
85
- ### Response Types
86
-
87
- **Single resource (GET /resource/:id):**
88
- ```typescript
89
- interface OrderResponse {
90
- id: string;
91
- customerId: string;
92
- items: OrderItem[];
93
- status: 'pending' | 'confirmed' | 'shipped' | 'delivered';
94
- total: number;
95
- createdAt: string; // ISO 8601
96
- updatedAt: string;
97
- }
98
- ```
99
-
100
- **List response (GET /resource):**
101
- ```typescript
102
- interface ListOrdersResponse {
103
- data: OrderResponse[];
104
- pagination: {
105
- total: number;
106
- limit: number;
107
- offset: number;
108
- hasMore: boolean;
109
- };
110
- }
111
- ```
112
-
113
- **Create response (POST /resource):**
114
- ```typescript
115
- // Return created resource with 201 status
116
- interface CreateOrderResponse extends OrderResponse {
117
- id: string; // Generated by server
118
- }
119
- ```
120
-
121
- ### Timestamp Conventions
122
-
123
- **Use ISO 8601 for all timestamps:**
124
- ```json
125
- {
126
- "createdAt": "2024-01-21T10:30:45Z",
127
- "updatedAt": "2024-01-21T10:30:45Z",
128
- "deletedAt": null
129
- }
130
- ```
131
-
132
- **Never:** Unix timestamps, custom formats, or timezone abbreviations
133
-
134
- ## Error Handling
135
-
136
- ### HTTP Status Codes
137
-
138
- **Success:**
139
- - `200 OK` - GET, PATCH succeeded
140
- - `201 Created` - POST created resource
141
- - `204 No Content` - DELETE or update with no response body
142
-
143
- **Client Errors:**
144
- - `400 Bad Request` - Invalid input validation
145
- - `401 Unauthorized` - Missing authentication
146
- - `403 Forbidden` - Authenticated but insufficient permissions
147
- - `404 Not Found` - Resource not found
148
- - `409 Conflict` - State violation (can't transition state)
149
- - `422 Unprocessable Entity` - Validation failed
150
-
151
- **Server Errors:**
152
- - `500 Internal Server Error` - Unhandled exception
153
- - `503 Service Unavailable` - Temporary outage
154
-
155
- ### Error Response Format
156
-
157
- **Validation error (400):**
158
- ```typescript
159
- interface ValidationErrorResponse {
160
- error: 'Validation failed';
161
- code: 'VALIDATION_ERROR';
162
- details: {
163
- field: string;
164
- message: string;
165
- }[];
166
- }
167
-
168
- // Example
169
- {
170
- "error": "Validation failed",
171
- "code": "VALIDATION_ERROR",
172
- "details": [
173
- { "field": "items", "message": "Must have at least one item" },
174
- { "field": "customerId", "message": "Invalid customer ID format" }
175
- ]
176
- }
177
- ```
178
-
179
- **Business rule violation (409):**
180
- ```typescript
181
- interface ConflictErrorResponse {
182
- error: string;
183
- code: string;
184
- details?: Record<string, unknown>;
185
- }
186
-
187
- // Example
188
- {
189
- "error": "Cannot cancel shipped order",
190
- "code": "ORDER_ALREADY_SHIPPED",
191
- "details": {
192
- "status": "shipped",
193
- "orderId": "order-123"
194
- }
195
- }
196
- ```
197
-
198
- **Not found (404):**
199
- ```json
200
- {
201
- "error": "Order not found",
202
- "code": "ORDER_NOT_FOUND",
203
- "details": { "id": "order-123" }
204
- }
205
- ```
206
-
207
- **Generic error (500):**
208
- ```json
209
- {
210
- "error": "Internal server error",
211
- "code": "INTERNAL_ERROR"
212
- }
213
- ```
214
-
215
- ### Error Code Convention
216
-
217
- Use SCREAMING_SNAKE_CASE for error codes:
218
- - `VALIDATION_ERROR` - Input validation failed
219
- - `ORDER_NOT_FOUND` - Resource not found
220
- - `ORDER_ALREADY_SHIPPED` - State violation
221
- - `INSUFFICIENT_INVENTORY` - Business rule violation
222
- - `AUTHENTICATION_REQUIRED` - Auth failed
223
- - `PERMISSION_DENIED` - Authz failed
224
-
225
- ## Versioning Patterns
226
-
227
- ### URL Versioning
228
-
229
- **Include version in path:**
230
- ```
231
- GET /v1/orders
232
- GET /v2/orders
233
- ```
234
-
235
- **Pros:** Explicit, clear to consumers
236
- **Cons:** Requires multiple code paths
237
-
238
- ### Accept Header Versioning
239
-
240
- **Use media type version:**
241
- ```
242
- GET /orders
243
- Accept: application/vnd.myapi.v2+json
244
- ```
245
-
246
- **Pros:** Cleaner URLs, single endpoint
247
- **Cons:** Less discoverable
248
-
249
- ### Pragmatic Approach
250
-
251
- 1. Start without versioning (all responses same format)
252
- 2. Add versioning when you need breaking changes
253
- 3. Support at least 2 versions during transition
254
- 4. Provide clear deprecation timeline
255
-
256
- ### Backwards Compatibility
257
-
258
- **Adding fields (safe):**
259
- ```typescript
260
- // v1
261
- interface OrderResponse {
262
- id: string;
263
- total: number;
264
- }
265
-
266
- // v2 (backwards compatible)
267
- interface OrderResponse {
268
- id: string;
269
- total: number;
270
- tax?: number; // New optional field
271
- }
272
- ```
273
-
274
- **Removing fields (breaking change):**
275
- ```typescript
276
- // Requires new API version
277
- // v1 has 'total'
278
- // v2 has 'subtotal' and 'tax'
279
- ```
280
-
281
- ## Example: Complete Order API
282
-
283
- ### Endpoints
284
-
285
- ```
286
- POST /orders
287
- Create order
288
- Request: CreateOrderRequest
289
- Response: 201 OrderResponse
290
-
291
- GET /orders
292
- List orders
293
- Query: ListOrdersQuery
294
- Response: 200 ListOrdersResponse
295
-
296
- GET /orders/:id
297
- Get order
298
- Response: 200 OrderResponse
299
-
300
- PATCH /orders/:id
301
- Update order
302
- Request: UpdateOrderRequest
303
- Response: 200 OrderResponse
304
-
305
- POST /orders/:id/cancel
306
- Cancel order
307
- Response: 200 OrderResponse
308
-
309
- DELETE /orders/:id
310
- Delete order
311
- Response: 204 (no body)
312
- ```
313
-
314
- ### Implementation Pattern
315
-
316
- ```typescript
317
- // Router handles HTTP concerns
318
- router.post('/orders', async (req, res) => {
319
- // 1. Parse request
320
- const request: CreateOrderRequest = req.body;
321
-
322
- // 2. Validate input (preliminary)
323
- if (!request.customerId) {
324
- return res.status(400).json({
325
- error: 'Validation failed',
326
- code: 'VALIDATION_ERROR',
327
- details: [{ field: 'customerId', message: 'Required' }]
328
- });
329
- }
330
-
331
- // 3. Call service
332
- const result = await orderService.createOrder(request);
333
-
334
- // 4. Handle result
335
- if (result.ok) {
336
- return res.status(201).json(result.value.toResponse());
337
- }
338
-
339
- // 5. Return error
340
- res.status(409).json({
341
- error: result.error,
342
- code: result.code || 'UNKNOWN_ERROR'
343
- });
344
- });
345
- ```
@@ -1,318 +0,0 @@
1
- # Data Modeling Reference
2
-
3
- Entity design principles, schema patterns, and access pattern optimization.
4
-
5
- ## Entity Design
6
-
7
- ### Design Process
8
- 1. Start with domain concepts from product requirements
9
- 2. Identify aggregates and their boundaries
10
- 3. Define attributes and relationships
11
- 4. Add validation rules and invariants
12
- 5. Include transformation methods (fromRequest, toRecord, toResponse)
13
-
14
- ### Entity Structure
15
-
16
- **Core transformation methods:**
17
- ```typescript
18
- class Order {
19
- // Create from external request
20
- static fromRequest(req: CreateOrderRequest): Order
21
-
22
- // Create from database record
23
- static fromRecord(record: OrderRecord): Order
24
-
25
- // Convert to database record
26
- toRecord(): OrderRecord
27
-
28
- // Convert to API response
29
- toResponse(): OrderResponse
30
-
31
- // Validate invariants
32
- validate(): Result<Order>
33
- }
34
- ```
35
-
36
- ### Example Entity Design
37
-
38
- ```typescript
39
- class Order {
40
- constructor(
41
- public readonly id: string,
42
- public readonly customerId: string,
43
- public readonly items: OrderItem[],
44
- public readonly status: OrderStatus,
45
- public readonly total: number,
46
- public readonly createdAt: Date,
47
- public readonly metadata: OrderMetadata
48
- ) {}
49
-
50
- static fromRequest(req: CreateOrderRequest): Order {
51
- return new Order(
52
- generateId(),
53
- req.customerId,
54
- req.items.map(i => new OrderItem(i)),
55
- 'pending',
56
- req.items.reduce((sum, i) => sum + i.price * i.quantity, 0),
57
- new Date(),
58
- { source: req.source || 'web' }
59
- );
60
- }
61
-
62
- toRecord(): OrderRecord {
63
- return {
64
- id: this.id,
65
- customer_id: this.customerId,
66
- items: JSON.stringify(this.items),
67
- status: this.status,
68
- total: this.total,
69
- created_at: this.createdAt.toISOString(),
70
- metadata: this.metadata
71
- };
72
- }
73
-
74
- toResponse(): OrderResponse {
75
- return {
76
- id: this.id,
77
- customerId: this.customerId,
78
- items: this.items,
79
- status: this.status,
80
- total: this.total,
81
- createdAt: this.createdAt.toISOString()
82
- };
83
- }
84
-
85
- validate(): Result<Order> {
86
- if (this.items.length === 0) {
87
- return Err('Order must have at least one item');
88
- }
89
- if (this.total < 0) {
90
- return Err('Order total cannot be negative');
91
- }
92
- return Ok(this);
93
- }
94
- }
95
- ```
96
-
97
- ## Schema Patterns
98
-
99
- ### Relational Design
100
-
101
- **Orders table:**
102
- ```sql
103
- CREATE TABLE orders (
104
- id UUID PRIMARY KEY,
105
- customer_id UUID NOT NULL REFERENCES customers(id),
106
- status VARCHAR(20) NOT NULL CHECK (status IN ('pending', 'confirmed', 'shipped', 'delivered')),
107
- total DECIMAL(10,2) NOT NULL,
108
- created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
109
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
110
- );
111
-
112
- CREATE INDEX idx_orders_customer ON orders(customer_id);
113
- CREATE INDEX idx_orders_status ON orders(status);
114
- CREATE INDEX idx_orders_created ON orders(created_at DESC);
115
- ```
116
-
117
- **Order items (normalized):**
118
- ```sql
119
- CREATE TABLE order_items (
120
- id UUID PRIMARY KEY,
121
- order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
122
- product_id UUID NOT NULL,
123
- quantity INT NOT NULL CHECK (quantity > 0),
124
- price DECIMAL(10,2) NOT NULL,
125
- UNIQUE(order_id, product_id)
126
- );
127
-
128
- CREATE INDEX idx_order_items_order ON order_items(order_id);
129
- ```
130
-
131
- ### DynamoDB Single Table Design
132
-
133
- **Items structure:**
134
- ```typescript
135
- {
136
- PK: 'ORDER#123',
137
- SK: 'ORDER#123',
138
- type: 'Order',
139
- customerId: 'CUST#456',
140
- status: 'pending',
141
- total: 99.99,
142
- items: [...],
143
- createdAt: '2024-01-21T10:00:00Z',
144
-
145
- // GSI for customer lookup
146
- GSI1PK: 'CUST#456',
147
- GSI1SK: 'ORDER#2024-01-21T10:00:00Z',
148
-
149
- // GSI for status lookup
150
- GSI2PK: 'pending',
151
- GSI2SK: 'ORDER#2024-01-21T10:00:00Z'
152
- }
153
-
154
- {
155
- PK: 'ORDER#123',
156
- SK: 'ITEM#item-001',
157
- type: 'OrderItem',
158
- productId: 'PROD#999',
159
- quantity: 2,
160
- price: 49.99
161
- }
162
- ```
163
-
164
- **Key design:**
165
- - PK = partition key (primary lookup)
166
- - SK = sort key (range queries)
167
- - GSI = global secondary index (alternative queries)
168
-
169
- ## Access Patterns
170
-
171
- ### Define Patterns First
172
-
173
- List all data access patterns **before** designing schema:
174
-
175
- 1. **Find order by ID**
176
- - Query: `PK = ORDER#123, SK = ORDER#123`
177
- - Index: Primary key
178
-
179
- 2. **List orders by customer**
180
- - Query: `GSI1PK = CUST#456`
181
- - Index: Global secondary index
182
-
183
- 3. **List pending orders by date**
184
- - Query: `GSI2PK = pending, GSI2SK > date`
185
- - Index: Global secondary index sorted by date
186
-
187
- 4. **Count orders by status**
188
- - Query: Scan with filter (or GSI)
189
- - Performance: Consider status table
190
-
191
- 5. **Get recent orders for customer**
192
- - Query: `GSI1PK = CUST#456` sorted by date DESC
193
- - Index: Global secondary index
194
-
195
- ### Query Optimization
196
-
197
- **N+1 Problem:**
198
- ```typescript
199
- // BAD: N+1 queries
200
- const orders = await orderRepo.findByCustomer(customerId);
201
- const itemsPerOrder = await Promise.all(
202
- orders.map(o => itemRepo.findByOrder(o.id)) // N queries
203
- );
204
-
205
- // GOOD: Single query with denormalization
206
- const orderData = await db.orders
207
- .where({ customerId })
208
- .select(['*', 'items']) // Includes denormalized items
209
- .sort({ createdAt: 'DESC' });
210
- ```
211
-
212
- **Index Coverage:**
213
- ```sql
214
- -- Bad: Full table scan
215
- SELECT * FROM orders WHERE customer_id = $1;
216
-
217
- -- Good: Index-covered query
218
- CREATE INDEX idx_orders_customer_status
219
- ON orders(customer_id, status);
220
-
221
- SELECT * FROM orders
222
- WHERE customer_id = $1 AND status = 'pending';
223
- ```
224
-
225
- ## Data Transformation Patterns
226
-
227
- ### Request → Entity → Record → Response Flow
228
-
229
- ```typescript
230
- // 1. HTTP Request arrives
231
- POST /orders
232
- {
233
- "customerId": "cust-123",
234
- "items": [{ "productId": "prod-1", "quantity": 2 }]
235
- }
236
-
237
- // 2. Router parses to request type
238
- const request: CreateOrderRequest = req.body;
239
-
240
- // 3. Entity transforms from request (with ID generation)
241
- const order = Order.fromRequest(request);
242
-
243
- // 4. Entity validates business rules
244
- const validation = order.validate();
245
- if (!validation.ok) return error;
246
-
247
- // 5. Service performs logic, uses repository
248
- await repo.save(order.toRecord());
249
-
250
- // 6. Repository converts to database record
251
- {
252
- id: "order-abc",
253
- customer_id: "cust-123",
254
- items: "[...]",
255
- status: "pending",
256
- created_at: "2024-01-21T10:00:00Z"
257
- }
258
-
259
- // 7. Response converts from record
260
- const response = order.toResponse();
261
-
262
- // 8. HTTP Response sends
263
- {
264
- "id": "order-abc",
265
- "customerId": "cust-123",
266
- "items": [...],
267
- "status": "pending"
268
- }
269
- ```
270
-
271
- ### Transformation Considerations
272
-
273
- **Immutability:**
274
- ```typescript
275
- // Bad: Mutation during transform
276
- toRecord(): OrderRecord {
277
- this.items.forEach(i => i.status = 'recorded');
278
- return { items: this.items };
279
- }
280
-
281
- // Good: No side effects
282
- toRecord(): OrderRecord {
283
- return {
284
- items: this.items.map(i => ({
285
- ...i,
286
- // Transform properties as needed
287
- }))
288
- };
289
- }
290
- ```
291
-
292
- **Versioning:**
293
- ```typescript
294
- // Handle multiple API versions
295
- toResponse(version: 'v1' | 'v2'): OrderResponse {
296
- const base = {
297
- id: this.id,
298
- customerId: this.customerId,
299
- status: this.status
300
- };
301
-
302
- if (version === 'v2') {
303
- return { ...base, total: this.total };
304
- }
305
- return base;
306
- }
307
- ```
308
-
309
- **Partial Loading:**
310
- ```typescript
311
- // Only load fields needed for the operation
312
- async findOrderSummary(id: string): Promise<OrderSummary> {
313
- const record = await db.orders
314
- .select(['id', 'status', 'total'])
315
- .findOne({ id });
316
- return { id: record.id, status: record.status, total: record.total };
317
- }
318
- ```