@genex-ai/cli-demo 0.70.0-dev.182 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/index.js +8 -354
  2. package/package.json +1 -2
  3. package/templates/controllers/character/vrm/vrm-loader.ts +11 -74
  4. package/templates/skills/genex-ai-menu/SKILL.md +1 -7
  5. package/templates/skills/genex-ai-skybox/SKILL.md +4 -15
  6. package/templates/skills/genex-ai-texture/SKILL.md +1 -1
  7. package/templates/skills/genex-ai-video/SKILL.md +1 -1
  8. package/templates/skills/genex-explore/SKILL.md +1 -1
  9. package/templates/skills/genex-getting-started/SKILL.md +2 -2
  10. package/templates/skills/genex-threejs-bloom/SKILL.md +1 -4
  11. package/templates/skills/genex-threejs-bloom/references/bloom.md +1 -1
  12. package/templates/skills/genex-threejs-camera-direction/SKILL.md +8 -48
  13. package/templates/skills/genex-threejs-camera-direction/references/camera-rigs.md +0 -62
  14. package/templates/skills/genex-threejs-embed-auth/SKILL.md +1 -4
  15. package/templates/skills/genex-threejs-game-feel/SKILL.md +1 -4
  16. package/templates/skills/genex-threejs-game-ui/SKILL.md +8 -42
  17. package/templates/skills/genex-threejs-image-pipeline/SKILL.md +0 -5
  18. package/templates/skills/genex-threejs-image-pipeline/references/image-pipeline.md +1 -1
  19. package/templates/skills/genex-threejs-lighting-design/SKILL.md +1 -5
  20. package/templates/skills/genex-threejs-multiplayer/SKILL.md +1 -7
  21. package/templates/skills/genex-threejs-multiplayer/references/host-physics.md +3 -6
  22. package/templates/skills/genex-threejs-physics-rapier/references/colliders-from-assets.md +0 -1
  23. package/templates/skills/genex-threejs-screen-space-ambient-occlusion/references/ambient-occlusion.md +1 -1
  24. package/templates/skills/genex-threejs-shadow-systems/SKILL.md +0 -6
  25. package/templates/skills/genex-threejs-shadow-systems/references/shadow-systems.md +1 -1
  26. package/templates/skills/genex-threejs-skill-router/SKILL.md +5 -26
  27. package/templates/skills/genex-threejs-skill-router/references/routing-map.md +7 -21
  28. package/templates/skills/genex-threejs-spectral-ocean/references/spectral-ocean.md +1 -1
  29. package/templates/skills/genex-threejs-touch-controls/SKILL.md +0 -11
  30. package/templates/skills/genex-threejs-visual-validation/SKILL.md +12 -29
  31. package/templates/skills/genex-threejs-water-optics/references/water-optics.md +1 -1
  32. package/templates/skills/genex-updates/SKILL.md +1 -1
  33. package/templates/controllers/quality/governor.ts +0 -147
  34. package/templates/controllers/quality/pick-asset.ts +0 -57
  35. package/templates/controllers/quality/tier.ts +0 -170
  36. package/templates/skills/genex-threejs-adaptive-quality/SKILL.md +0 -141
  37. package/templates/skills/genex-threejs-adaptive-quality/references/adaptive-quality.md +0 -105
@@ -71,7 +71,7 @@ Add `--json` for machine-readable output.
71
71
 
72
72
  1. `git clone <clone URL from the output> <name>` — pick a short one-word name.
73
73
  2. `cd <name>`, then run init on the SAME CLI channel your current project
74
- uses: `npx @genex-ai/cli-demo@dev init <name>` — or `@dev` when you're
74
+ uses: `npx @genex-ai/cli-demo@latest init <name>` — or `@dev` when you're
75
75
  on the dev stand (unsure? `dashboardOrigins` in your current project's
76
76
  `.genex/project.json` says which). Never use `--force`. This creates your
77
77
  own project; the original is untouched.
@@ -130,7 +130,7 @@ and re-link the clone to the same live game:
130
130
  ```bash
131
131
  git clone <the game's repo url> my-game && cd my-game
132
132
  npm install
133
- npx @genex-ai/cli-demo@dev link <slug> # slug = the name in the play URL
133
+ npx @genex-ai/cli-demo@latest link <slug> # slug = the name in the play URL
134
134
  ```
135
135
 
136
136
  Don't know the slug? **`npx genex list`** prints every game on your account —
@@ -157,7 +157,7 @@ Safe to run any time — genex-owned skills are refreshed to the latest version,
157
157
  and your own files are never touched:
158
158
 
159
159
  ```bash
160
- npx @genex-ai/cli-demo@dev init
160
+ npx @genex-ai/cli-demo@latest init
161
161
  ```
162
162
 
163
163
  Use `--force` only if you intentionally want your own existing files overwritten
@@ -32,10 +32,7 @@ reference before adding selective bloom to a composed scene.
32
32
  - selective bloom requires mutating scene materials every frame without restoration guarantees;
33
33
  - transparent particles disappear from extraction because pass ownership is unclear;
34
34
  - bloom radius changes wildly with resolution;
35
- - highlights become gray because energy is clamped too early;
36
- - bloom ships un-tiered: phone tiers run the light post level
37
- (`$genex-threejs-adaptive-quality`) — bloom is a desktop-tier pass, and its
38
- full-res HDR target is exactly the allocation phones get killed for.
35
+ - highlights become gray because energy is clamped too early.
39
36
 
