@rune-kit/rune 2.3.1 → 2.3.3

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/README.md CHANGED
@@ -32,7 +32,7 @@ Mesh: A ↔ B ↔ C (B fails = A reaches C via D→E)
32
32
  D ↔ E ↔ F
33
33
  ```
34
34
 
35
- ## What's New (v2.3.1)
35
+ ## What's New (v2.3.3)
36
36
 
37
37
  - **UI/UX Pro Max Integration** — 161 palettes, 84 styles, 73 font pairings, 161 reasoning rules from [UI/UX Pro Max](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill) (MIT, 42.8k★) meshed into `design` skill + `@rune/ui` pack
38
38
  - **11 Core Skill Enrichments** — deviation rules, repair operators, evidence quality gate, decision classification, debug knowledge base, CSO discipline, YAGNI pushback, formal pause/resume
package/docs/index.html CHANGED
@@ -62,7 +62,7 @@
62
62
  <canvas id="mesh-canvas"></canvas>
63
63
  </div>
64
64
  <div class="hero-content">
65
- <p class="hero-badge">v2.3.1 &mdash; 59 skills &bull; 8 platforms &bull; MIT</p>
65
+ <p class="hero-badge">v2.3.3 &mdash; 59 skills &bull; 8 platforms &bull; MIT</p>
66
66
  <h1>Less skills.<br><span class="accent">Deeper connections.</span></h1>
67
67
  <p class="hero-sub">A mesh ecosystem for AI coding assistants. Skills call each other bidirectionally, forming resilient workflows that adapt when things go wrong.</p>
68
68
  <div class="hero-actions">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rune-kit/rune",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "59-skill mesh for AI coding assistants — 5-layer architecture, 200+ connections, 8 platforms (Claude Code, Cursor, Windsurf, Antigravity, Codex, OpenCode, OpenClaw, Generic)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -3,7 +3,7 @@ name: db
3
3
  description: Database workflow specialist. Generates migration files with rollback scripts, detects breaking schema changes, and validates query parameterization.
4
4
  metadata:
5
5
  author: runedev
6
- version: "0.1.0"
6
+ version: "0.2.0"
7
7
  layer: L2
8
8
  model: sonnet
9
9
  group: development
@@ -35,6 +35,10 @@ Database workflow specialist. Handles the parts of database work that cause prod
35
35
  - `deploy` (L2): pre-deploy migration safety check
36
36
  - `audit` (L2): database health dimension
37
37
 
38
+ ## References
39
+
40
+ - `references/scaling-reference.md` — Index strategies, query optimization, N+1 prevention, connection pooling, read replicas, partitioning, sharding, denormalization. Load when scaling, performance, or indexing context detected.
41
+
38
42
  ## Executable Steps
39
43
 
40
44
  ### Step 1 — Discovery
@@ -0,0 +1,271 @@
1
+ # Database Scaling Reference
2
+
3
+ > Loaded by `db` skill when scaling, indexing, or performance optimization context is detected.
4
+ > Source patterns: production-proven PostgreSQL scaling strategies.
5
+
6
+ ---
7
+
8
+ ## Indexing Strategy
9
+
10
+ ### Index Type Selection
11
+
12
+ | Type | Use Case | Example |
13
+ |------|----------|---------|
14
+ | **B-tree** (default) | Equality, range, sorting | `WHERE id = 1`, `ORDER BY date` |
15
+ | **GIN** | Arrays, JSONB, full-text search | `WHERE tags @> ARRAY['a']` |
16
+ | **GiST** | Geometric, spatial, nearest-neighbor | PostGIS, `ORDER BY location <->` |
17
+ | **BRIN** | Large tables with natural ordering | Time-series > 100GB |
18
+
19
+ ### Compound Index Rules
20
+
21
+ Order columns: **equality → range → sort**
22
+
23
+ ```sql
24
+ -- Query: WHERE customer_id = X AND status IN (...) AND created_at > Y ORDER BY id
25
+ CREATE INDEX idx_orders ON orders(customer_id, status, created_at, id);
26
+ ```
27
+
28
+ ### Partial Indexes (index what you query)
29
+
30
+ ```sql
31
+ -- Only index active users (90% smaller, 90% faster writes)
32
+ CREATE INDEX idx_active_users ON users(email) WHERE status = 'active';
33
+
34
+ -- Only index pending orders
35
+ CREATE INDEX idx_pending_orders ON orders(customer_id) WHERE status = 'pending';
36
+ ```
37
+
38
+ ### Covering Indexes (avoid heap lookups)
39
+
40
+ ```sql
41
+ -- Query only needs total and date — include them in index
42
+ CREATE INDEX idx_orders_covering ON orders(customer_id)
43
+ INCLUDE (total, created_at);
44
+
45
+ -- Index-only scan — no heap access needed
46
+ SELECT total, created_at FROM orders WHERE customer_id = 123;
47
+ ```
48
+
49
+ ### Index Anti-Patterns
50
+
51
+ - Indexing every column (slows writes, wastes storage)
52
+ - Indexing low-cardinality columns alone (status with 3 values → useless)
53
+ - Missing indexes on foreign keys (kills JOIN performance)
54
+ - Unused indexes (check `pg_stat_user_indexes` for `idx_scan = 0`)
55
+
56
+ ---
57
+
58
+ ## Query Optimization
59
+
60
+ ### EXPLAIN ANALYZE — Always Profile
61
+
62
+ ```sql
63
+ EXPLAIN (ANALYZE, BUFFERS, TIMING ON)
64
+ SELECT * FROM orders WHERE customer_id = 123 AND created_at > NOW() - INTERVAL '30d';
65
+ ```
66
+
67
+ **Red flags in output:**
68
+ - `Seq Scan` on large table → missing index
69
+ - `Filter` removes most rows → index should be more selective
70
+ - `Sort` with high cost → add index that matches ORDER BY
71
+ - `Nested Loop` with large outer table → consider hash/merge join
72
+
73
+ ### pg_stat_statements — Find Problem Queries
74
+
75
+ ```sql
76
+ -- Top 10 slowest queries by total time
77
+ SELECT query, calls, total_exec_time / 1000 AS total_sec,
78
+ mean_exec_time AS avg_ms,
79
+ 100.0 * shared_blks_hit / NULLIF(shared_blks_hit + shared_blks_read, 0) AS cache_pct
80
+ FROM pg_stat_statements
81
+ ORDER BY total_exec_time DESC LIMIT 10;
82
+
83
+ -- N+1 detector: queries called many times with low individual cost
84
+ SELECT query, calls, mean_exec_time AS avg_ms
85
+ FROM pg_stat_statements
86
+ WHERE calls > 1000 AND mean_exec_time < 5
87
+ ORDER BY calls DESC LIMIT 10;
88
+ ```
89
+
90
+ ---
91
+
92
+ ## N+1 Query Prevention
93
+
94
+ ### Prisma
95
+
96
+ ```typescript
97
+ // BAD: 1 + N queries
98
+ const users = await prisma.user.findMany();
99
+ for (const u of users) {
100
+ u.posts = await prisma.post.findMany({ where: { authorId: u.id } });
101
+ }
102
+
103
+ // GOOD: 2 queries (parallel fetch)
104
+ const users = await prisma.user.findMany({ include: { posts: true } });
105
+
106
+ // GOOD: Single query (database JOIN)
107
+ const users = await prisma.user.findMany({
108
+ relationLoadStrategy: 'join',
109
+ include: { posts: { select: { id: true, title: true } } }
110
+ });
111
+ ```
112
+
113
+ ### Drizzle (no N+1 by design)
114
+
115
+ ```typescript
116
+ const results = await db.select().from(users)
117
+ .leftJoin(posts, eq(users.id, posts.userId));
118
+ ```
119
+
120
+ ### Detection
121
+
122
+ Enable query logging — look for **query count = 1 + N** where N = row count.
123
+
124
+ ```typescript
125
+ // Prisma query logging
126
+ const prisma = new PrismaClient({ log: [{ emit: 'event', level: 'query' }] });
127
+ prisma.$on('query', (e) => {
128
+ if (e.duration > 100) console.warn(`SLOW: ${e.duration}ms — ${e.query}`);
129
+ });
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Connection Pooling
135
+
136
+ ### Sizing Formula
137
+
138
+ ```
139
+ pool_size = (CPU cores × 2) + effective_spindle_count
140
+
141
+ 4-core → 9 connections
142
+ 8-core → 17 connections
143
+ 16-core → 33 connections
144
+ ```
145
+
146
+ ### PgBouncer Configuration
147
+
148
+ ```ini
149
+ [pgbouncer]
150
+ pool_mode = transaction # Release after each transaction
151
+ default_pool_size = 25 # Per database/user pair
152
+ min_pool_size = 10 # Keep warm
153
+ reserve_pool_size = 5 # Overflow buffer
154
+ max_client_connections = 1000 # Total client limit
155
+ server_idle_timeout = 600 # Close idle server connections (10min)
156
+ query_wait_timeout = 120 # Max wait for available connection
157
+ ```
158
+
159
+ **Warning signs:** Pool utilization > 80%, rising wait times, connection timeouts.
160
+
161
+ ---
162
+
163
+ ## Read Replicas
164
+
165
+ ### When to Add
166
+
167
+ - Read:write ratio exceeds **10:1**
168
+ - Primary CPU consistently > 70% from read queries
169
+ - Analytics queries competing with transactional reads
170
+
171
+ ### Routing Pattern
172
+
173
+ ```typescript
174
+ const primaryPool = new Pool({ host: 'primary.db.com' });
175
+ const replicaPool = new Pool({ host: 'replica.db.com' });
176
+
177
+ async function query(sql: string, params: unknown[], opts?: { write?: boolean }) {
178
+ const pool = opts?.write ? primaryPool : replicaPool;
179
+ return pool.query(sql, params);
180
+ }
181
+ ```
182
+
183
+ ### Replication Lag
184
+
185
+ - Typical: 5-50ms for well-tuned async replication
186
+ - **Read-your-writes consistency**: After a write, read from primary for that user's session
187
+ - **Analytics queries**: Always safe on replicas (stale data acceptable)
188
+
189
+ ---
190
+
191
+ ## Partitioning
192
+
193
+ ### When to Partition
194
+
195
+ - Table exceeds **100GB** or **100M+ rows**
196
+ - Queries always filter on a specific column (date, tenant)
197
+ - Need fast deletion of old data (`DROP` partition vs `DELETE`)
198
+
199
+ ### Range Partitioning (time-series)
200
+
201
+ ```sql
202
+ CREATE TABLE events (
203
+ id BIGSERIAL, created_at TIMESTAMPTZ NOT NULL, data JSONB
204
+ ) PARTITION BY RANGE (created_at);
205
+
206
+ CREATE TABLE events_2025_01 PARTITION OF events
207
+ FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');
208
+
209
+ -- Delete old data instantly
210
+ DROP TABLE events_2024_01; -- 0.01s vs DELETE minutes
211
+ ```
212
+
213
+ ### Hash Partitioning (even distribution)
214
+
215
+ ```sql
216
+ CREATE TABLE orders (id BIGSERIAL, customer_id INT, data JSONB)
217
+ PARTITION BY HASH (customer_id);
218
+
219
+ CREATE TABLE orders_0 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 0);
220
+ CREATE TABLE orders_1 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 1);
221
+ ```
222
+
223
+ **Rule:** Keep partition count under 500 — query planning overhead grows with partition count.
224
+
225
+ ---
226
+
227
+ ## Sharding Decision Matrix
228
+
229
+ ### When to Shard (Last Resort)
230
+
231
+ | Strategy | Pros | Cons |
232
+ |----------|------|------|
233
+ | **Hash-based** | Even distribution | No range queries on shard key |
234
+ | **Range-based** | Range queries work | Hot shards if distribution skewed |
235
+ | **Tenant-based** | Strong isolation | Uneven if tenants vary in size |
236
+
237
+ ### Before Sharding, Try These First
238
+
239
+ 1. Add proper indexes
240
+ 2. Fix N+1 queries
241
+ 3. Add read replicas
242
+ 4. Add caching layer
243
+ 5. Partition large tables
244
+ 6. Vertical scaling (bigger instance)
245
+ 7. Archive old data
246
+ 8. Optimize queries with EXPLAIN ANALYZE
247
+
248
+ ---
249
+
250
+ ## Denormalization Decision Matrix
251
+
252
+ | Scenario | Keep Normalized | Denormalize |
253
+ |----------|----------------|-------------|
254
+ | High write volume | Yes | No |
255
+ | High read volume, slow joins | No | Yes |
256
+ | Data consistency critical | Yes | No |
257
+ | Analytics / reporting | No | Yes (materialized views) |
258
+
259
+ ### Materialized Views
260
+
261
+ ```sql
262
+ CREATE MATERIALIZED VIEW order_stats AS
263
+ SELECT customer_id, COUNT(*) AS order_count, SUM(total) AS total_spent
264
+ FROM orders GROUP BY customer_id;
265
+
266
+ -- Refresh periodically (CONCURRENTLY allows reads during refresh)
267
+ REFRESH MATERIALIZED VIEW CONCURRENTLY order_stats;
268
+ CREATE UNIQUE INDEX ON order_stats(customer_id);
269
+ ```
270
+
271
+ **Rule:** Start normalized. Denormalize specific queries only when EXPLAIN shows expensive joins that caching can't solve.
@@ -3,7 +3,7 @@ name: perf
3
3
  description: Performance regression gate. Detects N+1 queries, sync-in-async, missing indexes, memory leaks, and bundle bloat before they reach production.
