@genex-ai/cli-demo 0.78.0-dev.200 → 0.80.0-dev.211

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 (23) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/templates/README.md +1 -1
  4. package/templates/controllers/quality/pick-asset.ts +12 -7
  5. package/templates/skills/genex-ai-character/SKILL.md +2 -4
  6. package/templates/skills/genex-ai-hud/SKILL.md +69 -23
  7. package/templates/skills/genex-ai-menu/SKILL.md +17 -12
  8. package/templates/skills/genex-ai-model/SKILL.md +58 -7
  9. package/templates/skills/genex-game-director/SKILL.md +265 -0
  10. package/templates/skills/genex-game-director/references/design-contract.md +148 -0
  11. package/templates/skills/{genex-threejs-skill-router → genex-game-director}/references/routing-map.md +82 -63
  12. package/templates/skills/genex-getting-started/SKILL.md +3 -2
  13. package/templates/skills/genex-threejs-adaptive-quality/SKILL.md +23 -8
  14. package/templates/skills/genex-threejs-adaptive-quality/references/adaptive-quality.md +16 -4
  15. package/templates/skills/genex-threejs-character-controller/SKILL.md +2 -4
  16. package/templates/skills/genex-threejs-embed-auth/SKILL.md +6 -48
  17. package/templates/skills/genex-threejs-game-content/SKILL.md +3 -4
  18. package/templates/skills/genex-threejs-game-ui/SKILL.md +95 -76
  19. package/templates/skills/genex-threejs-game-ui/references/style-capsules.md +9 -5
  20. package/templates/skills/genex-threejs-lighting-design/SKILL.md +7 -0
  21. package/templates/skills/genex-threejs-multiplayer/SKILL.md +1 -2
  22. package/templates/skills/genex-threejs-visual-validation/SKILL.md +2 -4
  23. package/templates/skills/genex-threejs-skill-router/SKILL.md +0 -263
@@ -112,11 +112,13 @@ and `$genex-ai-texture` skills show the wiring in place.
112
112
 
113
113
  ## Generated models: load through the rungs
114
114
 
115
- Generated GLBs are provider-raw multiple 1–4K PBR textures + dense geometry.
116
- Every model ships a `@1024` mobile rung (textures budgeted to 1024, meshopt-
117
- compressed, simplified where safe) plus a `.ktx2` sibling whose textures stay
115
+ Provider-raw GLBs are NOT game assets: one prop is ~500k triangles + several
116
+ 4K PBR textures (a pilot scene of them submitted 66M triangles/frame and
117
+ floored an M4 Max). Every model ships a game-ready ladder `@2048` (the
118
+ desktop rung) and `@1024` (the phone rung), both meshopt-compressed and
119
+ simplified where safe, each with a `.ktx2` sibling whose textures stay
118
120
  compressed ON the GPU (~6× less texture VRAM). A plain `GLTFLoader` can decode
119
- neither — wire the decoders once and load through the ladder:
121
+ none of them — wire the decoders once and load through the ladder:
120
122
 
121
123
  ```ts
122
124
  import { createGltfLoader } from "./controllers/quality/gltf-loader.ts";
@@ -126,11 +128,24 @@ const gltfLoader = createGltfLoader(renderer); // meshopt always; KTX2 when the
126
128
  const gltf = await loadModelWithFallback(
127
129
  MODEL_URL, tier, (u) => gltfLoader.loader.loadAsync(u), { ktx2: gltfLoader.ktx2 },
128
130
  );
131
+ // Provider PBR sometimes ships mirror-metal (metalness~1 + near-zero roughness)
132
+ // that reflects the sky env and swims with camera motion. Tame ONLY that extreme
133
+ // — do NOT flatten every material to 0.6 (it dulls legitimately metallic props):
134
+ gltf.scene.traverse((o) => {
135
+ const m = (o as THREE.Mesh).material as THREE.MeshStandardMaterial;
136
+ if (!m?.isMeshStandardMaterial) return;
137
+ if (m.metalness > 0.85 && m.roughness < 0.2) {
138
+ m.metalness = 0.7;
139
+ m.roughness = Math.max(m.roughness, 0.3);
140
+ }
141
+ m.envMapIntensity = Math.min(m.envMapIntensity, 0.8);
142
+ });
129
143
  ```
130
144
 