40
37
  ## Routing boundary
41
38
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this reference to choose bloom ownership, signal order, selective contribution, and scene-relative emissive ranges without making bloom responsible for the underlying form.
4
4
 
5
- > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project. Either way the effect obeys the device tier (`$genex-threejs-adaptive-quality`): expensive passes are desktop-tier, and on WebGPU the per-target MSAA sample count is a runtime knob the governor may drive.
5
+ > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project.
6
6
 
7
7
  ## Contents
8
8
 
@@ -35,12 +35,9 @@ rules, floating-origin shot, pointer controls, and implementation limits.
35
35
 
36
36
  ## Aiming and pointer lock
37
37
 
38
- The rule is binary: during play, **the cursor is either a gameplay tool or it is
39
- locked away**. An OS arrow parked over the action in a game that never uses it is
40
- a shipped defect, not a default. On the bundled `FollowCamera`, pointer-lock aim
41
- is ON by default on desktop — a click locks the pointer and raw mouse movement
42
- drives the view — so mostly you decide whether to turn it OFF. Name the bucket in
43
- the build plan:
38
+ On the bundled `FollowCamera`, **pointer-lock aim is ON by default** on desktop:
39
+ a click locks the pointer and raw mouse movement drives the view. You rarely turn
40
+ it on you decide whether to turn it OFF. Name the bucket in the build plan:
44
41
 
45
42
  - **MANDATORY** — first-person of any kind (FPS, walking sim, horror) and any
46
43
  mouse-aimed action (third-person shooter, turret/range). Lock is on by default;
@@ -50,16 +47,11 @@ the build plan:
50
47
  `genex controller character` game). On by default; leave it on. Opt out with
51
48
  `pointerLockAim: false` only for a stated reason (a cursor-heavy UI at the core
52
49
  of play).
