@genex-ai/cli-demo 0.69.0-dev.175 → 0.71.0-dev.186

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 (30) hide show
  1. package/dist/index.js +365 -14
  2. package/package.json +2 -1
  3. package/templates/controllers/character/vrm/vrm-loader.ts +74 -11
  4. package/templates/controllers/quality/governor.ts +147 -0
  5. package/templates/controllers/quality/pick-asset.ts +57 -0
  6. package/templates/controllers/quality/tier.ts +170 -0
  7. package/templates/skills/genex-ai-hud/SKILL.md +8 -2
  8. package/templates/skills/genex-ai-menu/SKILL.md +14 -2
  9. package/templates/skills/genex-ai-skybox/SKILL.md +14 -3
  10. package/templates/skills/genex-threejs-adaptive-quality/SKILL.md +141 -0
  11. package/templates/skills/genex-threejs-adaptive-quality/references/adaptive-quality.md +105 -0
  12. package/templates/skills/genex-threejs-bloom/SKILL.md +4 -1
  13. package/templates/skills/genex-threejs-bloom/references/bloom.md +1 -1
  14. package/templates/skills/genex-threejs-embed-auth/SKILL.md +4 -1
  15. package/templates/skills/genex-threejs-game-ui/SKILL.md +56 -24
  16. package/templates/skills/genex-threejs-game-ui/references/style-capsules.md +2 -1
  17. package/templates/skills/genex-threejs-image-pipeline/SKILL.md +5 -0
  18. package/templates/skills/genex-threejs-image-pipeline/references/image-pipeline.md +1 -1
  19. package/templates/skills/genex-threejs-lighting-design/SKILL.md +5 -1
  20. package/templates/skills/genex-threejs-multiplayer/SKILL.md +7 -1
  21. package/templates/skills/genex-threejs-multiplayer/references/host-physics.md +6 -3
  22. package/templates/skills/genex-threejs-physics-rapier/references/colliders-from-assets.md +1 -0
  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 +6 -0
  25. package/templates/skills/genex-threejs-shadow-systems/references/shadow-systems.md +1 -1
  26. package/templates/skills/genex-threejs-skill-router/SKILL.md +14 -1
  27. package/templates/skills/genex-threejs-skill-router/references/routing-map.md +20 -7
  28. package/templates/skills/genex-threejs-spectral-ocean/references/spectral-ocean.md +1 -1
  29. package/templates/skills/genex-threejs-touch-controls/SKILL.md +7 -0
  30. package/templates/skills/genex-threejs-water-optics/references/water-optics.md +1 -1