4
4
  metadata:
5
5
  author: runedev
6
- version: "0.1.0"
6
+ version: "0.2.0"
7
7
  layer: L2
8
8
  model: sonnet
9
9
  group: quality
@@ -38,6 +38,11 @@ Performance regression gate. Analyzes code changes for patterns that cause measu
38
38
  - `review` (L2): performance patterns detected in diff
39
39
  - `deploy` (L2): pre-deploy perf regression check
40
40
 
41
+ ## References
42
+
43
+ - `references/cost-reference.md` — Cost priority hierarchy, quick wins checklist, instance right-sizing, data transfer traps, serverless optimization, observability cost control, managed vs self-hosted matrix, unit economics tracking. Load when cost analysis or FinOps context detected.
44
+ - `references/scalability-reference.md` — Bottleneck identification flow, performance thresholds, API patterns (cursor pagination, rate limiting, circuit breaker, graceful shutdown), caching strategies, queue-based load leveling, concurrency patterns, K8s HPA, CDN headers, load testing. Load when scaling or infrastructure optimization context detected.
45
+
41
46
  ## Executable Steps
42
47
 
43
48
  ### Step 1 — Scope
@@ -0,0 +1,205 @@
1
+ # Cost Optimization Reference
2
+
3
+ > Loaded by `perf` skill when cost analysis, cloud spending, or FinOps context is detected.
4
+ > Patterns: production-proven cost reduction strategies with dollar-impact estimates.
5
+
6
+ ---
7
+
8
+ ## Cost Priority Hierarchy
9
+
10
+ Optimize in this order — higher tiers save 10x more than lower:
11
+
12
+ ```
13
+ 1. Architecture choices (10x impact — monolith vs micro, serverless vs containers)
14
+ 2. Data transfer (NAT Gateway, cross-region, CDN vs origin)
15
+ 3. Compute right-sizing (instance types, spot/reserved, autoscaling)
16
+ 4. Database optimization (query tuning, connection pooling, read replicas)
17
+ 5. Caching layer (Redis, CDN, in-memory — ROI depends on hit rate)
18
+ 6. Storage tiering (S3 lifecycle, cold storage, cleanup)
19
+ 7. Bundle/asset size (tree-shaking, image optimization, compression)
20
+ 8. Observability costs (log sampling, trace sampling, retention)
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Quick Wins Checklist
26
+
27
+ | Fix | Typical Savings | Effort |
28
+ |-----|----------------|--------|
29
+ | S3 Intelligent-Tiering on infrequent buckets | 40-70% storage | 5 min |
30
+ | Fix N+1 queries (Prisma `include`) | 10-100x query reduction | 30 min |
31
+ | WebP/AVIF images (Sharp pipeline) | 25-80% bandwidth | 1 hr |
32
+ | Add CDN for static assets | 50-90% origin traffic | 1 hr |
33
+ | NAT Gateway → VPC endpoints for AWS services | $30-100/mo per service | 30 min |
34
+ | Log sampling (10% INFO, 100% ERROR) | 50-80% observability bill | 30 min |
35
+ | Gzip/Brotli response compression | 70-90% transfer size | 15 min |
36
+ | Lambda memory right-sizing (power tuning) | 10-40% Lambda cost | 1 hr |
37
+
38
+ ---
39
+
40
+ ## Instance Right-Sizing
41
+
42
+ ### AWS EC2 Strategy
43
+
44
+ | Strategy | Savings | Commitment |
45
+ |----------|---------|-----------|
46
+ | On-Demand | Baseline | None |
47
+ | Spot Instances | 60-90% | Can be interrupted |
48
+ | Reserved (1-yr) | ~40% | 1 year |
49
+ | Reserved (3-yr) | ~60% | 3 years |
50
+ | Savings Plans | ~30-40% | Flexible commitment |
51
+
52
+ ### Kubernetes Right-Sizing
53
+
54
+ ```yaml
55
+ # Set requests = actual P95 usage, limits = 2x requests
56
+ resources:
57
+ requests:
58
+ cpu: "250m" # Based on actual P95 CPU usage
59
+ memory: "256Mi" # Based on actual P95 memory
60
+ limits:
61
+ cpu: "500m"
62
+ memory: "512Mi"
63
+ ```
64
+
65
+ Check actual usage: `kubectl top pods --sort-by=cpu`
66
+
67
+ ---
68
+
69
+ ## Data Transfer Cost Traps
70
+
71
+ ### NAT Gateway Problem
72
+
73
+ NAT Gateway: **$0.045/GB + $0.045/hr** — one of the most expensive AWS surprises.
74
+
75
+ **Fix:** Replace with VPC endpoints for AWS services:
76
+ ```
77
+ S3 Gateway Endpoint → Free (gateway type)
78
+ DynamoDB Gateway Endpoint → Free (gateway type)
79
+ SQS/SNS Interface Endpoint → $0.01/hr (still 4x cheaper than NAT)
80
+ ```
81
+
82
+ ### Cross-Region Transfer
83
+
84
+ - Same region, same AZ: **Free**
85
+ - Same region, different AZ: **$0.01/GB**
86
+ - Cross-region: **$0.02/GB**
87
+ - Internet egress: **$0.09/GB** (first 10TB)
88
+
89
+ **Rule:** Keep services in the same AZ when possible. Use CloudFront for global distribution.
90
+
91
+ ---
92
+
93
+ ## Serverless Optimization
94
+
95
+ ### Lambda Memory Tuning
96
+
97
+ Lambda CPU scales linearly with memory. Sometimes MORE memory = CHEAPER (faster execution):
98
+
99
+ ```
100
+ 128MB, 3000ms = 375,000 GB-ms = $0.00000625
101
+ 512MB, 800ms = 400,000 GB-ms = $0.00000667 (similar cost, 4x faster)
102
+ 1024MB, 400ms = 400,000 GB-ms = $0.00000667 (same cost, 7.5x faster)
103
+ ```
104
+
105
+ Use [AWS Lambda Power Tuning](https://github.com/alexcasalboni/aws-lambda-power-tuning) to find optimal memory.
106
+
107
+ ### Cold Start Reduction
108
+
109
+ | Technique | Impact |
110
+ |-----------|--------|
111
+ | Smaller deployment package | -100-500ms |
112
+ | Use Graviton (arm64) | -200ms + 20% cheaper |
113
+ | Provisioned concurrency | Eliminates cold starts |
114
+ | Lazy-load heavy SDKs | -200-1000ms |
115
+ | Use ESM instead of CJS | -100-300ms (Node.js) |
116
+
117
+ ---
118
+
119
+ ## Observability Cost Control
120
+
121
+ ### Log Sampling
122
+
123
+ ```typescript
124
+ // Sample 10% of INFO logs, keep 100% of errors
125
+ const shouldLog = (level: string): boolean => {
126
+ if (level === 'error' || level === 'warn') return true;
127
+ return Math.random() < 0.1; // 10% sampling
128
+ };
129
+ ```
130
+
131
+ ### Trace Sampling
132
+
133
+ ```typescript
134
+ // 100% errors and slow requests, 10% normal
135
+ const shouldTrace = (duration: number, isError: boolean): boolean => {
136
+ if (isError) return true;
137
+ if (duration > 1000) return true; // Slow requests
138
+ return Math.random() < 0.1;
139
+ };
140
+ ```
141
+
142
+ ### High-Cardinality Metrics — NEVER DO
143
+
144
+ ```typescript
145
+ // BAD: Creates millions of unique time series
146
+ metrics.counter('requests', { userId: req.userId }); // ← kills Datadog bill
147
+
148
+ // GOOD: Low-cardinality labels only
149
+ metrics.counter('requests', { endpoint: '/api/users', method: 'GET', status: '200' });
150
+ ```
151
+
152
+ ### Retention Policies
153
+
154
+ | Data Type | Recommended Retention |
155
+ |-----------|----------------------|
156
+ | Raw logs | 7-14 days |
157
+ | Aggregated metrics | 90 days |
158
+ | Error logs | 30-90 days |
159
+ | Traces | 7 days |
160
+ | Audit logs | 1-7 years (compliance) |
161
+
162
+ ---
163
+
164
+ ## Managed vs Self-Hosted Decision Matrix
165
+
166
+ | Service | Self-Host When | Stay Managed When |
167
+ |---------|---------------|-------------------|
168
+ | Auth | >200K MAU ($4K+/mo managed) | <200K MAU or need compliance |
169
+ | Search | >500K records or >$500/mo | <500K records, need instant setup |
170
+ | Database | >$500/mo RDS bill | Need HA, backups, patching handled |
171
+ | Email | Almost never | Always (deliverability is hard) |
172
+ | Monitoring | >$1K/mo Datadog | Need APM + distributed tracing |
173
+
174
+ ---
175
+
176
+ ## Unit Economics Tracking
177
+
178
+ ```typescript
179
+ // Track cost per unit to detect inefficiency trends
180
+ interface UnitEconomics {
181
+ costPerRequest: number; // Total infra / total requests
182
+ costPerUser: number; // Total infra / MAU
183
+ costPerTransaction: number; // Total infra / transactions
184
+ }
185
+
186
+ // Alert if unit cost increases >20% month-over-month
187
+ function checkCostTrend(current: number, previous: number): void {
188
+ const increase = (current - previous) / previous;
189
+ if (increase > 0.2) {
190
+ alert(`Unit cost increased ${(increase * 100).toFixed(0)}% — investigate`);
191
+ }
192
+ }
193
+ ```
194
+
195
+ ---
196
+
197
+ ## Cost Optimization Priority Matrix
198
+
199
+ | Effort | Low Savings (<$100/mo) | Med Savings ($100-500) | High Savings (>$500) |
200
+ |--------|----------------------|----------------------|---------------------|
201
+ | **Low** | Log retention | Image optimization | S3 tiering |
202
+ | **Medium** | Bundle analysis | Caching layer | Instance right-sizing |
203
+ | **High** | — | Query optimization | Architecture redesign |
204
+
205
+ **Rule:** Start top-right (high savings, low effort), work diagonally down-left.
@@ -0,0 +1,378 @@
1
+ # Scalability Reference
2
+
3
+ > Loaded by `perf` skill when scaling, load handling, or infrastructure optimization context is detected.
4
+ > Patterns: production-proven scalability strategies for Node.js/TypeScript applications.
5
+
6
+ ---
7
+
8
+ ## Bottleneck Identification Flow
9
+
10
+ Profile BEFORE optimizing. Follow this decision tree:
11
+
12
+ ```
13
+ Is database the bottleneck (>50% of response time)?
14
+ ├── YES → Index optimization, connection pooling, read replicas, query caching
15
+ │ See db/references/scaling-reference.md
16
+ └── NO
17
+ Is external API the bottleneck?
18
+ ├── YES → Circuit breaker, caching, parallel requests, queue background
19
+ └── NO
20
+ Is it CPU-bound?
21
+ ├── YES → Worker threads, horizontal scaling, algorithm optimization
22
+ └── NO
23
+ Is it memory pressure?
24
+ ├── YES → Leak detection, streaming, pagination, bounded caches
25
+ └── NO → Measure again with better instrumentation
26
+ ```
27
+
28
+ ## Performance Thresholds
29
+
30
+ | Metric | Healthy | Warning | Critical |
31
+ |--------|---------|---------|----------|
32
+ | p99 latency | <200ms | 200-500ms | >500ms |
33
+ | DB cache hit ratio | >95% | 90-95% | <90% |
34
+ | Connection pool utilization | <70% | 70-85% | >85% |
35
+ | CPU utilization | <60% | 60-80% | >80% |
36
+ | Memory utilization | <70% | 70-85% | >85% |
37
+ | Error rate | <0.1% | 0.1-1% | >1% |
38
+ | Queue depth | <100 | 100-1000 | >1000 |
39
+ | Queue wait time | <1s | 1-10s | >10s |
40
+
41
+ ---
42
+
43
+ ## API Scalability Patterns
44
+
45
+ ### Cursor-Based Pagination
46
+
47
+ Offset pagination breaks at scale (`OFFSET 100000` = scan 100K rows). Use cursor-based:
48
+
49
+ ```typescript
50
+ // Cursor-based — consistent performance at any depth
51
+ async function listOrders(cursor?: string, limit = 20) {
52
+ const where = cursor ? { id: { gt: cursor } } : {};
53
+ const items = await prisma.order.findMany({
54
+ where,
55
+ take: limit + 1, // Fetch one extra to detect hasMore
56
+ orderBy: { id: 'asc' },
57
+ });
58
+
59
+ const hasMore = items.length > limit;
60
+ const data = hasMore ? items.slice(0, -1) : items;
61
+
62
+ return {
63
+ data,
64
+ cursor: data.at(-1)?.id ?? null,
65
+ hasMore,
66
+ };
67
+ }
68
+ ```
69
+
70
+ ### Rate Limiting (Tiered)
71
+
72
+ ```typescript
73
+ const rateLimits = {
74
+ free: { requests: 100, window: '15m' },
75
+ pro: { requests: 1000, window: '15m' },
76
+ enterprise: { requests: 10000, window: '15m' },
77
+ };
78
+
79
+ // Response headers (always include)
80
+ // X-RateLimit-Limit: 1000
81
+ // X-RateLimit-Remaining: 847
82
+ // X-RateLimit-Reset: 1699234567
83
+ // Retry-After: 30 (only on 429)
84
+ ```
85
+
86
+ ### Circuit Breaker
87
+
88
+ ```typescript
89
+ import CircuitBreaker from 'opossum';
90
+
91
+ const breaker = new CircuitBreaker(callExternalAPI, {
92
+ timeout: 3000, // Fail if function takes > 3s
93
+ errorThresholdPercentage: 50, // Open if 50% fail
94
+ resetTimeout: 30000, // Try again after 30s
95
+ volumeThreshold: 10, // Min calls before tripping
96
+ });
97
+
98
+ breaker.fallback(() => cachedResponse);
99
+ breaker.on('open', () => logger.warn('Circuit breaker OPEN'));
100
+ ```
101
+
102
+ ### Graceful Shutdown
103
+
104
+ ```typescript
105
+ async function shutdown(signal: string) {
106
+ logger.info(`${signal} received — starting graceful shutdown`);
107
+
108
+ // 1. Stop accepting new connections
109
+ server.close();
110
+
111
+ // 2. Finish in-flight requests (with timeout)
112
+ await Promise.race([
113
+ finishInflightRequests(),
114
+ new Promise(resolve => setTimeout(resolve, 30000)),
115
+ ]);
116
+
117
+ // 3. Close DB connections
118
+ await prisma.$disconnect();
119
+ await redis.quit();
120
+
121
+ process.exit(0);
122
+ }
123
+
124
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
125
+ process.on('SIGINT', () => shutdown('SIGINT'));
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Caching Strategies
131
+
132
+ ### Strategy Selection
133
+
134
+ | Strategy | When to Use | Trade-off |
135
+ |----------|-------------|-----------|
136
+ | **Cache-aside** | Most common. App checks cache, falls back to DB | May serve stale data |
137
+ | **Write-through** | Cache updated on every write | Higher write latency |
138
+ | **Write-behind** | Cache updated async after write | Risk of data loss |
139
+ | **Read-through** | Cache auto-fetches on miss | Cache library dependency |
140
+
141
+ ### TTL Guidelines
142
+
143
+ | Data Type | TTL | Rationale |
144
+ |-----------|-----|-----------|
145
+ | Static config | 1 hour | Rarely changes |
146
+ | User profile | 5 min | Changes occasionally |
147
+ | Product catalog | 15 min | Balance freshness vs load |
148
+ | Session data | 30 min sliding | Security + UX |
149
+ | Rate limit counters | Match window | Exact timing matters |
150
+ | Search results | 60s | High-read, low-freshness need |
151
+
152
+ ### Cache Invalidation Patterns
153
+
154
+ ```typescript
155
+ // 1. TTL-based (simplest, eventual consistency)
156
+ await redis.setex(`user:${id}`, 300, JSON.stringify(user));
157
+
158
+ // 2. Explicit invalidation (strongest consistency)
159
+ await prisma.user.update({ where: { id }, data });
160
+ await redis.del(`user:${id}`);
161
+
162
+ // 3. Tag-based (invalidate groups)
163
+ await redis.sadd('tag:users', `user:${id}`, `user:${id}:posts`);
164
+ // On invalidate:
165
+ const keys = await redis.smembers('tag:users');
166
+ await redis.del(...keys);
167
+
168
+ // 4. Versioned keys (zero-downtime cache migration)
169
+ const version = 'v2';
170
+ await redis.setex(`user:${version}:${id}`, 300, data);
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Queue-Based Load Leveling
176
+
177
+ ### When to Use Queues
178
+
179
+ - Request takes > 500ms to process
180
+ - External API with rate limits
181
+ - Spiky traffic patterns
182
+ - Fire-and-forget operations (email, webhooks, analytics)
183
+
184
+ ### BullMQ Pattern
185
+
186
+ ```typescript
187
+ import { Queue, Worker } from 'bullmq';
188
+
189
+ const emailQueue = new Queue('emails', { connection: redis });
190
+
191
+ // Producer — returns immediately
192
+ await emailQueue.add('welcome', { userId, email }, {
193
+ attempts: 3,
194
+ backoff: { type: 'exponential', delay: 1000 },
195
+ removeOnComplete: 1000, // Keep last 1000 completed
196
+ removeOnFail: 5000, // Keep last 5000 failed
197
+ });
198
+
199
+ // Consumer — processes in background
200
+ const worker = new Worker('emails', async (job) => {
201
+ await sendEmail(job.data.email, 'Welcome!');
202
+ }, {
203
+ connection: redis,
204
+ concurrency: 5, // Process 5 emails in parallel
205
+ limiter: { max: 10, duration: 1000 }, // Rate limit: 10/sec
206
+ });
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Concurrency Patterns
212
+
213
+ ### Worker Threads (CPU-intensive)
214
+
215
+ ```typescript
216
+ import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
217
+
218
+ if (isMainThread) {
219
+ const worker = new Worker(__filename, { workerData: { input } });
220
+ worker.on('message', (result) => resolve(result));
221
+ worker.on('error', reject);
222
+ } else {
223
+ const result = heavyComputation(workerData.input);
224
+ parentPort?.postMessage(result);
225
+ }
226
+ ```
227
+
228
+ ### Backpressure (prevent OOM)
229
+
230
+ ```typescript
231
+ // Bounded queue — reject when full instead of consuming infinite memory
232
+ class BoundedQueue<T> {
233
+ private queue: T[] = [];
234
+ constructor(private maxSize: number) {}
235
+
236
+ enqueue(item: T): boolean {
237
+ if (this.queue.length >= this.maxSize) return false; // Apply backpressure
238
+ this.queue.push(item);
239
+ return true;
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### Semaphore (limit concurrent operations)
245
+
246
+ ```typescript
247
+ class Semaphore {
248
+ private current = 0;
249
+ private queue: (() => void)[] = [];
250
+
251
+ constructor(private max: number) {}
252
+
253
+ async acquire(): Promise<void> {
254
+ if (this.current < this.max) {
255
+ this.current++;
256
+ return;
257
+ }
258
+ return new Promise((resolve) => this.queue.push(resolve));
259
+ }
260
+
261
+ release(): void {
262
+ this.current--;
263
+ const next = this.queue.shift();
264
+ if (next) { this.current++; next(); }
265
+ }
266
+ }
267
+
268
+ // Usage: limit to 10 concurrent DB connections
269
+ const sem = new Semaphore(10);
270
+ await sem.acquire();
271
+ try { await db.query(sql); }
272
+ finally { sem.release(); }
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Deployment Scalability
278
+
279
+ ### Kubernetes HPA
280
+
281
+ ```yaml
282
+ apiVersion: autoscaling/v2
283
+ kind: HorizontalPodAutoscaler
284
+ metadata:
285
+ name: api-hpa
286
+ spec:
287
+ scaleTargetRef:
288
+ apiVersion: apps/v1
289
+ kind: Deployment
290
+ name: api
291
+ minReplicas: 2
292
+ maxReplicas: 20
293
+ metrics:
294
+ - type: Resource
295
+ resource:
296
+ name: cpu
297
+ target:
298
+ type: Utilization
299
+ averageUtilization: 70
300
+ behavior:
301
+ scaleUp:
302
+ stabilizationWindowSeconds: 60
303
+ scaleDown:
304
+ stabilizationWindowSeconds: 300 # Slow scale-down prevents flapping
305
+ ```
306
+
307
+ ### CDN Cache-Control Headers
308
+
309
+ ```
310
+ # Immutable assets (hashed filenames)
311
+ Cache-Control: public, max-age=31536000, immutable
312
+
313
+ # API responses (short cache + revalidation)
314
+ Cache-Control: public, max-age=60, stale-while-revalidate=30
315
+
316
+ # Private user data
317
+ Cache-Control: private, no-store
318
+
319
+ # HTML pages (revalidate every time)
320
+ Cache-Control: no-cache
321
+ ```
322
+
323
+ ### Zero-Downtime Database Migrations
324
+
325
+ 3-phase safe migration pattern:
326
+
327
+ ```
328
+ Phase 1: ADD new column (nullable) → deploy
329
+ Phase 2: Deploy code that writes to BOTH old + new columns → backfill
330
+ Phase 3: Drop old column → deploy
331
+
332
+ NEVER in one step:
333
+ - Rename column (breaks running code)
334
+ - Change type (data loss risk)
335
+ - Add NOT NULL without default (fails on existing rows)
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Load Testing
341
+
342
+ ### k6 Quick Start
343
+
344
+ ```javascript
345
+ import http from 'k6/http';
346
+ import { check, sleep } from 'k6';
347
+
348
+ export const options = {
349
+ stages: [
350
+ { duration: '1m', target: 50 }, // Ramp up
351
+ { duration: '3m', target: 50 }, // Steady state
352
+ { duration: '1m', target: 0 }, // Ramp down
353
+ ],
354
+ thresholds: {
355
+ http_req_duration: ['p(99)<500'], // 99th percentile < 500ms
356
+ http_req_failed: ['rate<0.01'], // Error rate < 1%
357
+ },
358
+ };
359
+
360
+ export default function () {
361
+ const res = http.get('https://api.example.com/orders');
362
+ check(res, { 'status 200': (r) => r.status === 200 });
363
+ sleep(1);
364
+ }
365
+ ```
366
+
367
+ ### What to Measure
368
+
369
+ | Metric | Target | Why |
370
+ |--------|--------|-----|
371
+ | p50 latency | <100ms | Typical user experience |
372
+ | p99 latency | <500ms | Worst-case user experience |
373
+ | Throughput (RPS) | >baseline | Capacity headroom |
374
+ | Error rate | <0.1% | Reliability |
375
+ | CPU during load | <80% | Scaling headroom |
376
+ | Memory during load | <70% | Leak detection |
377
+
378
+ **Rule:** Always observe p99, not p50. Median latency hides tail latency that kills user experience.
@@ -3,7 +3,7 @@ name: skill-forge
3
3
  description: Use when creating new Rune skills, editing existing skills, or verifying skill quality before deployment. Applies TDD discipline to skill authoring — test before write, verify before ship.
4
4
  metadata:
5
5
  author: runedev
6
- version: "1.5.0"
6
+ version: "1.6.0"
7
7
  layer: L2
8
8
  model: opus
9
9
  group: creation
@@ -34,6 +34,10 @@ The skill that builds skills. Applies Test-Driven Development to skill authoring
34
34
 
35
35
  - `cook` (L1): when the feature being built IS a new skill
36
36
 
37
+ ## References
38
+
39
+ - `references/claude-skill-reference.md` — Claude Code skill system: frontmatter fields, variables, shell injection, invocation control matrix, skill type patterns (task/research/knowledge/dynamic), file structure, and quality checklist. Load when creating or editing any skill.
40
+
37
41
  ## Workflow
38
42
 
39
43
  ### Phase 1 — DISCOVER
@@ -0,0 +1,182 @@
1
+ # Claude Code Skill System Reference
2
+
3
+ > Loaded by `skill-forge` when creating or editing skills. Covers frontmatter fields, variables, shell injection, invocation control, and skill type patterns.
4
+
5
+ ---
6
+
7
+ ## Frontmatter Fields
8
+
9
+ ### Required
10
+
11
+ | Field | Type | Description |
12
+ |-------|------|-------------|
13
+ | `name` | string | Kebab-case identifier. Becomes the `/slash-command`. Must match directory name. |
14
+ | `description` | string | What the skill does. Claude uses this for auto-activation matching. Include action verbs and trigger phrases. |
15
+
16
+ ### Optional
17
+
18
+ | Field | Type | Default | Description |
19
+ |-------|------|---------|-------------|
20
+ | `argument-hint` | string | — | Shown in autocomplete after command name. Use `[brackets]`. |
21
+ | `user-invocable` | boolean | `true` | If `false`, no slash command — auto-activate only. |
22
+ | `auto-activate` | boolean | `true` | If `false`, slash command only — never auto-activates. |
23
+ | `allowed-tools` | string[] | all | Whitelist of tools the skill can use. |
24
+ | `disallowed-tools` | string[] | none | Blacklist of tools. |
25
+
26
+ ### Invocation Control Matrix
27
+
28
+ | `user-invocable` | `auto-activate` | Behavior |
29
+ |-------------------|-----------------|----------|
30
+ | `true` (default) | `true` (default) | Full access: slash command + auto-activates |
31
+ | `true` | `false` | Slash command only, never auto-activates |
32
+ | `false` | `true` | Auto-activate only, no slash command |
33
+ | `false` | `false` | Never runs — avoid this combination |
34
+
35
+ ---
36
+
37
+ ## Variables
38
+
39
+ Replaced at invocation time before Claude sees the content.
40
+
41
+ | Variable | Description |
42
+ |----------|-------------|
43
+ | `$ARGUMENTS` | Everything after `/command`. Empty if no arguments. |
44
+ | `$0` | Alias for `$ARGUMENTS` |
45
+ | `${CLAUDE_SKILL_DIR}` | Absolute path to skill directory. Use for referencing supporting files. |
46
+ | `${CLAUDE_SESSION_ID}` | Unique ID for current Claude Code session. |
47
+
48
+ **Usage in SKILL.md:**
49
+ ```markdown
50
+ The user wants: $ARGUMENTS
51
+ Read `${CLAUDE_SKILL_DIR}/reference.md` for details.
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Shell Injection
57
+
58
+ Embed live command output using `` !`command` `` syntax:
59
+
60
+ ```markdown
61
+ Current branch: !`git branch --show-current`
62
+ Node version: !`node --version`
63
+ Changed files: !`git diff main --name-only`
64
+ ```
65
+
66
+ **How it works:**
67
+ - Commands execute when skill activates (not at definition time)
68
+ - Output replaces the `` !`command` `` inline
69
+ - Commands run in current working directory
70
+ - Keep commands fast — slow commands delay skill activation
71
+ - Don't use for side effects — skill content is for context, not execution
72
+
73
+ ---
74
+
75
+ ## Skill Type Patterns
76
+
77
+ ### Task Skill (side effects)
78
+
79
+ Performs actions — deploy, commit, publish. Use `auto-activate: false` for destructive operations.
80
+
81
+ ```yaml
82
+ ---
83
+ name: deploy
84
+ description: Deploy application to production or staging. Use when user wants to deploy, ship, release.
85
+ argument-hint: [environment: staging|production]
86
+ auto-activate: false
87
+ ---
88
+ ```
89
+
90
+ ### Research Skill (information gathering)
91
+
92
+ Gathers and synthesizes information. Uses Agent subagents for parallel research.
93
+
94
+ ```yaml
95
+ ---
96
+ name: deep-research
97
+ description: Perform deep research on a topic using web search and analysis.
98
+ argument-hint: [topic or question to research]
99
+ ---
100
+ ```
101
+
102
+ ### Knowledge Skill (pure reference)
103
+
104
+ Provides reference context. Auto-activates when relevant, no slash command needed.
105
+
106
+ ```yaml
107
+ ---
108
+ name: api-conventions
109
+ description: API design conventions for this project. Use when writing API endpoints or reviewing API code.
110
+ user-invocable: false
111
+ ---
112
+ ```
113
+
114
+ ### Dynamic Context Skill (live state)
115
+
116
+ Uses shell injection to inject current project state.
117
+
118
+ ```markdown
119
+ Branch: !`git branch --show-current`
120
+ Changed files: !`git diff main --name-only`
121
+ ```
122
+
123
+ ---
124
+
125
+ ## File Structure & Loading
126
+
127
+ ```
128
+ skills/my-skill/
129
+ ├── SKILL.md # Required — loaded on activation
130
+ ├── reference.md # Optional — read on-demand via ${CLAUDE_SKILL_DIR}
131
+ ├── examples.md # Optional — read on-demand
132
+ └── scripts/ # Optional — bundled scripts, never auto-loaded
133
+ ```
134
+
135
+ **Loading behavior:**
136
+ - **SKILL.md**: Always loaded when skill activates
137
+ - **Supporting `.md` files**: NOT auto-loaded. Only read when SKILL.md references them via `${CLAUDE_SKILL_DIR}`
138
+ - **Scripts**: Available on disk, never auto-loaded
139
+
140
+ This means: keep SKILL.md focused (under 300 lines), put detailed references in separate files that load lazily.
141
+
142
+ ---
143
+
144
+ ## Skill Quality Checklist
145
+
146
+ 1. **Name**: kebab-case, matches directory name
147
+ 2. **Description**: includes trigger phrases Claude can match against
148
+ 3. **SKILL.md under 300 lines**: move details to reference files
149
+ 4. **Supporting files referenced via `${CLAUDE_SKILL_DIR}`**: never hardcode paths
150
+ 5. **`$ARGUMENTS` used for user input**: contains everything after slash command
151
+ 6. **One skill per concern**: don't bundle unrelated functionality
152
+ 7. **Templates are minimal**: show patterns, not complete applications
153
+ 8. **Tool restrictions only when safety-critical**: don't over-constrain
154
+
155
+ ---
156
+
157
+ ## Anti-Patterns
158
+
159
+ | Don't | Do Instead |
160
+ |-------|-----------|
161
+ | Giant monolith SKILL.md (>300 lines) | Split into supporting reference files |
162
+ | Vague description ("Helps with stuff") | Action-oriented with trigger phrases |
163
+ | Hardcoded paths to supporting files | Use `${CLAUDE_SKILL_DIR}` |
164
+ | Over-engineering frontmatter | Most skills only need name + description |
165
+ | Duplicating built-in Claude behavior | Only create skills for project-specific patterns |
166
+ | Missing argument-hint | Users won't know what to type after `/command` |
167
+
168
+ ---
169
+
170
+ ## Rune-Specific Conventions
171
+
172
+ When creating Rune skills (vs generic Claude Code skills):
173
+
174
+ | Field | Rune Convention |
175
+ |-------|----------------|
176
+ | Frontmatter | Add `metadata:` block with author, version, layer, model, group, tools |
177
+ | Layer | L0 (router), L1 (orchestrator), L2 (workflow), L3 (utility), L4 (extension pack) |
178
+ | Connections | Document `Calls` (outbound) and `Called By` (inbound) sections |
179
+ | Model | haiku (scan), sonnet (code), opus (architecture) |
180
+ | Version | semver — bump on enrichment |
181
+ | References | Store in `references/` subdirectory |
182
+ | Cross-references | Use `rune:skill-name` syntax |