@genex-ai/cli-demo 0.74.0 → 0.76.0-dev.195

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 (33) hide show
  1. package/dist/index.js +13196 -12810
  2. package/package.json +1 -1
  3. package/templates/controllers/NOTICE.md +10 -0
  4. package/templates/controllers/assets/basis_transcoder.js +19 -0
  5. package/templates/controllers/assets/basis_transcoder.wasm +0 -0
  6. package/templates/controllers/character/meshy/meshy-loader.ts +29 -3
  7. package/templates/controllers/quality/gltf-loader.ts +67 -0
  8. package/templates/controllers/quality/governor.ts +21 -3
  9. package/templates/controllers/quality/pick-asset.ts +69 -0
  10. package/templates/controllers/quality/tier.ts +62 -6
  11. package/templates/skills/genex-ai-character/SKILL.md +4 -1
  12. package/templates/skills/genex-ai-hud/SKILL.md +191 -28
  13. package/templates/skills/genex-ai-hud/references/masked-fill.md +54 -0
  14. package/templates/skills/genex-ai-hud/references/stage1-prompt-template.md +28 -7
  15. package/templates/skills/genex-ai-hud/references/stage2-prompt-template.md +8 -4
  16. package/templates/skills/genex-ai-menu/SKILL.md +84 -18
  17. package/templates/skills/genex-ai-model/SKILL.md +20 -5
  18. package/templates/skills/genex-ai-skybox/SKILL.md +1 -1
  19. package/templates/skills/genex-ai-texture/SKILL.md +1 -1
  20. package/templates/skills/genex-ai-video/SKILL.md +1 -1
  21. package/templates/skills/genex-explore/SKILL.md +1 -1
  22. package/templates/skills/genex-getting-started/SKILL.md +2 -2
  23. package/templates/skills/genex-threejs-adaptive-quality/SKILL.md +49 -8
  24. package/templates/skills/genex-threejs-adaptive-quality/references/adaptive-quality.md +31 -16
  25. package/templates/skills/genex-threejs-character-controller/SKILL.md +4 -1
  26. package/templates/skills/genex-threejs-game-content/SKILL.md +3 -1
  27. package/templates/skills/genex-threejs-game-ui/SKILL.md +60 -35
  28. package/templates/skills/genex-threejs-game-ui/references/style-capsules.md +17 -0
  29. package/templates/skills/genex-threejs-multiplayer/SKILL.md +3 -0
  30. package/templates/skills/genex-threejs-skill-router/SKILL.md +4 -1
  31. package/templates/skills/genex-threejs-skill-router/references/routing-map.md +18 -6
  32. package/templates/skills/genex-threejs-visual-validation/SKILL.md +4 -1
  33. package/templates/skills/genex-updates/SKILL.md +1 -1
@@ -87,7 +87,7 @@ scene.background = texture; // keep the raw texture for the visible sky
87
87
 
88
88
  ## Troubleshooting
89
89
 
90
- - **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
90
+ - **"Not authorized"** — run `npx @genex-ai/cli-demo@dev init` first (it writes your `GENEX_TOKEN`).
91
91
  - **"Out of credits" (`insufficient_credits`)** — the account has no credits left for
92
92
  this skybox generation. Tell the user the facts the CLI printed: their balance, this
93
93
  generation's cost, and when their credits refill. Then offer to continue the build
@@ -225,7 +225,7 @@ first one is the one a screenshot of the whole arena will not show you.
225
225
 
226
226
  ## Troubleshooting
227
227
 
228
- - **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
228
+ - **"Not authorized"** — run `npx @genex-ai/cli-demo@dev init` first (it writes your `GENEX_TOKEN`).
229
229
  - **"Out of credits" (`insufficient_credits`)** — the account has no credits left for
230
230
  this texture generation. Tell the user the facts the CLI printed: their balance,
231
231
  this generation's cost, and when their credits refill. Then offer to continue the
@@ -145,7 +145,7 @@ set belongs to `$genex-ai-hud` — both build on `npx genex image`/`video`.
145
145
 
146
146
  ## Troubleshooting
147
147
 