@@ -0,0 +1,105 @@
1
+ # Genex adaptive quality — tiers, knobs, and the governor in depth
2
+
3
+ Use this reference when tuning the tier ladder, deciding which knob may change
4
+ when, or teaching the governor a game-specific step.
5
+
6
+ ## Why boot-conservative
7
+
8
+ The phone budget is a hard ceiling that includes GPU memory (textures,
9
+ framebuffers), and the OS kill arrives with no catchable event. Boot is the
10
+ danger window: skybox + models + post targets decode together. So phone tiers
11
+ START one notch below what the heuristics suggest and the governor steps UP
12
+ after ~20 smooth seconds. The cost of guessing low is moments of softness; the
13
+ cost of guessing high is a dead page.
14
+
15
+ ## The tier ladder
16
+
17
+ | Knob | phone-low | phone | desktop |
18
+ |---|---|---|---|
19
+ | DPR cap | 1.0 | 1.5 | 2 |
20
+ | antialias (context) | off | off | on |
21
+ | Shadow map | 512 (static-cached) | 1024 | 2048 |
22
+ | Post level | tone map only | + FXAA/vignette | full named stack |
23
+ | Skybox rung | @2048 (~11 MB) | @4096 (~45 MB) | original |
24
+ | Texture rung (props) | @1024 | @2048 | original |
25
+ | Particles/scatter | 0.25× | 0.5× | 1× |
26
+ | Draw distance | 0.5× | 0.75× | 1× |
27
+ | Frame target | stable 30 | 60 | 60 |
28
+ | Remote avatars animated | 4 | 8 | all |
29
+ | Prop colliders | hull/cuboid | hull | as designed |
30
+
31
+ A DPR drop from 3 (raw iPhone) to 1.5 cuts every full-screen surface — color,
32
+ depth, and each post target — to a quarter of the bytes. It is the single
33
+ strongest lever the tier owns.
34
+
35
+ ## The knob split — what may change when
36
+
37
+ Getting this wrong produces silent no-ops or a session stuck ugly:
38
+
39
+ - **Context-creation-fixed (never changes live):** `antialias`, `alpha`,
40
+ `stencil`, `powerPreference` on WebGL. Changing them means a new context and
41
+ a full re-init — the tier must decide them BEFORE the renderer exists.
42
+ (WebGPU differs: MSAA is per-render-target sample count and is runtime-
43
+ changeable.)
44
+ - **Load-time (fixed for the session once fetched):** asset rungs (skybox and
45
+ texture resolutions), model LOD sets. `pickAsset` decides them from the tier
46
+ at load; switching later means a re-fetch — treat as fixed.
47
+ - **Runtime-free (the governor's domain):** `setPixelRatio`, post passes on/off
48
+ and their target resolutions, shadow map size (realloc), draw distance and
49
+ fog, LOD bias, particle counts, mixer update rates, frame cap, remote-avatar
50
+ animation count.
51
+
52
+ ## Governor mechanics
53
+
54
+ - Slow = frame delta over budget for a SUSTAINED window (4 s) — never single
55
+ spikes, which are usually shader compiles or GC. Precompiling with
56
+ `renderer.compileAsync` during the loader screen removes most spikes at the
57
+ source (and keeps first-frame jank from reading as a stall to the platform's
58
+ telemetry).
59
+ - Step-down order: DPR ×0.8 → post off → draw distance ×0.6 → 30 fps cap.
60
+ Each step is the cheapest remaining lever with the biggest headroom return.
61
+ - Step-up needs 20 smooth seconds (hysteresis), and a step that had to be
62
+ re-applied twice is pinned for the session — oscillating quality reads worse
63
+ than stable-low.
64
+ - The governor never stops: thermal throttling degrades phones after minutes
65
+ of play, so a boot-time benchmark alone always ends up wrong.
66
+ - A stable 30 fps cap beats a stuttery 40–50: consistent frame pacing reads
67
+ smoother and halves GPU work per second (heat, battery, memory bandwidth).
68
+ - Backgrounded tab (`visibilitychange`): pause the render loop and audio, not
69
+ just the governor — a hidden game burning GPU is pure thermal debt on the
70
+ device class that can least afford it.
71
+
72
+ ## Detection honesty
73
+
74
+ - Apple devices mask the GPU renderer string ("Apple GPU") — screen dims + DPR
75
+ + iOS major version are the usable signals there, and the governor corrects
76
+ the rest from measured frames.
77
+ - Android exposes real renderer strings (Adreno/Mali/Xclipse); the vendored
78
+ lookup in `tier.ts` promotes strong GPUs to the `phone` tier. It is a
79
+ heuristic on purpose — extend the regex when field data shows a
80
+ misclassified family, and let the governor absorb the rest.
81
+ - Never burn a probe context on a memory-strapped phone at play time; the one
82
+ probe in `tier.ts` runs at boot and frees its context immediately.
83
+
84
+ ## Memory discipline that rides the tier
85
+
86
+ - Dispose on every level swap: traverse the outgoing scene and call
87
+ `.dispose()` on geometry, material, AND each material's textures — material
88
+ dispose does not free textures, and three frees nothing automatically.
89
+ - Watch `renderer.info.memory.{textures,geometries}` across swaps in dev; a
90
+ monotonic climb is a leak marching toward the OS kill. The governor
91
+ publishes these counts for the platform's field telemetry.
92
+ - Prefer meshopt/instanced geometry for repeats; `BatchedMesh` batches
93
+ HETEROGENEOUS static meshes into one draw where instancing (identical
94
+ meshes only) can't.
95
+ - Half-resolution transparency: render heavy particle/transparency passes to a
96
+ half-size target and composite up — fill-rate is the phone bottleneck.
97
+
98
+ ## Multiplayer at tier
99
+
100
+ Remotes are visual-only; with the shared avatar file, `loadVrmClone` gives N
101
+ remotes one set of GPU geometry/textures. Animate and fully draw only the
102
+ nearest `tier.remoteAvatarCap`; beyond it, freeze the mixer and billboard or
103
+ hide. Matchmade games can also declare a lower `maxPlayers` in
104
+ `genex.matchmaking` for phone-heavy audiences — capacity is a server-owned
105
+ knob.
@@ -32,7 +32,10 @@ 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.
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.
36
39
 
37
40
  ## Routing boundary
38
41
 
@@ -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.
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.
6
6
 
7
7
  ## Contents
8
8
 
@@ -162,7 +162,10 @@ 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:
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:
166
169
 
167
170
  ```ts
168
171
  function animate() {
@@ -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 | when there is anything to set | 1 |
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 |
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
 
@@ -79,25 +79,40 @@ lap counter in a game without laps). `--aspect 16:9 --quality high
79
79
  --no-wait`, enqueued FIRST of all art; the URL goes into the style-brief
80
80
  comment.
81
81
 
82
- **Share it before building on it — actually SHOW the image, don't just ask.**
83
- When the concept lands, pick it up with `genex wait <id> --open` (or generate it
84
- with `--open`): it opens in the user's browser AND prints the link. Paste that
85
- URL as a clickable link in your approval message a URL is invisible in a
86
- terminal, and "do you like it?" with no picture in front of the user is the #1
87
- way this checkpoint fails (they end up digging logs for the file path). Then ask
88
- ONE structured question "this is roughly how the game will look: keep it, or
89
- change something?" with 2–3 concrete adjustment options. Keep building
90
- gameplay-neutral work (scaffold, physics, netcode) while waiting, but do NOT
91
- anchor further art to an unapproved frame. **Approval is a LOOP, not a
92
- one-shot:** if the user dislikes ANYTHING, regenerate with their exact notes
93
- (`--candidates 2–3` gives them options to choose from), open + link the new
94
- frame, and ask again repeat until they actually approve. Carry every note
82
+ **Share it the moment it lands queue first, show immediately, never wait.**
83
+ When the concept lands, enqueue the Tier-2 UI jobs and the core asset set
84
+ against it in the same breath the frame you just generated IS the working
85
+ style until the user says otherwise. Then pick it up with
86
+ `genex wait <id> --open` (or generate it with `--open`): it opens in the
87
+ user's browser AND prints the link. Paste that URL as a clickable link in
88
+ your messagea URL is invisible in a terminal, and "do you like it?" with
89
+ no picture in front of the user is the #1 way this checkpoint fails (they end
90
+ up digging logs for the file path). Ask ONE keep-or-change question — "this
91
+ is roughly how the game will look: keep it, or change something?" — **as
92
+ plain chat text, never via the blocking structured-question tool: a suspended
93
+ turn is a gate, and this question must not gate anything.** Silence is
94
+ acceptance; only explicit notes reopen the style. An unanswered style
95
+ question that parks the art pipeline is how a finished game ships bare walls
96
+ and a placeholder HUD — strictly worse than re-rolling a few assets later.
97
+ **Feedback triggers a LOOP whenever it arrives:** if the user comes back
98
+ disliking ANYTHING — immediately or an hour later — regenerate with their
99
+ exact notes (`--candidates 2–3` gives them options to choose from), open +
100
+ link the new frame, and ask again the same non-blocking way. Carry every note
95
101
  forward so each round compounds; if two rounds don't converge, offer 2–3
96
- distinct directions as a structured question instead of re-rolling blind. The
97
- HUD mockup, the menu, and every downstream asset wait for a frame the user has
98
- signed off a single "meh" is never permission to move on. The same "open it +
99
- paste the link" rule covers every image the user weighs in on the menu still,
100
- the HUD mockup candidates.
102
+ distinct directions instead of re-rolling blind (plain chat, same rule).
103
+ Every shown frame becomes the working style exactly like the first did:
104
+ silence after a shown regeneration accepts THAT frame, and when
105
+ `--candidates` goes unanswered, pick the strongest yourself and say so. When
106
+ the style actually changes, re-anchor the style-carrying art made against
107
+ the old frame: the menu still is re-edited (`--edit`) against the new frame
108
+ and its video re-run once from the new still (`$genex-ai-menu` — a
109
+ user-driven style change re-opens its one-video rule), and the HUD chrome
110
+ re-runs its pipeline from Stage 1 with the new frame as the `--edit` anchor
111
+ (`$genex-ai-hud` — budget the full serial chain; it is the most expensive
112
+ re-anchor in the set). Style-neutral assets (most textures, sfx, models)
113
+ usually survive — judge each in one line. The same "open it + paste the
114
+ link" rule covers every image the user weighs in on — the menu still, the
115
+ HUD mockup candidates.
101
116
 
102
117
  **The concept anchors STYLE, not truth.** Palette, materials, light, and
103
118
  register come from the frame; CONTENT comes from the game contract. When
@@ -391,6 +406,16 @@ Order the HUD by what the player loses the game for ignoring:
391
406
  - **Contrast against the real scene.** Test text over the brightest AND
392
407
  darkest areas of actual gameplay; a soft dark plate or text-shadow beats
393
408
  restyling per level.
409
+ - **Panel and button corners come from `border-radius`, not a CSS clip.**
410
+ Don't chamfer, notch, or slice corners with `clip-path: polygon(...)` or a
411
+ `mask` for a "hi-tech" look: a raw CSS clip hard-cuts the box, so it shears
412
+ off whatever sits near the corner (text, padding, the focus ring, a glow)
413
+ and leaves a jagged aliased diagonal that reads as *broken*, not as a
414
+ designed bevel. Soft corners are `border-radius`; a genuinely angular or
415
+ ornamented frame is a generated frame sprite (`$genex-ai-hud` chrome, or a
416
+ Tier-3 9-slice panel), never hand-cut in CSS. This governs decorative
417
+ panel/button **shape** only — it does not touch the masked-fill HUD reveal
418
+ or `genex ui` masks, which are the correct uses of `mask`/`clip-path`.
394
419
  - **One cohesion layer.** A single full-screen vignette div (a subtle radial
395
420
  gradient darkening the corners, optionally faint grain) over canvas + UI is
396
421
  the cheapest way to make DOM-over-WebGL read as one composed image instead
@@ -401,11 +426,13 @@ Order the HUD by what the player loses the game for ignoring:
401
426
  `vUv` grain shimmers.
402
427
  - **Desktop first.** Verify at desktop sizes and survive window resizes
403
428
  without clipping; don't design phone layouts or test mobile viewports unless
404
- the user asks. Exception: touch *input* is wired by default when a recipe
405
- fits a bundled controller's built-in touch controls, or the touch kit +
406
- recipes in `$genex-threejs-touch-controls` behind
407
- `navigator.maxTouchPoints > 0`, invisible on desktop, so the shared link
408
- isn't dead on a phone (skipping needs a one-line reason, not silence).
429
+ the user asks. Two exceptions ship by default precisely BECAUSE you don't
430
+ test on phones: touch *input* when a recipe fits a bundled controller's
431
+ built-in touch controls, or the touch kit + recipes in
432
+ `$genex-threejs-touch-controls` — behind `navigator.maxTouchPoints > 0`,
433
+ invisible on desktop (skipping needs a one-line reason, not silence); and
434
+ the adaptive-quality tier at boot (`$genex-threejs-adaptive-quality`), which
435
+ keeps the shared link from being a dead OR crashing link on a phone.
409
436
 
410
437
  ## Wire UI to game state, never the reverse
411
438
 
@@ -440,6 +467,11 @@ architecture and consume the shared style brief.
440
467
  - Hard-cut phase swaps, a menu whose elements just appear, numbers that
441
468
  teleport.
442
469
  - A silent menu; a bare "Loading…" over black.
470
+ - The art pipeline parked on an unanswered look question — the question is
471
+ advisory: queue Tier-2 + the asset set against the shown frame and keep
472
+ moving; silence is acceptance.
473
+ - Panel or button corners chamfered/notched with `clip-path`/`mask` instead of
474
+ `border-radius` — the corner looks sheared off, not designed.
443
475
  - UI panels covering the player or the thing about to kill them.
444
476
  - Layout shifting as numbers grow.
445
477
  - A fail state with no visible restart key, or a restart that reloads the page.
@@ -10,7 +10,8 @@ says what it's made of in THIS game.
10
10
 
11
11
  Every capsule below assumes the base rules from the skill: corners/edges for
12
12
  UI, one display + one body font, tabular numerals, contrast plates over
13
- arbitrary scenes.
13
+ arbitrary scenes, and panel/button corners from `border-radius` or a generated
14
+ frame — never a raw CSS `clip-path`/`mask` chamfer.
14
15
 
15
16
  ## Fantasy / action RPG
16
17
 
@@ -43,6 +43,11 @@ 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.
46
51
 
47
52
  ## Routing boundary
48
53
 
@@ -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.
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.
6
6
 
7
7
  ## Contents
8
8
 
@@ -107,7 +107,11 @@ 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.
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.
111
115
  - The rig must read with post off: time of day and where-to-go, before bloom.
112
116
 
113
117
  ## Routing boundary
@@ -536,7 +536,13 @@ 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
- `loadVrm(p.avatarUrl || "./assets/avatar.vrm")`; never publish avatar URLs through `me.set`.
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.
540
546
  - `room.activePlayers` — the connected-only subset of `room.players`; use its size for live quorum.
541
547
  - `room.objects` — shared objects nobody owns until claimed (a ball, an NPC):
542
548
  - `claim(id)` — **legacy** optimistic request. It flips local ownership immediately and is corrected
@@ -275,9 +275,12 @@ 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
- // 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
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
281
284
  // synced flags via the avatar's own update(flags, dt). The character-controller skill's
282
285
  // animations reference owns the flag set.
283
286
  const pl = room.players.get(id)!;
@@ -26,6 +26,7 @@ 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 |
29
30
 
30
31
  ## Explicit primitive helpers
31
32
 
@@ -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.
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.
6
6
 
7
7
  ## Contents
8
8
 
@@ -12,6 +12,12 @@ 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
+
15
21
  ## Cached clipmap workflow
16
22
 
17
23
  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.
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.
6
6
 
7
7
  ## Contents
8
8
 
@@ -20,6 +20,7 @@ map, execution order, and acceptance gate.
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` |
23
24
  | anything falls, collides, gets pushed, or needs physics: Rapier world setup, colliders for meshes and GLBs, collision events | `$genex-threejs-physics-rapier` |
24
25
  | launch and docking timelines, procedural transform phases, springs, staging, rotating-frame alignment, debris motion | `$genex-threejs-procedural-animation` |
25
26
  | reusable scalar/vector fields, domain warping, causal masks, procedural normals | `$genex-threejs-procedural-fields` |
@@ -58,6 +59,14 @@ map, execution order, and acceptance gate.
58
59
  mentions sign-in, saves, progress, per-player state, a persistent world, or
59
60
  leaderboards. Multiplayer auth (`getColyseusAuth`) comes from it too.
60
61
 
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
+
61
70
  **Character-animation routing:** use the existing VRM + UAL character
62
71
  controller by default. Use `npx genex character` when the game needs a custom
63
72
  generated humanoid or an action unavailable in UAL. Before generating a Meshy
@@ -122,7 +131,11 @@ stack this game ships — read off the concept frame's OWN look (the grade, bloo
122
131
  level, haze, grain it already shows) and which post the 2–3 AAA references lean
