@rune-kit/rune 2.1.1 → 2.2.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 (157) hide show
  1. package/README.md +40 -34
  2. package/compiler/__tests__/pack-split.test.js +145 -0
  3. package/compiler/adapters/antigravity.js +1 -1
  4. package/compiler/adapters/codex.js +77 -0
  5. package/compiler/adapters/cursor.js +1 -1
  6. package/compiler/adapters/generic.js +1 -1
  7. package/compiler/adapters/index.js +4 -0
  8. package/compiler/adapters/opencode.js +86 -0
  9. package/compiler/adapters/windsurf.js +1 -1
  10. package/compiler/bin/rune.js +10 -7
  11. package/compiler/doctor.js +42 -0
  12. package/compiler/emitter.js +64 -10
  13. package/compiler/parser.js +42 -3
  14. package/compiler/transformer.js +10 -6
  15. package/compiler/transforms/branding.js +1 -1
  16. package/compiler/transforms/compliance.js +40 -0
  17. package/extensions/ai-ml/PACK.md +38 -474
  18. package/extensions/ai-ml/skills/ai-agents.md +172 -0
  19. package/extensions/ai-ml/skills/code-sandbox.md +187 -0
  20. package/extensions/ai-ml/skills/deep-research.md +146 -0
  21. package/extensions/ai-ml/skills/embedding-search.md +66 -0
  22. package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -0
  23. package/extensions/ai-ml/skills/llm-architect.md +125 -0
  24. package/extensions/ai-ml/skills/llm-integration.md +64 -0
  25. package/extensions/ai-ml/skills/prompt-patterns.md +72 -0
  26. package/extensions/ai-ml/skills/rag-patterns.md +66 -0
  27. package/extensions/ai-ml/skills/web-extraction.md +114 -0
  28. package/extensions/analytics/PACK.md +19 -484
  29. package/extensions/analytics/skills/ab-testing.md +72 -0
  30. package/extensions/analytics/skills/dashboard-patterns.md +83 -0
  31. package/extensions/analytics/skills/data-validation.md +68 -0
  32. package/extensions/analytics/skills/funnel-analysis.md +81 -0
  33. package/extensions/analytics/skills/sql-patterns.md +57 -0
  34. package/extensions/analytics/skills/statistical-analysis.md +79 -0
  35. package/extensions/analytics/skills/tracking-setup.md +71 -0
  36. package/extensions/backend/PACK.md +44 -618
  37. package/extensions/backend/skills/api-patterns.md +84 -0
  38. package/extensions/backend/skills/async-pipeline.md +193 -0
  39. package/extensions/backend/skills/auth-patterns.md +97 -0
  40. package/extensions/backend/skills/background-jobs.md +133 -0
  41. package/extensions/backend/skills/caching-patterns.md +108 -0
  42. package/extensions/backend/skills/cli-generation.md +133 -0
  43. package/extensions/backend/skills/database-patterns.md +87 -0
  44. package/extensions/backend/skills/middleware-patterns.md +104 -0
  45. package/extensions/chrome-ext/PACK.md +19 -921
  46. package/extensions/chrome-ext/skills/cws-preflight.md +143 -0
  47. package/extensions/chrome-ext/skills/cws-publish.md +104 -0
  48. package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -0
  49. package/extensions/chrome-ext/skills/ext-messaging.md +139 -0
  50. package/extensions/chrome-ext/skills/ext-storage.md +133 -0
  51. package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -0
  52. package/extensions/content/PACK.md +43 -335
  53. package/extensions/content/skills/blog-patterns.md +88 -0
  54. package/extensions/content/skills/cms-integration.md +131 -0
  55. package/extensions/content/skills/content-scoring.md +107 -0
  56. package/extensions/content/skills/i18n.md +83 -0
  57. package/extensions/content/skills/mdx-authoring.md +137 -0
  58. package/extensions/content/skills/reference.md +1014 -0
  59. package/extensions/content/skills/seo-patterns.md +67 -0
  60. package/extensions/content/skills/video-repurpose.md +153 -0
  61. package/extensions/devops/PACK.md +38 -457
  62. package/extensions/devops/skills/chaos-testing.md +67 -0
  63. package/extensions/devops/skills/ci-cd.md +75 -0
  64. package/extensions/devops/skills/docker.md +58 -0
  65. package/extensions/devops/skills/edge-serverless.md +163 -0
  66. package/extensions/devops/skills/infra-as-code.md +158 -0
  67. package/extensions/devops/skills/kubernetes.md +110 -0
  68. package/extensions/devops/skills/monitoring.md +57 -0
  69. package/extensions/devops/skills/server-setup.md +64 -0
  70. package/extensions/devops/skills/ssl-domain.md +42 -0
  71. package/extensions/ecommerce/PACK.md +62 -226
  72. package/extensions/ecommerce/skills/cart-system.md +79 -0
  73. package/extensions/ecommerce/skills/inventory-mgmt.md +102 -0
  74. package/extensions/ecommerce/skills/order-management.md +126 -0
  75. package/extensions/ecommerce/skills/payment-integration.md +472 -0
  76. package/extensions/ecommerce/skills/shopify-dev.md +69 -0
  77. package/extensions/ecommerce/skills/subscription-billing.md +93 -0
  78. package/extensions/ecommerce/skills/tax-compliance.md +117 -0
  79. package/extensions/gamedev/PACK.md +66 -317
  80. package/extensions/gamedev/skills/asset-pipeline.md +74 -0
  81. package/extensions/gamedev/skills/audio-system.md +129 -0
  82. package/extensions/gamedev/skills/camera-system.md +87 -0
  83. package/extensions/gamedev/skills/ecs.md +98 -0
  84. package/extensions/gamedev/skills/game-loops.md +72 -0
  85. package/extensions/gamedev/skills/input-system.md +199 -0
  86. package/extensions/gamedev/skills/multiplayer.md +180 -0
  87. package/extensions/gamedev/skills/particles.md +105 -0
  88. package/extensions/gamedev/skills/physics-engine.md +89 -0
  89. package/extensions/gamedev/skills/scene-management.md +146 -0
  90. package/extensions/gamedev/skills/threejs-patterns.md +90 -0
  91. package/extensions/gamedev/skills/webgl.md +71 -0
  92. package/extensions/mobile/PACK.md +56 -223
  93. package/extensions/mobile/skills/app-store-connect.md +152 -0
  94. package/extensions/mobile/skills/app-store-prep.md +66 -0
  95. package/extensions/mobile/skills/deep-linking.md +109 -0
  96. package/extensions/mobile/skills/flutter.md +60 -0
  97. package/extensions/mobile/skills/ios-build-pipeline.md +142 -0
  98. package/extensions/mobile/skills/native-bridge.md +66 -0
  99. package/extensions/mobile/skills/ota-updates.md +97 -0
  100. package/extensions/mobile/skills/push-notifications.md +111 -0
  101. package/extensions/mobile/skills/react-native.md +82 -0
  102. package/extensions/saas/PACK.md +26 -720
  103. package/extensions/saas/skills/billing-integration.md +121 -0
  104. package/extensions/saas/skills/feature-flags.md +130 -0
  105. package/extensions/saas/skills/multi-tenant.md +103 -0
  106. package/extensions/saas/skills/onboarding-flow.md +139 -0
  107. package/extensions/saas/skills/subscription-flow.md +95 -0
  108. package/extensions/saas/skills/team-management.md +144 -0
  109. package/extensions/security/PACK.md +10 -448
  110. package/extensions/security/skills/api-security.md +140 -0
  111. package/extensions/security/skills/compliance.md +68 -0
  112. package/extensions/security/skills/owasp-audit.md +64 -0
  113. package/extensions/security/skills/pentest-patterns.md +77 -0
  114. package/extensions/security/skills/secret-mgmt.md +65 -0
  115. package/extensions/security/skills/supply-chain.md +65 -0
  116. package/extensions/trading/PACK.md +18 -535
  117. package/extensions/trading/skills/chart-components.md +55 -0
  118. package/extensions/trading/skills/experiment-loop.md +125 -0
  119. package/extensions/trading/skills/fintech-patterns.md +47 -0
  120. package/extensions/trading/skills/indicator-library.md +58 -0
  121. package/extensions/trading/skills/quant-analysis.md +111 -0
  122. package/extensions/trading/skills/realtime-data.md +58 -0
  123. package/extensions/trading/skills/trade-logic.md +104 -0
  124. package/extensions/ui/PACK.md +34 -853
  125. package/extensions/ui/skills/a11y-audit.md +91 -0
  126. package/extensions/ui/skills/animation-patterns.md +106 -0
  127. package/extensions/ui/skills/component-patterns.md +75 -0
  128. package/extensions/ui/skills/design-decision.md +98 -0
  129. package/extensions/ui/skills/design-system.md +68 -0
  130. package/extensions/ui/skills/landing-patterns.md +155 -0
  131. package/extensions/ui/skills/palette-picker.md +162 -0
  132. package/extensions/ui/skills/react-health.md +90 -0
  133. package/extensions/ui/skills/type-system.md +125 -0
  134. package/extensions/ui/skills/web-vitals.md +153 -0
  135. package/extensions/zalo/PACK.md +117 -0
  136. package/extensions/zalo/skills/zalo-oa-mcp.md +317 -0
  137. package/extensions/zalo/skills/zalo-oa-messaging.md +429 -0
  138. package/extensions/zalo/skills/zalo-oa-setup.md +236 -0
  139. package/extensions/zalo/skills/zalo-oa-webhook.md +189 -0
  140. package/extensions/zalo/skills/zalo-personal-messaging.md +194 -0
  141. package/extensions/zalo/skills/zalo-personal-setup.md +153 -0
  142. package/extensions/zalo/skills/zalo-rate-guard.md +219 -0
  143. package/package.json +5 -2
  144. package/skills/brainstorm/SKILL.md +63 -1
  145. package/skills/cook/SKILL.md +89 -6
  146. package/skills/debug/SKILL.md +5 -0
  147. package/skills/fix/SKILL.md +5 -0
  148. package/skills/mcp-builder/SKILL.md +48 -1
  149. package/skills/neural-memory/SKILL.md +362 -0
  150. package/skills/plan/SKILL.md +3 -0
  151. package/skills/rescue/SKILL.md +5 -0
  152. package/skills/review/SKILL.md +44 -5
  153. package/skills/review-intake/SKILL.md +17 -1
  154. package/skills/skill-router/SKILL.md +106 -8
  155. package/skills/team/SKILL.md +24 -1
  156. package/skills/test/SKILL.md +18 -0
  157. package/skills/verification/SKILL.md +40 -1
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: "tax-compliance"
3
+ pack: "@rune/ecommerce"
4
+ description: "Tax calculation — sales tax API integration, VAT for EU, digital goods tax, tax-inclusive pricing, audit trail."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # tax-compliance
10
+
11
+ Tax calculation — sales tax API integration, VAT for EU, digital goods tax, tax-inclusive pricing, audit trail.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Detect tax setup**
16
+ Use Grep to find: `tax`, `vat`, `taxjar`, `avalara`, `tax_rate`, `taxAmount`, `tax_exempt`. Check if tax calculation exists and where it happens (cart time vs checkout time).
17
+
18
+ **Step 2 — Audit tax accuracy**
19
+ Check for:
20
+ - Tax calculated at cart time but not recalculated at checkout (rate may have changed, or user changed shipping address)
21
+ - Hardcoded tax rates instead of API-based calculation (rates change; nexus rules are complex)
22
+ - Missing tax on digital goods (many US states and all EU countries tax digital products)
23
+ - EU VAT: must charge buyer's country VAT rate for B2C digital sales (not seller's country)
24
+ - Tax-inclusive vs tax-exclusive display: must be consistent and clearly labeled
25
+ - No tax audit trail: amounts, rates, and jurisdiction must be stored per order for compliance
26
+ - Missing tax exemption handling (B2B customers with valid VAT number or tax-exempt certificate)
27
+
28
+ **Step 3 — Emit tax patterns**
29
+ Emit: tax calculation at checkout time (not cart time), API-based rate lookup, EU VAT reverse charge for B2B, and tax audit trail per order line item.
30
+
31
+ #### Example
32
+
33
+ ```typescript
34
+ // Tax calculation at CHECKOUT time (not cart time) — rates may change
35
+ interface TaxLineItem {
36
+ productId: string;
37
+ amount: number;
38
+ quantity: number;
39
+ taxCode: string; // Product tax code (e.g., 'txcd_10000000' for general goods)
40
+ }
41
+
42
+ async function calculateTax(
43
+ items: TaxLineItem[],
44
+ shippingAddress: Address,
45
+ customerTaxExempt: boolean
46
+ ): Promise<TaxResult> {
47
+ if (customerTaxExempt) {
48
+ return { totalTax: 0, lineItems: items.map(i => ({ ...i, tax: 0, rate: 0 })) };
49
+ }
50
+
51
+ // Use tax API — never hardcode rates
52
+ const calculation = await stripe.tax.calculations.create({
53
+ currency: 'usd',
54
+ line_items: items.map(item => ({
55
+ amount: item.amount * item.quantity,
56
+ reference: item.productId,
57
+ tax_code: item.taxCode,
58
+ })),
59
+ customer_details: {
60
+ address: {
61
+ line1: shippingAddress.line1,
62
+ city: shippingAddress.city,
63
+ state: shippingAddress.state,
64
+ postal_code: shippingAddress.postalCode,
65
+ country: shippingAddress.country,
66
+ },
67
+ address_source: 'shipping',
68
+ },
69
+ });
70
+
71
+ return {
72
+ totalTax: calculation.tax_amount_exclusive,
73
+ lineItems: calculation.line_items.data.map(li => ({
74
+ productId: li.reference,
75
+ tax: li.amount_tax,
76
+ rate: li.tax_breakdown?.[0]?.rate ?? 0,
77
+ jurisdiction: li.tax_breakdown?.[0]?.jurisdiction?.display_name ?? 'Unknown',
78
+ })),
79
+ };
80
+ }
81
+
82
+ // EU VAT validation — B2B reverse charge
83
+ async function validateEuVat(vatNumber: string, buyerCountry: string): Promise<boolean> {
84
+ // Use VIES (VAT Information Exchange System) API
85
+ const res = await fetch(
86
+ `https://ec.europa.eu/taxation_customs/vies/rest-api/ms/${buyerCountry}/vat/${vatNumber.replace(/^[A-Z]{2}/, '')}`
87
+ );
88
+ const data = await res.json();
89
+ return data.isValid === true;
90
+ }
91
+
92
+ // Store tax audit trail per order (required for compliance)
93
+ interface OrderTaxRecord {
94
+ orderId: string;
95
+ lineItemId: string;
96
+ taxAmount: number;
97
+ taxRate: number;
98
+ jurisdiction: string;
99
+ calculatedAt: Date;
100
+ taxApiTransactionId: string;
101
+ }
102
+
103
+ // Commit tax record immediately at payment creation — never calculate retroactively
104
+ async function commitTaxRecord(orderId: string, calculation: TaxResult, txnId: string) {
105
+ await prisma.orderTaxRecord.createMany({
106
+ data: calculation.lineItems.map(li => ({
107
+ orderId,
108
+ lineItemId: li.productId,
109
+ taxAmount: li.tax,
110
+ taxRate: li.rate,
111
+ jurisdiction: li.jurisdiction,
112
+ calculatedAt: new Date(),
113
+ taxApiTransactionId: txnId,
114
+ })),
115
+ });
116
+ }
117
+ ```
@@ -1,19 +1,20 @@
1
1
  ---
2
2
  name: "@rune/gamedev"
3
- description: Game development patterns — Three.js, WebGL, game loops, physics engines, and asset pipelines.
3
+ description: Game development patterns — Three.js, WebGL, game loops, physics engines, asset pipelines, multiplayer, audio, input, ECS, particles, camera, and scene management.
4
4
  metadata:
5
5
  author: runedev
6
- version: "0.1.0"
6
+ version: "0.2.0"
7
7
  layer: L4
8
8
  price: "$12"
9
9
  target: Game developers
10
+ format: split
10
11
  ---
11
12
 
12
13
  # @rune/gamedev
13
14
 
14
15
  ## Purpose
15
16
 
16
- Web game development hits performance walls that traditional web apps never encounter: 60fps render loops that stutter on garbage collection, physics simulations that diverge between clients, shaders that work on desktop but fail on mobile GPUs, and asset loading that blocks the first frame for 10 seconds. This pack provides patterns for the full web game stack — rendering, simulation, physics, and assets — each optimized for the unique constraints of real-time interactive applications running in a browser.
17
+ Web game development hits performance walls that traditional web apps never encounter: 60fps render loops that stutter on garbage collection, physics simulations that diverge between clients, shaders that work on desktop but fail on mobile GPUs, and asset loading that blocks the first frame for 10 seconds. This pack provides patterns for the full web game stack — rendering, simulation, physics, assets, multiplayer, audio, input, ECS, particles, camera, and scene management — each optimized for the unique constraints of real-time interactive applications running in a browser.
17
18
 
18
19
  ## Triggers
19
20
 
@@ -23,329 +24,62 @@ Web game development hits performance walls that traditional web apps never enco
23
24
  - `/rune game-loops` — implement or audit game loop architecture
24
25
  - `/rune physics-engine` — set up or optimize physics simulation
25
26
  - `/rune asset-pipeline` — optimize asset loading and management
27
+ - `/rune multiplayer` — WebSocket game server and client prediction
28
+ - `/rune audio-system` — Web Audio API, spatial audio, SFX management
29
+ - `/rune input-system` — keyboard/mouse/gamepad/touch input handling
30
+ - `/rune ecs` — Entity Component System architecture
31
+ - `/rune particles` — GPU particle system with WebGL
32
+ - `/rune camera-system` — follow camera, screen shake, zoom
33
+ - `/rune scene-management` — scene transitions, preloading, serialization
26
34
  - Called by `cook` (L1) when game development task detected
27
35
 
28
36
  ## Skills Included
29
37
 
30
- ### threejs-patterns
31
-
32
- Three.js patterns — scene setup, React Three Fiber integration, PBR materials, post-processing, performance optimization.
33
-
34
- #### Workflow
35
-
36
- **Step 1 Detect Three.js setup**
37
- Use Grep to find Three.js usage: `THREE.`, `useThree`, `useFrame`, `Canvas`, `@react-three/fiber`, `@react-three/drei`. Read the main scene file to understand: renderer setup, scene graph structure, camera type, and lighting model.
38
-
39
- **Step 2 Audit performance**
40
- Check for: objects created inside `useFrame` (GC pressure), missing `dispose()` on unmount (memory leak), no frustum culling on large scenes, textures without power-of-two dimensions, unoptimized geometry (too many draw calls), and missing LOD for distant objects.
41
-
42
- **Step 3 Emit optimized scene**
43
- Emit: properly structured R3F scene with declarative lights, memoized geometries, disposal on unmount, instanced meshes for repeated objects, and post-processing pipeline.
44
-
45
- #### Example
46
-
47
- ```tsx
48
- // React Three Fiber — optimized scene with instancing and post-processing
49
- import { Canvas, useFrame } from '@react-three/fiber';
50
- import { OrbitControls, Environment, useGLTF, Instances, Instance } from '@react-three/drei';
51
- import { EffectComposer, Bloom, Vignette } from '@react-three/postprocessing';
52
- import { useRef, useMemo } from 'react';
53
-
54
- function InstancedTrees({ count = 500 }) {
55
- const positions = useMemo(() =>
56
- Array.from({ length: count }, () => [
57
- (Math.random() - 0.5) * 100,
58
- 0,
59
- (Math.random() - 0.5) * 100,
60
- ] as [number, number, number]),
61
- [count]);
62
-
63
- return (
64
- <Instances limit={count}>
65
- <cylinderGeometry args={[0.2, 0.4, 3]} />
66
- <meshStandardMaterial color="#4a7c59" />
67
- {positions.map((pos, i) => <Instance key={i} position={pos} />)}
68
- </Instances>
69
- );
70
- }
71
-
72
- function GameScene() {
73
- return (
74
- <Canvas camera={{ position: [0, 10, 20], fov: 60 }} gl={{ antialias: true }}>
75
- <ambientLight intensity={0.3} />
76
- <directionalLight position={[10, 20, 10]} intensity={1} castShadow />
77
- <Environment preset="sunset" />
78
- <InstancedTrees count={500} />
79
- <OrbitControls maxPolarAngle={Math.PI / 2.2} />
80
- <EffectComposer>
81
- <Bloom intensity={0.3} luminanceThreshold={0.8} />
82
- <Vignette offset={0.3} darkness={0.6} />
83
- </EffectComposer>
84
- </Canvas>
85
- );
86
- }
87
- ```
88
-
89
- ---
90
-
91
- ### webgl
92
-
93
- WebGL patterns — shader programming, GLSL, buffer management, texture handling, instanced rendering.
94
-
95
- #### Workflow
96
-
97
- **Step 1 — Detect WebGL usage**
98
- Use Grep to find WebGL code: `getContext('webgl`, `gl.createShader`, `gl.createProgram`, `*.glsl`, `*.vert`, `*.frag`. Read shader files and GL initialization to understand: WebGL version, shader complexity, and buffer strategy.
99
-
100
- **Step 2 — Audit shader and buffer efficiency**
101
- Check for: uniforms set every frame that don't change (use UBO), separate draw calls for identical geometry (use instancing), textures not using mipmaps, missing `gl.deleteBuffer`/`gl.deleteTexture` cleanup, and shaders with expensive per-fragment branching.
102
-
103
- **Step 3 — Emit optimized WebGL code**
104
- Emit: WebGL2 setup with proper context attributes, VAO-based buffer management, instanced rendering for repeated geometry, and GLSL shaders with documented inputs/outputs.
105
-
106
- #### Example
107
-
108
- ```glsl
109
- // Vertex shader — instanced rendering with per-instance transform
110
- #version 300 es
111
- layout(location = 0) in vec3 aPosition;
112
- layout(location = 1) in vec3 aNormal;
113
- layout(location = 2) in mat4 aInstanceMatrix; // per-instance (locations 2-5)
114
-
115
- uniform mat4 uViewProjection;
116
-
117
- out vec3 vNormal;
118
- out vec3 vWorldPos;
119
-
120
- void main() {
121
- vec4 worldPos = aInstanceMatrix * vec4(aPosition, 1.0);
122
- vWorldPos = worldPos.xyz;
123
- vNormal = mat3(transpose(inverse(aInstanceMatrix))) * aNormal;
124
- gl_Position = uViewProjection * worldPos;
125
- }
126
- ```
127
-
128
- ```glsl
129
- // Fragment shader — PBR-lite with single directional light
130
- #version 300 es
131
- precision highp float;
132
-
133
- in vec3 vNormal;
134
- in vec3 vWorldPos;
135
- out vec4 fragColor;
136
-
137
- uniform vec3 uLightDir;
138
- uniform vec3 uCameraPos;
139
- uniform vec3 uBaseColor;
140
-
141
- void main() {
142
- vec3 N = normalize(vNormal);
143
- vec3 L = normalize(uLightDir);
144
- vec3 V = normalize(uCameraPos - vWorldPos);
145
- vec3 H = normalize(L + V);
146
-
147
- float diffuse = max(dot(N, L), 0.0);
148
- float specular = pow(max(dot(N, H), 0.0), 32.0);
149
- vec3 ambient = uBaseColor * 0.15;
150
-
151
- fragColor = vec4(ambient + uBaseColor * diffuse + vec3(specular * 0.5), 1.0);
152
- }
153
- ```
154
-
155
- ---
156
-
157
- ### game-loops
158
-
159
- Game loop architecture — fixed timestep, interpolation, input handling, state machines, ECS.
160
-
161
- #### Workflow
162
-
163
- **Step 1 — Detect game loop pattern**
164
- Use Grep to find loop code: `requestAnimationFrame`, `setInterval.*16`, `update`, `fixedUpdate`, `deltaTime`, `gameLoop`. Read the main loop to understand: timestep strategy, update/render separation, and input handling.
165
-
166
- **Step 2 — Audit loop correctness**
167
- Check for: variable timestep physics (non-deterministic), no accumulator for fixed update (physics tied to framerate), input polled inside render (inconsistent), missing interpolation between fixed steps (visual stuttering), and no frame budget monitoring.
168
-
169
- **Step 3 — Emit fixed timestep loop**
170
- Emit: fixed timestep (60Hz) with accumulator, interpolation for smooth rendering, decoupled input handler, and frame budget monitoring.
171
-
172
- #### Example
173
-
174
- ```typescript
175
- // Fixed timestep game loop with interpolation
176
- const TICK_RATE = 60;
177
- const TICK_DURATION = 1000 / TICK_RATE;
178
-
179
- class GameLoop {
180
- private accumulator = 0;
181
- private previousTime = 0;
182
- private running = false;
183
-
184
- constructor(
185
- private update: (dt: number) => void, // fixed timestep logic
186
- private render: (alpha: number) => void, // interpolated rendering
187
- ) {}
188
-
189
- start() {
190
- this.running = true;
191
- this.previousTime = performance.now();
192
- requestAnimationFrame(this.tick);
193
- }
194
-
195
- private tick = (currentTime: number) => {
196
- if (!this.running) return;
197
- const elapsed = Math.min(currentTime - this.previousTime, 250); // cap spiral of death
198
- this.previousTime = currentTime;
199
- this.accumulator += elapsed;
200
-
201
- while (this.accumulator >= TICK_DURATION) {
202
- this.update(TICK_DURATION / 1000); // dt in seconds
203
- this.accumulator -= TICK_DURATION;
204
- }
205
-
206
- const alpha = this.accumulator / TICK_DURATION; // interpolation factor [0, 1)
207
- this.render(alpha);
208
- requestAnimationFrame(this.tick);
209
- };
210
-
211
- stop() { this.running = false; }
212
- }
213
-
214
- // Usage
215
- const loop = new GameLoop(
216
- (dt) => { world.step(dt); entities.forEach(e => e.update(dt)); },
217
- (alpha) => { renderer.render(scene, camera, alpha); },
218
- );
219
- loop.start();
220
- ```
221
-
222
- ---
223
-
224
- ### physics-engine
225
-
226
- Physics integration — Rapier.js, rigid bodies, constraints, raycasting, collision callbacks, deterministic simulation.
227
-
228
- #### Workflow
229
-
230
- **Step 1 — Detect physics setup**
231
- Use Grep to find physics libraries: `rapier`, `cannon`, `ammo`, `@dimforge/rapier3d`, `RigidBody`, `Collider`. Read physics initialization and body creation to understand: engine choice, world configuration, and collision handling.
232
-
233
- **Step 2 — Audit physics configuration**
234
- Check for: physics step tied to render frame (non-deterministic), missing collision groups (everything collides with everything), no sleep threshold (wasted CPU on static objects), raycasts without max distance (expensive), and missing body cleanup on entity destroy.
235
-
236
- **Step 3 — Emit optimized physics**
237
- Emit: Rapier.js (WASM, deterministic) setup with proper collision groups, sleep thresholds, event-driven collision callbacks, and raycasting utility.
238
-
239
- #### Example
240
-
241
- ```typescript
242
- // Rapier.js (WASM) — setup with collision groups and raycasting
243
- import RAPIER from '@dimforge/rapier3d-compat';
244
-
245
- await RAPIER.init();
246
- const world = new RAPIER.World({ x: 0, y: -9.81, z: 0 });
247
-
248
- // Collision groups: player=0x0001, enemy=0x0002, ground=0x0004, projectile=0x0008
249
- const GROUPS = { PLAYER: 0x0001, ENEMY: 0x0002, GROUND: 0x0004, PROJECTILE: 0x0008 };
250
-
251
- // Ground — static, collides with everything
252
- const groundBody = world.createRigidBody(RAPIER.RigidBodyDesc.fixed().setTranslation(0, 0, 0));
253
- world.createCollider(
254
- RAPIER.ColliderDesc.cuboid(50, 0.1, 50)
255
- .setCollisionGroups((GROUPS.GROUND << 16) | 0xFFFF),
256
- groundBody,
257
- );
258
-
259
- // Player — dynamic, collides with ground + enemy (not own projectiles)
260
- const playerBody = world.createRigidBody(RAPIER.RigidBodyDesc.dynamic().setTranslation(0, 5, 0));
261
- world.createCollider(
262
- RAPIER.ColliderDesc.capsule(0.5, 0.3)
263
- .setCollisionGroups((GROUPS.PLAYER << 16) | (GROUPS.GROUND | GROUPS.ENEMY))
264
- .setActiveEvents(RAPIER.ActiveEvents.COLLISION_EVENTS),
265
- playerBody,
266
- );
267
-
268
- // Raycast utility
269
- function raycast(origin: RAPIER.Vector3, direction: RAPIER.Vector3, maxDist = 100) {
270
- const ray = new RAPIER.Ray(origin, direction);
271
- const hit = world.castRay(ray, maxDist, true);
272
- if (hit) {
273
- const point = ray.pointAt(hit.timeOfImpact);
274
- return { point, normal: hit.normal, collider: hit.collider };
275
- }
276
- return null;
277
- }
278
- ```
279
-
280
- ---
281
-
282
- ### asset-pipeline
283
-
284
- Game asset pipeline — glTF loading, texture compression, audio management, asset manifest, preloading.
285
-
286
- #### Workflow
287
-
288
- **Step 1 — Detect asset strategy**
289
- Use Glob to find asset files: `*.gltf`, `*.glb`, `*.ktx2`, `*.basis`, `*.png` in `assets/` or `public/`. Use Grep to find loaders: `GLTFLoader`, `TextureLoader`, `KTX2Loader`, `Howler`, `Audio`. Read the loading code to understand: preloading strategy, compression, and caching.
290
-
291
- **Step 2 — Audit asset efficiency**
292
- Check for: uncompressed textures (PNG/JPG instead of KTX2/Basis), glTF without Draco compression, no asset manifest (scattered inline paths), missing preloader (assets load mid-gameplay causing stutters), audio files in WAV format (use OGG/MP3), and no LOD variants for 3D models.
293
-
294
- **Step 3 — Emit asset pipeline**
295
- Emit: asset manifest with typed entries, preloader with progress tracking, glTF loader with Draco decoder, KTX2 texture loader, and audio manager with Howler.js.
296
-
297
- #### Example
298
-
299
- ```typescript
300
- // Asset manifest + preloader with progress tracking
301
- interface AssetManifest {
302
- models: Record<string, { url: string; draco?: boolean }>;
303
- textures: Record<string, { url: string; format: 'ktx2' | 'png' }>;
304
- audio: Record<string, { url: string; volume?: number; loop?: boolean }>;
305
- }
306
-
307
- const MANIFEST: AssetManifest = {
308
- models: {
309
- player: { url: '/assets/player.glb', draco: true },
310
- level1: { url: '/assets/level1.glb', draco: true },
311
- },
312
- textures: {
313
- terrain: { url: '/assets/terrain.ktx2', format: 'ktx2' },
314
- },
315
- audio: {
316
- bgm: { url: '/assets/bgm.ogg', volume: 0.5, loop: true },
317
- jump: { url: '/assets/jump.ogg', volume: 0.8 },
318
- },
319
- };
320
-
321
- class AssetLoader {
322
- private loaded = 0;
323
- private total = 0;
324
-
325
- async loadAll(manifest: AssetManifest, onProgress: (pct: number) => void) {
326
- const entries = [
327
- ...Object.values(manifest.models),
328
- ...Object.values(manifest.textures),
329
- ...Object.values(manifest.audio),
330
- ];
331
- this.total = entries.length;
332
-
333
- await Promise.all(entries.map(async (entry) => {
334
- await fetch(entry.url); // preload into browser cache
335
- this.loaded++;
336
- onProgress(this.loaded / this.total);
337
- }));
338
- }
339
- }
340
- ```
341
-
342
- ---
38
+ | Skill | Model | Description |
39
+ |-------|-------|-------------|
40
+ | [threejs-patterns](skills/threejs-patterns.md) | sonnet | Three.js scene, React Three Fiber, PBR materials, LOD, post-processing, instanced rendering, and disposal patterns. |
41
+ | [webgl](skills/webgl.md) | sonnet | Raw WebGL2, GLSL shaders, VAO buffer management, instanced rendering, and texture handling. |
42
+ | [game-loops](skills/game-loops.md) | sonnet | Fixed timestep with accumulator, interpolation for smooth rendering, decoupled input handler, and frame budget monitoring. |
43
+ | [physics-engine](skills/physics-engine.md) | sonnet | Rapier.js (WASM) setup with collision groups, sleep thresholds, event-driven collision callbacks, and raycasting. |
44
+ | [asset-pipeline](skills/asset-pipeline.md) | sonnet | glTF/Draco loading, KTX2 texture compression, typed asset manifest, preloader with progress tracking. |
45
+ | [multiplayer](skills/multiplayer.md) | sonnet | Authoritative WebSocket game server, client-side prediction, reconciliation, entity interpolation, and lag compensation. |
46
+ | [audio-system](skills/audio-system.md) | sonnet | Web Audio API AudioManager — spatial audio, music crossfade, SFX pooling, browser autoplay policy handling. |
47
+ | [input-system](skills/input-system.md) | sonnet | Unified keyboard/mouse/gamepad/touch input with action mapping, input buffering, coyote time, and virtual joystick. |
48
+ | [ecs](skills/ecs.md) | sonnet | Lightweight archetype-based ECS dense component storage, query-based entity iteration, and pure system functions. |
49
+ | [particles](skills/particles.md) | sonnet | Object-pooled CPU particle system with WebGL instancing path for 10k+ particles and emitter presets. |
50
+ | [camera-system](skills/camera-system.md) | sonnet | 2D camera with smooth lerp follow, dead zone, screen shake decay, and zoom-to target. |
51
+ | [scene-management](skills/scene-management.md) | sonnet | Stack-based SceneManager with fade transitions, asset preloading before enter, and level JSON serialization. |
52
+
53
+ ## Common Workflows
54
+
55
+ | Workflow | Skills Involved | Typical Trigger |
56
+ |----------|----------------|----------------|
57
+ | 2D platformer bootstrap | game-loops → physics-engine → input-system → camera-system | new Phaser/PixiJS project |
58
+ | 3D world with NPCs | threejs-patterns ecs → physics-engine → camera-system | Three.js/R3F project |
59
+ | Multiplayer action game | game-loops multiplayer → physics-engine → input-system | real-time PvP feature |
60
+ | Mobile game port | asset-pipeline → input-system → camera-system → game-loops | add touch controls |
61
+ | VFX & atmosphere | particles → webgl → threejs-patterns → audio-system | visual polish sprint |
62
+ | Game level editor | scene-management → asset-pipeline → ecs → camera-system | tooling sprint |
63
+ | Performance audit | game-loops → webgl → particles → asset-pipeline | frame rate complaints |
64
+
65
+ ## Cross-Pack Connections
66
+
67
+ | Target Pack | Connection | Use Case |
68
+ |-------------|-----------|----------|
69
+ | **@rune/ui** | HUD components, inventory screens, pause menus, leaderboard overlays | Health bars, minimap, skill cooldowns, settings modal |
70
+ | **@rune/backend** | REST/WebSocket API for leaderboards, save data, player accounts, matchmaking | POST `/scores`, GET `/leaderboard`, save game state to DB |
71
+ | **@rune/analytics** | Player telemetry — session length, death locations, skill usage heatmaps | `analytics.track('player_died', { x, y, cause })` |
72
+ | **@rune/ai-ml** | NPC behavior trees, pathfinding ML, procedural content, cheat detection | A* pathfinding, trained NPC models, PCG level generation |
343
73
 
344
74
  ## Connections
345
75
 
346
76
  ```
347
77
  Calls → perf (L2): frame budget and rendering performance audit
348
78
  Calls → asset-creator (L3): generate placeholder assets and sprites
79
+ Calls → @rune/ui: HUD, inventory, menus, overlays
80
+ Calls → @rune/backend: leaderboards, save data, player accounts, matchmaking
81
+ Calls → @rune/analytics: player telemetry and session tracking
82
+ Calls → @rune/ai-ml: NPC behavior, procedural content, cheat detection
349
83
  Called By ← cook (L1): when game development task detected
350
84
  Called By ← review (L2): when game code under review
351
85
  ```
@@ -367,6 +101,9 @@ Called By ← review (L2): when game code under review
367
101
  3. MUST NOT create objects inside the render loop — allocate outside, reuse inside.
368
102
  4. MUST test on target minimum hardware (mobile GPU) not just development machine.
369
103
  5. MUST use compressed asset formats (Draco for geometry, KTX2/Basis for textures) — raw assets cause unacceptable load times.
104
+ 6. MUST use authoritative server model for multiplayer — never trust client position data.
105
+ 7. MUST resume AudioContext on user gesture — browsers block autoplay audio.
106
+ 8. MUST call `input.flush()` at end of each fixed tick — prevents justPressed persisting across frames.
370
107
 
371
108
  ## Sharp Edges
372
109
 
@@ -378,6 +115,10 @@ Called By ← review (L2): when game code under review
378
115
  | Shader compiles on first use causing frame drop (shader cache miss) | MEDIUM | Pre-warm shaders during loading screen; use `renderer.compile(scene, camera)` |
379
116
  | Asset loading blocks first frame (white screen for 5+ seconds) | HIGH | Implement progressive loading with preloader UI; prioritize visible assets |
380
117
  | Mobile GPU fails on desktop-quality shaders (WebGL context lost) | HIGH | Detect GPU tier with `detect-gpu`; provide shader LOD variants |
118
+ | Multiplayer client trusts own position — speed hack trivial | CRITICAL | Server is authoritative; client sends inputs only, reconciles with server state |
119
+ | AudioContext locked until user gesture — no music on load | MEDIUM | Resume AudioContext in first click/keydown handler; show muted indicator |
120
+ | Gamepad axes not zeroed when gamepad disconnects | LOW | Set axes to 0 in gamepaddisconnected handler |
121
+ | Input justPressed persists to next frame if flush() skipped | HIGH | Always flush at end of fixed update, not render |
381
122
 
382
123
  ## Done When
383
124
 
@@ -386,8 +127,16 @@ Called By ← review (L2): when game code under review
386
127
  - All GPU resources properly disposed on cleanup
387
128
  - Assets compressed and preloaded with progress indicator
388
129
  - Game loop decouples update from render with interpolation
130
+ - Multiplayer: server authoritative, client predicts + reconciles
131
+ - Audio: spatial SFX + crossfade music, resumable after user gesture
132
+ - Input: keyboard/mouse/gamepad/touch unified, buffered, rebindable
133
+ - ECS: entities/components/systems cleanly separated, query-based
134
+ - Particles: pooled, no GC spikes, emitter presets for common FX
135
+ - Camera: smooth follow, dead zone, screen shake on impact
136
+ - Scenes: transition with fade, preload assets before enter
137
+ - Performance: quadtree spatial queries, frame budget monitoring active
389
138
  - Structured report emitted for each skill invoked
390
139
 
391
140
  ## Cost Profile
392
141
 
393
- ~10,000–20,000 tokens per full pack run (all 5 skills). Individual skill: ~2,000–4,000 tokens. Sonnet default. Use haiku for asset detection scans; escalate to sonnet for shader optimization and physics configuration.
142
+ ~10,000–20,000 tokens per full pack run (all skills). Individual skill: ~2,000–4,000 tokens. Sonnet default. Use haiku for asset detection scans and grep passes; sonnet for physics config, shader optimization, and multiplayer architecture; escalate to opus for full game architecture decisions spanning multiple systems.
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: "asset-pipeline"
3
+ pack: "@rune/gamedev"
4
+ description: "Game asset pipeline — glTF loading, texture compression, audio management, asset manifest, preloading."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # asset-pipeline
10
+
11
+ Game asset pipeline — glTF loading, texture compression, audio management, asset manifest, preloading.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Detect asset strategy**
16
+ Use Glob to find asset files: `*.gltf`, `*.glb`, `*.ktx2`, `*.basis`, `*.png` in `assets/` or `public/`. Use Grep to find loaders: `GLTFLoader`, `TextureLoader`, `KTX2Loader`, `Howler`, `Audio`. Read the loading code to understand: preloading strategy, compression, and caching.
17
+
18
+ **Step 2 — Audit asset efficiency**
19
+ Check for: uncompressed textures (PNG/JPG instead of KTX2/Basis), glTF without Draco compression, no asset manifest (scattered inline paths), missing preloader (assets load mid-gameplay causing stutters), audio files in WAV format (use OGG/MP3), and no LOD variants for 3D models.
20
+
21
+ **Step 3 — Emit asset pipeline**
22
+ Emit: asset manifest with typed entries, preloader with progress tracking, glTF loader with Draco decoder, KTX2 texture loader, and audio manager with Howler.js.
23
+
24
+ #### Example
25
+
26
+ ```typescript
27
+ // Asset manifest + preloader with progress tracking
28
+ interface AssetManifest {
29
+ models: Record<string, { url: string; draco?: boolean }>;
30
+ textures: Record<string, { url: string; format: 'ktx2' | 'png' }>;
31
+ audio: Record<string, { url: string; volume?: number; loop?: boolean }>;
32
+ }
33
+
34
+ const MANIFEST: AssetManifest = {
35
+ models: {
36
+ player: { url: '/assets/player.glb', draco: true },
37
+ level1: { url: '/assets/level1.glb', draco: true },
38
+ },
39
+ textures: {
40
+ terrain: { url: '/assets/terrain.ktx2', format: 'ktx2' },
41
+ },
42
+ audio: {
43
+ bgm: { url: '/assets/bgm.ogg', volume: 0.5, loop: true },
44
+ jump: { url: '/assets/jump.ogg', volume: 0.8 },
45
+ },
46
+ };
47
+
48
+ class AssetLoader {
49
+ private loaded = 0;
50
+ private total = 0;
51
+ private cache = new Map<string, unknown>();
52
+
53
+ async loadAll(manifest: AssetManifest, onProgress: (pct: number) => void) {
54
+ const entries = [
55
+ ...Object.entries(manifest.models).map(([k, v]) => ({ key: k, ...v, type: 'model' })),
56
+ ...Object.entries(manifest.textures).map(([k, v]) => ({ key: k, ...v, type: 'texture' })),
57
+ ...Object.entries(manifest.audio).map(([k, v]) => ({ key: k, ...v, type: 'audio' })),
58
+ ];
59
+ this.total = entries.length;
60
+
61
+ await Promise.all(entries.map(async (entry) => {
62
+ await fetch(entry.url); // preload into browser cache
63
+ this.loaded++;
64
+ onProgress(this.loaded / this.total);
65
+ }));
66
+ }
67
+
68
+ get<T>(key: string): T {
69
+ const asset = this.cache.get(key);
70
+ if (!asset) throw new Error(`Asset not loaded: ${key}`);
71
+ return asset as T;
72
+ }
73
+ }
74
+ ```