148
- - **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
148
+ - **"Not authorized"** — run `npx @genex-ai/cli-demo@dev init` first (it writes your `GENEX_TOKEN`).
149
149
  - **"Prompt rejected"** — the provider's content-safety filter blocked the prompt.
150
150
  This is non-retryable; retrying the same wording fails again. Rewrite the prompt.
151
151
  - **Nothing plays / black surface** — the first `video.play()` must run inside a user
@@ -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@latest init <name>` — or `@dev` when you're
74
+ uses: `npx @genex-ai/cli-demo@dev 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@latest link <slug> # slug = the name in the play URL
133
+ npx @genex-ai/cli-demo@dev 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@latest init
160
+ npx @genex-ai/cli-demo@dev init
161
161
  ```
162
162
 
163
163
  Use `--force` only if you intentionally want your own existing files overwritten
@@ -23,20 +23,32 @@ you still verify on desktop only.
23
23
  npx genex controller quality
24
24
  ```
25
25
 
26
- Installs `src/controllers/quality/{tier.ts, governor.ts, pick-asset.ts}` —
27
- game-owned code, edit freely.
26
+ Installs `src/controllers/quality/{tier.ts, governor.ts, pick-asset.ts,
27
+ gltf-loader.ts}` — game-owned code, edit freely — plus the KTX2 basis
28
+ transcoder (`basis_transcoder.js` + `.wasm`) into `public/assets/` (loaded by
29
+ path at runtime; Vite would drop it anywhere else).
28
30
 
29
31
  ## Wire the tier at boot (before renderer construction)
30
32
 
31
33
  ```ts
32
- import { detectTier } from "./controllers/quality/tier.ts";
34
+ import { detectTier, rendererAntialias } from "./controllers/quality/tier.ts";
33
35
  import { QualityGovernor } from "./controllers/quality/governor.ts";
34
36
 
35
- const tier = detectTier(); // phone-low | phone | desktop; manual Quality setting wins
36
- const renderer = new THREE.WebGLRenderer({ antialias: tier.antialias });
37
+ const tier = detectTier(); // phone-low | phone | desktop-low | desktop; manual Quality setting wins
38
+ // Context MSAA is WASTED under an EffectComposer (it multisamples a buffer the
39
+ // composer never reads — the classic weak-MacBook lag recipe). Games with a
40
+ // post stack pass willRunPost=true and get their AA from the composer target:
41
+ const renderer = new THREE.WebGLRenderer({ antialias: rendererAntialias(tier, true) });
37
42
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, tier.dprCap));
43
+ // With post: AA comes from the composer's multisampled target instead —
44
+ const target = new THREE.WebGLRenderTarget(innerWidth, innerHeight, { samples: tier.composerSamples });
45
+ const composer = new EffectComposer(renderer, target);
38
46
  ```
39
47
 