123
132
  on, not a default single bloom; ONE built render-pass effect is the FLOOR
124
133
  against no-post for EVERY game, never the target — ship the richness the concept
125
- implies (the UI vignette div or a CSS canvas filter does not count;
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;
126
139
  `$genex-threejs-image-pipeline` owns ordering when 2+ compose), a decision for
127
140
  **every primitive surface** the game builds — walls, barriers, kerbs and
128
141
  platforms each get a real texture or a **shader** where that surface wants motion
@@ -52,8 +52,10 @@ Three.js release or branch, and do not blindly copy demo architecture.
52
52
  while you build the game. FIRST of all art: the gate's **concept frame** —
53
53
  a playable-moment shot (verb + threat + objective in frame, per the
54
54
  game-ui gate), shown to the user for a keep-or-change answer the moment
55
- it lands; later `--edit`-able generations anchor to it for STYLE while
56
- the game contract owns content. Then the `$genex-ai-hud` Stage-1 mockup, enqueued
55
+ it lands the answer is advisory, never a gate: the art pipeline starts
56
+ against the frame as-is, and the game-ui skill owns the re-anchor loop
57
+ when notes arrive; later `--edit`-able generations anchor to it for STYLE
58
+ while the game contract owns content. Then the `$genex-ai-hud` Stage-1 mockup, enqueued
57
59
  here for EVERY game; and the `$genex-ai-menu` video whenever the menu