131
- Fallback chain: `.ktx2` rung → universal `@1024` rung → original — each step
132
- warns, the worst case is today's full download, never a broken boot. Desktop
133
- always loads the original. Meshy characters take the same ladder through
145
+ Fallback chain: `.ktx2` rung → the tier's universal rung (`@2048` desktop,
146
+ `@1024` phones) original each step warns; the original is archival/remix
147
+ source, fetched only as the fallback of last resort. Meshy characters take
148
+ the same ladder through
134
149
  `loadMeshyCharacter(manifestUrl, { loader: gltfLoader.loader, modelUrlCandidates: (u) => [pickModel(u, tier, { ktx2: gltfLoader.ktx2 }), pickModel(u, tier), u] })`.
135
150
  KTX2-capable games can also pass `ktx2Load` to `loadTextureWithFallback` so
136
151
  skyboxes/textures use their `.ktx2` variants.
@@ -149,7 +164,7 @@ not the player's account. Default Auto.
149
164
  at most 2 cascades on phones (`$genex-threejs-shadow-systems`).
150
165
  - Post: phone floor is a BUILT tone-mapping/output pass (`postLevel: 'light'`
151
166
  adds FXAA/vignette); SSAO, volumetrics, and DoF are desktop-tier only
152
- (`$genex-threejs-skill-router` owns the floor wording).
167
+ (`$genex-game-director`'s routing map owns the floor wording).
153
168
  - Particles/scatter: multiply counts by `tier.particleScale`; render heavy
154
169
  transparency at half resolution and upsample.
155
170
  - Animation: distant mixers update at 1/2–1/4 rate; multiplayer remotes above
@@ -22,7 +22,7 @@ cost of guessing high is a dead page.
22
22
  | Shadow map | 512 (static-cached) | 1024 | 1024 | 2048 |
23
23
  | Post level | tone map only | + FXAA/vignette | + FXAA/vignette | full named stack |
24
24
  | Skybox rung | @2048 (~11 MB) | @4096 (~45 MB) | original | original |
25
- | Model rung | @1024 (+.ktx2 when wired) | @1024 (+.ktx2 when wired) | original | original |
25
+ | Model rung | @1024 (+.ktx2 when wired) | @1024 (+.ktx2 when wired) | @2048 (+.ktx2) | @2048 (+.ktx2) |
26
26
  | Texture rung (props) | @1024 | @2048 | original | original |
27
27
  | Particles/scatter | 0.25× | 0.5× | 0.75× | 1× |
28
28
  | Draw distance | 0.5× | 0.75× | 1× | 1× |
@@ -69,6 +69,12 @@ Getting this wrong produces silent no-ops or a session stuck ugly:
69
69
  fog, LOD bias, particle counts, mixer update rates, frame cap, remote-avatar
70
70
  animation count. Light `intensity` is runtime-free; light COUNT is not (see
71
71
  above).
72
+ - **Shadow maps of STATIC lights render once, not per frame:** shadow maps
73
+ default to re-rendering every frame, and a PointLight's is a 6-face cube —
74
+ four static shadow lanterns = 24 redundant passes/frame over the whole
75
+ caster set (measured 66M submitted triangles/frame in a pilot). Freeze them:
76
+ `light.shadow.autoUpdate = false; light.shadow.needsUpdate = true;` — only
77
+ the key light that shadows moving actors stays dynamic.
72
78
 
73
79
  ## Governor mechanics
74
80
 
@@ -113,9 +119,15 @@ Getting this wrong produces silent no-ops or a session stuck ugly:
113
119
  - Watch `renderer.info.memory.{textures,geometries}` across swaps in dev; a
114
120
  monotonic climb is a leak marching toward the OS kill. The governor
115
121
  publishes these counts for the platform's field telemetry.
116
- - Prefer meshopt/instanced geometry for repeats; `BatchedMesh` batches
117
- HETEROGENEOUS static meshes into one draw where instancing (identical
118
- meshes only) can't.
122
+ - Prefer meshopt/instanced geometry for repeats: 3+ copies of the same
123
+ generated model `InstancedMesh` (one draw call per source mesh instead of
124
+ per copy — `$genex-ai-model` has the collapse snippet); `BatchedMesh`
125
+ batches HETEROGENEOUS static meshes into one draw where instancing
126
+ (identical meshes only) can't.
127
+ - Distance LOD comes free with the rung ladder: `THREE.LOD` with the phone
128
+ rung (`@1024`) as the far level — `lod.addLevel(near, 0);
129
+ lod.addLevel(far, 25)`. One extra fetch; worth it past ~25 m sightlines,
130
+ skip in small arenas.
119
131
  - Half-resolution transparency: render heavy particle/transparency passes to a
120
132
  half-size target and composite up — fill-rate is the phone bottleneck.
121
133
 
@@ -57,10 +57,8 @@ Meshy Image-to-3D first produces an unremeshed high-detail model. Show its
57
57
  front, back, left, and right views and report its measured face count. Preserve
58
58
  that model in R2. Before rigging, ask the user to approve a separate
59
59
  10,000-face triangle remesh. The 10k remesh—not the high-detail source—is
60
- rigged and animated. (For these approvals, use your environment's structured
61
- question tool when it has one Claude Code: `AskUserQuestion`; Codex:
62
- `request_user_input`; if it has none, e.g. Cursor, a short numbered list in
63
- chat.)
60
+ rigged and animated. (For these approvals, use your question tool when you
61
+ have one; if you have none, a short numbered list in chat.)
64
62
 
65
63
  That is a separate, **same-rig Meshy-native lane**. Its animation-only GLBs are
66
64
  accepted only when their skeleton signature matches the active character
@@ -34,26 +34,19 @@ Guest sessions have **no** overlay — the game just plays.
34
34
  ## Install
35
35
 
36
36
  ```bash
37
- npm i @genex-ai/embed-sdk @sentry/browser
37
+ npm i @genex-ai/embed-sdk
38
38
  ```
39
39
 
40
- (`@sentry/browser` powers the crash reporting + session replay wiring below
41
- it's an optional peer of the SDK, and every Genex game installs it. Already
42
- installed if you followed Step 3 of the scaffold; repeated here so this skill
43
- is self-contained.)
40
+ (Already installed if you followed Step 3 of the scaffold; repeated here so
41
+ this skill is self-contained.)
44
42
 
45
43
  ## Bootstrap (required, every game)
46
44
 
47
45
  ```ts
48
- // main.ts — the FIRST things in the boot sequence, before any other game code
49
- import { initGameSentry } from "@genex-ai/embed-sdk/sentry";
46
+ // main.ts — the FIRST thing in the boot sequence, before any other game code
50
47
  import { initEmbed } from "@genex-ai/embed-sdk";
51
48
  import { GENEX } from "./genex.config";
52
49
 
53
- // Crash reporting + session replay FIRST — so even a failure inside the auth
54
- // boot below gets reported. One required field; never pass tokens to it.
55
- initGameSentry({ slug: GENEX.slug });
56
-
57
50
  initEmbed({
58
51
  slug: GENEX.slug,
59
52
  apiUrl: GENEX.apiUrl,
@@ -153,29 +146,6 @@ Server write limits (per player, per minute): **60 player-saves, 120
153
146
  world-saves, 30 score submits**. A debounced ~1/sec checkpoint never gets near
154
147
  them — only a save-per-frame loop does (it surfaces as HTTP 429).
155
148
 
156
- From `@genex-ai/embed-sdk/sentry` (crash reporting; exactly these two):
157
-
158
- - `initGameSentry({ slug, dsn?, environment? })` — call once, BEFORE
159
- `initEmbed()`. Only `slug` is required; the shared Genex Sentry project DSN
160
- is built in. Errors, tracing, and session replay all start here; the current
161
- player (account or guest) is attached automatically (no code needed).
162
- - `sentryCanvasSnapshot(canvas)` — session replay records the DOM, not the 3D
163
- canvas; call this once per frame at the END of the render loop so replays
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:
169
-
170
- ```ts
171
- function animate() {
172
- requestAnimationFrame(animate);
173
- // ...game update...
174
- renderer.render(scene, camera);
175
- sentryCanvasSnapshot(renderer.domElement); // AFTER render, same frame
176
- }
177
- ```
178
-
179
149
  ## Saving progress (per-player — every player has their own slot)
180
150
 
181
151
  Use the SDK helpers; never hand-roll fetch calls to the state API. Progression,
@@ -224,16 +194,6 @@ their Genex account) and keep-best — submitting a worse score changes nothing
224
194
  post when they sign in. Send a consistent `mode` per board. Scores are
225
195
  client-reported (arcade-style trust) — don't present them as anti-cheat.
226
196
 
227
- ## Crash reporting rules
228
-
229
- - `initGameSentry` has token scrubbing built in (the sign-in return-trip pass
230
- in URLs is redacted automatically). Never wrap, reimplement, or bypass it —
231
- and never add Sentry options that capture network request/response bodies.
232
- - Don't call `Sentry.init` yourself or add a second error reporter —
233
- `initGameSentry` is the one entry point.
234
- - Manual capture is fine where a try/catch swallows a real bug:
235
- `import * as Sentry from "@sentry/browser"; Sentry.captureException(err)`.
236
-
237
197
  ## NEVER log the tokens
238
198
 
239
199
  **NEVER log the return value of `getEmbedToken()` or `getColyseusAuth()` — not
@@ -328,10 +288,8 @@ Rules:
328
288
 
329
289
  ## Checklist
330
290
 
331
- - [ ] `initGameSentry({ slug: GENEX.slug })` is the very first call in `main.ts`.
332
- - [ ] `initEmbed(...)` follows it, with all three config fields.
333
- - [ ] `sentryCanvasSnapshot(renderer.domElement)` runs after `renderer.render()`
334
- in the main loop (WebGL and WebGPU alike).
291
+ - [ ] `initEmbed(...)` is the very first call in `main.ts`, with all three
292
+ config fields.
335
293
  - [ ] `genex.config.ts` includes `dashboardOrigins` (from `.genex/project.json`).
336
294
  - [ ] Multiplayer and player-name UI await `waitForPlayer()` — NEVER
337
295
  `waitForAuth()` (guests would hang forever). Both `connect()` and
@@ -48,11 +48,10 @@ Rules that make the contract real:
48
48
  - **Scope belongs to the user.** Building a small first slice is the right
49
49
  ORDER (`$genex-threejs-game-ui`'s v0 beat still applies) — but the slice is
50
50
  a milestone on the way to the contract, never a quiet replacement for it.
51
- If the full ask genuinely doesn't fit, shrinking any line is a structured
51
+ If the full ask genuinely doesn't fit, shrinking any line is a
52
52
  question to the user with real options — never a silent cut justified as
53
- "standard practice". (Use your environment's structured question tool when
54
- it has one Claude Code: `AskUserQuestion`; Codex: `request_user_input`;
55
- if it has none, e.g. Cursor, a short numbered list in chat.)
53
+ "standard practice". (Use your question tool when you have one; if you
54
+ have none, a short numbered list in chat.)
56
55
  - **Minute ten is the design test.** If the honest answer is "the same sixty
57
56
  seconds, again", the contract needs another beat (a new area unlocks, a
58
57
  quest chain escalates, a build comes online) before any polish work.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: genex-threejs-game-ui
3
- description: Design the 2D interface of a Genex Three.js game — plan the full screen set up front (loader, menu, HUD, pause/win/lose, lobby) under one shared art direction, then build it as an animated DOM overlay. Use for every new game before writing UI code, and whenever the game needs on-screen text, meters, buttons, or menus, or the interface reads as a generic dashboard, covers the action, or shifts as numbers change.
3
+ description: Design the UI HUD interface of a Genex Three.js game — plan the full screen set up front (loader, menu, HUD, pause/win/lose, lobby) under one shared art direction, then build it as an animated DOM overlay. Use for every new game before writing UI code, and whenever the game needs on-screen text, meters, buttons, or menus, or the interface reads as a generic dashboard, covers the action, or shifts as numbers change.
4
4
  ---
5
5
 
6
6
  # Genex Three.js Game UI
@@ -43,10 +43,7 @@ The table lists screens; **elements are inventoried separately**. Walk the
43
43
  whole loop in your head — loader → menu → spawn → action → pickup → damage →
44
44
  death → retry → win — and write down EVERY on-screen element the player will
45
45
  ever see: the reticle and each of its states, aim/interact cues, toasts,
46
- damage numbers, kill feeds, timers, countdowns, pickup popups… Each element
47
- gets a treatment from the brief. **Nothing ships looking like default
48
- browser CSS** — an element styled like a bare `<div>` or a system button is
49
- a bug wherever it appears, listed or not.
46
+ damage numbers, kill feeds, timers, countdowns, pickup popups.
50
47
 
51
48
  **2. One shared style brief — for the WHOLE game, not just the UI.** Write it
52
49
  once — 4–5 named hues, materials, one display + one body font, mood — and
@@ -61,17 +58,12 @@ is LOADED for real — a Google Fonts `<link>` (or `@font-face`) in
61
58
  ships as a system-stack fallback (`Arial Black`, `Impact`) is the same bug in
62
59
  type.
63
60
 
64
- **3. Name your referencesAAA, by name.** Pick the closest capsule in
65
- [references/style-capsules.md](references/style-capsules.md), name 2–3 top
66
- AAA games of the genre, and state in one line which structural conventions
67
- you're borrowing. The bar is what those games ship, not "good enough for a
68
- demo". Conventions only — never logos, exact layouts, or trade dress. The
69
- same 2–3 names carry into the router's visual-direction gate for the scene.
70
- Then turn references + brief into ONE **concept mockup** — the game concept
61
+ **3. Make ONE concept mockup** — the game concept
71
62
  and the HUD Stage-1 mockup are the SAME image, generated once (never a
72
63
  separate UI-free concept first): a single image of a PLAYABLE MOMENT of this
73
64
  game with its complete HUD composited over it, built with `$genex-ai-hud`'s
74
- Stage-1 prompt template. The scene half of the prompt comes from the game
65
+ Stage-1 prompt template. For genre conventions to borrow, skim
66
+ [references/style-capsules.md](references/style-capsules.md). The scene half of the prompt comes from the game
75
67
  contract in TEXT, not from a prior image: what the player is DOING
76
68
  mid-action (the verb), what threatens them right now (enemy silhouettes),
77
69
  what they are chasing (the objective — a finish gate, a goal, a pickup),
@@ -82,44 +74,63 @@ game doesn't have (a lap counter in a game without laps). Generate it
82
74
  `--size 2560x1440 --quality high --candidates 2 --no-wait`, enqueued FIRST
83
75
  of all art; the picked candidate's URL goes into the style-brief comment.
84
76
 
85
- **Share it the moment it lands queue first, show immediately, never wait.**
86
- When the mockup lands, pick the stronger of the two candidates yourself,
87
- enqueue the downstream UI jobs and the core asset set against it in the same
88
- breath the frame you just generated IS the working style until the user
89
- says otherwise. Then pick it up with
90
- `genex wait <id> --open` (or generate it with `--open`): it opens in the
91
- user's browser AND prints the links. Paste BOTH candidates' URLs as
92
- clickable links in your message and say which one you picked and why — a URL
93
- is invisible in a terminal, and "do you like it?" with
94
- no picture in front of the user is the #1 way this checkpoint fails (they end
95
- up digging logs for the file path). Ask ONE keep-or-change question "this
96
- is roughly how the game and its HUD will look: keep it, or change
97
- something?" — **as
98
- plain chat text, never via the blocking structured-question tool: a suspended
99
- turn is a gate, and this question must not gate anything.** Silence is
100
- acceptance of YOUR pick; only explicit notes reopen the style. An unanswered style
101
- question that parks the art pipeline is how a finished game ships bare walls
102
- and a placeholder HUD strictly worse than re-rolling a few assets later.
103
- **Feedback triggers a LOOP whenever it arrives:** if the user comes back
104
- disliking ANYTHING immediately or an hour later regenerate with their
105
- exact notes (`--candidates 2–3` gives them options to choose from), open +
106
- link the new frame, and ask again the same non-blocking way. Carry every note
107
- forward so each round compounds; if two rounds don't converge, offer 2–3
108
- distinct directions instead of re-rolling blind (plain chat, same rule).
109
- Every shown frame becomes the working style exactly like the first did:
110
- silence after a shown regeneration accepts THAT frame, and when
111
- `--candidates` goes unanswered, pick the strongest yourself and say so. When
112
- the style actually changes, re-run Stage 1 the concept mockup itself
113
- with the user's exact notes (strictly CHEAPER than it used to be: one image
114
- carries scene + HUD, there is no separate concept to redo), then re-anchor
115
- the style-carrying art made against the old mockup: the menu still is
116
- re-edited (`--edit`) against the new mockup and its video re-run once from
117
- the new still (`$genex-ai-menu` a user-driven style change re-opens its
118
- one-video rule), and the HUD deconstruct (Stage 2 onward, `$genex-ai-hud`)
119
- restarts from the new mockup. Style-neutral assets (most textures, sfx,
120
- models) usually survive judge each in one line. The same "open it + paste the
121
- link" rule covers every image the user weighs in on the menu still, the
122
- HUD mockup candidates.
77
+ **Describe the concept, show it, then get a YES before the style-dependent
78
+ work fans out.** First lay the concept out in WORDS — the playable moment
79
+ (the verb), what threatens the player, what they chase, how the space reads,
80
+ and the brief's palette / materials / light / references so the user is
81
+ weighing a stated direction, not guessing at a picture. Generate the mockup
82
+ FIRST of all art (`--candidates 2`) and get it in front of the user AS FAST
83
+ AS POSSIBLE: pick the stronger candidate yourself, pick it up with
84
+ `genex wait <id> --open` (or generate it with `--open`) so it opens in the
85
+ user's browser AND prints the links, and paste BOTH candidates' URLs as
86
+ clickable links saying which one you picked and why a URL is invisible in a
87
+ terminal, and "do you like it?" with no picture in front of the user is the
88
+ #1 way this checkpoint fails (they end up digging logs for the file path).
89
+
90
+ **Then ask for the yes with your question tool** the one that shows the
91
+ user clickable options; a short numbered list in chat only where there is
92
+ none. ONE question "this is roughly
93
+ how the game and its HUD will look keep this direction, or change
94
+ something?" with concrete keep / change options. This confirmation is
95
+ REQUIRED for every game: the concept sets the STYLE every later asset
96
+ inherits, so the user gets a real say before that style is committed. This
97
+ reverses the old "advisory, never gate" rule the concept now gates, but
98
+ ONLY the style-dependent work (below), never the whole build.
99
+
100
+ **The yes gates the STYLE-DEPENDENT work nothing else.** Until the user
101
+ approves a frame, do NOT fan out the art or subagents that build ON the
102
+ chosen look: the HUD Stage-2 deconstruct (from the picked candidate), the
103
+ menu still + video (`--edit`-anchored to the mockup), and the logotype. (The core asset set — hero model, ground texture, skybox,
104
+ sfx is prompted from the game IDEA, not the picked image, and mostly
105
+ survives a style change, so it does NOT wait: launch it up front with
106
+ placeholders, re-rolling only the few that don't survive if the look shifts.)
107
+ Everything else that does NOT depend on the look
108
+ keeps moving at full speed IN PARALLEL the scaffold and boot wiring, the
109
+ core gameplay / network loop, the controller, and the gameplay-LOGIC subagent
110
+ modules (world, quests, enemies, items their structure comes from the
111
+ contract, not the picture). The wait is therefore never idle: a slow-to-answer
112
+ user still gets a walkable first version, and the instant they say yes the
113
+ style pipeline launches against the frame they approved. (A user who vanishes
114
+ entirely leaves the LOOK pending, not the game — the deliberate trade for
115
+ never committing a style behind their back.)
116
+
117
+ **Change reopens the loop, same shape.** If the user picks "change" — or
118
+ comes back with notes immediately or an hour later — re-run Stage 1 (the
119
+ concept mockup itself) with their exact notes (`--candidates 2–3` gives them
120
+ options to choose from), open + link the new frame, and ask again the same
121
+ structured way. Carry every note forward so each round compounds; if two
122
+ rounds don't converge, offer 2–3 distinct directions instead of re-rolling
123
+ blind. Each frame the user approves becomes the working style, and the
124
+ style-dependent pipeline stays gated on the latest yes (strictly CHEAPER than
125
+ it used to be: one image carries scene + HUD, there is no separate concept to
126
+ redo). When the style actually changes after downstream art already ran,
127
+ re-anchor it: the menu still is re-edited (`--edit`) against the new mockup
128
+ and its video re-run once from the new still (`$genex-ai-menu` — a
129
+ user-driven style change re-opens its one-video rule), and the HUD deconstruct
130
+ (Stage 2 onward, `$genex-ai-hud`) restarts from the new mockup. Style-neutral
131
+ assets (most textures, sfx, models) usually survive — judge each in one line.
132
+ The same "open it + paste the link" rule covers every image the user weighs
133
+ in on — the menu still, the HUD mockup candidates.
123
134
 
124
135
  **The concept anchors STYLE, not truth.** Palette, materials, light, and
125
136
  register come from the frame; CONTENT comes from the game contract. This
@@ -136,11 +147,10 @@ an invented mechanic, or the absence of a real one, from a picture.
136
147
 
137
148
  **4. Ask only when genuinely ambiguous.** If the concept pins the mood (a
138
149
  "gothic horror dungeon crawler" pins it), decide and state the plan in one
139
- line. Only when the art direction is truly open, ask ONE structured question
150
+ line. Only when the art direction is truly open, ask ONE question
140
151
  with 2–3 concrete directions, each naming its palette + font pair — using
141
- your environment's structured question tool when it has one (Claude Code:
142
- `AskUserQuestion`; Codex: `request_user_input`); if it has none (e.g.
143
- Cursor), a short numbered list in chat. Never ask about the screen
152
+ your question tool when you have one; if you have none, a short numbered
153
+ list in chat. Never ask about the screen
144
154
  inventory — it derives from the game type.
145
155
 
146
156
  **5. Style follows THIS game's concept.** The examples in every Genex skill
@@ -158,9 +168,11 @@ UI plan
158
168
  • Style: <4–5 named hues> · fonts <display> / <body>
159
169
  • References: <2–3 AAA games — one line on what's borrowed>
160
170
  • Menu: <archetype + button treatment, one-line reason from the brief>
161
- • Concept (HUD mockup): <generation id — 2 candidates>
162
- • Queued next: HUD sheet (Stage 2, from the picked mockup) · menu still →
163
- video <or "no menu: reason"> · logotype <or "skipped: reason">
171
+ • Concept (HUD mockup): <generation id — 2 candidates> — awaiting your keep / change
172
+ • Queued ON YOUR YES (style-dependent): HUD sheet (Stage 2, from the picked
173
+ mockup) · menu still → video <or "no menu: reason"> · logotype <or
174
+ "skipped: reason">
175
+ • Building now (style-independent): <core loop · logic modules already moving>
164
176
  • Deferred from mockup: <widgets the image invented but the game lacks — or "none">
165
177
  ```
166
178
 
@@ -178,7 +190,8 @@ A message missing any line means the gate did not run — go back and run it.
178
190
  every game), and the generated **logotype** — one `--transparent` wordmark