53
- - **Keyboard-driven games lock too** a racer, platformer, or runner that never
54
- reads the mouse still locks the pointer on the play/Start click: the cursor is
55
- not a tool there, so lock it away (hidden cursor, no stray clicks, Esc = pause
56
- as usual). Bundled-controller games get this for free; a hand-rolled game uses
57
- the minimal lock recipe in `$genex-threejs-game-ui` (~6 lines).
58
- - **NEVER** — cursor-core games where the pointer IS the gameplay tool (top-down
59
- click-to-move, tower defense, builders, card/board/puzzle) and spectator/orbit
60
- showcases. These **must pass `pointerLockAim: false`** — otherwise the bundled
61
- camera grabs the cursor on the first click. (Touch needs nothing: pointer lock
62
- doesn't exist there and the mode no-ops on coarse pointers.)
50
+ - **NEVER** — cursor-core games (top-down click-to-move, tower defense, builders,
51
+ card/board/puzzle) and spectator/orbit showcases. These **must pass
52
+ `pointerLockAim: false`** otherwise the bundled camera grabs the cursor on the
53
+ first click. (Touch needs nothing: pointer lock doesn't exist there and the mode
54
+ no-ops on coarse pointers.)
63
55
 
64
56
  **Mechanism — games on the bundled controller (most games):** do NOT hand-roll
65
57
  lock handling. Aim is already enabled; the kit ships a ready-made cue overlay —
@@ -121,36 +113,6 @@ grants the permission.
121
113
  (trackpad "natural scrolling" only flips the wheel). If look feels inverted it's a
122
114
  sign bug in the rig, not a device quirk — fix the sign, don't sniff the trackpad.
123
115
 
124
- ## The screen-direction contract
125
-
126
- Every input axis has one correct on-screen direction, for every rig, bundled or
127
- hand-rolled. These four invariants are testable and non-negotiable:
128
-
129
- 1. Mouse/touchpad RIGHT turns the view right; mouse UP looks up (down only behind
130
- an explicit invert option the player chose).
131
- 2. `KeyD`/ArrowRight moves or turns the player toward screen-RIGHT; `KeyA`/
132
- ArrowLeft toward screen-left. Same for a touch stick's +x.
133
- 3. Drag-pan picks ONE convention — grab-the-world (terrain follows the pointer)
134
- or move-the-camera — and BOTH axes obey it. One axis each is the
135
- "diagonals feel twisted" bug.
136
- 4. See the OS-setting note above: inversion is always your sign, never the device.
137
-
138
- The formula that settles every sign argument: `screenRight = cross(cameraForward, worldUp)`.
139
- For a Y-up world and forward `(sin yaw, 0, cos yaw)`, screen-right is
140
- `(-cos yaw, 0, sin yaw)`. **Warning — `(cos yaw, 0, -sin yaw)` is the LEFT
141
- vector** (that's `cross(worldUp, cameraForward)`), and writing it as "right" is
142
- the single most-shipped direction bug in generated games: two independent
143
- projects inverted their A/D exactly this way. Related trap: positive
144
- `rotation.y` turns a +Z-facing object toward +X, which is screen-LEFT from a
145
- chase camera behind it — so "positive yaw = turn right" is false in this basis.
146
-
147
- Never derive signs by intuition — intuition about right-handed frames is wrong
148
- about half the time and has been wrong in every shipped instance. Copy a
149
- verified pair (sign AND basis together) from
150
- [references/camera-rigs.md](references/camera-rigs.md), then confirm with the
151
- input-direction part of the smoke check: hold D and watch which way the world
152
- answers.
153
-
154
116
  ## Non-negotiable rules
155
117
 
156
118
  - Use subject dimensions to derive offsets; do not tune one fixed distance for
@@ -160,8 +122,6 @@ answers.
160
122
  - During an explicit handoff, use one interpolation stage. Do not stack a
161
123
  transition blend and a second follow smoother over the same interval.
162
124
  - Re-sync yaw/pitch from the camera when pointer lock is acquired.
163
- - Hand-rolled steering/pan/look math copies a verified basis from the reference
164
- and passes the input-direction check — signs are never derived by intuition.
165
125
  - Update the projection matrix whenever FOV, near, far, or aspect changes.
166
126
  - Keep stars or infinite backgrounds camera-relative when large translation
167
127
  would create false parallax or precision loss.
@@ -11,7 +11,6 @@ Use this reference for scale-aware chase, side, orbit, authored-shot, pointer-lo
11
11
  - Explicit camera handoffs
12
12
  - cinematic implementation shot ownership
13
13
  - Pointer-look and movement constraints
14
- - Verified screen-direction bases
15
14
  - Floating origin and background handling
16
15
  - Projection and lifecycle ownership
17
16
  - Failure modes and diagnostics
@@ -167,9 +166,6 @@ yaw -= mouseDeltaX * 0.0022
167
166
  pitch -= mouseDeltaY * 0.0018
168
167
  ```
169
168
 
170
- Expected on screen: mouse-right orbits the view right, mouse-up tilts it up —
171
- verify both axes against the screen-direction contract before retuning the scales.
172
-
173
169
  Pitch bounds vary by flight mode. The implementation also enforces camera height above
174
170
  the ship:
175
171
 
@@ -285,9 +281,6 @@ distance = movementSpeed * dt
285
281
 
286
282
  Default speed is `9`, sensitivity `0.0023`.
287
283
 
288
- Expected on screen: mouse-right turns the view right, mouse-up looks up — assert
289
- both axes (yaw-only evidence has let inverted pitch ship).
290
-
291
284
  Keys are cleared on:
292
285
 
293
286
  - pointer-lock exit;
@@ -302,61 +295,6 @@ Scene-specific constraints then run after controls:
302
295
 
303
296
  Input control and spatial constraint are separate layers.
304
297
 
305
- ## Verified screen-direction bases
306
-
307
- Copy these pairs whole — the sign and the basis are only correct TOGETHER. Each
308
- was derived from `screenRight = cross(cameraForward, worldUp)` and verified
309
- against the on-screen result; if you change one half, re-verify with the
310
- input-direction check instead of reasoning about it.
311
-
312
- **Chase-cam steering** (vehicle/character heading, camera behind):
313
-
314
- ```text
315
- heading = (sin yaw, 0, cos yaw) // matches rotation.y for a +Z-front model
316
- yaw -= steer * rate * dt // steer: D/right = +1, A/left = -1
317
- position += heading * speed * dt
318
- camera at position - heading * dist, lookAt(position)
319
- ```
320
-
321
- Why the minus: the camera looks along `heading`, so screen-right is
322
- `cross(heading, up) = (-cos yaw, 0, sin yaw)`, while `d(heading)/d(yaw) =
323
- (cos yaw, 0, -sin yaw)` — exactly screen-LEFT. Increasing yaw always veers the
324
- nose left on screen, so "D turns right" needs `yaw -=`. (Equivalently
325
- `yaw += steer` is correct only with heading `(-sin yaw, 0, cos yaw)` — a pair,
326
- never a lone sign.)
327
-
328
- **RTS / overhead pan camera** (fixed pitch, yaw-orbiting):
329
-
330
- ```text
331
- right = (-cos yaw, 0, sin yaw) // pitch-independent screen-right on the ground
332
- forwardGround = (sin yaw, 0, cos yaw) // into the screen along the ground
333
- D / ArrowRight: target += right * pan A / ArrowLeft: target -= right * pan
334
- W / ArrowUp: target += forwardGround * pan S: target -= forwardGround * pan
335
- ```
336
-
337
- Drag-pan, grab-the-world (terrain follows the pointer; both axes, one
338
- convention — `movementY` is positive DOWNWARD):
339
-
340
- ```text
341
- target -= right * movementX * k
342
- target += forwardGround * movementY * k
343
- ```
344
-
345
- Move-the-camera convention = flip BOTH signs, never one. The classic shipped bug
346
- writes `right = (cos yaw, 0, -sin yaw)` — that is `cross(up, forward)`, the LEFT
347
- vector — inverting A/D and the horizontal drag while W/S stay correct.
348
-
349
- **Pointer-look** (locked mouse driving yaw/pitch, Euler order `YXZ`):
350
-
351
- ```text
352
- yaw -= movementX * sensitivity // mouse-right -> view turns RIGHT
353
- pitch -= movementY * sensitivity // mouse-up -> view tilts UP
354
- ```
355
-
356
- Expected on screen, both axes, before any tuning: a straight-ahead landmark
357
- slides LEFT when the mouse moves right (the view pans right) and slides DOWN
358
- when the mouse moves up (the view tilts up).
359
-
360
298
  ## Floating origin and background handling
361
299
 
362
300
  The Saturn scene first computes a virtual camera pose, stores its orientation
@@ -162,10 +162,7 @@ From `@genex-ai/embed-sdk/sentry` (crash reporting; exactly these two):
162
162
  - `sentryCanvasSnapshot(canvas)` — session replay records the DOM, not the 3D
163
163
  canvas; call this once per frame at the END of the render loop so replays
164
164
  show actual gameplay. Works for BOTH WebGL and WebGPU renderers; internally
165
- throttled, so calling at 60fps is fine. On TOUCH devices it is a deliberate
166
- no-op (and session replay/tracing sample down): each capture is a full-canvas
167
- GPU readback, exactly the overhead phones get memory-killed for — mobile
168
- replays are DOM-only by design, on-error replays still record everywhere:
165
+ throttled, so calling at 60fps is fine:
169
166
 
170
167
  ```ts
171
168
  function animate() {
@@ -37,10 +37,7 @@ no matter how good it looks.
37
37
  unlocked drag-to-turn camera feels imprecise no matter how tight the numbers
38
38
  are. The bucket rule + the bundled `FollowCamera` aim mode live in
39
39
  `$genex-threejs-camera-direction`; on the bundled controller it's ON by default
40
- (with a ready-made cue), not hand-rolled events. Direction is half of it: a
41
- movement key or look axis whose on-screen direction contradicts its label is a
42
- defect, not a tuning issue — the screen-direction contract and verified bases
43
- are in `$genex-threejs-camera-direction`.
40
+ (with a ready-made cue), not hand-rolled events.
44
41
 
45
42
  ## Movement: snappy beats realistic
46
43
 
@@ -27,7 +27,7 @@ in another.
27
27
  | Pause | always — opens on the Escape key | 1 — menu backdrop under a dark overlay |
28
28
  | Fail / retry | always | 1 — a *graded* variant of the menu screen |
29
29
  | Win / next | always | 1 — graded variant, warm |
30
- | Settings | always every game carries the Quality picker (Auto/Low/Medium/High, `$genex-threejs-adaptive-quality`), plus whatever else it has to set | 1 |
30
+ | Settings | when there is anything to set | 1 |
31
31
  | Lobby / waiting | multiplayer only | 1 over the menu backdrop |
32
32
  | HUD | always | 2 — generated sprite HUD (`$genex-ai-hud`), enqueued at this gate for EVERY game; plain CSS is the placeholder until the sprites land, never the final HUD |
33
33
 
@@ -250,15 +250,8 @@ document.addEventListener("keydown", (e) => {
250
250
  so ALSO keep the pointer-lock-loss → pause path (`pointerlockchange`: if
251
251
  unlocked while `playing`, `setPhase("paused")`). Escape then always pauses; it
252
252
  only *also* drops fullscreen on browsers without the lock — unavoidable there.
253
- - **Skip Keyboard Lock + fullscreen only when the cursor stays a tool.**
254
- Cursor-core / top-down / menu-driven games never capture the pointer — skip
255
- `enterImmersive` and Keyboard Lock entirely. But ANY game that locks the
256
- pointer during play — aim games AND keyboard-only racers/platformers/runners
257
- under the lock-or-tool rule (next section) — keeps the Escape → pause path and
258
- the `pointerlockchange` fallback (if unlocked while `playing`, pause): without
259
- it, Esc frees the cursor while the game keeps running. Keyboard-only games may
260
- still skip Keyboard Lock + fullscreen; the lock + pause/resume path is the
261
- non-negotiable part.
253
+ - **Only for immersive/pointer-lock games.** A top-down or menu-driven game never
254
+ captures the mouse and has no window to shrink — skip all of this.
262
255
  - **Dashboard embed:** no setup needed — the platform's game frame grants keyboard
263
256
  lock (and pointer lock + fullscreen), so Escape-to-pause works the same inside
264
257
  `/world/` + `/draft/` as it does standalone (`<slug>.genex.technology`).
@@ -268,28 +261,6 @@ menu — trackpads feel slower than mice, so let the player tune it. On the bund
268
261
  camera the setter is live: `slider.oninput = () => { followCam.aimSensitivity = +slider.value; };`
269
262
  (radians per pixel; default `0.0023`, a usable range is ~`0.0008`–`0.005`).
270
263
 
271
- ## The cursor during play: locked or a tool
272
-
273
- During play the OS cursor is either the gameplay tool (cursor-core: click-to-move,
274
- tower defense, builders, card/board — it stays visible, that's correct) or it is
275
- **locked away — including keyboard-only games** (racer, platformer, runner): an
276
- arrow parked over the action for the whole session is a shipped defect. Games on
277
- the bundled `FollowCamera` get the lock free (on by default). A hand-rolled game
278
- locks with ~6 lines, reusing this section's Escape flow:
279
-
280
- ```ts
281
- // In the Play/Start/Resume CLICK handler (lock needs a user gesture):
282
- canvas.requestPointerLock?.(); // hides the cursor, focuses the game
283
- // Already in the Escape recipe above: pointerlockchange → if unlocked while
284
- // playing, pause; the Resume click re-locks. Keyboard games need nothing more —
285
- // no reticle, no aim code; the lock just parks the cursor.
286
- ```
287
-
288
- If the lock is genuinely unavailable (a third-party embed without
289
- `allow="pointer-lock"`), fall back to hiding the idle cursor over the canvas:
290
- `canvas.style.cursor = "none"` after ~2s without `pointermove`, restored
291
- instantly on move. Menus and pause screens always keep their cursor.
292
-
293
264
  ## The loader
294
265
 
295
266
  The loader is the first thing every player sees — a bare "Loading… 3/5" over
@@ -401,13 +372,11 @@ Order the HUD by what the player loses the game for ignoring:
401
372
  `vUv` grain shimmers.
402
373
  - **Desktop first.** Verify at desktop sizes and survive window resizes
403
374
  without clipping; don't design phone layouts or test mobile viewports unless
404
- the user asks. Two exceptions ship by default precisely BECAUSE you don't
405
- test on phones: touch *input* when a recipe fits a bundled controller's
406
- built-in touch controls, or the touch kit + recipes in
407
- `$genex-threejs-touch-controls` — behind `navigator.maxTouchPoints > 0`,
408
- invisible on desktop (skipping needs a one-line reason, not silence); and
409
- the adaptive-quality tier at boot (`$genex-threejs-adaptive-quality`), which
410
- keeps the shared link from being a dead OR crashing link on a phone.
375
+ the user asks. Exception: touch *input* is wired by default when a recipe
376
+ fits a bundled controller's built-in touch controls, or the touch kit +
377
+ recipes in `$genex-threejs-touch-controls` behind
378
+ `navigator.maxTouchPoints > 0`, invisible on desktop, so the shared link
379
+ isn't dead on a phone (skipping needs a one-line reason, not silence).
411
380
 
412
381
  ## Wire UI to game state, never the reverse
413
382
 
@@ -430,9 +399,6 @@ architecture and consume the shared style brief.
430
399
  - HUD sprites never enqueued at the gate — the placeholder CSS shipped as the
431
400
  final HUD.
432
401
  - No pause screen, or a pause that isn't bound to Escape.
433
- - The OS arrow parked over the action for the whole session in a keyboard-driven
434
- game (the cursor is either a gameplay tool or locked away — see the cursor
435
- section).
436
402
  - A style brief whose fonts were never actually loaded (a system-stack display
437
403
  font at runtime).
438
404
  - A micro-element (reticle, cue, toast, damage number) left as default CSS
@@ -43,11 +43,6 @@ ownership boundaries between whole-scene and effect-local graphs.
43
43
  - Build pass toggles and effect-only views before tuning.
44
44
  - UI rendered in the same target needs an explicit protection strategy.
45
45
  - Do not load all atomic post skills by default. Route only the effects actually requested.
46
- - Budget the pipeline per device tier (`$genex-threejs-adaptive-quality`):
47
- phone pixel budget ≈ 1,000,000 px at DPR ≤ 1.25–1.5, desktop ≈ 1,650,000 px —
48
- every full-res pass target multiplies that cost, so phone tiers run the light
49
- post level and per-pass resolution scales (0.4–0.5 DPR blurs) are the norm,
50
- not an optimization.
51
46
 
52
47
  ## Routing boundary
53
48
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this reference to compose shared scene buffers, lighting effects, atmosphere, bloom, exposure, tone mapping, grading, and feature-local render targets with explicit ownership.
4
4
 
5
- > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project. Either way the effect obeys the device tier (`$genex-threejs-adaptive-quality`): expensive passes are desktop-tier, and on WebGPU the per-target MSAA sample count is a runtime knob the governor may drive.
5
+ > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project.
6
6
 
7
7
  ## Contents
8
8
 
@@ -107,11 +107,7 @@ kill-switch diagnostic.
107
107
  whole rig after a tone-mapping change is self-inflicted.
108
108
  - Never repair unbalanced light ratios with exposure — fix the lights.
109
109
  - Flicker from elapsed time, never per-frame randomness.
110
- - Dispose lights and their shadow maps with the level that spawned them — and
111
- the rest of the level with them: traverse the outgoing scene and dispose
112
- geometry, materials, AND textures separately (three frees nothing; material
113
- dispose does not touch textures). Leaked levels march phones toward the
114
- OS memory kill — `$genex-threejs-adaptive-quality` owns the budget watch.
110
+ - Dispose lights and their shadow maps with the level that spawned them.
115
111
  - The rig must read with post off: time of day and where-to-go, before bloom.
116
112
 
117
113
  ## Routing boundary
@@ -536,13 +536,7 @@ fights (many writers). A ball on `objects` glides and has one owner. That's the
536
536
  `stateRaw` is the raw latest (hit-tests, discrete values). A reconnect-grace seat remains in this
537
537
  map with `connected: false`. `avatarUrl` is that player's verified VRM pick (server-set, `''`
538
538
  when unknown) — in a VRM-lane game render each remote with
539
- `loadVrmClone(p.avatarUrl || "./assets/avatar.vrm")` (the vendored loader's shared-GPU clone:
540
- N remotes share one set of geometry/textures instead of re-parsing per player — retarget
541
- clips once on `loadVrmClone.base(url)` and play them on each clone's own mixer); never
542
- publish avatar URLs through `me.set`. On phone tiers, animate and fully draw only the
543
- nearest `tier.remoteAvatarCap` remotes (`$genex-threejs-adaptive-quality`) — freeze the
544
- mixer and billboard or hide the rest; a room allows up to 64 players and 64 live avatars
545
- is a real phone memory kill on its own.
539
+ `loadVrm(p.avatarUrl || "./assets/avatar.vrm")`; never publish avatar URLs through `me.set`.
546
540
  - `room.activePlayers` — the connected-only subset of `room.players`; use its size for live quorum.
547
541
  - `room.objects` — shared objects nobody owns until claimed (a ball, an NPC):
548
542
  - `claim(id)` — **legacy** optimistic request. It flips local ownership immediately and is corrected
@@ -275,12 +275,9 @@ room.me.set({
275
275
 
276
276
  // Remote players: a VISUAL-ONLY avatar — NO Rapier body, NO controller instance for remotes.
277
277
  // Build each remote's visual from THEIR OWN model: in a VRM-lane game that is
278
- // loadVrmClone(pl.avatarUrl || "./assets/avatar.vrm") — the verified per-player pick the
279
- // relay replicates ('' = unknown → fall back; deepDispose the clone on 'leave'). The clone
280
- // shares parsed GPU geometry/textures across remotes with the same file (most rooms: all of
281
- // them) — retarget clips once against loadVrmClone.base(url).vrm and drive each clone's own
282
- // AnimationMixer. Never reuse your own avatar OBJECT for a remote (clones, not references).
283
- // Phone tiers animate only the nearest tier.remoteAvatarCap remotes (adaptive-quality skill). Position/rotation from smoothed state; animation from the
278
+ // loadVrm(pl.avatarUrl || "./assets/avatar.vrm") — the verified per-player pick the relay
279
+ // replicates ('' = unknown → fall back; deepDispose the model on 'leave'). Never reuse your
280
+ // own avatar file for every remote. Position/rotation from smoothed state; animation from the
284
281
  // synced flags via the avatar's own update(flags, dt). The character-controller skill's
285
282
  // animations reference owns the flag set.
286
283
  const pl = room.players.get(id)!;
@@ -26,7 +26,6 @@ already resolved — constructing a collider before WASM init throws.
26
26
  | tall dynamic props, posts | `capsuleCollider` / `cylinderCollider` | stable standing shapes |
27
27
  | pickups, triggers, zones | any shape + `{ sensor: true, mass: 0 }` | overlap events, no contact forces |
28
28
  | the player, cars, drones | none of the above — `npx genex controller` | controllers own their collider recipes |
29
- | any prop on a PHONE tier (`$genex-threejs-adaptive-quality`) | prefer `cuboidCollider`/hull over trimesh | trimesh contacts scale with triangle count — a phone CPU/memory tax; keep trimesh for static level geometry only |
30
29
 
31
30
  ## Explicit primitive helpers
32
31
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this reference for a bounded-cost WebGPU/TSL ambient-visibility pass with half-resolution horizon integration, bent normals, bilateral reconstruction, and directional ambient tint.
4
4
 
5
- > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project. Either way the effect obeys the device tier (`$genex-threejs-adaptive-quality`): expensive passes are desktop-tier, and on WebGPU the per-target MSAA sample count is a runtime knob the governor may drive.
5
+ > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project.
6
6
 
7
7
  ## Contents
8
8
 
@@ -12,12 +12,6 @@ and shadows shimmer, swim, or run out of coverage.
12
12
 
13
13
  Use a single shadow map only when its receiver region is genuinely bounded. For large moving views, make shadow coverage an explicit spatial hierarchy.
14
14
 
15
- **Phone budgets ride the quality tier** (`$genex-threejs-adaptive-quality`):
16
- shadow maps ≤1024² on phones (512² on the low tier — a 4096² map alone is
17
- ~67 MB of the phone's whole GPU budget), at most 2 cascades where desktop runs
18
- 4, and `shadowMap.autoUpdate = false` for static scenes (re-render on demand:
19
- a shadow pass is a full extra scene render every frame otherwise).
20
-
21
15
  ## Cached clipmap workflow
22
16
 
23
17
  1. Define concentric light-space square levels.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this reference for stable directional shadows across a large procedural scene using committed light-space centers, texel snapping, bounded refresh budgets, cross-level blending, and targeted invalidation.
4
4
 
5
- > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project. Either way the effect obeys the device tier (`$genex-threejs-adaptive-quality`): expensive passes are desktop-tier, and on WebGPU the per-target MSAA sample count is a runtime knob the governor may drive.
5
+ > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project.
6
6
 
7
7
  ## Contents
8
8
 
@@ -15,12 +15,11 @@ map, execution order, and acceptance gate.
15
15
 
16
16
  | Work needed | Load |
17
17
  | --- | --- |
18
- | shot composition, chase/side/orbit rigs, camera handoffs, projection ownership, pointer look, mouse-aimed action (shooter, FPS/first-person, sniper, turret, crosshair/reticle), mouse-look, hand-rolled steering/pan/look input signs (screen-direction contract), floating origins | `$genex-threejs-camera-direction` |
18
+ | shot composition, chase/side/orbit rigs, camera handoffs, projection ownership, pointer look, mouse-aimed action (shooter, FPS/first-person, sniper, turret, crosshair/reticle), mouse-look, floating origins | `$genex-threejs-camera-direction` |
19
19
  | on-foot player movement: walk/run/jump/crouch, third-person character, slopes, stairs, moving platforms, personal VRM animation, directional locomotion, transitions, action motion | `$genex-threejs-character-controller` |
20
20
  | a custom generated playable humanoid or Meshy animation coverage beyond UAL: reference-informed A-pose concepts, explicit candidate + 10k-remesh approvals, exact action IDs, same-rig adapter | `$genex-ai-character` + `$genex-threejs-character-controller` |
21
21
  | the player drives or flies something: cars, drones, vehicle physics, gearbox, enter/exit between character and vehicle | `$genex-threejs-vehicle-controllers` |
22
22
  | playable on phones: touch/mobile input for any game — joystick, virtual buttons, drag zones, per-genre touch recipes, rotate-device overlay — wired by default for every NEW game when a recipe fits (skip with a one-line reason) | `$genex-threejs-touch-controls` |
23
- | phone-survivable rendering — device tiers, DPR/shadow/post budgets, the runtime quality governor, per-tier asset rungs for generated skyboxes/textures, the Quality picker, dispose-on-swap discipline — **mandatory for every game at boot wiring** | `$genex-threejs-adaptive-quality` |
24
23
  | anything falls, collides, gets pushed, or needs physics: Rapier world setup, colliders for meshes and GLBs, collision events | `$genex-threejs-physics-rapier` |
25
24
  | launch and docking timelines, procedural transform phases, springs, staging, rotating-frame alignment, debris motion | `$genex-threejs-procedural-animation` |
26
25
  | reusable scalar/vector fields, domain warping, causal masks, procedural normals | `$genex-threejs-procedural-fields` |
@@ -59,14 +58,6 @@ map, execution order, and acceptance gate.
59
58
  mentions sign-in, saves, progress, per-player state, a persistent world, or
60
59
  leaderboards. Multiplayer auth (`getColyseusAuth`) comes from it too.
61
60
 
62
- **Adaptive quality is mandatory routing:** every game wires the device tier at
63
- boot — `$genex-threejs-adaptive-quality` (three lines: `detectTier()` before the
64
- renderer, tier-capped `setPixelRatio`, the governor in the loop; generated
65
- skyboxes/textures load through their rungs). Phones enforce a hard GPU-memory
66
- kill desktops never show you; the tier is what keeps a phone boot alive while
67
- desktop keeps the full look. This is a completion gate like the post stack —
68
- cheap to wire, not a new testing burden (desktop-only verification stands).
69
-
70
61
  **Character-animation routing:** use the existing VRM + UAL character
71
62
  controller by default. Use `npx genex character` when the game needs a custom
72
63
  generated humanoid or an action unavailable in UAL. Before generating a Meshy
@@ -131,11 +122,7 @@ stack this game ships — read off the concept frame's OWN look (the grade, bloo
131
122
  level, haze, grain it already shows) and which post the 2–3 AAA references lean
132
123
  on, not a default single bloom; ONE built render-pass effect is the FLOOR
133
124
  against no-post for EVERY game, never the target — ship the richness the concept
134
- implies. The floor is TIER-AWARE (`$genex-threejs-adaptive-quality`): on phone
135
- tiers it is satisfied by the built tone-mapping/output pass with the light
136
- additions the tier allows (FXAA/vignette), while the full named stack remains
137
- the desktop floor — never ship the heavy stack undropped to phones (the UI
138
- vignette div or a CSS canvas filter does not count on any tier;
125
+ implies (the UI vignette div or a CSS canvas filter does not count;
139
126
  `$genex-threejs-image-pipeline` owns ordering when 2+ compose), a decision for
140
127
  **every primitive surface** the game builds — walls, barriers, kerbs and
141
128
  platforms each get a real texture or a **shader** where that surface wants motion
@@ -217,16 +204,8 @@ concept-driven — a richer first build beats a grey-box one.
217
204
  drag-orbit (`pointerLockAim: false`) only with a stated reason (e.g. a
218
205
  cursor-heavy UI core). **Never** — cursor-core games (click-to-move, tower
219
206
  defense, builder, card/puzzle), orbit showcases, touch-only; these MUST pass
220
- `pointerLockAim: false`. Keyboard-only games (racer, platformer) lock too
221
- the cursor is either a gameplay tool or locked away during play. The mechanism
222
- and the full aim contract live in `$genex-threejs-camera-direction`.
223
- - Input direction (always — every game that moves with keys or pointer):
224
- D/ArrowRight must move or turn the player screen-RIGHT, mouse-right must turn
225
- the view right, drag-pan axes share one convention. The screen-direction
226
- contract and verified copy-paste bases live in
227
- `$genex-threejs-camera-direction` — hand-rolled steering/pan/look math copies
228
- one instead of deriving signs, and the smoke check's input-direction pass
229
- verifies it.
207
+ `pointerLockAim: false`. The mechanism and the full aim contract live in
208
+ `$genex-threejs-camera-direction`.
230
209
  - Art direction follows THIS game's concept. The style examples inside skills
231
210
  are examples, not defaults — never default to neon/cyberpunk/synthwave (or any
232
211
  other single register) unless the concept calls for it.
@@ -243,7 +222,7 @@ concept-driven — a richer first build beats a grey-box one.
243
222
  - Use `$genex-threejs-visual-validation` before declaring graphics/procedural-system
244
223
  work done. **Game fast path:** for game tasks that loaded no procedural/visual-system
245
224
  skill, done = a screenshot plus an interaction smoke check (load the page, press each
246
- control, see the visible response in its labeled direction) — don't run the full diagnostic gate — PLUS the
225
+ control, see the visible response) — don't run the full diagnostic gate — PLUS the
247
226
  floors from the routing-map's acceptance gate: the generated sprite HUD wired in
248
227
  (not the CSS placeholder), pause on Escape, the branded loader with its key-art
249
228
  background, the brief's fonts actually loaded, the renderer baseline + at least one
@@ -180,10 +180,7 @@ Three.js release or branch, and do not blindly copy demo architecture.
180
180
  (`$genex-threejs-visual-validation` owns the capture discipline).
181
181
  7. Add camera direction when framing, controls, transitions, or scale perception
182
182
  affect play — or the game aims with the mouse (shooter/FPS/turret): the
183
- step-4 bucket decision executes here. And before ANY hand-rolled
184
- steering/pan/look math: the screen-direction contract (D → screen-right,
185
- mouse-right → view right, drag axes one convention) with verified copy-paste
186
- bases lives there — signs are copied, never derived.
183
+ step-4 bucket decision executes here.
187
184
  8. Add procedural animation when object motion needs authored phases,
188
185
  convergence, looping, or deterministic timelines.
189
186
  9. Add shared fields before writing multiple independent noise layers.
@@ -194,11 +191,7 @@ Three.js release or branch, and do not blindly copy demo architecture.
194
191
  step-4 post plan, not inventing one now. This is a completion gate: the
195
192
  named post stack must be BUILT before the game is called done, published,
196
193
  or handed off — a game rendering on stock three.js defaults is not done,
197
- and the gate does not wait for the word "done" to be said. The stack is
198
- tier-gated (`$genex-threejs-adaptive-quality`): full on desktop, the built
199
- tone-mapping pass + the tier's light additions on phones — wire the
200
- governor's post toggle so phone tiers drop the heavy passes, never ship
201
- them undropped.
194
+ and the gate does not wait for the word "done" to be said.
202
195
  12. Once the loop is playable, build the planned interface states via
203
196
  `$genex-threejs-game-ui` (HUD, pause on Escape, fail/retry, win, and the
204
197
  full loading state grown from the step-6 loader), then `npx genex wait`
@@ -257,7 +250,7 @@ module — a corrupted entry point costs more than the minutes saved.
257
250
 
258
251
  **Game fast path:** for a game task that loaded no procedural/visual-system skill,
259
252
  done = a screenshot plus an interaction smoke check (load the page, press each
260
- control, assert a visible response in its labeled direction — `$genex-threejs-visual-validation` has the
253
+ control, assert a visible response — `$genex-threejs-visual-validation` has the
261
254
  procedure), **plus the UI floor from `$genex-threejs-game-ui` (the generated
262
255
  sprite HUD wired in — not the CSS placeholder — pause on Escape, the branded
263
256
  loader with its key-art background, the brief's font pair actually loaded)
@@ -284,11 +277,7 @@ A routed Genex scene is incomplete until it exposes:
284
277
  - named perceptual parameters for the important visual systems;
285
278
  - debug views for generated fields, masks, or passes;
286
279
  - a no-post baseline that still communicates the subject;
287
- - a clear quality tier or render-budget knob when the effect is expensive
288
- and for every GAME, the adaptive-quality tier wired at boot
289
- (`$genex-threejs-adaptive-quality`): tier-capped pixel ratio, tier shadow
290
- budget, the runtime governor in the loop, and generated skybox/texture
291
- loads routed through their rungs;
280
+ - a clear quality tier or render-budget knob when the effect is expensive;
292
281
  - when physics or controllers are in play, a fixed-timestep loop: per-frame
293
282
  work (platforms, enter/exit, controller updates) runs inside the physics
294
283
  world's before-step hook, then the world steps — never in the render loop;
@@ -298,12 +287,9 @@ A routed Genex scene is incomplete until it exposes:
298
287
 
299
288
  **Publishing IS calling it done.** Before `npx genex publish`, every completion
300
289
  gate above must pass — sprite HUD wired, Escape pause working, branded loader
301
- with its key art, fonts loaded, renderer baseline + one built post effect
302
- (tier-aware), the adaptive-quality tier wired at boot, world dressing placed
303
- or validly waived, and the content contract's countables present or
304
- explicitly re-scoped by the user. `genex preview`/`publish` print a mobile
305
- preflight (estimated phone GPU memory vs budget) — treat a warning there as a
306
- gate item too. If any is still
290
+ with its key art, fonts loaded, renderer baseline + one built post effect,
291
+ world dressing placed or validly waived, and the content contract's
292
+ countables present or explicitly re-scoped by the user. If any is still
307
293
  pending, say which and publish only after an explicit go-ahead.
308
294
 
309
295
  Do not invent unavailable Genex service APIs. When preparing a game for Genex
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this reference for a large, unbounded-looking ocean whose identity comes from directional spectral synthesis, staged inverse FFTs, derivative maps, Jacobian whitecaps, and coherent optical shading.
4
4
 
5
- > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project. Either way the effect obeys the device tier (`$genex-threejs-adaptive-quality`): expensive passes are desktop-tier, and on WebGPU the per-target MSAA sample count is a runtime knob the governor may drive.
5
+ > **Renderer note:** this reference assumes `WebGPURenderer` + TSL node materials. Check the project's actual renderer first — the Genex scaffold ships vanilla WebGL three.js. On WebGL, adapt the technique with standard materials / `EffectComposer` passes or pick a simpler alternative; never switch renderers mid-project.
6
6
 
7
7
  ## Contents
8
8