58
60
  decision is yes (the default for every game — "it's only a draft" is not a
59
61
  reason to decide no). Skipping this enqueue is
@@ -194,7 +196,11 @@ Three.js release or branch, and do not blindly copy demo architecture.
194
196
  step-4 post plan, not inventing one now. This is a completion gate: the
195
197
  named post stack must be BUILT before the game is called done, published,
196
198
  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.
199
+ and the gate does not wait for the word "done" to be said. The stack is
200
+ tier-gated (`$genex-threejs-adaptive-quality`): full on desktop, the built
201
+ tone-mapping pass + the tier's light additions on phones — wire the
202
+ governor's post toggle so phone tiers drop the heavy passes, never ship
203
+ them undropped.
198
204
  12. Once the loop is playable, build the planned interface states via
199
205
  `$genex-threejs-game-ui` (HUD, pause on Escape, fail/retry, win, and the
200
206
  full loading state grown from the step-6 loader), then `npx genex wait`
@@ -280,7 +286,11 @@ A routed Genex scene is incomplete until it exposes:
280
286
  - named perceptual parameters for the important visual systems;
281
287
  - debug views for generated fields, masks, or passes;
282
288
  - a no-post baseline that still communicates the subject;
283
- - a clear quality tier or render-budget knob when the effect is expensive;
289
+ - a clear quality tier or render-budget knob when the effect is expensive
290
+ and for every GAME, the adaptive-quality tier wired at boot
291
+ (`$genex-threejs-adaptive-quality`): tier-capped pixel ratio, tier shadow
292
+ budget, the runtime governor in the loop, and generated skybox/texture
293
+ loads routed through their rungs;
284
294
  - when physics or controllers are in play, a fixed-timestep loop: per-frame