48
+ `detectTier()` also demotes WEAK desktops (Intel iGPU MacBooks, old integrated
49
+ AMD — desktop GPU strings are unmasked, unlike iOS) to `desktop-low`: DPR 1.5,
50
+ no MSAA, 1024 shadows, light post. The Quality picker still overrides.
51
+
40
52
  The tier owns every budget decision: `dprCap` (1.5 on phones — the single
41
53
  biggest framebuffer lever), `antialias` (off on phones; it is fixed at context
42
54
  creation and can never change live), `shadowMapSize` (1024 phone / 2048
@@ -51,6 +63,10 @@ knobs may change at runtime vs load time vs never: [references/adaptive-quality.
51
63
  const governor = new QualityGovernor(tier, {
52
64
  setDprScale: (m) => renderer.setPixelRatio(Math.min(window.devicePixelRatio, tier.dprCap * m)),
53
65
  setPostEnabled: (on) => (composerEnabled = on),
66
+ setShadowQuality: (level) => {
67
+ sun.shadow.mapSize.setScalar(level === 'full' ? tier.shadowMapSize : tier.shadowMapSize / 2);
68
+ sun.shadow.map?.dispose(); sun.shadow.map = null; // realloc at the new size
69
+ },
54
70
  setDrawDistanceScale: (m) => (scene.fog!.far = baseFogFar * tier.drawDistanceScale * m),
55
71
  }, renderer);
56
72
 
@@ -58,9 +74,9 @@ const governor = new QualityGovernor(tier, {
58
74
  governor.frame(deltaMs);
59
75
  ```
60
76
 
61
- Sustained slow frames step down (DPR ×0.8 → post off → draw distance
62
- 30 fps cap); twenty smooth seconds step back up; a knob that failed twice
63
- stays down for the session. It keeps governing forever — thermal throttling
77
+ Sustained slow frames step down (DPR ×0.8 → post off → shadows reduced
78
+ DPR ×0.65 → draw distance → 30 fps cap); twenty smooth seconds step back up; a
79
+ knob whose recovery failed twice stays down for the session. It keeps governing forever — thermal throttling
64
80
  arrives at minute eight, not second thirty. It also pauses judgment when the
65
81
  tab is hidden and publishes memory counts the platform's crash telemetry
66
82
  reads; pause your own loop and audio on `visibilitychange` too.
@@ -84,6 +100,31 @@ Desktop loads the original, phones the `@2048` rung (~11 MB), and a missing
84
100
  rung falls back to the original — never a broken boot. The `$genex-ai-skybox`
85
101
  and `$genex-ai-texture` skills show the wiring in place.
86
102
 
103
+ ## Generated models: load through the rungs
104
+
105
+ Generated GLBs are provider-raw — multiple 1–4K PBR textures + dense geometry.
106
+ Every model ships a `@1024` mobile rung (textures budgeted to 1024, meshopt-
107
+ compressed, simplified where safe) plus a `.ktx2` sibling whose textures stay
108
+ compressed ON the GPU (~6× less texture VRAM). A plain `GLTFLoader` can decode
109
+ neither — wire the decoders once and load through the ladder:
110
+
111
+ ```ts
112
+ import { createGltfLoader } from "./controllers/quality/gltf-loader.ts";
113
+ import { loadModelWithFallback } from "./controllers/quality/pick-asset.ts";
114
+
115
+ const gltfLoader = createGltfLoader(renderer); // meshopt always; KTX2 when the transcoder is present
116
+ const gltf = await loadModelWithFallback(
117
+ MODEL_URL, tier, (u) => gltfLoader.loader.loadAsync(u), { ktx2: gltfLoader.ktx2 },
118
+ );
119
+ ```
120
+
121
+ Fallback chain: `.ktx2` rung → universal `@1024` rung → original — each step
122
+ warns, the worst case is today's full download, never a broken boot. Desktop
123
+ always loads the original. Meshy characters take the same ladder through
124
+ `loadMeshyCharacter(manifestUrl, { loader: gltfLoader.loader, modelUrlCandidates: (u) => [pickModel(u, tier, { ktx2: gltfLoader.ktx2 }), pickModel(u, tier), u] })`.
125
+ KTX2-capable games can also pass `ktx2Load` to `loadTextureWithFallback` so
126
+ skyboxes/textures use their `.ktx2` variants.
127
+
87
128
  ## Quality picker in settings
88
129
 
89
130
  The pause/settings screen (see `$genex-threejs-game-ui`) always carries a
@@ -14,19 +14,28 @@ cost of guessing high is a dead page.
14
14
 
15
15
  ## The tier ladder
16
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× | |
26
- | Draw distance | 0.5× | 0.75× | |
27
- | Frame target | stable 30 | 60 | 60 |
28
- | Remote avatars animated | 4 | 8 | all |
29
- | Prop colliders | hull/cuboid | hull | as designed |
17
+ | Knob | phone-low | phone | desktop-low | desktop |
18
+ |---|---|---|---|---|
19
+ | DPR cap | 1.0 | 1.5 | 1.5 | 2 |
20
+ | antialias (context, no-post games) | off | off | off | on |
21
+ | Composer MSAA samples | 0 | 0 | 0 | 4 |
22
+ | Shadow map | 512 (static-cached) | 1024 | 1024 | 2048 |
23
+ | Post level | tone map only | + FXAA/vignette | + FXAA/vignette | full named stack |
24
+ | Skybox rung | @2048 (~11 MB) | @4096 (~45 MB) | original | original |
25
+ | Model rung | @1024 (+.ktx2 when wired) | @1024 (+.ktx2 when wired) | original | original |
26
+ | Texture rung (props) | @1024 | @2048 | original | original |
27
+ | Particles/scatter | 0.25× | 0.5× | 0.75× | |
28
+ | Draw distance | 0.5× | 0.75× | | |
29
+ | Frame target | stable 30 | 60 | 60 | 60 |
30
+ | Remote avatars animated | 4 | 8 | all | all |
31
+ | Prop colliders | hull/cuboid | hull | as designed | as designed |
32
+
33
+ `desktop-low` is the weak-desktop demotion (Intel iGPU MacBooks, old integrated
34
+ AMD): desktop GPU renderer strings are UNMASKED (unlike iOS), so one boot probe
35
+ separates a 2015 Intel Air from an M3 Max. The full desktop path on those
36
+ machines — DPR 2 + 4× MSAA + 2048 PCFSoft shadows + full bloom — is the classic
37
+ "huge lags on a MacBook" recipe, and two of its costs (context MSAA, shadow
38
+ budget) were previously invisible to the governor.
30
39
 
31
40
  A DPR drop from 3 (raw iPhone) to 1.5 cuts every full-screen surface — color,
32
41
  depth, and each post target — to a quarter of the bytes. It is the single
@@ -40,7 +49,10 @@ Getting this wrong produces silent no-ops or a session stuck ugly:
40
49
  `stencil`, `powerPreference` on WebGL. Changing them means a new context and
41
50
  a full re-init — the tier must decide them BEFORE the renderer exists.
42
51
  (WebGPU differs: MSAA is per-render-target sample count and is runtime-
43
- changeable.)
52
+ changeable.) **Context MSAA under an EffectComposer is pure waste** — it
53
+ multisamples a buffer the composer never reads. Post games construct with
54
+ `rendererAntialias(tier, true)` (false) and put their AA on the composer's
55
+ own target via `tier.composerSamples`; only no-post games keep context MSAA.
44
56
  - **Load-time (fixed for the session once fetched):** asset rungs (skybox and
45
57
  texture resolutions), model LOD sets. `pickAsset` decides them from the tier
46
58
  at load; switching later means a re-fetch — treat as fixed.
@@ -56,8 +68,11 @@ Getting this wrong produces silent no-ops or a session stuck ugly:
56
68
  `renderer.compileAsync` during the loader screen removes most spikes at the
57
69
  source (and keeps first-frame jank from reading as a stall to the platform's
58
70
  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.
71
+ - Step-down order: DPR ×0.8 → post off → shadows reduced (half the map +
72
+ realloc via `setShadowQuality`) DPR ×0.65 draw distance ×0.6 30 fps
73
+ cap. Each step is the cheapest remaining lever with the biggest headroom
74
+ return; the shadow rung and second DPR step exist because one ×0.8 was
75
+ often not enough on weak desktops.
61
76
  - Step-up needs 20 smooth seconds (hysteresis), and a step that had to be
62
77
  re-applied twice is pinned for the session — oscillating quality reads worse
63
78
  than stable-low.
@@ -57,7 +57,10 @@ 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.
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.)
61
64
 
62
65
  That is a separate, **same-rig Meshy-native lane**. Its animation-only GLBs are
63
66
  accepted only when their skeleton signature matches the active character
@@ -50,7 +50,9 @@ Rules that make the contract real:
50
50
  a milestone on the way to the contract, never a quiet replacement for it.
51
51
  If the full ask genuinely doesn't fit, shrinking any line is a structured
52
52
  question to the user with real options — never a silent cut justified as
53
- "standard practice".
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.)
54
56
  - **Minute ten is the design test.** If the honest answer is "the same sixty
55
57
  seconds, again", the contract needs another beat (a new area unlocks, a
56
58
  quest chain escalates, a build comes online) before any polish work.
@@ -67,31 +67,37 @@ AAA games of the genre, and state in one line which structural conventions
67
67
  you're borrowing. The bar is what those games ship, not "good enough for a
68
68
  demo". Conventions only — never logos, exact layouts, or trade dress. The
69
69
  same 2–3 names carry into the router's visual-direction gate for the scene.
70
- Then turn references + brief into ONE **concept frame** — a single generated
71
- image of a PLAYABLE MOMENT of this game, not key art. Build the prompt from
72
- the game contract, not just the mood: what the player is DOING mid-action
73
- (the verb), what threatens them right now (enemy silhouettes), what they
74
- are chasing (the objective a finish gate, a goal, a pickup), and how the
75
- space reads (route, scale) plus the brief's palette, materials, and
76
- light. A beautiful empty vista with nothing to fight and nowhere to go is a
77
- FAILED concept; so is one that invents mechanics the game doesn't have (a
78
- lap counter in a game without laps). `--aspect 16:9 --quality high
79
- --no-wait`, enqueued FIRST of all art; the URL goes into the style-brief
80
- comment.
70
+ Then turn references + brief into ONE **concept mockup** — the game concept
71
+ and the HUD Stage-1 mockup are the SAME image, generated once (never a
72
+ separate UI-free concept first): a single image of a PLAYABLE MOMENT of this
73
+ 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
75
+ contract in TEXT, not from a prior image: what the player is DOING
76
+ mid-action (the verb), what threatens them right now (enemy silhouettes),
77
+ what they are chasing (the objective a finish gate, a goal, a pickup),
78
+ and how the space reads (route, scale) plus the brief's palette,
79
+ materials, and light. A beautiful empty vista with nothing to fight and
80
+ nowhere to go is a FAILED concept; so is one that invents mechanics the
81
+ game doesn't have (a lap counter in a game without laps). Generate it
82
+ `--size 2560x1440 --quality high --candidates 2 --no-wait`, enqueued FIRST
83
+ of all art; the picked candidate's URL goes into the style-brief comment.
81
84
 
82
85
  **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
+ 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
86
90
  `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 message a URL is invisible in a terminal, and "do you like it?" with
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
89
94
  no picture in front of the user is the #1 way this checkpoint fails (they end
90
95
  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
96
+ is roughly how the game and its HUD will look: keep it, or change
97
+ something?" — **as
92
98
  plain chat text, never via the blocking structured-question tool: a suspended
93
99
  turn is a gate, and this question must not gate anything.** Silence is
94
- acceptance; only explicit notes reopen the style. An unanswered style
100
+ acceptance of YOUR pick; only explicit notes reopen the style. An unanswered style
95
101
  question that parks the art pipeline is how a finished game ships bare walls
96
102
  and a placeholder HUD — strictly worse than re-rolling a few assets later.
97
103
  **Feedback triggers a LOOP whenever it arrives:** if the user comes back
@@ -103,19 +109,25 @@ distinct directions instead of re-rolling blind (plain chat, same rule).
103
109
  Every shown frame becomes the working style exactly like the first did:
104
110
  silence after a shown regeneration accepts THAT frame, and when
105
111
  `--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
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
114
121
  link" rule covers every image the user weighs in on — the menu still, the
115
122
  HUD mockup candidates.
116
123
 
117
124
  **The concept anchors STYLE, not truth.** Palette, materials, light, and
118
- register come from the frame; CONTENT comes from the game contract. When
125
+ register come from the frame; CONTENT comes from the game contract. This
126
+ matters MORE now that the concept carries a HUD: every widget in the mockup
127
+ is a PROPOSAL, and a widget with no backing mechanic is cut before Stage 2 —
128
+ mechanics come from the agreed game, never from the picture. Extra widgets
129
+ the image invented are recorded in the plan message as "deferred from
130
+ mockup" — never silently wired, never silently dropped. When
119
131
  the frame lands, diff it against the contract in one visible line — what
120
132
  does this game have that the frame doesn't show (enemies? arenas? the
121
133
  finish? the pickup)? Carry those requirements in words into every later
@@ -125,9 +137,11 @@ an invented mechanic, or the absence of a real one, from a picture.
125
137
  **4. Ask only when genuinely ambiguous.** If the concept pins the mood (a
126
138
  "gothic horror dungeon crawler" pins it), decide and state the plan in one
127
139
  line. Only when the art direction is truly open, ask ONE structured question
128
- (your environment's `AskUserQuestion`-style tool) with 2–3 concrete directions,
129
- each naming its palette + font pair. Never ask about the screen inventory —
130
- it derives from the game type.
140
+ 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
144
+ inventory — it derives from the game type.
131
145
 
132
146
  **5. Style follows THIS game's concept.** The examples in every Genex skill
133
147
  are examples, not defaults. Do not default to neon/cyberpunk/synthwave — or
@@ -143,8 +157,11 @@ UI plan
143
157
  • Screens: <list with tiers — loader / menu / pause (Esc) / win/lose / …>
144
158
  • Style: <4–5 named hues> · fonts <display> / <body>
145
159
  • References: <2–3 AAA games — one line on what's borrowed>
146
- Concept frame: <generation id>
147
- Queued: HUD chrome <id> · menu video <id or "no menu: reason">
160
+ 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">
164
+ • Deferred from mockup: <widgets the image invented but the game lacks — or "none">
148
165
  ```
149
166
 
150
167
  A message missing any line means the gate did not run — go back and run it.
@@ -156,9 +173,12 @@ A message missing any line means the gate did not run — go back and run it.
156
173
  navigation, phase transitions, UI sounds, vignette. Zero generations — the
157
174
  game is playable immediately.
158
175
  - **Tier 2 — the production UI, generated, async — mandatory, not an upsell.**
159
- The sprite HUD (`$genex-ai-hud`) for EVERY game, and the cinematic menu
176
+ The sprite HUD (`$genex-ai-hud`) for EVERY game, the cinematic menu
160
177
  video (`$genex-ai-menu`) whenever the menu decision is yes (the default for
161
- every game). Enqueue BOTH at the plan gate with `--no-wait`,
178
+ every game), and the generated **logotype** one `--transparent` wordmark
179
+ in the brief's display register (`$genex-ai-menu`'s logotype step), default
180
+ 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`,
162
182
  keep building, pick results up with `npx genex wait <id>`, swap them in as
163
183
  they land. **Tier 2 must never block a playable v0 — but the game is NOT
164
184
  DONE until its Tier-2 assets have landed and been wired in** (the only
@@ -169,7 +189,7 @@ A message missing any line means the gate did not run — go back and run it.
169
189
  Shipping the placeholder CSS HUD as the final HUD is a failure, not a
170
190
  tier choice.
171
191
  - **Tier 3 — offer, don't build.** Video layers over the HUD, 9-slice panel
172
- sprites, a generated logotype, animated menu sprites. Offer in one line
192
+ sprites, animated menu sprites. Offer in one line
173
193
  after the player has seen Tier 1+2 working; build on request.
174
194
 
175
195
  ## Architecture: DOM overlay by default
@@ -470,6 +490,11 @@ architecture and consume the shared style brief.
470
490
 
471
491
  - No UI plan: screens invented one at a time, menu and HUD styled in two
472
492
  different worlds.
493
+ - A separate UI-free concept frame generated before the HUD mockup — the
494
+ concept IS the Stage-1 mockup, one generation; a second scene image for
495
+ "the concept" is a wasted spend and a style-drift risk.
496
+ - The concept/mockup fed to `genex video --frame` — it has a HUD baked in;
497
+ the UI-free menu still is the ONLY valid frame input (`$genex-ai-menu`).
473
498
  - HUD sprites never enqueued at the gate — the placeholder CSS shipped as the
474
499
  final HUD.
475
500
  - No pause screen, or a pause that isn't bound to Escape.
@@ -25,6 +25,9 @@ artifacts, and text never collides or truncates.
25
25
  - Serif or engraved display type; humanist body; muted earthy palette with ONE
26
26
  saturated accent reserved for danger/low-health.
27
27
  - Feedback is material: gold glints on pickup, red vignette pulse on damage.
28
+ - Menu lean: **boxed plate buttons** (or left rail when the vista carries a
29
+ strong subject); ornate engraved logotype; sprite-chrome buttons suit the
30
+ most crafted briefs.
28
31
 
29
32
  ## Clean sci-fi / space
30
33
 
@@ -35,6 +38,8 @@ artifacts, and text never collides or truncates.
35
38
  - Panels read as glass: slight transparency, subtle inner glow, no drop
36
39
  shadows heavier than a whisper.
37
40
  - Motion is precise and quick (120–200 ms), no bounce.
41
+ - Menu lean: **centered stack** or **minimal fullbleed**; hairline plate
42
+ buttons or bare text with wide tracking; a thin geometric logotype.
38
43
 
39
44
  ## Racing / arcade sport
40
45
 
@@ -46,6 +51,8 @@ artifacts, and text never collides or truncates.
46
51
  - Saturated team/brand hues are fine — but two, not six.
47
52
  - Values tween FAST (speed) or pop (position change); a gear change may
48
53
  flash — a full-screen flash may not.
54
+ - Menu lean: **bottom command bar** (a garage/grid row); oblique bare-text
55
+ or chip buttons; a fast angular logotype.
49
56
 
50
57
  ## Military / modern shooter
51
58
 
@@ -54,6 +61,8 @@ artifacts, and text never collides or truncates.
54
61
  - Stencil or condensed grotesque display; desaturated palette — amber/red
55
62
  exist ONLY as warnings, so they still mean something.
56
63
  - Damage reads as a directional vignette, not a number cloud.
64
+ - Menu lean: **left rail** with stencil bare text, or a **bottom command
65
+ bar**; a stencil logotype, desaturated.
57
66
 
58
67
  ## Horror
59
68
 
@@ -63,6 +72,8 @@ artifacts, and text never collides or truncates.
63
72
  grain in the cohesion layer.
64
73
  - UI motion is slow (400 ms+) and quiet; a sudden UI move is itself a scare —
65
74
  spend it deliberately.
75
+ - Menu lean: **diegetic corner** or **minimal fullbleed** — prompt the still
76
+ to leave a calm region for the buttons; worn-type logotype, dim.
66
77
 
67
78
  ## Retro / 8-bit
68
79
 
@@ -72,6 +83,8 @@ artifacts, and text never collides or truncates.
72
83
  already know; lean on them.
73
84
  - Motion is stepped (frame-quantized), not eased; an optional scanline overlay
74
85
  in the cohesion layer sells it.
86
+ - Menu lean: **centered stack** (the arcade attract screen); pixel-font bare
87
+ text with a blinking selector; a chunky pixel logotype at integer scale.
75
88
 
76
89
  ## Cozy / casual
77
90
 
@@ -81,6 +94,8 @@ artifacts, and text never collides or truncates.
81
94
  (scale 0.95 → 1.02 → 1) instead of fading.
82
95
  - Nothing flashes red; even failure is gentle (desaturate + a soft "try
83
96
  again").
97
+ - Menu lean: **centered stack** with plump CSS plate buttons; a rounded
98
+ friendly logotype.
84
99
 
85
100
  ## Painterly / stylized adventure
86
101
 
@@ -90,3 +105,5 @@ artifacts, and text never collides or truncates.
90
105
  readability.
91
106
  - Palette lifted from the scene's own key art — sample it, don't invent a
92
107
  second palette.
108
+ - Menu lean: **left rail** or **diegetic corner** over the painted vista;
109
+ brushwork logotype; bare text with calligraphic display face.
@@ -67,6 +67,9 @@ 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
72
+ list in chat.)
70
73
 
71
74
  | Player experience | Model | Why |
72
75
  | --- | --- | --- |
@@ -114,7 +114,10 @@ chain, which locations, what progression), plus the minute-ten answer. Those
114
114
  lines are hard floors exactly like the sprite HUD — the game is not done,
115
115
  published, or handed off while a contract line is missing, and shrinking one
116
116
  is a structured question to the user, never a silent cut ("vertical slice
117
- first" is a build order, not a smaller destination). A request that says
117
+ first" is a build order, not a smaller destination) use your environment's
118
+ structured question tool when it has one (Claude Code: `AskUserQuestion`;
119
+ Codex: `request_user_input`); if it has none (e.g. Cursor), a short numbered
120
+ list in chat. A request that says
118
121
  **big/open world** also loads `$genex-threejs-open-world` and fixes the
119
122
  world's scale as a number in the same plan — world size comes from streamed
120
123
  terrain, never from fog hiding the edges of a small plane. This routing
@@ -29,7 +29,10 @@ Three.js release or branch, and do not blindly copy demo architecture.
29
29
  additionally fixes the world's scale class as a number here via
30
30
  `$genex-threejs-open-world` — kilometers of streamed terrain, never one
31
31
  fogged plane. Scope belongs to the user: shipping fewer or smaller than
32
- the ask requires their explicit OK through a structured question — a
32
+ the ask requires their explicit OK through a structured question (your
33
+ environment's structured question tool when it has one — Claude Code:
34
+ `AskUserQuestion`; Codex: `request_user_input`; if none, e.g. Cursor, a
35
+ short numbered list in chat) — a
33
36
  "vertical slice first" is a build order, never a license to shrink the
34
37
  destination silently. **Close the contract with the reuse sweep:** run
35
38
  `npx genex explore` once (no query) and map the plan's systems against the
@@ -49,9 +52,12 @@ Three.js release or branch, and do not blindly copy demo architecture.
49
52
  one shared style brief, a tier per screen — stated visibly in chat, never
50
53
  decided silently. Enqueue the Tier-2 UI generations now with `--no-wait`
51
54
  (pick them up later with `npx genex wait <id>`) — they render server-side
52
- while you build the game. FIRST of all art: the gate's **concept frame** —
55
+ while you build the game. FIRST of all art: the gate's **concept mockup** —
53
56
  a playable-moment shot (verb + threat + objective in frame, per the
54
- game-ui gate), shown to the user for a keep-or-change answer the moment
57
+ game-ui gate) WITH the full HUD composited over it: the `$genex-ai-hud`
58
+ Stage-1 image, one generation serving as concept, style checkpoint, and
59
+ HUD blueprint (never a separate UI-free concept first). Shown to the user
60
+ for a keep-or-change answer the moment
55
61
  it lands — the answer is advisory, never a gate: the art pipeline starts
56
62
  against the frame as-is, and the game-ui skill owns the re-anchor loop
57
63
  when notes arrive; later `--edit`-able generations anchor to it for STYLE
@@ -224,11 +230,17 @@ subagents (e.g. Claude Code's Agent tool), split these off; in environments
224
230
  without them (Cursor), the same order simply runs sequentially and the
225
231
  `--no-wait` pattern still hides most generation latency.
226
232
 
227
- - **HUD chain worker.** The moment the Stage-1 mockup lands, hand the whole
233
+ - **HUD chain worker.** The moment the Stage-1 mockup (the game concept)
234
+ lands, hand the whole
228
235
  `$genex-ai-hud` chain to one subagent: pick the better candidate → Stage-2
229
236
  sheet → clean → extract → masks → write the sprite wiring. Its prompt must
230
- be self-contained — the style brief, concept-frame and mockup URLs, the
231
- output dir, and exactly which files it owns.
237
+ be self-contained — the style brief, the mockup URL, the
238
+ output dir, and exactly which files it owns. **Handoff rule:** whoever
239
+ wires the HUD after the subagent finishes MUST read the produced
240
+ `*.annotated-progress.json` and `.bbox.json` files from disk — fillBox
241
+ numbers, `segments`, and sprite dims do not survive a prose summary, and
242
+ wiring from the summary is how validated masks end up on disk while the
243
+ shipped fill is a naive width%.
232
244
  - **Asset shepherd.** One subagent runs `npx genex wait` on every queued ID
233
245
  and wires each asset in as it lands (skybox, models, menu video, dressing),
234
246
  swapping placeholders out and reporting each swap.
@@ -40,7 +40,10 @@ 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.
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.)
44
47
 
45
48
  The selected high-detail model remains in a neutral A-pose before animation.
46
49
  Record evidence that the user saw its four views and face count before
@@ -38,7 +38,7 @@ update, so update immediately.)
38
38
  Run exactly the command the nudge printed, from the game project root:
39
39
 
40
40
  ```bash
41
- npm i -D @genex-ai/cli-demo@latest # the genex CLI (a dev dependency)
41
+ npm i -D @genex-ai/cli-demo@dev # the genex CLI (a dev dependency)
42
42
  npm i @genex-ai/embed-sdk@latest # identity/saves SDK (ships inside the game)
43
43
  npm i @genex-ai/multiplayer@latest # multiplayer SDK (only if the game uses it)
44
44
  ```