@codihaus/claude-skills 1.5.0 → 1.6.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.
- package/package.json +5 -2
- package/skills/debrief/SKILL.md +10 -7
- package/skills/debrief/scripts/generate_questionnaire.py +0 -0
- package/skills/dev-coding/SKILL.md +302 -22
- package/skills/dev-coding-backend/SKILL.md +15 -1
- package/skills/dev-coding-backend/references/fundamentals.md +428 -0
- package/skills/dev-coding-frontend/SKILL.md +17 -1
- package/skills/dev-coding-frontend/references/fundamentals.md +577 -0
- package/skills/dev-scout/SKILL.md +36 -1
- package/skills/dev-specs/SKILL.md +25 -6
- package/src/commands/init.js +84 -13
- package/src/utils/config.js +54 -3
- package/src/utils/deps.js +164 -9
- package/src/utils/skills.js +27 -0
- package/templates/HOOK_TRIGGER_TEST.md +143 -0
- package/templates/hooks-guide.md +372 -0
- package/templates/scripts/safe-graph-update.sh +65 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Backend Fundamentals
|
|
2
|
+
|
|
3
|
+
The principles and patterns that enable scalable, maintainable backend systems.
|
|
4
|
+
|
|
5
|
+
## Core Mindset
|
|
6
|
+
|
|
7
|
+
**"I am the guardian of truth. I trust nothing. I enforce rules. I must be reliable."**
|
|
8
|
+
|
|
9
|
+
The backend is the last line of defense. It:
|
|
10
|
+
- Protects data integrity
|
|
11
|
+
- Enforces business rules
|
|
12
|
+
- Handles failures gracefully
|
|
13
|
+
- Scales under load
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## The Principles
|
|
18
|
+
|
|
19
|
+
Principles are the fundamental laws. Patterns are solutions derived from them.
|
|
20
|
+
|
|
21
|
+
### 1. Separation of Concerns
|
|
22
|
+
|
|
23
|
+
**Law**: Each piece of code should have ONE responsibility.
|
|
24
|
+
|
|
25
|
+
**Why**: When things are mixed, changing one breaks another. Testing becomes impossible. New developers get lost.
|
|
26
|
+
|
|
27
|
+
**Patterns derived**:
|
|
28
|
+
|
|
29
|
+
| Pattern | What it Separates |
|
|
30
|
+
|---------|-------------------|
|
|
31
|
+
| Service Layer | Business logic FROM HTTP handling |
|
|
32
|
+
| Repository | Data access FROM business logic |
|
|
33
|
+
| Controller/Route | Request parsing FROM processing |
|
|
34
|
+
| Middleware | Cross-cutting concerns FROM main logic |
|
|
35
|
+
| Event-Driven | "What happened" FROM "What to do about it" |
|
|
36
|
+
|
|
37
|
+
**Recognition signals**:
|
|
38
|
+
- Function does more than one thing
|
|
39
|
+
- Can't test without real database/HTTP
|
|
40
|
+
- Changing one feature breaks another
|
|
41
|
+
- File is > 300 lines
|
|
42
|
+
|
|
43
|
+
**Structure example**:
|
|
44
|
+
```
|
|
45
|
+
# BAD: Mixed concerns
|
|
46
|
+
route('/orders', async (req) => {
|
|
47
|
+
validate(req.body) # validation
|
|
48
|
+
const user = await db.users.find(req.userId) # data access
|
|
49
|
+
if (user.balance < req.body.total) throw Error # business rule
|
|
50
|
+
await db.orders.create(...) # data access
|
|
51
|
+
await sendEmail(user.email) # side effect
|
|
52
|
+
return order
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
# GOOD: Separated concerns
|
|
56
|
+
route('/orders', OrderController.create)
|
|
57
|
+
|
|
58
|
+
OrderController.create(req) {
|
|
59
|
+
const dto = OrderValidator.validate(req.body) # validation layer
|
|
60
|
+
const order = await OrderService.create(dto, req.userId) # service layer
|
|
61
|
+
return OrderPresenter.format(order) # presentation layer
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
OrderService.create(dto, userId) {
|
|
65
|
+
const user = await UserRepository.findById(userId) # repository
|
|
66
|
+
OrderRules.validateCanOrder(user, dto) # business rules
|
|
67
|
+
const order = await OrderRepository.create(dto)
|
|
68
|
+
await EventBus.emit('order.created', order) # events for side effects
|
|
69
|
+
return order
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### 2. Single Source of Truth
|
|
76
|
+
|
|
77
|
+
**Law**: Each piece of data or rule should exist in ONE place only.
|
|
78
|
+
|
|
79
|
+
**Why**: Duplicated data gets out of sync. Duplicated rules diverge over time.
|
|
80
|
+
|
|
81
|
+
**Patterns derived**:
|
|
82
|
+
|
|
83
|
+
| Pattern | What it Centralizes |
|
|
84
|
+
|---------|---------------------|
|
|
85
|
+
| Repository | All access to a data type |
|
|
86
|
+
| Domain Model | Business rules for an entity |
|
|
87
|
+
| Configuration | Environment-specific values |
|
|
88
|
+
| Constants/Enums | Magic values and statuses |
|
|
89
|
+
| Event Store | Historical record of changes |
|
|
90
|
+
|
|
91
|
+
**Recognition signals**:
|
|
92
|
+
- Same validation in multiple places
|
|
93
|
+
- Same query written twice
|
|
94
|
+
- Hardcoded values scattered around
|
|
95
|
+
- "Which one is correct?" questions
|
|
96
|
+
|
|
97
|
+
**Structure example**:
|
|
98
|
+
```
|
|
99
|
+
# BAD: Rules in multiple places
|
|
100
|
+
# In controller:
|
|
101
|
+
if (order.status !== 'pending') throw Error
|
|
102
|
+
|
|
103
|
+
# In service:
|
|
104
|
+
if (order.status !== 'pending') throw Error
|
|
105
|
+
|
|
106
|
+
# In another service:
|
|
107
|
+
if (order.status != 'pending' && order.status != 'draft') throw Error # diverged!
|
|
108
|
+
|
|
109
|
+
# GOOD: Single source
|
|
110
|
+
class Order {
|
|
111
|
+
canBeModified() {
|
|
112
|
+
return ['pending', 'draft'].includes(this.status)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# Everywhere else:
|
|
117
|
+
if (!order.canBeModified()) throw Error
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### 3. Don't Repeat Work
|
|
123
|
+
|
|
124
|
+
**Law**: If the same work is done repeatedly with the same result, do it once and remember.
|
|
125
|
+
|
|
126
|
+
**Why**: Wasted resources, slower response, higher costs, database overload.
|
|
127
|
+
|
|
128
|
+
**Patterns derived**:
|
|
129
|
+
|
|
130
|
+
| Pattern | What it Remembers |
|
|
131
|
+
|---------|-------------------|
|
|
132
|
+
| Caching (Redis/Memory) | Expensive query results |
|
|
133
|
+
| Memoization | Function computation |
|
|
134
|
+
| Database Indexes | Query paths |
|
|
135
|
+
| CDN | Static assets |
|
|
136
|
+
| Materialized Views | Pre-computed aggregations |
|
|
137
|
+
|
|
138
|
+
**Recognition signals**:
|
|
139
|
+
- Same query runs multiple times per request
|
|
140
|
+
- Same computation on same input
|
|
141
|
+
- Dashboard aggregations are slow
|
|
142
|
+
- Database CPU is high
|
|
143
|
+
|
|
144
|
+
**Decision guide**:
|
|
145
|
+
```
|
|
146
|
+
How often does data change?
|
|
147
|
+
├── Never (static) → CDN, aggressive cache
|
|
148
|
+
├── Rarely (config) → Long TTL cache (hours)
|
|
149
|
+
├── Sometimes (user profile) → Medium TTL (minutes)
|
|
150
|
+
├── Often (feed) → Short TTL (seconds) or real-time
|
|
151
|
+
└── Always (balance) → No cache, or cache with invalidation
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### 4. Don't Make Users Wait
|
|
157
|
+
|
|
158
|
+
**Law**: If something takes long and user doesn't need immediate result, do it later.
|
|
159
|
+
|
|
160
|
+
**Why**: Users leave, connections timeout, server resources blocked.
|
|
161
|
+
|
|
162
|
+
**Patterns derived**:
|
|
163
|
+
|
|
164
|
+
| Pattern | Use When |
|
|
165
|
+
|---------|----------|
|
|
166
|
+
| Message Queue | Task takes > 1-2 seconds |
|
|
167
|
+
| Background Jobs | Scheduled or deferred work |
|
|
168
|
+
| Webhooks | Notify instead of poll |
|
|
169
|
+
| Streaming | Large data transfer |
|
|
170
|
+
| Pagination | Large result sets |
|
|
171
|
+
|
|
172
|
+
**Recognition signals**:
|
|
173
|
+
- API timeout errors
|
|
174
|
+
- User waits > 3 seconds
|
|
175
|
+
- Sending emails in request
|
|
176
|
+
- Processing files in request
|
|
177
|
+
- Generating reports in request
|
|
178
|
+
|
|
179
|
+
**Structure example**:
|
|
180
|
+
```
|
|
181
|
+
# BAD: User waits for everything
|
|
182
|
+
route('/orders', async (req) => {
|
|
183
|
+
const order = await createOrder(req.body)
|
|
184
|
+
await generateInvoicePDF(order) # 3 seconds
|
|
185
|
+
await sendEmail(order) # 2 seconds
|
|
186
|
+
await notifyWarehouse(order) # 1 second
|
|
187
|
+
await updateAnalytics(order) # 500ms
|
|
188
|
+
return order # User waited 6.5 seconds!
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
# GOOD: Return fast, process later
|
|
192
|
+
route('/orders', async (req) => {
|
|
193
|
+
const order = await createOrder(req.body)
|
|
194
|
+
await queue.add('order.process', { orderId: order.id })
|
|
195
|
+
return order # User waited 200ms
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
# Background worker handles the rest
|
|
199
|
+
worker.process('order.process', async (job) => {
|
|
200
|
+
const order = await OrderRepository.find(job.orderId)
|
|
201
|
+
await generateInvoicePDF(order)
|
|
202
|
+
await sendEmail(order)
|
|
203
|
+
await notifyWarehouse(order)
|
|
204
|
+
await updateAnalytics(order)
|
|
205
|
+
})
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### 5. Don't Trust Anyone
|
|
211
|
+
|
|
212
|
+
**Law**: Every input is potentially malicious or malformed. Validate at boundaries.
|
|
213
|
+
|
|
214
|
+
**Why**: Security breaches, data corruption, system crashes.
|
|
215
|
+
|
|
216
|
+
**Patterns derived**:
|
|
217
|
+
|
|
218
|
+
| Pattern | What it Protects |
|
|
219
|
+
|---------|------------------|
|
|
220
|
+
| Input Validation | Data integrity |
|
|
221
|
+
| Authentication | Identity verification |
|
|
222
|
+
| Authorization | Access control |
|
|
223
|
+
| Rate Limiting | Resource protection |
|
|
224
|
+
| Sanitization | Injection prevention |
|
|
225
|
+
|
|
226
|
+
**Recognition signals**:
|
|
227
|
+
- User input used directly in queries
|
|
228
|
+
- No authentication on endpoints
|
|
229
|
+
- Missing role checks
|
|
230
|
+
- No request size limits
|
|
231
|
+
- Error messages expose internals
|
|
232
|
+
|
|
233
|
+
**Validation layers**:
|
|
234
|
+
```
|
|
235
|
+
Request arrives
|
|
236
|
+
↓
|
|
237
|
+
[1. Rate Limit] → Too many? Reject 429
|
|
238
|
+
↓
|
|
239
|
+
[2. Authentication] → Who is this? Reject 401 if unknown
|
|
240
|
+
↓
|
|
241
|
+
[3. Authorization] → Can they do this? Reject 403 if not
|
|
242
|
+
↓
|
|
243
|
+
[4. Input Validation] → Is data valid? Reject 400 if not
|
|
244
|
+
↓
|
|
245
|
+
[5. Business Rules] → Is action allowed? Reject 422 if not
|
|
246
|
+
↓
|
|
247
|
+
Process request
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
### 6. Plan for Failure
|
|
253
|
+
|
|
254
|
+
**Law**: Everything will fail eventually. Design for it.
|
|
255
|
+
|
|
256
|
+
**Why**: Network fails, services go down, databases crash, disks fill up.
|
|
257
|
+
|
|
258
|
+
**Patterns derived**:
|
|
259
|
+
|
|
260
|
+
| Pattern | Failure it Handles |
|
|
261
|
+
|---------|-------------------|
|
|
262
|
+
| Circuit Breaker | External service down |
|
|
263
|
+
| Retry with Backoff | Temporary failures |
|
|
264
|
+
| Timeout | Hung connections |
|
|
265
|
+
| Fallback | Degraded operation |
|
|
266
|
+
| Dead Letter Queue | Unprocessable messages |
|
|
267
|
+
| Idempotency | Duplicate requests |
|
|
268
|
+
|
|
269
|
+
**Recognition signals**:
|
|
270
|
+
- No try/catch around external calls
|
|
271
|
+
- No timeout on HTTP requests
|
|
272
|
+
- Retrying without backoff (hammering)
|
|
273
|
+
- No fallback when service unavailable
|
|
274
|
+
- Duplicate orders when user clicks twice
|
|
275
|
+
|
|
276
|
+
**Structure example**:
|
|
277
|
+
```
|
|
278
|
+
# BAD: Assumes success
|
|
279
|
+
const payment = await paymentService.charge(order)
|
|
280
|
+
|
|
281
|
+
# GOOD: Plans for failure
|
|
282
|
+
const payment = await circuitBreaker.call(
|
|
283
|
+
() => paymentService.charge(order),
|
|
284
|
+
{
|
|
285
|
+
timeout: 5000,
|
|
286
|
+
retry: { attempts: 3, backoff: 'exponential' },
|
|
287
|
+
fallback: () => {
|
|
288
|
+
queue.add('payment.retry', { orderId: order.id })
|
|
289
|
+
return { status: 'pending', message: 'Processing...' }
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Idempotency example**:
|
|
296
|
+
```
|
|
297
|
+
# Problem: User clicks "Pay" twice, charged twice
|
|
298
|
+
|
|
299
|
+
# Solution: Idempotency key
|
|
300
|
+
route('/payments', async (req) => {
|
|
301
|
+
const existingPayment = await PaymentRepository.findByIdempotencyKey(
|
|
302
|
+
req.headers['idempotency-key']
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
if (existingPayment) {
|
|
306
|
+
return existingPayment # Return same result, don't process again
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const payment = await processPayment(req.body)
|
|
310
|
+
payment.idempotencyKey = req.headers['idempotency-key']
|
|
311
|
+
await PaymentRepository.save(payment)
|
|
312
|
+
return payment
|
|
313
|
+
})
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### 7. Stateless Design
|
|
319
|
+
|
|
320
|
+
**Law**: Server should not remember anything between requests (store state externally).
|
|
321
|
+
|
|
322
|
+
**Why**: Enables horizontal scaling, survives server restarts, simplifies deployment.
|
|
323
|
+
|
|
324
|
+
**Patterns derived**:
|
|
325
|
+
|
|
326
|
+
| Pattern | State it Externalizes |
|
|
327
|
+
|---------|----------------------|
|
|
328
|
+
| JWT Tokens | Session data in token |
|
|
329
|
+
| External Session Store | Session data in Redis |
|
|
330
|
+
| Database | All persistent data |
|
|
331
|
+
| Shared Cache | Computed/temporary data |
|
|
332
|
+
| Object Storage | Files and uploads |
|
|
333
|
+
|
|
334
|
+
**Recognition signals**:
|
|
335
|
+
- Using server memory for sessions
|
|
336
|
+
- Files stored on local disk
|
|
337
|
+
- In-memory caches that miss after deploy
|
|
338
|
+
- "Works on one server, fails with two"
|
|
339
|
+
|
|
340
|
+
**Structure example**:
|
|
341
|
+
```
|
|
342
|
+
# BAD: Stateful (breaks with multiple servers)
|
|
343
|
+
const sessions = {} # In memory!
|
|
344
|
+
app.post('/login', (req) => {
|
|
345
|
+
sessions[userId] = { user, timestamp }
|
|
346
|
+
})
|
|
347
|
+
app.get('/me', (req) => {
|
|
348
|
+
return sessions[req.userId] # Other server doesn't have this!
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
# GOOD: Stateless (works with any number of servers)
|
|
352
|
+
app.post('/login', async (req) => {
|
|
353
|
+
const token = jwt.sign({ userId, role }) # State in token
|
|
354
|
+
await redis.set(`session:${userId}`, { lastLogin }) # State in Redis
|
|
355
|
+
return { token }
|
|
356
|
+
})
|
|
357
|
+
app.get('/me', async (req) => {
|
|
358
|
+
const payload = jwt.verify(req.token) # State from token
|
|
359
|
+
const session = await redis.get(`session:${payload.userId}`) # State from Redis
|
|
360
|
+
return { user: payload, session }
|
|
361
|
+
})
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Pattern Decision Matrix
|
|
367
|
+
|
|
368
|
+
Quick reference for choosing patterns:
|
|
369
|
+
|
|
370
|
+
| Situation | Apply These Patterns |
|
|
371
|
+
|-----------|---------------------|
|
|
372
|
+
| Code is getting messy, hard to test | Service Layer + Repository + DI |
|
|
373
|
+
| Same logic in multiple places | Extract to Domain Model or Service |
|
|
374
|
+
| API is slow | Caching, Queue, Pagination |
|
|
375
|
+
| High database load | Caching, Indexing, Read Replicas |
|
|
376
|
+
| External service unreliable | Circuit Breaker, Retry, Fallback |
|
|
377
|
+
| Need audit trail | Event Sourcing or Audit Log |
|
|
378
|
+
| Complex workflows | Saga, State Machine |
|
|
379
|
+
| Many services communicating | Event Bus, API Gateway |
|
|
380
|
+
| Users hitting API too hard | Rate Limiting, Throttling |
|
|
381
|
+
| File uploads | Object Storage, Signed URLs |
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Architecture Layers
|
|
386
|
+
|
|
387
|
+
Standard backend structure:
|
|
388
|
+
|
|
389
|
+
```
|
|
390
|
+
┌─────────────────────────────────────────────┐
|
|
391
|
+
│ HTTP Layer (Routes/Controllers) │
|
|
392
|
+
│ - Parse request │
|
|
393
|
+
│ - Call service │
|
|
394
|
+
│ - Format response │
|
|
395
|
+
├─────────────────────────────────────────────┤
|
|
396
|
+
│ Service Layer │
|
|
397
|
+
│ - Business logic │
|
|
398
|
+
│ - Orchestrate operations │
|
|
399
|
+
│ - Emit events │
|
|
400
|
+
├─────────────────────────────────────────────┤
|
|
401
|
+
│ Domain Layer (Models/Entities) │
|
|
402
|
+
│ - Business rules │
|
|
403
|
+
│ - Validation │
|
|
404
|
+
│ - State transitions │
|
|
405
|
+
├─────────────────────────────────────────────┤
|
|
406
|
+
│ Repository Layer │
|
|
407
|
+
│ - Data access │
|
|
408
|
+
│ - Query building │
|
|
409
|
+
│ - Caching │
|
|
410
|
+
├─────────────────────────────────────────────┤
|
|
411
|
+
│ Infrastructure (Database, Queue, Cache) │
|
|
412
|
+
└─────────────────────────────────────────────┘
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
**Rule**: Upper layers can call lower layers. Never the reverse.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## Checklist Before Implementation
|
|
420
|
+
|
|
421
|
+
- [ ] Which principle applies to this feature?
|
|
422
|
+
- [ ] What patterns does that principle suggest?
|
|
423
|
+
- [ ] Is there existing similar code to follow?
|
|
424
|
+
- [ ] Where does validation happen?
|
|
425
|
+
- [ ] What if this fails?
|
|
426
|
+
- [ ] What if 1000 users do this at once?
|
|
427
|
+
- [ ] Does this need to be synchronous?
|
|
428
|
+
- [ ] What state needs to be stored?
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dev-coding-frontend
|
|
3
3
|
description: Frontend implementation patterns and workflows
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# /dev-coding-frontend - Frontend Implementation
|
|
@@ -12,6 +12,22 @@ version: 2.0.0
|
|
|
12
12
|
|
|
13
13
|
Frontend-specific workflow for UI components, pages, and client-side logic.
|
|
14
14
|
|
|
15
|
+
## Fundamentals (MUST READ FIRST)
|
|
16
|
+
|
|
17
|
+
**Before implementing, understand the principles:**
|
|
18
|
+
|
|
19
|
+
→ Read `references/fundamentals.md`
|
|
20
|
+
|
|
21
|
+
This covers:
|
|
22
|
+
- **Core Mindset**: "Communicator with humans - clear, responsive, consistent"
|
|
23
|
+
- **6 Principles**: Always Communicate, Feel Instant, Stay Consistent, Work for Everyone, Single Source of Truth, Minimize Complexity
|
|
24
|
+
- **Pattern Recognition**: When to use Loading States, Optimistic UI, State Management, Lazy Loading, etc.
|
|
25
|
+
- **UI States**: Every component must handle loading, error, empty, success
|
|
26
|
+
|
|
27
|
+
**Key Decision**: For each piece of code, ask "which principle applies?" Then choose the pattern that principle suggests.
|
|
28
|
+
|
|
29
|
+
**CRITICAL - Consistency**: Before writing ANY code, check existing codebase for naming conventions, file structure, component patterns, and styling approach. Match them exactly.
|
|
30
|
+
|
|
15
31
|
## Knowledge Loading (CRITICAL)
|
|
16
32
|
|
|
17
33
|
Before implementing, load relevant knowledge:
|