285
295
  work (platforms, enter/exit, controller updates) runs inside the physics
286
296
  world's before-step hook, then the world steps — never in the render loop;
@@ -290,9 +300,12 @@ A routed Genex scene is incomplete until it exposes:
290
300
 
291
301
  **Publishing IS calling it done.** Before `npx genex publish`, every completion
292
302
  gate above must pass — sprite HUD wired, Escape pause working, branded loader
293
- with its key art, fonts loaded, renderer baseline + one built post effect,
294
- world dressing placed or validly waived, and the content contract's
295
- countables present or explicitly re-scoped by the user. If any is still
303
+ with its key art, fonts loaded, renderer baseline + one built post effect
304
+ (tier-aware), the adaptive-quality tier wired at boot, world dressing placed
305
+ or validly waived, and the content contract's countables present or
306
+ explicitly re-scoped by the user. `genex preview`/`publish` print a mobile
307
+ preflight (estimated phone GPU memory vs budget) — treat a warning there as a
308
+ gate item too. If any is still
296
309
  pending, say which and publish only after an explicit go-ahead.
297
310
 
298
311
  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.
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.
6
6
 
7
7
  ## Contents
8
8
 
@@ -153,6 +153,13 @@ z-order stays: drag zone (5) under joystick/buttons (10) under pause menus.
153
153
  canvas. If the game also needs taps there (tap to shoot), read them from the
154
154
  zone (`onChange` + a small-movement threshold) or shrink the zone.
155
155
 
156
+ ## Input is half of phone-playable
157
+
158
+ This skill is INPUT only. A phone that can steer a game that then runs out of
159
+ GPU memory still loses the player — the rendering half (device tiers, DPR and
160
+ shadow budgets, the runtime governor, per-tier asset rungs) lives in
161
+ `$genex-threejs-adaptive-quality` and is wired at boot for every game.
162
+
156
163
  ## When you skip
157
164
 
158
165
  Say it in one plain line — *"skipped touch controls: the game is
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this reference for bounded or analytic water with shared displacement and normals, derivative-filtered detail, analytic reflection, heuristic refraction, absorption, and crest foam. Use `$genex-threejs-spectral-ocean` for stochastic FFT seas.
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.
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.
6
6
 
7
7
  ## Contents
8
8