179
191
  in the brief's display register (`$genex-ai-menu`'s logotype step), default
180
192
  YES for every game with a menu; skipping it needs a one-line stated reason.
181
- Enqueue the chain at the plan gate with `--no-wait`,
193
+ Enqueue this chain the instant the user approves the concept
194
+ (`--no-wait`) — it is style-dependent, so it waits on the yes — then
182
195
  keep building, pick results up with `npx genex wait <id>`, swap them in as
183
196
  they land. **Tier 2 must never block a playable v0 — but the game is NOT
184
197
  DONE until its Tier-2 assets have landed and been wired in** (the only
@@ -441,19 +454,18 @@ Order the HUD by what the player loses the game for ignoring:
441
454
  - **Contrast against the real scene.** Test text over the brightest AND
442
455
  darkest areas of actual gameplay; a soft dark plate or text-shadow beats
443
456
  restyling per level.
444
- - **CSS-shaped corners must survive their contents.** `border-radius`,
445
- `clip-path`, and `mask` are all fair ways to shape a panel or button —
446
- including a chamfered/notched "hi-tech" corner in pure CSS. What is
447
- non-negotiable is the execution: the cut must never shear off anything
448
- that sits near the corner (text, padding, the focus ring, a glow) keep
449
- enough inner padding that content clears the cut shape and the result
450
- must be clean, not crooked: no jagged aliased diagonals, no half-clipped
451
- borders or shadows, no text colliding with an edge or truncating. The
452
- same bar applies to CSS plates. Verify the corners at real sizes over
453
- real gameplay. When the art direction wants a genuinely ornamented
454
- frame, a generated frame sprite (`$genex-ai-hud` chrome, or a Tier-3
455
- 9-slice panel) is still the richer tool. The masked-fill HUD reveal and
456
- `genex ui` masks remain the other established uses of `mask`/`clip-path`.
457
+ - **Panel and button corners come from `border-radius` or a generated frame
458
+ sprite — never a raw `clip-path`/`mask` chamfer.** A CSS-cut angular corner
459
+ is the recurring "cut corners" defect: the clip shears off borders, shadows,
460
+ and any content that sits near the corner, and it re-breaks the instant the
461
+ padding, font, or value length changes so it can only be held together by
462
+ a per-build visual check that is easy to skip. It is not worth that fragility.
463
+ For a soft corner use `border-radius` (it keeps its `border`/`box-shadow`
464
+ natively). For a genuinely angular or ornamented "hi-tech" frame, generate it
465
+ as chrome (`$genex-ai-hud`, or a Tier-3 9-slice panel) and lay the DOM over
466
+ it that reads richer and physically cannot shear. `mask`/`clip-path` stay
467
+ reserved for their ONE established HUD use: the masked-fill progress reveal
468
+ driven by `genex ui` masks. Never for corner shaping.
457
469
  - **One cohesion layer.** A single full-screen vignette div (a subtle radial
458
470
  gradient darkening the corners, optionally faint grain) over canvas + UI is
459
471
  the cheapest way to make DOM-over-WebGL read as one composed image instead
@@ -510,12 +522,19 @@ architecture and consume the shared style brief.
510
522
  - Hard-cut phase swaps, a menu whose elements just appear, numbers that
511
523
  teleport.
512
524
  - A silent menu; a bare "Loading…" over black.
513
- - The art pipeline parked on an unanswered look question — the question is
514
- advisory: queue Tier-2 + the asset set against the shown frame and keep
515
- moving; silence is acceptance.
525
+ - Style-dependent art fanned out before the user approved the concept — the
526
+ concept confirmation is REQUIRED and gates the look-dependent work (HUD
527
+ Stage 2, menu still/video, logotype, style-matched assets); OR the whole
528
+ build stalled waiting on that yes, when concept-INDEPENDENT work (scaffold,
529
+ core loop, logic subagents) must keep moving in parallel while it is pending.
516
530
  - A CSS-cut corner (`clip-path`/`mask`) that shears its own content — clipped
517
- text or padding, a lost focus ring or glow, a jagged aliased edge the
531
+ text or padding, a lost focus ring or glow, a jagged aliased edge, or a
532
+ border/frame that stops at the cut instead of following it — the
518
533
  technique is fine; the sloppy cut is the defect.
534
+ - A rectangular semi-transparent plate protruding past an opaque/angular
535
+ widget frame — a dark box floating over the scene. The frame's own art is
536
+ the backing; a plate is only for bare-text/outline widgets and stays inside
537
+ the widget silhouette (`$genex-ai-hud`'s plate rule).
519
538
  - UI panels covering the player or the thing about to kill them.
520
539
  - Layout shifting as numbers grow.
521
540
  - A fail state with no visible restart key, or a restart that reloads the page.
@@ -9,11 +9,15 @@ the capsule says a racing HUD leans oblique and bottom-right-heavy; your brief
9
9
  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
- UI, one display + one body font, tabular numerals, contrast plates over
13
- arbitrary scenes, and panel/button corners executed cleanly `border-radius`,
14
- a CSS `clip-path`/`mask` shape, or a generated frame all work, as long as the
15
- cut never clips content (text, padding, glow), stays free of jagged-edge
16
- artifacts, and text never collides or truncates.
12
+ UI, one display + one body font, tabular numerals, contrast plates for bare
13
+ text over arbitrary scenes (never a second plate stacked behind an opaque
14
+ frame sprite), and panel/button corners done the durable way `border-radius`
15
+ for soft corners (it keeps its `border`/`box-shadow` natively), or a generated
16
+ frame (`$genex-ai-hud` chrome / a Tier-3 9-slice panel) with the DOM laid over
17
+ it for genuinely angular looks. Raw CSS `clip-path`/`mask` corner cuts are
18
+ banned per the skill — they shear borders, shadows, and near-corner content,
19
+ and re-break on any padding/font change; `mask`/`clip-path` stay reserved for
20
+ their ONE established HUD use, the masked-fill progress reveal.
17
21
 
18
22
  ## Fantasy / action RPG
19
23
 
@@ -111,6 +111,13 @@ kill-switch diagnostic.
111
111
  legitimate time the population changes.
112
112
  - Couple a practical to its emitter: one color, one envelope, one on/off state.
113
113
  - The key owns shadows; practicals cast none until a shot proves they must.
114
+ - **A shadow-casting practical that never moves gets a FROZEN map**: a
115
+ PointLight shadow is a 6-face cube render, re-drawn every frame by default —
116
+ four static lanterns cost 24 shadow passes/frame over your densest props for
117
+ zero visual change (a pilot game submitted 66M triangles/frame this way).
118
+ Set `light.shadow.autoUpdate = false; light.shadow.needsUpdate = true;` so
119
+ the cube renders once; keep only the key (which shadows the movers) dynamic,
120
+ and budget frozen practicals at ≤1024 map size.
114
121
  - Tune intensities only after the renderer baseline is locked — retuning the
115
122
  whole rig after a tone-mapping change is self-inflicted.
116
123
  - Never repair unbalanced light ratios with exposure — fix the lights.
@@ -67,8 +67,7 @@ Infer this yourself when the experience is clear. Do **not** make the player cho
67
67
  preset, or config. Ask one plain-language question only when the design genuinely supports both
68
68
  models and the answer changes the experience — for example: *"Should this be one ongoing arena
69
69
  people drop into, or a fresh fair match that waits for everyone and then starts together?"*
70
- (Use your environment's structured question tool when it has one Claude Code:
71
- `AskUserQuestion`; Codex: `request_user_input`; if it has none, e.g. Cursor, a short numbered
70
+ (Use your question tool when you have one; if you have none, a short numbered
72
71
  list in chat.)
73
72
 
74
73
  | Player experience | Model | Why |
@@ -40,10 +40,8 @@ Meshy Image-to-3D first produces an unremeshed high-detail model. Show its
40
40
  front, back, left, and right views and report its measured face count. Preserve
41
41
  that model in R2. Before rigging, ask the user to approve a separate
42
42
  10,000-face triangle remesh. The 10k remesh—not the high-detail source—is
43
- rigged and animated. (For these approvals, use your environment's structured
44
- question tool when it has one Claude Code: `AskUserQuestion`; Codex:
45
- `request_user_input`; if it has none, e.g. Cursor, a short numbered list in
46
- chat.)
43
+ rigged and animated. (For these approvals, use your question tool when you
44
+ have one; if you have none, a short numbered list in chat.)
47
45
 
48
46
  The selected high-detail model remains in a neutral A-pose before animation.
49
47
  Record evidence that the user saw its four views and face count before